diff --git a/KREngine/KREngine/Classes/KRResource+fbx.cpp b/KREngine/KREngine/Classes/KRResource+fbx.cpp index 72d95a9..f2dcf49 100644 --- a/KREngine/KREngine/Classes/KRResource+fbx.cpp +++ b/KREngine/KREngine/Classes/KRResource+fbx.cpp @@ -276,24 +276,205 @@ void LoadMesh(std::vector &resources, KFbxGeometryConverter *pGeom KFbxVector4* control_points = pMesh->GetControlPoints(); int polygon_count = pMesh->GetPolygonCount(); + int uv_count = pMesh->GetElementUVCount(); + int normal_count = pMesh->GetElementNormalCount(); + int tangent_count = pMesh->GetElementTangentCount(); + int material_count = pMesh->GetElementMaterialCount(); + printf(" Polygon Count: %i (before triangulation: %i)\n", polygon_count, pSourceMesh->GetPolygonCount()); std::vector vertices; std::vector uva; + std::vector uvb; std::vector normals; std::vector tangents; std::vector submesh_lengths; std::vector submesh_starts; std::vector material_names; + + int source_vertex_id = 0; + int dest_vertex_id = 0; + KFbxGeometryElementMaterial* pMaterial = NULL; + int iMaterial = -1; + int mat_vertex_count = 0; + int mat_vertex_start = 0; + for(int iPolygon = 0; iPolygon < polygon_count; iPolygon++) { int lPolygonSize = pMesh->GetPolygonSize(iPolygon); if(lPolygonSize != 3) { - assert(lPolygonSize == 3); + source_vertex_id += lPolygonSize; + printf(" Warning - Poly with %i vertices found. Expecting only triangles.", lPolygonSize); + } else { + // ----====---- Read SubMesh / Material Mapping ----====---- + int iPrevMat = iMaterial; + KFbxGeometryElementMaterial *pPrevMat = pMaterial; + iMaterial = -1; + pMaterial = NULL; + for (int l = 0; l < material_count; l++) + { + KFbxGeometryElementMaterial* leMat = pMesh->GetElementMaterial(l); + if(leMat) { + if (leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX || leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX_TO_DIRECT) { + int new_id = leMat->GetIndexArray().GetAt(iPolygon); + if(new_id >= 0) { + iMaterial = new_id; + pMaterial = leMat; + } + } + } + } + + if(iMaterial != iPrevMat) { + if(pPrevMat && mat_vertex_count) { + submesh_starts.push_back(mat_vertex_start); + submesh_lengths.push_back(mat_vertex_count); + material_names.push_back(pNode->GetMaterial(iMaterial)->GetName()); + printf(" Material \"%s\" from %i to %i\n", pNode->GetMaterial(iMaterial)->GetName(), mat_vertex_start, mat_vertex_count + mat_vertex_start - 1); + } + + mat_vertex_count = 0; + mat_vertex_start = dest_vertex_id; + } + + + + // ----====---- Read Vertex-level Attributes ----====---- + for(int iVertex=0; iVertex<3; iVertex++) { + // ----====---- Read Vertex Position ----====---- + int lControlPointIndex = pMesh->GetPolygonVertex(iPolygon, iVertex); + KFbxVector4 v = control_points[lControlPointIndex]; + vertices.push_back(KRVector3(v[0], v[1], v[2])); + + + // ----====---- Read UVs ----====---- + for (int l = 0; l < uv_count; ++l) + { + KFbxVector2 uv; + KFbxGeometryElementUV* leUV = pMesh->GetElementUV(l); + + switch (leUV->GetMappingMode()) { + case KFbxGeometryElement::eBY_CONTROL_POINT: + switch (leUV->GetReferenceMode()) { + case KFbxGeometryElement::eDIRECT: + uv = leUV->GetDirectArray().GetAt(lControlPointIndex); + break; + case KFbxGeometryElement::eINDEX_TO_DIRECT: + { + int id = leUV->GetIndexArray().GetAt(lControlPointIndex); + uv = leUV->GetDirectArray().GetAt(id); + } + break; + default: + break; // other reference modes not shown here! + } + break; + + case KFbxGeometryElement::eBY_POLYGON_VERTEX: + { + int lTextureUVIndex = pMesh->GetTextureUVIndex(iPolygon, iVertex); + switch (leUV->GetReferenceMode()) + { + case KFbxGeometryElement::eDIRECT: + case KFbxGeometryElement::eINDEX_TO_DIRECT: + { + uv = leUV->GetDirectArray().GetAt(lTextureUVIndex); + } + break; + default: + break; // other reference modes not shown here! + } + } + break; + + case KFbxGeometryElement::eBY_POLYGON: // doesn't make much sense for UVs + case KFbxGeometryElement::eALL_SAME: // doesn't make much sense for UVs + case KFbxGeometryElement::eNONE: // doesn't make much sense for UVs + break; + } + + if(l == 0) { + uva.push_back(KRVector2(uv[0], uv[1])); + } else if(l == 1) { + uvb.push_back(KRVector2(uv[0], uv[1])); + } + } + + // ----====---- Read Normals ----====---- + for(int l = 0; l < normal_count; ++l) + { + KFbxVector4 new_normal; + KFbxGeometryElementNormal* leNormal = pMesh->GetElementNormal(l); + + if(leNormal->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX) { + switch (leNormal->GetReferenceMode()) + { + case KFbxGeometryElement::eDIRECT: + new_normal = leNormal->GetDirectArray().GetAt(source_vertex_id); + break; + case KFbxGeometryElement::eINDEX_TO_DIRECT: + { + int id = leNormal->GetIndexArray().GetAt(source_vertex_id); + new_normal = leNormal->GetDirectArray().GetAt(id); + } + break; + default: + break; // other reference modes not shown here! + } + } + if(l == 0) { + normals.push_back(KRVector3(new_normal[0], new_normal[1], new_normal[2])); + } + + } + + // ----====---- Read Tangents ----====---- + for(int l = 0; l < tangent_count; ++l) + { + KFbxVector4 new_tangent; + KFbxGeometryElementTangent* leTangent = pMesh->GetElementTangent(l); + + if(leTangent->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX) { + switch (leTangent->GetReferenceMode()) { + case KFbxGeometryElement::eDIRECT: + new_tangent = leTangent->GetDirectArray().GetAt(source_vertex_id); + break; + case KFbxGeometryElement::eINDEX_TO_DIRECT: + { + int id = leTangent->GetIndexArray().GetAt(source_vertex_id); + new_tangent = leTangent->GetDirectArray().GetAt(id); + } + break; + default: + break; // other reference modes not shown here! + } + } + if(l == 0) { + tangents.push_back(KRVector3(new_tangent[0], new_tangent[1], new_tangent[2])); + } + + } + + + + source_vertex_id++; + dest_vertex_id++; + mat_vertex_count++; + } } } + // ----====---- Complete last material / submesh ----====---- + if(iMaterial >= 0 && mat_vertex_count) { + submesh_starts.push_back(mat_vertex_start); + submesh_lengths.push_back(mat_vertex_count); + material_names.push_back(pNode->GetMaterial(iMaterial)->GetName()); + printf(" Material \"%s\" from %i to %i\n", pNode->GetMaterial(iMaterial)->GetName(), mat_vertex_start, mat_vertex_count + mat_vertex_start - 1); + } + + + // ----====---- Generate Output Mesh Object ----====---- KRMesh *new_mesh = new KRMesh(pNode->GetName()); new_mesh->LoadData(vertices, uva, normals, tangents, submesh_starts, submesh_lengths, material_names);