[committed] More JBullet code changes

Okay guys, here's another set of changes for the JBullet integration.  Feel free to ping me with critiques.  If I haven't heard from anybody by the weekend, I'll go ahead and commit.



It's a long-ish one, so here goes.



Fixes include:

-Better null-checking in collisions and PendingContact classes

-PhysicsSpace.collide() method implemented

-PhysicsSpace.pick() method implementd

-PhysicsPicker implemented

-ContactCallbacks cleaned up a bit.

-PhysicsCallbacks wired up

-Fixed (as in 0 axis) Joints implemented

-CollisionGroup handling fixed.  (had a wacky bit o' logic in the last checkin)

-Attempted to fix 'applyForce' and 'applyTorque' methods, but with only sporadic success.

-Fixed some more bugs with mass calculations that caused JBullet to interpret dynamic nodes as static.

-Added 'worldBounds' and 'maxObject' properties to PhysicsSpace to allow for more optimization

-Added optimization code to auto-switch to better broadphase sweeping algorithms when world bounds are specified.

-Added better null-checking in com.jmex.physics.material.MaterialContactCallback. (get material from node when geometries aren't available.)



Code changes:



com.jmex.physics.PhysicsSpace:

added the following code:


    private Vector3f worldMinBounds = new Vector3f(Float.MIN_VALUE,Float.MIN_VALUE,Float.MIN_VALUE);
    private Vector3f worldMaxBounds = new Vector3f(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE);
    
    /**
     * Change the declared boundaries of the physics world.  This value is used for optimization only and
     * will not actually limit the placement of objects.  However, tuning world boundaries MAY for some
     * implementations result in a performance improvement.  Default values at start are Float.MIN_VALUE and
     * Float.MAX_VALUE respectively for all axes.
     *
     * @param min The minimum boundary of the physics space.
     * @param max The maximum boundary of the physics space.
     */
    public void setWorldBounds(Vector3f min, Vector3f max)
    {
       if(min!=null)
          worldMinBounds.set(min);
       if(max!=null)
          worldMaxBounds.set(max);
    }
    
    public Vector3f getWorldMinBound(Vector3f store)
    {
       if(store==null)
          store = new Vector3f();
       store.set(worldMinBounds);
       return store;
    }
    
    public Vector3f getWorldMaxBound(Vector3f store)
    {
       if(store==null)
          store = new Vector3f();
       store.set(worldMaxBounds);
       return store;
    }
    
    private int maxObjects = 10000; //This default can change, if need be.  Seems like a decent start tho.
    
    public int getMaxObjects() {
      return maxObjects;
   }

    /**
     * sets the maximum number of physics objects (i.e. physics nodes) in the world.  This number MAY
     * be a hard limit depending on the implementation, but can be invaluable for tuning and performance
     * improvement purposes.
     *
     * @return
     */
   public void setMaxObjects(int maxObjects) {
      this.maxObjects = maxObjects;
   }



com.jmex.physics.material.MaterialContactCallback:
changed lines 65 and 66 to:


        Material m1 = (contact.getGeometry1()!=null)?contact.getGeometry1().getMaterial():contact.getNode1().getMaterial();
        Material m2 = (contact.getGeometry2()!=null)?contact.getGeometry2().getMaterial():contact.getNode2().getMaterial();



com.jmex.physics.impl.jbullet.callback.JBulletPendingContactCache:
changed lines 18 and 19 to:


      ShapeProxy sp1=(ShapeProxy)obj1.getLastTempProxyCollisionShape();
      ShapeProxy sp2=(ShapeProxy)obj2.getLastTempProxyCollisionShape();
      ContactSet cs1 = new ContactSet((sp1==null)?null:sp1.getJmeShape(),obj1.getParentNode());
      ContactSet cs2 = new ContactSet((sp2==null)?null:sp2.getJmeShape(),obj2.getParentNode());



com.jmex.physics.impl.jbullet.JBulletCollisionGroup:
inserted at line 11:


        this.collidesWith(this, true);



com.jmex.physics.impl.jbullet.JBulletPhysicsNode,
com.jmex.physics.impl.jbullet.JBulletStaticPhysicsNode:
changed 'getBody()' method to return JBulletRigidBody

com.jmex.physics.impl.jbullet.JBulletRigidBody:
changed 'checkCollideWithOverride()' method to the following:


   public boolean checkCollideWith(CollisionObject co) {
      if(co instanceof JBulletRigidBody)
      {
         CollisionGroup cg1 = ((PhysicsNode)getParentNode()).getCollisionGroup();
         CollisionGroup cg2 = ((PhysicsNode)((JBulletRigidBody)co).getParentNode()).getCollisionGroup();
         if(cg1.getCollidesWith().contains(cg2) || cg2.getCollidesWith().contains(cg1))
            return super.checkCollideWith(co);
         return false;
      }
      return super.checkCollideWith(co);
   }


also, added the following method:


   @Override
   public void setGravity(Vector3f acceleration) {
      if(((JBulletDynamicPhysicsNode)getParentNode()).isAffectedByGravity())
         super.setGravity(acceleration);
   }



Remaining changes are too large to paste, and have been included as attached files.  No lib changes or anything else too wacky.  Let me know if you see problems.

-Falken

So . . . with that done . . . a quick "caveat emptor" here.



JBullet is NOT a complete library, as I started to really find out this week.  There are some notable features missing that are going to make this integration either tricky, or impossible to complete:


  1. JBullet has NOT implemented all of Bullet Physics' joint motor functionality.  Consequently, a lot of the spring, damping and force application you're used to with ODE will NOT be available in JBullet joints until the author ports them over.


  2. Bullet Physics' Hinge2 joint is noticeably absent, making the 2xrotational axis joints a bit difficult to do correctly.  ESPECIALLY with no joint motors available.


  3. JBullet doesn't seem to have a way to ignore collisions once they're been detected.  This means the PendingContact.ignore property will NEVER work correctly unless JBullet undergoes a rather significant architectural change.


  4. The materials handling is different enough in JBullet that many material properties available in JMEPhysics (most notably slip and surfacemotion) will be difficult to implement in JBullet.



    So . . . that's the short list.  I'm still digging through the Bullet Physics docs to see if we might be able to expect these features at some point in the future from JBullet, but I'm not holding my breath, as the author seems to have slowed his development pace down a wee bit.



    Let me know if you all out there have suggestions or workarounds for any of these issues.  I'd welcome any help or thoughts and look forward to getting this binding refined enough to use . . . even if it's missing some key features.



    So, for now, I'm back to work.  Hope you all enjoy!



    -Falken

Nice! Do you think the problem might be that jME-physics was made to work under ODE only? Maybe when a generic physics layer is created, it should be designed with several existing implementations in mind, so only the subset of all features supported by all physics implementations is supported.

You'll see that JBullet actually has several features that work a little bit differently than ODE/jME-physics, but for the same purpose. For example, JBullet has kinetic bodies which apply force to other objects but don't receive force. It also has support for collision layers, and a broadphase way to choose to ignore a collision, as a narrowphase way would be much slower (think object vs. object instead of contact vs. contact).

heya Momoko,



You might be right.  For the most part, I haven't had a TON of trouble translating the physics concepts from our API into the implementation specific concepts.  Mostly, it's just different words or design for the same concepts.



And actually, even the differences you mentioned haven't been a huge problem.  I still have the ability to apply the collision groups during the broadphase part of collision detection.  It's actually really nice, 'cause it does save time.



The problem comes with trying to ignore collisions AFTER contact.  e.g. an object hitting water . . . you might want to slow its velocity, apply some friction, make a splash, detect the collision, but not actually have the physics engine do anything about it.  I'm not sure I'm seeing how to do that with JBullet.



As for the kinetic bodies, I'm still trying to figure out what to do with those.  :)  the physics picker we've built works pretty good for moving things around, but yeah . . . I think we may be missing an opportunity with that feature.



And there's other oddities.  I can detect which SHAPES collided, (via an evil, but INGENIOUS hack :))but on meshes, JBullet treats the individual triangle as the "shape".  I have no way to know which "PhysicsCollisionGeometry" that triangle belongs to.  The good news is that only happens with 'TriMesh' objects, so for the most part our collision events will stay intact.



And like I said . . . a lot of it's just details.  I wish we had slip and surface motion, but we may be able to cobble together a hacky little implementation for it that works.  It's just irritating is all.



And actually, I think optimization is where it's at at this point.  bugfixes and optimization.  :slight_smile:



Sounds like fun.



-Falken

After a full weekend with no objections, committed to the jbullet-integration branch.



-Falken

Hi Falken224.  I got the following error when compiling jME Physics 2 (219):



Description Resource Path Location Type

The method applyForces(float) in the type JBulletDynamicPhysicsNode is not applicable for the arguments () JBulletPhysicsSpace.java /jME Physics 2/impl/jbullet/src/com/jmex/physics/impl/jbullet line 565 Java Problem

Hmm . . . very odd.  A wee bit of subversion wackiness, I think.



Checked in the fix.  My apologies for committing broken code.  :slight_smile:

On the contrary Falken224, thank you for the wonderful contribution.

All working now