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 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"); }
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 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 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 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 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 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); } }
MeshData* FBXImporter::GetMeshInfo() { mMeshData = new MeshData(); int indicesIndexOffset = 0; // 记录当前mesh在整个ib中的索引位移。 int verticesIndexOffset = 0; // 记录当前mesh在整个vb中的顶点位移。 for (int meshIndex = 0; meshIndex < mFBXMeshDatas.size(); meshIndex++) { FbxMesh* mesh = mFBXMeshDatas[meshIndex]->mMesh; FBXMeshData* fbxMeshData = mFBXMeshDatas[meshIndex]; fbxMeshData->mVerticesCount = mesh->GetControlPointsCount(); fbxMeshData->mIndicesCount = mesh->GetPolygonVertexCount(); fbxMeshData->mTrianglesCount = mesh->GetPolygonCount(); // 获取3dsmax中的全局变换矩阵,稍后可以在DX中还原。 FbxMatrix gloableTransform = mesh->GetNode()->EvaluateGlobalTransform(); FbxAMatrix matrixGeo; matrixGeo.SetIdentity(); const FbxVector4 lT = mesh->GetNode()->GetGeometricTranslation(FbxNode::eSourcePivot); const FbxVector4 lR = mesh->GetNode()->GetGeometricRotation(FbxNode::eSourcePivot); const FbxVector4 lS = mesh->GetNode()->GetGeometricScaling(FbxNode::eSourcePivot); matrixGeo.SetT(lT); matrixGeo.SetR(lR); matrixGeo.SetS(lS); FbxAMatrix matrixL2W; matrixL2W.SetIdentity(); matrixL2W = mesh->GetNode()->EvaluateGlobalTransform(); matrixL2W *= matrixGeo; XMMATRIX globalTransform = XMLoadFloat4x4(&fbxMeshData->globalTransform); FbxMatrixToXMMATRIX(globalTransform, matrixL2W); XMStoreFloat4x4(&fbxMeshData->globalTransform, globalTransform); // 读取顶点。 ReadVertices(fbxMeshData); // 读取索引。 ReadIndices(fbxMeshData); // 先读取网格对应的材质索引信息,以便优化稍后纹理读取。 // 一个网格可能只对应一个materialId,也可能对应多个materialId(3dsmax里的Multi/Sub-Object材质)。 // 如果只对应一个材质,简单的读取就行,不过普遍情况可能是为了优化渲染合并mesh从而拥有多材质。 // 这个函数调用完毕我们会得到materialId和拥有这个materialId的三角形列表(三角形编号列表),保存在vector<MaterialIdOffset>的容器中。 //struct Material //{ // Material() {} // Material(int id, string diffuse, string normalMap) // : materialId(id), // diffuseTextureFile(diffuse), // normalMapTextureFile(normalMap) // {} // // int materialId; // string diffuseTextureFile; // string normalMapTextureFile; //}; // struct MaterialIdOffset //{ // MaterialIdOffset() // : polygonCount(0) // {} // int polygonCount; // Material material; //}; ConnectMaterialsToMesh(mesh, fbxMeshData->mTrianglesCount); // 根据ConnectMaterialsToMesh得到的信息读取材质纹理信息,同样存入vector<MaterialIdOffset>容器。 LoadMaterials(fbxMeshData); int triangleCount = mesh->GetPolygonCount(); int controlPointIndex = 0; int normalIndex = 0; fbxMeshData->mUVs.resize(fbxMeshData->mIndicesCount, XMFLOAT2(-1.0f, -1.0f)); // Extract normals and uvs from FbxMesh. for (int i = 0; i < triangleCount; i++) { int polygonSize = mesh->GetPolygonSize(i); for (int j = 0; j < polygonSize; j++) { controlPointIndex = mesh->GetPolygonVertex(i, j); ReadNormals(fbxMeshData, controlPointIndex, normalIndex); // 有纹理我们才读取uv,tangent以及binormal。 if (fbxMeshData->hasDiffuseTexture()) { ReadUVs(fbxMeshData, controlPointIndex, normalIndex, mesh->GetTextureUVIndex(i, j), 0); ReadTangents(fbxMeshData, controlPointIndex, normalIndex); ReadBinormals(fbxMeshData, controlPointIndex, normalIndex); } normalIndex++; } } SplitVertexByNormal(fbxMeshData); if (fbxMeshData->hasDiffuseTexture()) { SplitVertexByUV(fbxMeshData); } else { fbxMeshData->mUVs.resize(fbxMeshData->mVerticesCount); } if (fbxMeshData->hasNormalMapTexture()) { SplitVertexByTangent(fbxMeshData); SplitVertexByBinormal(fbxMeshData); } else { fbxMeshData->mTangents.resize(fbxMeshData->mVerticesCount); fbxMeshData->mBinormals.resize(fbxMeshData->mVerticesCount); } // 如果.fbx包含一个以上的mesh,需要计算当前FBXMeshData的索引在全局索引中的位置。 for (int i = 0; i < fbxMeshData->mIndicesCount; i++) { fbxMeshData->mIndices[i] = fbxMeshData->mIndices[i] + verticesIndexOffset; } mMeshData->verticesCount += fbxMeshData->mVerticesCount; mMeshData->indicesCount += fbxMeshData->mIndicesCount; mMeshData->meshesCount++; // 多材质的情况。 // 根据之前填充的materialIdOffsets容器保存的materialId和三角形的对应关系, // 计算每个RenderPackage渲染所需的索引数量和索引起始位置(偏移)。 if (isByPolygon && fbxMeshData->hasDiffuseTexture()) { vector<MaterialIdOffset> materialIdOffsets = mMeshData->materialIdOffsets; for (int i = 0; i < materialIdOffsets.size(); i++) { RenderPackage renderPacakge; renderPacakge.globalTransform = fbxMeshData->globalTransform; renderPacakge.indicesCount = materialIdOffsets[i].polygonCount * 3; if (i == 0) { renderPacakge.indicesOffset = indicesIndexOffset; } else { renderPacakge.indicesOffset += indicesIndexOffset; } renderPacakge.material = materialIdOffsets[i].material; mMeshData->renderPackages.push_back(renderPacakge); indicesIndexOffset += renderPacakge.indicesCount; } } else // 单一材质的情况。 { RenderPackage renderPackage; renderPackage.indicesCount = fbxMeshData->mIndicesCount; renderPackage.indicesOffset = indicesIndexOffset; renderPackage.material = fbxMeshData->mMaterial; renderPackage.globalTransform = fbxMeshData->globalTransform; mMeshData->renderPackages.push_back(renderPackage); indicesIndexOffset += fbxMeshData->mIndices.size(); } verticesIndexOffset += fbxMeshData->mVertices.size(); // 将当前mesh的数据追加到全局数据容器。 Merge(mMeshData->vertices, fbxMeshData->mVertices); Merge(mMeshData->indices, fbxMeshData->mIndices); Merge(mMeshData->normals, fbxMeshData->mNormals); Merge(mMeshData->uvs, fbxMeshData->mUVs); Merge(mMeshData->tangents, fbxMeshData->mTangents); Merge(mMeshData->binormals, fbxMeshData->mBinormals); mMeshData->materialIdOffsets.clear(); } clear(); return mMeshData; }
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; }
bool FillData(ModelData* someData,FbxNode* aNode, AnimationData* aAnimation) { FbxMesh* mesh = aNode->GetMesh(); if (mesh == nullptr || !aNode) return false; const int lPolygonCount = mesh->GetPolygonCount(); // Count the polygon count of each material FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL; FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone; if (mesh->GetElementMaterial()) { lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray(); lMaterialMappingMode = mesh->GetElementMaterial()->GetMappingMode(); if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) { FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount); if (lMaterialIndice->GetCount() == lPolygonCount) { // Count the faces of each material for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); lMaterialIndex; /*if (someData->mSubMeshes[lMaterialIndex] == NULL) { someData->mSubMeshes[lMaterialIndex] = new ModelData::SubMesh; } someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;*/ } // Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen // if, in the loop above, we resized the mSubMeshes by more than one slot. /*for (int i = 0; i < someData->mSubMeshes.Count(); i++) { if (someData->mSubMeshes[i] == NULL) someData->mSubMeshes[i] = new ModelData::SubMesh; }*/ // Record the offset (how many vertex) const int lMaterialCount = someData->mSubMeshes.Size(); lMaterialCount; int lOffset = 0; /*for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) { someData->mSubMeshes[lIndex]->IndexOffset = lOffset; lOffset += someData->mSubMeshes[lIndex]->TriangleCount * 3; // This will be used as counter in the following procedures, reset to zero someData->mSubMeshes[lIndex]->TriangleCount = 0; }*/ FBX_ASSERT(lOffset == lPolygonCount * 3); } } } // All faces will use the same material. if (someData->mSubMeshes.Size() == 0) { if (someData->mSubMeshes.GetCapacity() == 0) { someData->mSubMeshes.Init(1); } someData->mSubMeshes.RemoveAll(); someData->mSubMeshes.AddEmptyObject(); someData->mSubMeshes[0] = new ModelData::SubMesh(); } bool hasNormalMap = false; const int lMaterialCount = aNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = aNode->GetMaterial(lMaterialIndex); if (lMaterial && !lMaterial->GetUserDataPtr()) { TextureInfo diffuseInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sDiffuse,FbxSurfaceMaterial::sDiffuseFactor,diffuseInfo.myFileName); diffuseInfo.myType = DIFFUSE; if(diffuseInfo.myFileName.empty() == false) { someData->myTextures.push_back(diffuseInfo); } TextureInfo normalInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sNormalMap,FbxSurfaceMaterial::sBumpFactor,normalInfo.myFileName); hasNormalMap = normalInfo.myFileName.empty() == false; normalInfo.myType = NORMALMAP; if(normalInfo.myFileName.empty() == false) { someData->myTextures.push_back(normalInfo); hasNormalMap = true; } TextureInfo roughnessInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sSpecular,FbxSurfaceMaterial::sSpecularFactor,roughnessInfo.myFileName); roughnessInfo.myType = ROUGHNESS; if(roughnessInfo.myFileName.empty() == false) { someData->myTextures.push_back(roughnessInfo); } TextureInfo substanceInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sReflection,FbxSurfaceMaterial::sReflectionFactor,substanceInfo.myFileName); substanceInfo.myType = SUBSTANCE; if(substanceInfo.myFileName.empty() == false) { someData->myTextures.push_back(substanceInfo); } TextureInfo ambientInfo; GetMaterialProperty(lMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, ambientInfo.myFileName); ambientInfo.myType = AO; if (substanceInfo.myFileName.empty() == false) { someData->myTextures.push_back(ambientInfo); } } } // Congregate all the data of a mesh to be cached in VBOs. // If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.' someData->mHasNormal = mesh->GetElementNormalCount() > 0; someData->mHasUV = mesh->GetElementUVCount() > 0; someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0; FbxSkin * lSkinDeformer = (FbxSkin *)mesh->GetDeformer(0, FbxDeformer::eSkin); someData->myHasSkinweights = lSkinDeformer != nullptr; if(hasNormalMap && someData->myHasBiNormal == false) { mesh->GenerateTangentsDataForAllUVSets(); someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0; } someData->myHasTangents = mesh->GetElementTangentCount() > 0; FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone; FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone; if (someData->mHasNormal) { lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode(); if (lNormalMappingMode == FbxGeometryElement::eNone) { someData->mHasNormal = false; } if (someData->mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint) { someData->mAllByControlPoint = false; } } if (someData->mHasUV) { lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode(); if (lUVMappingMode == FbxGeometryElement::eNone) { someData->mHasUV = false; } if (someData->mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint) { someData->mAllByControlPoint = false; } } // Allocate the array memory, by control point or by polygon vertex. int lPolygonVertexCount = mesh->GetControlPointsCount(); //if (!someData->my) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_POS; newLayout.mySize = VERTEX_STRIDE; newLayout.myOffset = 0; someData->myLayout.Add(newLayout); lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT; } int stride = VERTEX_STRIDE; size_t size = lPolygonVertexCount * VERTEX_STRIDE; //float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE]; unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT]; someData->myIndexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT; //float * lNormals = NULL; if (someData->mHasNormal) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_NORMAL; newLayout.mySize = NORMAL_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += NORMAL_STRIDE; size += lPolygonVertexCount * NORMAL_STRIDE; //lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE]; } //float * lUVs = NULL; FbxStringList lUVNames; mesh->GetUVSetNames(lUVNames); const char * lUVName = NULL; if (someData->mHasUV && lUVNames.GetCount()) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_UV; newLayout.mySize = UV_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += UV_STRIDE; size += lPolygonVertexCount * UV_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; lUVName = lUVNames[0]; } if (someData->myHasBiNormal) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_BINORMAL; newLayout.mySize = BINORMAL_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += BINORMAL_STRIDE; size += lPolygonVertexCount * BINORMAL_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } if (someData->myHasTangents) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_TANGENT; newLayout.mySize = TANGENT_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += TANGENT_STRIDE; size += lPolygonVertexCount * TANGENT_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } if (someData->myHasSkinweights) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_SKINWEIGHTS; newLayout.mySize = SKINWEIGHT_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += SKINWEIGHT_STRIDE; size += lPolygonVertexCount * SKINWEIGHT_STRIDE; newLayout.myType = ModelData::VERTEX_BONEID; newLayout.mySize = BONEID_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += BONEID_STRIDE; size += lPolygonVertexCount * BONEID_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } float * lVertices = new float[size]; FbxAMatrix globalPos; FbxVector4* weights = nullptr; FbxVectorTemplate4<int>* bones = nullptr; FbxTime time = static_cast<FbxTime>(0.0f); if(someData->myHasSkinweights) { weights = new FbxVector4[mesh->GetControlPointsCount()]; bones = new FbxVectorTemplate4<int>[mesh->GetControlPointsCount()]; ComputeLinearDeformation(globalPos,mesh,weights,bones,aAnimation); } const FbxGeometryElementBinormal * lBiNormalElement = NULL; const FbxGeometryElementTangent * lTangentElement = NULL; if (someData->myHasBiNormal) { lBiNormalElement = mesh->GetElementBinormal(0); } if (someData->myHasTangents) { lTangentElement = mesh->GetElementTangent(0); } // Populate the array with vertex attribute, if by control point. const FbxVector4 * lControlPoints = mesh->GetControlPoints(); FbxVector4 lCurrentVertex; FbxVector4 lCurrentNormal; FbxVector4 lCurrentBiNormal; FbxVector4 lCurrentTangent; FbxVector2 lCurrentUV; if (someData->mAllByControlPoint) { const FbxGeometryElementNormal * lNormalElement = NULL; const FbxGeometryElementUV * lUVElement = NULL; if (someData->mHasNormal) { lNormalElement = mesh->GetElementNormal(0); } if (someData->mHasUV) { lUVElement = mesh->GetElementUV(0); } for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex) { int currentIndex = lIndex * stride; int addedSize = VERTEX_STRIDE; // Save the vertex position. lCurrentVertex = lControlPoints[lIndex]; CU::Vector4f position(static_cast<float>(lCurrentVertex[0]), static_cast<float>(lCurrentVertex[1]), static_cast<float>(lCurrentVertex[2]), 1); CU::Matrix44f fixMatrix; fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1,0,0)); position = position*fixMatrix; lVertices[currentIndex] = position.x; lVertices[currentIndex + 1] = position.y; lVertices[currentIndex + 2] = position.z; lVertices[currentIndex + 3] = 1; // Save the normal. if (someData->mHasNormal) { int lNormalIndex = lIndex; if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex); } lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex); CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += NORMAL_STRIDE; } // Save the UV. if (someData->mHasUV) { int lUVIndex = lIndex; if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex); } lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex); lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f; addedSize += 2; } if (someData->myHasBiNormal) { int lBinormIndexIndex = lIndex; if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lIndex); } lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex); //mesh->GetElementBinormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); //lCurrentNormal = lCurrentNormal CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += BINORMAL_STRIDE; } if (someData->myHasTangents) { int lBinormIndexIndex = lIndex; if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lIndex); } lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex); //lCurrentNormal = lCurrentNormal CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += TANGENT_STRIDE; } if(someData->myHasSkinweights) { FbxVector4 currentWeights = weights[lIndex]; //currentWeights.Normalize(); lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]); addedSize += SKINWEIGHT_STRIDE; FbxVectorTemplate4<int> currentBones = bones[lIndex]; lVertices[currentIndex + addedSize] = static_cast<float>(currentBones[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentBones[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentBones[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentBones[3]); addedSize += BONEID_STRIDE; } } } int lVertexCount = 0; for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { // The material for current face. int lMaterialIndex = 0; if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) { lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); } // Where should I save the vertex attribute index, according to the material const int lIndexOffset = someData->mSubMeshes[lMaterialIndex]->IndexOffset + someData->mSubMeshes[lMaterialIndex]->TriangleCount * 3; for (int lVerticeIndex = TRIANGLE_VERTEX_COUNT-1; lVerticeIndex > -1; --lVerticeIndex) { const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex); int vertexIndex = lIndexOffset + (TRIANGLE_VERTEX_COUNT-1) - lVerticeIndex; if (someData->mAllByControlPoint) { lIndices[vertexIndex] = static_cast<unsigned int>(lControlPointIndex); } // Populate the array with vertex attribute, if by polygon vertex. else { lIndices[vertexIndex] = static_cast<unsigned int>(lVertexCount); lCurrentVertex = lControlPoints[lControlPointIndex]; int addedSize = VERTEX_STRIDE; int currentIndex = lVertexCount * stride; CU::Vector4f position(static_cast<float>(lCurrentVertex[0]), static_cast<float>(lCurrentVertex[1]), static_cast<float>(lCurrentVertex[2]), 1); //fixMatrix CU::Matrix44f fixMatrix; fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); position = position*fixMatrix; lVertices[currentIndex] = position.x; lVertices[currentIndex + 1] = position.y; lVertices[currentIndex + 2] = position.z; lVertices[currentIndex + 3] = 0; if (someData->mHasNormal) { mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += NORMAL_STRIDE; } if (someData->mHasUV) { bool lUnmappedUV; mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV); lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f; addedSize += UV_STRIDE; } if (someData->myHasBiNormal) { int lBinormIndexIndex = lVerticeIndex; if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lVerticeIndex); } lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex); CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += BINORMAL_STRIDE; } if (someData->myHasTangents) { int lBinormIndexIndex = lVerticeIndex; if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lVerticeIndex); } lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex); mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += TANGENT_STRIDE; } if(someData->myHasSkinweights) { FbxVector4 currentWeights = weights[lControlPointIndex]; FbxVectorTemplate4<int> currentBones = bones[lControlPointIndex]; for(int l = 0;l < 4;++l) { if(currentBones[l] == -1) { currentWeights[l] = 0.0f; } } currentWeights.Normalize(); lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]); addedSize += SKINWEIGHT_STRIDE; lVertices[currentIndex + addedSize] = *(float*)¤tBones[0]; lVertices[currentIndex + addedSize + 1] = *(float*)¤tBones[1]; lVertices[currentIndex + addedSize + 2] = *(float*)¤tBones[2]; lVertices[currentIndex + addedSize + 3] = *(float*)¤tBones[3]; addedSize += BONEID_STRIDE; } } ++lVertexCount; } someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1; } someData->myVertexCount = lVertexCount; someData->myVertexStride = stride; someData->myVertexBuffer = lVertices; someData->myIndicies = lIndices; if(weights) { delete [] weights; delete [] bones; } return true; }
void fbxLoader2::processMesh(FbxNode* node) { FbxMesh* mesh = node->GetMesh(); this->readAnimationWeigths(mesh); if(mesh!=NULL && mesh->IsTriangleMesh()) { for (int i = 0; i<mesh->GetControlPointsCount(); i++) { readVertex(mesh, i, &vertex[i]); vertexArray[i].position = D3DXVECTOR3(vertex[i]); } int a = mesh->GetPolygonVertexCount(); for (int i = 0; i<mesh->GetPolygonVertexCount(); i++) { readUV(mesh, i, 0, &uv[i]); readNormal(mesh, i, &normal[i]); indices[i].indice = mesh->GetPolygonVertices()[i]; indices[i].normal1 = normal[i]; indices[i].uv1 = uv[i]; indicesMeshCount++; } } //vertexLists.push_back(vertexArray); indiceLists.push_back(indices); FbxAnimStack* pAnimStack = FbxCast<FbxAnimStack>(scene->GetSrcObject(FBX_TYPE(FbxAnimStack))); int numAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(FbxAnimLayer)); this->setBindPoseCluster(node); for (int i = 0; i < numAnimLayers; i++) { FbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(FbxAnimLayer), i); FbxAnimCurve* animCv = this->findSkeletonRootBone(scene->GetRootNode())->GetChild(0)->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X); if (animCv) { FbxTimeSpan animationLength; int p = animCv->KeyGetCount(); animCv->GetTimeInterval(animationLength); for(int j = 0; j<animationStructure->GetFramesNumber();j++) { FbxTime timeKey = animCv->KeyGet(j).mTime; //FbxTime interval = (duration/p)*j + animationLength.GetStart(); //int intervalVal = (duration.GetSecondCount()/p)*j + animationLength.GetStart().GetSecondCount(); const FbxTime pTime = animCv->KeyGet(j).mTime; FbxAMatrix pGlobalPos = GetGlobalPosition(node, pTime, scene->GetPose(j)); ComputeSkinDeformation(pGlobalPos, mesh, timeKey, scene->GetPose(j), j); } } } for(int i = 0; i<node->GetChildCount(); i++) { processMesh(node->GetChild(i)); } }
Model* FbxModelLoader::LoadModel(const char* fileName) { Model* model = nullptr; if (!m_importer->Initialize(fileName, -1, m_manager->GetIOSettings())) { return nullptr; } FbxScene* lScene = FbxScene::Create(m_manager, "myscene"); m_importer->Import(lScene); FbxNode* lRootNode = lScene->GetRootNode(); if (lRootNode) { if (lRootNode->GetChildCount() > 0) { FbxNode* lNode = lRootNode->GetChild(0); FbxMesh* lMesh = lNode->GetMesh(); if (!lMesh) return nullptr; std::ofstream file; file.open("DataFromFbxVector.txt"); char* buffer = new char[1024]; sprintf_s(buffer, 1024, "Number of children in Root: %d\n\n\n\n", lRootNode->GetChildCount()); file << buffer; if (lMesh->IsTriangleMesh()) file << "It's a triangle mesh!"; else file << "It's NOT a triangle mesh!"; FbxVector4* vertexArray = lMesh->GetControlPoints(); for (int i = 0; i < lMesh->GetControlPointsCount(); i++) { sprintf(buffer, "(%f, %f, %f)\n", vertexArray[i].mData[0], vertexArray[i].mData[1], vertexArray[i].mData[2]); file << buffer; } delete buffer; file.close(); Polygon* polygons = new Polygon[lMesh->GetPolygonCount()]; int polygonCount = lMesh->GetPolygonCount(); int index = 0; buffer = new char[1024]; file.open("DataFromPolygons.txt"); for (int i = 0; i < lMesh->GetPolygonCount(); i++) { index = lMesh->GetPolygonVertex(i, 0); sprintf(buffer, "\n\nPolygon #%d\nPolygon Vertex Index #%d: ", i, index); file << buffer; polygons[i].vertex1.x = (float)vertexArray[index].mData[0]; polygons[i].vertex1.y = (float)vertexArray[index].mData[1]; polygons[i].vertex1.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex1.x, polygons[i].vertex1.y, polygons[i].vertex1.z); file << buffer; index = lMesh->GetPolygonVertex(i, 1); sprintf(buffer, "Polygon Vertex Index #%d: ", index); file << buffer; polygons[i].vertex2.x = (float)vertexArray[index].mData[0]; polygons[i].vertex2.y = (float)vertexArray[index].mData[1]; polygons[i].vertex2.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex2.x, polygons[i].vertex2.y, polygons[i].vertex2.z); file << buffer; index = lMesh->GetPolygonVertex(i, 2); sprintf(buffer, "Polygon Vertex Index #%d: ", index); file << buffer; polygons[i].vertex3.x = (float)vertexArray[index].mData[0]; polygons[i].vertex3.y = (float)vertexArray[index].mData[1]; polygons[i].vertex3.z = (float)vertexArray[index].mData[2]; sprintf(buffer, "(%f, %f, %f)\n", polygons[i].vertex3.x, polygons[i].vertex3.y, polygons[i].vertex3.z); file << buffer; } file.close(); delete buffer; model = new Model(); model->Vertices = new DirectX::XMFLOAT3[polygonCount * 3]; model->NumVertices = polygonCount * 3; file.open("DataFromPolygonToModelTransfer.txt"); buffer = new char[1024]; for (int i = 0; i < lMesh->GetPolygonCount() * 3; i += 3) { model->Vertices[i] = polygons[i/3].vertex1; model->Vertices[i+1] = polygons[i/3].vertex2; model->Vertices[i+2] = polygons[i/3].vertex3; sprintf_s(buffer, 1024, "Polygon #%d:\n(%f, %f, %f)\n(%f, %f, %f)\n(%f, %f, %f)\n\n" , i / 3 , model->Vertices[i].x, model->Vertices[i].y, model->Vertices[i].z , model->Vertices[i+1].x, model->Vertices[i+1].y, model->Vertices[i+1].z , model->Vertices[i+2].x, model->Vertices[i+2].y, model->Vertices[i+2].z); file << buffer; } delete buffer; file.close(); // delete [] polygons; } else return nullptr; } else return nullptr; return model; }
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); } }
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 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 FbxLoader::LoadAttribute(FbxNodeAttribute* pAttribute) { if (pAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* pMesh = (FbxMesh*)pAttribute; FbxVector4* IControlPoints = pMesh->GetControlPoints(); m_vertexCount = pMesh->GetControlPointsCount(); m_vertexBuffer = new float[m_vertexCount * 4]; for (int i = 0; i < m_vertexCount * 4; i+=4) { m_vertexBuffer[i] = (float)IControlPoints[i / 4].mData[0]; m_vertexBuffer[i + 1] = (float)IControlPoints[i / 4].mData[1]; m_vertexBuffer[i + 2] = (float)IControlPoints[i / 4].mData[2]; m_vertexBuffer[i + 3] = 1.0f;// IControlPoints[i / 4].mData[3]; } int* pIndices = pMesh->GetPolygonVertices(); m_indexCount = pMesh->GetPolygonVertexCount(); m_indexBuffer = new uint32[m_indexCount]; for (int i = 0; i < m_indexCount; ++i) { m_indexBuffer[i] = pIndices[i]; } FbxLayer* pLayer = pMesh->GetLayer(0); if (pLayer != NULL) { FbxLayerElementNormal* pNormal = pLayer->GetNormals(); m_normalCount = pNormal->mDirectArray->GetCount(); m_normalBuffer = new float[m_normalCount * 3]; for (int i = 0; i < m_normalCount * 3; i+=3) { m_normalBuffer[i] = (float)(*pNormal->mDirectArray)[i / 3][0]; m_normalBuffer[i + 1] = (float)(*pNormal->mDirectArray)[i / 3][1]; m_normalBuffer[i + 2] = (float)(*pNormal->mDirectArray)[i / 3][2]; //m_normalBuffer[i + 3] = (*pNormal->mDirectArray)[i / 4][3]; } FbxLayerElementUV* pUV = pLayer->GetUVs(); if (pUV->GetMappingMode() == FbxLayerElement::eByPolygonVertex) { if (pUV->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { m_uvCount = pUV->mIndexArray->GetCount(); m_uvBuffer = new float[m_uvCount * 2]; for (int i = 0; i < m_uvCount * 2; i+=2) { m_uvBuffer[i] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][0]; m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][1]; } } else { m_uvCount = pUV->mDirectArray->GetCount(); m_uvBuffer = new float[m_uvCount * 2]; for (int i = 0; i < m_uvCount * 2; i += 2) { m_uvBuffer[i] = (float)(*pUV->mDirectArray)[i / 2][0]; m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[i / 2][1]; } } } else { if (pUV->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { m_uvCount = pUV->mIndexArray->GetCount(); m_uvBuffer = new float[m_uvCount * 2]; for (int i = 0; i < m_uvCount * 2; i+=2) { m_uvBuffer[i] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][0]; m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][1]; } } else { m_uvCount = pUV->mDirectArray->GetCount(); m_uvBuffer = new float[m_uvCount * 2]; for (int i = 0; i < m_uvCount * 2; i+=2) { m_uvBuffer[i] = (float)(*pUV->mDirectArray)[i / 2][0]; m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[i / 2][1]; } } } } } }