Slow fps when looking at a bunch of Boxes

Alright, so I see a bunch of games out there like Mythruna (awesome) and minecraft (awesome) that have buches of cubes and stuff that dont have that bad fps. However, when I make my own with only 2000 Boxes (not that many at all in comparison) I only get like 20 fps. If I up it to 10000 Boxes, I get around 5 fps at max. Am I doing something wrong? Here is the current code:

[java]package jme3test.helloworld;

import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;

import com.jme3.input.controls.KeyTrigger;

import java.util.ArrayList;

import java.util.Random;

public class HelloJME3 extends SimpleApplication

{

public static void main(String[] args)

{

HelloJME3 app = new HelloJME3();

settingst = new AppSettings(true);

settingst.setFrameRate(75);

settingst.setFullscreen(true);

settingst.setResolution(1280, 800);

app.setSettings(settingst);

app.start();

}

private ActionListener al = new ActionListener() {

public void onAction(String name, boolean isPressed, float tpf) {

if (name.equals("Start Game")) {

// randomGenerator();

}

}

};

protected Random rand = new Random();

protected int maxCubes = 2000;

protected int startAt = 0;

protected ArrayList<Box> cube = new ArrayList<Box>();

protected static int xPositions = 0, yPositions = 0, zPositions = 0;

protected int returner = 0;

protected ArrayList<Integer> xPosition = new ArrayList<Integer>();

protected ArrayList<Integer> yPosition = new ArrayList<Integer>();

protected ArrayList<Integer> zPosition = new ArrayList<Integer>();

protected int xLimitf = 60, xLimits = -60, yLimitf = 20, yLimits = -20, zLimitf = 60, zLimits = -60;

protected int circ = 8;//increases by 8 every time.

protected int dynamic = 4;

protected static AppSettings settingst;

protected boolean isTrue = true;

private BitmapText helloText2;

private int lineLength = 100;

private int lineWidth = 100;

private int createAtX = 0;

private int createAtZ = 0;

//protected

// protected Geometry player;

@Override

public void simpleInitApp()

{

guiNode.detachAllChildren();

guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");

BitmapText helloText = new BitmapText(guiFont, false);

helloText.setSize(guiFont.getCharSet().getRenderedSize());

helloText.setText("Created by: Veenen, Inc.");

helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);

helloText2 = new BitmapText(guiFont, false);

helloText2.setSize(guiFont.getCharSet().getRenderedSize());

helloText2.setText("Cubes: " + startAt + 1);

helloText2.move(5, 52, 0);

fpsText.move(5, 15, 0);

guiNode.attachChild(helloText);

guiNode.attachChild(helloText2);

guiNode.attachChild(fpsText);

//rootNode.attachChild(SkyFactory.createSky(

// assetManager, "Textures/SKY02.zip", false));

inputManager.addMapping("Start Game", new KeyTrigger(KeyInput.KEY_J));

inputManager.addListener(al, new String[]{"Start Game"});

flyCam.setMoveSpeed(25);

//ChaseCamera c = new ChaseCamera();

//flyCam.setEnabled(false);

xPosition.add(0);

yPosition.add(0);

zPosition.add(0);

Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

yPosition.get(yPosition.size() - 1), zPosition.get(zPosition.size() - 1)), 1, 1, 1);

Geometry blue = new Geometry("Box", box1);

Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat1.setColor("Color", ColorRGBA.Cyan);

blue.setMaterial(mat1);

rootNode.attachChild(blue);

randomGenerator();

}

public void randomGenerator()

{

for(int i = startAt; i < maxCubes - 1; i++)

{

randomize();

cube.add(new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

yPosition.get(yPosition.size() - 1),

zPosition.get(zPosition.size() - 1)), 1,1,1));

Geometry box = new Geometry("Box", cube.get(i));

Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat1.setColor("Color", randomColor());

box.setMaterial(mat1);

rootNode.attachChild(box);

}

}

public ColorRGBA randomColor() {

ColorRGBA color = ColorRGBA.Black;

int randomn = rand.nextInt(4);

if (randomn == 0)

{

color = ColorRGBA.Orange;

}

else if (randomn == 1)

{

color = ColorRGBA.Blue;

}

else if (randomn == 2)

{

color = ColorRGBA.Brown;

}

else if (randomn == 3)

{

color = ColorRGBA.Magenta;

}

return color;

}

public void randomize()

