Trouble using BatchNode

@pspeed said:
By definition, a batch = 1 geometry. 1 geometry = 1 material

ergo: changing the material parameter changes it for the whole mesh.

Actually the BatchNode automatically creates multiple geometries from multiple materials.
@homsi: The same way, you have to know what vertices there are.
@homsi said:
and thats exactly my question how do I do that?

for quad I simply do something like
[java] Vector2f[] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0, 0);
texCoord[1] = new Vector2f(0.1f,0);
texCoord[2] = new Vector2f(0,.1f);
texCoord[3] = new Vector2f(.1f,.1f);[/java]


You don't really need to get that complicated. You could use the same x for every texture coordinate and the same y since you aren't using real texture. Stretching one texel over the whole face is not a problem.

Find the geometry you want to change. Reset its texture buffer.

If you already tested RESETTING (note: not just setting the first time but changing it later) the texture buffer on a simple cube then it is exactly the same... or should be.
@pspeed said:

Find the geometry you want to change. Reset its texture buffer.

If you already tested RESETTING (note: not just setting the first time but changing it later) the texture buffer on a simple cube then it is exactly the same… or should be.


so I reset it:
[java] geom.getMesh().clearBuffer(Type.TexCoord);[/java]

then I want to re-set it to the blue part, how do I do that ??? thats the question :S i am sorry if i'm slow..

this will trigger an illegalArgumentException as my obj has more vertices than 4:
[java]geom.getMesh().setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(new float[]{0,0, 0,0.5f, 0.5f,0.5f, 0.5f,0}));[/java]

edit:
in fact my object has 80 vertices so even if I do that:
[java]
for(int i = 0; i < 80; i++)
{
texCoord = new Vector2f(0, 0);
}
Geometry geom = (Geometry) mySpatial;
geom.getMesh().clearBuffer(Type.TexCoord);
geom.getMesh().setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
[/java]

I still get the same error. of course I would not want to do that as I have different types of shelves with diff amount of vertices

This may be too hard for you, but…



Get the existing buffer. Change all of its values.

okay so I did this:



[java]

Geometry geom = (Geometry) mySpatial;

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

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

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

geom.getMesh().updateBound();

[/java]



and this point to the tecture located at the bottom left - great- it all works fine and batches correctly.



now the question is how would I choose/map to another texture? It looks like I have 240 vertices in my object :S

Now, I haven’t really worked at this level much, but as that worked, perhaps like this?

[java]Geometry geom = (Geometry) mySpatial;

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

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

float yTexel = 150f; // 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();[/java]

Just a quick guess, I really haven’t tried this, it just seemed logical. :slight_smile:

1 Like

:facepalm: As he said, set all 240 vertices to the same coordinate… the things you don’t immediately get in the answers is not some background noise. After you have understood one thing, read the other answers again.

This may be too hard for you, but…



Get the existing buffer. Change all of its values.



The x,y you will use will be the center texture coordinate of the color you want.



What is this for? Is it for school or for you job?

@tumaini your code makes perfect sense. I had a bg confusion in textures buffers and now I got it figure out however why would the follwoing code not work to change the color of a batched geom after the batch?



[java] public void changeColor( String id) {



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

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

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

Geometry geom = (Geometry) spatialToColor;

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

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

float yTexel = 100f; // 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();



}[/java]



I cant set the material on the geom as I’ll get:

Cannot set the material of a batched geometry, change the material of the parent BatchNode.



and changing the TexCoords on the geom itself without setting the material keeps the color the same

@homsi said:
and changing the TexCoords on the geom itself without setting the material keeps the color the same


Material has nothing to do with texture coordinates... so you are doing something else wrong.

Show us a simple test case with a JME Box and we will show you what you are doing wrong.

I believe that the actual batched geometries aren’t shown (CullHint.Always), but are still kept so you can manipulate them.

