Skip to content

Commit

Permalink
Merge pull request #7165 from Garima3110/createModel
Browse files Browse the repository at this point in the history
Solves issue #6891
  • Loading branch information
davepagurek authored Aug 20, 2024
2 parents 26a194e + 35056cf commit 0312e44
Showing 1 changed file with 173 additions and 1 deletion.
174 changes: 173 additions & 1 deletion src/webgl/loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import p5 from '../core/main';
import './p5.Geometry';


/**
* Loads a 3D model to create a
* <a href="#/p5.Geometry">p5.Geometry</a> object.
Expand Down Expand Up @@ -1129,4 +1130,175 @@ p5.prototype.model = function(model) {
}
};

export default p5;
/**
* Load a 3d model from an OBJ or STL string.
*
* OBJ and STL files lack a built-in sense of scale, causing models exported from different programs to vary in size.
* If your model doesn't display correctly, consider using `loadModel()` with `normalize` set to `true` to standardize its size.
* Further adjustments can be made using the `scale()` function.
*
* Also, the support for colored STL files is not present. STL files with color will be
* rendered without color properties.
*
* * Options can include:
* - `modelString`: Specifies the plain text string of either an stl or obj file to be loaded.
* - `fileType`: Defines the file extension of the model.
* - `normalize`: Enables standardized size scaling during loading if set to true.
* - `successCallback`: Callback for post-loading actions with the 3D model object.
* - `failureCallback`: Handles errors if model loading fails, receiving an event error.
* - `flipU`: Flips the U texture coordinates of the model.
* - `flipV`: Flips the V texture coordinates of the model.
*
*
* @method createModel
* @param {String} modelString String of the object to be loaded
* @param {String} [fileType] The file extension of the model
* (<code>.stl</code>, <code>.obj</code>).
* @param {Boolean} normalize If true, scale the model to a
* standardized size when loading
* @param {function(p5.Geometry)} [successCallback] Function to be called
* once the model is loaded. Will be passed
* the 3D model object.
* @param {function(Event)} [failureCallback] called with event error if
* the model fails to load.
* @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
*
* @example
* <div>
* <code>
* const octahedron_model = `
* v 0.000000E+00 0.000000E+00 40.0000
* v 22.5000 22.5000 0.000000E+00
* v 22.5000 -22.5000 0.000000E+00
* v -22.5000 -22.5000 0.000000E+00
* v -22.5000 22.5000 0.000000E+00
* v 0.000000E+00 0.000000E+00 -40.0000
* f 1 2 3
* f 1 3 4
* f 1 4 5
* f 1 5 2
* f 6 5 4
* f 6 4 3
* f 6 3 2
* f 6 2 1
* f 6 1 5
* `;
* //draw a spinning octahedron
* let octahedron;
*
* function setup() {
* createCanvas(100, 100, WEBGL);
* octahedron = createModel(octahedron_model);
* describe('Vertically rotating 3D octahedron.');
* }
*
* function draw() {
* background(200);
* rotateX(frameCount * 0.01);
* rotateY(frameCount * 0.01);
* model(octahedron);
*}
* </code>
* </div>
*/
/**
* @method createModel
* @param {String} modelString
* @param {String} [fileType]
* @param {function(p5.Geometry)} [successCallback]
* @param {function(Event)} [failureCallback]
* @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
*/
/**
* @method createModel
* @param {String} modelString
* @param {String} [fileType]
* @param {Object} [options]
* @param {function(p5.Geometry)} [options.successCallback]
* @param {function(Event)} [options.failureCallback]
* @param {boolean} [options.normalize]
* @param {boolean} [options.flipU]
* @param {boolean} [options.flipV]
* @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
*/
let modelCounter = 0;
p5.prototype.createModel = function(modelString, fileType=' ', options) {
p5._validateParameters('createModel', arguments);
let normalize= false;
let successCallback;
let failureCallback;
let flipU = false;
let flipV = false;
if (options && typeof options === 'object') {
normalize = options.normalize || false;
successCallback = options.successCallback;
failureCallback = options.failureCallback;
flipU = options.flipU || false;
flipV = options.flipV || false;
} else if (typeof options === 'boolean') {
normalize = options;
successCallback = arguments[3];
failureCallback = arguments[4];
} else {
successCallback = typeof arguments[2] === 'function' ? arguments[2] : undefined;
failureCallback = arguments[3];
}
const model = new p5.Geometry();
model.gid = `${fileType}|${normalize}|${modelCounter++}`;

if (fileType.match(/\.stl$/i)) {
try {
let uint8array = new TextEncoder().encode(modelString);
let arrayBuffer = uint8array.buffer;
parseSTL(model, arrayBuffer);
} catch (error) {
if (failureCallback) {
failureCallback(error);
} else {
p5._friendlyError('Error during parsing: ' + error.message);
}
return;
}
} else if (fileType.match(/\.obj$/i)) {
try {
const lines = modelString.split('\n');
parseObj(model, lines);
} catch (error) {
if (failureCallback) {
failureCallback(error);
} else {
p5._friendlyError('Error during parsing: ' + error.message);
}
return;
}
} else {
p5._friendlyFileLoadError(3, modelString);
if (failureCallback) {
failureCallback();
} else {
p5._friendlyError(
'Sorry, the file type is invalid. Only OBJ and STL files are supported.'
);
}
}
if (normalize) {
model.normalize();
}

if (flipU) {
model.flipU();
}

if (flipV) {
model.flipV();
}

if (typeof successCallback === 'function') {
successCallback(model);
}

return model;
};


export default p5;

0 comments on commit 0312e44

Please sign in to comment.