{

int xpos = xPosition.get(xPosition.size() - 1);

int ypos = yPosition.get(yPosition.size() - 1);

int zpos = zPosition.get(zPosition.size() - 1);

int x = 0;

int y = 0;

int z = 0;

boolean unTrue = true;

while (unTrue)

{

unTrue = false;

boolean xChanged = false;

x = 0;

y = 0;

z = 0;

if (xpos >= lineLength)

{

x = 2;

xChanged = true;

}

else

{

x = xPosition.get(xPosition.size() - 1) + 2;

}

if (xChanged)

{

//y = yPosition.get(yPosition.size() - 50) + 2;

}

else {

y = rand.nextInt(3);

if (yPosition.size() > 50)

{

if (yPosition.size() > 51)

{

if (y == 0 && ypos < yLimitf && getym(50) > ypos - 2)

{

y = ypos + 2;

}

else if (y == 1 && ypos > yLimits && getym(50) < ypos + 2)

{

y = ypos - 2;

}

else if (y == 2 && getym(50) > ypos - 2 && getym(50) < ypos + 2)

{

y = ypos;

}

else

{

if (ypos >= yLimitf)

{

y = ypos - 2;

}

else if (ypos <= yLimits)

{

y = ypos + 2;

}

else if (y == 0 && getym(50) >= ypos - 4)

{

y = ypos - 2;

}

else if (y == 0 && getym(50) >= ypos - 2)

{

y = ypos;

}

else if (y == 1 && getym(50) >= ypos + 4)

{

y = ypos + 2;

}

else if (y == 1 && getym(50) >= ypos + 2)

{

y = ypos;

}

else if (y == 2 && getym(50) <= ypos - 2)

{

y = ypos - 2;

}

else if (y == 2 && getym(50) >= ypos + 2)

{

y = ypos + 2;

}

else

{

System.out.println("wtf");

}

}

}

else if (yPosition.size() == 50)

{

if (y == 0 && ypos < yLimitf)

{

y = getym(50) + 2;

}

else if (y == 1 && ypos > yLimits)

{

y = getym(50) - 2;

}

}

}

else

{

if (y == 0 && ypos < yLimitf)

{

y = ypos + 2;

}

else if (y == 1 && ypos > yLimits)

{

y = ypos - 2;

}

else if (y == 2)

{

y = ypos;

}

else if (y == 0 && ypos >= yLimitf)

{

y = ypos - 2;

}

else if (y == 1 && ypos <= yLimits)

{

y = ypos + 2;

}

}

}

if (xChanged)

{

z = zpos + 2;

}

else {

z = zpos;

}

// for (int i = 0; i < xPosition.size(); i++)

// {

// if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&

// y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1

// &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=

// -1)

// {

// unTrue = true;

// }

// }

}

xPosition.add(x);

yPosition.add(y);

zPosition.add(z);

}

public int getxm(int i)

{

return xPosition.get(xPosition.size() - i);

}

public int getym(int i)

{

return yPosition.get(yPosition.size() - i);

}

public int getzm(int i)

{

return zPosition.get(zPosition.size() - i);

}

public int getx(int i)

{

return xPosition.get(i);

}

public int gety(int i)

{

return yPosition.get(i);

}

public int getz(int i)

{

return zPosition.get(i);

}

@Override

public void simpleUpdate(float tpf) {

helloText2.setText("Cubes: " + xPosition.size());

}

}[/java]

Basically they combine hundrets of boxes to one large model consisting out of boxes, to workaround that limitation, as pure polygon power is not the problem, only the object count.



GeometryBatchFactory is one starting point for this.

Also you should think of a intelligent system to remove not visible boxes from the rendering process (eg. all where on 6 sides around them is a nontransparent one)

http://hub.jmonkeyengine.org/groups/general/forum/topic/object-count-performance-sourvey-everyone-please-participate/



No way in rendering brute force use a better logic behind this, search forum for more.

@EmpirePhoenix: You wanted to show him even more boxes and slow downs? :stuck_out_tongue:

I did the survey… and it seems that I have a low end computer. Oh well. This still does not answer the question of how minecraft and mythruna run so much better.

[edit]Well it indirectly answers my question. I guess I will have a fun time searching the forums.

Would TerraMonkey work for block type terrains?[/edit]

I too need a lot of Boxes or even Spheres and Arrows in the future and I’ve no idea how to “optimize” the code … I was hoping it would be enough to just put each in a Node and have all millions of them there in mem loaded and so…



here’s your code with 20k boxes

http://i.imgur.com/XxTO0.png



and the code that did that (your code from first post, a bit modified):

pre type="java"
package org.jme3.tests;





import java.util.ArrayList;


import java.util.Random;





import com.jme3.app.SimpleApplication;


import com.jme3.font.BitmapText;


import com.jme3.input.KeyInput;


import com.jme3.input.controls.ActionListener;


import com.jme3.input.controls.KeyTrigger;


import com.jme3.material.Material;


import com.jme3.math.ColorRGBA;


import com.jme3.math.Vector3f;


import com.jme3.scene.Geometry;


import com.jme3.scene.shape.Box;


import com.jme3.system.AppSettings;





public class XXx extends SimpleApplication {





