Skip to content

Commit

Permalink
Merge pull request #1970 from zenustech/improve-fbx
Browse files Browse the repository at this point in the history
improve-fbx
  • Loading branch information
littlemine authored Aug 2, 2024
2 parents 76578d5 + b6d8b70 commit f6665c6
Showing 1 changed file with 65 additions and 127 deletions.
192 changes: 65 additions & 127 deletions projects/FBX/FBXSDK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,132 +396,6 @@ void getAttr(T* arr, std::string name, std::shared_ptr<PrimitiveObject> prim) {
}
}

bool GetMesh(FbxNode* pNode, std::shared_ptr<PrimitiveObject> prim, std::string name) {
FbxMesh* pMesh = pNode->GetMesh();
if (!pMesh) return false;
std::string nodeName = pNode->GetName();
if (name.size() > 0 && nodeName != name) {
return false;
}
prim->userData().set2("RootName", nodeName);

FbxAMatrix bindMatrix = pNode->EvaluateGlobalTransform();
auto s = bindMatrix.GetS();
auto t = bindMatrix.GetT();
// zeno::log_info("s {} {} {}", s[0], s[1], s[2]);
// zeno::log_info("t {} {} {}", t[0], t[1], t[2]);

int numVertices = pMesh->GetControlPointsCount();
FbxVector4* vertices = pMesh->GetControlPoints();
prim->verts.resize(numVertices);

for (int i = 0; i < numVertices; ++i) {
auto pos = bindMatrix.MultT( FbxVector4(vertices[i][0], vertices[i][1], vertices[i][2], 1.0));
prim->verts[i] = vec3f(pos[0], pos[1], pos[2]);
}
int numPolygons = pMesh->GetPolygonCount();
prim->polys.resize(numPolygons);
std::vector<int> loops;
loops.reserve(numPolygons * 4);
int count = 0;
for (int i = 0; i < numPolygons; ++i) {
int numVertices = pMesh->GetPolygonSize(i);
for (int j = 0; j < numVertices; ++j) {
int vertexIndex = pMesh->GetPolygonVertex(i, j);
loops.push_back(vertexIndex);
}
prim->polys[i] = {count, numVertices};
count += numVertices;
}
loops.shrink_to_fit();
prim->loops.values = loops;
// zeno::log_info("pMesh->GetDeformerCount(FbxDeformer::eSkin) {}", pMesh->GetDeformerCount(FbxDeformer::eSkin));
auto &ud = prim->userData();
if (pMesh->GetDeformerCount(FbxDeformer::eSkin)) {
auto &bi = prim->verts.add_attr<vec4i>("boneName");
std::fill(bi.begin(), bi.end(), vec4i(-1, -1, -1, -1));
auto &bw = prim->verts.add_attr<vec4f>("boneWeight");
std::fill(bw.begin(), bw.end(), vec4f(-1.0, -1.0, -1.0, -1.0));

FbxSkin* pSkin = (FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin);
std::vector<std::string> bone_names;

// Iterate over each cluster (bone)
for (int j = 0; j < pSkin->GetClusterCount(); ++j) {
FbxCluster* pCluster = pSkin->GetCluster(j);

// Get the link node (bone)
FbxNode* pBoneNode = pCluster->GetLink();
if (!pBoneNode) continue;

// Get the bone weights
int numIndices = pCluster->GetControlPointIndicesCount();
int* indices = pCluster->GetControlPointIndices();
double* weights = pCluster->GetControlPointWeights();

bone_names.emplace_back(pBoneNode->GetName());
for (int k = 0; k < numIndices; ++k) {
for (auto l = 0; l < 4; l++) {
if (bi[indices[k]][l] == -1) {
bi[indices[k]][l] = j;
bw[indices[k]][l] = weights[k];
break;
}
}
}
}
ud.set2("boneName_count", int(bone_names.size()));
for (auto i = 0; i < bone_names.size(); i++) {
ud.set2(zeno::format("boneName_{}", i), bone_names[i]);
}
}
if (pMesh->GetElementUVCount() > 0) {
auto* arr = pMesh->GetElementUV(0);
std::string name = "uv";
if (arr->GetMappingMode() == FbxLayerElement::EMappingMode::eByControlPoint) {
zeno::log_info("{}, eByControlPoint", name);
auto &attr = prim->verts.add_attr<vec3f>(name);
for (auto i = 0; i < prim->verts.size(); i++) {
int pIndex = i;
if (arr->GetReferenceMode() == FbxLayerElement::EReferenceMode::eIndexToDirect) {
pIndex = arr->GetIndexArray().GetAt(i);
}
auto x = arr->GetDirectArray().GetAt(pIndex)[0];
auto y = arr->GetDirectArray().GetAt(pIndex)[1];
attr[i] = vec3f(x, y, 0);
}
}
else if (arr->GetMappingMode() == FbxLayerElement::EMappingMode::eByPolygonVertex) {
zeno::log_info("{}, eByPolygonVertex", name);
if (arr->GetReferenceMode() == FbxLayerElement::EReferenceMode::eDirect) {
auto &uvs = prim->loops.add_attr<int>("uvs");
std::iota(uvs.begin(), uvs.end(), 0);
prim->uvs.resize(prim->loops.size());
}
else if (arr->GetReferenceMode() == FbxLayerElement::EReferenceMode::eIndexToDirect) {
auto &uvs = prim->loops.add_attr<int>("uvs");
for (auto i = 0; i < prim->loops.size(); i++) {
uvs[i] = arr->GetIndexArray().GetAt(i);
}
int count = arr->GetDirectArray().GetCount();
prim->uvs.resize(count);
}
for (auto i = 0; i < prim->uvs.size(); i++) {
auto x = arr->GetDirectArray().GetAt(i)[0];
auto y = arr->GetDirectArray().GetAt(i)[1];
prim->uvs[i] = vec2f(x, y);
}
}
}
if (pMesh->GetElementNormalCount() > 0) {
getAttr(pMesh->GetElementNormal(0), "nrm", prim);
}
if (pMesh->GetElementTangentCount() > 0) {
getAttr(pMesh->GetElementTangent(0), "tang", prim);
}
return true;
}

