Skip to main content

Drawing a large number of objects

1 reply [Last post]
davidstarina
Offline
Joined: 2012-05-29
Points: 0

Hi everybody,

what is the correct way of drawing a large number of objects? I have to draw a large number of 3D pixels, and it seems quite a lot of code to draw a pixel and set its position. Can you please take a look at my code and tell me if this is the right approach?

           for(InterestingVoxel iv: visibleList) {  
               // I need to have own appearance for each voxel, because in the final version, each will be of unique color 
               Appearance ap = new Appearance(); 
               ColoringAttributes ca = new ColoringAttributes(); 
               ca.setColor(1, 1, 1); 
               ap.setColoringAttributes(ca); 
     
               Box voxel = new Box(1, 1, 1, ap); 
               TransformGroup tg = new TransformGroup(); 
               Transform3D transform = new Transform3D(); 
               Vector3f vector = new Vector3f( iv.getI(), iv.getJ(), iv.getK()); 
               transform.setTranslation(vector); 
               tg.setTransform(transform); 
               tg.addChild(voxel); 
               contents.addChild(tg); 
           } 

With this approach, I am getting a heap space error (about 300 000 objects/pixels) - I gave it 2 Gb of memory, but was not enough ...

Thank you for any help,
David

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
interactivemesh
Offline
Joined: 2006-06-07
Points: 0

Assuming - according to your case - that the position of a single box/voxel is fixed and the color isn't to be shaded, another approach would be to collect all boxes/voxels into a single GeometryArray and to assign this one to a single Shape3D with no Appearance.

Following code was taken from a multi box test program and adapted to your case. I found out that memory footprint and performance are best on OpenGL (ogl) if an IndexedQuadArray is used and on Direct3D (d3d) if a TriangleArray is taken (d3d renders several times faster. d3d is buggy for larger indexed geometry arrays.).

August

// On OpenGL only
private Shape3D getVisibleVoxelsQuad(ArrayList<InterestingVoxel> visibleList) {

    int numVerts = 24; // 6 faces * 1 quad * 4 vertices
    int numVoxel = visibleList.size();

    int indexCount   = numVerts * numVoxel;
    int vertexCount  = numVoxel * 8; // 8 vertices/corners of the box/voxel
    int vertexFormat = TriangleArray.COORDINATES | TriangleArray.COLOR_3 |
       TriangleArray.USE_COORD_INDEX_ONLY;

    // One geometry for all visible voxels
    IndexedQuadArray voxels = new IndexedQuadArray(vertexCount, vertexFormat, indexCount);

    int indexOffset = 0;
    int voxelOffset = 0;

    int[]   voxelIndices = null;
    float[] voxelCoords  = null;
    float[] voxelColors  = null;

    for (InterestingVoxel iv: visibleList) { 

    voxelIndices = getBoxQuadIndices(voxelOffset);
   
    voxelCoords  = getBoxIndexedCoords(iv.getI(), iv.getJ(), iv.getK());       
    voxelColors  = getBoxIndexedColors(iv.getR(), iv.getG(), iv.getB());

    voxels.setCoordinateIndices(indexOffset, voxelIndices);
   
    voxels.setCoordinates(voxelOffset, voxelCoords);
    voxels.setColors(voxelOffset, voxelColors);
   
    indexOffset += numVerts;
    voxelOffset += 8;  
    }   

    // One Shape3D for all visible voxels, null Apearance
    return new Shape3D(voxels, null);
}

// On Direct3D
private Shape3D getVisibleVoxelsTria(ArrayList<InterestingVoxel> visibleList) {

    int numVerts = 36; // 6 faces * 2 triangles * 3 vertices
    int numVoxel = visibleList.size();

    int vertexCount  = numVerts * numVoxel;
    int vertexFormat = TriangleArray.COORDINATES | TriangleArray.COLOR_3;

    // One geometry for all visible voxels
    TriangleArray voxels = new TriangleArray(vertexCount, vertexFormat);

    int voxelOffset = 0;

    float[] voxelCoords = null;
    float[] voxelColors = null;

    for (InterestingVoxel iv: visibleList) { 

    voxelCoords  = getBoxTriaCoords(iv.getI(), iv.getJ(), iv.getK());       
    voxelColors  = getBoxTriaColors(iv.getR(), iv.getG(), iv.getB());
   
    voxels.setCoordinates(voxelOffset, voxelCoords);
    voxels.setColors(voxelOffset, voxelColors);
   
    voxelOffset += numVerts;
    }   

    // One Shape3D for all visible voxels, null Apearance
    return new Shape3D(voxels, null);
}
  
    // (x, y, z) = translation