    public static void main(String[] args) {


XXx app = new XXx();


settingst = new AppSettings(true);


settingst.setFrameRate(75);


settingst.setFullscreen(false);


settingst.setResolution(1280, 800);


settingst.setVSync(true);


app.setSettings(settingst);


app.setShowSettings(false);


app.start();


    }





    private final ActionListener al = new ActionListener() {





@Override


public void onAction(String name, boolean isPressed, float tpf) {


    if (name.equals(“Start Game”)) {


// randomGenerator();


    }


}


    };


    protected Random rand = new Random();


    protected int maxCubes = 20000;


    protected int startAt = 0;


    protected ArrayList<Box> cube = new ArrayList<Box>();


    protected static int xPositions = 0, yPositions = 0, zPositions = 0;


    protected int returner = 0;


    protected ArrayList<Integer> xPosition = new ArrayList<Integer>();


    protected ArrayList<Integer> yPosition = new ArrayList<Integer>();


    protected ArrayList<Integer> zPosition = new ArrayList<Integer>();


    protected int xLimitf = 60, xLimits = -60, yLimitf = 20, yLimits = -20,


    zLimitf = 60, zLimits = -60;


    protected int circ = 8; // increases


    // by


    // 8


    // every


    // time.


    protected int dynamic = 4;


    protected static AppSettings settingst;


    protected boolean isTrue = true;


    private BitmapText helloText2;


    private final int lineLength = 100;


    private final int lineWidth = 100;


    private final int createAtX = 0;


    private final int createAtZ = 0;





    // protected


    // protected Geometry player;


    @Override


    public void simpleInitApp() {


// guiNode.detachAllChildren();


guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);


BitmapText helloText = new BitmapText(guiFont, false);


helloText.setSize(guiFont.getCharSet().getRenderedSize());


helloText.setText(“Created by: Veenen, Inc.”);


helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);


helloText2 = new BitmapText(guiFont, false);


helloText2.setSize(guiFont.getCharSet().getRenderedSize());


helloText2.setText("Cubes: " + startAt + 1);


helloText2.move(145, 52, 0);


fpsText.move(145, 15, 0);


guiNode.attachChild(helloText);


guiNode.attachChild(helloText2);


guiNode.attachChild(fpsText);


// rootNode.attachChild(SkyFactory.createSky(


// assetManager, “Textures/SKY02.zip”, false));


inputManager.addMapping(“Start Game”, new KeyTrigger(KeyInput.KEY_J));


inputManager.addListener(al, new String[] { “Start Game” });


flyCam.setMoveSpeed(25);


// ChaseCamera c = new ChaseCamera();


// flyCam.setEnabled(false);


xPosition.add(new Integer(0));


yPosition.add(new Integer(0));


zPosition.add(new Integer(0));


Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1)


.floatValue(),


yPosition.get(yPosition.size() - 1).floatValue(), zPosition


.get(zPosition.size() - 1).floatValue()), 1, 1, 1);


Geometry blue = new Geometry(“Box”, box1);


Material mat1 = new Material(assetManager,


“Common/MatDefs/Misc/Unshaded.j3md”);


mat1.setColor(“Color”, ColorRGBA.Cyan);


blue.setMaterial(mat1);


rootNode.attachChild(blue);


