# P5.JS 3D Dot Diagram rendering extremely slow

**URL:** https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953
**Category:** Coding Questions
**Created:** [August 26, 2021, 3:17pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953 "2021-08-26T15:17:43Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 26, 2021, 3:17pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/1 "2021-08-26T15:17:43Z")

</div>

I am trying to convert a normal 2D image(a simple JPEG) into a 3D Dot Diagram that the user can move around with. But upon trying to render that dot diagram, the program becomes extremely slow. Can anyone point where I am going wrong?

```
var x = [];
var y = [];
var z = [];
var colors = [];
var a = 0;
var counter = 0;

let img;

function preload() {
    img = loadImage('assets/image.jpeg');
}

function setup() {
  createCanvas(720, 400, WEBGL);
  background(0);

  img.resize(width/3, height/2);

  for(let col = 0; col < img.width; col+=3){
    for(let row = 0; row < img.height; row+=3){
        let c = img.get(col,row);
        let rgb_val = c[0] + c[1] + c[2]
        colors[a] = c 
        x[a] = map(col,0,255,-125,125)
        y[a] = map(row,0,255,-125,125)
        z[a] = map(rgb_val,0,765,-50,0)
        stroke(c)
        push();
        a++
    }
  }

}

function draw() {
   translate(0,0,-50);
   rotateY(frameCount * 0.1);
  background(0);

  for (var i = 0; i < a; i++) {
    stroke(colors[i])
    push();
    translate(x[i], y[i], z[i]);
    sphere(1);
    pop();
  }

  orbitControl();

}
```

---

<div class="post-metadata">

### Author: ![liogra](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@liogra](https://discourse.processing.org/u/liogra)
#### Post date: [August 26, 2021, 5:41pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/2 "2021-08-26T17:41:52Z")

</div>

```auto
 for(let col = 0; col < img.width; col+=3){
    for(let row = 0; row < img.height; row+=3){

```

the img.width and img.hight make your render possibly larger than your canvas. how big is your jpeg in pixels?

---

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 26, 2021, 6:09pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/3 "2021-08-26T18:09:10Z")

</div>

> [@liogra](#):
>
> the img.width and img.hight make your render possibly larger than your canvas. how big is your jpeg in pixels?

Hello liogra,

The image I am trying on it right now is around 197x256.

---

<div class="post-metadata">

### Author: ![liogra](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@liogra](https://discourse.processing.org/u/liogra)
#### Post date: [August 26, 2021, 6:35pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/4 "2021-08-26T18:35:07Z")

</div>

maybe use sphereDetail() and use less than the default 30 to make is run smoother?

---

<div class="post-metadata">

### Author: ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)
#### Post date: [August 27, 2021, 3:25am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/5 "2021-08-27T03:25:22Z")

</div>

This is a cross post from StackOverflow: [javascript - P5.JS 3D Dot Diagram rendering extremely slow - Stack Overflow](https://stackoverflow.com/questions/68898347/p5-js-3d-dot-diagram-rendering-extremely-slow)

---

<div class="post-metadata">

### Author: ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)
#### Post date: [August 27, 2021, 10:59pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/6 "2021-08-27T22:59:38Z")

</div>

Answered on StackOverflow. This took some doing but I got it up to ~60 FPS using `p5.Geometry` 🤯

```auto
const dotRadius = 1;
const detail = 4;

let img;

let fpsDisplay;
let lastTime = 0;

let geom;

function preload() {
  img = loadImage('https://www.paulwheeler.us/files/clooney.jpeg');
}

function setup() {
  console.log('Initializing');
  createCanvas(720, 400, WEBGL);
  // Because the spheres are so small, the default stroke makes them all black.
  // You could also use strokeWeight(0.1);
  noStroke();

  img.resize(width / 3, height / 2);

  const dotGrid = function() {
    const sliceCount = this.detailX + 1;
    let dotNumber = 0;
    for (let col = 0; col < img.width; col += 3) {
      for (let row = 0; row < img.height; row += 3) {
        let c = img.get(col, row);
        let rgb_val = c[0] + c[1] + c[2];
        let xOff = map(col, 0, img.width, -125, 125);
        let yOff = map(row, 0, img.height, -125, 125);
        let zOff = map(rgb_val, 0, 765, -50, 0);
        for (let i = 0; i <= this.detailY; i++) {
          const v = i / this.detailY;
          const phi = PI * v - PI / 2;
          const cosPhi = cos(phi);
          const sinPhi = sin(phi);

          for (let j = 0; j <= this.detailX; j++) {
            const u = j / this.detailX;
            const theta = 2 * PI * u;
            const cosTheta = cos(theta);
            const sinTheta = sin(theta);
            const p = createVector(
              xOff + dotRadius * cosPhi * sinTheta,
              yOff + dotRadius * sinPhi,
              zOff + dotRadius * cosPhi * cosTheta
            );
            this.vertices.push(p);
            this.vertexNormals.push(p);
            // All vertices in each dot get the same UV coordinates
            this.uvs.push(map(col, 0, img.width, 0, 1), map(row, 0, img.height, 0, 1));
          }
        }

        // Generate faces for the current dot

        // offset = number of vertices for previous dots.
        let offset = dotNumber * (this.detailX + 1) * (this.detailY + 1);
        let v1, v2, v3, v4;
        for (let i = 0; i < this.detailY; i++) {
          for (let j = 0; j < this.detailX; j++) {
            v1 = i * sliceCount + j + offset;
            v2 = i * sliceCount + j + 1 + offset;
            v3 = (i + 1) * sliceCount + j + 1 + offset;
            v4 = (i + 1) * sliceCount + j + offset;
            this.faces.push([v1, v2, v4]);
            this.faces.push([v4, v2, v3]);
          }
        }

        dotNumber++;
      }
    }
    console.log(`Dots: ${dotNumber}`);

    console.log(`Vertices: ${this.vertices.length}`);
    console.log(`Faces: ${this.faces.length}`);
  };

  geom = new p5.Geometry(detail, detail, dotGrid);
  geom.gid = 'dot-grid';

  fpsDisplay = createInput('0');
  fpsDisplay.position(10, 10);
}

function draw() {
  background(0);
  orbitControl(2, 1, 0.1);

  texture(img);
  model(geom);

  let t = millis();
  fpsDisplay.value(`${1000 / (t - lastTime)}`);
  lastTime = t;
}

```

---

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 30, 2021, 6:35am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/7 "2021-08-30T06:35:51Z")

</div>

I’ve tried and it seems to have no effect on the performance.

---

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 30, 2021, 6:36am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/8 "2021-08-30T06:36:31Z")

