Skip to content

Commit

Permalink
Merge branch 'release/4.0.4'.
Browse files Browse the repository at this point in the history
  • Loading branch information
petrbroz committed Aug 8, 2023
2 parents a6eb2e5 + 33fbf85 commit 8198078
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 43 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.0.4] - 2023-08-08

- Added
- Support for gltf output filtering based on fragment IDs.
- Support for svf input filtering based on dbID or fragment ID.

## [4.0.3] - 2023-06-28

- Fixed
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "forge-convert-utils",
"version": "4.0.3",
"version": "4.0.4",
"description": "Tools for converting Autodesk Forge file formats.",
"main": "lib/index.js",
"bin": {
Expand Down
6 changes: 3 additions & 3 deletions src/gltf/writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface IWriterOptions {
skipUnusedUvs?: boolean; /** Skip unused tex coordinates. */
center?: boolean; /** Move the model to origin. */
log?: (msg: string) => void; /** Optional logging function. */
filter?: (dbid: number) => boolean;
filter?: (dbid: number, fragid: number) => boolean;
}

function hasTextures(material: IMF.Material | null): boolean {
Expand Down Expand Up @@ -75,7 +75,7 @@ export class Writer {
skipUnusedUvs: !!options.skipUnusedUvs,
center: !!options.center,
log: (options && options.log) || function (msg: string) {},
filter: options && options.filter || ((dbid: number) => true)
filter: options && options.filter || ((dbid: number, fragid: number) => true)
};

// All these properties will be properly initialized in the 'reset' call
Expand Down Expand Up @@ -253,7 +253,7 @@ export class Writer {
if (fragment.kind !== IMF.NodeKind.Object) {
continue;
}
if (!filter(fragment.dbid)) {
if (!filter(fragment.dbid, i)) {
continue;
}
const material = imf.getMaterial(fragment.material);
Expand Down
104 changes: 65 additions & 39 deletions src/svf/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export class Scene implements IMF.IScene {
export interface IReaderOptions {
log?: (msg: string) => void;
skipPropertyDb?: boolean;
filter?: (dbid: number, fragid: number) => boolean;
}

/**
Expand Down Expand Up @@ -269,56 +270,57 @@ export class Reader {
let tasks: Promise<void>[] = [];
const log = (options && options.log) || function (msg: string) {};

tasks.push((async () => {
log(`Reading fragments...`);
output.fragments = await this.readFragments();
log(`Reading fragments: done`);
})());
tasks.push((async () => {
log(`Reading geometries...`);
output.geometries = await this.readGeometries();
log(`Reading geometries: done`);
})());
tasks.push((async () => {
log(`Reading materials...`);
output.materials = await this.readMaterials();
log(`Reading materials: done`);
})());
log(`Reading fragments...`);
output.fragments = await this.readFragments();
log(`Reading fragments: done`);

log(`Reading geometries...`);
output.geometries = await this.readGeometries();
log(`Reading geometries: done`);

log(`Reading materials...`);
output.materials = await this.readMaterials();
log(`Reading materials: done`);

if (!(options && options.skipPropertyDb)) {
tasks.push((async () => {
log(`Reading property database...`);
output.properties = await this.getPropertyDb();
log(`Reading property database: done`);
})());
}
for (let i = 0, len = this.getMeshPackCount(); i < len; i++) {
tasks.push((async (id: number) => {
log(`Reading meshpack #${id}...`);
output.meshpacks[id] = await this.readMeshPack(id);
log(`Reading meshpack #${id}: done`);
})(i));

if (options && options.filter) {
const fragments = output.fragments as SVF.IFragment[];
const geometries = output.geometries as SVF.IGeometryMetadata[];
const packIds = new Set<number>();
for (let i = 0, len = fragments.length; i < len; i++) {
const fragment = fragments[i];
if (options.filter(fragment.dbID, i)) {
packIds.add(geometries[fragment.geometryID].packID);
}
}
for (const packId of packIds.values()) {
tasks.push((async (id: number) => {
log(`Reading meshpack #${id}...`);
output.meshpacks[id] = await this.readMeshPack(id);
log(`Reading meshpack #${id}: done`);
})(packId));
}
} else {
for (let i = 0, len = this.getMeshPackCount(); i < len; i++) {
tasks.push((async (id: number) => {
log(`Reading meshpack #${id}...`);
output.meshpacks[id] = await this.readMeshPack(id);
log(`Reading meshpack #${id}: done`);
})(i));
}
}

for (const img of this.listImages()) {
tasks.push((async (uri: string) => {
log(`Downloading image ${uri}...`);
const normalizedUri = uri.toLowerCase().split(/[\/\\]/).join(path.sep);
let imageData = null;
// Sometimes, Model Derivative service URIs must be left unmodified...
try {
imageData = await this.getAsset(uri);
} catch (err) {}
// Sometimes, they must be lower-cased...
if (!imageData) {
log(`Could not find image ${uri}, trying a lower-cased version of the URI...`);
try {
imageData = await this.getAsset(uri.toLowerCase());
} catch (err) {}
}
// And sometimes, they're just missing...
if (!imageData) {
log(`Still could not find image ${uri}; will default to a single black pixel placeholder image...`);
imageData = undefined;
}
const { normalizedUri, imageData } = await this.loadImage(uri);
output.images[normalizedUri] = imageData;
log(`Downloading image ${uri}: done`);
})(img));
Expand Down Expand Up @@ -504,6 +506,30 @@ export class Reader {
return Array.from(parseMaterials(buffer));
}

/**
* Loads an image.
* @param uri Image URI.
*/
async loadImage(uri: string) {
const normalizedUri = uri.toLowerCase().split(/[\/\\]/).join(path.sep);
let imageData = null;
// Sometimes, Model Derivative service URIs must be left unmodified...
try {
imageData = await this.getAsset(uri);
} catch (err) {}
// Sometimes, they must be lower-cased...
if (!imageData) {
try {
imageData = await this.getAsset(uri.toLowerCase());
} catch (err) {}
}
// And sometimes, they're just missing...
if (!imageData) {
imageData = undefined;
}
return { normalizedUri, imageData };
}

/**
* Finds URIs of all image assets referenced in the SVF.
* These can then be retrieved using {@link getAsset}.
Expand Down

0 comments on commit 8198078

Please sign in to comment.