Skip to content

Commit

Permalink
Merge pull request #28 from adobe/v1.0.5
Browse files Browse the repository at this point in the history
version 1.0.5 update
  • Loading branch information
kwblackstone authored Jun 26, 2024
2 parents a59d270 + 5bde4df commit 154937f
Show file tree
Hide file tree
Showing 41 changed files with 866 additions and 497 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ build-meta

# Generated documentation
docs
bin

# Test
Testing
bin
test/__pycache__
test/output
test/assets/fbx/*.usd
Expand Down
18 changes: 18 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
v1.0.5 June 26th, 2024
fbx:
- import/export linear/srgb option
- import animations for non-skeletal nodes
gltf:
- documentation added khronos latest extensions to readme
obj:
- group name and material index propagation
- import/export linear/srgb option
sbsar:
- if $outputsize is voluntary un-exposed we must skip resolution variant creation
- support all output values
- delayed substance engine initialization
- set default resolution using a global class prim in USD for materials
utility:
- static analysis cleanup
- move info from comment to doc

v1.0.4 May 31st, 2024
gltf:
- ability to open gltf file from within usd archive
Expand Down
26 changes: 26 additions & 0 deletions fbx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ displacement → phongSurface::DisplacementColor
```
The phong to PBR conversion follows https://docs.microsoft.com/en-us/azure/remote-rendering/reference/material-mapping. Keep in mind it is a lossy conversion.
* `fbxOriginalColorSpace`: USD uses linear colorspace, however, FBX colorspace could be either linear or sRGB.
The user can set which one the data was in during import. If the data is in sRGB it will be converted to linear while in USD. Exporting will also consider the original color space. See Export -> outputColorSpace for details.
```
UsdStageRefPtr stage = UsdStage::Open("cube.fbx:SDF_FORMAT_ARGS:fbxOriginalColorSpace=sRGB")
```
**Export:**
* `embedImages` Embed images in the exported fbx file instead of as separate files. Default is `false`.
Expand All @@ -100,6 +107,25 @@ displacement → phongSurface::DisplacementColor
SdfLayer::FileFormatArguments args = { {"embedImages", "true"} };
stage->Export("cube.fbx", false, args);
```
* `outputColorSpace`: USD uses linear colorspace, however, the original FBX colorspace could be either linear or sRGB.
If fbxOriginalColorSpace was set the fileformat plugin will use it when exporting unless outputColorSpace is specified.
Order or precendence on export (Note: the plugin assumes usd data is linear)
1. If outputColorSpace=linear, the usd color data is exported as is.
2. If outputColorSpace=sRGB, the usd color data is converted to sRGB on export
3. If outputColorSpace is not set and fbxOriginalColorSpace is known, it will export the color data in the original format
4. If outputColorSpace is not set and fbxOriginalColorSpace is not known, it will export the color data as is.
Example:
```
UsdStageRefPtr stage = UsdStage::Open("cube.fbx:SDF_FORMAT_ARGS:fbxOriginalColorSpace=sRGB")
# round trip the asset using the original colorspace
stage.Export("round_trip_original_cube_srgb.fbx") // exported file will have sRGB colorspace
# round trip the asset overriding the original colorspace
stage.Export("round_trip_original_cube_linear.fbx:SDF_FORMAT_ARGS:outputColorSpace=linear") // exported file will have linear colorspace
```
## Debug codes
* `FILE_FORMAT_FBX`: Common debug messages.
Expand Down
3 changes: 2 additions & 1 deletion fbx/src/fbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ namespace adobe::usd {

struct ExportFbxOptions
{
bool embedImages;
bool embedImages = false;
std::string exportParentPath;
PXR_NS::TfToken outputColorSpace;
};

struct Fbx
Expand Down
121 changes: 33 additions & 88 deletions fbx/src/fbxExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ namespace adobe::usd {

struct ExportFbxContext
{
UsdData* usd;
Fbx* fbx;
UsdData* usd = nullptr;
Fbx* fbx = nullptr;
std::vector<FbxSurfaceMaterial*> materials;
std::vector<FbxMesh*> meshes;
std::vector<FbxCamera*> cameras;
std::vector<FbxNode*> skeletons;
std::string exportParentPath;
bool hasYUp;
bool hasYUp = true;
bool convertColorSpaceToSRGB = false;
};

bool
Expand Down Expand Up @@ -156,7 +157,7 @@ exportFbxTransform(ExportFbxContext& ctx, const Node& node, FbxNode* fbxNode)
void
setElementUVs(FbxMesh* fbxMesh,
FbxGeometryElementUV* elementUvs,
const Primvar<PXR_NS::GfVec2f>& uvs)
const Primvar<GfVec2f>& uvs)
{
FbxGeometryElement::EMappingMode uvMapping;
if (!exportFbxMapping(uvs.interpolation, uvMapping)) {
Expand Down Expand Up @@ -235,17 +236,17 @@ exportFbxMeshes(ExportFbxContext& ctx)

// Positions
size_t k = 0;
for (size_t i = 0; i < m.faces.size(); i++) {
for (size_t j = 0; j < m.faces.size(); j++) {
fbxMesh->BeginPolygon();
for (int j = 0; j < m.faces[i]; j++) {
for (int l = 0; l < m.faces[j]; l++) {
fbxMesh->AddPolygon(m.indices[k++]);
}
fbxMesh->EndPolygon();
}
fbxMesh->InitControlPoints(m.points.size());
for (size_t i = 0; i < m.points.size(); i++) {
GfVec3f p = m.points[i];
fbxMesh->SetControlPointAt(FbxVector4(p[0], p[1], p[2]), i);
for (size_t j = 0; j < m.points.size(); j++) {
GfVec3f p = m.points[j];
fbxMesh->SetControlPointAt(FbxVector4(p[0], p[1], p[2]), j);
}

// Normals
Expand All @@ -258,15 +259,15 @@ exportFbxMeshes(ExportFbxContext& ctx)

FbxGeometryElementNormal* elementNormal = fbxMesh->CreateElementNormal();
elementNormal->SetMappingMode(normalMapping);
for (size_t i = 0; i < m.normals.values.size(); i++) {
GfVec3f n = m.normals.values[i];
for (size_t j = 0; j < m.normals.values.size(); j++) {
GfVec3f n = m.normals.values[j];
FbxVector4 normal = FbxVector4(n[0], n[1], n[2]);
elementNormal->GetDirectArray().Add(normal);
}
if (m.normals.indices.size()) {
elementNormal->SetReferenceMode(FbxGeometryElement::EReferenceMode::eIndexToDirect);
for (size_t i = 0; i < m.normals.indices.size(); i++) {
elementNormal->GetIndexArray().Add(m.normals.indices[i]);
for (size_t j = 0; j < m.normals.indices.size(); j++) {
elementNormal->GetIndexArray().Add(m.normals.indices[j]);
}
} else {
elementNormal->SetReferenceMode(FbxGeometryElement::EReferenceMode::eDirect);
Expand All @@ -289,6 +290,7 @@ exportFbxMeshes(ExportFbxContext& ctx)
}
}

// Colors and Opacities
if (m.colors.size() || m.opacities.size()) {
TfToken interpolation;
VtIntArray indices;
Expand Down Expand Up @@ -323,91 +325,33 @@ exportFbxMeshes(ExportFbxContext& ctx)
interpolation.GetText());
}

// TODO: Maybe it's necessary to adjust data if indices differ
// Convert colors to sRGB if needed
if (ctx.convertColorSpaceToSRGB) {
for (size_t j = 0; j < colorValues.size(); j++) {
colorValues[j][0] = linearToSRGB(colorValues[j][0]);
colorValues[j][1] = linearToSRGB(colorValues[j][1]);
colorValues[j][2] = linearToSRGB(colorValues[j][2]);
}
}

FbxGeometryElementVertexColor* vertexColor = fbxMesh->CreateElementVertexColor();
vertexColor->SetMappingMode(colorMapping);
if (indices.size()) {
vertexColor->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
vertexColor->GetIndexArray().SetCount(indices.size());
for (size_t i = 0; i < indices.size(); i++) {
vertexColor->GetIndexArray().SetAt(i, indices[i]);
for (size_t j = 0; j < indices.size(); j++) {
vertexColor->GetIndexArray().SetAt(j, indices[j]);
}
} else {
vertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
}
vertexColor->GetDirectArray().SetCount(colorValues.size());
for (size_t i = 0; i < colorValues.size(); i++) {
GfVec3f c = colorValues[i];
FbxDouble4 vector = FbxDouble4(c[0], c[1], c[2], opacityValues[i]);
vertexColor->GetDirectArray().SetAt(i, vector);
for (size_t j = 0; j < colorValues.size(); j++) {
GfVec3f c = colorValues[j];
FbxDouble4 vector = FbxDouble4(c[0], c[1], c[2], opacityValues[j]);
vertexColor->GetDirectArray().SetAt(j, vector);
}
}

// Crease
// TfToken interpolateBoundary;
// if (meshSchema.GetInterpolateBoundaryAttr().Get(&interpolateBoundary, timeCode))
// {
// if (UsdGeomTokens->edgeOnly == interpolateBoundary)
// fbxMesh->SetBoundaryRule(FbxMesh::EBoundaryRule::eCreaseEdge);
// else if (UsdGeomTokens->edgeAndCorner == interpolateBoundary)
// fbxMesh->SetBoundaryRule(FbxMesh::EBoundaryRule::eCreaseAll);
// }

// VtArray<int> creaseIndices;
// VtArray<float> creaseSharpnesses;
// VtArray<int> creaseLengths;

// if (meshSchema.GetCreaseIndicesAttr().Get(&creaseIndices, timeCode) &&
// meshSchema.GetCreaseSharpnessesAttr().Get(&creaseSharpnesses, timeCode) &&
// meshSchema.GetCreaseLengthsAttr().Get(&creaseLengths, timeCode))
// {
// bool onValuePerEdge = creaseSharpnesses.size() == creaseLengths.size();
// size_t loopIndex = 0;

// if (onValuePerEdge)
// {
// for (size_t i = 0; i < creaseLengths.size(); i++)
// {
// int edgetVertCount = creaseLengths[i];
// float sharpness = creaseSharpnesses[i];

// for (int j = 0; j < edgetVertCount; j++)
// {
// int creaseIndex = creaseIndices[loopIndex];
// fbxMesh->SetVertexCreaseInfo(creaseIndex, sharpness);
// loopIndex++;
// }
// }
// }
// else
// {
// for (size_t i = 0; i < creaseLengths.size(); i++)
// {
// int edgetVertCount = creaseLengths[i];

// for (int j = 0; j < edgetVertCount; j++)
// {
// int creaseIndex = creaseIndices[loopIndex];
// float sharpness = creaseSharpnesses[loopIndex];
// fbxMesh->SetVertexCreaseInfo(creaseIndex, sharpness);
// loopIndex++;
// }
// }
// }
// }

// Smoothing
// TODO: Add smoothing information to FBX.
// VtArray<int> cornderSharpnessIndexes;
// VtArray<float> cornerSharpnes;

// if (!geomMesh.GetCornerIndicesAttr().Get(&cornderSharpnessIndexes, timeCode) ||
// !geomMesh.GetCornerSharpnessesAttr().Get(&cornerSharpnes, timeCode))
// return;

// auto pSmoothingGroup = fbxMesh->CreateElementSmoothing();
// pSmoothingGroup->SetMappingMode(FbxLayerElement::EMappingMode::eByControlPoint);
// pSmoothingGroup->SetReferenceMode(FbxLayerElement::EReferenceMode::eIndexToDirect);
}
return true;
}
Expand Down Expand Up @@ -626,7 +570,7 @@ exportSkeletons(ExportFbxContext& ctx)
skeletonNodesMap[joint] = fbxNode;
fbxNodes[j] = fbxNode;
// auto nodePath = prim.GetName().GetString() + jointPath;
// context.AddNodePath(PXR_NS::SdfPath(nodePath), currentNode);
// context.AddNodePath(SdfPath(nodePath), currentNode);

FbxSkeleton* fbxSkeleton = FbxSkeleton::Create(ctx.fbx->scene, "");
fbxNode->AddNodeAttribute(fbxSkeleton);
Expand All @@ -637,7 +581,7 @@ exportSkeletons(ExportFbxContext& ctx)
fbxSkeleton->SetSkeletonType(fbxsdk::FbxSkeleton::eLimbNode);
}

PXR_NS::GfMatrix4d restTransform = skeleton.restTransforms[j];
GfMatrix4d restTransform = skeleton.restTransforms[j];
FbxAMatrix fbxMatrix = GetFBXMatrixFromUSD(restTransform);
fbxNode->LclRotation = fbxMatrix.GetR();
fbxNode->LclTranslation = fbxMatrix.GetT();
Expand Down Expand Up @@ -867,6 +811,7 @@ exportFbx(const ExportFbxOptions& options, UsdData& usd, Fbx& fbx)
ctx.usd = &usd;
ctx.fbx = &fbx;
ctx.exportParentPath = options.exportParentPath;
ctx.convertColorSpaceToSRGB = shouldConvertToSRGB(usd, options.outputColorSpace);
exportFbxSettings(ctx);
exportFbxMaterials(ctx);
exportFbxCameras(ctx);
Expand Down
Loading

0 comments on commit 154937f

Please sign in to comment.