Optimizing Shapes3d code

edited September 2016 in Library Questions

I have returned to working on my dissertation project and need a little help. I completely rewrote my code from years ago to utilize Shapes3d and to simplify as much as possible, so that I can concentrate on the theory code, not so much the display code. The trouble is that when I switched from using PShapes and buffers for picking to using Shapes3d, I lost a magnitude of speed. On my old version, I could have up to 100x100x100 cubes. Now with the new code, I am luck to have rotation at 50x50x50.

I have three questions: 1) Would I be better using a minecraft type library/code with unlimited size of map, but only displaying what is close by and not the entire map?

2) When I loaded all of the map into a single shape and displayed it, it seem to really speed things up. Is there any way that I can do something similar with Shapes3d boxes/shapes?

3) I keep reading about culling and only displaying what is needed, but I thought all of that happened in the background of Processing, am I not enabling something that I should be? I am really surprised that I keep reaching these data visualization limits.

4) Any and all suggestions on optimization or improvements would be greatly appreciated. I really only want to code the final function (cellLogic). Any of the other code that can be improved and will get me back up to my 100x100x100 display needed, will really help.

5) Would I be better off using a gaming engine instead of P3? All of the gaming engines seem to be overkill for the limited amount of display capabilities I need.

Thank you for any and all help/suggestions that anybody has. The code is below.

Michael

import peasy.*;
import shapes3d.*;

// version 1.0 Base program
// version 2.0 Add Shape?
PeasyCam cam;
int   cells_per_side = 10;                         // number of cells per side - no greater than 100
int   winSize = 2100;                              //size of display window in both directions
int   numcells =0;

Box[][][] box = new Box[cells_per_side][cells_per_side][cells_per_side];
Shape3D picked = null;
boolean clicked = false;

float boundries = winSize *.8;                    // overall brain size in comparison to window
float init_rescale = 0.4, rescale=init_rescale;   // 0.1 .. 1.0  percentage cell takes of allocated space
float gridSize = boundries / cells_per_side;
float cellSize = gridSize * init_rescale;
float offset=(cells_per_side-1)*gridSize/2.0;
color[] faceColor = { 0x88FF0000, 0x8800FF00, 0x880000FF, 0x88FFFF00, 0x8800FFFF, 0x88FF00FF  };
double rotateAngle = .002;

/PShape  model;

//_________________________________________________________________ 

void setup() {
  size(2100, 2100, P3D);
  cursor(CROSS);
  cam = new PeasyCam(this, 2800);

  //model = createShape(GROUP);
  for (int i = 0; i < cells_per_side; i++) {
    for (int j = 0; j < cells_per_side; j++) {
      for (int k = 0; k < cells_per_side; 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)));}
        box[i][j][k].stroke(color(64, 0, 64));
        box[i][j][k].strokeWeight(0.6);
        box[i][j][k].visible(true);
        box[i][j][k].drawMode(S3D.SOLID);
        box[i][j][k].tag = "Box " + i + " " + j + " " + k;        
    }}}        
    // model.addChild(box[i][j][k]);                
  }

//_________________________________________________________________ 
void draw() {
  background(#E0FFFF);
  cam.beginHUD();    // now draw things that you want relative to the camera's position and orientation
  cam.endHUD(); 

  pushMatrix();
      for (int i = 0; i < cells_per_side; i++) {
       for (int j = 0; j < cells_per_side; j++) {
        for (int k = 0; k < cells_per_side; k++) { 
          box[i][j][k].draw();}}}
   popMatrix();

  // shape(model);    //This will draw the entire model
   cellLogic();
   cam.rotateY(rotateAngle);   //cam.rotateX(rotateAngle);   cam.rotateZ(rotateAngle);
  }

//_________________________________________________________________ 
void mouseClicked() {  
    picked = Shape3D.pickShape(this, mouseX, mouseY);
    if (picked != null)      picked.visible(false);
    if (mouseButton == LEFT) {rotateAngle=0;} else if (mouseButton == RIGHT) {rotateAngle=.002;}      
}

//_________________________________________________________________ 
//------------The actual application logic goes here
//_________________________________________________________________
final float A90=PI/2;
void cellLogic() {
  int a=floor(random(cells_per_side));
  int b=floor(random(cells_per_side));
  int c=floor(random(cells_per_side));

  box[a][b][c].rotateBy(int(random(cells_per_side))*A90,int(random(cells_per_side))*A90,int(random(cells_per_side))*A90);

}
Tagged:

Answers

  • Answer ✓

    You need to format the code for this forum.

    Changing the drawMode for the boxes to S3D.SOLID (removing the wire) will speed things up a bit.

    Also the code logic performs the same calculation radians(90) loads of times. Also better to cast to int than use floor because the random numbers generated will always be positive

    final float A90 = PI/2;
    
    void cellLogic() {
      int a=(int)random(cells_per_side);
      int b=(int)random(cells_per_side);
      int c=(int)random(cells_per_side);
    
      if (box[a][b][c].visible()) 
        box[a][b][c].rotateBy((int)(random(cells_per_side))*A90, (int)(random(cells_per_side))*A90, (int)(random(cells_per_side))*A90);
    }
    

    1) I don't know the answer to that

    2) No Shapes3D does not have a similar option

    3) OpenGL should take care of culling for you so it is unlikely you can improve on that much. You are using transparent fill colours which means that pixel colour data has to be merged rather than replaced by nearer objects but when I tried using RGB colours it didn't make much difference.

    5) A game engine will use the most advanced features of OpenGL to maximise speed. AFAIK Processing doesn't do that.

    Shapes3D is slow because it processes all the vertex data on the CPU rather than the much faster GPU (Graphics processor unit on the graphics card).

  • OpenGL should take care of culling for you

    I'm not sure this is entirely true because there are lots of options and it depends on the object being defined with the correct vertex order. I'm not sure what the defaults are. Backface culling with cubes saves you drawing at least half the faces.

    (Oh, reading that again he might be talking about frustum culling, not backface culling)

  • Thank you for the suggestions. I will continue to see if I can improve my code. Any additional suggestions for optimization are hugely appreciated.

  • He can't use backface culling because he is using colours with transparency - he can see inside the cubes.

    Turning on/off backface culling is just 2 OpenGL settings -

    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    

    The OpenGL glFrustrum or gluPerspective methods modify the projection transformation which is then used to define a viewing volume. This viewing volume does 2 things

    1) determines how an object appears on screen

    2) defines which objects or portions of objects are clipped out of the final image

    With Shapes3D it might be worth working out whether a shape is inside the viewing volume because of the time needed to pass the vertex coordinates to OpenGL is significant.

  • Extra: This probably won't help because most of the cubes will be visible anyway.

Sign In or Register to comment.