Failing in setting the position of some physics objects.. bug inside?

hi to all!



I'm doing a shooter game using jme and jme physics…I'm having severial problems with the setting of the position of physics objects like bullets and ammo packages which are generated during the game



the ammo packages problem looks very strange! when an enemy dies, an ammo pack must be created in his position…an ammo pack is just a random coloured box, attached to a dynamic physics node…now it doesen't work properly: the pack is placed in 0,0,0 instead of the character position, and it doesen't looks well coloured!! the very strange thing is that if I toggle wireframe on and again off the pack will be in the correct position and will be well coloured!!



the other problem is on the physics bullet…the bullet is just a sphere geometry created on a dynamic physics node, and a force is given to it to shoot it in the cam direction…

when a bullet is created, it must be placed in the cam position…

now the bullet position isn't ever setted properly, sometimes it's placed on 0,0,0 and not in the correct position…



this is the code for the physicsBullet:


public PhysicsBullet( String id, GraphicalWorld world, Vector3f direction, WeaponType weaponType, Vector3f position ) {
      this.id = id;
      this.world = world;
      this.direction = new Vector3f( direction );
      this.weaponType = weaponType;
      this.bullet = new Node( id );

                // bullet is the main Node parent of the physics dynamic node physicsBullet
      world.getRootNode().attachChild( bullet );
      bullet.setLocalTranslation( position.clone() );

      // Create the bullet Physics
      physicsBullet = world.getPhysicsSpace().createDynamicNode();

                // Create bullet geometry
      bulletGeometry = physicsBullet.createSphere( id + "geometry" );
      bulletGeometry.setLocalScale( 0.3f );

      bullet.attachChild( physicsBullet );
      
      contactDetection();
      
      physicsBullet.addForce( direction.mult( weaponType.getPower() ) );
   }



I hope you can help me...

thanks

Well . . . couple pointers.


  1. No need to ‘setLocalTranslation(position.clone())’  setLocalTranslation does a value copy anyway getLocalTranslation.set(position) will do a value copy for you.  That’ll reduce your object overhead a wee bit.



    (Edited for content . . . see posts below)


  2. No need for two separate nodes for your graphics bullet and your physics bullet.  You could simply do something like this.



      physicsBullet = world.getPhysicsSpace().createDynamicNode();
      physicsBullet.createSphere( id + "geometry" ).setLocalScale( 0.3f );
      world.getRootNode().attachChild( bullet );
      physicsBullet.setLocalTranslation(position);



And that should do what you want it to.

3) Not sure how you're doing the collision detection, but if you're not careful, physics engines can be bad about detecting collisions between fast-moving objects.  

Other than that, I really have no more advice.  Looks like it oughta be working, to me.

What physics implementation are you using?  ODE?  JBullet?

-Falken

hmm no 1) is not true, setLocalTranslation(x) just sets the reference.

only getLocalTranslation.set(x) sets a copy.

So, in a vain effort to salvage some dignity, I went digging through all the physics code and implementations I've been working on over the last months, just to see if SOMEWHERE, SOMETHING had a setLocalTranslation() that didn't set by reference.  Even setAngularVelocity() or setDirectionToClosestCheeseWhiz() so I could say I was confused.



:expressionless:



Evidently . . . not so much.  Just pretty much wrong.



My apologies.  I promise THE REST of my credibility is still intact!  No more leading people astray.  Double-check my references.  No posting after 11:00pm.



-Falken (a.k.a. Mr. Wrongy-Pants)

Falken224 said:

Well . . . couple pointers.

1) No need to 'setLocalTranslation(position.clone())'  setLocalTranslation does a value copy anyway getLocalTranslation.set(position) will do a value copy for you.  That'll reduce your object overhead a wee bit.


the code posted is just the last try...I've already tried this and nothing change...

Falken224 said:

2) No need for two separate nodes for your graphics bullet and your physics bullet.  You could simply do something like this.


      physicsBullet = world.getPhysicsSpace().createDynamicNode();
      physicsBullet.createSphere( id + "geometry" ).setLocalScale( 0.3f );
      world.getRootNode().attachChild( bullet );
      physicsBullet.setLocalTranslation(position);



And that should do what you want it to.


yes, I tried this too...no change...

Falken224 said:

3) Not sure how you're doing the collision detection, but if you're not careful, physics engines can be bad about detecting collisions between fast-moving objects.  

Other than that, I really have no more advice.  Looks like it oughta be working, to me.

What physics implementation are you using?  ODE?  JBullet?


I use ODE and I'm doing the collision detection with a ridefined input action, just like the physics tutorials do....
I know that object very fast doesn't work well, so I already slow down their velocity and now the collision detection works very well...infact I've no problem (yet) with collision detection...I've problems with the position set of this objects...and JUST this object....the others (energy packages, characters, etc) work well

I'll make more tries....and hope in some other advice...

thanks!


This is the physicsBullet class...


public class PhysicsBullet {
   
   /** the bullet's identifier */
   String id;
   
   /** the bullet Node */
   Node bullet;
   
   /** the bullet physicsNode */
   DynamicPhysicsNode physicsBullet;
   
   /** the bullet geometry */
   PhysicsSphere bulletGeometry;
   
   /** an input handler used to detect bullet's collisions */
   InputHandler contactDetect = new InputHandler();
   
   /** the graphical world witch contains the bullet */
   GraphicalWorld world;
   
   /** the direction of the shoot */
   Vector3f direction;
   
   /** the type of the weapon witch shoot the bullet */
   WeaponType weaponType;
   
