OpenGL加载FBX模型显示异常,寻求技术解决方案
Hey there, let's dig into why your FBX model is showing up wonky in OpenGL. I've gone through your code and spotted a couple of critical issues that are causing the abnormal rendering. Let's break them down and fix them step by step.
1. Your Normal Retrieval Isn't Handling FBX's Data Structure Correctly
This is probably the biggest reason your model looks off. FBX stores normals with different mapping and reference modes—you can't just grab them directly by vertex counter like you're doing. You need to account for whether normals are mapped per control point or per polygon vertex, and if there's an index array involved.
Here's the corrected code to pull normals properly:
FbxGeometryElementNormal* normalEl = mesh->GetElementNormal(); if(normalEl) { int numNormals = mesh->GetPolygonCount() * 3; normals = new float[numNormals * 3]; int vertexCounter = 0; for(int polyCounter = 0; polyCounter < mesh->GetPolygonCount(); polyCounter++) { // We'll stick with triangles since your rendering code assumes that for(int k = 0; k < 3; k++) { int controlPointIdx = mesh->GetPolygonVertex(polyCounter, k); FbxVector4 normal; // Handle per-control-point normals if(normalEl->GetMappingMode() == FbxGeometryElement::eByControlPoint) { if(normalEl->GetReferenceMode() == FbxGeometryElement::eDirect) { normal = normalEl->GetDirectArray().GetAt(controlPointIdx); } else if(normalEl->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) { int normalIndex = normalEl->GetIndexArray().GetAt(controlPointIdx); normal = normalEl->GetDirectArray().GetAt(normalIndex); } } // Handle per-polygon-vertex normals (common for smoothed meshes) else if(normalEl->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) { int polyVertIndex = mesh->GetPolygonVertexIndex(polyCounter, k); if(normalEl->GetReferenceMode() == FbxGeometryElement::eDirect) { normal = normalEl->GetDirectArray().GetAt(polyVertIndex); } else if(normalEl->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) { int normalIndex = normalEl->GetIndexArray().GetAt(polyVertIndex); normal = normalEl->GetDirectArray().GetAt(normalIndex); } } normals[vertexCounter*3] = (float)normal[0]; normals[vertexCounter*3+1] = (float)normal[1]; normals[vertexCounter*3+2] = (float)normal[2]; vertexCounter++; } } }
2. Your Render Loop Is Drawing Overlapping Triangles
Right now, your loop increments i by 1 each time, which means you're drawing triangles with indices [0,1,2], then [1,2,3], then [2,3,4], etc.—that's creating a mess of overlapping, incorrect geometry. Instead, you need to step through the indices 3 at a time since each triangle uses exactly 3 indices:
// Fix the rendering loop to draw proper triangles for(int i = 0; i < numIndices; i += 3) { glBegin(GL_TRIANGLES); // Assign the correct normal and vertex for each corner of the triangle for(int j = 0; j < 3; j++) { int currentIdx = i + j; glNormal3f(normals[currentIdx*3], normals[currentIdx*3+1], normals[currentIdx*3+2]); int vertIdx = indices[currentIdx]; glVertex3f(vertices[vertIdx].x, vertices[vertIdx].y, vertices[vertIdx].z); glColor3f(0.3f, 0.3f, 0.3f); } glEnd(); }
3. Quick Additional Checks to Rule Out Other Issues
- Double-check that
numVerticesstarts at 0 before you populate the vertices array—if it's initialized to something else, you'll be writing to the wrong spots in the array. - If your FBX model has n-gons (polygons with more than 3 sides), you'll need to triangulate it first using
FbxGeometryConverter::TriangulateMesh()—your current code assumes all polygons are triangles. - Make sure you've enabled OpenGL depth testing with
glEnable(GL_DEPTH_TEST)—without it, faces will draw on top of each other regardless of their position in 3D space, which makes models look broken. - If you're using lighting, ensure
glEnable(GL_LIGHTING)andglEnable(GL_LIGHT0)are turned on—otherwise, your normals won't affect the rendering.
内容的提问来源于stack exchange,提问作者Buttburger

