diff --git a/npm/index.js b/npm/index.js index c570984..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()}`); } @@ -63,7 +64,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); diff --git a/src/Fbx2Raw.cpp b/src/Fbx2Raw.cpp index 33d1444..297cc56 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, @@ -627,10 +627,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. @@ -737,7 +738,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) { @@ -773,15 +774,8 @@ 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); - RawVertex rawVertices[3]; + bool vertexTransparency = false; for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++, polygonVertexIndex++) { const int controlPointIndex = pMesh->GetPolygonVertex(polygonIndex, vertexIndex); @@ -824,6 +818,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 (!targetShapes.empty()) { @@ -896,6 +893,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); } } @@ -1000,11 +1002,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"); } diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index cc479cc..3aafe3c 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; } @@ -413,8 +413,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.cpp b/src/RawModel.cpp index 4c23a27..22084c2 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) && @@ -103,7 +99,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; @@ -198,7 +194,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 97c8e32..1d0961f 100644 --- a/src/RawModel.h +++ b/src/RawModel.h @@ -155,10 +155,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 diff --git a/src/mathfu.h b/src/mathfu.h index a49f687..922267f 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() }; } @@ -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 ++) {