// 三角形化 void CFBXLoader::TriangulateRecursive(FbxNode* pNode) { FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh || lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs || lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbsSurface || lNodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch) { FbxGeometryConverter lConverter(pNode->GetFbxManager()); // これでどんな形状も三角形化 #if 0 lConverter.TriangulateInPlace(pNode); // 古い手法 #endif // 0 lConverter.Triangulate( mScene, true ); } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { // 子ノードを探索 TriangulateRecursive(pNode->GetChild(lChildIndex)); } }
void FBXTriangulateRecursive( FbxNode* pNode ) { FbxNodeAttribute* pNodeAttr = pNode->GetNodeAttribute(); if( pNodeAttr ) { if( pNodeAttr->GetAttributeType() == FbxNodeAttribute::eMesh || pNodeAttr->GetAttributeType() == FbxNodeAttribute::eNurbs || pNodeAttr->GetAttributeType() == FbxNodeAttribute::eNurbsSurface || pNodeAttr->GetAttributeType() == FbxNodeAttribute::ePatch ) { FbxGeometryConverter lConverter( pNode->GetFbxManager() ); lConverter.TriangulateInPlace( pNode ); } } const int nChildCount = pNode->GetChildCount(); for( int i = 0; i < nChildCount; i++ ) { FBXTriangulateRecursive( pNode->GetChild( i ) ); } }
// Triangulate all NURBS, patch and mesh under this node recursively. void TriangulateRecursive(FbxNode* pNode) { FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { FbxNodeAttribute::EType eAttrType = lNodeAttribute->GetAttributeType(); if (eAttrType == FbxNodeAttribute::eMesh || eAttrType == FbxNodeAttribute::eNurbs || eAttrType == FbxNodeAttribute::eNurbsSurface || eAttrType == FbxNodeAttribute::ePatch) { FbxGeometryConverter lConverter(pNode->GetFbxManager()); lConverter.TriangulateInPlace(pNode); } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { TriangulateRecursive(pNode->GetChild(lChildIndex)); } }
osgDB::ReaderWriter::ReadResult OsgFbxReader::readFbxNode( FbxNode* pNode, bool& bIsBone, int& nLightCount) { if (FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute()) { FbxNodeAttribute::EType attrType = lNodeAttribute->GetAttributeType(); switch (attrType) { case FbxNodeAttribute::eNurbs: case FbxNodeAttribute::ePatch: case FbxNodeAttribute::eNurbsCurve: case FbxNodeAttribute::eNurbsSurface: { FbxGeometryConverter lConverter(&pSdkManager); #if FBXSDK_VERSION_MAJOR < 2014 if (!lConverter.TriangulateInPlace(pNode)) #else if (!lConverter.Triangulate(lNodeAttribute,true,false)) #endif { OSG_WARN << "Unable to triangulate FBX NURBS " << pNode->GetName() << std::endl; } } break; default: break; } } bIsBone = false; bool bCreateSkeleton = false; FbxNodeAttribute::EType lAttributeType = FbxNodeAttribute::eUnknown; if (pNode->GetNodeAttribute()) { lAttributeType = pNode->GetNodeAttribute()->GetAttributeType(); if (lAttributeType == FbxNodeAttribute::eSkeleton) { bIsBone = true; } } if (!bIsBone && fbxSkeletons.find(pNode) != fbxSkeletons.end()) { bIsBone = true; } unsigned nMaterials = pNode->GetMaterialCount(); std::vector<StateSetContent > stateSetList; for (unsigned i = 0; i < nMaterials; ++i) { FbxSurfaceMaterial* fbxMaterial = pNode->GetMaterial(i); assert(fbxMaterial); stateSetList.push_back(fbxMaterialToOsgStateSet.convert(fbxMaterial)); } osg::NodeList skeletal, children; int nChildCount = pNode->GetChildCount(); for (int i = 0; i < nChildCount; ++i) { FbxNode* pChildNode = pNode->GetChild(i); if (pChildNode->GetParent() != pNode) { //workaround for bug that occurs in some files exported from Blender continue; } bool bChildIsBone = false; osgDB::ReaderWriter::ReadResult childResult = readFbxNode( pChildNode, bChildIsBone, nLightCount); if (childResult.error()) { return childResult; } else if (osg::Node* osgChild = childResult.getNode()) { if (bChildIsBone) { if (!bIsBone) bCreateSkeleton = true; skeletal.push_back(osgChild); } else { children.push_back(osgChild); } } } std::string animName = readFbxAnimation(pNode, pNode->GetName()); osg::Matrix localMatrix; makeLocalMatrix(pNode, localMatrix); bool bLocalMatrixIdentity = localMatrix.isIdentity(); osg::ref_ptr<osg::Group> osgGroup; bool bEmpty = children.empty() && !bIsBone; switch (lAttributeType) { case FbxNodeAttribute::eMesh: { size_t bindMatrixCount = boneBindMatrices.size(); osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pNode, stateSetList); if (meshRes.error()) { return meshRes; } else if (osg::Node* node = meshRes.getNode()) { bEmpty = false; if (bindMatrixCount != boneBindMatrices.size()) { //The mesh is skinned therefore the bind matrix will handle all transformations. localMatrix.makeIdentity(); bLocalMatrixIdentity = true; } if (animName.empty() && children.empty() && skeletal.empty() && bLocalMatrixIdentity) { return osgDB::ReaderWriter::ReadResult(node); } children.insert(children.begin(), node); } } break; case FbxNodeAttribute::eCamera: case FbxNodeAttribute::eLight: { osgDB::ReaderWriter::ReadResult res = lAttributeType == FbxNodeAttribute::eCamera ? readFbxCamera(pNode) : readFbxLight(pNode, nLightCount); if (res.error()) { return res; } else if (osg::Group* resGroup = dynamic_cast<osg::Group*>(res.getObject())) { bEmpty = false; if (animName.empty() && bLocalMatrixIdentity) { osgGroup = resGroup; } else { children.insert(children.begin(), resGroup); } } } break; default: break; } if (bEmpty) { osgDB::ReaderWriter::ReadResult(0); } if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bIsBone, nodeMap, fbxScene); osg::Group* pAddChildrenTo = osgGroup.get(); if (bCreateSkeleton) { osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, fbxSkeletons, skeletonMap); osgSkeleton->setDefaultUpdateCallback(); pAddChildrenTo->addChild(osgSkeleton); pAddChildrenTo = osgSkeleton; } for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it) { pAddChildrenTo->addChild(it->get()); } for (osg::NodeList::iterator it = children.begin(); it != children.end(); ++it) { pAddChildrenTo->addChild(it->get()); } return osgDB::ReaderWriter::ReadResult(osgGroup.get()); }