The shown mesh is the one (if you have one material) that is the result of combining the meshes of the batched geometries (it’s a separate mesh). Perhaps a change to the TexCoord buffer for the original meshes won’t be automatically reflected in the batch mesh?

You might try detaching the geometry, changing the TexCoord buffer, then reattaching and batching again, to see if there is any difference, but as pspeed notes, a test case would make it clearer what might be wrong.

testCase… one of the boxes must change colors from blue to brown and ir doesnt.



[java]package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.scene.BatchNode;

import com.jme3.scene.Geometry;

import com.jme3.scene.Spatial;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.scene.shape.Box;

import com.jme3.util.BufferUtils;



public class TestTextureAtlas extends SimpleApplication

{

BatchNode batch;

static Material mat;

static Box box = new Box(new Vector3f(0,0,0),.5f,.5f,.5f);



public static void main(String[] args)

{

TestTextureAtlas app = new TestTextureAtlas();

app.start();

}





public void simpleInitApp()

{

flyCam.setMoveSpeed(30);

batch = new BatchNode("batch");



//mat = new Material(assetManager ,"Common/MatDefs/Light/Lighting.j3md");

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

mat.setTexture("ColorMap", assetManager.loadTexture("Models/atlasColors.png"));



for (int i=0;i<5;i++)

{

for (int j=0;j<5;j++)

{

//rootNode.attachChild(createGeom(i,0,j));

createGeom(i,0,j);

}

}



batcher(); // batch nodes into one



changeColor();

}



private void createGeom(int i, int k, int j)

{



Geometry geom = new Geometry("Box", box);

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



// this should be blue

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

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



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

texCoord[ix] = new Vector2f(xTexel, yTexel);

}



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

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

geom.getMesh().updateBound();

geom.setMaterial(mat);



geom.setLocalTranslation(new Vector3f(i,k,j));



batch.attachChild(geom);







}



private void batcher() {



batch.batch();

rootNode.attachChild(batch);

}



private void changeColor() {

// change the color of one of the batched blue spatials to brown

Spatial spatialToMove = batch.getChild(0);

Geometry geo = (Geometry) spatialToMove;





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

// this should be brown

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

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



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

texCoord = new Vector2f(xTexel, yTexel);

}



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

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

geo.getMesh().updateBound();



}

}[/java]



You will need the atlas file: http://i.imgur.com/8A3no.png

@tumaini detaching and reattaching from BatchNode defies the purpose for me using a Texture Atlas file. I did that specifically not to deatach and attach.

No it doesn’t, as I said, if you map the textures beforehand you can add them to the batch with the same material. So in blender, create multiple boxes. Then set the texture coordinates of each box to point at different locations in the map. When you then load such a box (or any other model created this way) and add it to a batch with the others it will batch with them when you set the same material.

but thats what I did in the example above and the color did not change when I called changeColor()

Texture coordinates are 0 - 1.0



50 = 0 = 1 = 2 = 5 = 10



So it’s logical that your color didn’t change, I guess.

…background noise…

@pspeed not reallly b/c if I set this at the beginning before batching I get brown

[java] // this should be brown

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

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



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

texCoord[ix] = new Vector2f(xTexel, yTexel);

}[/java]





@normen did you look at my code? it did what ur saying. didnt it?

Nope, you changed the mesh of the geometry (which isn’t used when the geometry is in the batch), you didn’t add anything to the batch. Sorry, I’ll stop answering now, you’re in way over your head and this is becoming a fulltime teachers job.

I was wrong on one point. 0 is not the same as 1. But 50 is the same as 1. As is 2, 3, 4, 5, 6, 7, 8, 9, 10, etc.



Texture coordinates are from 0-1 unless you want repeating patterns… but if you have a texture that is 512 pixels wide then pixel 0 is texture coordinate 0, pixel 512 is texture coordinate 1, pixel 256 is texture coordinate 0.5 and so on.



So while this may not be why your color doesn’t change it will mess you up later, for sure.