static void* MyRealloc(void* pData, size_t pSize) { if (pData) { FBX_ASSERT(*((char*)pData-1)=='#'); if (*((char*)pData-1)=='#') { char *p = (char*)realloc((char*)pData-1, pSize+1); *p = '#'; return p+1; } else { // Mismatch char *p = (char*)realloc((char*)pData, pSize+1); *p = '#'; return p+1; } } else { char *p = (char*)realloc(NULL, pSize+1); *p = '#'; return p+1; } }
MCE::FBX::TimeRange FilmboxNode::GetAnimationTimeRange() const { TimeRange animation_range; if( m_node ) { KFbxScene* fbx_scene = m_node->GetScene(); FBX_ASSERT( fbx_scene->GetSrcObjectCount( FBX_TYPE( KFbxAnimStack ) ) == 0, "Multiple animation stacks are not supported!" ); KFbxAnimStack* anim_stack = fbx_scene->GetSrcObject( FBX_TYPE( KFbxAnimStack ), 0 ); if( anim_stack ) { const char* anim_name = anim_stack->GetName(); KTimeSpan anim_timespan = anim_stack->GetLocalTimeSpan(); KTime anim_start = anim_timespan.GetStart(); KTime anim_stop = anim_timespan.GetStop(); animation_range.StartFrame = (int)( anim_start.GetFrame( true ) ); animation_range.EndFrame = (int)( anim_stop.GetFrame( true ) ); } } return animation_range; }
int Scene::AddCollisionMesh( MCE::FBX::Mesh* mesh ) { FBX_ASSERT( mesh, "Null mesh" ); int collision_mesh_id = NumCollisionMeshes(); m_collision_meshes.push_back( mesh ); return collision_mesh_id; }
int Scene::AddObject( MCE::FBX::SceneObject* object ) { FBX_ASSERT( object, "Null object" ); object->SetScene( this ); int id = NumObjects(); m_objects.push_back( object ); return id; }
void Scene::addNode(SceneNode *node, SceneNode *parent) { if (parent != NULL) { parent->children.push_back(node); } else { FBX_ASSERT(m_root == NULL); m_root = node; } }
const MCE::FBX::SceneObject* SceneNode::GetObject() const { FBX_ASSERT( m_scene, "Null scene" ); const MCE::FBX::SceneObject* scene_object = NULL; if( m_object_id >= 0 ) { scene_object = m_scene->GetSceneObject( m_object_id ); } return scene_object; }
const MCE::FBX::Mesh* SceneNode::GetCollisionMesh() const { FBX_ASSERT( m_scene, "Null scene" ); const MCE::FBX::Mesh* collision_mesh = NULL; if( m_collision_mesh_id >= 0 ) { collision_mesh = m_scene->GetCollisionMesh( m_collision_mesh_id ); } return collision_mesh; }
static void MyFree(void* pData) { if (pData==NULL) return; FBX_ASSERT(*((char*)pData-1)=='#'); if (*((char*)pData-1)=='#') { free((char*)pData-1); } else { // Mismatch free(pData); } }
void SceneNode::SetCollisionMesh( MCE::FBX::Mesh* collision_mesh ) { FBX_ASSERT( m_scene, "Null scene" ); if( collision_mesh ) { int id = m_scene->AddCollisionMesh( collision_mesh ); m_collision_mesh_id = id; } else { m_collision_mesh_id = -1; } }
void SceneNode::SetObject( MCE::FBX::SceneObject* object ) { FBX_ASSERT( m_scene, "Null scene" ); if( object ) { int id = m_scene->AddObject( object ); object->SetNode( this ); m_object_id = id; } else { m_object_id = -1; } }
void SceneNode::RemoveChildNode( MCE::FBX::SceneNode* node ) { FBX_ASSERT( node, "Null node" ); int num_child_nodes = NumChildNodes(); for( int i = 0; i < num_child_nodes; ) { MCE::FBX::SceneNode* child_node = m_child_nodes[ i ]; if( child_node == node ) { m_child_nodes.erase( m_child_nodes.begin() + i ); --num_child_nodes; } else { ++i; } } }
bool Mesh::init(FbxMesh* pFbxMesh) { uint32_t normalCount = pFbxMesh->GetElementNormalCount(); uint32_t uvCount = pFbxMesh->GetElementUVCount(); FbxGeometryElement::EMappingMode normalMappingMode = normalCount ? pFbxMesh->GetElementNormal(0)->GetMappingMode() : FbxGeometryElement::eNone; FbxGeometryElement::EMappingMode uvMappingModel = uvCount ? pFbxMesh->GetElementUV(0)->GetMappingMode() : FbxGeometryElement::eNone; bool hasNormal = normalMappingMode != FbxGeometryElement::eNone; bool hasUV = uvMappingModel != FbxGeometryElement::eNone; bool byControlPoint = hasNormal && normalMappingMode == FbxGeometryElement::eByControlPoint && hasUV && uvMappingModel == FbxGeometryElement::eByControlPoint; uint32_t polygonCount = pFbxMesh->GetPolygonCount(); uint32_t controlPointCount = byControlPoint ? pFbxMesh->GetControlPointsCount() : polygonCount * TRIANGLE_VERTEX_COUNT; this->vertices.resize(controlPointCount * VERTEX_STRIDE); this->indices.resize(polygonCount * TRIANGLE_VERTEX_COUNT); if (hasNormal) this->normals.resize(controlPointCount * NORMAL_STRIDE); FbxStringList uvNames; pFbxMesh->GetUVSetNames(uvNames); const char* pUVName = nullptr; if (hasUV) { this->uvs.resize(controlPointCount * UV_STRIDE); pUVName = uvNames[0]; } /* Vertex Attributes */ const FbxVector4* pControlPoints = pFbxMesh->GetControlPoints(); FbxVector4 currentVertex; FbxVector4 currentNormal; FbxVector2 currentUV; if (byControlPoint) { const FbxGeometryElementNormal* pNormalElement = nullptr; const FbxGeometryElementUV* pUVElement = nullptr; if (hasNormal) pNormalElement = pFbxMesh->GetElementNormal(0); if (hasUV) pUVElement = pFbxMesh->GetElementUV(0); for (uint32_t i = 0; i < controlPointCount; ++i) { currentVertex = pControlPoints[i]; this->vertices[i * VERTEX_STRIDE] = static_cast<float>(currentVertex[0]); this->vertices[i * VERTEX_STRIDE + 1] = static_cast<float>(currentVertex[1]); this->vertices[i * VERTEX_STRIDE + 2] = static_cast<float>(currentVertex[2]); this->vertices[i * VERTEX_STRIDE + 3] = 1.0f; if (hasNormal) { int normalIndex = i; if (pNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { normalIndex = pNormalElement->GetIndexArray().GetAt(i); } currentNormal = pNormalElement->GetDirectArray().GetAt(normalIndex); this->normals[i * NORMAL_STRIDE] = static_cast<float>(currentNormal[0]); this->normals[i * NORMAL_STRIDE + 1] = static_cast<float>(currentNormal[1]); this->normals[i * NORMAL_STRIDE + 2] = static_cast<float>(currentNormal[2]); } if (hasUV) { int uvIndex = i; if (pUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { uvIndex = pUVElement->GetIndexArray().GetAt(i); } currentUV = pUVElement->GetDirectArray().GetAt(uvIndex); this->uvs[i * UV_STRIDE] = static_cast<float>(currentUV[0]); this->uvs[i * UV_STRIDE + 1] = static_cast<float>(currentUV[1]); } } } // end of byControlPoint /* Slice the mesh according to materials */ FbxLayerElementArrayTemplate<int>* pMaterialIndices = nullptr; FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone; if (pFbxMesh->GetElementMaterial()) { pMaterialIndices = &pFbxMesh->GetElementMaterial()->GetIndexArray(); materialMappingMode = pFbxMesh->GetElementMaterial()->GetMappingMode(); if (pMaterialIndices && materialMappingMode == FbxGeometryElement::eByPolygon) { FBX_ASSERT(pMaterialIndices->GetCount() == polygonCount); for (uint32_t i = 0; i < polygonCount; ++i) { const uint32_t materialIndex = pMaterialIndices->GetAt(i); if (materialIndex >= slices.size()) // we meet a new material { slices.emplace_back(0, 0); } slices[materialIndex].triangleCount += 1; } int offset = 0; for (uint32_t i = 0; i < slices.size(); ++i) { slices[i].indexOffset = offset; offset += slices[i].triangleCount * 3; // this will be reused during per-Polygon processing slices[i].triangleCount = 0; } FBX_ASSERT(offset == polygonCount * 3); } } // There is only one material. if (slices.size() == 0) { slices.emplace_back(0, 0); } /* Indices */ for (uint32_t vertexCount = 0, i = 0; i < polygonCount; ++i) { int materialIndex = 0; if (pMaterialIndices && materialMappingMode == FbxGeometryElement::eByPolygon) { materialIndex = pMaterialIndices->GetAt(i); } const int indexOffset = slices[materialIndex].indexOffset + slices[materialIndex].triangleCount * 3; for (int v = 0; v < TRIANGLE_VERTEX_COUNT; ++v) { const int controlPointIndex = pFbxMesh->GetPolygonVertex(i, v); if (byControlPoint) { this->indices[indexOffset + v] = static_cast<unsigned int>(controlPointIndex); } else { this->indices[indexOffset + v] = static_cast<unsigned int>(vertexCount); currentVertex = pControlPoints[controlPointIndex]; this->vertices[vertexCount * VERTEX_STRIDE] = static_cast<float>(currentVertex[0]); this->vertices[vertexCount * VERTEX_STRIDE + 1] = static_cast<float>(currentVertex[1]); this->vertices[vertexCount * VERTEX_STRIDE + 2] = static_cast<float>(currentVertex[2]); this->vertices[vertexCount * VERTEX_STRIDE + 3] = 1.0f; if (hasNormal) { pFbxMesh->GetPolygonVertexNormal(i, v, currentNormal); this->normals[vertexCount * NORMAL_STRIDE] = static_cast<float>(currentNormal[0]); this->normals[vertexCount * NORMAL_STRIDE + 1] = static_cast<float>(currentNormal[1]); this->normals[vertexCount * NORMAL_STRIDE + 2] = static_cast<float>(currentNormal[2]); } if (hasUV) { bool bUnmappedUV; pFbxMesh->GetPolygonVertexUV(i, v, pUVName, currentUV, bUnmappedUV); this->uvs[vertexCount * UV_STRIDE] = static_cast<float>(currentUV[0]); this->uvs[vertexCount * UV_STRIDE] = static_cast<float>(currentUV[1]); } } ++vertexCount; } slices[materialIndex].triangleCount += 1; } return true; }
//ур╣╫ак bool VBOMesh::Initialize(const FbxMesh *pMesh) { if (!pMesh->GetNode()) return false; const int lPolygonCount = pMesh->GetPolygonCount(); // Count the polygon count of each material FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL; FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone; if (pMesh->GetElementMaterial()) { lMaterialIndice = &pMesh->GetElementMaterial()->GetIndexArray(); lMaterialMappingMode = pMesh->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); if (mSubMeshes.GetCount() < lMaterialIndex + 1) { mSubMeshes.Resize(lMaterialIndex + 1); } if (mSubMeshes[lMaterialIndex] == NULL) { mSubMeshes[lMaterialIndex] = new SubMesh; } 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 < mSubMeshes.GetCount(); i++) { if (mSubMeshes[i] == NULL) mSubMeshes[i] = new SubMesh; } // Record the offset (how many vertex) const int lMaterialCount = mSubMeshes.GetCount(); int lOffset = 0; for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) { mSubMeshes[lIndex]->IndexOffset = lOffset; lOffset += mSubMeshes[lIndex]->TriangleCount * 3; // This will be used as counter in the following procedures, reset to zero mSubMeshes[lIndex]->TriangleCount = 0; } FBX_ASSERT(lOffset == lPolygonCount * 3); } } } // All faces will use the same material. if (mSubMeshes.GetCount() == 0) { mSubMeshes.Resize(1); mSubMeshes[0] = new SubMesh(); } // 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. mHasNormal = pMesh->GetElementNormalCount() > 0; mHasUV = pMesh->GetElementUVCount() > 0; FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone; FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone; if (mHasNormal) { lNormalMappingMode = pMesh->GetElementNormal(0)->GetMappingMode(); if (lNormalMappingMode == FbxGeometryElement::eNone) { mHasNormal = false; } if (mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint) { mAllByControlPoint = false; } } if (mHasUV) { lUVMappingMode = pMesh->GetElementUV(0)->GetMappingMode(); if (lUVMappingMode == FbxGeometryElement::eNone) { mHasUV = false; } if (mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint) { mAllByControlPoint = false; } } // Allocate the array memory, by control point or by polygon vertex. int lPolygonVertexCount = pMesh->GetControlPointsCount(); if (!mAllByControlPoint) { lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT; } float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE]; unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT]; float * lNormals = NULL; if (mHasNormal) { lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE]; } float * lUVs = NULL; FbxStringList lUVNames; pMesh->GetUVSetNames(lUVNames); const char * lUVName = NULL; if (mHasUV && lUVNames.GetCount()) { lUVs = new float[lPolygonVertexCount * UV_STRIDE]; lUVName = lUVNames[0]; } // Populate the array with vertex attribute, if by control point. const FbxVector4 * lControlPoints = pMesh->GetControlPoints(); FbxVector4 lCurrentVertex; FbxVector4 lCurrentNormal; FbxVector2 lCurrentUV; if (mAllByControlPoint) { const FbxGeometryElementNormal * lNormalElement = NULL; const FbxGeometryElementUV * lUVElement = NULL; if (mHasNormal) { lNormalElement = pMesh->GetElementNormal(0); } if (mHasUV) { lUVElement = pMesh->GetElementUV(0); } for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex) { // Save the vertex position. lCurrentVertex = lControlPoints[lIndex]; lVertices[lIndex * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]); lVertices[lIndex * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]); lVertices[lIndex * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]); lVertices[lIndex * VERTEX_STRIDE + 3] = 1; // Save the normal. if (mHasNormal) { int lNormalIndex = lIndex; if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex); } lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex); lNormals[lIndex * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]); lNormals[lIndex * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]); lNormals[lIndex * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]); } // Save the UV. if (mHasUV) { int lUVIndex = lIndex; if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex); } lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex); lUVs[lIndex * UV_STRIDE] = static_cast<float>(lCurrentUV[0]); lUVs[lIndex * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]); } } } 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 = mSubMeshes[lMaterialIndex]->IndexOffset + mSubMeshes[lMaterialIndex]->TriangleCount * 3; for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex) { const int lControlPointIndex = pMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex); if (mAllByControlPoint) { lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex); } // Populate the array with vertex attribute, if by polygon vertex. else { lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount); lCurrentVertex = lControlPoints[lControlPointIndex]; lVertices[lVertexCount * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]); lVertices[lVertexCount * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]); lVertices[lVertexCount * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]); lVertices[lVertexCount * VERTEX_STRIDE + 3] = 1; if (mHasNormal) { pMesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); lNormals[lVertexCount * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]); lNormals[lVertexCount * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]); lNormals[lVertexCount * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]); } if (mHasUV) { bool lUnmappedUV; pMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV); lUVs[lVertexCount * UV_STRIDE] = static_cast<float>(lCurrentUV[0]); lUVs[lVertexCount * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]); } } ++lVertexCount; } mSubMeshes[lMaterialIndex]->TriangleCount += 1; } // Create VBOs glGenBuffers(VBO_COUNT, mVBONames); // Save vertex attributes into GPU glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]); glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * VERTEX_STRIDE * sizeof(float), lVertices, GL_STATIC_DRAW); delete[] lVertices; if (mHasNormal) { glBindBuffer(GL_ARRAY_BUFFER, mVBONames[NORMAL_VBO]); glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * NORMAL_STRIDE * sizeof(float), lNormals, GL_STATIC_DRAW); delete[] lNormals; } if (mHasUV) { glBindBuffer(GL_ARRAY_BUFFER, mVBONames[UV_VBO]); glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * UV_STRIDE * sizeof(float), lUVs, GL_STATIC_DRAW); delete[] lUVs; } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBONames[INDEX_VBO]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, lPolygonCount * TRIANGLE_VERTEX_COUNT * sizeof(unsigned int), lIndices, GL_STATIC_DRAW); delete[] lIndices; return true; }
const MCE::FBX::SceneNode* SceneNode::GetChildNode( int index ) const { FBX_ASSERT( ( index >= 0 ) && ( index < NumChildNodes() ), "Index out of bounds" ); const MCE::FBX::SceneNode* node = m_child_nodes[ index ]; return node; }
void SceneNode::AddChildNode( MCE::FBX::SceneNode* node ) { FBX_ASSERT( node, "Null node" ); node->SetParentNode( this ); m_child_nodes.push_back( node ); }
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; }
SceneNode *SceneConverter::makeSceneNode(FbxNode *node) { SceneNode *sceneNode = new SceneNode(); if (node->GetParent() == NULL) // The root { // Type sceneNode->type = FbxString("root"); // Name sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); // Transformation FbxAMatrix m = node->EvaluateGlobalTransform(); const FbxVector4 translation = m.GetT(); const FbxVector4 rotation = m.GetR(); const FbxVector4 scaling = m.GetS(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f", (float)scaling[0], (float)scaling[1], (float)scaling[2], (float)rotation[0], (float)rotation[1], (float)rotation[2], (float)translation[0], (float)translation[1], (float)translation[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer))); } else { FbxCamera *camera = node->GetCamera(); if (camera != NULL) { sceneNode->type = FbxString("camera"); sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); sceneNode->attributes.push_back(std::make_pair(FbxString("fixed"), FbxString("true"))); FbxVector4 position = camera->EvaluatePosition(); FbxVector4 center = camera->EvaluateLookAtPosition(); // FIXME: seems EvaluateUpDirection doesn't give correct result as it // is affected by its parent nodes' tranforms however we attach camera // to the root in paper3d's scene. // FbxVector4 up = camera->EvaluateUpDirection(position, center); FbxDouble3 up = camera->UpVector.Get(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "eye:%8.5f,%8.5f,%8.5f,center:%8.5f,%8.5f,%8.5f,up:%8.5f,%8.5f,%8.5f", (float)position[0], (float)position[1], (float)position[2], (float)center[0], (float)center[1], (float)center[2], (float)up[0], (float)up[1], (float)up[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("lookat"), FbxString(buffer))); float nearZ = (float)camera->GetNearPlane(); float farZ = (float)camera->GetFarPlane(); if (camera->ProjectionType.Get() == FbxCamera::ePerspective) { FbxCamera::EAspectRatioMode lCamAspectRatioMode = camera->GetAspectRatioMode(); double lAspectX = camera->AspectWidth.Get(); double lAspectY = camera->AspectHeight.Get(); double lAspectRatio = 1.333333; switch( lCamAspectRatioMode) { case FbxCamera::eWindowSize: lAspectRatio = lAspectX / lAspectY; break; case FbxCamera::eFixedRatio: lAspectRatio = lAspectX; break; case FbxCamera::eFixedResolution: lAspectRatio = lAspectX / lAspectY * camera->GetPixelRatio(); break; case FbxCamera::eFixedWidth: lAspectRatio = camera->GetPixelRatio() / lAspectY; break; case FbxCamera::eFixedHeight: lAspectRatio = camera->GetPixelRatio() * lAspectX; break; default: break; } //get the aperture ratio double lFilmHeight = camera->GetApertureHeight(); double lFilmWidth = camera->GetApertureWidth() * camera->GetSqueezeRatio(); //here we use Height : Width double lApertureRatio = lFilmHeight / lFilmWidth; //change the aspect ratio to Height : Width lAspectRatio = 1 / lAspectRatio; //revise the aspect ratio and aperture ratio FbxCamera::EGateFit lCameraGateFit = camera->GateFit.Get(); switch( lCameraGateFit ) { case FbxCamera::eFitFill: if( lApertureRatio > lAspectRatio) // the same as eHORIZONTAL_FIT { lFilmHeight = lFilmWidth * lAspectRatio; camera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; } else if( lApertureRatio < lAspectRatio) //the same as eVERTICAL_FIT { lFilmWidth = lFilmHeight / lAspectRatio; camera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; } break; case FbxCamera::eFitVertical: lFilmWidth = lFilmHeight / lAspectRatio; camera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitHorizontal: lFilmHeight = lFilmWidth * lAspectRatio; camera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitStretch: lAspectRatio = lApertureRatio; break; case FbxCamera::eFitOverscan: if( lFilmWidth > lFilmHeight) { lFilmHeight = lFilmWidth * lAspectRatio; } else { lFilmWidth = lFilmHeight / lAspectRatio; } lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitNone: default: break; } //change the aspect ratio to Width : Height lAspectRatio = 1 / lAspectRatio; #define HFOV2VFOV(h, ar) (2.0 * atan((ar) * tan( (h * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectY / aspectX #define VFOV2HFOV(v, ar) (2.0 * atan((ar) * tan( (v * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectX / aspectY double lFieldOfViewX = 0.0; double lFieldOfViewY = 0.0; if (camera->GetApertureMode() == FbxCamera::eVertical) { lFieldOfViewY = camera->FieldOfView.Get(); lFieldOfViewX = VFOV2HFOV( lFieldOfViewY, 1 / lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eHorizontal) { lFieldOfViewX = camera->FieldOfView.Get(); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eFocalLength) { lFieldOfViewX = camera->ComputeFieldOfView(camera->FocalLength.Get()); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eHorizAndVert) { lFieldOfViewX = camera->FieldOfViewX.Get(); lFieldOfViewY = camera->FieldOfViewY.Get(); } #undef HFOV2VFOV #undef VFOV2HFOV FBXSDK_sprintf(buffer, 1024, "perspective,fov:%8.5f,aspect:-1,znear:%8.5f,zfar:%8.5f", (float)lFieldOfViewY, nearZ, farZ); sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer))); } else { FBXSDK_sprintf(buffer, 1024, "orthogonal,aspect:-1,znear:%8.5f,zfar:%8.5f", nearZ, farZ); sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer))); } m_numCameras++; } else { FbxLight *light = node->GetLight(); if (light != NULL) { m_numLights++; FBX_ASSERT(!"Not implemented!"); } else { // Type sceneNode->type = FbxString("drawable"); // Name sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); // Transformation FbxAMatrix m = node->EvaluateLocalTransform(); //FbxAMatrix m1 = node->EvaluateGlobalTransform(); const FbxVector4 translation = m.GetT(); const FbxVector4 rotation = m.GetR(); const FbxVector4 scaling = m.GetS(); float s[3], r[3], t[3]; t[0] = (float)translation.mData[0]; t[1] = (float)translation.mData[1]; t[2] = (float)translation.mData[2]; r[0] = (float)(rotation[0] * FBXSDK_DEG_TO_RAD); r[1] = (float)(rotation[1] * FBXSDK_DEG_TO_RAD); r[2] = (float)(rotation[2] * FBXSDK_DEG_TO_RAD); s[0] = (float)scaling[0]; s[1] = (float)scaling[1]; s[2] = (float)scaling[2]; //const FbxVector4 translation1 = m1.GetT(); //const FbxVector4 rotation1 = m1.GetR(); //const FbxVector4 scaling1 = m1.GetS(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f", s[0], s[1], s[2], r[0], r[1], r[2], t[0], t[1], t[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer))); // Mesh //if (node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eCamera) //{ // FBXSDK_printf("f**k"); //} static FbxUInt32 i = 0; if (node->GetMesh() == NULL) { sceneNode->type = FbxString("node"); } else { const char *meshName = node->GetMesh()->GetName(); if (meshName == NULL || meshName[0] == 0) { meshName = node->GetName(); } FbxString prefix; if (meshName == NULL || meshName[0] == 0) { prefix = FbxString("mesh_") + FbxString(int(i++)); } else { prefix = FbxString(meshName); } sceneNode->geometry = prefix + FbxString(".") + m_arguments->meshFormat; // Material FbxSurfaceMaterial *material = node->GetMaterial(0); if (material != NULL) { // This only gets the material of type sDiffuse, you probably need to // traverse all Standard Material Property by its name to get all // possible textures. FbxProperty prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse); // Check if it's layeredtextures int layeredTextureCount = prop.GetSrcObjectCount<FbxLayeredTexture>(); if (prop.GetSrcObjectCount<FbxTexture>() > 0) { FbxFileTexture *lTex = prop.GetSrcObject<FbxFileTexture>(0); FbxString filename = FbxPathUtils::GetFileName(lTex->GetFileName()); sceneNode->texture = filename.Lower(); m_textures.push_back(FbxString(lTex->GetFileName())); } // root node is not counted as a drawable. m_numDrawables++; } } } } } return sceneNode; }
const MCE::FBX::Material& Scene::GetMaterial( int id ) const { FBX_ASSERT( ( id >= 0 ) && ( id < NumMaterials() ), "Index out of bounds" ); const MCE::FBX::Material& material = m_materials[ id ]; return material; }
const MCE::FBX::Mesh* Scene::GetCollisionMesh( int id ) const { FBX_ASSERT( ( id >= 0 ) && ( id < NumCollisionMeshes() ), "Index out of bounds" ); const MCE::FBX::Mesh* mesh = m_collision_meshes[ id ]; return mesh; }
//-------------------------------------------------------------- void ofxFBXMesh::setFBXMesh( FbxMesh* lMesh ) { fbxMesh = lMesh; // name = lMesh->GetName(); mesh.clear(); // from ViewScene Example included with the FBX SDK // if (!lMesh->GetNode()) { ofLogError("ofxFBXMesh") << " error setFBXMesh, lMesh->GetNode failed" << endl; return; } const int lPolygonCount = lMesh->GetPolygonCount(); // Count the polygon count of each material FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL; FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone; if (lMesh->GetElementMaterial()) { lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray(); lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode(); if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) { FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount); if (lMaterialIndice->GetCount() == lPolygonCount) { // make sure the vector is setup and we have the proper amount of materials ready // for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); if(lMaterialIndex >= 0) { if (subMeshes.size() < lMaterialIndex + 1) { subMeshes.resize(lMaterialIndex + 1); } } } // Count the faces of each material for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); // cout << "lMaterialIndex = " << lMaterialIndex << " submesh.size = " << subMeshes.size() << endl; if(lMaterialIndex >= 0 ) { subMeshes[lMaterialIndex].triangleCount += 1; } } // Record the offset (how many vertex) const int lMaterialCount = subMeshes.size(); int lOffset = 0; for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) { subMeshes[lIndex].indexOffset = lOffset; lOffset += subMeshes[lIndex].triangleCount * 3; // subMeshes[lIndex].totalIndices = subMeshes[lIndex].triangleCount * 3; // cout << "polygon: " << lIndex << " totalIndices = " << subMeshes[lIndex].totalIndices << endl; // This will be used as counter in the following procedures, reset to zero subMeshes[lIndex].triangleCount = 0; } FBX_ASSERT(lOffset == lPolygonCount * 3); // what? } } } if(subMeshes.size() == 0) { subMeshes.resize(1); } // TODO: Account for if all mapping modes are not by control point // bool bHasNormals = lMesh->GetElementNormalCount() > 0; bool bMapNormalsByControlPoint = true; bool bHasUvs = lMesh->GetElementUVCount() > 0; bool bMapUvsByControlPoint = true; // are the normals mapped by control point or by polygon? FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone; if(bHasNormals) { lNormalMappingMode = lMesh->GetElementNormal(0)->GetMappingMode(); if (lNormalMappingMode == FbxGeometryElement::eNone) { bHasNormals = false; } if (bHasNormals && lNormalMappingMode != FbxGeometryElement::eByControlPoint) { bMapNormalsByControlPoint = false; } } FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone; if (bHasUvs) { lUVMappingMode = lMesh->GetElementUV(0)->GetMappingMode(); if (lUVMappingMode == FbxGeometryElement::eNone) { bHasUvs = false; } if (bHasUvs && lUVMappingMode != FbxGeometryElement::eByControlPoint) { bMapUvsByControlPoint = false; } } bAllMappedByControlPoint = (bMapNormalsByControlPoint && bMapUvsByControlPoint); // if(lMaterialMappingMode == FbxGeometryElement::eAllSame) { // // } int lPolygonVertexCount = lMesh->GetControlPointsCount(); if( bAllMappedByControlPoint ) { const FbxVector4 * lControlPoints = lMesh->GetControlPoints(); for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) { mesh.addVertex( ofVec3f( lControlPoints[i][0], lControlPoints[i][1], lControlPoints[i][2] ) ); } for(int i = 0; i < lMesh->GetPolygonCount(); i++ ) { for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) { const int lControlPointIndex = lMesh->GetPolygonVertex(i, lVerticeIndex); mesh.addIndex( lControlPointIndex ); } } if(subMeshes.size() == 1) { subMeshes[0].totalIndices = mesh.getNumIndices(); } // normals if(bHasNormals) { ofMesh normalsMesh; //cout << "ofxFBXMesh :: we have normals for " << getName() << endl; if(bMapNormalsByControlPoint) { //cout << "ofxFBXMesh :: normals by control point for " << getName() << endl; const FbxGeometryElementNormal * lNormalElement = lMesh->GetElementNormal(0); for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) { int lNormalIndex = i; if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lNormalIndex = lNormalElement->GetIndexArray().GetAt(i); } FbxVector4 lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex); normalsMesh.addNormal( ofVec3f(lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2]) ); } mesh.addNormals( normalsMesh.getNormals() ); } } // textures // if(bHasUvs) { //cout << "ofxFBXMesh :: we have tex coords for " << getName() << endl; if(bMapUvsByControlPoint) { //cout << "ofxFBXMesh :: tex coords by control point " << getName() << endl; const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0); for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) { int lUVIndex = i; if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lUVIndex = lUVElement->GetIndexArray().GetAt(i); } FbxVector2 lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex); mesh.addTexCoord( ofVec2f(lCurrentUV[0], lCurrentUV[1]) ); } } } } else { // cout << "--- " << getName() << " mapped by polygons ---------------" << endl; // cout << "numSubMeshes = " << subMeshes.size() << " polygon count = " << lPolygonCount << " control points = " << fbxMesh->GetControlPointsCount() << endl; // if(lMaterialMappingMode == FbxGeometryElement::eNone) { // cout << "Material mapping mode = none" << endl; // } else if (lMaterialMappingMode == FbxGeometryElement::eByControlPoint) { // cout << "Material mapping mode = eByControlPoint" << endl; // } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygonVertex) { // cout << "Material mapping mode = eByPolygonVertex" << endl; // } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygon) { // cout << "Material mapping mode = eByPolygon" << endl; // } else if(lMaterialMappingMode == FbxGeometryElement::eByEdge) { // cout << "Material mapping mode = eByEdge" << endl; // } else if(lMaterialMappingMode == FbxGeometryElement::eAllSame) { // cout << "Material mapping mode = eAllSame" << endl; // } // // if(lMaterialIndice) { // cout << "lMaterialIndice size = " << lMaterialIndice->GetCount() << endl; // } else { // cout << "did not get the lMaterialIndice" << endl; // } const FbxVector4 * lControlPoints = fbxMesh->GetControlPoints(); mesh.getVertices().resize( lPolygonCount * 3 ); mesh.getIndices().resize( lPolygonCount * 3 ); if(bHasNormals) { mesh.getNormals().resize( lPolygonCount * 3 ); } // cout << "Polygon vertex count = " << fbxMesh->GetPolygonVertexCount() << endl; const char * lUVName = NULL; FbxStringList lUVNames; fbxMesh->GetUVSetNames(lUVNames); if(bHasUvs && lUVNames.GetCount() ) { mesh.getTexCoords().resize( lPolygonCount * 3 ); lUVName = lUVNames[0]; } for(int i = 0; i < lUVNames.GetCount(); i++ ) { // cout << "lUVName = " << lUVNames[0] << endl; } FbxVector4 lCurrentVertex; FbxVector4 lCurrentNormal; FbxVector2 lCurrentUV; const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0); 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); if(lMaterialIndex < 0) { lMaterialIndex = 0; } } // Where should I save the vertex attribute index, according to the material const int lIndexOffset = subMeshes[lMaterialIndex].indexOffset + subMeshes[lMaterialIndex].triangleCount * 3; // const int lIndexOffset = fbxMesh->GetPolygonVertexIndex(lPolygonIndex); for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) { const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex); // Populate the array with vertex attribute, if by polygon vertex. mesh.getIndices()[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount); lCurrentVertex = lControlPoints[ lControlPointIndex ]; mesh.getVertices()[lVertexCount].set( lCurrentVertex[0], lCurrentVertex[1], lCurrentVertex[2] ); if (bHasNormals) { if(fbxMesh->GetPolygonVertexNormal( lPolygonIndex, lVerticeIndex, lCurrentNormal )) { int normalIndex = lVertexCount; mesh.getNormals()[normalIndex].set( lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2] ); } } if (bHasUvs) { bool lUnmappedUV; fbxMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV); int tcoordIndex = lVertexCount; mesh.getTexCoords()[ tcoordIndex ].set( lCurrentUV[0], lCurrentUV[1] ); } ++lVertexCount; } subMeshes[lMaterialIndex].triangleCount += 1; subMeshes[lMaterialIndex].totalIndices += 3; // cout << "materialIndex = " << lMaterialIndex << endl; } } // All faces will use the same material. // if ( subMeshes.size() == 1) { // // meshMaterials.resize(1); //// subMeshes[0].totalIndices = mesh.getNumIndices(); // } for(int i = 0; i < subMeshes.size(); i++ ) { // cout << i << " submesh totalindicies = " << subMeshes[i].totalIndices << " total verts = " << mesh.getNumVertices() << " polygonos = " << lPolygonCount << endl; } // cout << "--------------------------------------- " << endl << endl; veebs.setMesh( mesh, GL_STREAM_DRAW ); original = mesh; }
const MCE::FBX::SceneObject* Scene::GetSceneObject( int id ) const { FBX_ASSERT( ( id >= 0 ) && ( id < NumObjects() ), "Index out of bounds" ); const MCE::FBX::SceneObject* object = m_objects[ id ]; return object; }