/* 首先,已知顶点位置坐标v0 v1 v2 v3…和法向量n0 n1 n2 n3…。 * (上述vi 和 ni都是数组,长度为3,表示一个三维向量) * 因此,指定3个序号,比如0,1,2代表v0v1v2即可指定一个三角形3个顶点的位置; * 又指定3个序号,比如0,2,4代表n0n2n4即可指定一个三角形3个顶点的法向量。 * 把刚才指定的序号结合在一起,即0,1,2,0,2,4,即可描述一个三角形面的位置和方向 */ void MeshModel::LoadMeshDataFrom3DE( unsigned vertexNum, int face_indicies[][6], unsigned faceIndiciesLength, float vertices[][3], unsigned verticesLength, float normals[][3], unsigned normalsLength, float colorR, float colorG, float colorB) { std::vector<float> vecVertex; std::vector<float> vecNormal; std::vector<float> vecColor; for (unsigned i = 0; i<faceIndiciesLength / sizeof(face_indicies[0]); i++) { for (unsigned j = 0; j<3; j++) { int vi = face_indicies[i][j]; int ni = face_indicies[i][j + 3];//Normal index vecVertex.push_back(vertices[vi][0]); vecVertex.push_back(vertices[vi][1]); vecVertex.push_back(vertices[vi][2]); vecNormal.push_back(normals[ni][0]); vecNormal.push_back(normals[ni][1]); vecNormal.push_back(normals[ni][2]); vecColor.push_back(colorR); vecColor.push_back(colorG); vecColor.push_back(colorB); } } LoadColor(vecColor.data(), vecColor.size()*sizeof(float), GL_FLOAT, 3); LoadVertex(vecVertex.data(), vecVertex.size()*sizeof(float), GL_FLOAT, 3); LoadNormal(vecNormal.data(), vecNormal.size()*sizeof(float), GL_FLOAT); }
void MeshModel::LoadMeshDataWithTexFrom3DE( unsigned vertexNum, int face_indicies[][9], unsigned faceIndiciesLength, float vertices[][3], unsigned verticesLength, float normals[][3], unsigned normalsLength, std::string fileName, float textures[][2], unsigned texturesLength) { std::vector<float> vecVertex; std::vector<float> vecNormal; std::vector<float> vecTexture; for (unsigned i = 0; i<faceIndiciesLength / sizeof(face_indicies[0]); i++) { for (unsigned j = 0; j<3; j++) { int vi = face_indicies[i][j]; //顶点坐标的序号 int ni = face_indicies[i][j + 3]; //法向量的序号 int ti = face_indicies[i][j + 6]; //纹理坐标的序号 vecVertex.push_back(vertices[vi][0]); vecVertex.push_back(vertices[vi][1]); vecVertex.push_back(vertices[vi][2]); vecNormal.push_back(normals[ni][0]); vecNormal.push_back(normals[ni][1]); vecNormal.push_back(normals[ni][2]); vecTexture.push_back(textures[ti][0]); vecTexture.push_back(textures[ti][1]); } } LoadVertex(vecVertex.data(), vecVertex.size()*sizeof(float), GL_FLOAT, 3); LoadNormal(vecNormal.data(), vecNormal.size()*sizeof(float), GL_FLOAT); LoadTexture(fileName, vecTexture.data(), vecTexture.size()*sizeof(float), GL_FLOAT, 2); }
std::shared_ptr<Mesh> FBXConverter::LoadMesh(FbxMesh* fbxMesh) { assert(fbxMesh->GetLayerCount() > 0); auto node = fbxMesh->GetNode(); auto layer = fbxMesh->GetLayer(0); if (layer->GetNormals() == nullptr) { fbxMesh->GenerateNormals(true); } auto uvs = layer->GetUVs(); auto vcolors = layer->GetVertexColors(); auto normals = layer->GetNormals(); auto binormals = layer->GetBinormals(); auto materials = layer->GetMaterials(); auto controlPoints = fbxMesh->GetControlPoints(); auto controlPointsCount = fbxMesh->GetControlPointsCount(); auto polygonCount = fbxMesh->GetPolygonCount(); std::vector<FbxFace> faces; // Load weights std::vector<BoneConnector> bcs_temp; std::vector<Vertex> vs_temp; LoadSkin(fbxMesh, bcs_temp, vs_temp); // generate face vertex int32_t vertexID = 0; for (int32_t polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++) { int polygonPointCount = fbxMesh->GetPolygonSize(polygonIndex); FbxFace face; for (int32_t polygonPointIndex = 0; polygonPointIndex < polygonPointCount; polygonPointIndex++) { auto ctrlPointIndex = fbxMesh->GetPolygonVertex(polygonIndex, polygonPointIndex); Vertex v; v.Position = LoadPosition(fbxMesh, ctrlPointIndex); v.Weights = vs_temp[ctrlPointIndex].Weights; if (normals != nullptr) { v.Normal = LoadNormal(normals, vertexID, ctrlPointIndex); } if (uvs != nullptr) { v.UV = LoadUV(fbxMesh, uvs, vertexID, ctrlPointIndex, polygonIndex, polygonPointIndex); } else { // Auto generated v.UV[0] = v.Position[0] + v.Position[2]; v.UV[1] = v.Position[1]; } if (vcolors != nullptr) { v.VertexColor = LoadVertexColor(fbxMesh, vcolors, vertexID, ctrlPointIndex, polygonIndex, polygonPointIndex); } face.Vertecies.push_back(v); vertexID++; } faces.push_back(face); } // 面の表裏入れ替え for (auto& face : faces) { std::reverse(face.Vertecies.begin(), face.Vertecies.end()); } // メッシュで使用可能な形式に変換 // 頂点変換テーブル作成 int32_t vInd = 0; std::map<Vertex, int32_t> v2ind; std::map<int32_t, Vertex> ind2v; for (auto& face : faces) { for (int32_t vi = 0; vi < (int32_t)face.Vertecies.size(); vi++) { auto vertex = face.Vertecies[vi]; auto it = v2ind.find(vertex); if (it == v2ind.end()) { v2ind[vertex] = vInd; ind2v[vInd] = vertex; vInd++; } } } // 設定 auto mesh = std::make_shared<Mesh>(); mesh->Name = node->GetName(); mesh->BoneConnectors = bcs_temp; mesh->Vertexes.resize(vInd); for (auto& iv : ind2v) { mesh->Vertexes[iv.first] = iv.second; } for (auto& face : faces) { if (face.Vertecies.size() < 3) continue; if (face.Vertecies.size() == 3) { Face f; f.Index[0] = v2ind[face.Vertecies[0]]; f.Index[1] = v2ind[face.Vertecies[1]]; f.Index[2] = v2ind[face.Vertecies[2]]; mesh->Faces.push_back(f); } if (face.Vertecies.size() == 4) { Face f0; f0.Index[0] = v2ind[face.Vertecies[0]]; f0.Index[1] = v2ind[face.Vertecies[1]]; f0.Index[2] = v2ind[face.Vertecies[2]]; mesh->Faces.push_back(f0); Face f1; f1.Index[0] = v2ind[face.Vertecies[0]]; f1.Index[1] = v2ind[face.Vertecies[2]]; f1.Index[2] = v2ind[face.Vertecies[3]]; mesh->Faces.push_back(f1); } } // Binormal,Tangent計算 std::map<int32_t, VertexNormals> vInd2Normals; for (const auto& face : mesh->Faces) { FbxVector4 binormal, tangent; CalcTangentSpace( mesh->Vertexes[face.Index[0]], mesh->Vertexes[face.Index[1]], mesh->Vertexes[face.Index[2]], binormal, tangent); for (auto i = 0; i < 3; i++) { vInd2Normals[face.Index[i]].Binormal += binormal; vInd2Normals[face.Index[i]].Tangent += tangent; vInd2Normals[face.Index[i]].Count += 1; } } for (auto& vn : vInd2Normals) { vn.second.Binormal /= vn.second.Count; vn.second.Tangent /= vn.second.Count; } for (auto& vn : vInd2Normals) { mesh->Vertexes[vn.first].Binormal = vn.second.Binormal; mesh->Vertexes[vn.first].Tangent = vn.second.Tangent; // 適当な値を代入する if (mesh->Vertexes[vn.first].Binormal.Length() == 0.0f) { if (mesh->Vertexes[vn.first].Normal != FbxVector4(1, 0, 0)) { mesh->Vertexes[vn.first].Binormal = FbxVector4(1, 0, 0); mesh->Vertexes[vn.first].Tangent = FbxVector4(0, 1, 0); } else { mesh->Vertexes[vn.first].Binormal = FbxVector4(0, 1, 0); mesh->Vertexes[vn.first].Tangent = FbxVector4(1, 0, 0); } } } return mesh; }