void FBXConverter::CalcTangentSpace(const Vertex& v1, const Vertex& v2, const Vertex& v3, FbxVector4& binormal, FbxVector4& tangent) { binormal = FbxVector4(); tangent = FbxVector4(); FbxVector4 cp0[3]; cp0[0] = FbxVector4(v1.Position[0], v1.UV[0], v1.UV[1]); cp0[1] = FbxVector4(v1.Position[1], v1.UV[0], v1.UV[1]); cp0[2] = FbxVector4(v1.Position[2], v1.UV[0], v1.UV[1]); FbxVector4 cp1[3]; cp1[0] = FbxVector4(v2.Position[0], v2.UV[0], v2.UV[1]); cp1[1] = FbxVector4(v2.Position[1], v2.UV[0], v2.UV[1]); cp1[2] = FbxVector4(v2.Position[2], v2.UV[0], v2.UV[1]); FbxVector4 cp2[3]; cp2[0] = FbxVector4(v3.Position[0], v3.UV[0], v3.UV[1]); cp2[1] = FbxVector4(v3.Position[1], v3.UV[0], v3.UV[1]); cp2[2] = FbxVector4(v3.Position[2], v3.UV[0], v3.UV[1]); double u[3]; double v[3]; for (int32_t i = 0; i < 3; i++) { auto v1 = cp1[i] - cp0[i]; auto v2 = cp2[i] - cp1[i]; auto abc = v1.CrossProduct(v2); if (abc[0] == 0.0f) { return; } else { u[i] = -abc[1] / abc[0]; v[i] = -abc[2] / abc[0]; } } tangent = FbxVector4(u[0], u[1], u[2]); tangent.Normalize(); binormal = FbxVector4(v[0], v[1], v[2]); binormal.Normalize(); }
void FbxParser::ProcessCamera(FbxNode* pNode, GS::Camera& camera) { FbxCamera* lCamera = (FbxCamera*) pNode->GetNodeAttribute(); if (lCamera == NULL) return ; FbxNode* pTargetNode = pNode->GetTarget(); FbxNode* pTargetUpNode = pNode->GetTargetUp(); FbxVector4 lEye = lCamera->Position.Get(); FbxVector4 lUp; FbxVector4 lCenter; if (!pTargetNode) lCenter = lCamera->InterestPosition.Get(); if (!pTargetUpNode) lUp = lCamera->UpVector.Get(); double lRadians = PI * lCamera->Roll.Get() / 180.0; // Align the up vector. FbxVector4 lForward = lCenter - lEye; lForward.Normalize(); FbxVector4 lRight = lForward.CrossProduct(lUp); lRight.Normalize(); lUp = lRight.CrossProduct(lForward); lUp.Normalize(); lUp *= cos(lRadians); lRight *= sin(lRadians); lUp = lUp + lRight; GS::float3 pos(lEye[0], lEye[1], lEye[2]); GS::float3 up(lUp[0], lUp[1], lUp[2]); GS::float3 target(lCenter[0], lCenter[1], lCenter[2]); GS::Camera cam(pos, target, up); float lNearPlane = 0.01f; if (lCamera) lNearPlane = lCamera->GetNearPlane(); float lFarPlane = 1000.0; if (lCamera) lFarPlane = lCamera->GetFarPlane(); bool bPerspectice = lCamera->ProjectionType.Get() == FbxCamera::ePerspective ; //bPerspectice = true; cam.SetProjectionMode(bPerspectice); cam.SetProjectionPlanes(lNearPlane, lFarPlane); camera = cam; }
void Model::processMeshNormals(FbxMesh * mesh, Vertex * verts, int numVerts) { for (int iPolygon = 0; iPolygon < mesh->GetPolygonCount(); iPolygon++) { for (unsigned iPolygonVertex = 0; iPolygonVertex < 3; iPolygonVertex++) { int fbxCornerIndex = mesh->GetPolygonVertex(iPolygon, iPolygonVertex); FbxVector4 fbxNormal; mesh->GetPolygonVertexNormal(iPolygon, iPolygonVertex, fbxNormal); fbxNormal.Normalize(); verts[fbxCornerIndex].normal.x = fbxNormal[0]; verts[fbxCornerIndex].normal.y = fbxNormal[1]; verts[fbxCornerIndex].normal.z = fbxNormal[2]; } } }
void Model::processMeshNormals(FbxMesh *mesh, Vertex *verts, int count) { int polCount = mesh->GetPolygonCount(); for (int polInd = 0; polInd < polCount; polInd++) { for (int vertInd = 0; vertInd < 3; vertInd++) { int cornerIndex = mesh->GetPolygonVertex(polInd, vertInd); FbxVector4 normal; mesh->GetPolygonVertexNormal(polInd, vertInd, normal); normal.Normalize(); verts[cornerIndex].normal.x = normal[0]; verts[cornerIndex].normal.y = normal[1]; verts[cornerIndex].normal.z = normal[2]; verts[cornerIndex].tangent = getTangent(verts[cornerIndex].normal); verts[cornerIndex].binormal = getBinormal(verts[cornerIndex].normal, verts[cornerIndex].tangent); } } }
void FBXSceneImporter::read_mesh(FbxNode *pNode, FbxMesh* pMesh) { std::vector<Mesh::Vertex> vertices; std::vector<int> indices; //pMesh->GenerateTangentsDataForAllUVSets(); Mesh *new_mesh = new Mesh(); new_mesh->set_name(pNode->GetName()); int polygonCount = pMesh->GetPolygonCount(); FbxVector4* controlPoints = pMesh->GetControlPoints(); int controlPointCount = pMesh->GetControlPointsCount(); int vertexID = 0; for (int polygon = polygonCount - 1; polygon > -1; polygon--) { int polyVertCount = pMesh->GetPolygonSize(polygon); assert(polyVertCount == 3); for (int polyVert = 0; polyVert < polyVertCount; polyVert++) { Mesh::Vertex vertex; int cpIndex = pMesh->GetPolygonVertex(polygon, polyVert); // Grab our CP index as well our position information //uniqueVert.m_nControlPointIndex = cpIndex; vertex.position[0] = controlPoints[cpIndex].mData[0]; vertex.position[1] = controlPoints[cpIndex].mData[1]; vertex.position[2] = controlPoints[cpIndex].mData[2]; vertex.position[3] = 1; // Grab UVs int uvElementCount = pMesh->GetElementUVCount(); int ctrlPointIndex = pMesh->GetPolygonVertex(polygon, polyVert); for (int uvElement = 0; uvElement < uvElementCount; uvElement++) { FbxGeometryElementUV* geomElementUV = pMesh->GetElementUV(uvElement); FbxLayerElement::EMappingMode mapMode = geomElementUV->GetMappingMode(); FbxLayerElement::EReferenceMode refMode = geomElementUV->GetReferenceMode(); if (FbxGeometryElement::eByControlPoint == mapMode) { switch (geomElementUV->GetReferenceMode()) { case FbxGeometryElement::eDirect: { vertex.texture_coord.x = static_cast<float>(geomElementUV->GetDirectArray().GetAt(ctrlPointIndex).mData[0]); vertex.texture_coord.y = static_cast<float>(geomElementUV->GetDirectArray().GetAt(ctrlPointIndex).mData[1]); } break; case FbxGeometryElement::eIndexToDirect: { int index = geomElementUV->GetIndexArray().GetAt(ctrlPointIndex); vertex.texture_coord.x = static_cast<float>(geomElementUV->GetDirectArray().GetAt(index).mData[0]); vertex.texture_coord.y = static_cast<float>(geomElementUV->GetDirectArray().GetAt(index).mData[1]); } break; default: throw std::exception("Invalid Reference"); } } if (FbxGeometryElement::eByPolygonVertex == mapMode) { int directIndex = -1; if (FbxGeometryElement::eDirect == refMode) { directIndex = vertexID; } else if (FbxGeometryElement::eIndexToDirect == refMode) { directIndex = geomElementUV->GetIndexArray().GetAt(vertexID); } // If we got an index if (directIndex != -1) { FbxVector4 texture_coord = geomElementUV->GetDirectArray().GetAt(directIndex); vertex.texture_coord = D3DXVECTOR4((float)texture_coord.mData[0], (float)texture_coord.mData[1], 0, 0); } } } // Grab normals int normElementCount = pMesh->GetElementNormalCount(); for (int normalElement = 0; normalElement < normElementCount; normalElement++) { FbxGeometryElementNormal* geomElementNormal = pMesh->GetElementNormal(normalElement); FbxLayerElement::EMappingMode mapMode = geomElementNormal->GetMappingMode(); FbxLayerElement::EReferenceMode refMode = geomElementNormal->GetReferenceMode(); FbxVector4 fbxNormal; pMesh->GetPolygonVertexNormal(polygon, polyVert, fbxNormal); fbxNormal.Normalize(); vertex.normal = D3DXVECTOR4(fbxNormal.mData[0], fbxNormal.mData[1], fbxNormal.mData[2], 0); //if (FbxGeometryElement::eByControlPoint == mapMode) //{ // switch (geomElementNormal->GetReferenceMode()) // { // case FbxGeometryElement::eDirect: // { // vertex.normal.x = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[0]); // vertex.normal.y = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[1]); // vertex.normal.z = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(ctrlPointIndex).mData[2]); // D3DXVec4Normalize(&vertex.normal, &vertex.normal); // } // break; // // case FbxGeometryElement::eIndexToDirect: // { // int index = geomElementNormal->GetIndexArray().GetAt(ctrlPointIndex); // vertex.normal.x = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[0]); // vertex.normal.y = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[1]); // vertex.normal.z = static_cast<float>(geomElementNormal->GetDirectArray().GetAt(index).mData[2]); // D3DXVec4Normalize(&vertex.normal, &vertex.normal); // } // break; // // default: // throw std::exception("Invalid Reference"); // } //} //if (FbxGeometryElement::eByPolygonVertex == mapMode) //{ // int directIndex = -1; // if (FbxGeometryElement::eDirect == refMode) // { // directIndex = vertexID; // } // else if (FbxGeometryElement::eIndexToDirect == refMode) // { // directIndex = geomElementNormal->GetIndexArray().GetAt(vertexID); // } // // // If we got an index // if (directIndex != -1) // { // FbxVector4 norm = geomElementNormal->GetDirectArray().GetAt(directIndex); // // D3DXVECTOR4 normal_final((float)norm.mData[0], (float)norm.mData[1], (float)norm.mData[2], 0); // D3DXVec4Normalize(&vertex.normal, &normal_final); // } //} } // grab tangents int tangentElementCount = pMesh->GetElementTangentCount(); for (int normalElement = 0; normalElement < tangentElementCount; normalElement++) { FbxGeometryElementTangent* geomElementTangent = pMesh->GetElementTangent(normalElement); FbxLayerElement::EMappingMode mapMode = geomElementTangent->GetMappingMode(); FbxLayerElement::EReferenceMode refMode = geomElementTangent->GetReferenceMode(); int directIndex = -1; if (FbxGeometryElement::eByPolygonVertex == mapMode) { if (FbxGeometryElement::eDirect == refMode) { directIndex = vertexID; } else if (FbxGeometryElement::eIndexToDirect == refMode) { directIndex = geomElementTangent->GetIndexArray().GetAt(vertexID); } } // If we got an index if (directIndex != 1) { FbxVector4 tangent = geomElementTangent->GetDirectArray().GetAt(directIndex); vertex.tangent = D3DXVECTOR4((float)tangent.mData[0], (float)tangent.mData[1], (float)tangent.mData[2], 0); } } size_t size = vertices.size(); size_t i = size; //for (i = 0; i < size; i++) //{ // if (vertex == vertices[i]) // { // break; // } //} // if (i == size) { vertices.push_back(vertex); } indices.push_back(i); ++vertexID; } //int cur_size = indices.size(); //int temp = indices[cur_size - 3]; //indices[cur_size - 3] = indices[cur_size - 1]; //indices[cur_size - 1] = temp; } int materialCount = pNode->GetSrcObjectCount<FbxSurfaceMaterial>(); new_mesh->create_from_buffers(vertices, indices); scene_to_fill->add_mesh(new_mesh); if (materialCount > 0) { FbxSurfaceMaterial* material = (FbxSurfaceMaterial*)pNode->GetSrcObject<FbxSurfaceMaterial>(0); new_mesh->set_material(read_material(pNode, material)); } get_transformation_matrix(pNode, new_mesh); cout << "Read mesh : " << new_mesh->get_name() << "\n"; }
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; }
CGeometryComponent * CModelLoader::loadFbxModelFromFile(ID3D10Device *pDevice,const string& filename) { CGeometryComponent * pRenderable=NULL; FbxManager* lSdkManager = FbxManager::Create(); FbxIOSettings *ios = FbxIOSettings::Create(lSdkManager, IOSROOT); lSdkManager->SetIOSettings(ios); // Create an importer using our sdk manager. FbxImporter* lImporter = FbxImporter::Create(lSdkManager,""); //Sean: uncomment back to this when you compile, I am using the latest version of fbx SDK //KFbxGeometryConverter converter( lSdkManager); //Sean: has comment out the line below FbxGeometryConverter converter( lSdkManager); // Use the first argument as the filename for the importer. if(!lImporter->Initialize(filename.c_str(), -1, lSdkManager->GetIOSettings())) { return NULL; } // Create a new scene so it can be populated by the imported file. FbxScene* lScene = FbxScene::Create(lSdkManager,"myScene"); FbxAxisSystem SceneAxisSystem = lScene->GetGlobalSettings().GetAxisSystem(); //FbxAxisSystem::DirectX.ConvertScene( lScene ); INT iUpAxisSign; //Sean: Uncomment this below //KFbxAxisSystem::eUpVector UpVector = SceneAxisSystem.GetUpVector( iUpAxisSign ); //Sean: and comment this out FbxAxisSystem::EUpVector UpVector = SceneAxisSystem.GetUpVector( iUpAxisSign ); // Import the contents of the file into the scene. lImporter->Import(lScene); // The file has been imported; we can get rid of the importer. lImporter->Destroy(); FbxNode* lRootNode = lScene->GetRootNode(); FbxMesh * pMesh=NULL; if(lRootNode) { for (int i=0;i<lRootNode->GetChildCount();i++){ FbxNode * modelNode=lRootNode->GetChild(i); for(int i=0;i<modelNode->GetNodeAttributeCount();i++) { FbxNodeAttribute *pAttributeNode=modelNode->GetNodeAttributeByIndex(i); //Sean: Uncomment this //if (pAttributeNode->GetAttributeType()==KFbxNodeAttribute::eMESH) //Sean Comment this out if (pAttributeNode->GetAttributeType()==FbxNodeAttribute::eMesh) { //found mesh pMesh=(FbxMesh*)pAttributeNode; break; } } } if (pMesh) { pMesh=converter.TriangulateMesh(pMesh); FbxVector4 * verts=pMesh->GetControlPoints(); int noVerts=pMesh->GetControlPointsCount(); int noIndices=pMesh->GetPolygonVertexCount(); int *pIndices=pMesh->GetPolygonVertices(); Vertex * pVerts=new Vertex[noVerts]; for(int i=0;i<noVerts;i++) { pVerts[i].Pos.x=verts[i][0]; pVerts[i].Pos.y=verts[i][1]; pVerts[i].Pos.z=verts[i][2]; } for (int iPolygon = 0; iPolygon < pMesh->GetPolygonCount(); iPolygon++) { for (unsigned iPolygonVertex = 0; iPolygonVertex < 3; iPolygonVertex++) { int fbxCornerIndex = pMesh->GetPolygonVertex(iPolygon, iPolygonVertex); FbxVector4 fbxVertex = verts[fbxCornerIndex]; FbxVector4 fbxNormal; pMesh->GetPolygonVertexNormal(iPolygon, iPolygonVertex, fbxNormal); fbxNormal.Normalize(); //pVerts[fbxCornerIndex].Normal=D3DXVECTOR3(fbxNormal[0],fbxNormal[1],fbxNormal[2]); FbxVector2 fbxUV = FbxVector2(0.0, 0.0); FbxLayerElementUV* fbxLayerUV = pMesh->GetLayer(0)->GetUVs(); // Get texture coordinate if (fbxLayerUV) { int iUVIndex = 0; switch (fbxLayerUV->GetMappingMode()) { //Sean Uncomment this //case KFbxLayerElement::eBY_CONTROL_POINT: //Sean comment the line below out case FbxLayerElement::eByControlPoint: iUVIndex = fbxCornerIndex; break; //Sean Uncomment this //case KFbxLayerElement::eBY_POLYGON_VERTEX: //Sean comment the line below out case FbxLayerElement::eByPolygonVertex: //Sean Uncomment this //iUVIndex = pMesh->GetTextureUVIndex(iPolygon, iPolygonVertex, KFbxLayerElement::eDIFFUSE_TEXTURES); //Sean comment this out iUVIndex = pMesh->GetTextureUVIndex(iPolygon, iPolygonVertex, FbxLayerElement::eTextureDiffuse); break; } fbxUV = fbxLayerUV->GetDirectArray().GetAt(iUVIndex); //pVerts[fbxCornerIndex].TextureCoords.x=fbxUV[0]; //pVerts[fbxCornerIndex].TextureCoords.y= 1.0f-fbxUV[1]; } } } pRenderable=new CGeometryComponent(); for (int i=0;i<noVerts;i++) { pRenderable->addVertex(pVerts[i]); } for (int i=0;i<noIndices;i++) { pRenderable->addIndex(pIndices[i]); } //pRenderable->create<TexturedLitVertex>(pDevice,noVerts,noIndices,pVerts,(UINT*)pIndices); if (pVerts) { delete [] pVerts; pVerts=NULL; } //} } } lSdkManager->Destroy(); return pRenderable; }