   /** PhysicsBullet constructor <br>
    *
    * @param id - (String) the identifier of the bullet
    * @param world - (GraphicalWorld) the graphical world witch contains the bullet
    * @param direction - (Vector3d) the direction of the shoot
    * @param weaponType - (WeaponType) the type of the weapon witch shoot the bullet
    * @param position - (Vector3f) the position where to create the bullet
    */
   public PhysicsBullet( String id, GraphicalWorld world, Vector3f direction, WeaponType weaponType, Vector3f position ) {
      this.id = id;
      this.world = world;
      this.direction = new Vector3f( direction );
      this.weaponType = weaponType;
      this.bullet = new Node( id );
      
      physicsBullet = world.getPhysicsSpace().createDynamicNode();
      physicsBullet.getLocalTranslation().set( position );
      physicsBullet.createSphere( id + "geometry" ).setLocalScale( 0.3f );
      
      bullet.attachChild( physicsBullet );
      world.getRootNode().attachChild( bullet );
      
      contactDetection();
      
      physicsBullet.addForce( direction.mult( weaponType.getPower() ) );
   }
   
   /** Function used to detect a contact between the bullet and something
    *  when a contact is detected, the bullet is detached from the rootnode
    */
   void contactDetection() {
        SyntheticButton collisionHandler = physicsBullet.getCollisionEventHandler();
       
        InputAction collisionAction = new InputAction() {
            public void performAction( InputActionEvent evt ) {
               ContactInfo contactInfo = (ContactInfo) evt.getTriggerData();
               
               remove();
              
              /** Control if the bullet hit a character */
              for( String id : world.characters.keySet() ) {
                 if( ( contactInfo.getNode1() == world.characters.get(id).getCharacterBody() ||
                    contactInfo.getNode2() == world.characters.get(id).getCharacterBody() ) ||
                    ( contactInfo.getNode1() == world.characters.get(id).getCharacterFeet() ||
                      contactInfo.getNode2() == world.characters.get(id).getCharacterFeet() ) ){
                    GraphicalWorld.logger.info( id + " e stato colpito da un proiettile");
                    world.getCore().characterShoted( id, weaponType.getDamage() );
                 }
              }
            }
        };
       
        /** the action to do when a collision is detected */
        contactDetect.addAction( collisionAction, collisionHandler, false );
    }
   
   private void remove() {
      physicsBullet.clearDynamics();
//      physicsBullet.detachAllChildren();
      physicsBullet.delete();
      bullet.detachAllChildren();
      world.getRootNode().detachChild( bullet );
      world.bullets.remove( id );
   }
   
   /** ContactDetect update
    * @param time
    */
   public void update( float time ) {
      contactDetect.update(time);
   }
}



and this is the ammoPack class...


public class PhysicsAmmoPackage {
   
   String id;
   
   DynamicPhysicsNode physicsPack;
   
   Box pack;
   
   GraphicalWorld world;
   
   Vector3f position;
   
   InputHandler contactDetect;
   

   PhysicsAmmoPackage( String id, GraphicalWorld world, Vector3f position ) {
      this.id = id;
      this.world = world;
      this.position = new Vector3f( position );
      // this.position.setY( 10 );
      this.contactDetect = new InputHandler();
      createPhysics();
      contactDetector();
   }
   
   public void createPhysics() {
                // create the physics
      physicsPack = world.getPhysicsSpace().createDynamicNode();
      world.getRootNode().attachChild( physicsPack );

                // create a mesh
      pack = new Box( id, new Vector3f(), 1, 1, 1 );
      pack.setRandomColors();
      physicsPack.attachChild( pack );

      physicsPack.generatePhysicsGeometry();
      physicsPack.getLocalTranslation().set( position );
   }
   
   public void contactDetector() {
        SyntheticButton ammoPackCollisionHandler = physicsPack.getCollisionEventHandler();
       
        InputAction collisionAction = new InputAction() {
            public void performAction( InputActionEvent evt ) {
                ContactInfo contactInfo = (ContactInfo) evt.getTriggerData();
               
                // it's for multiplayer...but now we have just 1 player...
                for( String playerId : world.getCore().getPlayersId() ) {
                   if ( contactInfo.getNode1() == world.characters.get(playerId).getCharacterFeet() ||
                       contactInfo.getNode2() == world.characters.get(playerId).getCharacterFeet() ) {
                      
                      if( world.getCore().catchAmmoPack( playerId, id ) )
                         deletePackage();
                   }
                }
            }
        };
       
        contactDetect.addAction( collisionAction, ammoPackCollisionHandler, false );
   }

   public void deletePackage() {
      world.getRootNode().detachChild( physicsPack );
      physicsPack.detachAllChildren();
      physicsPack.delete();
      
      world.ammoPackages.remove( id );
   }

   public void update(float time) {
      contactDetect.update(time);
   }
}



I resolved the bullet problem…



we must not use createSphere() but create a sphere mesh and then generate the physics geometry on it…



it looks very very strange…



this is the correct code:



physicsBullet.setName( "physics" + id );
      physicsBullet = world.getPhysicsSpace().createDynamicNode();
      world.getRootNode().attachChild( physicsBullet );
      physicsBullet.getLocalTranslation().set( position );
      
      Sphere s = new Sphere( id, 10, 10, 0.05f );
      physicsBullet.attachChild( s );
      physicsBullet.generatePhysicsGeometry();
      
      physicsBullet.addForce( direction.mult( weaponType.getPower() ) );
      
      contactDetection();