</div>

Yes, I did post it on Stack Overflow but no one seemed to answer even after a day, so then I decided to post the question here.

---

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 30, 2021, 6:39am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/9 "2021-08-30T06:39:09Z")

</div>

Whatttt, I can’t believe you did it 🤯, I gave up thinking it was impossible to build. But I don’t know how to thank you on this. Thank you so so much Paul!!!

---

<div class="post-metadata">

### Author: ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)
#### Post date: [August 30, 2021, 9:57pm UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/10 "2021-08-30T21:57:52Z")

</div>

> [@salmans911](#):
>
> Yes, I did post it on Stack Overflow but no one seemed to answer even after a day, so then I decided to post the question here.

That’s fine, I just recommend that when you cross post between this forum and StackOverflow you add comments in both places mentioning the other post. That way somebody doesn’t invest time answering your question in one place without realizing it has already been answered elsewhere.

Cheers.

---

<div class="post-metadata">

### Author: ![salmans911](https://avatars.discourse-cdn.com/v4/letter/s/eb8c5e/32.png) [@salmans911](https://discourse.processing.org/u/salmans911)
#### Post date: [August 31, 2021, 6:23am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/11 "2021-08-31T06:23:02Z")

</div>

Okay, good point, I didn’t realize that but I will do that from now on. By the way, I’ve asked if you could explain the code a bit on SO, I’ll ask that here too in case you may not have not seen my comment in SO.

---

<div class="post-metadata">

### Author: ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)
#### Post date: [August 31, 2021, 10:50am UTC](https://discourse.processing.org/t/p5-js-3d-dot-diagram-rendering-extremely-slow/31953/12 "2021-08-31T10:50:16Z")

</div>

I’m working on a detailed article about how `p5.Geometry` works, but here’s some quick notes:

The `p5.Geometry` constructor takes three arguments: `detailX`, `detailY`, and a callback function. Both `detailX` and `detailY` are expected to be numbers, in this case I’m using them to represent the number of dots. The built in p5.Geometry types (like sphere and plane) use these differently, and they are necessary for `p5.Geometry.computeFaces` to work properly because it uses them to determine how many vertices there are per strip of triangles. So `computeFaces` is not going to work with this geometry hence I generate the faces in `dotGrid`.

The callback function (which is `dotGrid` in this case) is where the magic happens. This function is responsible for generating the list of `vertices` and `uvs` (and in this case `vertexNormals` and `faces` as well). For some geometry you can use `computeNormals` but I’m not sure it works in this particular case, and because we already know the normal for each vertex, specifying it manually is easier.

The callback function is invoked as a member of the `p5.Geometry` instance, so in the `dotGrid` function `this` is the `p5.Geometry` instance.

Much of the code in my `dotGrid` function was shamelessly stolen from the [ellipsoid function](https://github.com/processing/p5.js/blob/main/src/webgl/3d_primitives.js#L768) from p5.js itself, which uses trig to generate a set of vertices for a sphere. However I offset these positions depending on where the dot is in the grid, and then I also manually generate the faces for each sphere.

The `vertices` array is a list of `p5.Vector` objects that represent the corners of the triangles that make up the geometry in 3d space. The `faces` array contains arrays of three integers which are the indices in the `vertices` array for the three corners of each triangle.
