I am fairly new to Processing and am trying to draw 3D shapes and do what seems to be a fairly simple animation. However, the performance is very poor (the animation speed is not uniform - slows way down and speeds up) and the sketch uses 50 to 80 percent of my MacBook Pro M1’s CPU.
I’m not sure if using a PMatrix3D the way I am is recommended practice. The reason for that is I wanted to be able to draw a quad strip between polygons that have been translated and rotated independently of one another, and you cannot call any transformations while building a shape (between beginShape() and endShape()) So this seemed like a pretty straightforward way of making that work.
Apologies if there is something obviously wrong here, or if drawing a 3D object of this complexity is simply exceeding the limits of Java or Processing.
ArrayList<ArrayList<PVector>> polygons;
PMatrix3D matrix;
int numberPoints = 4;
void setup() {
size(640, 480, P3D);
smooth();
polygons = new ArrayList<ArrayList<PVector>>();
matrix = new PMatrix3D();
}
void draw() {
background(255);
lights();
translate(width/2, height/2, 0);
rotateY(radians(frameCount));
PVector center = new PVector(0, 0, 0);
int crossSectionNumberPoints = 5;
float crossSectionRadius = 20;
float radius = 100;
if (frameCount % 10 == 0) {
if (numberPoints == 50) {
numberPoints = 4;
} else {
++numberPoints;
}
}
polygons.clear();
matrix.reset();
matrix.translate(center.x, center.y, center.z);
matrix.rotateZ(radians(-90));
ArrayList<PVector> shapeVerticesBase = polygonVertices(0, 0, crossSectionRadius, crossSectionNumberPoints);
float angle = TWO_PI / numberPoints;
float angleTotal = 0;
for (int pointIndex = 0; pointIndex < numberPoints; ++pointIndex) {
matrix.rotateX(radians(90));
matrix.rotateY(angleTotal);
matrix.translate(radius, 0, 0);
polygons.add(transformVertices(shapeVerticesBase, matrix));
matrix.translate(-radius, 0, 0);
matrix.rotateY(-angleTotal);
matrix.rotateX(radians(-90));
angleTotal += angle;
}
for (int i = 0; i < polygons.size() - 1; ++i) {
PShape s = buildQuadStripFromPolygons(
polygons.get(i),
polygons.get(i + 1)
);
shape(s, 0, 0);
}
PShape s = buildQuadStripFromPolygons(
polygons.get(polygons.size() - 1),
polygons.get(0)
);
shape(s, 0, 0);
}
PShape buildQuadStripFromPolygons(
ArrayList<PVector> polygon1,
ArrayList<PVector> polygon2) {
PShape shape = createShape();
shape.beginShape(QUAD_STRIP);
for (int i = 0; i < polygon1.size(); i++) {
shape.vertex(
polygon1.get(i).x,
polygon1.get(i).y,
polygon1.get(i).z
);
shape.vertex(
polygon2.get(i).x,
polygon2.get(i).y,
polygon2.get(i).z
);
}
shape.vertex(
polygon1.get(0).x,
polygon1.get(0).y,
polygon1.get(0).z
);
shape.vertex(
polygon2.get(0).x,
polygon2.get(0).y,
polygon2.get(0).z
);
shape.endShape();
return shape;
}
ArrayList<PVector> transformVertices(ArrayList<PVector> vertices, PMatrix3D matrix) {
ArrayList<PVector> tVertices = new ArrayList<PVector>();
PVector tVertex = new PVector();
for (PVector vertex : vertices) {
matrix.mult(vertex, tVertex);
tVertices.add(new PVector(tVertex.x, tVertex.y, tVertex.z));
}
return tVertices;
}
ArrayList<PVector> polygonVertices(float x, float y, float radius, int npoints) {
ArrayList<PVector> vertices = new ArrayList<PVector>();
float angle = TWO_PI / npoints;
float angleTotal = 0;
for (int pointIndex = 0; pointIndex < npoints; ++pointIndex) {
vertices.add(new PVector(
x + cos(angleTotal) * radius,
y + sin(angleTotal) * radius,
0
));
angleTotal += angle;
}
return vertices;
}