Why important keep the object render count around 100-200?

This is limitation of JME3 or Java garbage collector?

I used
someNode.setCullHint(Spatial.CullHint.Dynamic);
this reduced the Object Count (Batch Count),

and
-XX:+UseSerialGC
this pick up fps on 50%.

But in my thought this is few, if in scene necessary render objects over 5000.

This is a sign that your scene is completely messed up. That’s why we recommend a smaller number because usually the people who want to render 5000 objects (ie: 5000 separate draw dispatch round trips to the GPU per frame) have done something very wrong.

This is answer on my question?

In that case if this issue of hardware, I in impasse…

You’ve provided no information about your scene so it is impossible for us to help you further.

  1. Code there (MonkeyBlaster_Tutorial_Part5, need to move assets in project folder)
    http://cdn.tutsplus.com/gamedev/uploads/2013/11/MonkeyBlaster-Source.zip
    I created more objects by increase “int numColumns , int numRows” in class “Grid”.

  2. Class “Grid” creates geometry with fully the same materials in method:
    private Geometry createLine(float thickness, AssetManager assetManager) {…

  3. Trouble - I try
    a. GeometryBatchFactory.optimize(gridNode);

  • this don"t render “gridNode”
    b. gridNode = new SimpleBatchNode(“BatchNode”); // or
    gridNode = new BatchNode(“BatchNode”);
    gridNode.batch();
  • this have any effects.
    с. gridNode.batch();
    after add geometry in “gridNode” - NullPointerException.

In my experience, you can use 2,000 to 5,000 objects, provided you are using decent computer hardware (what would typically be considered a gaming machine).

While the code in the tutorial is fine, it cannot be used to create this amount of lines. Apparently the author never thought of creating more than a dozen of lines, so he did not over-optimise it for clarity. If you are to create hundreds of lines, then the best way would be to put them all into a single Geometry and use a single material. You can modify the Geometrys vertex position buffer to manipulate the lines. I would suggest you to look at the custom mesh tutorial and examine the code of ParticleEmitter.

Mesh Mode
Mesh.Mode.Points
Mesh.Mode.Lines
Mesh.Mode.LineLoop
Mesh.Mode.LineStrip
Mesh.Mode.Triangles
Mesh.Mode.TriangleStrip
Mesh.Mode.TriangleFan
Mesh.Mode.Hybrid

Which required to use?

Depends on your needs. If you want a more wireframe-like behavior, you can use one of the Line* modes. Or you could just go with quads and use the standard Triangles mode (a quad is made of 2 triangles). If you need help understanding any of these, please read the correcponsing OpenGL documentation papers like here or here.

I view this example for batching:
jmonkeyengine/TestBatchNodeCluster.java at master · jMonkeyEngine/jmonkeyengine · GitHub{

and tried write code to create stars. But I have dont work batching. Maybe this caused because batching in jME is experimental function.

Quote code


package monkeyblaster;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
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.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.scene.*;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.system.NanoTimer;
import java.util.ArrayList;
import java.util.Random;
import jme3tools.optimize.GeometryBatchFactory;
import com.jme3.scene.Mesh;
import com.jme3.util.BufferUtils;

public class TestBatchNodeCluster extends SimpleApplication {

public static void main(String[] args) {
    TestBatchNodeCluster app = new TestBatchNodeCluster();
    settingst = new AppSettings(true);
    settingst.setResolution(1640, 880);
    settingst.setVSync(false);
    settingst.setFullscreen(false);
    app.setSettings(settingst);
    app.setShowSettings(false);
    app.start();
}

public Geometry star;
public Geometry[] stars;
protected static AppSettings settingst;
protected BatchNode batchNode;

@Override
public void simpleInitApp() {
    batchNode = new BatchNode("BatchNode");

    cam.setLocation(new Vector3f(-34.403286f, 126.65158f, 434.791f));
    flyCam.setMoveSpeed(100);
    rootNode.attachChild(batchNode);
    Vector3f pos = new Vector3f(-40, 0, -40);
    batchNode.setLocalTranslation(pos);
    FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
    fpp.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects));
    viewPort.addProcessor(fpp);

     batchNode.batch();

     for (int i = 0; i < 600 ; i++) {
        star=createStar(1f, assetManager, 0.9f,0.9f, 0.95f, 0.9f);
        float x=new Random().nextFloat(); float y=new Random().nextFloat();
        star.setLocalTranslation(x*300f,y*300f,0);
        batchNode.attachChild(star);
    }
    //batchNode.batch(); NullPointerException
}

@Override
public void simpleUpdate(float tpf) {
    } 

private Geometry createStar(float thickness, AssetManager assetManager, float r,float g,float b,float a ) {
    Vector3f[] vertices = {new Vector3f(1,1,0),new Vector3f(2,2,0)};
    int[] indices = {0,1};
    
    Mesh PointMesh = new Mesh();
    PointMesh.setMode(Mesh.Mode.Lines);
    PointMesh.setLineWidth(thickness);
    PointMesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
    PointMesh.setBuffer(VertexBuffer.Type.Index, 1, BufferUtils.createIntBuffer(indices));
    PointMesh.updateBound();

    
    Geometry PointGeom = new Geometry("lineMesh", PointMesh);
    Material matWireframe = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    matWireframe.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
    matWireframe.setColor("Color", new ColorRGBA(r,g,b,a));
    PointGeom.setMaterial(matWireframe);
   
    return PointGeom;
}

}

You can’t batch point meshes. But if you’re already using point meshes with your own vertices, why don’t you simply put all vertices in one mesh?

You mean “GeometryBatchFactory”? I want to independently move every mesh. This code as example.

So just change the vertices accordingly when you want to move them. You are already doing the low level work, no need to use GeometryBatchFactory or BatchNode.

Ok

To be as explicit as possible: you have to modify the vertex coordinates within a mesh to simulate multiple meshes. In actuality you have just 1 mesh, but it is dynamic.

Well, I changed the point meshes to standard box meshes.
The number of objects decreased, but FPS remained unchanged. For sure on every
rendering batching is performed, so this poor performance (only 600 objects cannot take much CPU time).

I also tried to use the unpacked meshes instead “optimized” , this is do nothing. But in other scene with extreme count of objects 200 000 I got better performance during batching.

Batching off:

Batching on:

Other scene (batching on):

With:

        Geometry box = new Geometry("Box" + i, new Box(Vector3f.ZERO, 1, 1, 1));
        Geometry box1 = new Geometry ();
        Mesh boxmesh =new Mesh(); 
        boxmesh=box.getMesh();  
        box1.setMesh(boxmesh); 

I try to deal with it later.

Hm… Box worlds are not made out of boxes, I hope you know that.

Sorry, in the second test “box1” had static position. Truly fps the same.
Also, the addition of four materials of boxes take up fps, but have freezing.
Truly on every frame batching is performed, and take of many CPU cycles.

you are renderin 14! million vertices… depending on your hardware this is quite a heavy load.