We are about to switch to a new forum software. Until then we have removed the registration on this forum.
The question I have is that in the following code I am only changing 1 box every second or so, but i am having to redraw all 8000 blocks each draw cycle. Is there a way to have draw only redraw the changed objects? Is there any way to write these boxes to a single shape or similar and once I update the single box every few seconds, then I update the stores shape, or do I have to redraw everything every 1/60 second..... Any suggestions on improving any areas of this code are appreciated.
import peasy.*;
import shapes3d.*;
import processing.opengl.*;
PeasyCam cam;
int CPS = 20; // number of cells per side - no greater than 100
int winSize = 1024; //size of display window in both directions
Box[][][] box = new Box[CPS][CPS][CPS];
Shape3D picked = null;
boolean clicked = false;
float boundries = winSize *.8;
float gridSize = boundries / CPS;
float cellSize = gridSize * .4;
float offset=(CPS-1)*gridSize/2.0;
double rotateAngle = .002;
color[] faceColor = { 0x44FF0000, 0x4400FF00, 0x440000FF, 0x44FFFF00, 0x4400FFFF, 0x44FF00FF };
//_________________________________________________________________
void setup() {
size(1024, 1024, P3D);
cursor(CROSS);
cam = new PeasyCam(this, winSize*1.25);
for (int i = 0; i < CPS; i++) { for (int j = 0; j < CPS; j++) { for (int k = 0; k < CPS; k++) {
box[i][j][k] = new Box(this, cellSize, cellSize, cellSize);
box[i][j][k].moveTo(i*gridSize-offset,j*gridSize-offset,k*gridSize-offset);
for (int c = 0; c<faceColor.length; c++) {box[i][j][k].fill(faceColor[c],int(pow(2,c)));} //every side of the cells needs a different color
box[i][j][k].drawMode(S3D.SOLID);
}}} }
//_________________________________________________________________
void draw() {
background(127);
pushMatrix();
for (int i = 0; i < CPS; i++) { for (int j = 0; j < CPS; j++) { for (int k = 0; k < CPS; k++) {
box[i][j][k].draw(); }}}
popMatrix();
cam.rotateY(rotateAngle); cam.rotateX(rotateAngle); cam.rotateZ(rotateAngle);
}
//_________________________________________________________________
void mouseClicked() {if (mouseButton == LEFT) {rotateAngle=0;} else if (mouseButton == RIGHT) {rotateAngle=.002;}}
Answers
Did you try without the libs, would this be faster?
Please edit your post and format the code with CTRL-o to aid other forum members in reading and testing your code.
In theory I could write code for the camera viewing instead of Peasycam and the box&picking code instead of using Shapes3d, but I mainly trying to do the research portion of the program and not the display portion. Thanks for the suggestion.
Using a PShape is the way around this. It bundles all the geometry together, uploads it to the graphics card and then in your draw loop you can just draw the entire thing with one shape call.
The problem comes when you then want to change a single block. (Which you don't in your example code but might in real life). It is possible, just fiddly.
And how fiddly?
Do you get rid of one lib and then use all box with GROUP and then use child shape somehow
I've never done it, but I know in the underlying opengl vbo that you have to specify the buffer as a different kind and then you can update individual bits if you know the offset into the data for that bit.
getVertex / setVertex are probably the calls using PShape. No idea about shapes3d.
(And in my limited experience using PShape children affects performance more than you think it would so i'd avoid it, especially with 8000 children.)
thanks!
Another potential optimization strategy to avoid redrawing (in general) is with PGraphics. I'm not sure if this would work in a sketch with live camera control, but in general if you can abstract out unchanging graphics as a layer, then you can render it once into a PGraphics / PImage and not touch draw to the image again until it changes -- you just render it to the screen each loop e.g. with image().