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();
}

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!!!

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.

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.

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 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.