Hello all,
I just started playing with jME and Physics 2 so chances are Im doing something fundamentally wrong. I took the Lesson 3 which had 4 cubes of different materials and enclosed them into a crude area so I could watch them bounce around more. I also added a rubber sphere as well. When the sphere hits the red block from Lesson 3 I get a NPE comming out of Material.
[java] java.lang.NullPointerException
[java] at com.jmex.physics.material.Material.getContactHandlingDetails(Material.java:318)
[java] at com.jmex.physics.material.MaterialContactCallback.adjustContact(MaterialContactCa
llback.java:67)
[java] at com.jmex.physics.PhysicsSpace.adjustContact(PhysicsSpace.java:125)
[java] at com.jmex.physics.impl.ode.OdePhysicsSpace.iterateContacts(OdePhysicsSpace.java:82
9)
[java] at com.jmex.physics.impl.ode.OdePhysicsSpace.computeTimeStep(OdePhysicsSpace.java:75
6)
[java] at com.jmex.physics.impl.ode.OdePhysicsSpace.update(OdePhysicsSpace.java:589)
[java] at com.jmex.physics.util.SimplePhysicsGame.update(SimplePhysicsGame.java:141)
[java] at com.jme.app.BaseGame.start(Unknown Source)
The code is as follows:
package client;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.MaterialState;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.contact.MutableContactInfo;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;
/**
* Learn about physics materials, friction, bounciness etc.
*
* @author Irrisor
*/
public class FrontEndGui extends SimplePhysicsGame {
protected void simpleInitGame() {
//root static object node
StaticPhysicsNode staticNode = getPhysicsSpace().createStaticNode();
rootNode.attachChild( staticNode );
// first we will create the floor
final Box visualFloorBox = new Box( "floor", new Vector3f(), 5, 0.25f, 10 );
//tilt it a bit
visualFloorBox.getLocalRotation().fromAngleNormalAxis( 0.3f, new Vector3f( 0, 0, -1 ) );
staticNode.attachChild( visualFloorBox );
// and create another part below
final Box visualFloorBox2 = new Box( "floor", new Vector3f(), 5, 0.25f, 10 );
visualFloorBox2.getLocalTranslation().set( 9.7f, -1.5f, 0 );
staticNode.attachChild( visualFloorBox2 );
//another part
final Box visualFloorBox3 = new Box("floor", new Vector3f(),5,0.25f,10);
visualFloorBox3.getLocalRotation().fromAngleNormalAxis(0.3f,new Vector3f(0,0,1));
visualFloorBox3.getLocalTranslation().set( 19.4f, 0, 0 );
staticNode.attachChild( visualFloorBox3 );
//wall 1
final Box visualWall1 = new Box("wall", new Vector3f(),15f,6,0.25f);
visualWall1.getLocalTranslation().set(10f,0,-10);
staticNode.attachChild(visualWall1);
//wall 2
final Box visualWall2 = new Box("wall", new Vector3f(),15f,6,0.25f);
visualWall2.getLocalTranslation().set(10f,0,10);
staticNode.attachChild(visualWall2);
//wall 3
final Box visualWall3 = new Box("wall", new Vector3f(),0.25f,2.5f,10);
visualWall3.getLocalTranslation().set(-5f,3,0);
staticNode.attachChild(visualWall3);
//wall 4
final Box visualWall4 = new Box("wall", new Vector3f(),0.25f,2.5f,10);
visualWall4.getLocalTranslation().set(24f,3,0);
staticNode.attachChild(visualWall4);
//create the physics for the current static node
staticNode.generatePhysicsGeometry();
cam.setLocation(new Vector3f(0,10,10));
cam.lookAt(new Vector3f(10,0,0),new Vector3f(0,1,0));
// second we create a box - as we create multiple boxes this time the code moved into a separate method
DynamicPhysicsNode dynamicNode = createBox();
dynamicNode.computeMass();
// the first box gets in the center above the floor
dynamicNode.getLocalTranslation().set( 0, 5, 0 );
// this box keeps the default material
// ok first we will explore some predefined materials
// lets create an ice block...
final DynamicPhysicsNode iceQube = createBox();
iceQube.setMaterial( Material.ICE );
// changing material means changing desity
// you may choose to compute the mass from the volume and density of an object
iceQube.computeMass();
// color the visual representation in transparent blue
color( iceQube, new ColorRGBA( 0.5f, 0.5f, 0.9f, 0.6f ) );
// move the iceQube besides the first box
iceQube.getLocalTranslation().set( 0, 5, 1.5f );
// ... a rubber ...
final DynamicPhysicsNode rubber = createBox();
rubber.setMaterial( Material.RUBBER );
rubber.computeMass();
// color the visual representation in yellow
color( rubber, new ColorRGBA( 0.9f, 0.9f, 0.3f, 1 ) );
// move the rubber on the other side of the first box
rubber.getLocalTranslation().set( 0, 5, -1.5f );
// finally we define a custom material
final Material customMaterial = new Material( "supra-stopper" );
// we make it really light
customMaterial.setDensity( 0.05f );
// a material should define contact detail pairs for each other material it could collide with in the scene
// do that just for the floor material - the DEFAULT material
MutableContactInfo contactDetails = new MutableContactInfo();
// our material should not bounce on DEFAULT
contactDetails.setBounce( 0 );
// and should never slide on DEFAULT
contactDetails.setMu( 1000 ); // todo: Float.POSITIVE_INFINITY seems to cause issues on Linux (only o_O)
// now set that behaviour
customMaterial.putContactHandlingDetails( Material.DEFAULT, contactDetails );
// ... finally test our supra-stopper with a red cube
final DynamicPhysicsNode stopper = createBox();
stopper.setMaterial( customMaterial );
// don't forget to compute mass from density
stopper.computeMass();
// color the visual representation in yellow
color( stopper, new ColorRGBA( 1, 0, 0, 1 ) );
// move the stopper to the front
stopper.getLocalTranslation().set( 0, 5, 3 );
DynamicPhysicsNode ball1 = createBall();
ball1.getLocalTranslation().set(20,10,1);
ball1.setMaterial(Material.RUBBER);
ball1.computeMass();
color(ball1,new ColorRGBA( 0.9f, 0.9f, 0.3f, 0.6f ));
// start paused - press P to start the action :)
pause = true;
}
/**
* Little helper method to color a spatial.
*
* @param spatial the spatial to be colored
* @param color desired color
*/
private void color( Spatial spatial, ColorRGBA color ) {
final MaterialState materialState = display.getRenderer().createMaterialState();
materialState.setDiffuse( color );
if ( color.a < 1 ) {
final AlphaState alphaState = display.getRenderer().createAlphaState();
alphaState.setEnabled( true );
alphaState.setBlendEnabled( true );
alphaState.setSrcFunction( AlphaState.SB_SRC_ALPHA );
alphaState.setDstFunction( AlphaState.DB_ONE_MINUS_SRC_ALPHA );
spatial.setRenderState( alphaState );
spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
}
spatial.setRenderState( materialState );
}
/**
* Create a box like known from Lesson2.
*
* @return a physics node containing a box
*/
private DynamicPhysicsNode createBox() {
DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
rootNode.attachChild( dynamicNode );
final Box visualFallingBox = new Box( "falling box", new Vector3f(), 0.5f, 0.5f, 0.5f );
dynamicNode.attachChild( visualFallingBox );
dynamicNode.generatePhysicsGeometry();
return dynamicNode;
}
private DynamicPhysicsNode createBall() {
DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
rootNode.attachChild( dynamicNode );
final Sphere visualFallingSphere = new Sphere( "falling sphere", 10, 10, 1.0f);
dynamicNode.attachChild( visualFallingSphere );
dynamicNode.generatePhysicsGeometry();
return dynamicNode;
}
/**
* The main method to allow starting this class as application.
*
* @param args command line arguments
*/
public static void main( String[] args ) {
Logger.getLogger( "" ).setLevel( Level.WARNING ); // to see the important stuff
new FrontEndGui().start();
}
}
Any help would be appreciated. I was looking in the Material class and the error is here:
if ( details == null && contactMaterial != null ) {
// use default contact details
details = contactDetails.get( null );
if ( details.isIgnored() || // <---### error line, did the above line not work?
!details.isApplied() ) {
return details;
}