private float[] getBoxTriaCoords(float x, float y, float z) {
    float[] coords = {
        // +X box right
    1.0f + x,  1.0f + y,  1.0f + z,    1.0f + x, -1.0f + y,  1.0f + z,   1.0f + x, -1.0f + y, -1.0f + z,
         1.0f + x,  1.0f + y,  1.0f + z,    1.0f + x, -1.0f + y, -1.0f + z,   1.0f + x,  1.0f + y, -1.0f + z,
        // -X box left
        -1.0f + x,  1.0f + y, -1.0f + z,   -1.0f + x, -1.0f + y, -1.0f + z,  -1.0f + x, -1.0f + y,  1.0f + z,
        -1.0f + x,  1.0f + y, -1.0f + z,   -1.0f + x, -1.0f + y,  1.0f + z,  -1.0f + x,  1.0f + y,  1.0f + z,
// +Y box top
        -1.0f + x,  1.0f + y, -1.0f + z,   -1.0f + x,  1.0f + y,  1.0f + z,   1.0f + x,  1.0f + y,  1.0f + z,
        -1.0f + x,  1.0f + y, -1.0f + z,    1.0f + x,  1.0f + y,  1.0f + z,   1.0f + x,  1.0f + y, -1.0f + z,
        // -Y box bottom
        -1.0f + x, -1.0f + y,  1.0f + z,   -1.0f + x, -1.0f + y, -1.0f + z,   1.0f + x, -1.0f + y,  1.0f + z,                
         1.0f + x, -1.0f + y,  1.0f + z,   -1.0f + x, -1.0f + y, -1.0f + z,   1.0f + x, -1.0f + y, -1.0f + z,          
        // +Z box front
        -1.0f + x,  1.0f + y,  1.0f + z,   -1.0f + x, -1.0f + y,  1.0f + z,   1.0f + x, -1.0f + y,  1.0f + z,
        -1.0f + x,  1.0f + y,  1.0f + z,    1.0f + x, -1.0f + y,  1.0f + z,   1.0f + x,  1.0f + y,  1.0f + z,
        // -Z box back
         1.0f + x,  1.0f + y, -1.0f + z,    1.0f + x, -1.0f + y, -1.0f + z,  -1.0f + x, -1.0f + y, -1.0f + z,
         1.0f + x,  1.0f + y, -1.0f + z,   -1.0f + x, -1.0f + y, -1.0f + z,  -1.0f + x,  1.0f + y, -1.0f + z
    };
    return coords;
}
// (r, g, b) = color
private float[] getBoxTriaColors(float r, float g, float b) {
    float[] colors = {
r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b,

r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b,

r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b,

r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b,

r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b,

        r, g, b,  r, g, b,  r, g, b,
r, g, b,  r, g, b,  r, g, b
    };
    return colors;
}   
// Quad indices
private int[] getBoxQuadIndices(int offset) {
    int[] indices = {
        // +X box right
0, 6, 5, 1,
        // -X box left
3, 2, 4, 7,
// +Y box top
0, 1, 2, 3,
        // -Y box bottom
4, 5, 6, 7,
        // +Z box front
0, 3, 7, 6,
        // -Z box back
4, 2, 1, 5
    };

    for (int i=0; i < 24; i++)
        indices[i] += offset;

    return indices;
}  
// Triangle indices
private int[] getBoxTriaIndices(int offset) {
    int[] indices = {
        // +X box right
0, 6, 5,   0, 5, 1,
        // -X box left
3, 2, 4,   3, 4, 7,
// +Y box top
0, 1, 2,   0, 2, 3,
        // -Y box bottom
4, 5, 6,   4, 6, 7,
        // +Z box front
0, 3, 7,   0, 7, 6,
        // -Z box back
4, 2, 1,   4, 1, 5
    };

    for (int i=0; i < 36; i++)
        indices[i] += offset;

    return indices;
}  
// (x, y, z) = translation
private float[] getBoxIndexedCoords(float x, float y, float z) {
    float[] coords = {
// box top
    1.0f + x,  1.0f + y,  1.0f + z, // 0  
    1.0f + x,  1.0f + y, -1.0f + z,  // 1
    -1.0f + x,  1.0f + y, -1.0f + z,  // 2
    -1.0f + x,  1.0f + y,  1.0f + z, // 3
   
        // box bottom
    -1.0f + x, -1.0f + y, -1.0f + z, // 4
    1.0f + x, -1.0f + y, -1.0f + z, // 5
    1.0f + x, -1.0f + y,  1.0f + z, // 6      
        -1.0f + x, -1.0f + y,  1.0f + z,   // 7        
    };
    return coords;
}
// (r, g, b) = color
private float[] getBoxIndexedColors(float r, float g, float b) {
    float[] colors = {
r, g, b, // 0
r, g, b, // 1 
r, g, b, // 2 
r, g, b, // 3

r, g, b, // 4 
r, g, b, // 5 
r, g, b, // 6 
r, g, b  // 7
    };
    return colors;
}