From a3841fe7cd1f3652f47af8ed0566f8414ba00ad2 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sat, 23 Feb 2019 23:51:05 -0800 Subject: [PATCH 1/4] Formatting-only change. --- npm/tests/test/fbx2gltf.ts | 124 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/npm/tests/test/fbx2gltf.ts b/npm/tests/test/fbx2gltf.ts index ea88cf2..da2ed0f 100644 --- a/npm/tests/test/fbx2gltf.ts +++ b/npm/tests/test/fbx2gltf.ts @@ -1,76 +1,76 @@ -import { readFileSync } from 'fs'; -import * as tmp from 'tmp'; -import * as path from 'path'; +import {assert, expect} from 'chai'; import * as fbx2gltf from 'fbx2gltf'; -import { assert, expect } from 'chai'; -import { validateBytes } from 'gltf-validator'; +import {readFileSync} from 'fs'; +import {validateBytes} from 'gltf-validator'; +import * as path from 'path'; +import * as tmp from 'tmp'; interface Model { - path: string; - ignoredIssues?: Array; - args?: Array; + path: string; + ignoredIssues?: Array; + args?: Array; } -const MODELS :Array = [ - { path: 'fromFacebook/Jon/jon_morph' }, - { - path: 'fromFacebook/Jon/troll-final', - ignoredIssues: [ 'ACCESSOR_NON_UNIT' ], - }, - { path: 'fromFacebook/Natalie/GlitchRobot' }, - { path: 'fromFacebook/Ocean/blackvan/blackvan_with_windows' }, - { path: 'fromFacebook/Ocean/zell_van_vertex_color' }, - { path: 'fromFacebook/RAZ/RAZ_ape' }, - { path: 'fromFbxSDK/Box' }, - { - path: 'fromFbxSDK/Humanoid', - ignoredIssues: [ 'UNSUPPORTED_EXTENSION' ], - }, - { - path: 'fromFbxSDK/Camera', - ignoredIssues: [ 'UNSUPPORTED_EXTENSION' ], - }, - { path: 'fromFbxSDK/Normals' }, - { path: 'fromGltfSamples/BoxVertexColors/BoxVertexColors' }, - { path: 'fromGltfSamples/WaterBottle/NewWaterBottle' }, +const MODELS: Array = [ + {path : 'fromFacebook/Jon/jon_morph'}, + { + path : 'fromFacebook/Jon/troll-final', + ignoredIssues : [ 'ACCESSOR_NON_UNIT' ], + }, + {path : 'fromFacebook/Natalie/GlitchRobot'}, + {path : 'fromFacebook/Ocean/blackvan/blackvan_with_windows'}, + {path : 'fromFacebook/Ocean/zell_van_vertex_color'}, + {path : 'fromFacebook/RAZ/RAZ_ape'}, + {path : 'fromFbxSDK/Box'}, + { + path : 'fromFbxSDK/Humanoid', + ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ], + }, + { + path : 'fromFbxSDK/Camera', + ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ], + }, + {path : 'fromFbxSDK/Normals'}, + {path : 'fromGltfSamples/BoxVertexColors/BoxVertexColors'}, + {path : 'fromGltfSamples/WaterBottle/NewWaterBottle'}, ]; const CONVERSION_TIMEOUT_MS = 50000; describe('FBX2glTF', () => { - const tmpobj = tmp.dirSync(); - for(let model of MODELS) { - const modelName = path.basename(model.path); - describe('Model: ' + modelName, () => { - const fbxPath = path.join('models', model.path + '.fbx'); - let glbBytes; - it('should convert fbx to glb', async () => { - const glbPath = path.join(tmpobj.name, modelName + '.glb'); + const tmpobj = tmp.dirSync(); + for (let model of MODELS) { + const modelName = path.basename(model.path); + describe('Model: ' + modelName, () => { + const fbxPath = path.join('models', model.path + '.fbx'); + let glbBytes; + it('should convert fbx to glb', async () => { + const glbPath = path.join(tmpobj.name, modelName + '.glb'); - try { - const destPath = await fbx2gltf(fbxPath, glbPath, model.args || []); - assert.isNotNull(destPath); - glbBytes = readFileSync(destPath); - } catch (err) { - throw new Error('Conversion failed: ' + err); - } - }).timeout(CONVERSION_TIMEOUT_MS); + try { + const destPath = await fbx2gltf(fbxPath, glbPath, model.args || []); + assert.isNotNull(destPath); + glbBytes = readFileSync(destPath); + } catch (err) { + throw new Error('Conversion failed: ' + err); + } + }).timeout(CONVERSION_TIMEOUT_MS); - it('resulting glb should be valid', async() => { - try { - let options = {}; - if (model.ignoredIssues) { - options.ignoredIssues = model.ignoredIssues; - } - const report = await validateBytes(glbBytes, options); - expect(report.issues.numErrors).to.equal(0); - expect(report.issues.numWarnings).to.equal(0); + it('resulting glb should be valid', async () => { + try { + let options = {}; + if (model.ignoredIssues) { + options.ignoredIssues = model.ignoredIssues; + } + const report = await validateBytes(glbBytes, options); + expect(report.issues.numErrors).to.equal(0); + expect(report.issues.numWarnings).to.equal(0); - } catch (err) { - throw new Error('Validation failed: ' + err); - } - }); - }); - } - console.log('GLB files may be inspected in: ' + tmpobj.name); + } catch (err) { + throw new Error('Validation failed: ' + err); + } + }); + }); + } + console.log('GLB files may be inspected in: ' + tmpobj.name); }); From 4780efdc6f013dab9eb9816766dd40aac42045f0 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sun, 24 Feb 2019 17:42:13 -0800 Subject: [PATCH 2/4] Extend tests a bit. --- npm/tests/test/fbx2gltf.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/npm/tests/test/fbx2gltf.ts b/npm/tests/test/fbx2gltf.ts index da2ed0f..118a2b7 100644 --- a/npm/tests/test/fbx2gltf.ts +++ b/npm/tests/test/fbx2gltf.ts @@ -19,8 +19,12 @@ const MODELS: Array = [ }, {path : 'fromFacebook/Natalie/GlitchRobot'}, {path : 'fromFacebook/Ocean/blackvan/blackvan_with_windows'}, - {path : 'fromFacebook/Ocean/zell_van_vertex_color'}, - {path : 'fromFacebook/RAZ/RAZ_ape'}, + { + path : 'fromFacebook/Ocean/zell_van_vertex_color', + args : [ '--draco' ], + ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ], + }, + {path : 'fromFacebook/RAZ/RAZ_ape', args : [ '--long-indices=always' ]}, {path : 'fromFbxSDK/Box'}, { path : 'fromFbxSDK/Humanoid', @@ -31,7 +35,7 @@ const MODELS: Array = [ ignoredIssues : [ 'UNSUPPORTED_EXTENSION' ], }, {path : 'fromFbxSDK/Normals'}, - {path : 'fromGltfSamples/BoxVertexColors/BoxVertexColors'}, + {path : 'fromGltfSamples/BoxVertexColors/BoxVertexColors', args : [ '--khr-materials-unlit' ]}, {path : 'fromGltfSamples/WaterBottle/NewWaterBottle'}, ]; From a596073f0423635115ad9db42cd855a80b055ffd Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sun, 24 Feb 2019 19:32:13 -0800 Subject: [PATCH 3/4] Identify materials by unique ID, not name. At the end of the various material/mesh transformations we do, we were still using a ridiculously simplistic method of mapping RawMaterial to glTF MaterialData. This switches to using FBX's GetUniqueID(), which should be the law of the land in general. Other model entities may need further investigation as well. --- src/fbx/Fbx2Raw.cpp | 7 +++++-- src/fbx/materials/3dsMaxPhysicalMaterial.cpp | 1 + src/fbx/materials/FbxMaterials.hpp | 5 +++-- src/fbx/materials/RoughnessMetallicMaterials.hpp | 3 ++- src/fbx/materials/StingrayPBSMaterial.cpp | 1 + src/fbx/materials/TraditionalMaterials.cpp | 4 ++-- src/fbx/materials/TraditionalMaterials.hpp | 7 +++++-- src/gltf/Raw2Gltf.cpp | 14 ++++++-------- src/raw/RawModel.cpp | 3 +++ src/raw/RawModel.hpp | 2 ++ 10 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 189828e..9a11bdd 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -209,9 +209,11 @@ static void ReadMesh( std::shared_ptr rawMatProps; FbxString materialName; + long materialId; if (fbxMaterial == nullptr) { materialName = "DefaultMaterial"; + materialId = -1; rawMatProps.reset(new RawTraditionalMatProps( RAW_SHADING_MODEL_LAMBERT, Vec3f(0, 0, 0), @@ -222,6 +224,7 @@ static void ReadMesh( } else { materialName = fbxMaterial->name; + materialId = fbxMaterial->id; const auto maybeAddTexture = [&](const FbxFileTexture* tex, RawTextureUsage usage) { if (tex != nullptr) { @@ -436,8 +439,8 @@ static void ReadMesh( const RawMaterialType materialType = GetMaterialType(raw, textures, vertexTransparency, skinning.IsSkinned()); - const int rawMaterialIndex = - raw.AddMaterial(materialName, materialType, textures, rawMatProps, userProperties); + const int rawMaterialIndex = raw.AddMaterial( + materialId, materialName, materialType, textures, rawMatProps, userProperties); raw.AddTriangle( rawVertexIndices[0], diff --git a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp index aa619cd..362c3a7 100644 --- a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp +++ b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp @@ -149,6 +149,7 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso } std::unique_ptr res(new FbxRoughMetMaterialInfo( + fbxMaterial->GetUniqueID(), fbxMaterial->GetName(), FbxRoughMetMaterialInfo::FBX_SHADER_METROUGH, baseCol, diff --git a/src/fbx/materials/FbxMaterials.hpp b/src/fbx/materials/FbxMaterials.hpp index 9141b78..c48a829 100644 --- a/src/fbx/materials/FbxMaterials.hpp +++ b/src/fbx/materials/FbxMaterials.hpp @@ -16,9 +16,10 @@ class FbxMaterialInfo { public: - FbxMaterialInfo(const FbxString& name, const FbxString& shadingModel) - : name(name), shadingModel(shadingModel) {} + FbxMaterialInfo(const FbxUInt64 id, const FbxString& name, const FbxString& shadingModel) + : id(id), name(name), shadingModel(shadingModel) {} + const FbxUInt64 id; const FbxString name; const FbxString shadingModel; }; diff --git a/src/fbx/materials/RoughnessMetallicMaterials.hpp b/src/fbx/materials/RoughnessMetallicMaterials.hpp index 9123e28..ad430ae 100644 --- a/src/fbx/materials/RoughnessMetallicMaterials.hpp +++ b/src/fbx/materials/RoughnessMetallicMaterials.hpp @@ -21,12 +21,13 @@ struct FbxRoughMetMaterialInfo : FbxMaterialInfo { const std::map& textureLocations); FbxRoughMetMaterialInfo( + const FbxUInt64 id, const FbxString& name, const FbxString& shadingModel, FbxDouble4 baseColor, FbxDouble metallic, FbxDouble roughness) - : FbxMaterialInfo(name, shadingModel), + : FbxMaterialInfo(id, name, shadingModel), baseColor(baseColor), metallic(metallic), roughness(roughness) {} diff --git a/src/fbx/materials/StingrayPBSMaterial.cpp b/src/fbx/materials/StingrayPBSMaterial.cpp index 05dc5e1..29ef74f 100644 --- a/src/fbx/materials/StingrayPBSMaterial.cpp +++ b/src/fbx/materials/StingrayPBSMaterial.cpp @@ -54,6 +54,7 @@ std::unique_ptr FbxStingrayPBSMaterialResolver::resolve FbxDouble3 baseColor = getVec("base_color"); std::unique_ptr res(new FbxRoughMetMaterialInfo( + fbxMaterial->GetUniqueID(), fbxMaterial->GetName(), FbxRoughMetMaterialInfo::FBX_SHADER_METROUGH, FbxDouble4(baseColor[0], baseColor[1], baseColor[2], 1), diff --git a/src/fbx/materials/TraditionalMaterials.cpp b/src/fbx/materials/TraditionalMaterials.cpp index 6b0bc17..919dd99 100644 --- a/src/fbx/materials/TraditionalMaterials.cpp +++ b/src/fbx/materials/TraditionalMaterials.cpp @@ -68,8 +68,8 @@ std::unique_ptr FbxTraditionalMaterialResolver::reso }; std::string name = fbxMaterial->GetName(); - std::unique_ptr res( - new FbxTraditionalMaterialInfo(name.c_str(), fbxMaterial->ShadingModel.Get())); + std::unique_ptr res(new FbxTraditionalMaterialInfo( + fbxMaterial->GetUniqueID(), name.c_str(), fbxMaterial->ShadingModel.Get())); // four properties are on the same structure and follow the same rules auto handleBasicProperty = [&](const char* colName, diff --git a/src/fbx/materials/TraditionalMaterials.hpp b/src/fbx/materials/TraditionalMaterials.hpp index c0fa51d..31a3912 100644 --- a/src/fbx/materials/TraditionalMaterials.hpp +++ b/src/fbx/materials/TraditionalMaterials.hpp @@ -14,8 +14,11 @@ struct FbxTraditionalMaterialInfo : FbxMaterialInfo { static constexpr const char* FBX_SHADER_BLINN = "Blinn"; static constexpr const char* FBX_SHADER_PHONG = "Phong"; - FbxTraditionalMaterialInfo(const FbxString& name, const FbxString& shadingModel) - : FbxMaterialInfo(name, shadingModel) {} + FbxTraditionalMaterialInfo( + const FbxUInt64 id, + const FbxString& name, + const FbxString& shadingModel) + : FbxMaterialInfo(id, name, shadingModel) {} FbxFileTexture* texAmbient{}; FbxVector4 colAmbient{}; diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index 01b4afe..9b35618 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -77,11 +77,6 @@ static const std::vector getIndexArray(const RawModel& raw) { return result; } -// TODO: replace with a proper MaterialHasher class -static const std::string materialHash(const RawMaterial& m) { - return m.name + "_" + std::to_string(m.type); -} - ModelData* Raw2Gltf( std::ofstream& gltfOutStream, const std::string& outputFolder, @@ -123,7 +118,7 @@ ModelData* Raw2Gltf( std::unique_ptr gltf(new GltfModel(options)); std::map> nodesById; - std::map> materialsByName; + std::map> materialsById; std::map> textureByIndicesKey; std::map> meshBySurfaceId; @@ -394,7 +389,8 @@ ModelData* Raw2Gltf( emissiveFactor * emissiveIntensity, khrCmnUnlitMat, pbrMetRough)); - materialsByName[materialHash(material)] = mData; + fmt::printf("Stashing material of id %ls, name %s...\n", material.id, material.name.c_str()); + materialsById[material.id] = mData; if (options.enableUserProperties) { mData->userProperties = material.userProperties; @@ -408,7 +404,9 @@ ModelData* Raw2Gltf( const RawMaterial& rawMaterial = surfaceModel.GetMaterial(surfaceModel.GetTriangle(0).materialIndex); - const MaterialData& mData = require(materialsByName, materialHash(rawMaterial)); + fmt::printf( + "Seeking material of id %ls, name %s...\n", rawMaterial.id, rawMaterial.name.c_str()); + const MaterialData& mData = require(materialsById, rawMaterial.id); MeshData* mesh = nullptr; auto meshIter = meshBySurfaceId.find(surfaceId); diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index 38b5fc7..cafc076 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -129,6 +129,7 @@ int RawModel::AddTexture( int RawModel::AddMaterial(const RawMaterial& material) { return AddMaterial( + material.id, material.name.c_str(), material.type, material.textures, @@ -137,6 +138,7 @@ int RawModel::AddMaterial(const RawMaterial& material) { } int RawModel::AddMaterial( + const long id, const char* name, const RawMaterialType materialType, const int textures[RAW_TEXTURE_USAGE_MAX], @@ -169,6 +171,7 @@ int RawModel::AddMaterial( } RawMaterial material; + material.id = id; material.name = name; material.type = materialType; material.info = materialInfo; diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index 0b81903..c21c4bb 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -262,6 +262,7 @@ struct RawMetRoughMatProps : RawMatProps { }; struct RawMaterial { + long id; std::string name; RawMaterialType type; std::shared_ptr info; @@ -374,6 +375,7 @@ class RawModel { RawTextureUsage usage); int AddMaterial(const RawMaterial& material); int AddMaterial( + const long id, const char* name, const RawMaterialType materialType, const int textures[RAW_TEXTURE_USAGE_MAX], From b8d587d2c793032235af572e9e4629f77f22e5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Winzell?= Date: Mon, 25 Feb 2019 09:31:15 -0800 Subject: [PATCH 4/4] Add link to bleeding-edge builds. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7ec8fab..14992c5 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ a modern runtime asset delivery format. Precompiled binaries releases for Windows, Mac OS X and Linux may be found [here](https://github.com/facebookincubator/FBX2glTF/releases). +Bleeding-edge binaries are periodically built and publicly available [here](https://dev.azure.com/parwinzell/FBX2glTF/): click a build (usually the most recent), then the 'Artefacts' dropdown in the upper right. + ## Running The tool can be invoked like so: