JNIEXPORT jfloatArray JNICALL Java_de_tesis_dynaware_javafx_graphics_importers_fbx_JFbxLib_getMeshVertices(JNIEnv *env, jobject obj, jint attributeIndex) { // Check FBX file has been opened. if (!isOpen()) { throwFileClosedException(env); } // Check attribute index bounds for safety. if (!checkAttributeBounds(attributeIndex)) { throwArrayOutOfBoundsException(env); } // Check attribute type for safety. if (!isValidType(attributeIndex, FbxNodeAttribute::EType::eMesh)) { return NULL; } FbxMesh* mesh = (FbxMesh*)currentNode->GetNodeAttributeByIndex(attributeIndex); FbxVector4 *controlPoints = mesh->GetControlPoints(); const int controlPointsCount = mesh->GetControlPointsCount(); jfloatArray vertices = env->NewFloatArray(3*controlPointsCount); // Check memory could be allocated. if (vertices == NULL) { throwOutOfMemoryError(env); } for (int i=0; i<controlPointsCount; i++) { jfloat vertex[3]; vertex[0] = controlPoints[i][0]; vertex[1] = controlPoints[i][1]; vertex[2] = controlPoints[i][2]; env->SetFloatArrayRegion(vertices, 3*i, 3, vertex); } return vertices; }
void FBXImporter::ReadUVs(FBXMeshData* fbxMeshData, int controlPointIndex, int index, int textureUVIndex, int uvLayer) { FbxMesh* mesh = fbxMeshData->mMesh; vector<XMFLOAT2>& uvs = fbxMeshData->mUVs; if (uvLayer >= 2 || mesh->GetElementUVCount() <= uvLayer) { return; } FbxGeometryElementUV* vertexUV = mesh->GetElementUV(0); switch (vertexUV->GetMappingMode()) { case FbxGeometryElement::eByControlPoint: switch (vertexUV->GetReferenceMode()) { case FbxGeometryElement::eDirect: { XMFLOAT2 uv; FbxVector2 fbxUV = vertexUV->GetDirectArray().GetAt(controlPointIndex); uv.x = static_cast<float>(fbxUV[0]); uv.y = static_cast<float>(fbxUV[1]); uvs.push_back(uv); } break; case FbxGeometryElement::eIndexToDirect: { int id = vertexUV->GetIndexArray().GetAt(controlPointIndex); FbxVector2 fbxUV = vertexUV->GetDirectArray().GetAt(id); XMFLOAT2 uv; uv.x = static_cast<float>(fbxUV[0]); uv.y = static_cast<float>(fbxUV[1]); uvs.push_back(uv); } break; default: break; } case FbxGeometryElement::eByPolygonVertex: switch (vertexUV->GetReferenceMode()) { case FbxGeometryElement::eDirect: case FbxGeometryElement::eIndexToDirect: #if USE_RIGHT_HAND uvs[index].x = static_cast<float>(vertexUV->GetDirectArray().GetAt(textureUVIndex)[0]); #else uvs[index].x = 1.0f - static_cast<float>(vertexUV->GetDirectArray().GetAt(textureUVIndex)[0]); #endif uvs[index].y = 1.0f - static_cast<float>(vertexUV->GetDirectArray().GetAt(textureUVIndex)[1]); break; default: break; } break; } }
FbxMesh* GenerateLOD::CreateNewMesh(FbxVector4 *pControlPoints, FbxMesh *pMesh, FbxScene *pScene) { // ********************************************************************************* // // Following is Create new Mesh FbxMesh *newMesh = FbxMesh::Create(pScene, "newMesh"); newMesh->InitControlPoints((*ControlP).size()); int count = 0; std::unordered_map<int, int> RemainPoints; for (std::unordered_map<int, Point>::iterator it = (*ControlP).begin(); it != (*ControlP).end(); ++it) { newMesh->SetControlPointAt(pControlPoints[it->first], count); RemainPoints[it->first] = count; ++count; } FbxGeometryElementUV *newElementUV = newMesh->CreateElementUV("DiffuseUV"); if (!newElementUV) { MessageBox(NULL, "CreateElementUV Error!", "�ב�¾", 0); //exit(0); } newElementUV->SetMappingMode(FbxLayerElement::eByPolygonVertex); newElementUV->SetReferenceMode(FbxLayerElement::eIndexToDirect); //# copy oldElementUV.DirectArray() into newElementUV.DirectArray() FbxGeometryElementUV *oldElementUV = pMesh->GetElementUV(0); int length = oldElementUV->GetDirectArray().GetCount(); for (int i = 0; i < length; ++i) newElementUV->GetDirectArray().Add(oldElementUV->GetDirectArray()[i]); //# Now we have set the UVs as eIndexToDirect reference and //# in eByPolygonVertex mapping mode, we must Set the size of the index array. int PolygonCount = (*Triangles).size(); newElementUV->GetIndexArray().SetCount(3 * PolygonCount); //# Add new triangles to pMesh int newPolygonIndex = 0; for (std::unordered_map<int, Face>::iterator it = (*Triangles).begin(); it != (*Triangles).end(); ++it) { newMesh->BeginPolygon(-1, -1, -1, false); newMesh->AddPolygon(RemainPoints[it->second.points[0]], it->second.uvs[0]); newElementUV->GetIndexArray().SetAt(newPolygonIndex * 3 + 0, it->second.uvs[0]); newMesh->AddPolygon(RemainPoints[it->second.points[1]], it->second.uvs[1]); newElementUV->GetIndexArray().SetAt(newPolygonIndex * 3 + 1, it->second.uvs[1]); newMesh->AddPolygon(RemainPoints[it->second.points[2]], it->second.uvs[2]); newElementUV->GetIndexArray().SetAt(newPolygonIndex * 3 + 2, it->second.uvs[2]); newMesh->EndPolygon(); newPolygonIndex += 1; } //# Automatically generate edge data for the mesh. newMesh->BuildMeshEdgeArray(); return newMesh; }
// Bake node attributes and materials under this node recursively. // Currently only mesh, light and material. void LoadCacheRecursive(SceneContext* pSceneCtx, FbxNode * pNode, FbxAnimLayer * pAnimLayer, bool pSupportVBO) { // Bake material and hook as user data. const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && !lMaterial->GetUserDataPtr()) { FbxAutoPtr<MaterialCache> lMaterialCache(new MaterialCache); if (lMaterialCache->Initialize(lMaterial)) { lMaterial->SetUserDataPtr(lMaterialCache.Release()); } } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Bake mesh as VBO(vertex buffer object) into GPU. if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (pSupportVBO && lMesh && !lMesh->GetUserDataPtr()) { FbxAutoPtr<VBOMesh> lMeshCache(new VBOMesh); if (lMeshCache->Initialize(pSceneCtx, lMesh)) { lMesh->SetUserDataPtr(lMeshCache.Release()); } } } // Bake light properties. else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && !lLight->GetUserDataPtr()) { FbxAutoPtr<LightCache> lLightCache(new LightCache); if (lLightCache->Initialize(lLight, pAnimLayer)) { lLight->SetUserDataPtr(lLightCache.Release()); } } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { LoadCacheRecursive(pSceneCtx, pNode->GetChild(lChildIndex), pAnimLayer, pSupportVBO); } }
void FBXImporter::ProcessMesh(FbxNodeAttribute* nodeAttribute) { FbxMesh* mesh = (FbxMesh*)nodeAttribute; // 网格是否三角化的?如果不是先将其转为三角化的。 // 注意:一步其实应该在建模软件导出的时候进行。 if (!mesh->IsTriangleMesh()) { FbxGeometryConverter converter(mSDKManager); // #1 // For FBX SDK 2015.1 nodeAttribute = converter.Triangulate(nodeAttribute, true, false); // For FBX SDK 2013.3 //converter.TriangulateInPlace(nodeAttribute->GetNode()); mesh = (FbxMesh*)nodeAttribute; } FBXMeshData* fbxMeshData = new FBXMeshData(); fbxMeshData->mMesh = mesh; mFBXMeshDatas.push_back(fbxMeshData); Log("TriangleCount:%d\n", mesh->GetPolygonCount()); Log("VertexCount:%d\n", mesh->GetControlPointsCount()); Log("IndexCount:%d\n", mesh->GetPolygonVertexCount()); Log("Layer:%d\n", mesh->GetLayerCount()); Log("DeformerCount:%d\n", mesh->GetDeformerCount()); Log("MaterialCount%d\n", mesh->GetNode()->GetMaterialCount()); Log("\n"); }
void CFBXLoader::SetupNode(FbxNode* pNode, std::string parentName) { if(!pNode) return ; FBX_MESH_NODE meshNode; meshNode.name = pNode->GetName(); meshNode.parentName = parentName; ZeroMemory( &meshNode.elements, sizeof(MESH_ELEMENTS) ); FbxMesh* lMesh = pNode->GetMesh(); if(lMesh) { const int lVertexCount = lMesh->GetControlPointsCount(); if (lVertexCount>0) { // 頂点があるならノードにコピー CopyVertexData(lMesh, &meshNode); } } // マテリアル const int lMaterialCount = pNode->GetMaterialCount(); for(int i=0;i<lMaterialCount;i++) { FbxSurfaceMaterial* mat = pNode->GetMaterial(i); if(!mat) continue; FBX_MATERIAL_NODE destMat; CopyMatrialData(mat, &destMat); meshNode.m_materialArray.push_back(destMat); } // ComputeNodeMatrix(pNode, &meshNode); m_meshNodeArray.push_back(meshNode); const int lCount = pNode->GetChildCount(); for (int i = 0; i < lCount; i++) { SetupNode(pNode->GetChild(i), meshNode.name); } }
void fbxLoader2::computeMesh(FbxNode* pNode, FbxTime& pTime, FbxAnimLayer* pAnimLayer, FbxAMatrix& pGlobalPosition, FbxPose* pPose, int frame) { FbxMesh* lMesh = pNode->GetMesh(); const int lVertexCount = lMesh->GetControlPointsCount(); // No vertex to draw. if (lVertexCount == 0) { return; } // If it has some defomer connection, update the vertices position const bool lHasVertexCache = lMesh->GetDeformerCount(FbxDeformer::eVertexCache) && (static_cast<FbxVertexCacheDeformer*>(lMesh->GetDeformer(0, FbxDeformer::eVertexCache)))->IsActive(); const bool lHasShape = lMesh->GetShapeCount() > 0; const bool lHasSkin = lMesh->GetDeformerCount(FbxDeformer::eSkin) > 0; const bool lHasDeformation = lHasVertexCache || lHasShape || lHasSkin; if (lHasDeformation) { //we need to get the number of clusters const int lSkinCount = lMesh->GetDeformerCount(FbxDeformer::eSkin); int lClusterCount = 0; for (int lSkinIndex = 0; lSkinIndex < lSkinCount; ++lSkinIndex) { lClusterCount += ((FbxSkin *)(lMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin)))->GetClusterCount(); } if (lClusterCount) { // Deform the vertex array with the skin deformer. ComputeSkinDeformation(pGlobalPosition, lMesh, pTime, pPose, frame); } } }
void FbxLoader::ProcessControlPoints(FbxNode* node, Node& meshNode) { FbxMesh* currMesh = node->GetMesh(); if(!currMesh) return; const int ctrlPointCount = currMesh->GetControlPointsCount(); meshNode.controlPoints.resize(ctrlPointCount); for(int i = 0; i < ctrlPointCount; i++) { FbxVector4 p = currMesh->GetControlPointAt(i); auto& cp = meshNode.controlPoints[i]; cp.position = { (float)p[0], (float)p[1], (float)p[2] }; } }
void LoadMeshes(FbxNode* pFbxNode, packed_freelist<Mesh>& sceneMeshes) { // Material const uint32_t materialCount = pFbxNode->GetMaterialCount(); for (uint32_t i = 0; i < materialCount; ++i) { FbxSurfaceMaterial* pFbxMaterial = pFbxNode->GetMaterial(i); if (pFbxMaterial && !pFbxMaterial->GetUserDataPtr()) { FbxAutoPtr<Material> pMaterial(new Material); if (pMaterial->init(pFbxMaterial)) { pFbxMaterial->SetUserDataPtr(pMaterial.Release()); } } } FbxNodeAttribute* nodeAttribute = pFbxNode->GetNodeAttribute(); if (nodeAttribute) { // Mesh if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* pFbxMesh = pFbxNode->GetMesh(); if (pFbxMesh && !pFbxMesh->GetUserDataPtr()) { Mesh mesh; if (mesh.init(pFbxMesh)) { sceneMeshes.insert(mesh); } // TODO: FbxAutoPtr<Mesh> pMesh(new Mesh); if (pMesh->init(pFbxMesh)) { pFbxMesh->SetUserDataPtr(pMesh.Release()); } } } // Light else if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight* pFbxLight = pFbxNode->GetLight(); if (pFbxLight && !pFbxLight->GetUserDataPtr()) { FbxAutoPtr<Light> pLight(new Light); if (pLight->init(pFbxLight)) { pFbxLight->SetUserDataPtr(pLight.Release()); } } } } const int childCount = pFbxNode->GetChildCount(); for (int i = 0; i < childCount; ++i) { LoadMeshes(pFbxNode->GetChild(i), sceneMeshes); } }
// Unload the cache and release the memory under this node recursively. void UnloadCacheRecursive(FbxNode * pNode) { // Unload the material cache const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && lMaterial->GetUserDataPtr()) { MaterialCache * lMaterialCache = static_cast<MaterialCache *>(lMaterial->GetUserDataPtr()); lMaterial->SetUserDataPtr(NULL); delete lMaterialCache; } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Unload the mesh cache if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (lMesh && lMesh->GetUserDataPtr()) { VBOMesh * lMeshCache = static_cast<VBOMesh *>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete lMeshCache; } } // Unload the light cache else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && lLight->GetUserDataPtr()) { LightCache * lLightCache = static_cast<LightCache *>(lLight->GetUserDataPtr()); lLight->SetUserDataPtr(NULL); delete lLightCache; } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { UnloadCacheRecursive(pNode->GetChild(lChildIndex)); } }
void fbxLoader2::setBindPoseCluster(FbxNode *node) { if( node->GetNodeAttribute()) { switch(node->GetNodeAttribute()->GetAttributeType()) { case FbxNodeAttribute::eMesh: FbxMesh *mesh = node->GetMesh(); for (int j = 0; j<mesh->GetDeformerCount(); j++) { FbxSkin *skin = (FbxSkin*) mesh->GetDeformer(j,FbxDeformer::eSkin); int clusters = skin->GetClusterCount(); for(int k = 0; k<clusters; k++) { FbxCluster* cluster = skin->GetCluster(k); FbxNode* boneLink = cluster->GetLink(); if(boneLink) { std::string nameLink = boneLink->GetName(); FbxAMatrix translationM; FbxAMatrix invert; cluster->GetTransformLinkMatrix(translationM); cluster->GetTransformMatrix(invert); translationM = translationM * invert.Inverse(); D3DXMATRIX mat = D3DXMATRIX((float)translationM.mData[0].mData[0], (float)translationM.mData[0].mData[1], (float)translationM.mData[0].mData[2], (float)translationM.mData[3].mData[0], (float)translationM.mData[1].mData[0], (float)translationM.mData[1].mData[1], (float)translationM.mData[1].mData[2], (float)translationM.mData[3].mData[1], (float)translationM.mData[2].mData[0], (float)translationM.mData[2].mData[1], (float)translationM.mData[2].mData[2], (float)translationM.mData[3].mData[2], 0,0,0,1); skeleton->GetBone(skeleton->GetBoneByName(nameLink))->SetTransformation(mat); } } } break; } } for (int i = 0; i<node->GetChildCount(); i++) { FbxNode* child = node->GetChild(i); setBindPoseCluster(child); } }
//=============================================================================================================================== void FBXLoader::AssociateMaterialToMesh(FbxNode* inNode) { FbxLayerElementArrayTemplate<int>* materialIndices; FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone; FbxMesh* mesh = inNode->GetMesh(); if (mesh->GetElementMaterial()) { materialIndices = &(mesh->GetElementMaterial()->GetIndexArray()); materialMappingMode = mesh->GetElementMaterial()->GetMappingMode(); FBXSubsets* subset = mSubsets[iCurrentSubset]; if (materialIndices) { switch (materialMappingMode) { case FbxGeometryElement::eByPolygon: { if (materialIndices->GetCount() == subset->mPolygonCount) { for (uint32 i = 0; i < subset->mPolygonCount; ++i) { uint32 materialIndex = materialIndices->GetAt(i); //subset->mTriangles[i].materialIndex = materialIndex; subset->mMaterialIndex = materialIndex; } } } break; case FbxGeometryElement::eAllSame: { uint32 materialIndex = materialIndices->GetAt(0); for (uint32 i = 0; i < subset->mPolygonCount; ++i) { //subset->mTriangles[i].materialIndex = materialIndex; subset->mMaterialIndex = materialIndex; } } break; default: throw std::exception("Invalid mapping mode for material\n"); } } } }
//=============================================================================================================================== void FBXLoader::LoadControlPoints(FbxNode* node) { FbxMesh* mesh = node->GetMesh(); uint32 controlPointCount = mesh->GetControlPointsCount(); for (uint32 i = 0; i < controlPointCount; ++i) { ZShadeSandboxMesh::PhysicalPoint* currCtrlPoint = new ZShadeSandboxMesh::PhysicalPoint(); XMFLOAT3 position; position.x = static_cast<float>(mesh->GetControlPointAt(i).mData[0]); position.y = static_cast<float>(mesh->GetControlPointAt(i).mData[1]); position.z = static_cast<float>(mesh->GetControlPointAt(i).mData[2]); currCtrlPoint->position = position; mControlPoints[i] = currCtrlPoint; } }
// Load Fbx File void GenerateLOD::LoadFbx() { FbxManager *fbxManager = FbxManager::Create(); //Create an IOSetting FbxIOSettings *ios = FbxIOSettings::Create(fbxManager, IOSROOT); fbxManager->SetIOSettings(ios); //Create an impoter FbxImporter *lImporter = FbxImporter::Create(fbxManager, "myImporter"); std::string tmp = std::string(".\\LODs\\") + srcFbxName; bool lImporterStatus = lImporter->Initialize(tmp.c_str(), -1, fbxManager->GetIOSettings()); if (!lImporterStatus) { MessageBox(NULL, "No Scuh File in .\\LODs\\ directory !", "Warning", 0); return; } FbxScene *fbxScene = FbxScene::Create(fbxManager, "myScene"); lImporter->Import(fbxScene); FbxNode *rootNode = fbxScene->GetRootNode(); if (rootNode != NULL) { for (int i = 0; i < rootNode->GetChildCount(); ++i) { FbxNode *node = rootNode->GetChild(i); FbxNodeAttribute *Att = node->GetNodeAttribute(); if (Att != NULL && Att->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh *lMesh = (FbxMesh *)(Att); //FbxMesh *lMesh = dynamic_cast<FbxMesh *>(Att); if (!lMesh->IsTriangleMesh()) { FbxGeometryConverter converter = FbxGeometryConverter(fbxManager); FbxNodeAttribute *Attr = converter.Triangulate(lMesh, true); lMesh = (FbxMesh *)(Attr); } //Following is the SImplification Reduction_EdgesCollapse_UV(node, lMesh, fbxManager, fbxScene); } } } //MessageBox(NULL, "Export Succeed!", "Export", 0); fbxManager->Destroy(); }
void FBXExporter::ProcessMesh(FbxNode* inNode) { FbxMesh* currMesh = inNode->GetMesh(); mTriangleCount = currMesh->GetPolygonCount(); int vertexCounter = 0; mTriangles.reserve(mTriangleCount); //per triangle for (unsigned int i = 0; i < mTriangleCount; ++i) { XMFLOAT3 normal[3]; XMFLOAT3 binormal[3]; XMFLOAT2 UV[3][2]; Triangle currTriangle; mTriangles.push_back(currTriangle); //per vertex for (unsigned int j = 0; j < 3; ++j) { int ctrlPointIndex = currMesh->GetPolygonVertex(i, j); CtrlPoint* currCtrlPoint = mControlPoints[ctrlPointIndex]; PNTIWVertex temp; temp.mPosition = currCtrlPoint->mPosition; temp.mNormal = normal[j]; temp.mUV = UV[j][0]; mVertices.push_back(temp); mTriangles.back().mIndices.push_back(vertexCounter); ++vertexCounter; } } // Now mControlPoints has served its purpose // We can free its memory for(auto itr = mControlPoints.begin(); itr != mControlPoints.end(); ++itr) { delete itr->second; } mControlPoints.clear(); }
void FbxUtil::LoadMesh(const SceneNode::Ptr &ntNode, FbxNode* fbxNode) { FbxMesh* fbxMesh = static_cast<FbxMesh*>(fbxNode->GetNodeAttribute()); // first, we test if ther's already a mesh asset exits with this name. Mesh::Ptr mesh = EntityUtil::Instance()->FindEntity<Mesh>(fbxMesh->GetName()); if (mesh == nullptr) { // if not, we read the mesh data. mesh = CreateMesh(fbxMesh); EntityUtil::Instance()->AddEntity(mesh); } // attach mesh component to node. ntNode->AddComponent(MeshRender::Create(nullptr, mesh)); LoadMaterial(ntNode, fbxNode); }
JNIEXPORT jintArray JNICALL Java_de_tesis_dynaware_javafx_graphics_importers_fbx_JFbxLib_getMeshFaceSmoothingGroups(JNIEnv *env, jobject obj, jint attributeIndex) { // Check FBX file has been opened. if (!isOpen()) { throwFileClosedException(env); } // Check attribute index bounds for safety. if (!checkAttributeBounds(attributeIndex)) { throwArrayOutOfBoundsException(env); } // Check attribute type for safety. if (!isValidType(attributeIndex, FbxNodeAttribute::EType::eMesh)) { return NULL; } FbxMesh* mesh = (FbxMesh*)currentNode->GetNodeAttributeByIndex(attributeIndex); FbxGeometryElementSmoothing* smoothingElement = mesh->GetElementSmoothing(0); // If smoothing is not defined explicitly, try to convert from normals. Convert edge-smoothing to face-smoothing. if (!smoothingElement || smoothingElement->GetMappingMode() == FbxGeometryElement::eByEdge) { FbxGeometryConverter geometryConverter(sdkManager); if (!smoothingElement) { geometryConverter.ComputeEdgeSmoothingFromNormals(mesh); smoothingElement = mesh->GetElementSmoothing(0); } if (smoothingElement->GetMappingMode() == FbxGeometryElement::eByEdge) { geometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(mesh); } } const int polygonCount = mesh->GetPolygonCount(); jintArray faceSmoothingGroups = env->NewIntArray(polygonCount); // Check memory could be allocated. if (faceSmoothingGroups == NULL) { throwOutOfMemoryError(env); } for (int i=0; i<polygonCount; i++) { jint iValue = smoothingElement->GetDirectArray().GetAt(i); env->SetIntArrayRegion(faceSmoothingGroups, i, 1, &iValue); } return faceSmoothingGroups; }
void FBXSceneEncoder::loadModel(FbxNode* fbxNode, Node* node) { FbxMesh* fbxMesh = fbxNode->GetMesh(); if (!fbxMesh) { return; } if (fbxMesh->IsTriangleMesh()) { Mesh* mesh = loadMesh(fbxMesh); Model* model = new Model(); model->setMesh(mesh); node->setModel(model); loadSkin(fbxMesh, model); if (model->getSkin()) { node->resetTransformMatrix(); } } }
void generateTangentsAndBinormals(FbxNode* fbxNode, const EncoderArguments& arguments) { if (!fbxNode) return; const char* name = fbxNode->GetName(); if (name && strlen(name) > 0) { FbxMesh* fbxMesh = fbxNode->GetMesh(); if (fbxMesh && arguments.isGenerateTangentBinormalId(string(name))) { fbxMesh->GenerateTangentsDataForAllUVSets(); } } // visit child nodes const int childCount = fbxNode->GetChildCount(); for (int i = 0; i < childCount; ++i) { generateTangentsAndBinormals(fbxNode->GetChild(i), arguments); } }
FbxNode* ILDLMesh::CreateMesh( FbxScene* pScene, const char* pName ) { int nVerts = (int)m_vertex_list.size(); FbxMesh* lMesh = FbxMesh::Create(pScene,pName); lMesh->InitControlPoints( nVerts ); FbxVector4* lControlPoints = lMesh->GetControlPoints(); FbxGeometryElementNormal* lGeometryElementNormal= lMesh->CreateElementNormal(); lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint); lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect); int vi = 0, glidx = 0; for( ILDLVertexIter i = m_vertex_list.begin(); i != m_vertex_list.end(); ++i, vi++ ) { ILDLVertexPtr vp = (*i); vp->m_glIdx = glidx; vec3 coords = vp->getCoords(); lControlPoints[vi] = FbxVector4( coords[0], coords[1], coords[2] ); vec3 normal = vp->getNormal(); lGeometryElementNormal->GetDirectArray().Add( FbxVector4( normal[0], normal[1], normal[2] ) ); glidx++; } for( ILDLFaceIter i = m_face_list.begin(); i != m_face_list.end(); ++i ) { ILDLFacePtr fp = *i; ILDLFaceVertexPtr fvp = fp->front(); lMesh->BeginPolygon(-1, -1, -1, false); lMesh->AddPolygon( fvp->getVertexPtr()->m_glIdx ); fvp = fvp->next(); lMesh->AddPolygon( fvp->getVertexPtr()->m_glIdx ); fvp = fvp->next(); lMesh->AddPolygon( fvp->getVertexPtr()->m_glIdx ); lMesh->EndPolygon (); } FbxNode* lNode = FbxNode::Create(pScene,pName); lNode->SetNodeAttribute(lMesh); return lNode; }
void FbxParser::ProcessMesh(FbxNode* pNode,std::vector<GS::BaseMesh*>& meshs) { FbxMesh* lMesh = (FbxMesh*) pNode->GetNodeAttribute (); if (lMesh == NULL) return ; int triangleCount = lMesh->GetPolygonCount(); int vertexCounter = 0; if (triangleCount ==0) return ; GS::BaseMesh* pMesh = new GS::BaseMesh(); GS::double3 p0, p1, p2; int vertexId = 0; GS::VertexInfo v1, v2, v3; for(int i = 0 ; i < triangleCount ; ++i) { int ctrlPointIndex = lMesh->GetPolygonVertex(i , 0); ReadVertex(lMesh, ctrlPointIndex, v1.pos); ReadColor(lMesh, ctrlPointIndex, vertexId, v1.color); ReadNormal(lMesh, ctrlPointIndex, vertexId++, v1.normal); // read the second vertex ctrlPointIndex = lMesh->GetPolygonVertex(i , 1); ReadVertex(lMesh, ctrlPointIndex, v2.pos); ReadColor(lMesh, ctrlPointIndex, vertexId, v2.color); ReadNormal(lMesh, ctrlPointIndex, vertexId++, v2.normal); // read the third vertex ctrlPointIndex = lMesh->GetPolygonVertex(i , 2); ReadVertex(lMesh, ctrlPointIndex, v3.pos); ReadColor(lMesh, ctrlPointIndex, vertexId, v3.color); ReadNormal(lMesh, ctrlPointIndex, vertexId++, v3.normal); pMesh->Add(v1, v2, v3); } pMesh->GenID(); //pMesh->GenSurface(); pMesh->GenAABB(true); meshs.push_back(pMesh); }
reMesh* reFBXAsset::importMesh(FbxNode* fbxNode) { qDebug() << "import mesh for" << fbxNode->GetName(); reMesh* mesh = new reMesh; FbxMesh* fmesh = (FbxMesh*) fbxNode->GetNodeAttribute(); FbxVector4* controlPoints = fmesh->GetControlPoints(); for (int i=0; i<fmesh->GetPolygonCount(); i++) { reFace* face = new reFace; for (int j=0; j<fmesh->GetPolygonSize(i); j++) { int vi = fmesh->GetPolygonVertex(i, j); reVertex vertex; vertex.pos = reVec3(controlPoints[vi][0], controlPoints[vi][1], controlPoints[vi][2]); FbxVector4 fNormal; fmesh->GetPolygonVertexNormal(i, j, fNormal); vertex.uv = getUV(fmesh, vi, i, j); vertex.normal = reVec3(fNormal[0], fNormal[1], fNormal[2]); face->vertices.push_back(vertex); } reMaterial* mat = getMaterial(fmesh, i, mesh->materialSet); mesh->addFace(face,mat ? mat->id: -1); } reMeshAsset* meshAsset = new reMeshAsset(meshes); meshAsset->mesh = mesh; meshes->children.push_back(meshAsset); meshAsset->setPath((dataDir().toStdString() + "/" + fbxNode->GetName() + ".mesh").c_str()); mesh->save(dataDir().toStdString() + "/" + fbxNode->GetName() + ".mesh"); return mesh; }
std::shared_ptr<Mesh> FbxParser::CreateMesh(GameObjectPtr node, FbxNode * fbxNode) { Mesh::Ptr mesh = Mesh::Create(fbxNode->GetName()); FbxMesh* fbxMesh = static_cast<FbxMesh*>(fbxNode->GetNodeAttribute()); int polygonCount = fbxMesh->GetPolygonCount(); int indicesCount = polygonCount * 3; mesh->Positions.Data.reserve(indicesCount * 3); mesh->Indices.Data.reserve(indicesCount); mesh->Colors.Data.reserve(indicesCount * 3); for (int i = 0; i < polygonCount; ++i) { ASSERT(fbxMesh->GetPolygonSize(i) <= 3, "Error: triangulate %s", mesh->GetName()); for (int jj = 0; jj < 3; ++jj) { int ctrPointIdx = fbxMesh->GetPolygonVertex(i, jj); // TODO // Use Triangle Strip instead of triangle list auto position = fbxMesh->GetControlPointAt(ctrPointIdx); mesh->Positions.Data.push_back((double*)&position); int indices = i * 3 + jj; mesh->Indices.Data.push_back(indices); auto color = fbxMesh->GetElementVertexColor(ctrPointIdx); mesh->Colors.Data.push_back((double*)&color); } } mesh->UpdateBuffer(); return mesh; }
/* Extract Mesh objects by recursing the scene. They will initialise themselves. */ void SceneImporter::loadCacheRecursive(FbxNode * pNode) { // Bake material and hook as user data. FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (lMesh && !lMesh->GetUserDataPtr()) { _meshes.push_back(std::auto_ptr<Mesh>(new Mesh(lMesh))); } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { loadCacheRecursive(pNode->GetChild(lChildIndex)); } }
void Parser::bake_meshes_recursive(FbxNode * node, FbxAnimLayer * animation_layer) { FbxPose * pose = NULL; FbxTime current_time; FbxAMatrix parent_global_position; FbxAMatrix global_position = get_global_position(node, current_time, pose, &parent_global_position); FbxNodeAttribute* node_attribute = node->GetNodeAttribute(); if(node_attribute) { if(node_attribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * mesh = node->GetMesh(); FbxAMatrix geometry_offset = get_geometry(node); FbxAMatrix global_offset_position = global_position * geometry_offset; FbxVector4* control_points = mesh->GetControlPoints(); bake_global_positions(control_points, mesh->GetControlPointsCount(), global_offset_position); if(mesh && !mesh->GetUserDataPtr()) { VBOMesh * mesh_cache = new VBOMesh; if(mesh_cache->initialize(mesh)) { bake_mesh_deformations(mesh, mesh_cache, current_time, animation_layer, global_offset_position, pose); meshes->push_back(mesh_cache); } } } } const int node_child_count = node->GetChildCount(); for(int node_child_index = 0; node_child_index < node_child_count; ++node_child_index) { bake_meshes_recursive(node->GetChild(node_child_index), animation_layer); } }
JNIEXPORT jfloatArray JNICALL Java_de_tesis_dynaware_javafx_graphics_importers_fbx_JFbxLib_getMeshTexCoords(JNIEnv *env, jobject obj, jint attributeIndex) { // Check FBX file has been opened. if (!isOpen()) { throwFileClosedException(env); } // Check attribute index bounds for safety. if (!checkAttributeBounds(attributeIndex)) { throwArrayOutOfBoundsException(env); } // Check attribute type for safety. if (!isValidType(attributeIndex, FbxNodeAttribute::EType::eMesh)) { return NULL; } FbxMesh* mesh = (FbxMesh*)currentNode->GetNodeAttributeByIndex(attributeIndex); // Currently we only read from the first layer. FbxLayerElementUV *firstLayer = mesh->GetElementUV(0); if (firstLayer==NULL) { return NULL; } const int uvCount = firstLayer->GetDirectArray().GetCount(); jfloatArray texCoords = env->NewFloatArray(2*uvCount); if (texCoords == NULL) { return NULL; } for (int i=0; i<uvCount; i++) { jfloat uv[2]; // Note that we invert the 'v' index to match the JavaFX (DirectX?) convention. uv[0] = firstLayer->GetDirectArray().GetAt(i)[0]; uv[1] = 1-firstLayer->GetDirectArray().GetAt(i)[1]; env->SetFloatArrayRegion(texCoords, 2*i, 2, uv); } return texCoords; }
// メッシュ情報処理(再帰関数) void GetMeshData(FbxNode *parent, VertexDataArray& outVertexData) { // メッシュだけ処理 int numKids = parent->GetChildCount(); for(int i = 0; i < numKids; i++) { FbxNode *child = parent->GetChild(i); // メッシュを見つけたら if(child->GetMesh()) { FbxMesh* pMesh = child->GetMesh();// static_cast<FbxMesh*>(child->GetNodeAttribute()); printf("メッシュ発見\n"); printf("名前:%s\n", pMesh->GetName()); printf("ポリゴン数:%d\n", pMesh->GetPolygonCount()); printf("マテリアル数:%d\n", pMesh->GetElementMaterialCount()); printf("コントロールポイント数(頂点座標):%d\n", pMesh->GetControlPointsCount()); printf("UV数:%d\n", pMesh->GetTextureUVCount()); FbxArray<FbxVector4> normals; pMesh->GetPolygonVertexNormals(normals); printf("法線数:%d\n", normals.GetCount()); // 頂点情報取得 GetFBXVertexData(pMesh, outVertexData); } // マテリアル int numMat = child->GetMaterialCount(); for(int j = 0; j < numMat; ++j) { FbxSurfaceMaterial* mat = child->GetMaterial(j); if(mat) { GetMatrialData(mat); } } if(numMat == 0) { printf("マテリアルなし\n"); } child->GetChild(0); // 更に子を処理 GetMeshData(child, outVertexData); } }
void FBXMesh::Builder::unloadCacheRecursive(FbxNode * pNode) { // Unload the material cache const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && lMaterial->GetUserDataPtr()) { FBXMaterialCache* lMaterialCache = static_cast<FBXMaterialCache*>(lMaterial->GetUserDataPtr()); lMaterial->SetUserDataPtr(NULL); delete lMaterialCache; } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Unload the mesh cache if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (lMesh && lMesh->GetUserDataPtr()) { #ifndef USE_META_DATA VBOMesh * lMeshCache = static_cast<VBOMesh *>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete lMeshCache; #else FbxMetaData * fbxMetaData = static_cast<FbxMetaData*>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete fbxMetaData; #endif } } // Unload the light cache else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && lLight->GetUserDataPtr()) { FBXLightCache* lLightCache = static_cast<FBXLightCache*>(lLight->GetUserDataPtr()); lLight->SetUserDataPtr(NULL); delete lLightCache; } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { unloadCacheRecursive(pNode->GetChild(lChildIndex)); } }
void FBXScene::ProcessMesh(FbxNode* pNode) { FbxMesh* pFBXMesh = pNode->GetMesh(); if( !pFBXMesh ) return; if ( pFBXMesh->GetPolygonVertexCount() != pFBXMesh->GetPolygonCount() * 3 ) { FbxGeometryConverter GeometryConverter(pNode->GetFbxManager()); if( !GeometryConverter.TriangulateInPlace( pNode ) ) { return; } pFBXMesh = pNode->GetMesh(); } pFBXMesh->InitNormals(); pFBXMesh->ComputeVertexNormals(true); pFBXMesh->GenerateTangentsDataForAllUVSets(); int nVertexCount = pFBXMesh->GetControlPointsCount(); if( nVertexCount <= 0 ) return; std::vector<BoneWeights> boneWeights(nVertexCount); ProcessBoneWeights(pFBXMesh, boneWeights); Model* pModel = new Model(pNode->GetName(), m_Models.GetCount(), false); FbxVector4* aControlPoints = pFBXMesh->GetControlPoints(); for( int pi = 0; pi < pFBXMesh->GetPolygonCount(); ++pi ) // Whole for-loop takes some time too, investigate further. { // Material Material* pMaterial = NULL; for( unsigned int pvi = 0; pvi < 3; ++pvi ) { int nVertexIndex = pFBXMesh->GetPolygonVertex(pi, pvi); if( nVertexIndex < 0 || nVertexIndex >= nVertexCount ) continue; // Material if( pMaterial == NULL ) pMaterial = GetMaterialLinkedWithPolygon(pFBXMesh, 0, pi, 0, nVertexIndex); // Position FbxVector4 fbxPosition = aControlPoints[nVertexIndex]; // Normals And Tangents FbxVector4 fbxNormal, fbxTangent; fbxNormal = GetNormal(pFBXMesh, 0, pi, pvi, nVertexIndex); fbxTangent = GetTangent(pFBXMesh, 0, pi, pvi, nVertexIndex); // Add Vertex pModel->AddVertex(pMaterial, FbxVector4ToBTHFBX_VEC3(fbxPosition), FbxVector4ToBTHFBX_VEC3(fbxNormal), FbxVector4ToBTHFBX_VEC3(fbxTangent), GetTexCoord(pFBXMesh, 0, pi, pvi, nVertexIndex), boneWeights[nVertexIndex]); // Update Bounding Box UpdateBoundingBoxDataFromVertex(FbxVector4ToBTHFBX_VEC3(fbxPosition)); } } // Geometric Offset pModel->SetGeometricOffset2(GetGeometricOffset2(pNode)); // Insert Model m_Models.Add(pModel->GetName(), pModel); }
void FBXConverter::processAnimations( FbxNode* node , std::vector<JointData> &skeleton , std::vector<VertexData> &verts , std::vector<IndexData> &indices ) { FbxMesh* theMesh = node->GetMesh(); FbxAnimStack* animationStack = node->GetScene()->GetSrcObject<FbxAnimStack>(); FbxAnimLayer* animationLayer = animationStack->GetMember<FbxAnimLayer>(); std::vector<FbxTime> frames; for ( int curveNodeIndex = 0; curveNodeIndex < animationLayer->GetMemberCount(); ++curveNodeIndex ) { FbxAnimCurveNode* currentCurve = animationLayer->GetMember<FbxAnimCurveNode>( curveNodeIndex ); for ( unsigned int channelIndex = 0; channelIndex < currentCurve->GetChannelsCount(); ++channelIndex ) { for ( int curve = 0; curve < currentCurve->GetCurveCount( channelIndex ); ++curve ) { FbxAnimCurve* theCurveVictim = currentCurve->GetCurve( channelIndex , curve ); for ( int keyIndex = 0; keyIndex < theCurveVictim->KeyGetCount(); ++keyIndex ) { bool alreadyIn = false; for ( unsigned int frameIndex = 0; frameIndex < frames.size(); ++frameIndex ) { if ( ( unsigned int ) frames[frameIndex].GetFrameCount() == ( unsigned int ) theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() ) { alreadyIn = true; //std::cout << frames[frameIndex].GetFrameCount() << " " << theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() << " " << alreadyIn << std::endl; break; } } std::cout << theCurveVictim->KeyGet( keyIndex ).GetTime().GetFrameCount() << " " << alreadyIn << std::endl; if(!alreadyIn) frames.push_back(theCurveVictim->KeyGet( keyIndex ).GetTime()); } } } } std::sort( frames.begin() , frames.end() , frameCompare ); FbxAMatrix geoTransform( node->GetGeometricTranslation( FbxNode::eSourcePivot ) , node->GetGeometricRotation( FbxNode::eSourcePivot ) , node->GetGeometricScaling( FbxNode::eSourcePivot ) ); for ( int i = 0; i < theMesh->GetDeformerCount(); ++i ) { FbxSkin* theSkin = reinterpret_cast< FbxSkin* >( theMesh->GetDeformer( i , FbxDeformer::eSkin ) ); if ( !theSkin ) continue; for ( int j = 0; j < theSkin->GetClusterCount(); ++j ) { FbxCluster* cluster = theSkin->GetCluster( j ); std::string jointName = cluster->GetLink()->GetName(); int currentJointIndex = -1; for ( unsigned int k = 0; k < skeleton.size(); ++k ) { if ( !skeleton[k].name.compare( jointName ) ) { currentJointIndex = k; break; } } if ( currentJointIndex < 0 ) { std::cout << "wrong bone" << std::endl; continue; } FbxAMatrix transformMatrix, transformLinkMatrix, offsetMatrix; cluster->GetTransformMatrix( transformMatrix ); cluster->GetTransformLinkMatrix( transformLinkMatrix ); //offsetMatrix = transformLinkMatrix.Inverse() * transformMatrix * geoTransform; FbxMatrix realMatrix( transformLinkMatrix.Inverse() * transformMatrix ); for ( unsigned int row = 0; row < 4; ++row ) { for ( unsigned int column = 0; column < 4; ++column ) { skeleton[currentJointIndex].offsetMatrix[row][column] = (float)realMatrix.Get( row , column ); } } for ( int k = 0; k < cluster->GetControlPointIndicesCount(); ++k ) { BlendingIndexWeightPair weightPair; weightPair.blendingIndex = currentJointIndex; weightPair.blendingWeight = (float)cluster->GetControlPointWeights()[k]; unsigned int controlPoint = cluster->GetControlPointIndices()[k]; for ( unsigned int z = 0; z < indices.size(); ++z ) { if ( indices[z].oldControlPoint == controlPoint ) { if ( verts[indices[z].index].blendingInfo.size() > 4 ) { std::cout << "Warning: vert has more than 4 bones connected, ignoring additional bone." << std::endl; } //else verts[indices[z].index].blendingInfo.push_back( weightPair ); bool found = false; for ( unsigned int omg = 0; omg < verts[indices[z].index].blendingInfo.size(); ++omg ) { if ( verts[indices[z].index].blendingInfo[omg].blendingIndex == weightPair.blendingIndex ) { found = true; break; } } if ( !found ) verts[indices[z].index].blendingInfo.push_back( weightPair ); } } } for ( unsigned int frameIndex = 0; frameIndex < frames.size(); ++frameIndex ) { FbxVector4 translation = cluster->GetLink()->EvaluateLocalTranslation( frames[frameIndex] ); FbxVector4 rotation = cluster->GetLink()->EvaluateLocalRotation( frames[frameIndex] ); FbxVector4 scale = cluster->GetLink()->EvaluateLocalScaling( frames[frameIndex] ); AnimationData animData; animData.frame = (int)frames[frameIndex].GetFrameCount(); animData.translation = glm::vec3(translation[0],translation[1],translation[2]); animData.rotation = glm::angleAxis( glm::radians( (float)rotation[2] ), glm::vec3(0,0,1)) * glm::angleAxis(glm::radians((float) rotation[1]), glm::vec3(0,1,0)) * glm::angleAxis(glm::radians((float)rotation[0]), glm::vec3(1,0,0)); animData.scale = glm::vec3(scale[0],scale[1],scale[2]); skeleton[currentJointIndex].animation.push_back( animData ); } } } }