2

Hi everyone i have a problem with rendering 3D models using p5.js WEBGL mode.

I am working on a project for a client with 3D boxes, some of them render fine - the smaller .obj files with simpler geometry. The bigger with more complex shapes render badly with distorted geometry. In other 3d browser viewers the big models render fine.

Here is a small sample of the code, it is set to render the complex model that causes the problem:

code:
https://glitch.com/edit/#!/four-polyester-tent
preview:
https://four-polyester-tent.glitch.me

I would prefer not to change the render method, as the project is almost finished, but if this is the only option then ok.

Thanks for any help in advance !

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    I'm pretty sure you found a bug where p5.js cannot render models with > 65535 vertices. I'm investigating a fix. – Paul Wheeler May 29 '21 at 08:40
  • 2
    Paul's answer is amazing! (+1). The model is pretty heavy (almost 20MB) which for people on a data plan on be fun. As a hacky workaround once suggestion I have is simplifying the model. Most 3D editors can simplify meshes, for example Blender (free / opensource) has a [Decimate](https://docs.blender.org/manual/en/latest/modeling/modifiers/generate/decimate.html) modifier – George Profenza May 29 '21 at 10:36

1 Answers1

4

This is due to a bug/limitation of p5.js that it can only handle geometry with fewer than 65535 vertices. This is because it uses a Uint16Array to store vertex indices.

p5.RendererGL.prototype.createBuffers = function(gId, model) {  
    // ...

    this._bindBuffer(indexBuffer, gl.ELEMENT_ARRAY_BUFFER, vals, Uint16Array);

    // ...
};

And when passing the buffer to drawTriangles it specified the type gl.UNSIGNED_SHORT:

p5.RendererGL.prototype._drawElements = function(drawMode, gId) {
    // ...

    gl.drawElements(gl.TRIANGLES, buffers.vertexCount, gl.UNSIGNED_SHORT, 0);

    // ...
}

This is most likely due to the fact that WebGL 1.0 requires an extension ('OES_element_index_uint') in order to support 32 bit vertex indices.

However I was able to throw together a potential fix. Here is a sketch demonstrating it in action with your model:

let mdl;
let cnv;

function preload() {
  mdl = loadModel("https://art-open.pl/3D/Z-5.obj", true);
}

function setup() {
  cnv = createCanvas(windowWidth, windowHeight, WEBGL);
  noStroke();
}

function draw() {
  background(237);
  orbitControl(2, 2, 0.01);

  let locX = 0;
  let locY = 200;
  ambientLight(120, 120, 120);
  pointLight(255, 255, 255, locX, locY, 200);
  pointLight(255, 255, 255, locX, locY, -200);

  // normalMaterial();
  push();
  translate(0, 70, 0);
  scale(6, -6, 6);
  model(mdl);
  pop();
}
<script src="https://www.paulwheeler.us/files/p5-large-model-fix.min.js"></script>

You can find the un-minified version of my patch here.

Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41