Geometry Batching in JME3

Are you using last SVN/nightly?

There was a change last week on how the batchNode gather geoms and compare materials.

1 Like

I am using an SVN of Feb 23 or so, shall I update?



is this supposed to get me the right index? cz its not



[java]int index = spatialToColor.getParent().getChildIndex(spatialToColor);[/java]

yes you should update.

What index are you talking about?

your pseudocode works perfectly except that if I am trying to chagne the color of a spatial x another spatial is changing color indicating that the batch geom being changed is not accurate. Here’s my code so u can understand more:



[java] Spatial spatialToColor = myApp.getRootNode().getChild(id);

Geometry geom = (Geometry) spatialToColor;



// int theIndex = Integer.parseInt(id.replaceAll("[\D]", “”));

int index = spatialToColor.getParent().getChildIndex(spatialToColor);

// BatchNode creates Batch geometries resulting of the merge of its sub geometries.

// the geometry batch containing the desired mesh

Geometry g = (Geometry) batch.getChild(“batch-batch”+ index); <<<<<<<<<<<<<<<<<<<<<<<<<



//Geometry g = (Geometry) batch.getChild(“batch-batch”+ index);

System.out.println(">>>>>>" +spatialToColor.getParent().getChildren());



float[] texCoordsFloat = new float[g.getMesh().getVertexCount() * 2];



//this should be brown

float xyTexel = 0.4f; // the xy coord in your atlas texture e.g: (0.4,0.4)

// new design atlas this color will be located at (0.4,0.4)



for(int i=0; i<texCoordsFloat.length; i++) {

//texCoordsFloat[i-1] = xTexel;

texCoordsFloat = xyTexel;



}





//getting the texture coordinate buffer of the batch geom

VertexBuffer buff = g.getMesh().getBuffer(Type.TexCoord);



//getting the FloatBuffer of this vertex buffer

FloatBuffer fb = (FloatBuffer) buff.getData();



//Rewinds this buffer. The position is set to zero

fb.rewind();



// sets the position of the buffer

fb.position(batch.getOffsetIndex(g));



// inserts the new texCoordsFloat

fb.put(texCoordsFloat);



// update buffer

buff.updateData(fb);



// update mesh

g.getMesh().updateBound();

}[/java]

updating past nightly 24th of March makes all my batched objects disappear. Is there a bug or something?



also can anyone tell me please how to get the index of the right batch geom from the main parent batch? why the code above is not working?



Edit:



@nehon correct me if I am wrong: I looked at the code changes after your nightly batchnode update and I think I should keep it batch0 as ur code looks into the materials using isEquals function and sets them together so I should only have one bacth node goem thich is the batch0 correct??



However I noticed that all the batched geometries disappeared from my scene - what am I missing?

mhhh… actually…there is no way to get the index of the batch from a geometry…

I’ll add a convenience method for that. like getBatchGeometry(Geometry geom)



I would need a test case for your issue so i can test it. Also how do you initialize each geometry material?

1 Like

thats great! would I still need to update my code past March 22nd though?



I initialize the geometry material like this: (it’s a loop depending on the number of objects to create)



[java]Material mateo = new Material(myApp.getAssetManager(),“Common/MatDefs/Light/Lighting.j3md”);

mateo.setTexture(“DiffuseMap”, myApp.getAssetManager().loadTexture("/Materials/TextureAtlas/atlasColors.png")); // atlas file







Geometry geom = (Geometry) mySpatial;

//Vector2f[] texCoord = new Vector2f[geom.getMesh().getVertexCount()];



Vector2f[] texCoord = new Vector2f[geom.getMesh().getVertexCount()];



float xTexel = 0f; // the x coord in your atlas texture

float yTexel = 0f; // the y coord in your atlas texture



for(int i=0; i<texCoord.length; i++) {

texCoord = new Vector2f(xTexel, yTexel);

}



geom.getMesh().clearBuffer(Type.TexCoord);

geom.getMesh().setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

geom.getMesh().updateBound();



