Skip to content

Commit 0b09791

Browse files
committed
chg. refactor material conversion
1 parent 50a3a2c commit 0b09791

8 files changed

Lines changed: 76 additions & 77 deletions

File tree

131 KB
Binary file not shown.

examples/01_model/assets/model.glb

19.4 KB
Binary file not shown.

tools/gltf_importer/src/converter/meshConverter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ T3DM::ModelChunked chunkUpModel(const T3DM::Model &model)
137137
};
138138
res.chunks.reserve(model.triangles.size() * 3 / T3DM::MAX_VERTEX_COUNT);
139139
res.chunks.push_back(T3DM::MeshChunk{});
140-
res.chunks.back().material = model.material;
140+
res.chunks.back().materialName = model.materialName;
141141
res.chunks.back().name = model.name;
142142

143143
uint32_t emittedVerts = 0;
@@ -235,7 +235,7 @@ T3DM::ModelChunked chunkUpModel(const T3DM::Model &model)
235235
}
236236
}
237237

238-
res.chunks.push_back(T3DM::MeshChunk{.material = model.material, .name = model.name});
238+
res.chunks.push_back(T3DM::MeshChunk{.materialName = model.materialName, .name = model.name});
239239

240240
chunkOffset += emittedVerts;
241241
emittedVerts = 0;

tools/gltf_importer/src/parser.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,18 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath)
186186
//printf(" - Primitive %d:\n", j);
187187

188188
if(prim->material) {
189-
parseMaterial(gltfBasePath, i, j, model, prim);
189+
auto matName = prim->material->name;
190+
if(matName && matName[0] && t3dm.materials.find(matName) == t3dm.materials.end()) {
191+
t3dm.materials[matName] = parseMaterial(gltfBasePath, prim);
192+
}
193+
model.materialName = matName ? matName : "";
194+
}
195+
196+
if(model.materialName.empty())
197+
{
198+
printf("Skipping model '%s', no material assigned!\n", model.name.c_str());
199+
t3dm.models.pop_back();
200+
continue;
190201
}
191202

192203
// find vertex count
@@ -319,8 +330,9 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath)
319330
std::vector<VertexT3D> verticesT3D{};
320331
verticesT3D.resize(vertices.size());
321332

322-
float texSizeX = model.material.texA.texWidth;
323-
float texSizeY = model.material.texA.texHeight;
333+
auto &material = t3dm.materials[model.materialName];
334+
float texSizeX = material.texA.texWidth;
335+
float texSizeY = material.texA.texHeight;
324336

325337
if(texSizeX == 0)texSizeX = 32;
326338
if(texSizeY == 0)texSizeY = 32;
@@ -330,7 +342,7 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath)
330342
for(int k = 0; k < vertices.size(); k++) {
331343
convertVertex(
332344
config.globalScale, texSizeX, texSizeY, vertices[k], verticesT3D[k],
333-
mat, matrixStack, model.material.uvFilterAdjust
345+
mat, matrixStack, material.uvFilterAdjust
334346
);
335347
}
336348

@@ -360,18 +372,17 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath)
360372