randomGenerator();


    }





    public void randomGenerator() {


for (int i = startAt; i < maxCubes - 1; i++) {


    randomize();


    cube.add(new Box(new Vector3f(xPosition.get(xPosition.size() - 1)


    .floatValue(), yPosition.get(yPosition.size() - 1)


    .floatValue(), zPosition.get(zPosition.size() - 1)


    .floatValue()), 1, 1, 1));


    Geometry box = new Geometry(“Box”, cube.get(i));


    Material mat1 = new Material(assetManager,


    “Common/MatDefs/Misc/Unshaded.j3md”);


    mat1.setColor(“Color”, randomColor());


    box.setMaterial(mat1);


    rootNode.attachChild(box);


}


    }





    public ColorRGBA randomColor() {


ColorRGBA color = ColorRGBA.Black;


int randomn = rand.nextInt(4);


if (randomn == 0) {


    color = ColorRGBA.Orange;


} else if (randomn == 1) {


    color = ColorRGBA.Blue;


} else if (randomn == 2) {


    color = ColorRGBA.Brown;


} else if (randomn == 3) {


    color = ColorRGBA.Magenta;


}


return color;


    }





    public void randomize() {


int xpos = xPosition.get(xPosition.size() - 1).intValue();


int ypos = yPosition.get(yPosition.size() - 1).intValue();


int zpos = zPosition.get(zPosition.size() - 1).intValue();


int x = 0;


int y = 0;


int z = 0;


boolean unTrue = true;


while (unTrue) {


    unTrue = false;


    boolean xChanged = false;


    x = 0;


    y = 0;


    z = 0;


    if (xpos >= lineLength) {


x = 2;


xChanged = true;


    } else {


x = xPosition.get(xPosition.size() - 1).intValue() + 2;


    }


    if (xChanged) {


// y = yPosition.get(yPosition.size() - 50) + 2;


    } else {


y = rand.nextInt(3);


if (yPosition.size() > 50) {


    if (yPosition.size() > 51) {


if (y == 0 && ypos < yLimitf && getym(50) > ypos - 2) {


    y = ypos + 2;


} else if (y == 1 && ypos > yLimits


&& getym(50) < ypos + 2) {


    y = ypos - 2;


} else if (y == 2 && getym(50) > ypos - 2


&& getym(50) < ypos + 2) {


    y = ypos;


} else {


    if (ypos >= yLimitf) {


y = ypos - 2;


    } else if (ypos <= yLimits) {


y = ypos + 2;


    } else if (y == 0 && getym(50) >= ypos - 4) {


y = ypos - 2;


    } else if (y == 0 && getym(50) >= ypos - 2) {


y = ypos;


    } else if (y == 1 && getym(50) >= ypos + 4) {


y = ypos + 2;


    } else if (y == 1 && getym(50) >= ypos + 2) {


y = ypos;


    } else if (y == 2 && getym(50) <= ypos - 2) {


y = ypos - 2;


    } else if (y == 2 && getym(50) >= ypos + 2) {


y = ypos + 2;


    } else {


System.out.println(“wtf”);


    }


}


    } else if (yPosition.size() == 50) {


if (y == 0 && ypos < yLimitf) {


    y = getym(50) + 2;


} else if (y == 1 && ypos > yLimits) {


    y = getym(50) - 2;


}


    }


} else {


    if (y == 0 && ypos < yLimitf) {


y = ypos + 2;


    } else if (y == 1 && ypos > yLimits) {


y = ypos - 2;


    } else if (y == 2) {


y = ypos;


    } else if (y == 0 && ypos >= yLimitf) {


y = ypos - 2;


    } else if (y == 1 && ypos <= yLimits) {


y = ypos + 2;


    }


}


    }


    if (xChanged) {


z = zpos + 2;


    } else {


z = zpos;


    }


    // for (int i = 0; i < xPosition.size(); i++)


    // {


    // if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&


    // y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1


    // &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=


    // -1)


    // {


    // unTrue = true;


    // }


    // }


}


xPosition.add(new Integer(x));


yPosition.add(new Integer(y));


zPosition.add(new Integer(z));


    }





    public int getxm(int i) {


return xPosition.get(xPosition.size() - i).intValue();


    }





    public int getym(int i) {


return yPosition.get(yPosition.size() - i).intValue();


    }





    public int getzm(int i) {


return zPosition.get(zPosition.size() - i).intValue();


    }





    public int getx(int i) {


return xPosition.get(i).intValue();


    }





    public int gety(int i) {


return yPosition.get(i).intValue();


    }





    public int getz(int i) {


return zPosition.get(i).intValue();


    }





    @Override


    public void simpleUpdate(float tpf) {


helloText2.setText("Cubes: " + xPosition.size());


    }


}



/pre

check this out: http://www.youtube.com/watch?v=bkXFkxrYtLY

the idea starting at 0:38 might be how …

Don’t attach the cubes directly to the rootnode,



for a start use a seperate node to build the cube worldm, then use the GeometryBatchFactory.optimize(yournodehere) and attach the returned Node to the rootnode. The function basically copies all the modeldata into one big model and returns it. Whenever you change any cube you have to regenerate that model for rendering.



While this probably is not enough alone, at least it should get you playable framerates.

1 Like

Try to use the GeometryBatchFactory.optimize, it merges objects that have the same material in a single geometry, so it you have 10000 boxes with the same material you’ll end up with one object. Note that the amount of vertices or polygon won’t change.



The thing is modern graphic cards can handle a draw call with millions of polygons, but not a million of draw calls with one polygon.



@cyuczieekc in your case it won’t work, because you generate a new material for each box.

You should create your 4 materials first and then randomly choose between them.

Then use the batch factory, your scene will be reduced to 4 objects, and will run very faster.

1 Like

I tried GeometryBatchFactory.optimize(terrain); with my new terrain Node that I added all of my stuff terrain boxes to, however, this did not seem to decrease the number of objects in the scene. Although it did speed the fps up a little.

Well read the last post again

1 Like

Ok my remark on material I made to @cyuczieekc stands for you too. (in fact @cyuczieekc was using your code, I didn’t get that)

You create a new material for each box, just create your four materials in the simple init and choose randomly among this for to assign to your generated boxes.

1 Like

@EmpirePhoenix



Ahh! I see now. Thanks.

Hmm… well… maybe not. Should I create a new Geometry every time? Here is what I have and its not working:



