Skip to content

Commit

Permalink
Merge pull request #32 from adobe/v1.0.7
Browse files Browse the repository at this point in the history
v1.0.7
  • Loading branch information
kwblackstone authored Aug 30, 2024
2 parents 5a3b1b9 + 7dabe2b commit 4045f51
Show file tree
Hide file tree
Showing 31 changed files with 1,340 additions and 699 deletions.
24 changes: 24 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
v1.0.7 August 30th, 2024
fbx:
- improved error handling in readFbx
- add light export support
- always make opacity a single value for usd on import
- mesh and node error checking
- export non-skeletal node animations
gltf:
- add support for importing lights
- update tinygltf version
- glb export avoid assert when there is a missing image file
obj:
- handle tabs before mtl name, and support .tif extension
- fix for converting with multiple materials
ply:
- add support to uint16 ply and allow gsplat without high-order shs
sbsar
- plugin add 8k resolution
stl
- calculate normals from geometry
utility:
- adjust interface material attributes to be closer to ASM
- fanTriangulate now fails when we have a malformed file

v1.0.6 July 31st, 2024
fbx:
- update FBXSDK to 2020.3.7
Expand Down
5 changes: 5 additions & 0 deletions fbx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
||||
|Cameras |||
||||
|Lights |⚠️|⚠️|
||||
|Mesh positions |||
|Mesh normals |||
|Mesh uvs |||
Expand Down Expand Up @@ -50,6 +52,7 @@
|FbxSurfaceLambert → UsdPreviewSurface|
|Hardware material is not imported|

- Only point, directional, and spot lights are imported. Other light types are ignored.

**Export:**

Expand All @@ -69,6 +72,8 @@ opacity → phongSurface::TransparentColor
ior → Not been used.
displacement → phongSurface::DisplacementColor

- Only point, directional, and spot lights are imported. Other light types are exported as point lights.

- **OBS: The image files used by the UsdPreviewShader node will be extracted from the USDZ file and saved as PNG files in the same folder as the generated fbx. If the source file is USD the files should also be copied from the USD folder into the FBX folder.**

