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; }
//=============================================================================================================================== 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; } }
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 MeshImporter::LoadNodeMesh(FbxNode* node, ID3D11Device3* device, ID3D11DeviceContext3* context) { unsigned int numPolygons = 0; unsigned int numVertices = 0; unsigned int numIndices = 0; unsigned int numPolygonVert = 0; if (node->GetNodeAttribute() != NULL && node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh) { //PrintNode(node); // Create meshes FbxMesh* fbxMesh = node->GetMesh(); numPolygons = fbxMesh->GetPolygonCount(); numIndices = fbxMesh->GetPolygonVertexCount(); numVertices = fbxMesh->GetControlPointsCount(); // Do not use indexed drawing method numVertices = numIndices; vector<Vertex> vertices(numVertices); vector<unsigned int> indices(numIndices); numPolygonVert = 3; //assert(numPolygonVert == 3); FbxVector4* controlPoints = fbxMesh->GetControlPoints(); int* indices_array = fbxMesh->GetPolygonVertices(); // Need to be changed for optimization for (unsigned int i = 0; i < numIndices; i++) { indices[i] = indices_array[i]; vertices[i].pos.x = (float)fbxMesh->GetControlPointAt(indices[i]).mData[0];// / 1000.0f; vertices[i].pos.y = (float)fbxMesh->GetControlPointAt(indices[i]).mData[1];// / 1000.0f; vertices[i].pos.z = (float)fbxMesh->GetControlPointAt(indices[i]).mData[2];// / 1000.0f; } // For indexed drawing /*for (unsigned int i = 0; i < numVertices; i++) { vertices[i].pos.x = (float)controlPoints[i].mData[0]; vertices[i].pos.y = (float)controlPoints[i].mData[1]; vertices[i].pos.z = (float)controlPoints[i].mData[2]; }*/ LoadUV(fbxMesh, &vertices[0], &indices[0]); //OutputDebugStringA(("\n number of polygons: " + to_string(numPolygons) + " \n").c_str()); //OutputDebugStringA(("\n number of indices: " + to_string(numIndices) + " \n").c_str()); //OutputDebugStringA(("\n number of vertices: " + to_string(vertices.size()) + " \n").c_str()); // Read mesh base transform matrix FbxAMatrix fbxGlobalMeshBaseMatrix = node->EvaluateGlobalTransform().Inverse().Transpose(); XMFLOAT4X4 globalMeshBaseMatrix; for (int r = 0; r < 4; r++) { //PrintTab("Global mesh base mat: " + to_string(fbxGlobalMeshBaseMatrix.mData[r][0])); for (int c = 0; c < 4; c++) { globalMeshBaseMatrix.m[r][c] = (float)fbxGlobalMeshBaseMatrix.mData[r][c]; } } // To be considered when importing Maya fbx model //FbxAMatrix geoMatrix = GetTransformMatrix(node); //ConvertFbxAMatrixToDXMatrix(&globalMeshBaseMatrix, fbxGlobalMeshBaseMatrix); MeshEntry mesh; mesh.vertices = vertices; mesh.indices = indices; mesh.numVertices = numVertices; mesh.numIndices = numIndices; mesh.fbxNode = node; mesh.globalMeshBaseMatrix = globalMeshBaseMatrix; // Load materials and textures LoadMaterials(node, &mesh, device, context); // Load weights LoadWeight(fbxMesh, &mesh); // Set to be clockwise, must be done after reading uvs, normals, weights and etc for (auto it = mesh.vertices.begin(); it != mesh.vertices.end(); it += 3) { swap(*it, *(it + 2)); } model->entries.push_back(mesh); } int numChild = node->GetChildCount(); for (int i = 0; i < numChild; i++) { LoadNodeMesh(node->GetChild(i), device, context); } }
void MeshImporter::LoadNodeMesh(FbxNode* node, ID3D11Device3* device, ID3D11DeviceContext3* context) { unsigned int numPolygons = 0; unsigned int numVertices = 0; unsigned int numIndices = 0; unsigned int numPolygonVert = 0; if (node->GetNodeAttribute() != NULL && node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh) { //PrintNode(node); // Create meshes FbxMesh* fbxMesh = node->GetMesh(); numPolygons = fbxMesh->GetPolygonCount(); numIndices = fbxMesh->GetPolygonVertexCount(); numVertices = fbxMesh->GetControlPointsCount(); // Do not use indexed drawing method numVertices = numIndices; vector<Vertex> vertices(numVertices); vector<unsigned int> indices(numIndices); numPolygonVert = 3; //assert(numPolygonVert == 3); FbxVector4* controlPoints = fbxMesh->GetControlPoints(); int* indices_array = fbxMesh->GetPolygonVertices(); // Need to be changed for optimization for (unsigned int i = 0; i < numIndices; i++) { indices[i] = indices_array[i]; vertices[i].pos.x = (float)fbxMesh->GetControlPointAt(indices[i]).mData[0] / 10000.0f; vertices[i].pos.y = (float)fbxMesh->GetControlPointAt(indices[i]).mData[1] / 10000.0f; vertices[i].pos.z = (float)fbxMesh->GetControlPointAt(indices[i]).mData[2] / 10000.0f; } // For indexed drawing /*for (unsigned int i = 0; i < numVertices; i++) { vertices[i].pos.x = (float)controlPoints[i].mData[0];// / 25.0f; vertices[i].pos.y = (float)controlPoints[i].mData[1];// / 25.0f; vertices[i].pos.z = (float)controlPoints[i].mData[2];// / 25.0f; }*/ LoadUV(fbxMesh, &vertices[0], &indices[0]); // Set to be clockwise, must be done after reading uvs and normals for (auto it = vertices.begin(); it != vertices.end(); it += 3) { std::swap(*it, *(it + 2)); } //OutputDebugStringA(("\n number of polygons: " + to_string(numPolygons) + " \n").c_str()); //OutputDebugStringA(("\n number of indices: " + to_string(numIndices) + " \n").c_str()); //OutputDebugStringA(("\n number of vertices: " + to_string(vertices.size()) + " \n").c_str()); ModelObj::MeshEntry mesh; mesh.vertices = vertices; mesh.indices = indices; mesh.numVertices = numVertices; mesh.numIndices = numIndices; LoadMaterials(node, &mesh, device, context); model->entries.push_back(mesh); } for (int i = 0; i < node->GetChildCount(); i++) { LoadNodeMesh(node->GetChild(i), device, context); } }
HRESULT FBXLoader::loadFBXFile(char* filePath, VertexBuffer** vBuf, IndexBuffer** iBuf, Renderer* renderer, bool centerShift) { if (g_pFbxSdkManager == nullptr) { g_pFbxSdkManager = FbxManager::Create(); FbxIOSettings* pIOsettings = FbxIOSettings::Create(g_pFbxSdkManager, IOSROOT); g_pFbxSdkManager->SetIOSettings(pIOsettings); } this->shiftCenter = centerShift; FbxImporter* pImporter = FbxImporter::Create(g_pFbxSdkManager, ""); FbxScene* pFbxScene = FbxScene::Create(g_pFbxSdkManager, ""); bool bSuccess = pImporter->Initialize(filePath, -1, g_pFbxSdkManager->GetIOSettings()); if (!bSuccess) return E_FAIL; bSuccess = pImporter->Import(pFbxScene); if (!bSuccess) return E_FAIL; FbxAxisSystem sceneAxisSystem = pFbxScene->GetGlobalSettings().GetAxisSystem(); FbxAxisSystem DirectXAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eLeftHanded); if (sceneAxisSystem != DirectXAxisSystem) { DirectXAxisSystem.ConvertScene(pFbxScene); } pImporter->Destroy(); FbxNode* pFbxRootNode = pFbxScene->GetRootNode(); if (pFbxRootNode) { // Check if the getChildCount is > 1 TODO int test = pFbxRootNode->GetChildCount(); for (int i = 0; i < pFbxRootNode->GetChildCount(); i++) { FbxNode* pFbxChildNode = pFbxRootNode->GetChild(i); if (pFbxChildNode->GetNodeAttribute() == NULL) continue; FbxNodeAttribute::EType AttributeType = pFbxChildNode->GetNodeAttribute()->GetAttributeType(); if (AttributeType != FbxNodeAttribute::eMesh) continue; FbxMesh* pMesh = (FbxMesh*)pFbxChildNode->GetNodeAttribute(); int numControlPoints = pMesh->GetControlPointsCount(); bool initial = true; float xMin, yMin, zMin; float xMax, yMax, zMax; float xIn, yIn, zIn; float xCenter, yCenter, zCenter; if (this->shiftCenter){ for (int c = 0; c < numControlPoints; c++) { xIn = (float)pMesh->GetControlPointAt(c).mData[0]; yIn = (float)pMesh->GetControlPointAt(c).mData[1]; zIn = (float)pMesh->GetControlPointAt(c).mData[2]; if (initial) { xMin = xIn; yMin = yIn; zMin = zIn; xMax = xIn; yMax = yIn; zMax = zIn; initial = false; } else { if (xIn < xMin) { xMin = xIn; } if (yIn < yMin) { yMin = yIn; } if (zIn < zMin) { zMin = zIn; } if (xIn > xMax) { xMax = xIn; } if (yIn > yMax) { yMax = yIn; } if (zIn > zMax) { zMax = zIn; } } } xCenter = (xMin + xMax) / 2.0f; yCenter = (yMin + yMax) / 2.0f; zCenter = (zMin + zMax) / 2.0f; } else { xCenter = 0; yCenter = 0; zCenter = 0; } FbxVector4* pVertices = pMesh->GetControlPoints(); int vertexCount = pMesh->GetPolygonVertexCount(); //Vertex vertex; Vertex* vertexArray = new Vertex[vertexCount]; //Vertex vertexArray[2592]; int numIndices = vertexCount; unsigned int* indexArray = new unsigned int[numIndices]; FbxVector4 fbxNorm(0, 0, 0, 0); FbxVector2 fbxUV(0, 0); bool isMapped; int vertexIndex = 0; // Loop iterates through the polygons and fills the vertex and index arrays for the buffers for (int j = 0; j < pMesh->GetPolygonCount(); j++) { int iNumVertices = pMesh->GetPolygonSize(j); assert(iNumVertices == 3); //1st vertex int controlIndex = pMesh->GetPolygonVertex(j, 2); pMesh->GetPolygonVertexUV(j, 2, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 2, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; //2nd vertex controlIndex = pMesh->GetPolygonVertex(j, 1); pMesh->GetPolygonVertexUV(j, 1, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 1, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; //3rd vertex controlIndex = pMesh->GetPolygonVertex(j, 0); pMesh->GetPolygonVertexUV(j, 0, "map1", fbxUV, isMapped); pMesh->GetPolygonVertexNormal(j, 0, fbxNorm); vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter; vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter; vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter; vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0]; vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1]; vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0]; vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1]; vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2]; indexArray[vertexIndex] = vertexIndex; vertexIndex++; } // Generate vertex and index buffers from the vertex and index arrays *vBuf = renderer->createVertexBuffer(vertexArray, vertexCount); *iBuf = renderer->createIndexBuffer(indexArray, numIndices); delete[] vertexArray; delete[] indexArray; } } return S_OK; }
void importFBXNode( FbxNode *node, vector<Vector3> &vertices, vector<Color> &colors, vector<Vector2> &uvs, vector<Vector3> &normals, vector<uint32> &elements) { FbxNode *childNode = 0; int numKids = node->GetChildCount(); for ( int i=0 ; i<numKids ; i++) { childNode = node->GetChild(i); FbxMesh *mesh = childNode->GetMesh(); if ( mesh != NULL ) { auto offset = node->GetGeometricTranslation(FbxNode::eSourcePivot); //================= Get Vertices ==================================== int baseline = vertices.size(); int numVerts = mesh->GetControlPointsCount(); for ( int j=0; j<numVerts; j++) { FbxVector4 vert = mesh->GetControlPointAt(j); vertices.push_back( Vector3(vert.mData[0], vert.mData[1], vert.mData[2]) /*+ Vector3(offset.mData[0], offset.mData[1], offset.mData[2])*/); colors.push_back(Vector3(1, 1, 1)); uvs.push_back(Vector2(0, 0)); } //================= Get Indices ==================================== int numIndices=mesh->GetPolygonVertexCount(); int *indicesRaw = mesh->GetPolygonVertices(); for (int j = 0; j < numIndices; j++) { elements.push_back(indicesRaw[j] + baseline); } int cnt = 0; int polygonCount = mesh->GetPolygonCount(); for (int j = 0; j < polygonCount; ++j) { FbxLayerElementArrayTemplate<FbxVector2>* uvVertices= 0; mesh->GetTextureUV(&uvVertices, FbxLayerElement::eTextureDiffuse); for (int k = 0; k < mesh->GetPolygonSize(j); ++k) { FbxVector2 uv = (*uvVertices)[mesh->GetTextureUVIndex(j, k)]; uvs[indicesRaw[cnt] + baseline].x = uv[0]; uvs[indicesRaw[cnt] + baseline].y = uv[1]; cnt++; } } } importFBXNode(childNode, vertices, colors, uvs, normals, elements); } }