[java]package com.veenen;



import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;

import com.jme3.input.controls.KeyTrigger;

import java.util.ArrayList;

import java.util.Random;

import com.jme3.light.DirectionalLight;

import com.jme3.scene.Node;

import jme3tools.optimize.GeometryBatchFactory;



public class Main extends SimpleApplication

{



public static void main(String[] args)

{

Main app = new Main();

settingst = new AppSettings(true);

settingst.setFrameRate(75);

settingst.setResolution(1280, 700);

settingst.setVSync(true);

settingst.setFullscreen(false);

app.setSettings(settingst);

app.setShowSettings(false);

app.start();

}



private ActionListener al = new ActionListener() {



public void onAction(String name, boolean isPressed, float tpf) {

if (name.equals("Start Game")) {

// randomGenerator();

}

}

};

protected Random rand = new Random();

protected int maxCubes = 2000;

protected int startAt = 0;

protected ArrayList<Box> cube = new ArrayList<Box>();

protected static int xPositions = 0, yPositions = 0, zPositions = 0;

protected int returner = 0;

protected ArrayList<Integer> xPosition = new ArrayList<Integer>();

protected ArrayList<Integer> yPosition = new ArrayList<Integer>();

protected ArrayList<Integer> zPosition = new ArrayList<Integer>();

protected int xLimitf = 60, xLimits = -60, yLimitf = 60, yLimits = -20, zLimitf = 60, zLimits = -60;

protected int circ = 8;//increases by 8 every time.

protected int dynamic = 4;

protected static AppSettings settingst;

protected boolean isTrue = true;

private BitmapText helloText2;

private int lineLength = 50;

protected Node terrain;



Material mat1;

Material mat2;

Material mat3;

Material mat4;



//protected



// protected Geometry player;



@Override

public void simpleInitApp()

{

// guiNode.detachAllChildren();

// guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");

// BitmapText helloText = new BitmapText(guiFont, false);

// helloText.setSize(guiFont.getCharSet().getRenderedSize());

// helloText.setText("Created by: Veenen, Inc.");

// helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);

// helloText2 = new BitmapText(guiFont, false);

// helloText2.setSize(guiFont.getCharSet().getRenderedSize());

// helloText2.setText("Cubes: " + startAt + 1);

// helloText2.move(5, 52, 0);

// fpsText.move(5, 15, 0);

// guiNode.attachChild(helloText);

// guiNode.attachChild(helloText2);

// guiNode.attachChild(fpsText);



terrain = new Node();



mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat1.setColor("Color", ColorRGBA.Blue);

mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat2.setColor("Color", ColorRGBA.Brown);

mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat3.setColor("Color", ColorRGBA.Pink);

mat4 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat4.setColor("Color", ColorRGBA.Orange);

//rootNode.attachChild(SkyFactory.createSky(

// assetManager, "Textures/SKY02.zip", false));



inputManager.addMapping("Start Game", new KeyTrigger(KeyInput.KEY_J));

inputManager.addListener(al, new String[]{"Start Game"});



flyCam.setMoveSpeed(25);

//ChaseCamera c = new ChaseCamera();

//flyCam.setEnabled(false);



xPosition.add(0);

yPosition.add(0);

zPosition.add(0);

Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

yPosition.get(yPosition.size() - 1), zPosition.get(zPosition.size() - 1)), 1, 1, 1);

Geometry blue = new Geometry("Box", box1);

Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat1.setColor("Color", ColorRGBA.Cyan);

blue.setMaterial(mat1);

terrain.attachChild(blue);



DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f(-0.1f, 50, -1.0f));

sun.setLastDistance(500);

rootNode.addLight(sun);



randomGenerator();

GeometryBatchFactory.optimize(terrain);

rootNode.attachChild(terrain);



}







public void randomGenerator()

{

for(int i = startAt; i < maxCubes - 1; i++)

{

randomize();

cube.add(new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

yPosition.get(yPosition.size() - 1),

zPosition.get(zPosition.size() - 1)), 1,1,1));

Geometry box = new Geometry("Box", cube.get(i));

box.setMaterial(randomMaterial());

GeometryBatchFactory.optimize(box);

terrain.attachChild(box);

}

}



public Material randomMaterial()

{

Material returnermat = new Material();



int randomn = rand.nextInt(4);



if (randomn == 0)

{

returnermat = mat1;

}

else if (randomn == 1)

{

returnermat = mat2;

}

else if (randomn == 2)

{

returnermat = mat3;

}

else if (randomn == 3)

{

returnermat = mat4;

}



return returnermat;

}



public ColorRGBA randomColor()