std::shared_ptr<PrimitiveObject> GetMesh(FbxNode* pNode) {
FbxMesh* pMesh = pNode->GetMesh();
if (!pMesh) return nullptr;
Expand Down Expand Up @@ -744,7 +618,12 @@ struct NewFBXImportSkin : INode {
else {
for(int i = 0; i < lRootNode->GetChildCount(); i++) {
auto pNode = lRootNode->GetChild(i);
if (GetMesh(pNode, prim, rootName)) {
std::string nodeName = pNode->GetName();
if (nodeName == rootName) {
auto sub_prim = GetMesh(pNode);
if (sub_prim) {
prim = sub_prim;
}
break;
}
}
Expand All @@ -755,6 +634,20 @@ struct NewFBXImportSkin : INode {
v = v * 0.01;
}
}
if (get_input2<bool>("CopyVectorsFromLoopsToVert")) {
auto vectors_str = get_input2<std::string>("vectors");
std::vector<std::string> vectors = zeno::split_str(vectors_str, ',');
for (auto vector: vectors) {
vector = zeno::trim_string(vector);
if (vector.size() && prim->loops.attr_is<vec3f>(vector)) {
auto &nrm = prim->loops.attr<vec3f>(vector);
auto &vnrm = prim->verts.add_attr<vec3f>(vector);
for (auto i = 0; i < prim->loops.size(); i++) {
vnrm[prim->loops[i]] = nrm[i];
}
}
}
}
{
auto &ud = prim->userData();
ud.set2("version", vec3i(major, minor, revision));
Expand All @@ -774,6 +667,8 @@ ZENDEFNODE(NewFBXImportSkin, {
{"readpath", "path"},
{"string", "rootName", ""},
{"bool", "ConvertUnits", "1"},
{"string", "vectors", "nrm,"},
{"bool", "CopyVectorsFromLoopsToVert", "1"},
},
{
"prim",
Expand Down Expand Up @@ -1383,6 +1278,48 @@ struct NewFBXBoneDeform : INode {
nrms[i] = zeno::normalize(nrm );
}
}
auto vectors_str = get_input2<std::string>("vectors");
std::vector<std::string> vectors = zeno::split_str(vectors_str, ',');
for (auto vector: vectors) {
vector = zeno::trim_string(vector);
if (vector.size()) {
if (prim->verts.attr_is<vec3f>(vector)) {
auto &nrms = prim->verts.attr<vec3f>(vector);
for (auto i = 0; i < vert_count; i++) {
glm::mat4 matrix(0);
float w = 0;
for (auto j = 0; j < 4; j++) {
if (bi[i][j] < 0) {
continue;
}
matrix += matrixs[bi[i][j]] * bw[i][j];
w += bw[i][j];
}
matrix = matrix / w;
auto nrm = transform_nrm(matrix, nrms[i]);
nrms[i] = zeno::normalize(nrm);
}
}
if (prim->loops.attr_is<vec3f>(vector)) {
auto &nrms = prim->loops.attr<vec3f>(vector);
for (auto i = 0; i < prim->loops.size(); i++) {
auto vi = prim->loops[i];
glm::mat4 matrix(0);
float w = 0;
for (auto j = 0; j < 4; j++) {
if (bi[vi][j] < 0) {
continue;
}
matrix += matrixs[bi[vi][j]] * bw[vi][j];
w += bw[vi][j];
}
matrix = matrix / w;
auto nrm = transform_nrm(matrix, nrms[i]);
nrms[i] = zeno::normalize(nrm);
}
}
}
}

set_output("prim", prim);
}
Expand All @@ -1393,6 +1330,7 @@ ZENDEFNODE(NewFBXBoneDeform, {
"GeometryToDeform",
"RestPointTransforms",
"DeformPointTransforms",
{"string", "vectors", "nrm,"},
},
{
"prim",
Expand Down

0 comments on commit f6665c6

Please sign in to comment.