Does anyone know if you can apply different textures to individual instances of a Geometry instance?
Applying textures to the individual objects whose batches become the new geometry batch instances does not work. I could only find a way to apply the same texture to all instances by applying it to the parent node or to the mesh.
Ummm, have you tried using Spatials and texturing them and then adding them to a node?
Spatial sphere1 = new Sphere( "sphere1", 12, 12, 1 );
Spatial sphere2 = new Sphere( "sphere2", 12, 12, 1 );
sphere2.setLocalTranslation( new Vector3f( 1, 0, 0 ) );
Texture texture1 = new Texture();
texture1.setImage( TextureManager.loadImage( java.awt.Image, [true|false] );
Texture texture2 = new Texture();
texture12setImage( TextureManager.loadImage( java.awt.Image, [true|false] );
TextureState textureState1 = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
textureState1.setTexture( texture1 );
TextureState textureState2 = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
textureState2.setTexture( texture2 );
sphere1.setRenderState( textureState1 );
sphere2.setRenderState( textureState2 );
Node bothSpheres = new Node( "BothSpheres" );
bothSphere.attachChild( sphere1 );
bothSphere.attachChild( sphere2 );
Thats working for me.
I don't mean normal instances of spatials. I mean geometry instances such as those created in TestGeometryInstancing.
Ummm, that class is just using a box (which is a spatial) and basically duplicating it (including all index and texture buffers), in essence it IS creating a LOT of EXACT clones. Therefore they are all using the same texture coordinates and the SAME texture. You would probably need multiple geometryInstances
Thanks for the advise. I am using this for a tile based game and so I created geometryBatchCreators for each type of tile and it works fine.
Glad I could help
About 1 out of every 10 times I run my program with this new code it crashes and gives:
ar 6, 2008 6:30:58 PM com.jmex.game.DefaultUncaughtExceptionHandler uncaughtException
SEVERE: Main game loop broken by uncaught exception
java.lang.NullPointerException
at com.jme.renderer.lwjgl.LWJGLRenderer.draw(Unknown Source)
at com.jme.scene.batch.TriangleBatch.draw(Unknown Source)
at com.jme.scene.TriMesh.draw(Unknown Source)
at com.jme.scene.Spatial.onDraw(Unknown Source)
at com.jme.scene.Node.draw(Unknown Source)
at com.jme.scene.Spatial.onDraw(Unknown Source)
at com.jme.scene.Node.draw(Unknown Source)
at com.jme.scene.Spatial.onDraw(Unknown Source)
at com.jme.renderer.lwjgl.LWJGLRenderer.draw(Unknown Source)
at com.jmex.game.state.BasicGameState.render(Unknown Source)
at com.jmex.game.state.GameStateNode.render(Unknown Source)
at com.jmex.game.StandardGame.render(Unknown Source)
at com.jmex.game.StandardGame.run(Unknown Source)
at java.lang.Thread.run(Thread.java:619)
This creates a new mesh and adds it to a node for each different type of tile I have.
private void createIsland(int[][] map)
{
GeometryBatchCreator geometryBatchCreator;/** The batch creator */
TriMesh mesh;/** The mesh containing the created batch */
FloatBuffer texCoords = BufferUtils.createVector2Buffer( 4 );
texCoords.put(getUForPixel(texCordX1, texWidth)).put(getVForPixel(texCordY1, texHeight));
texCoords.put(getUForPixel(texCordX1, texWidth)).put(getVForPixel(texCordY2, texHeight));
texCoords.put(getUForPixel(texCordX2, texWidth)).put(getVForPixel(texCordY2, texHeight));
texCoords.put(getUForPixel(texCordX2, texWidth)).put(getVForPixel(texCordY1, texHeight));
// A box that will be instantiated
Quad quad = new Quad( "Box", 64, 64 );
quad.setTextureBuffer( 0, texCoords );
for (int x = 0; x < states.getTextureStates().length; x++)
{
// The batch geometry creator
geometryBatchCreator = new GeometryBatchCreator();
for (int i = 0; i < map.length; i++)
{
for (int j = 0; j < map[i].length; j++)
{
if ( map[i][j] == x )
{
// Box instance attributes
GeometryBatchInstanceAttributes attributes = new GeometryBatchInstanceAttributes(
new Vector3f( 64 * j , 0, 64 * i ), // Translation
new Vector3f( 1.0f, 1.0f, 1.0f ), // Scale
new Vector3f( -FastMath.PI/2, 0.0f, 0.0f ), // Rotation
new ColorRGBA( 1.0f, 1.0f, 1.0f, 0.0f ) ); // Color
// Box instance (batch and attributes)
GeometryBatchInstance instance = new GeometryBatchInstance( quad.getBatch( 0 ), attributes );
// Add the instance
geometryBatchCreator.addInstance( instance );
}
}
}
if (geometryBatchCreator.getInstances().size() != 0)
{
// Create a TriMesh
mesh = new TriMesh();
mesh.setRenderState( states.getTextureStates()[x] );
mesh.updateRenderState();
TriangleBatch batch = mesh.getBatch( 0 );
batch.setModelBound( new BoundingBox() );
// Create the batch's buffers
batch.setIndexBuffer( BufferUtils.createIntBuffer( geometryBatchCreator.getNumIndices() ) );
batch.setVertexBuffer( BufferUtils.createVector3Buffer( geometryBatchCreator.getNumVertices() ) );
batch.setNormalBuffer( BufferUtils.createVector3Buffer( geometryBatchCreator.getNumVertices() ) );
batch.setTextureBuffer( BufferUtils.createVector2Buffer( geometryBatchCreator.getNumVertices() ), 0 );
batch.setColorBuffer( BufferUtils.createFloatBuffer( geometryBatchCreator.getNumVertices() * 4 ) );
// Commit the instances to the mesh batch
geometryBatchCreator.commit( batch );
batch.updateModelBound();
// Return the mesh
attachChild( mesh );
}
}
}
Well, its a null-pointer during the render loop.
So it could be one of a 1000 things, however you do have THIS piece of information. You could try wrapping possible problem areas with a try-catch and print results when an exception occurred. Also, if you are doing something like looking for a node name make sure ALL nodes have names (or at least an empty string).
Spatial spatial = new Spatial();
Legal but creates a spatial with it's name equal to null.
Names should not be the issue (they are ok to be null). Build jME with debug info (line numbers) and run your program again. After that you can check what's really causing that NPE.
private void setCallBacks() {
ContactCallback callBack = new ContactCallback() {
String [] nodeNames = new String[2];
public boolean adjustContact( PendingContact c ) {
nodeNames[0] = c.getNode1().getName();
nodeNames[1] = c.getNode2().getName();
c.setIgnored( false );
return false;
}
};
physicsSpace.getContactCallbacks().add( callBack );
}
That will throw an null pointer exception if one of the nodes has been created without setting the name ;)
Build jME with debug info
How is this done??
QFT:
basixs said:
private void setCallBacks() {
ContactCallback callBack = new ContactCallback() {
String [] nodeNames = new String[2];
public boolean adjustContact( PendingContact c ) {
nodeNames[0] = c.getNode1().getName();
nodeNames[1] = c.getNode2().getName();
c.setIgnored( false );
return false;
}
};
physicsSpace.getContactCallbacks().add( callBack );
}
Enlighten me. I'm missing where the NPE would happen in that code? nodeNames would have a null entry, but I don't see where it would have a npe.
hehe, renanse beat me to it (even with explanation), but still:
basixs said:
That will throw an null pointer exception if one of the nodes has been created without setting the name ;)
No, it will not. But of course you could write a piece of code which throws NPEs if there are no names. What I was trying to say: no code in jME (or jME Physics) should rely on the names to be set (and only little parts to). At least LWJGLRenderer.draw (where the posted NPE arises) does not even touch the name.
basixs said:
Build jME with debug info
How is this done??
erm, that really depends on your IDE and you really should do it with all your classes - give the IDE/compiler doc a shot.
:-o 2 Admin posts in a minute, guess I said something wrong. What I was trying to say is that its possible to have logic errors and to cause problems in jME that will cause weird errors like this. Didn't mean to offend anyone…
private void setCallBacks() {
ContactCallback callBack = new ContactCallback() {
public boolean adjustContact( PendingContact c ) {
if ( c.getNode1().getName() == "test" || c.getNode2().getName() == "test" ) {
}
c.setIgnored( false );
return false;
}
};
physicsSpace.getContactCallbacks().add( callBack );
}
There, thats closer to what is in the examples anyway :P
Build jME with debug info
OOHHH, you just mean debugg, gotcha
No need to worry. I don't think anyone gets offended that easily.
if ( c.getNode1().getName() == "test" || c.getNode2().getName() == "test" ) {
That still wouldn't cause an NPE (and is bad string comparison anyhow.) If you did "test".equals(c.getNode1().getName()) it would be correct string comparison and avoid null issues.
But yeah, you do have to be aware that names can be null.
Yup, thats how I do string comparisons also.
However, I believe thats how some of the physics examples do it.