361373
// sort models by transparency mode (opaque -> cutout -> transparent)
362374
// within the same transparency mode, sort by material
363-
std::sort(t3dm.models.begin(), t3dm.models.end(), [](const T3DM::Model &a, const T3DM::Model &b) {
364-
bool isTranspA = a.material.blendMode == RDP::BLEND::MULTIPLY;
365-
bool isTranspB = b.material.blendMode == RDP::BLEND::MULTIPLY;
375+
std::sort(t3dm.models.begin(), t3dm.models.end(), [&t3dm](const T3DM::Model &a, const T3DM::Model &b) {
376+
auto &matA = t3dm.materials[a.materialName];
377+
auto &matB = t3dm.materials[b.materialName];
378+
bool isTranspA = matA.blendMode == RDP::BLEND::MULTIPLY;
379+
bool isTranspB = matB.blendMode == RDP::BLEND::MULTIPLY;
366380
if(isTranspA == isTranspB) {
367-
if(a.material.uuid == b.material.uuid) {
368-
return a.name < b.name;
369-
}
370-
return a.material.uuid < b.material.uuid;
381+
return a.name < b.name;
371382
}
372383
if(!isTranspA && !isTranspB) {
373-
int isDecalA = (a.material.otherModeValue & RDP::SOM::ZMODE_DECAL) ? 1 : 0;
374-
int isDecalB = (b.material.otherModeValue & RDP::SOM::ZMODE_DECAL) ? 1 : 0;
384+
int isDecalA = (matA.otherModeValue & RDP::SOM::ZMODE_DECAL) ? 1 : 0;
385+
int isDecalB = (matB.otherModeValue & RDP::SOM::ZMODE_DECAL) ? 1 : 0;
375386
return isDecalA < isDecalB;
376387
}
377388
return isTranspB;

tools/gltf_importer/src/parser/materialParser.cpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,17 @@ namespace {
179179
}
180180
}
181181

182-
void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &model, cgltf_primitive *prim) {
183-
model.material.uuid = j * 1000 + i;
182+
T3DM::Material T3DM::parseMaterial(const fs::path &gltfBasePath, cgltf_primitive *prim) {
183+
184+
Material material{};
184185
if(prim->material->name) {
185-
model.material.uuid = stringHash(prim->material->name);
186-
model.material.name = prim->material->name;
186+
material.name = prim->material->name;
187187
}
188188
//printf(" Material: %s\n", prim->material->name);
189189

190-
if(config.ignoreMaterials) {
190+
if(config.ignoreMaterials || material.name.empty()) {
191191
printf("Ignoring material\n");
192-
return;
192+
return material;
193193
}
194194

195195
if(prim->material->extras.data == nullptr) {
@@ -219,23 +219,23 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
219219
auto cc2 = readCCFromJson(f3dData["combiner2"]);
220220
bool is2Cycle = true;
221221

222-
model.material.drawFlags = DrawFlags::DEPTH;
223-
model.material.blendColor[3] = 128; // default in case cutout is used
222+
material.drawFlags = DrawFlags::DEPTH;
223+
material.blendColor[3] = 128; // default in case cutout is used
224224

225-
model.material.setPrimColor = false;
225+
material.setPrimColor = false;
226226
if(f3dData.contains("set_prim")) {
227-
model.material.setPrimColor = f3dData["set_prim"].get<uint32_t>() != 0;
228-
readColor(f3dData["prim_color"], model.material.primColor);
227+
material.setPrimColor = f3dData["set_prim"].get<uint32_t>() != 0;
228+
readColor(f3dData["prim_color"], material.primColor);
229229
}
230230

231231
if(f3dData.contains("set_env")) {
232-
model.material.setEnvColor = f3dData["set_env"].get<uint32_t>() != 0;
233-
readColor(f3dData["env_color"], model.material.envColor);
232+
material.setEnvColor = f3dData["set_env"].get<uint32_t>() != 0;
233+
readColor(f3dData["env_color"], material.envColor);
234234
}
235235

236236
if(f3dData.contains("set_blend")) {
237-
model.material.setBlendColor = f3dData["set_blend"].get<uint32_t>() != 0;
238-
readColor(f3dData["blend_color"], model.material.blendColor);
237+
material.setBlendColor = f3dData["set_blend"].get<uint32_t>() != 0;
238+
readColor(f3dData["blend_color"], material.blendColor);
239239
}
240240

241241
if(f3dData.contains("rdp_settings"))
@@ -244,13 +244,13 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
244244
is2Cycle = rdpSettings["g_mdsft_cycletype"].get<uint32_t>() != 0;
245245

246246
if(rdpSettings["g_cull_back"].get<uint32_t>() != 0) {
247-
model.material.drawFlags |= DrawFlags::CULL_BACK;
247+
material.drawFlags |= DrawFlags::CULL_BACK;
248248
}
249249
if(rdpSettings["g_cull_front"].get<uint32_t>() != 0) {
250-
model.material.drawFlags |= DrawFlags::CULL_FRONT;
250+
material.drawFlags |= DrawFlags::CULL_FRONT;
251251
}
252252

253-
model.material.fogMode = rdpSettings["g_fog"].get<uint32_t>() + 1;
253+
material.fogMode = rdpSettings["g_fog"].get<uint32_t>() + 1;
254254

255255
uint32_t texFilter = rdpSettings["g_mdsft_text_filt"].get<uint32_t>() & 0b11;
256256
uint64_t textFilterMap[3] = {
@@ -260,10 +260,10 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
260260
};
261261
otherModeValue |= textFilterMap[texFilter];
262262

263-
model.material.uvFilterAdjust = texFilter != 0;
263+
material.uvFilterAdjust = texFilter != 0;
264264

265265
uint32_t texGen = rdpSettings["g_tex_gen"].get<uint32_t>();
266-
model.material.vertexFxFunc = (texGen != 0) ? UvGenFunc::SPHERE : UvGenFunc::NONE;
266+
material.vertexFxFunc = (texGen != 0) ? UvGenFunc::SPHERE : UvGenFunc::NONE;
267267

268268
/*uint32_t alphaComp = rdpSettings["g_mdsft_alpha_compare"].get<uint32_t>();
269269
if(alphaComp == 1) {
@@ -288,7 +288,7 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
288288
otherModeValue |= RDP::SOM::BLALPHA_CVG_X_CC | RDP::SOM::BLALPHA_CVG;
289289
}*/
290290

291-
model.material.blendMode = is2Cycle ? blenderMode2 : blenderMode1;
291+
material.blendMode = is2Cycle ? blenderMode2 : blenderMode1;
292292

293293
} else {
294294
// if no render mode is set, we need to check the draw layer
@@ -300,46 +300,46 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
300300
if(layerOOT > layerSM64) {
301301
switch(layerOOT) {
302302
default: // has only 3 distinct layers:
303-
case 0: model.material.blendMode = RDP::BLEND::NONE; break; // Opaque
304-
case 1: model.material.blendMode = RDP::BLEND::MULTIPLY; break; // Transparent
303+
case 0: material.blendMode = RDP::BLEND::NONE; break; // Opaque
304+
case 1: material.blendMode = RDP::BLEND::MULTIPLY; break; // Transparent
305305
case 2:
306-
model.material.blendMode = RDP::BLEND::NONE;
306+
material.blendMode = RDP::BLEND::NONE;
307307
otherModeValue |= RDP::SOM::ALPHA_COMPARE;
308308
break; // Overlay
309309
}
310310
} else {
311311
// has multiple layers with variants (e.g. intersecting) ignore the finer details here:
312312
if(layerSM64 <= 1) {
313-
model.material.blendMode = RDP::BLEND::NONE;
313+
material.blendMode = RDP::BLEND::NONE;
314314
} else if(layerSM64 <= 4) {
315-
model.material.blendMode = RDP::BLEND::NONE;
315+
material.blendMode = RDP::BLEND::NONE;
316316
otherModeValue |= RDP::SOM::ALPHA_COMPARE;
317317
} else {
318-
model.material.blendMode = RDP::BLEND::MULTIPLY;
318+
material.blendMode = RDP::BLEND::MULTIPLY;
319319
}
320320
}
321321
}
322322
}
323323

324-
if(model.material.fogMode == FogMode::ACTIVE || isUsingShade(cc1) || (is2Cycle && isUsingShade(cc2))) {
325-
model.material.drawFlags |= DrawFlags::SHADED;
324+
if(material.fogMode == FogMode::ACTIVE || isUsingShade(cc1) || (is2Cycle && isUsingShade(cc2))) {
325+
material.drawFlags |= DrawFlags::SHADED;
326326
}
327327

328328
if(isCCUsingTexture(cc1) || (is2Cycle && isCCUsingTexture(cc2))) {
329-
model.material.drawFlags |= DrawFlags::TEXTURED;
329+
material.drawFlags |= DrawFlags::TEXTURED;
330330

331-
if(f3dData.contains("tex0"))readMaterialFromJson(model.material.texA, f3dData["tex0"], gltfBasePath);
332-
if(f3dData.contains("tex1"))readMaterialFromJson(model.material.texB, f3dData["tex1"], gltfBasePath);
331+
if(f3dData.contains("tex0"))readMaterialFromJson(material.texA, f3dData["tex0"], gltfBasePath);
332+
if(f3dData.contains("tex1"))readMaterialFromJson(material.texB, f3dData["tex1"], gltfBasePath);
333333
}
334334

335335
if(is2Cycle) {
336-
model.material.colorCombiner = RDPQ_COMBINER_2PASS |
336+
material.colorCombiner = RDPQ_COMBINER_2PASS |
337337
rdpq_2cyc_comb2a_rgb(cc1.a, cc1.b, cc1.c, cc1.d) |
338338
rdpq_2cyc_comb2a_alpha(cc1.aAlpha, cc1.bAlpha, cc1.cAlpha, cc1.dAlpha) |
339339
rdpq_2cyc_comb2b_rgb(cc2.a, cc2.b, cc2.c, cc2.d) |
340340
rdpq_2cyc_comb2b_alpha(cc2.aAlpha, cc2.bAlpha, cc2.cAlpha, cc2.dAlpha);
341341
} else {
342-
model.material.colorCombiner =
342+
material.colorCombiner =
343343
rdpq_1cyc_comb_rgb(cc1.a, cc1.b, cc1.c, cc1.d) |
344344
rdpq_1cyc_comb_alpha(cc1.aAlpha, cc1.bAlpha, cc1.cAlpha, cc1.dAlpha);
345345
}
@@ -348,6 +348,7 @@ void T3DM::parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &mode
348348
printf("No Fast64 Material data found!\n");
349349
}
350350

351-
model.material.otherModeValue = otherModeValue;
352-
model.material.otherModeMask = otherModeMask;
351+
material.otherModeValue = otherModeValue;
352+
material.otherModeMask = otherModeMask;
353+
return material;
353354
}

tools/gltf_importer/src/parser/parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace fs = std::filesystem;
1818

1919
namespace T3DM
2020
{
21-
void parseMaterial(const fs::path &gltfBasePath, int i, int j, Model &model, cgltf_primitive *prim);
21+
Material parseMaterial(const fs::path &gltfBasePath, cgltf_primitive *prim);
2222
Mat4 parseNodeMatrix(const cgltf_node *node, bool recursive);
2323
Bone parseBoneTree(const cgltf_node *rootBone, Bone *parentBone, int &count);
2424
Anim parseAnimation(const cgltf_animation &anim, const std::unordered_map<std::string, const Bone*> &nodeMap, uint32_t sampleRate);

tools/gltf_importer/src/structs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ namespace T3DM
133133
uint32_t blendMode{};
134134
uint32_t drawFlags{};
135135

136-
uint32_t uuid{};
137136
uint8_t fogMode{};
138137
uint8_t vertexFxFunc{};
139138

@@ -152,7 +151,7 @@ namespace T3DM
152151
std::vector<int16_t> stripIndices[4]{};
153152
uint8_t seqStart{0};
154153
uint8_t seqCount{0};
155-
Material material{};
154+
std::string materialName{};
156155
uint32_t vertexOffset{0};
157156
uint32_t vertexCount{0};
158157
uint32_t vertexDestOffset{0};
@@ -164,7 +163,7 @@ namespace T3DM
164163
struct Model {
165164
std::vector<TriangleT3D> triangles{};
166165
std::string name{};
167-
Material material{};
166+
std::string materialName{};
168167
};
169168

170169
struct ModelChunked {
@@ -255,6 +254,7 @@ namespace T3DM
255254
std::vector<Model> models{};
256255
std::vector<Bone> skeletons{};
257256
std::vector<Anim> animations{};
257+
std::unordered_map<std::string, Material> materials{};
258258
};
259259

260260
struct Config {

tools/gltf_importer/src/writer.cpp

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,27 +73,13 @@ void T3DM::writeT3DM(
7373
{
7474
auto &config = T3DM::config;
7575

76-
// de-dupe materials and determine material indices
77-
std::unordered_map<uint32_t, uint32_t> materialUUIDMap{};
78-
std::vector<const Material*> usedMaterials{};
79-
{
80-
uint32_t nextMatIndex = 0;
81-
for(auto &model : t3dm.models) {
82-
auto matIdxIt = materialUUIDMap.find(model.material.uuid);
83-
if(matIdxIt == materialUUIDMap.end()) {
84-
materialUUIDMap.emplace(model.material.uuid, nextMatIndex++);
85-
usedMaterials.push_back(&model.material);
86-
}
87-
}
88-
}
89-
9076
int16_t aabbMin[3] = {32767, 32767, 32767};
9177
int16_t aabbMax[3] = {-32768, -32768, -32768};
9278

9379
uint32_t chunkIndex = 0;
9480
uint32_t chunkCount = 2; // vertices + indices
9581
if(config.createBVH)chunkCount += 1;
96-
chunkCount += usedMaterials.size();
82+
chunkCount += t3dm.materials.size();
9783
chunkCount += customChunks.size();
9884

9985
std::vector<ModelChunked> modelChunks{};
@@ -213,8 +199,10 @@ void T3DM::writeT3DM(
213199
}
214200

215201
// write used materials
216-
for(auto &material_ : usedMaterials) {
217-
auto &material = *material_;
202+
std::unordered_map<std::string, uint32_t> materialMap{};
203+
for(auto &material_ : t3dm.materials) {
204+
auto &material = material_.second;
205+
materialMap[material.name] = materialMap.size();
218206
auto f = std::make_shared<BinaryFile>();
219207
f->write(material.colorCombiner);
220208
f->write(material.otherModeValue);
@@ -236,10 +224,9 @@ void T3DM::writeT3DM(
236224
f->writeArray(material.blendColor, 4);
237225
f->write(insertString(stringTable, material.name));
238226

239-
// @TODO: refactor materials to match file/runtime structure
240-
std::vector<const T3DM::MaterialTexture*> materials{&material.texA, &material.texB};
241-
for(const T3DM::MaterialTexture* mat_ : materials) {
242-
const T3DM::MaterialTexture&mat = *mat_;
227+
std::vector materials{&material.texA, &material.texB};
228+
for(const MaterialTexture* mat_ : materials) {
229+
const MaterialTexture&mat = *mat_;
243230

244231
f->write(mat.texReference);
245232
std::string texPath = "";
@@ -294,7 +281,7 @@ void T3DM::writeT3DM(
294281
for(auto &model : t3dm.models)
295282
{
296283
addToChunkTable('O');
297-
uint32_t matIdx = materialUUIDMap[model.material.uuid];
284+
uint32_t matIdx = materialMap[model.materialName];
298285

299286
// write object chunk
300287
const auto &chunks = modelChunks[m];

0 commit comments

Comments
 (0)