Hi,
I want to render a bunch of boxes (shape that extends from AbstractBox) with an index buffer and an interleaved buffer because of the index buffer reduces the size of memory allocations and the interleaved data buffer reduces cache misses and overhead on the GPU.
So I have made a simple test scene. But all I see are some white quads instead of a bunch of boxes with the normal debug shader applied. I had to modify the method Mesh.updateCounts() because of it doesn’t work with interleaved buffers.
Am I doing something wrong or is it a engine render bug? Why is Mesh.setInterleaved() deprecated?
source code:
Mesh.java
[java]
@@ -773,11 +758,23 @@
*/
public void updateCounts()
{
-
VertexBuffer ib = getBuffer(Type.Index);
-
if (getBuffer(Type.InterleavedData) != null)
-
throw new IllegalStateException("Should update counts before interleave");
-
{
-
if (ib != null)
-
{
-
vertCount = ib.getData().limit() / ib.getNumComponents();
-
}
-
else
-
{
-
throw new IllegalStateException("Should update counts before interleave");
-
}
-
return;
-
} VertexBuffer pb = getBuffer(Type.Position);
-
VertexBuffer ib = getBuffer(Type.Index);
-
if (pb != null) { vertCount = pb.getData().limit() / pb.getNumComponents();
[/java]
RenderTest.java
[java]
package net.qb.tests.RenderTest;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.scene.BatchNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
public class RenderTest extends SimpleApplication
{
RenderTest app;
public RenderTest()
{
app = this;
app.setPauseOnLostFocus(false);
AppSettings settings = new AppSettings(false);
settings.setRenderer(AppSettings.LWJGL_OPENGL2);
app.setSettings(settings);
app.start(); // start the game
}
public static void main(String[] args)
{
new RenderTest();
}
@Override
public void simpleInitApp()
{
app.getFlyByCamera().setMoveSpeed(25);
int sizeX = 16;
int sizeY = 16;
int sizeZ = sizeX;
switch (0)
{
case 0:
noBatch(sizeX, sizeY, sizeZ);
break;
case 1:
tileBatch(sizeX, sizeY, sizeZ);
break;
case 2:
wholeBatch(sizeX, sizeY, sizeZ);
break;
}
System.out.println("finish");
}
private void wholeBatch(int sizeX, int sizeY, int sizeZ)
{
BatchNode batch = new BatchNode();
for (int x = 0; x < sizeX; x++)
{
for (int z = 0; z < sizeZ; z++)
{
for (int y = 0; y < sizeY; y++)
{
createMesh(batch, x, y, z);
}
}
}
batch.batch();
rootNode.attachChild(batch);
}
private void tileBatch(int sizeX, int sizeY, int sizeZ)
{
for (int x = 0; x < sizeX; x++)
{
for (int z = 0; z < sizeZ; z++)
{
BatchNode batch = new BatchNode();
for (int y = 0; y < sizeY; y++)
{
createMesh(batch, x, y, z);
}
batch.batch();
rootNode.attachChild(batch);
}
}
}
private void noBatch(int sizeX, int sizeY, int sizeZ)
{
for (int x = 0; x < sizeX; x++)
{
for (int z = 0; z < sizeZ; z++)
{
for (int y = 0; y < sizeY; y++)
{
createMesh(rootNode, x, y, z);
}
}
}
}
public void createMesh(Node node, int x, int y, int z)
{
// Box b = new Box(0.5f, 0.5f, 0.5f);
BoxInterleaved b = new BoxInterleaved(0.5f, 0.5f, 0.5f);
// b.updateCounts();
// b.setInterleaved();
// b.setStatic();
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
geom.setMaterial(mat);
geom.setLocalTranslation(x, y, z);
node.attachChild(geom);
}
}
[/java]
BoxInterleaved.java
[java]
package net.qb.tests.RenderTest;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import com.jme3.math.Vector3f;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.shape.AbstractBox;
import com.jme3.util.BufferUtils;
public class BoxInterleaved extends AbstractBox
{
private static final short[] GEOMETRY_INDICES_DATA = { //
2, 1, 0, 3, 2, 0, // back
6, 5, 4, 7, 6, 4, // right
10, 9, 8, 11, 10, 8, // front
14, 13, 12, 15, 14, 12, // left
18, 17, 16, 19, 18, 16, // top
22, 21, 20, 23, 22, 20 // bottom
};
private static final float[] GEOMETRY_NORMALS_DATA = {//
0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, // back
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // right
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // front
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // left
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // top
0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 // bottom
};
private static final float[] GEOMETRY_TEXTURE_DATA = {//
1, 0, 0, 0, 0, 1, 1, 1, // back
1, 0, 0, 0, 0, 1, 1, 1, // right
1, 0, 0, 0, 0, 1, 1, 1, // front
1, 0, 0, 0, 0, 1, 1, 1, // left
1, 0, 0, 0, 0, 1, 1, 1, // top
1, 0, 0, 0, 0, 1, 1, 1 // bottom
};
public BoxInterleaved(float x, float y, float z)
{
super();
updateGeometry(Vector3f.ZERO, x, y, z);
}
@Deprecated
public BoxInterleaved(Vector3f center, float x, float y, float z)
{
super();
updateGeometry(center, x, y, z);
}
public BoxInterleaved(Vector3f min, Vector3f max)
{
super();
updateGeometry(min, max);
}
/**
* Empty constructor for serialization only. Do not use.
*/
public BoxInterleaved()
{
super();
}
@Override
public BoxInterleaved clone()
{
return new BoxInterleaved(center.clone(), xExtent, yExtent, zExtent);
}
@Override
protected void duUpdateGeometryIndices()
{
}
@Override
protected void duUpdateGeometryNormals()
{
}
@Override
protected void duUpdateGeometryTextures()
{
}
@Override
protected void duUpdateGeometryVertices()
{
// size = ((vertComponents * verts * 2 (verts & normals) + texCoords) * six faces) * 4 float bytes
ByteBuffer byteBuffer = BufferUtils.createByteBuffer((3 * 4 * 2 + 8) * 6 * 4);
FloatBuffer fpb = byteBuffer.asFloatBuffer();
Vector3f[] v = computeVertices();
float[] verts = new float[] { //
v[0].x, v[0].y, v[0].z, v[1].x, v[1].y, v[1].z, v[2].x, v[2].y, v[2].z, v[3].x, v[3].y, v[3].z, // back
v[1].x, v[1].y, v[1].z, v[4].x, v[4].y, v[4].z, v[6].x, v[6].y, v[6].z, v[2].x, v[2].y, v[2].z, // right
v[4].x, v[4].y, v[4].z, v[5].x, v[5].y, v[5].z, v[7].x, v[7].y, v[7].z, v[6].x, v[6].y, v[6].z, // front
v[5].x, v[5].y, v[5].z, v[0].x, v[0].y, v[0].z, v[3].x, v[3].y, v[3].z, v[7].x, v[7].y, v[7].z, // left
v[2].x, v[2].y, v[2].z, v[6].x, v[6].y, v[6].z, v[7].x, v[7].y, v[7].z, v[3].x, v[3].y, v[3].z, // top
v[0].x, v[0].y, v[0].z, v[5].x, v[5].y, v[5].z, v[4].x, v[4].y, v[4].z, v[1].x, v[1].y, v[1].z // bottom
};
// put data for 24 vertices * components into the buffer
for (int i = 0, j = 0; i < 72; i += 3, j += 2)
{
fpb.put(verts[i + 0]);
fpb.put(verts[i + 1]);
fpb.put(verts[i + 2]);
fpb.put(GEOMETRY_NORMALS_DATA[i + 0]);
fpb.put(GEOMETRY_NORMALS_DATA[i + 1]);
fpb.put(GEOMETRY_NORMALS_DATA[i + 2]);
fpb.put(GEOMETRY_TEXTURE_DATA[j + 0]);
fpb.put(GEOMETRY_TEXTURE_DATA[j + 1]);
}
if (getBuffer(Type.Index) == null)
{
setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(GEOMETRY_INDICES_DATA));
}
setBuffer(Type.InterleavedData, 1, byteBuffer);
updateBound();
}
}
[/java]