-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.mtl files support for .obj files to render color in 3D custom geometry #6710
Changes from 9 commits
a47fbbc
2143dba
3498ad0
5c7c07e
b46af55
0b7a1fe
77637ba
1169993
06c5e28
2b46a55
0790146
1fa08a2
be5cf6c
cd6039d
32f94f3
16fad39
c3538b7
3cb1a13
90a3a53
2fffa53
48b07a3
341b131
60a3b06
9538edc
56bc7f2
97950c7
4e46332
104463a
a4047af
7236340
b32c935
19e4655
14a2420
687e010
2aa937f
31bdeb9
ac68110
d7aa2f7
25bbdc9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -343,7 +343,8 @@ function parseObj(model, lines, materials= {}) { | |
vn: [] | ||
}; | ||
|
||
const indexedVerts = {}; | ||
|
||
// Map from source index → Map of material → destination index | ||
const usedVerts = {}; // Track colored vertices | ||
let currentMaterial = null; | ||
for (let line = 0; line < lines.length; ++line) { | ||
|
@@ -377,57 +378,38 @@ function parseObj(model, lines, materials= {}) { | |
// OBJ faces can have more than three points. Triangulate points. | ||
for (let tri = 3; tri < tokens.length; ++tri) { | ||
const face = []; | ||
|
||
const vertexTokens = [1, tri - 1, tri]; | ||
|
||
for (let tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) { | ||
// Now, convert the given token into an index | ||
const vertString = tokens[vertexTokens[tokenInd]]; | ||
let vertIndex = 0; | ||
let vertParts; | ||
let vertParts=vertString.split('/'); | ||
|
||
// TODO: Faces can technically use negative numbers to refer to the | ||
// previous nth vertex. I haven't seen this used in practice, but | ||
// it might be good to implement this in the future. | ||
|
||
if (indexedVerts[vertString] !== undefined) { | ||
vertIndex = indexedVerts[vertString]; | ||
} else { | ||
vertParts = vertString.split('/'); | ||
for (let i = 0; i < vertParts.length; i++) { | ||
vertParts[i] = parseInt(vertParts[i]) - 1; | ||
} | ||
|
||
vertIndex = indexedVerts[vertString] = model.vertices.length; | ||
model.vertices.push(loadedVerts.v[vertParts[0]].copy()); | ||
if (loadedVerts.vt[vertParts[1]]) { | ||
model.uvs.push(loadedVerts.vt[vertParts[1]].slice()); | ||
} else { | ||
model.uvs.push([0, 0]); | ||
} | ||
for (let i = 0; i < vertParts.length; i++) { | ||
vertParts[i] = parseInt(vertParts[i]) - 1; | ||
} | ||
|
||
if (loadedVerts.vn[vertParts[2]]) { | ||
model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy()); | ||
} | ||
if (!usedVerts[vertParts[0]]) { | ||
usedVerts[vertParts[0]] = {}; | ||
} | ||
if (usedVerts[vertIndex] && usedVerts[vertIndex] | ||
!== currentMaterial) { | ||
// Duplicate vertex, UV, and normal,faces to refer to new indices | ||
vertParts = vertString.split('/'); | ||
for (let i = 0; i < vertParts.length; i++) { | ||
vertParts[i] = parseInt(vertParts[i]) - 1; | ||
} | ||
const duplicatedVertIndex = model.vertices.length; | ||
|
||
if (usedVerts[vertParts[0]][currentMaterial] === undefined) { | ||
const vertIndex = model.vertices.length; | ||
model.vertices.push(loadedVerts.v[vertParts[0]].copy()); | ||
model.uvs.push(loadedVerts.vt[vertParts[1]] ? | ||
loadedVerts.vt[vertParts[1]].slice() : [0, 0]); | ||
model.vertexNormals.push(loadedVerts.vn[vertParts[2]] ? | ||
loadedVerts.vn[vertParts[2]].copy() : new p5.Vector()); | ||
vertIndex = duplicatedVertIndex; | ||
} | ||
|
||
face.push(vertIndex); | ||
usedVerts[vertIndex] = currentMaterial; | ||
usedVerts[vertParts[0]][currentMaterial] = vertIndex; | ||
face.push(vertIndex); | ||
} else { | ||
face.push(usedVerts[vertParts[0]][currentMaterial]); | ||
} | ||
} | ||
|
||
if ( | ||
|
@@ -437,14 +419,14 @@ function parseObj(model, lines, materials= {}) { | |
) { | ||
model.faces.push(face); | ||
//same material for all vertices in a particular face | ||
const materialDiffuseColor = | ||
materials[currentMaterial].diffuseColor; | ||
for (let i=0 ;i<face.length;i++) { | ||
model.vertexColors.push([ | ||
materialDiffuseColor[0], | ||
materialDiffuseColor[1], | ||
materialDiffuseColor[2] | ||
]); | ||
if (currentMaterial && materials[currentMaterial]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now this will break if we have some vertices that don't have a material but others that do (since it means the earlier vertices won't have pushed colors to the array.) Our data needs it to be all or nothing. I don't think we need to actually support that case, but maybe we can try to detect it and throw an error if we encounter it? i.e. if we've added any vertices with no colors, and then find ourselves trying to add a vertex with color later on, throw an error letting people know they need colors for all their vertices or none. |
||
const materialDiffuseColor = | ||
materials[currentMaterial].diffuseColor; | ||
for (let i = 0; i < face.length; i++) { | ||
model.vertexColors.push(materialDiffuseColor[0]); | ||
model.vertexColors.push(materialDiffuseColor[1]); | ||
model.vertexColors.push(materialDiffuseColor[2]); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -455,7 +437,6 @@ function parseObj(model, lines, materials= {}) { | |
if (model.vertexNormals.length === 0) { | ||
model.computeNormals(); | ||
} | ||
console.log(model.vertexColors); | ||
return model; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,30 +107,30 @@ suite('loadModel', function() { | |
}; | ||
}); | ||
const expectedColors=[ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice work on this, it's great that this test can run and pass now! |
||
[0, 0, 0.5], | ||
[0, 0, 0.5], | ||
[0, 0, 0.5], | ||
[0, 0, 0.942654], | ||
[0, 0, 0.942654], | ||
[0, 0, 0.942654], | ||
[0, 0.815632, 1], | ||
[0, 0.815632, 1], | ||
[0, 0.815632, 1], | ||
[0, 0.965177, 1], | ||
[0, 0.965177, 1], | ||
[0, 0.965177, 1], | ||
[0.848654, 1, 0.151346], | ||
[0.848654, 1, 0.151346], | ||
[0.848654, 1, 0.151346], | ||
[1, 0.888635, 0], | ||
[1, 0.888635, 0], | ||
[1, 0.888635, 0], | ||
[1, 0.77791, 0], | ||
[1, 0.77791, 0], | ||
[1, 0.77791, 0], | ||
[0.5, 0, 0], | ||
[0.5, 0, 0], | ||
[0.5, 0, 0] | ||
0, 0, 0.5, | ||
0, 0, 0.5, | ||
0, 0, 0.5, | ||
0, 0, 0.942654, | ||
0, 0, 0.942654, | ||
0, 0, 0.942654, | ||
0, 0.815632, 1, | ||
0, 0.815632, 1, | ||
0, 0.815632, 1, | ||
0, 0.965177, 1, | ||
0, 0.965177, 1, | ||
0, 0.965177, 1, | ||
0.848654, 1, 0.151346, | ||
0.848654, 1, 0.151346, | ||
0.848654, 1, 0.151346, | ||
1, 0.888635, 0, | ||
1, 0.888635, 0, | ||
1, 0.888635, 0, | ||
1, 0.77791, 0, | ||
1, 0.77791, 0, | ||
1, 0.77791, 0, | ||
0.5, 0, 0, | ||
0.5, 0, 0, | ||
0.5, 0, 0 | ||
]; | ||
assert.deepEqual(model.vertexColors,expectedColors); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,4 +34,20 @@ visualSuite('WebGL', function() { | |
screenshot(); | ||
}); | ||
}); | ||
}); | ||
|
||
visualSuite('3DModel', function() { | ||
visualTest('OBJ model with MTL file displays diffuse colors correctly', function(p5, screenshot) { | ||
return new Promise(resolve => { | ||
p5.createCanvas(50, 50, p5.WEBGL); | ||
p5.loadModel('unit/assets/octa-color.obj', model => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now the screenshot looks like just a dot. Maybe to make this clearer we can call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can also add one more test importing an object with no colors, and then drawing it with a colored |
||
p5.background(200); | ||
p5.rotateX(10 * 0.01); | ||
p5.rotateY(10 * 0.01); | ||
p5.model(model); | ||
screenshot(); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"numScreenshots": 1 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!