No, moving it out of sight is faster then setting it to transparent. About recreating the object...i'm not sure how expensive that is. There's a bulk constructor in Object3D that might come in handy for this, but it still might suck. It's worth a try though.
Anyway, i went ahead and implemented a simple example that shows the basic idea (albeit without moving vertices out of sight, all cubes are visible all the time). It renders 1331 (11*11*11) blocks using a simple translation.
First, the version where each cube is a single Object3D. This version renders @~110fps on my machine:
package com.threed.jpct.demos.blocks;
import java.util.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;
/**
* Blocks done the "normal" way...
*
* @author EgonOlsen
*
*/
public class Blocks {
private World world;
private FrameBuffer buffer;
private List<Object3D> cubes;
private Object3D cube;
private float step = 1f;
public static void main(String[] args) throws Exception {
new Blocks().loop();
}
public Blocks() throws Exception {
world = new World();
world.setAmbientLight(100, 100, 100);
Light light = new Light(world);
light.setIntensity(255, 255, 255);
light.setPosition(new SimpleVector(0, 0, -100));
cubes = new ArrayList<Object3D>();
cube = Primitives.getCube(2);
cube.rotateY((float) (Math.PI / 4d));
cube.rotateMesh();
cube.clearRotation();
cube.build();
for (float y = -5; y < 6; y += step) {
for (float x = -5; x < 6; x += step) {
for (float z = -5; z < 6; z += step) {
Object3D c = new Object3D(cube, true);
c.shareCompiledData(cube);
c.compile();
c.build();
c.translate(x * 10, y * 10, z * 10);
cubes.add(c);
c.addParent(cube);
world.addObject(c);
}
}
}
world.getCamera().setPosition(0, 0, -150);
}
private void loop() throws Exception {
buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_GL_AA_2X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);
int fps = 0;
long time = System.currentTimeMillis();
int cnt = 0;
while (!org.lwjgl.opengl.Display.isCloseRequested()) {
boolean plus = (cnt / 100) % 2 != 0;
for (Object3D cube : cubes) {
SimpleVector trsn = cube.getTranslation();
if (trsn.length() > 2) {
trsn = trsn.normalize();
trsn.scalarMul(0.5f);
if (!plus) {
trsn.scalarMul(-1f);
}
cube.translate(trsn);
}
}
cnt++;
cube.rotateY(0.01f);
buffer.clear(java.awt.Color.BLUE);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
fps++;
if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps + "fps");
time = System.currentTimeMillis();
fps = 0;
}
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}
}
Second, the version where all cubes are merged into a mega cube. This version renders @~1500fps on my machine:
package com.threed.jpct.demos.blocks;
import java.util.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;
/**
* Blocks done the "hacky" way...
*
* @author EgonOlsen
*
*/
public class Bloxx {
private World world;
private FrameBuffer buffer;
private List<ObjectData> cubes;
private Object3D cube;
private Object3D megaCube;
private float step=1f;
public static void main(String[] args) throws Exception {
new Bloxx().loop();
}
public Bloxx() throws Exception {
world = new World();
world.setAmbientLight(100, 100, 100);
Light light = new Light(world);
light.setIntensity(255, 255, 255);
light.setPosition(new SimpleVector(0, 0, -100));
cubes = new ArrayList<ObjectData>();
cube = Primitives.getCube(2);
cube.rotateY((float) (Math.PI / 4d));
cube.rotateMesh();
cube.clearRotation();
cube.build();
List<Object3D> tmpCubes=new ArrayList<Object3D>();
for (float y = -5; y < 6; y += step) {
for (float x = -5; x < 6; x += step) {
for (float z = -5; z < 6; z += step) {
Object3D c = new Object3D(cube, true);
c.build();
ObjectData od=new ObjectData();
od.translate.set(x * 10, y * 10, z * 10);
cubes.add(od);
tmpCubes.add(c);
}
}
}
megaCube=Object3D.mergeAll(tmpCubes.toArray(new Object3D[0]));
megaCube.compile(true);
megaCube.build();
world.addObject(megaCube);
megaCube.addParent(cube);
megaCube.getMesh().setVertexController(new CubeTransformer(), false);
world.getCamera().setPosition(0, 0, -150);
}
private void loop() throws Exception {
buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_GL_AA_2X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);
int fps = 0;
long time = System.currentTimeMillis();
int cnt=0;
while (!org.lwjgl.opengl.Display.isCloseRequested()) {
boolean plus = (cnt / 100) % 2 != 0;
for (ObjectData cube : cubes) {
SimpleVector trsn = new SimpleVector(cube.translate);
if (trsn.length() > 2) {
trsn = trsn.normalize();
trsn.scalarMul(0.5f);
if (!plus) {
trsn.scalarMul(-1f);
}
cube.translate.add(trsn);
}
}
cnt++;
megaCube.getMesh().applyVertexController();
megaCube.touch();
cube.rotateY(0.01f);
buffer.clear(java.awt.Color.BLUE);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
fps++;
if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps + "fps");
time = System.currentTimeMillis();
fps = 0;
}
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}
private class CubeTransformer extends GenericVertexController {
private static final long serialVersionUID = 1L;
@Override
public void apply() {
SimpleVector[] toMesh=this.getDestinationMesh();
// SimpleVector[] toNormals=this.getDestinationMesh();
SimpleVector[] fromMesh=this.getSourceMesh();
// SimpleVector[] fromNormals=this.getSourceMesh();
int cubeCnt=-1;
SimpleVector translate=null;
SimpleVector tmp=new SimpleVector();
for (int i=0; i<fromMesh.length; i++) {
if (i%10==0) {
cubeCnt++;
translate=cubes.get(cubeCnt).translate;
}
tmp.set(fromMesh[i]);
tmp.add(translate);
toMesh[i].set(tmp);
}
}
}
private static class ObjectData {
SimpleVector translate=new SimpleVector();
Matrix rotation=new Matrix();
}
}
There are a few pitfalls with the second version of course...for example, all translations and rotations (which i'm not using in this example) have to be done in the IVertexController in object space instead of world space like in the first example. In this simple case, this actually doesn't matter though. I'm not going to say that this is the way to go, i just wanted to illustrate the idea.