I’ve loaded a model using loadModel(), but it requires a path from the website. And because I can’t upload a file larger than 5M,I wonder if there is a way to load a model just from local (maybe createFileInput)?
Thank you in advance.
It’s a little tricky but it is definitely possible:
let input;
let m;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL)
input = createFileInput(handleFile);
input.position(10, 10);
}
function draw() {
background(255);
orbitControl(2, 1, 0.05);
if (m) {
background(0);
// This will depend on your model (I'm using the standard teapot example)
scale(1, -1, 1);
translate(0, 10, 0);
model(m);
}
}
function handleFile(file) {
loadStrings(
file.data,
lines => {
// See: https://developer.mozilla.org/en-US/docs/Web/API/Blob
let blob = new Blob([lines.join('\n')], { type: 'text/plain' });
loadModel(
// This creates a temporary URL that can be used to fetch
// the data in the Blob.
// It is necessary to add the "#ext=.obj" to the end because
// loadModel() uses the file extension to determine what
// kind of model to load (which is a horrible design, but I digress).
URL.createObjectURL(blob) + "#ext=.obj",
true,
loaded => {
m = loaded;
}
);
}
);
}
Wow! I tried your code and it worked! Thank you so much for the timely reply, I really appreciate it.
emm, there’s stil one thing that bothers me. When I use my custom shader, and load a model, it just disappear. it seems I need a way to reload shader. Could you please take a look on that?Thank you.
let input;
let m,m0,currentmodel;
function preload(){
m0=loadModel('teapot.obj',true);
debugger
mandel=loadShader('shader.vert','shader.frag');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL)
input = createFileInput(handleFile);
input.position(10, 10);
noStroke();
}
function draw() {
background(255);
orbitControl(2, 1, 0.05);
if (m) {
currentmodel=m;}
else{
currentmodel=m0;
}
background(155);
// This will depend on your model (I'm using the standard teapot example)
scale(1, -1, 1);
//translate(0, 10, 0);
//mandel.setUniform(aPosition);
mandel.setUniform('cmatrix',this._renderer._curCamera.cameraMatrix.mat4);
mandel.setUniform('pmatrix',this._renderer._curCamera.projMatrix.mat4);
shader(mandel);
model(currentmodel);
}
function handleFile(file) {
loadStrings(
file.data,
lines => {
// See: https://developer.mozilla.org/en-US/docs/Web/API/Blob
let blob = new Blob([lines.join('\n')], { type: 'text/plain' });
m=loadModel(
// This creates a temporary URL that can be used to fetch
// the data in the Blob.
// It is necessary to add the "#ext=.obj" to the end because
// loadModel() uses the file extension to determine what
// kind of model to load (which is a horrible design, but I digress).
URL.createObjectURL(blob) + "#ext=.obj",
true
);
}
);
}
https://editor.p5js.org/yangshuzhan/sketches/0rO0eylNg
This is definitely weird. There’s no obvious reason why this wouldn’t work. I’ve verified that it doesn’t happen with the default shader, but I don’t see any reason why your shader would cause a problem. I’ve also verified that it’s not specific to my file input model loader code (the same issue occurs if you load a new model from a URL). Seems like a bug in p5.js as far as I can tell. Here’s my test sketch: p5.js Web Editor
Note that it’s functional if you use two seperate shaders for the two objects. I guess it’s because when I change the model, the shader and it’s attributes doesn’t change accordingly? I’m overwhelmed.
Ok, I figured it out: Calling loadModel while a custom shader is in use breaks the existing shader. · Issue #5455 · processing/p5.js · GitHub
This is a rather egregious p5.js bug. Basically loadModel calls outside of preload()
are causing setup()
to get re-run, which causes your preloaded shader to become invalid (because it is associated with a completely different WebGL context) . Hopefully the p5.js maintainers will address this quickly because I would consider this a high priority bug. I might try to submit a PR for it.
Well done! This bug bothered me for weeks. Love you so much.