Jump to content
  • Advertisement
Sign in to follow this  
furrymaster

[FBX SDK]Prolem with getting coords and normals

This topic is 3017 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, i have problem with getting tex coords and normals from KFbxMesh class. I read(some days ago) that coords and normals are kept in layers of mesh, but how can i take them for one object? i Mean i have tab of verices, indices and now i would like to have tab of coords and tab of normals. How to do that?
Thanks, for any useful advices.

Share this post


Link to post
Share on other sites
Advertisement
I actually had the same problem a few weeks ago but fortunately managed to figure it out. The FBX SDK seems to really be lacking in documentation, so it took a lot of guesswork. Anyway, take a look at my code in this post.

Share this post


Link to post
Share on other sites
I saw it before and it was so useful but sometimes i get
Quote:
"Error: invalid normal mapping mode"


And your code has 1 issue: if object doesn`t have normals u r "continue;" loop( i mean u jump to next step of loop)

Share this post


Link to post
Share on other sites
Have you tried KFbxMesh->GetPolygonVertexNormal() for getting the normals? Haven't tested it too mutch, but seems to work so far. If the mesh doesn't have normals you could try KFbxMesh->InitNormals() and KFbxMesh->ComputeNormals() and let the SDK generate them or just compute them yourself once the mesh is fully loaded.

For texture coordinates things are a little bit more complicated, as there is no other way then extracting them from the layers and work out the mapping/reference modes. It's the same as for normals in Gumgos example.

As for other examples of working with the FBX SDK, the best I've found so far is the ContentExporter sample that comes with the latest DirectX SDK. Seems to be quite complete when it comes to extracting the relevant information thats needed for realtime rendering.

Share this post


Link to post
Share on other sites
I really don`t know how to use GetPolygonVertexNormal(). For extracting vertices for example i use mesh->GetControlPoints(), so its another way than GetPolygonVertexNormal(). Can u show me example how to use it?

