Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/webgl/loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,21 @@ async function loadMaterialTextures(materials, modelPath, instance) {
// as the aggregate; each part gets its own localised verts with faces re-indexed
// against them, plus its material's state.
function buildMaterialParts(model, faceMaterials, materials) {
// only split when there are genuinely multiple materials. a single material
// (or none) stays as the geometry's own part and renders as before. one group
// per material, plus a null group for faces before any usemtl so none drop.
// one group per material, plus a null group for faces before any usemtl so
// none drop.
const names = [...new Set(faceMaterials)];

// one material covering every face. the geometry is already its own part, so
// hand it the state directly: splitting would duplicate every vertex to say
// the same thing, and would stop parts[0] being the geometry itself. without
// this a single material model never receives its maps at all.
if (names.length === 1 && names[0] != null) {
Object.assign(model.partState, mtlToPartState(materials[names[0]]));
return;
}

// nothing to split on: no materials, or one material alongside faces that
// were declared before any usemtl and so have none.
if (names.filter(name => name != null).length < 2) return;

const hasUvs = model.uvs.length > 0;
Expand Down
5 changes: 5 additions & 0 deletions test/unit/assets/single_material_textured.mtl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
newmtl only
Kd 1.000 1.000 1.000
Ks 0.500 0.500 0.500
Ns 60
map_Kd cat.jpg
12 changes: 12 additions & 0 deletions test/unit/assets/single_material_textured.obj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mtllib single_material_textured.mtl
v 0 0 0
v 1 0 0
v 1 1 0
v 0 1 0
vt 0 0
vt 1 0
vt 1 1
vt 0 1
usemtl only
f 1/1 2/2 3/3
f 1/1 3/3 4/4
19 changes: 19 additions & 0 deletions test/unit/io/loadModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,25 @@ suite('loadModel', function () {
assert.equal(model.parts[0], model, 'the geometry is its own single part');
});

test('a single-material OBJ still receives its maps', async function () {
const fakeImage = { width: 1, height: 1 };
mockP5Prototype.loadImage = async () => fakeImage;
try {
const model = await mockP5Prototype.loadModel(
'/test/unit/assets/single_material_textured.obj'
);
// one material, so no split: the geometry stays its own only part
assert.equal(model.parts.length, 1);
assert.equal(model.parts[0], model);
// and it carries the material's state rather than dropping it
assert.equal(model.partState.texture, fakeImage);
assert.equal(model.partState.shininess, 60);
assert.deepEqual(model.partState.specularColor, [0.5, 0.5, 0.5]);
} finally {
delete mockP5Prototype.loadImage;
}
});

test('a 12-material OBJ splits into 12 parts', async function () {
const model = await mockP5Prototype.loadModel(
'/test/unit/assets/multi_material_12.obj'
Expand Down
Loading