UNPKG

forge-convert-utils

Version:

Tools for converting Autodesk Forge file formats.

91 lines (79 loc) 3.79 kB
/* * Example: converting an SVF from Model Derivative service into glTF, * embedding object IDs into the COLOR_0 mesh channel. * Usage: * export FORGE_CLIENT_ID=<your client id> * export FORGE_CLIENT_SECRET=<your client secret> * node custom-gltf-attribute.js <your model urn> <path to output folder> */ const path = require('path'); const { ModelDerivativeClient, ManifestHelper } = require('forge-server-utils'); const { SvfReader, GltfWriter } = require('..'); /* * Customized glTF writer, outputting meshes with an additional _CUSTOM_INDEX * mesh attribute (UNSIGNED_BYTE, vec4) encoding a 32-bit object ID. */ class CustomGltfWriter extends GltfWriter { constructor(options) { super(options); this._currentDbId = -1; } createNode(fragment /* IMF.IObjectNode */, imf /* IMF.IScene */, outputUvs /* boolean */) /* gltf.Node */ { this._currentDbId = fragment.dbid; return super.createNode(fragment, imf, outputUvs); } createMeshGeometry(geometry /* IMF.IMeshGeometry */, imf /* IMF.IScene */, outputUvs /* boolean */) /* gltf.Mesh */ { let mesh = super.createMeshGeometry(geometry, imf, outputUvs); let prim = mesh.primitives[0]; if (prim) { // Output custom attr buffer const vertexCount = geometry.getVertices().length / 3; const customBuffer = Buffer.alloc(vertexCount * 4); for (let i = 0; i < customBuffer.length; i += 4) { customBuffer[i] = this._currentDbId & 0xff; customBuffer[i + 1] = (this._currentDbId >> 8) & 0xff; customBuffer[i + 2] = (this._currentDbId >> 16) & 0xff; customBuffer[i + 3] = (this._currentDbId >> 24) & 0xff; } const customBufferView = this.createBufferView(customBuffer); const customBufferViewID = this.addBufferView(customBufferView); const customAccessor = this.createAccessor(customBufferViewID, 5121 /* UNSIGNED_BYTE */, customBufferView.byteLength / 4, 'VEC4'); customAccessor.normalized = true; const customAccessorID = this.addAccessor(customAccessor); prim.attributes['COLOR_0'] = customAccessorID; } return mesh; } computeMeshHash(mesh /* gltf.Mesh */) /* string */ { return mesh.primitives.map(p => { return `${p.mode || ''}/${p.material || ''}/${p.indices}` + `/${p.attributes['POSITION'] || ''}/${p.attributes['NORMAL'] || ''}/${p.attributes['TEXCOORD_0'] || ''}` + `/${p.attributes['COLOR_0'] || ''}`; }).join('/'); } } const { FORGE_CLIENT_ID, FORGE_CLIENT_SECRET } = process.env; async function run(urn, outputDir) { const DefaultOptions = { deduplicate: false, skipUnusedUvs: false, center: true, log: console.log }; try { const auth = { client_id: FORGE_CLIENT_ID, client_secret: FORGE_CLIENT_SECRET }; const modelDerivativeClient = new ModelDerivativeClient(auth); const helper = new ManifestHelper(await modelDerivativeClient.getManifest(urn)); const derivatives = helper.search({ type: 'resource', role: 'graphics' }); const writer = new CustomGltfWriter(Object.assign({}, DefaultOptions)); for (const derivative of derivatives.filter(d => d.mime === 'application/autodesk-svf')) { const reader = await SvfReader.FromDerivativeService(urn, derivative.guid, auth); const scene = await reader.read({ log: console.log }); await writer.write(scene, path.join(outputDir, derivative.guid)); } } catch (err) { console.error(err); process.exit(1); } } run(process.argv[2], process.argv[3]);