FBX File import now re-orders vertices and batches all materials together to reduce draw calls

--HG--
extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%4020
This commit is contained in:
kearwood
2012-03-28 19:34:52 +00:00
parent 6edc77e32b
commit b7c8ae001b

View File

@@ -279,7 +279,8 @@ void LoadMesh(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeom
int uv_count = pMesh->GetElementUVCount(); int uv_count = pMesh->GetElementUVCount();
int normal_count = pMesh->GetElementNormalCount(); int normal_count = pMesh->GetElementNormalCount();
int tangent_count = pMesh->GetElementTangentCount(); int tangent_count = pMesh->GetElementTangentCount();
int material_count = pMesh->GetElementMaterialCount(); int elementmaterial_count = pMesh->GetElementMaterialCount();
int material_count = pNode->GetMaterialCount();
printf(" Polygon Count: %i (before triangulation: %i)\n", polygon_count, pSourceMesh->GetPolygonCount()); printf(" Polygon Count: %i (before triangulation: %i)\n", polygon_count, pSourceMesh->GetPolygonCount());
@@ -293,185 +294,170 @@ void LoadMesh(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeom
std::vector<int> submesh_starts; std::vector<int> submesh_starts;
std::vector<std::string> material_names; std::vector<std::string> material_names;
int source_vertex_id = 0;
int dest_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++) { for(int iMaterial=0; iMaterial < material_count; iMaterial++) {
int lPolygonSize = pMesh->GetPolygonSize(iPolygon); int source_vertex_id = 0;
if(lPolygonSize != 3) { int mat_vertex_count = 0;
source_vertex_id += lPolygonSize; int mat_vertex_start = dest_vertex_id;
printf(" Warning - Poly with %i vertices found. Expecting only triangles.", lPolygonSize); for(int iPolygon = 0; iPolygon < polygon_count; iPolygon++) {
} else { int lPolygonSize = pMesh->GetPolygonSize(iPolygon);
// ----====---- Read SubMesh / Material Mapping ----====---- if(lPolygonSize != 3) {
int iPrevMat = iMaterial; source_vertex_id += lPolygonSize;
KFbxGeometryElementMaterial *pPrevMat = pMaterial; printf(" Warning - Poly with %i vertices found. Expecting only triangles.", lPolygonSize);
iMaterial = -1; } else {
pMaterial = NULL; // ----====---- Read SubMesh / Material Mapping ----====----
for (int l = 0; l < material_count; l++) int iNewMaterial = -1;
{ for (int l = 0; l < elementmaterial_count; l++)
KFbxGeometryElementMaterial* leMat = pMesh->GetElementMaterial(l); {
if(leMat) { KFbxGeometryElementMaterial* leMat = pMesh->GetElementMaterial(l);
if (leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX || leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX_TO_DIRECT) { if(leMat) {
int new_id = leMat->GetIndexArray().GetAt(iPolygon); if (leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX || leMat->GetReferenceMode() == KFbxGeometryElement::eINDEX_TO_DIRECT) {
if(new_id >= 0) { int new_id = leMat->GetIndexArray().GetAt(iPolygon);
iMaterial = new_id; if(new_id >= 0) {
pMaterial = leMat; iNewMaterial = new_id;
}
} }
} }
} }
}
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; if(iMaterial == iNewMaterial) {
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];
// ----====---- Read Vertex-level Attributes ----====---- vertices.push_back(KRVector3(v[0], v[1], v[2]));
for(int iVertex=0; iVertex<3; iVertex++) {
// ----====---- Read Vertex Position ----====----
int lControlPointIndex = pMesh->GetPolygonVertex(iPolygon, iVertex); // ----====---- Read UVs ----====----
KFbxVector4 v = control_points[lControlPointIndex]; for (int l = 0; l < uv_count; ++l)
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); KFbxVector2 uv;
switch (leUV->GetReferenceMode()) KFbxGeometryElementUV* leUV = pMesh->GetElementUV(l);
{
case KFbxGeometryElement::eDIRECT: switch (leUV->GetMappingMode()) {
case KFbxGeometryElement::eINDEX_TO_DIRECT: case KFbxGeometryElement::eBY_CONTROL_POINT:
{ switch (leUV->GetReferenceMode()) {
uv = leUV->GetDirectArray().GetAt(lTextureUVIndex); 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; break;
default:
break; // other reference modes not shown here! 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;
} }
}
break;
case KFbxGeometryElement::eBY_POLYGON: // doesn't make much sense for UVs if(l == 0) {
case KFbxGeometryElement::eALL_SAME: // doesn't make much sense for UVs uva.push_back(KRVector2(uv[0], uv[1]));
case KFbxGeometryElement::eNONE: // doesn't make much sense for UVs } else if(l == 1) {
break; uvb.push_back(KRVector2(uv[0], uv[1]));
} }
}
if(l == 0) {
uva.push_back(KRVector2(uv[0], uv[1])); // ----====---- Read Normals ----====----
} else if(l == 1) { for(int l = 0; l < normal_count; ++l)
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: KFbxVector4 new_normal;
new_normal = leNormal->GetDirectArray().GetAt(source_vertex_id); KFbxGeometryElementNormal* leNormal = pMesh->GetElementNormal(l);
break;
case KFbxGeometryElement::eINDEX_TO_DIRECT: if(leNormal->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX) {
{ switch (leNormal->GetReferenceMode())
int id = leNormal->GetIndexArray().GetAt(source_vertex_id); {
new_normal = leNormal->GetDirectArray().GetAt(id); 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!
}
} }
break; if(l == 0) {
default: normals.push_back(KRVector3(new_normal[0], new_normal[1], new_normal[2]));
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) { // ----====---- Read Tangents ----====----
tangents.push_back(KRVector3(new_tangent[0], new_tangent[1], new_tangent[2])); 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++; source_vertex_id++;
dest_vertex_id++; dest_vertex_id++;
mat_vertex_count++; mat_vertex_count++;
}
}
} }
} }
// ----====---- Output last material / submesh details ----====----
if(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(" %s: %i - %i\n", pNode->GetMaterial(iMaterial)->GetName(), mat_vertex_start, mat_vertex_count + mat_vertex_start - 1);
}
} }
// ----====---- 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 ----====---- // ----====---- Generate Output Mesh Object ----====----