mySpatial.setMaterial(mateo);

batch.attachChild(geom);



}[/java]

ok you should not recreate your material for each geometry, create it once and then assign it to each geom

oh I see what was happening I was creating all these smaller batches because of that… ok so now I have batch-0 only so I tried two things:



1- your pseudocode with Geometry g = (Geometry) batch.getChild(“batch-batch0”); and that changes the WHOLE batch to the new color



2- your pseudocode with Geometry g = (Geometry) batch.getChild(spatialID); // as in teh batch children I can see the individual geoms so thought i’d give it a shot but that throws an null pointer at fb.position(batch.getOffsetIndex(g)); (I guess they’re invisible)





so even if I wait for your


convenience method for that. like getBatchGeometry(Geometry geom)


that's still gonna change the whole batch isn't it?

No, this convenience method will fetch the correct batch geom from the given geometry but won’t help you since now you got only one batch.



your problem is here

[java]

float[] texCoordsFloat = new float[g.getMesh().getVertexCount() * 2];

[/java]



g is your batch geometry, this line should be

[java]

float[] texCoordsFloat = new float[geom.getMesh().getVertexCount() * 2];

[/java]

geom is the spatial to color.

ah I see , but it colors now only one mesh (not the right one) all the time. Just to make sure we’re on teh same page:



