diff --git a/src/webgl/loading.js b/src/webgl/loading.js index b401217581..a068ee4cfd 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -103,6 +103,8 @@ import './p5.Geometry'; * @param {String} [fileType] * @return {p5.Geometry} the p5.Geometry object */ + +let materials = {}; //currently local p5.prototype.loadModel = function(path) { p5._validateParameters('loadModel', arguments); let normalize; @@ -150,16 +152,37 @@ p5.prototype.loadModel = function(path) { } else if (fileType.match(/\.obj$/i)) { this.loadStrings( path, - strings => { - parseObj(model, strings); - - if (normalize) { - model.normalize(); + async lines => { + const mtlLine = lines.find(line => line.startsWith('mtllib ')); + const mtlPath = mtlLine ? mtlLine.split(' ')[1] : undefined; + // console.log(mtlPath); + try{ + let parsedMaterials=null; + if(mtlPath){ + parsedMaterials=await parseMtl(mtlPath); // Pass parsed materials to OBJ parsing + } + if (parsedMaterials){ + await parseObj(model,lines, parsedMaterials); + }else { + await parseObj(model,lines); // No MTL file, parse OBJ directly + } + } catch (error) { + if (failureCallback) { + failureCallback(error); + } else { + p5._friendlyError('Error during parsing: ' + error.message); + } } + finally{ - self._decrementPreload(); - if (typeof successCallback === 'function') { - successCallback(model); + if (normalize) { + model.normalize(); + } + + self._decrementPreload(); + if (typeof successCallback === 'function') { + successCallback(model); + } } }, failureCallback @@ -238,7 +261,7 @@ function parseMtl(mtlPath){ //accepts mtlPath to load file * * f 4 3 2 1 */ -function parseObj(model, lines) { +function parseObj(model, lines, materials= {}) { // OBJ allows a face to specify an index for a vertex (in the above example), // but it also allows you to specify a custom combination of vertex, UV // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with @@ -254,6 +277,8 @@ function parseObj(model, lines) { vn: [] }; const indexedVerts = {}; + let currentMaterial = null; + for (let line = 0; line < lines.length; ++line) { // Each line is a separate object (vertex, face, vertex normal, etc) @@ -262,7 +287,10 @@ function parseObj(model, lines) { const tokens = lines[line].trim().split(/\b\s+/); if (tokens.length > 0) { - if (tokens[0] === 'v' || tokens[0] === 'vn') { + if (tokens[0] === 'usemtl') { + // Switch to a new material + currentMaterial = tokens[1]; + }else if (tokens[0] === 'v' || tokens[0] === 'vn') { // Check if this line describes a vertex or vertex normal. // It will have three numeric parameters. const vertex = new p5.Vector( @@ -314,6 +342,16 @@ function parseObj(model, lines) { if (loadedVerts.vn[vertParts[2]]) { model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy()); } + if (currentMaterial && materials[currentMaterial]) { + const diffuseColor = materials[currentMaterial].diffuseColor; + model.vertexColors.push([ + diffuseColor[0] * 255, + diffuseColor[1] * 255, + diffuseColor[2] * 255 + ]); + } else { + model.vertexColors.push([255, 255, 255]); + } } face.push(vertIndex);