And.. umh with your code I`m getting bad coords... Code:

struct F3Dbone
{
F3Dbone(std::string name_="", float* v_=0, float* c_=0, float* n_=0,unsigned int *idx_=0,unsigned int polyCount_=0,unsigned int icount=0,fMaterial *mat_=NULL):
name(name_),v(v_),c(c_),n(n_),idx(idx_),polyCount(polyCount_),iCount(icount),mat(mat_){};
std::string name;
float *v,*c,*n;
unsigned int *idx,polyCount,iCount;
fMaterial *mat;
};
void GetFBXSDKNodes(vector<F3Dbone> &bones,KFbxNode* node)
{
if(node==NULL)return;

for(int i=0;i<node->GetChildCount();i++)
{
GetFBXSDKNodes(bones,node->GetChild(i));
}
if(node->GetChildCount()>1)return;

KFbxMesh *mesh=node->GetMesh();
if(mesh==NULL)
return;
if (!mesh->IsTriangleMesh())
{
KFbxGeometryConverter converter ( mySdkManager );
mesh = converter.TriangulateMesh ( mesh );
}

F3Dbone bone;
bone.v=new float[mesh->GetControlPointsCount()*3];
bone.c=new float[mesh->GetControlPointsCount()*2];
bone.n=new float[mesh->GetControlPointsCount()*3];
bone.polyCount=mesh->GetControlPointsCount();
////////////////CHECK FOR INIT NORMALS
bool initedNormals=0;
for(int i=0;i<mesh->GetLayerCount();i++)
{
if(mesh->GetLayer( i )->GetNormals()!=NULL)
{
initedNormals=true;
break;
}
}
if(!initedNormals)
{
mesh->InitNormals();
mesh->ComputeVertexNormals();
}
/////////////////////////////////////////VERTICES
KFbxVector4 *vertex_data = mesh->GetControlPoints();
for( int i = 0; i < bone.polyCount; i++ )
{
for(int j=0;j<3;j++)
{
bone.v[i*3+j]=vertex_data.GetAt(j);
}
}

/////////////////////////////INDICES
int face_count=mesh->GetPolygonCount();
bone.iCount=0;
for(int i=0;i<face_count;i++)
{
for ( int j = 0; j < mesh->GetPolygonSize(i);j++)
bone.iCount++;
}
bone.idx=new unsigned int[bone.iCount];
int counter = 0;
for ( int i = 0; i < face_count; i++ )
{
int face_size = mesh->GetPolygonSize ( i );
for ( int j = 0; j < face_size; j++ )
{
bone.idx[counter] = mesh->GetPolygonVertex ( i, j );
counter++;
}
}
bool texCoordsFound = false;
bool normalsFound = false;
bool error=false;
for(int q=0;q<mesh->GetLayerCount();q++)
{
KFbxLayerElementUV * texCoords = texCoordsFound ? NULL : mesh->GetLayer( q )->GetUVs();
KFbxLayerElementNormal * normals = normalsFound ? NULL : mesh->GetLayer( q )->GetNormals();
for (int i = 0; i < face_count; ++i)
{
for (int v = 0; v < 3; ++v)
{
int positionIndex = mesh->GetPolygonVertexIndex( i ) + v;
if (texCoords != NULL)
{
texCoordsFound = true;
switch (texCoords->GetMappingMode()) {
case KFbxLayerElement::eBY_CONTROL_POINT:
switch (texCoords->GetReferenceMode()) {
case KFbxLayerElement::eDIRECT:
for (int p = 0; p < 2; ++p)////bone.idx*3- calculate poly , v*2 - calculate vert , p - UV
bone.c[bone.idx*3+v*2+p] = (float)texCoords->GetDirectArray().GetAt( positionIndex )

;
break;
case KFbxLayerElement::eINDEX_TO_DIRECT:
{
int index = texCoords->GetIndexArray().GetAt( positionIndex );
for (int p = 0; p < 2; ++p)
bone.c[bone.idx*3+v*2+p] = (float)texCoords->GetDirectArray().GetAt( index )

;
}
break;
default:
SM("Error: invalid texture coordinate reference mode\n");
error = true;
}
break;
case KFbxLayerElement::eBY_POLYGON_VERTEX:
{
int index = mesh->GetTextureUVIndex( i, v );
switch (texCoords->GetReferenceMode()) {
case KFbxLayerElement::eDIRECT:
case KFbxLayerElement::eINDEX_TO_DIRECT:
for (int p = 0; p < 2; ++p)
bone.c[bone.idx*3+v*2+p] = (float)texCoords->GetDirectArray().GetAt( index )

;
break;
default:
cout << " Error: invalid texture coordinate reference mode\n";
error = true;
}
}
break;
case KFbxLayerElement::eBY_POLYGON:
case KFbxLayerElement::eALL_SAME:
case KFbxLayerElement::eNONE:
cout << " Error: invalid texture coordinate mapping mode\n";
error = true;
}
}
if (normals != NULL)
{
normalsFound = true;
if (normals->GetMappingMode() == KFbxLayerElement::eBY_POLYGON_VERTEX)
{
switch (normals->GetReferenceMode())
{
case KFbxLayerElement::eDIRECT:
for (int p = 0; p < 3; ++p)
bone.n[bone.idx*3+v*3+p] = (float)normals->GetDirectArray().GetAt( positionIndex )

;
break;
case KFbxLayerElement::eINDEX_TO_DIRECT:
{
int index = normals->GetIndexArray().GetAt( positionIndex );
for (int p = 0; p < 3; ++p)
bone.n[bone.idx*3+v*3+p] = (float)normals->GetDirectArray().GetAt( index )

;
}
break;
default:
{
cout<<"Error: invalid normal reference mode\n";
error = true;
}
}
}
else
{
cout<<"Error: invalid normal mapping mode\n";
error = true;
}
if (error)
break;
}
if (error)
break;
}
if (error)
break;
}
if (error)
continue;
if (!texCoordsFound)
{
SM("Error: mesh has no texture coordinates\n");
continue;
}

}
bone.name=node->GetName();
bones.push_back(bone);



}

void Import(string filename)
{
mySdkManager= KFbxSdkManager::Create();
KFbxScene* myScene = KFbxScene::Create(mySdkManager, "");
KFbxImporter* myImporter = KFbxImporter::Create(mySdkManager, "");
const bool lImportStatus=myImporter->Initialize(filename.c_str(), -1, mySdkManager->GetIOSettings());
if( lImportStatus )
{
vector<F3Dbone> bones;
myImporter->Import(myScene);
//for(int i=0;i<myScene->GetNodeCount();i++)
GetFBXSDKNodes(bones,myScene->GetNode(0));

/*.............................
*/
for(int i=0;i<bones.size();i++)
{
delete[] bones.v;
delete[] bones.c;
delete[] bones.n;
delete[] bones.idx;
delete[] bones.mat;
}
bones.clear();
mySdkManager->Destroy();
}
//.......
}




Em, can u tell me what tag is for cpp [code=" "]?

[Edited by - furrymaster on July 20, 2010 4:51:01 AM]

Share this post


Link to post
Share on other sites
Thats what I'm currently using to get the positions/normals/texture coordinates of a mesh from the FBX SDK:


// Get control points (=vertices for a mesh)
KFbxVector4* fbxControlPoints = fbxMesh->GetControlPoints();

// For each polygon in the input mesh
for (int iPolygon = 0; iPolygon < fbxMesh->GetPolygonCount(); iPolygon++) {
// For each vertex in the polygon
for (unsigned iPolygonVertex = 0; iPolygonVertex < 3; iPolygonVertex++) {
int fbxCornerIndex = fbxMesh->GetPolygonVertex(iPolygon, iPolygonVertex);

// Get vertex position
KFbxVector4 fbxVertex = fbxControlPoints[fbxCornerIndex];

// Get normal
KFbxVector4 fbxNormal;
fbxMesh->GetPolygonVertexNormal(iPolygon, iPolygonVertex, fbxNormal);
fbxNormal.Normalize();

// Get texture coordinate
KFbxVector2 fbxUV = KFbxVector2(0.0, 0.0);
KFbxLayerElementUV* fbxLayerUV = fbxMesh->GetLayer(0)->GetUVs();
if (fbxLayerUV) {
int iUVIndex = 0;
switch (fbxLayerUV->GetMappingMode()) {
case KFbxLayerElement::eBY_CONTROL_POINT:
iUVIndex = fbxCornerIndex;
break;

case KFbxLayerElement::eBY_POLYGON_VERTEX:
iUVIndex = fbxMesh->GetTextureUVIndex(iPolygon, iPolygonVertex, KFbxLayerElement::eDIFFUSE_TEXTURES);
break;
}
fbxUV = fbxLayerUV->GetDirectArray().GetAt(iUVIndex);
}
}



(To get those code boxes use [ source lang="cpp"] and [ /source], without the spaces of course)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!