[java] public void changeColorRGBA(ColorRGBA convertedColor, String id) {



Spatial spatialToColor = myApp.getRootNode().getChild(id);

Geometry geom = (Geometry) spatialToColor;



// BatchNode creates a Batch geometry resulting of the merge of its sub geometries.

Geometry g = (Geometry) batch.getChild(“batch-batch0”);

System.out.println(">>>>>>" +spatialToColor.getParent().getChildren());



float[] texCoordsFloat = new float[geom.getMesh().getVertexCount() * 2];



//this should be brown

//float xTexel = 0.1f; // the x coord in your atlas texture

//float yTexel = 0.4f; // the y coord in your atlas texture

float xyTexel = 0.4f; // the xy coord in your atlas texture e.g: (0.4,0.4)

// new design atlas this color will be located at (0.4,0.4)



for(int i=0; i<texCoordsFloat.length; i++) {

//texCoordsFloat[i-1] = xTexel;

texCoordsFloat = xyTexel;



}





//getting the texture coordinate buffer of the batch geom

VertexBuffer buff = g.getMesh().getBuffer(Type.TexCoord);



//getting the FloatBuffer of this vertex buffer

FloatBuffer fb = (FloatBuffer) buff.getData();



//Rewinds this buffer. The position is set to zero

fb.rewind();



// sets the position of the buffer

fb.position(batch.getOffsetIndex(g));



// inserts the new texCoordsFloat

fb.put(texCoordsFloat);



// update buffer

buff.updateData(fb);



// update mesh

g.getMesh().updateBound();[/java]



sorry I am misunderstanding you :S

your id parameter must be the name of the spatial you want to color…if all your spatials have the same name it just takes the first one it founds.

make sure every spatial has a different name…

no they are different:



here are all the children that the batch has:

[java]>>>>>[shelf_1 (Geometry), shelf_2 (Geometry),shelf_3 (Geometry), shelf_4 (Geometry),shelf_5 (Geometry), shelf_6 (Geometry), shelf_7 (Geometry),shelf_8 (Geometry), shelf_9 (Geometry), shelf_10 (Geometry), shelf_11 , batch-batch0 (Geometry)][/java]



and the id passed (from debugger) is : shelf_9



then the second time the id passed is: shelf_11 and still the same shelf would get colored.



edit: a quick test I did was to explicitly change the shelf number of the id to 3 and still shelf_1 gets colored always.

-_-

[java]

fb.position(batch.getOffsetIndex(g));

[/java]



should be

[java]

fb.position(batch.getOffsetIndex(geom));

[/java]

1 Like

Just out of curiosity, how do you know it’s not the right one being colored? Could it be a case of mistaken identity on your part?

@nehon thanks!!!



the issue now >>>> when I explicitly try now with shelf_1 it works, shelf_3 it works etc all uneven shelves work fine. All even ones like shelf_2 weirdly color half of shelf_1 and half of shelf_2 weird huh? I have no idea why this is happening :frowning:



@madjack I’m sure by writing down which one is which on a paper

@homsi said:
I see what's the issue now >>>> when I explicitly try now with shelf_1 it works, shelf_3 it works etc all uneven shelves work fine. All even ones like shelf_2 weirdly color half of shelf_1 and half of shelf_2 weird huh? I have no idea why this is happening :(

are you sure you have the correct texture coordinates?

I got a -1 on both posts :frowning: so let me rephrase them as I agree that my posts were written fast





I create my objects (shelves) using:



[java]

else if (type.equals(shelf)) {

Geometry geom = (Geometry) mySpatial;

float[] texCoord = new float[geom.getMesh().getVertexCount() * 2];

float xyTexel = 0.0f; // this is blue according to the atlas file



for(int i=0; i<texCoord.length; i++) {

//texCoordsFloat[i-1] = xTexel;

texCoord = xyTexel;



material.setTexture(“DiffuseMap”, myApp.getAssetManager().loadTexture("/Materials/TextureAtlas/atlasColors.png"));





geom.getMesh().clearBuffer(Type.TexCoord);

geom.getMesh().setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

geom.getMesh().updateBound();

mySpatial.setMaterial(material);

batch.attachChild(geom);



[/java]



and when I want to change colors I use the following:





[java]public void changeColorRGBA(ColorRGBA convertedColor, String id) {



id = “Keep_pod_2”;

Spatial spatialToColor = myApp.getRootNode().getChild(id);

Geometry geom = (Geometry) spatialToColor;

System.out.println(">>>>>> spatial to color: " +id);





// BatchNode creates a Batch geometry resulting of the merge of its sub geometries.

Geometry g = (Geometry) batch.getChild(“batch-batch0”);

// this will be replaced with the appropriate batch id taken

// from the geom whenever jME update the helper method to get

// geom batch from a geometry. Now there’s only one batch geom

// but for optimal usage of batch nodes there will be multiple.



System.out.println(">>>>>>" +spatialToColor.getParent().getChildren());



float[] texCoordsFloat = new float[geom.getMesh().getVertexCount() * 2];



float xyTexel = 0.9f; // this should color it to green



for(int i=0; i<texCoordsFloat.length; i++) {

texCoordsFloat = xyTexel;



}





//getting the texture coordinate buffer of the batch geom

VertexBuffer buff = g.getMesh().getBuffer(Type.TexCoord);



//getting the FloatBuffer of this vertex buffer

FloatBuffer fb = (FloatBuffer) buff.getData();



//Rewinds this buffer. The position is set to zero

fb.rewind();



// sets the position of the buffer

fb.position(batch.getOffsetIndex(geom));



// inserts the new texCoordsFloat

fb.put(texCoordsFloat);



// update buffer

buff.updateData(fb);



// update mesh

g.getMesh().updateBound();



}[/java]







so what I was saying is I am sure I have the correct texture coordinates as I am setting all the textCoord float[] to the same number so even if I haven’t set it correctly why would the other shelf get affected?

1 Like

ohh yeah, i know what’s wrong



the offset index has to be multiplied by 2 since the buffer has 2 components.

[java]

// sets the position of the buffer

fb.position(batch.getOffsetIndex(geom));

[/java]



should be

[java]

// sets the position of the buffer

fb.position(batch.getOffsetIndex(geom) * 2);

[/java]



Edit : Also…out of curiosity…i didn’t follow all the posts about this (seems there are plenty…) so maybe there is a reason, but it seems you are just using one texel of the texture, so really your objects will just have a plain color. So why bother using a texture atlas when you just have to use the vertex color buffer?

1 Like
@nehon said:
So why bother using a texture atlas when you just have to use the vertex color buffer?


I thought that Lighting.j3md didn't support vertex colors.