{

ColorRGBA color = ColorRGBA.Black;



int randomn = rand.nextInt(4);



if (randomn == 0)

{

color = ColorRGBA.Orange;

}

else if (randomn == 1)

{

color = ColorRGBA.Blue;

}

else if (randomn == 2)

{

color = ColorRGBA.Brown;

}

else if (randomn == 3)

{

color = ColorRGBA.Magenta;

}



return color;

}



public void randomize()

{

int xpos = xPosition.get(xPosition.size() - 1);

int ypos = yPosition.get(yPosition.size() - 1);

int zpos = zPosition.get(zPosition.size() - 1);



int x = 0;

int y = 0;

int z = 0;



boolean unTrue = true;



while (unTrue)

{

unTrue = false;

boolean xChanged = false;



x = 0;

y = 0;

z = 0;



if (xpos >= lineLength * 2)

{

x = 2;

xChanged = true;

}

else

{

x = xPosition.get(xPosition.size() - 1) + 2;

}



if (xChanged)

{

//y = yPosition.get(yPosition.size() - lineLength) + 2;

}

else {

y = rand.nextInt(3);

if (yPosition.size() > lineLength)

{

if (yPosition.size() > 51)

{

if (y == 0 && ypos < yLimitf && getym(lineLength) > ypos - 2)

{

y = ypos + 2;

}

else if (y == 1 && ypos > yLimits && getym(lineLength) < ypos + 2)

{

y = ypos - 2;

}

else if (y == 2 && getym(lineLength) > ypos - 2 && getym(lineLength) < ypos + 2)

{

y = ypos;

}

else

{

if (ypos >= yLimitf)

{

y = ypos - 2;

}

else if (ypos <= yLimits)

{

y = ypos + 2;

}

else if (y == 0 && getym(lineLength) >= ypos - 4)

{

y = ypos - 2;

}

else if (y == 0 && getym(lineLength) >= ypos - 2)

{

y = ypos;

}

else if (y == 1 && getym(lineLength) >= ypos + 4)

{

y = ypos + 2;

}

else if (y == 1 && getym(lineLength) >= ypos + 2)

{

y = ypos;

}

else if (y == 2 && getym(lineLength) <= ypos - 2)

{

y = ypos - 2;

}

else if (y == 2 && getym(lineLength) >= ypos + 2)

{

y = ypos + 2;

}

else

{

System.out.println("wtf");

}

}

}

else if (yPosition.size() == lineLength)

{

if (y == 0 && ypos < yLimitf)

{

y = getym(lineLength) + 2;

}

else if (y == 1 && ypos > yLimits)

{

y = getym(lineLength) - 2;

}

}

}

else

{

if (y == 0 && ypos < yLimitf)

{

y = ypos + 2;

}

else if (y == 1 && ypos > yLimits)

{

y = ypos - 2;

}

else if (y == 2)

{

y = ypos;

}

else if (y == 0 && ypos >= yLimitf)

{

y = ypos - 2;

}

else if (y == 1 && ypos <= yLimits)

{

y = ypos + 2;

}

}

}



if (xChanged)

{

z = zpos + 2;

}

else {

z = zpos;

}





// for (int i = 0; i < xPosition.size(); i++)

// {

// if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&

// y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1

// &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=

// -1)

// {

// unTrue = true;

// }

// }

}

xPosition.add(x);

yPosition.add(y);

zPosition.add(z);

}



public int getxm(int i)

{

return xPosition.get(xPosition.size() - i);

}



public int getym(int i)

{

return yPosition.get(yPosition.size() - i);

}



public int getzm(int i)

{

return zPosition.get(zPosition.size() - i);

}



public int getx(int i)

{

return xPosition.get(i);

}



public int gety(int i)

{

return yPosition.get(i);

}



public int getz(int i)

{

return zPosition.get(i);

}



@Override

public void simpleUpdate(float tpf) {

//helloText2.setText("Cubes: " + xPosition.size() + ", " + settingst.getWidth());

}

}[/java]

looks fine to me

http://i.imgur.com/4DyQS.jpg



I removed the lines 24,26 and 123 though



Note that there are 14 objects that come from the GUI, so 18 objects is ok

I am trying that, and it still gives me 2000 objects in the scene. Maybe it just hates me. Mind posting the code that you ran to take that image?

now THAT is awesome!!!

I’m getting 727 fps with 20k cubes and that

GeometryBatchFactory.optimize( terrain );

this is freaking amazing!!!



Note that I removed these lines:

settingst.setFrameRate( 75 );

GeometryBatchFactory.optimize( box );



and disabled VSync (which limited fps to 60) by changing to this:

settingst.setVSync( false );



http://i.imgur.com/rPc1b.png

Ahhh! Its not working for me! Someone please post the working code! 8O

ehnohpe said:
Ahhh! Its not working for me! Someone please post the working code! 8O


ok, this is really your code from your last post:

