From a03e252866a9bd873074517d707cb51e61bf79c0 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 27 Oct 2017 12:21:13 -0700 Subject: [PATCH 1/9] Fix error reporting. --- npm/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/index.js b/npm/index.js index c570984..3b4030c 100644 --- a/npm/index.js +++ b/npm/index.js @@ -63,7 +63,7 @@ function convert(srcFile, destFile, opts = []) { // non-zero exit code is failure if (code != 0) { - reject(new Error(`Script ${script} output:\n` + + reject(new Error(`Converter output:\n` + (output.length ? output : ""))); } else { resolve(destPath + destExt); From 1829f6d6a6d3797568fecbba440978fa958d5d59 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 27 Oct 2017 15:29:09 -0700 Subject: [PATCH 2/9] RawSurface.skinRigid not used. --- src/RawModel.cpp | 1 - src/RawModel.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/RawModel.cpp b/src/RawModel.cpp index 5b625db..f9ffee7 100644 --- a/src/RawModel.cpp +++ b/src/RawModel.cpp @@ -196,7 +196,6 @@ int RawModel::AddSurface(const char *name, const char *nodeName) surface.nodeName = nodeName; surface.bounds.Clear(); surface.discrete = false; - surface.skinRigid = false; surfaces.emplace_back(surface); return (int) (surfaces.size() - 1); diff --git a/src/RawModel.h b/src/RawModel.h index 1dae913..ec86746 100644 --- a/src/RawModel.h +++ b/src/RawModel.h @@ -167,7 +167,6 @@ struct RawSurface std::vector jointGeometryMaxs; std::vector inverseBindMatrices; bool discrete; - bool skinRigid; }; struct RawChannel From 22354fd7ced08a4564794e4d3a02e10ce061146e Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 27 Oct 2017 15:31:21 -0700 Subject: [PATCH 3/9] Use standard library log2f. --- src/RawModel.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/RawModel.cpp b/src/RawModel.cpp index f9ffee7..8b3e134 100644 --- a/src/RawModel.cpp +++ b/src/RawModel.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #if defined( __unix__ ) @@ -21,11 +22,6 @@ #include "utils/Image_Utils.h" #include "RawModel.h" -static float Log2f(float f) -{ - return logf(f) * 1.442695041f; -} - bool RawVertex::operator==(const RawVertex &other) const { return (position == other.position) && @@ -101,7 +97,7 @@ int RawModel::AddTexture(const std::string &name, const std::string &fileName, c texture.name = name; texture.width = properties.width; texture.height = properties.height; - texture.mipLevels = (int) ceilf(Log2f(std::max((float) properties.width, (float) properties.height))); + texture.mipLevels = (int) ceilf(log2f(std::max((float) properties.width, (float) properties.height))); texture.usage = usage; texture.occlusion = (properties.occlusion == IMAGE_TRANSPARENT) ? RAW_TEXTURE_OCCLUSION_TRANSPARENT : RAW_TEXTURE_OCCLUSION_OPAQUE; From 075dc4a8c3b3dad137a0cd25273de2f93010ddc3 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 27 Oct 2017 15:47:49 -0700 Subject: [PATCH 4/9] Fix and improve inheritance warnings. We were warnings against eInheritRSrs, which is actually the one type of ineritance we're good with. It's eInheritRrSs we should freak out about. That said, no need to do it for the root node -- at that point there is no global transform to worry about. --- src/Fbx2Raw.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Fbx2Raw.cpp b/src/Fbx2Raw.cpp index d293c4e..c89798b 100644 --- a/src/Fbx2Raw.cpp +++ b/src/Fbx2Raw.cpp @@ -797,11 +797,11 @@ static void ReadNodeHierarchy( fmt::printf("node %d: %s\n", nodeIndex, newPath.c_str()); } - static int warnRSrsCount = 0; + static int warnRrSsCount = 0; static int warnRrsCount = 0; - if (lInheritType == FbxTransform::eInheritRSrs) { - if (++warnRSrsCount == 1) { - fmt::printf("Warning: node %s uses unsupported transform inheritance type 'eInheritRSrs'.\n", newPath); + if (lInheritType == FbxTransform::eInheritRrSs && !parentName.empty()) { + if (++warnRrSsCount == 1) { + fmt::printf("Warning: node %s uses unsupported transform inheritance type 'eInheritRrSs'.\n", newPath); fmt::printf(" (Further warnings of this type squelched.)\n"); } From 58518f5e00abc669a24d477cff4b2511cd9fe055 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sun, 29 Oct 2017 00:34:20 -0700 Subject: [PATCH 5/9] Tiny log string fix. --- src/Raw2Gltf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index d200378..5e5d383 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -320,7 +320,7 @@ ModelData *Raw2Gltf( const RawAnimation &animation = raw.GetAnimation(i); if (animation.channels.size() == 0) { - fmt::printf("Warning: animation '%s has zero channels. Skipping.\n", animation.name.c_str()); + fmt::printf("Warning: animation '%s' has zero channels. Skipping.\n", animation.name.c_str()); continue; } From 7f9aa3318a9c0895ab2ff1c21d8a3f8fa27b1aef Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Tue, 31 Oct 2017 11:33:32 -0700 Subject: [PATCH 6/9] Use .exe suffix on Windows. --- npm/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/npm/index.js b/npm/index.js index 3b4030c..7aa2d24 100644 --- a/npm/index.js +++ b/npm/index.js @@ -22,7 +22,8 @@ const binaries = { function convert(srcFile, destFile, opts = []) { return new Promise((resolve, reject) => { try { - let tool = path.join(__dirname, 'bin', os.type(), 'FBX2glTF'); + let binExt = os.type() === 'Windows_NT' ? '.exe' : ''; + let tool = path.join(__dirname, 'bin', os.type(), 'FBX2glTF' + binExt); if (!fs.existsSync(tool)) { throw new Error(`Unsupported OS: ${os.type()}`); } From 0fcd00cb5b0705373bf613f6b2588c9482ed48be Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Tue, 31 Oct 2017 20:18:14 -0700 Subject: [PATCH 7/9] Get rid of some pointless copying. --- src/mathfu.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mathfu.h b/src/mathfu.h index a49f687..f5e3617 100644 --- a/src/mathfu.h +++ b/src/mathfu.h @@ -33,7 +33,7 @@ struct Bounds initialized = false; } - void AddPoint(mathfu::Vector p) { + void AddPoint(const mathfu::Vector &p) { if (initialized) { for (int ii = 0; ii < d; ii ++) { min(ii) = std::min(min(ii), p(ii)); @@ -58,7 +58,7 @@ typedef mathfu::Matrix Mat4f; typedef mathfu::Quaternion Quatf; typedef Bounds Boundsf; -template static inline std::vector toStdVec(mathfu::Vector vec) +template static inline std::vector toStdVec(const mathfu::Vector &vec) { std::vector result(d); for (int ii = 0; ii < d; ii ++) { @@ -67,7 +67,7 @@ template static inline std::vector toStdVec(mathfu::Vector std::vector toStdVec(mathfu::Quaternion quat) { +template std::vector toStdVec(const mathfu::Quaternion &quat) { return std::vector { quat.vector()[0], quat.vector()[1], quat.vector()[2], quat.scalar() }; } From 14150269a05865f618b7ab5c2c3810627df9fa64 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 3 Nov 2017 21:48:41 -0700 Subject: [PATCH 8/9] Switch FbxDouble4 uses to FbxVector4, clean up. --- src/Fbx2Raw.cpp | 23 ++++++++++------------- src/mathfu.h | 4 ++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Fbx2Raw.cpp b/src/Fbx2Raw.cpp index c89798b..b3ac439 100644 --- a/src/Fbx2Raw.cpp +++ b/src/Fbx2Raw.cpp @@ -92,13 +92,13 @@ class FbxMaterialAccess { struct FbxMaterialProperties { FbxFileTexture *texAmbient {}; - FbxDouble4 colAmbient {}; + FbxVector4 colAmbient {}; FbxFileTexture *texSpecular {}; - FbxDouble4 colSpecular {}; + FbxVector4 colSpecular {}; FbxFileTexture *texDiffuse {}; - FbxDouble4 colDiffuse {}; + FbxVector4 colDiffuse {}; FbxFileTexture *texEmissive {}; - FbxDouble4 colEmissive {}; + FbxVector4 colEmissive {}; FbxFileTexture *texNormal {}; FbxFileTexture *texShininess {}; FbxDouble shininess {}; @@ -129,7 +129,7 @@ public: // four properties are on the same structure and follow the same rules auto handleBasicProperty = [&](const char *colName, const char *facName) { FbxFileTexture *colTex, *facTex; - FbxDouble4 vec; + FbxVector4 vec; std::tie(vec, colTex, facTex) = getSurfaceValues(colName, facName); if (colTex) { @@ -157,7 +157,7 @@ public: std::tie(res.shininess, res.texShininess) = getSurfaceScalar(FbxSurfaceMaterial::sShininess); // for transparency we just want a constant vector value; - FbxDouble4 transparency; + FbxVector4 transparency; // extract any existing textures only so we can warn that we're throwing them away FbxFileTexture *colTex, *facTex; std::tie(transparency, colTex, facTex) = @@ -204,7 +204,7 @@ public: return std::make_tuple(val, tex); } - std::tuple getSurfaceValues(const char *colName, const char *facName) const + std::tuple getSurfaceValues(const char *colName, const char *facName) const { const FbxProperty colProp = fbxMaterial->FindProperty(colName); const FbxProperty facProp = fbxMaterial->FindProperty(facName); @@ -227,7 +227,7 @@ public: factorVal = facProp.Get(); } - auto val = FbxDouble4( + auto val = FbxVector4( colorVal[0] * factorVal, colorVal[1] * factorVal, colorVal[2] * factorVal, @@ -552,7 +552,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: std::fill_n(textures, RAW_TEXTURE_USAGE_MAX, -1); FbxString shadingModel, materialName; - FbxDouble4 ambient, specular, diffuse, emissive; + FbxVector4 ambient, specular, diffuse, emissive; FbxDouble shininess; if (fbxMaterial == nullptr) { @@ -588,13 +588,10 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: maybeAddTexture(matProps.texShininess, RAW_TEXTURE_USAGE_SHININESS); } - auto toVec3 = [](FbxDouble4 vec4) { return Vec3f(vec4[0], vec4[1], vec4[2]); }; - auto toVec4 = [](FbxDouble4 vec4) { return Vec4f(vec4[0], vec4[1], vec4[2], vec4[3]); }; - const RawMaterialType materialType = GetMaterialType(raw, textures, skinning.IsSkinned()); const int rawMaterialIndex = raw.AddMaterial( materialName, shadingModel, materialType, textures, - toVec3(ambient), toVec4(diffuse), toVec3(specular), toVec3(emissive), shininess); + toVec3f(ambient), toVec4f(diffuse), toVec3f(specular), toVec3f(emissive), shininess); RawVertex rawVertices[3]; for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++, polygonVertexIndex++) { diff --git a/src/mathfu.h b/src/mathfu.h index f5e3617..922267f 100644 --- a/src/mathfu.h +++ b/src/mathfu.h @@ -75,6 +75,10 @@ static inline Vec3f toVec3f(const FbxVector4 &v) { return Vec3f((float) v[0], (float) v[1], (float) v[2]); } +static inline Vec4f toVec4f(const FbxVector4 &v) { + return Vec4f((float) v[0], (float) v[1], (float) v[2], (float) v[3]); +} + static inline Mat4f toMat4f(const FbxAMatrix &m) { auto result = Mat4f(); for (int row = 0; row < 4; row ++) { From 5e0f05261cff5f3be2dba18a565b021fb65940e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Winzell?= Date: Sat, 4 Nov 2017 20:10:28 -0700 Subject: [PATCH 9/9] Sort triangles with vertex transparency separately. (#32) Lean on the excellent pre-existing support for creating multiple glTF meshes from a single FBX mesh based on material type. All the triangles with (at least one) non-opaque vertex get flagged as transparent material. They will all go separately in their own mesh after the CreateMaterialModels() gauntlet. Fixes #25. --- src/Fbx2Raw.cpp | 21 +++++++++++++-------- src/Raw2Gltf.cpp | 2 -- src/RawModel.h | 2 -- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Fbx2Raw.cpp b/src/Fbx2Raw.cpp index b3ac439..8153183 100644 --- a/src/Fbx2Raw.cpp +++ b/src/Fbx2Raw.cpp @@ -458,10 +458,11 @@ static bool TriangleTexturePolarity(const Vec2f &uv0, const Vec2f &uv1, const Ve } static RawMaterialType -GetMaterialType(const RawModel &raw, const int textures[RAW_TEXTURE_USAGE_MAX], const bool skinned) +GetMaterialType(const RawModel &raw, const int textures[RAW_TEXTURE_USAGE_MAX], const bool vertexTransparency, const bool skinned) { - if ((raw.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_COLOR) != 0) { - return skinned ? RAW_MATERIAL_TYPE_SKINNED_VERTEX_COLORED : RAW_MATERIAL_TYPE_VERTEX_COLORED; + // if there is vertex transparency, definitely transparent + if (vertexTransparency) { + return skinned ? RAW_MATERIAL_TYPE_SKINNED_TRANSPARENT : RAW_MATERIAL_TYPE_TRANSPARENT; } // Determine material type based on texture occlusion. @@ -588,12 +589,8 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: maybeAddTexture(matProps.texShininess, RAW_TEXTURE_USAGE_SHININESS); } - const RawMaterialType materialType = GetMaterialType(raw, textures, skinning.IsSkinned()); - const int rawMaterialIndex = raw.AddMaterial( - materialName, shadingModel, materialType, textures, - toVec3f(ambient), toVec4f(diffuse), toVec3f(specular), toVec3f(emissive), shininess); - RawVertex rawVertices[3]; + bool vertexTransparency = false; for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++, polygonVertexIndex++) { const int controlPointIndex = pMesh->GetPolygonVertex(polygonIndex, vertexIndex); @@ -636,6 +633,9 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: vertex.jointWeights = skinning.GetVertexWeights(controlPointIndex); vertex.polarityUv0 = false; + // flag this triangle as transparent if any of its corner vertices substantially deviates from fully opaque + vertexTransparency |= (fabs(fbxColor.mAlpha - 1.0) > 1e-3); + rawSurface.bounds.AddPoint(vertex.position); if (skinning.IsSkinned()) { @@ -690,6 +690,11 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: rawVertexIndices[vertexIndex] = raw.AddVertex(rawVertices[vertexIndex]); } + const RawMaterialType materialType = GetMaterialType(raw, textures, vertexTransparency, skinning.IsSkinned()); + const int rawMaterialIndex = raw.AddMaterial( + materialName, shadingModel, materialType, textures, + toVec3f(ambient), toVec4f(diffuse), toVec3f(specular), toVec3f(emissive), shininess); + raw.AddTriangle(rawVertexIndices[0], rawVertexIndices[1], rawVertexIndices[2], rawMaterialIndex, rawSurfaceIndex); } } diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index 5e5d383..1dc3139 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -410,8 +410,6 @@ ModelData *Raw2Gltf( for (int materialIndex = 0; materialIndex < raw.GetMaterialCount(); materialIndex++) { const RawMaterial &material = raw.GetMaterial(materialIndex); const bool isTransparent = - material.type == RAW_MATERIAL_TYPE_VERTEX_COLORED || - material.type == RAW_MATERIAL_TYPE_SKINNED_VERTEX_COLORED || material.type == RAW_MATERIAL_TYPE_TRANSPARENT || material.type == RAW_MATERIAL_TYPE_SKINNED_TRANSPARENT; diff --git a/src/RawModel.h b/src/RawModel.h index ec86746..e0b01b9 100644 --- a/src/RawModel.h +++ b/src/RawModel.h @@ -136,10 +136,8 @@ enum RawMaterialType { RAW_MATERIAL_TYPE_OPAQUE, RAW_MATERIAL_TYPE_TRANSPARENT, - RAW_MATERIAL_TYPE_VERTEX_COLORED, RAW_MATERIAL_TYPE_SKINNED_OPAQUE, RAW_MATERIAL_TYPE_SKINNED_TRANSPARENT, - RAW_MATERIAL_TYPE_SKINNED_VERTEX_COLORED }; struct RawMaterial