MCPcopy Create free account
hub / github.com/OpenNFS/OpenNFS / LoadFCE

Method LoadFCE

src/Loaders/nfs4_loader.cpp:58–138  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

56}
57
58std::vector<CarModel> NFS4::LoadFCE(const std::string &fce_path) {
59 std::cout << "- Parsing FCE File: " << fce_path << std::endl;
60 glm::quat rotationMatrix = glm::normalize(glm::quat(glm::vec3(-SIMD_PI / 2, 0, 0))); // All Vertices are stored so that the model is rotated 90 degs on X. Remove this at Vert load time.
61 std::vector<CarModel> meshes;
62 bool isTraffic = fce_path.find("TRAFFIC") != std::string::npos;
63
64 ifstream fce(fce_path, ios::in | ios::binary);
65
66 auto *fceHeader = new FCE::NFS4::HEADER();
67 fce.read((char *) fceHeader, sizeof(FCE::NFS4::HEADER));
68
69
70 for (uint32_t part_Idx = 0; part_Idx < fceHeader->nParts; ++part_Idx) {
71 float specularDamper = 0.2f;
72 float specularReflectivity = 0.02f;
73 float envReflectivity = 0.4f;
74
75 std::vector<uint32_t> indices;
76 std::vector<uint32_t> polygonFlags;
77 std::vector<glm::vec3> vertices;
78 std::vector<glm::vec3> normals;
79 std::vector<glm::vec2> uvs;
80
81 std::string part_name(fceHeader->partNames[part_Idx]);
82 glm::vec3 center = rotationMatrix * glm::vec3(fceHeader->partCoords[part_Idx].x / 10, fceHeader->partCoords[part_Idx].y / 10, fceHeader->partCoords[part_Idx].z / 10);
83
84 auto *partVertices = new FLOATPT[fceHeader->partNumVertices[part_Idx]];
85 auto *partNormals = new FLOATPT[fceHeader->partNumVertices[part_Idx]];
86 auto *partTriangles = new FCE::TRIANGLE[fceHeader->partNumTriangles[part_Idx]];
87
88 fce.seekg(sizeof(FCE::NFS4::HEADER) + fceHeader->vertTblOffset + (fceHeader->partFirstVertIndices[part_Idx] * sizeof(FLOATPT)), ios_base::beg);
89 fce.read((char *) partVertices, fceHeader->partNumVertices[part_Idx] * sizeof(FLOATPT));
90 for (uint32_t vert_Idx = 0; vert_Idx < fceHeader->partNumVertices[part_Idx]; ++vert_Idx) {
91 vertices.emplace_back(rotationMatrix * glm::vec3(partVertices[vert_Idx].x / 10, partVertices[vert_Idx].y / 10, partVertices[vert_Idx].z / 10));
92 }
93
94 fce.seekg(sizeof(FCE::NFS4::HEADER) + fceHeader->normTblOffset + (fceHeader->partFirstVertIndices[part_Idx] * sizeof(FLOATPT)), ios_base::beg);
95 fce.read((char *) partNormals, fceHeader->partNumVertices[part_Idx] * sizeof(FLOATPT));
96 for (uint32_t normal_Idx = 0; normal_Idx < fceHeader->partNumVertices[part_Idx]; ++normal_Idx) {
97 normals.emplace_back(rotationMatrix * glm::vec3(partNormals[normal_Idx].x, partNormals[normal_Idx].y, partNormals[normal_Idx].z));
98 }
99
100 fce.seekg(sizeof(FCE::NFS4::HEADER) + fceHeader->triTblOffset + (fceHeader->partFirstTriIndices[part_Idx] * sizeof(FCE::TRIANGLE)), ios_base::beg);
101 fce.read((char *) partTriangles, fceHeader->partNumTriangles[part_Idx] * sizeof(FCE::TRIANGLE));
102 for (uint32_t tri_Idx = 0; tri_Idx < fceHeader->partNumTriangles[part_Idx]; ++tri_Idx) {
103 polygonFlags.emplace_back(partTriangles[tri_Idx].polygonFlags);
104 polygonFlags.emplace_back(partTriangles[tri_Idx].polygonFlags);
105 polygonFlags.emplace_back(partTriangles[tri_Idx].polygonFlags);
106 parsePolygonFlags(tri_Idx, partTriangles[tri_Idx].polygonFlags);
107 indices.emplace_back(partTriangles[tri_Idx].vertex[0]);
108 indices.emplace_back(partTriangles[tri_Idx].vertex[1]);
109 indices.emplace_back(partTriangles[tri_Idx].vertex[2]);
110 if (isTraffic) {
111 uvs.emplace_back(glm::vec2(partTriangles[tri_Idx].uvTable[0], partTriangles[tri_Idx].uvTable[3]));
112 uvs.emplace_back(glm::vec2(partTriangles[tri_Idx].uvTable[1], partTriangles[tri_Idx].uvTable[4]));
113 uvs.emplace_back(glm::vec2(partTriangles[tri_Idx].uvTable[2], partTriangles[tri_Idx].uvTable[5]));
114 } else {
115 uvs.emplace_back(glm::vec2(partTriangles[tri_Idx].uvTable[0], 1.0f - partTriangles[tri_Idx].uvTable[3]));

Callers

nothing calls this directly

Calls 2

parsePolygonFlagsFunction · 0.85
CarModelClass · 0.85

Tested by

no test coverage detected