`pre type="java"`
/**

 * 

 * Copyright (c) 2011, eviltry

 * All rights reserved.

 * 

 * Redistribution and use in source and binary forms, with or without

 * modification, are permitted provided that the following conditions are

 * met:

 * 

 * * Redistributions of source code must retain the above copyright

 * notice, this list of conditions and the following disclaimer.

 * 

 * * Redistributions in binary form must reproduce the above copyright

 * notice, this list of conditions and the following disclaimer in the

 * documentation and/or other materials provided with the distribution.

 * 

 * * Neither the name of 'frozenaxes' nor the names of its contributors

 * may be used to endorse or promote products derived from this software

 * without specific prior written permission.

 * 

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED

 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR

 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR

 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,

 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,

 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR

 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF

 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING

 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */



package org.jme3.tests;



import java.util.ArrayList;

import java.util.Random;



import jme3tools.optimize.GeometryBatchFactory;



import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;



public class Xaxadsads extends SimpleApplication {



    public static void main(String[] args) {

Xaxadsads app = new Xaxadsads();

settingst = new AppSettings(true);

// settingst.setFrameRate( 75 );

settingst.setResolution(1280, 700);

settingst.setVSync(false);

settingst.setFullscreen(false);

app.setSettings(settingst);

app.setShowSettings(false);

app.start();

    }



    private final ActionListener al = new ActionListener() {



@Override

public void onAction(String name, boolean isPressed, float tpf) {

    if (name.equals("Start Game")) {

// randomGenerator();

    }

}

    };

    protected Random rand = new Random();

    protected int maxCubes = 20000;

    protected int startAt = 0;

    protected ArrayList<Box> cube = new ArrayList<Box>();

    protected static int xPositions = 0, yPositions = 0, zPositions = 0;

    protected int returner = 0;

    protected ArrayList<Integer> xPosition = new ArrayList<Integer>();

    protected ArrayList<Integer> yPosition = new ArrayList<Integer>();

    protected ArrayList<Integer> zPosition = new ArrayList<Integer>();

    protected int xLimitf = 60, xLimits = -60, yLimitf = 60, yLimits = -20,

    zLimitf = 60, zLimits = -60;

    protected int circ = 8; // increases

    // by

    // 8

    // every

    // time.

    protected int dynamic = 4;

    protected static AppSettings settingst;

    protected boolean isTrue = true;

    private BitmapText helloText2;

    private final int lineLength = 50;

    protected Node terrain;

    Material mat1;

    Material mat2;

    Material mat3;

    Material mat4;



    // protected

    // protected Geometry player;

    @Override

    public void simpleInitApp() {

// guiNode.detachAllChildren();

// guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");

// BitmapText helloText = new BitmapText(guiFont, false);

// helloText.setSize(guiFont.getCharSet().getRenderedSize());

// helloText.setText("Created by: Veenen, Inc.");

// helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);

// helloText2 = new BitmapText(guiFont, false);

// helloText2.setSize(guiFont.getCharSet().getRenderedSize());

// helloText2.setText("Cubes: " + startAt + 1);

// helloText2.move(5, 52, 0);

// fpsText.move(5, 15, 0);

// guiNode.attachChild(helloText);

// guiNode.attachChild(helloText2);

// guiNode.attachChild(fpsText);

terrain = new Node();

mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat1.setColor("Color", ColorRGBA.Blue);

mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat2.setColor("Color", ColorRGBA.Brown);

mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat3.setColor("Color", ColorRGBA.Pink);

mat4 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat4.setColor("Color", ColorRGBA.Orange);

// rootNode.attachChild(SkyFactory.createSky(

// assetManager, "Textures/SKY02.zip", false));

inputManager.addMapping("Start Game", new KeyTrigger(KeyInput.KEY_J));

inputManager.addListener(al, new String[] { "Start Game" });

flyCam.setMoveSpeed(25);

// ChaseCamera c = new ChaseCamera();

// flyCam.setEnabled(false);

xPosition.add(0);

yPosition.add(0);

zPosition.add(0);

Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

yPosition.get(yPosition.size() - 1), zPosition.get(zPosition

.size() - 1)), 1, 1, 1);

Geometry blue = new Geometry("Box", box1);

Material mat11 = new Material(assetManager,

"Common/MatDefs/Misc/Unshaded.j3md");

mat11.setColor("Color", ColorRGBA.Cyan);

blue.setMaterial(mat11);

terrain.attachChild(blue);

DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f(-0.1f, 50, -1.0f));

sun.setLastDistance(500);

rootNode.addLight(sun);

randomGenerator();

GeometryBatchFactory.optimize(terrain);