## File Format Arguments
Expand Down
103 changes: 77 additions & 26 deletions fbx/src/fbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,30 +120,46 @@ printFbx(Fbx& fbx)
if (debugSkels) {
if (attrType == FbxNodeAttribute::eMesh) {
FbxMesh* fbxMesh = FbxCast<FbxMesh>(attribute);
int deformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
for (int i = 0; i < deformerCount; i++) {
FbxSkin* skin =
FbxCast<FbxSkin>(fbxMesh->GetDeformer(i, FbxDeformer::eSkin));
msg += " skin [";
for (int j = 0; j < skin->GetClusterCount(); j++) {
FbxCluster* cluster = skin->GetCluster(j);
FbxNode* link = cluster->GetLink();
msg += " skel::" + std::string(link->GetName());
if (fbxMesh != nullptr) {
int deformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
for (int j = 0; j < deformerCount; j++) {
FbxSkin* skin =
FbxCast<FbxSkin>(fbxMesh->GetDeformer(j, FbxDeformer::eSkin));
if (skin != nullptr) {
msg += " skin [";
for (int k = 0; k < skin->GetClusterCount(); k++) {
FbxCluster* cluster = skin->GetCluster(k);
if (cluster != nullptr) {
FbxNode* link = cluster->GetLink();
if (link != nullptr) {
msg += " skel::" + std::string(link->GetName());
} else {
TF_WARN("Cluster link is nullptr");
}
} else {
TF_WARN("Failed to retrieve cluster from skin");
}
}
msg += "]";
} else {
TF_WARN("Failed to cast Deformer to FbxSkin");
}
}
msg += "]";
} else {
TF_WARN("Failed to cast FbxNodeAttribute to FbxMesh");
}
}
if (i < nodeAttrCount - 1) {
msg += ", ";
}
}
if (i < nodeAttrCount - 1) {
msg += ", ";
}
}
msg += " }";
TF_DEBUG_MSG(FILE_FORMAT_FBX, "%*s%s\n", indent, " ", msg.c_str());
msg += " }";
TF_DEBUG_MSG(FILE_FORMAT_FBX, "%*s%s\n", indent, " ", msg.c_str());

indent += indentSize;
for (int i = 0; i < node->GetChildCount(); i++) {
printNode(node->GetChild(i), indent);
indent += indentSize;
for (int j = 0; j < node->GetChildCount(); j++) {
printNode(node->GetChild(j), indent);
}
}
};
printNode(fbx.scene->GetRootNode(), indentSize);
Expand All @@ -159,6 +175,10 @@ EmbedReadCBFunction(void* pUserData,
const void* pFileBuffer,
size_t pSizeInBytes)
{
if (!pUserData || !pFileName || !pFileBuffer || pSizeInBytes < 1) {
return FbxCallback::State::eNotHandled;
}

Fbx* fbx = reinterpret_cast<Fbx*>(pUserData);
TF_DEBUG_MSG(FILE_FORMAT_FBX, "EmbedReadCBFunction: %s\n", pFileName);

Expand All @@ -185,33 +205,49 @@ bool
readFbx(Fbx& fbx, const std::string& filename, bool onlyMaterials)
{
GUARD(fbx.manager != nullptr, "Invalid fbx manager");

FbxImporter* importer = FbxImporter::Create(fbx.manager, IOSROOT);
FbxIOSettings* ios = FbxIOSettings::Create(fbx.manager, IOSROOT);
GUARD(importer != nullptr, "Invalid fbx importer");
GUARD(ios != nullptr, "Invalid ios settings");

FbxIOSettings* ios = FbxIOSettings::Create(fbx.manager, IOSROOT);
if (!ios) {
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Failed to create FbxIOSettings");
importer->Destroy();
return false;
}

fbx.filename = filename;
ios->SetBoolProp(IMP_FBX_MATERIAL, true);
ios->SetBoolProp(IMP_FBX_TEXTURE, true);
ios->SetBoolProp(IMP_FBX_ANIMATION, !onlyMaterials);
ios->SetBoolProp(IMP_FBX_MODEL, !onlyMaterials);
fbx.loadImages = onlyMaterials;

if (!importer->Initialize(filename.c_str(), -1, ios)) {
FbxString error = importer->GetStatus().GetErrorString();
TF_RUNTIME_ERROR(FILE_FORMAT_FBX,
"Call to FbxExporter::Initialize() failed on opening file %s \n",
"Call to FbxImporter::Initialize() failed on opening file %s \n",
filename.c_str());
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Error returned: %s\n\n", error.Buffer());
importer->Destroy();
ios->Destroy();
return false;
}

// let fbx own importer
fbx.importer = importer;

// Create the read callback to handle loading embedded data (ie images)
FbxEmbeddedFileCallback* readCallback =
FbxEmbeddedFileCallback::Create(fbx.manager, "EmbeddedFileReadCallback");
GUARD(readCallback != nullptr, "Invalid read callback");

if (!readCallback) {
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Failed to create FbxEmbeddedFileCallback");
importer->Destroy();
ios->Destroy();
return false;
}

readCallback->RegisterReadFunction(EmbedReadCBFunction, (void*)&fbx);
importer->SetEmbeddedFileReadCallback(readCallback);

Expand All @@ -221,10 +257,11 @@ readFbx(Fbx& fbx, const std::string& filename, bool onlyMaterials)
TF_DEBUG_MSG(FILE_FORMAT_FBX, "FBX importer opened file %s \n", filename.c_str());
if (!importer->Import(fbx.scene)) {
FbxString error = importer->GetStatus().GetErrorString();
TF_RUNTIME_ERROR("Call to FbxExporter::Import() failed.\n");
TF_RUNTIME_ERROR("Error returned: %s\n\n", error.Buffer());
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Call to FbxImporter::Import() failed.\n");
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Error returned: %s\n\n", error.Buffer());
return false;
}

TF_DEBUG_MSG(FILE_FORMAT_FBX, "FBX read success \n");
printFbx(fbx);
return true;
Expand All @@ -237,6 +274,10 @@ EmbedWriteCBFunction(void* pUserData,
const void** pFileBuffer,
size_t* pSizeInBytes)
{
if (!pUserData || !pFileName || !pFileBuffer || !pSizeInBytes || *pSizeInBytes < 1) {
return FbxCallback::State::eNotHandled;
}

Fbx* fbx = reinterpret_cast<Fbx*>(pUserData);
TF_DEBUG_MSG(FILE_FORMAT_FBX, "EmbedWriteCBFunction: %s\n", pFileName);
for (const ImageAsset& image : fbx->images) {
Expand All @@ -262,7 +303,11 @@ writeFbx(const ExportFbxOptions& options, const Fbx& fbx, const std::string& fil
FbxIOSettings* ios = FbxIOSettings::Create(fbx.manager, IOSROOT);

GUARD(exporter != nullptr, "Invalid fbx exporter");
GUARD(ios != nullptr, "Invalid ios settings");
if (!ios) {
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Failed to create FbxIOSettings");
exporter->Destroy();
return false;
}
ios->SetBoolProp(EXP_FBX_MATERIAL, true);
ios->SetBoolProp(EXP_FBX_TEXTURE, true);
ios->SetBoolProp(EXP_FBX_ANIMATION, true);
Expand Down Expand Up @@ -296,10 +341,16 @@ writeFbx(const ExportFbxOptions& options, const Fbx& fbx, const std::string& fil
writeCallback->RegisterWriteFunction(EmbedWriteCBFunction, (void*)&fbx);
exporter->SetEmbeddedFileWriteCallback(writeCallback);
exportResult = exporter->Export(fbx.scene);
if (!exportResult) {
FbxString error = exporter->GetStatus().GetErrorString();
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Call to FbxExporter::Export() failed.\n");
TF_RUNTIME_ERROR(FILE_FORMAT_FBX, "Error returned: %s\n\n", error.Buffer());
}
writeCallback->Destroy();
}

exporter->Destroy();
ios->Destroy();
return exportResult;
}

Expand Down
Loading

0 comments on commit 4045f51

Please sign in to comment.