Cogs.Core
OpenFlightLoader.cpp
1#include "OpenFlightLoader.h"
2
3#include <mgapiall.h>
4
5#include "Context.h"
6
7Cogs::Core::Extensions::OpenFlightLoader::OpenFlightLoader()
8{
9 int i = 0;
10 mgInit(&i, 0);
11}
12
13bool Cogs::Core::Extensions::OpenFlightLoader::canLoadModel(Context * context, const std::string & fileName)
14{
15 auto ext = fileName.substr(fileName.rfind("."), fileName.size() - 1);
16
17 return ext == ".flt";
18}
19
20#include <unordered_map>
21
22namespace
23{
24 struct ParseContext
25 {
26 ParseContext()
27 {
28 const size_t reserve = 100000;
29
30 positions.reserve(reserve);
31 normals.reserve(reserve);
32 texCoords.reserve(reserve);
33
34 currentIndex = -1;
35 }
36
37 std::vector<glm::vec3> positions;
38 std::vector<glm::vec3> normals;
39 std::vector<glm::vec2> texCoords;
40
41 int currentIndex;
42
43 std::vector<std::vector<uint32_t>> subMeshes;
44 std::unordered_map<int, int> subMeshMapping;
45 };
46}
47
48static void ParsePolygon(mgrec * rec, void * userData)
49{
50 auto & parseContext = *(reinterpret_cast<ParseContext *>(userData));
51
52 mgrec * vertex = mgGetChild(rec);
53 mgcoord3d pos;
54 int count = 0;
55 bool useTexture = false;
56
57 glm::vec3 positions[4];
58 glm::vec3 normals[4];
59 glm::vec2 texCoords[4];
60
61 while (vertex) {
62 if (count < 4) {
63 if (mgGetVtxCoord(vertex, &pos.x, &pos.y, &pos.z) == MG_TRUE) {
64 positions[count] = glm::vec3(pos.x, pos.y, pos.z);
65 }
66
67 if (mgGetVtxNormal(vertex, &normals[count].x, &normals[count].y, &normals[count].z) == MG_TRUE) {
68
69 }
70
71 float u, v;
72 if (mgGetAttList(vertex, fltVU, &u, fltVV, &v, MG_NULL) == 2) {
73 texCoords[count] = glm::vec2(u, 1.0 - v);
74 useTexture = true;
75 }
76 }
77
78 vertex = mgGetNext(vertex);
79 count++;
80 }
81
82 if (count == 3 || count == 4) {
83 short textureIndex = -1;
84 short textureMappingIndex = -1;
85
86 mgGetAttList(rec,
87 fltPolyTexture, &textureIndex,
88 MG_NULL);
89
90 if (textureIndex > -1) {
91 if (textureIndex != parseContext.currentIndex) {
92 parseContext.currentIndex = parseContext.subMeshMapping[textureIndex];
93 }
94 } else {
95 parseContext.currentIndex = 0;
96 }
97
98 auto & subMeshIndexes = parseContext.subMeshes[parseContext.currentIndex];
99 const auto start = parseContext.positions.size();
100
101 if (count == 3) {
102 subMeshIndexes.push_back(start);
103 subMeshIndexes.push_back(start + 1);
104 subMeshIndexes.push_back(start + 2);
105
106 parseContext.positions.push_back(positions[0]);
107 parseContext.positions.push_back(positions[1]);
108 parseContext.positions.push_back(positions[2]);
109
110 parseContext.normals.push_back(normals[0]);
111 parseContext.normals.push_back(normals[1]);
112 parseContext.normals.push_back(normals[2]);
113
114 if (useTexture) {
115 parseContext.texCoords.push_back(texCoords[0]);
116 parseContext.texCoords.push_back(texCoords[1]);
117 parseContext.texCoords.push_back(texCoords[2]);
118 }
119 } else {
120 subMeshIndexes.push_back(start);
121 subMeshIndexes.push_back(start + 1);
122 subMeshIndexes.push_back(start + 2);
123
124 subMeshIndexes.push_back(start);
125 subMeshIndexes.push_back(start + 2);
126 subMeshIndexes.push_back(start + 3);
127
128 parseContext.positions.push_back(positions[0]);
129 parseContext.positions.push_back(positions[1]);
130 parseContext.positions.push_back(positions[2]);
131 parseContext.positions.push_back(positions[3]);
132
133 parseContext.normals.push_back(normals[0]);
134 parseContext.normals.push_back(normals[1]);
135 parseContext.normals.push_back(normals[2]);
136 parseContext.normals.push_back(normals[3]);
137
138 if (useTexture) {
139 parseContext.texCoords.push_back(texCoords[0]);
140 parseContext.texCoords.push_back(texCoords[1]);
141 parseContext.texCoords.push_back(texCoords[2]);
142 parseContext.texCoords.push_back(texCoords[3]);
143 }
144 }
145 } else {
146 return;
147 }
148}
149
150static mgbool Parse(mgrec * db, mgrec * parent, mgrec * rec, void * userData)
151{
152 if (mgGetCode(rec) == fltPolygon) {
153 ParsePolygon(rec, userData);
154 } else if (mgGetCode(rec) == fltMesh) {
155 return (MG_TRUE);
156 }
157
158 return (MG_TRUE);
159}
160
161Cogs::Core::ModelHandle Cogs::Core::Extensions::OpenFlightLoader::loadModel(Context * context, const std::string & fileName)
162{
163 auto & modelManager = context->modelManager;
164
165 ParseContext parseContext;
166
167 mgrec * db = mgOpenDb(fileName.c_str());
168
169 auto modelHandle = modelManager.createModel();
170 auto modelData = modelManager.getModel(modelHandle);
171
172 SubModel subModel;
173 subModel.transform = glm::mat4(1.0f);
174 subModel.mesh = modelManager.createMesh();
175
176 int texCount = mgGetTextureCount(db);
177
178 auto defmaterialHandle = context->materialManager.createMaterialInstance(context->materialManager.getDefaultMaterial());
179 auto defmaterial = context->materialManager.getMaterialInstance(defmaterialHandle);
180
181 defmaterial->vectorProperties["diffuseColor"] = glm::vec4(1, 1, 1, 1);
182
183 subModel.materials.push_back(defmaterialHandle);
184
185 parseContext.subMeshMapping[-1] = parseContext.subMeshes.size();
186 parseContext.subMeshes.push_back(std::vector<uint32_t>());
187
188 int textureIndex = 0;
189 char * textureName = nullptr;
190
191 mgbool hasTexture = mgGetFirstTexture(db, &textureIndex, textureName);
192
193 while (hasTexture) {
194 auto name = mgGetTextureName(db, textureIndex);
195
196 if (name) {
197 auto materialHandle = context->materialManager.createMaterialInstance(context->materialManager.getDefaultMaterial());
198 auto material = context->materialManager.getMaterialInstance(materialHandle);
199
200 material->vectorProperties["diffuseColor"] = glm::vec4(1, 1, 1, 1);
201
202 auto tName = std::string(name);
203 auto ext = tName.substr(tName.rfind("."), tName.size() - 1);
204
205 if (ext == ".inta" || ext == ".rgba") {
206
207 } else {
208 auto texture = context->textureManager.loadTexture(std::string(name));
209
210 if (texture != TextureHandle::NoHandle) {
211 material->textureProperties["diffuseMap"] = texture;
212
213 if (!defmaterial->textureProperties.size()) {
214 defmaterial->textureProperties["diffuseMap"] = material->textureProperties["diffuseMap"];
215 }
216 }
217 }
218
219 subModel.materials.push_back(materialHandle);
220
221 parseContext.subMeshMapping[textureIndex] = parseContext.subMeshes.size();
222 parseContext.subMeshes.push_back(std::vector<uint32_t>());
223 }
224
225 hasTexture = mgGetNextTexture(db, &textureIndex, textureName);
226 }
227
228 mgWalk(db, Parse, MG_NULL, &parseContext, MWALK_NOREADONLY);
229
230 auto mesh = modelManager.getMesh(subModel.mesh);
231
232 mesh->count = parseContext.positions.size();
233 mesh->setPositions(std::move(parseContext.positions));
234 mesh->setNormals(std::move(parseContext.normals));
235 mesh->setTexCoords(std::move(parseContext.texCoords));
236
237 for (auto & p : parseContext.subMeshes) {
238 mesh->addSubMesh(std::move(p), false);
239 }
240
241 modelData->subModels.push_back(std::move(subModel));
242
243 mgCloseDb(db);
244
245 return modelHandle;
246}
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.