rootNode.attachChild(terrain);

    }



    public void randomGenerator() {

for (int i = startAt; i < maxCubes - 1; i++) {

    randomize();

    cube.add(new Box(new Vector3f(xPosition.get(xPosition.size() - 1),

    yPosition.get(yPosition.size() - 1), zPosition

    .get(zPosition.size() - 1)), 1, 1, 1));

    Geometry box = new Geometry("Box", cube.get(i));

    box.setMaterial(randomMaterial());

    // GeometryBatchFactory.optimize( box );

    terrain.attachChild(box);

}

    }



    public Material randomMaterial() {

Material returnermat = new Material();

int randomn = rand.nextInt(4);

if (randomn == 0) {

    returnermat = mat1;

} else if (randomn == 1) {

    returnermat = mat2;

} else if (randomn == 2) {

    returnermat = mat3;

} else if (randomn == 3) {

    returnermat = mat4;

}

return returnermat;

    }



    public ColorRGBA randomColor() {

ColorRGBA color = ColorRGBA.Black;

int randomn = rand.nextInt(4);

if (randomn == 0) {

    color = ColorRGBA.Orange;

} else if (randomn == 1) {

    color = ColorRGBA.Blue;

} else if (randomn == 2) {

    color = ColorRGBA.Brown;

} else if (randomn == 3) {

    color = ColorRGBA.Magenta;

}

return color;

    }



    public void randomize() {

int xpos = xPosition.get(xPosition.size() - 1);

int ypos = yPosition.get(yPosition.size() - 1);

int zpos = zPosition.get(zPosition.size() - 1);

int x = 0;

int y = 0;

int z = 0;

boolean unTrue = true;

while (unTrue) {

    unTrue = false;

    boolean xChanged = false;

    x = 0;

    y = 0;

    z = 0;

    if (xpos >= lineLength * 2) {

x = 2;

xChanged = true;

    } else {

x = xPosition.get(xPosition.size() - 1) + 2;

    }

    if (xChanged) {

// y = yPosition.get(yPosition.size() - lineLength) + 2;

    } else {

y = rand.nextInt(3);

if (yPosition.size() > lineLength) {

    if (yPosition.size() > 51) {

if (y == 0 && ypos < yLimitf

&& getym(lineLength) > ypos - 2) {

    y = ypos + 2;

} else if (y == 1 && ypos > yLimits

&& getym(lineLength) < ypos + 2) {

    y = ypos - 2;

} else if (y == 2 && getym(lineLength) > ypos - 2

&& getym(lineLength) < ypos + 2) {

    y = ypos;

} else {

    if (ypos >= yLimitf) {

y = ypos - 2;

    } else if (ypos <= yLimits) {

y = ypos + 2;

    } else if (y == 0 && getym(lineLength) >= ypos - 4) {

y = ypos - 2;

    } else if (y == 0 && getym(lineLength) >= ypos - 2) {

y = ypos;

    } else if (y == 1 && getym(lineLength) >= ypos + 4) {

y = ypos + 2;

    } else if (y == 1 && getym(lineLength) >= ypos + 2) {

y = ypos;

    } else if (y == 2 && getym(lineLength) <= ypos - 2) {

y = ypos - 2;

    } else if (y == 2 && getym(lineLength) >= ypos + 2) {

y = ypos + 2;

    } else {

System.out.println("wtf");

    }

}

    } else if (yPosition.size() == lineLength) {

if (y == 0 && ypos < yLimitf) {

    y = getym(lineLength) + 2;

} else if (y == 1 && ypos > yLimits) {

    y = getym(lineLength) - 2;

}

    }

} else {

    if (y == 0 && ypos < yLimitf) {

y = ypos + 2;

    } else if (y == 1 && ypos > yLimits) {

y = ypos - 2;

    } else if (y == 2) {

y = ypos;

    } else if (y == 0 && ypos >= yLimitf) {

y = ypos - 2;

    } else if (y == 1 && ypos <= yLimits) {

y = ypos + 2;

    }

}

    }

    if (xChanged) {

z = zpos + 2;

    } else {

z = zpos;

    }

    // for (int i = 0; i < xPosition.size(); i++)

    // {

    // if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&

    // y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1

    // &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=

    // -1)

    // {

    // unTrue = true;

    // }

    // }

}

xPosition.add(x);

yPosition.add(y);

zPosition.add(z);

    }



    public int getxm(int i) {

return xPosition.get(xPosition.size() - i);

    }



    public int getym(int i) {

return yPosition.get(yPosition.size() - i);

    }



    public int getzm(int i) {

return zPosition.get(zPosition.size() - i);

    }



    public int getx(int i) {

return xPosition.get(i);

    }



    public int gety(int i) {

return yPosition.get(i);

    }



    public int getz(int i) {

return zPosition.get(i);

    }



    @Override

    public void simpleUpdate(float tpf) {

// helloText2.setText("Cubes: " + xPosition.size() + ", " +

// settingst.getWidth());

    }

}


`/pre`

For some reason it still does not work. Maybe because Im using mac?