GHOST Material events

Is it already done? Material.GHOST triggering events but not colliding.

Irrisor, need your help…



I'm trying to implement it. Just got the latest CVS and put my hands on the thing…



Ok, lets go:

1 - I put another boolean at MutableContactInfo, calling it ignoreContacts. So I setted Material.GHOST to have ignoreContacts true instead of having setIgnore(true).

2 - I checked OdePhysicsSpace at iterateContacts(boolean applyContacts)… And found out that some contacts are not applied (when are generated by rays, for instance). So I added one last condition for not applying them (but yet generating the events) - look at the last expression element:

boolean applyThisContact = applyContacts && !(geom1 instanceof GeomRay) && !(geom2 instanceof GeomRay) && !contact.isIgnoreContacts();



With this I thought every DynamicPhysicsNode with Material.GHOST would generate collision events, without forces or other physics related consequences. It ACTUALLY does, but... (we always have the but...)

After several contact events ODE CRASHED...

The output of the crash is this:

ODE Message 2: vector has zero size in dNormalize4()

ODE Message 2: vector has zero size in dNormalize4()

ODE Message 2: vector has zero size in dNormalize4()

ODE Message 2: vector has zero size in dNormalize4()

ODE Message 2: vector has zero size in dNormalize4()

ODE Message 2: vector has zero size in dNormalize4()
Invalid memory access of location afa989d4 eip=1a99c243


Any clue? I'll keep on trying since I need this ghost contact event to implement my triangle-accurate-cone-shaped-radar-plus-plus...

Thanks in advance.

OK… I did… Easier than I thought… ust put this for ignoredContacts as well:


ContactInfo info = reusableContactInfo(contact);
               collisionEvent(info);



It worked now... Without the new boolean as well...

Cool! I never got around to finishing the ghost stuff. Can you send a patch?  (sorry, I was of no help, found this thread just now)

OK… Here it is… I didn't do a proper "patch", but I'm posting the modification that worked well.



I just made one change inside the method iterateContacts of the OdePhysicsSpace class. Here it is:


private void iterateContacts(boolean applyContacts) {
      PhysicsNode previous1 = null;
      PhysicsNode previous2 = null;
      for (int i = 0; i < collision.getContactCount(); i++) {
         // set the index
         odeContact.setIndex(i);

         final Geom geom1 = odeContact.getGeom1();
         final Geom geom2 = odeContact.getGeom2();
         if (geom1 == null || geom2 == null) {
            odeContact.ignoreContact();
            continue;
         }
         PhysicsNode obj1 = geom1.getPhysicsObject();
         PhysicsNode obj2 = geom2.getPhysicsObject();

         {
            // don't let rays generate contact points in ode but generate
            // events
            boolean applyThisContact = applyContacts && !(geom1 instanceof GeomRay) && !(geom2 instanceof GeomRay);

            contact.clear();
            if (applyThisContact) {
               adjustContact(contact);
            }

            if (contact.isIgnored()) {
               odeContact.ignoreContact();
            } else {
               if (!applyThisContact) {
                  // don't apply contact points in but generate events
                  odeContact.ignoreContact();
               } else {
                  int mode = Ode.dContactApprox1;
                  odeContact.setMode(mode);

                  if (!Float.isNaN(contact.getMu())) {
                     odeContact.setMu(contact.getMu());
                  } else {
                     odeContact.setMu(100);
                  }

                  if (!Float.isNaN(contact.getBounce())) {
                     mode |= Ode.dContactBounce;
                     odeContact.setMode(mode);
                     odeContact.setBounce(contact.getBounce());
                  }
                  if (!Float.isNaN(contact.getMinimumBounceVelocity())) {
                     odeContact.setBounceVel(contact.getMinimumBounceVelocity());
                  } else {
                     odeContact.setBounceVel(1f);
                  }
                  if (!Float.isNaN(contact.getMuOrthogonal())) {
                     mode |= Ode.dContactMu2;
                     odeContact.setMode(mode);
                     odeContact.setMu2(contact.getMuOrthogonal());
                  }
                  Vector3f fdir = contact.getFrictionDirection(tmp2);
                  if (!Float.isNaN(fdir.x) && !Float.isNaN(fdir.y) && !Float.isNaN(fdir.z)) {
                     mode |= Ode.dContactFDir1;
                     odeContact.setFdir1(fdir);
                  }
                  Vector2f surfaceMotion = contact.getSurfaceMotion(tmpVec2);
                  if (!Float.isNaN(surfaceMotion.x) && surfaceMotion.x != 0) {
                     mode |= Ode.dContactMotion1;
                     odeContact.setMode(mode);
                     odeContact.setMotion1(surfaceMotion.x);
                  }
                  if (!Float.isNaN(surfaceMotion.y) && surfaceMotion.y != 0) {
                     mode |= Ode.dContactMotion2;
                     odeContact.setMode(mode);
                     odeContact.setMotion2(surfaceMotion.y);
                  }
                  Vector2f slip = contact.getSlip(tmpVec2);
                  if (!Float.isNaN(slip.x)) {
                     mode |= Ode.dContactSlip1;
                     odeContact.setMode(mode);
                     odeContact.setSlip1(slip.x);
                  }
                  if (!Float.isNaN(slip.y)) {
                     mode |= Ode.dContactSlip2;
                     odeContact.setMode(mode);
                     odeContact.setSlip2(slip.y);
                  }
               } // Erick end of else aplyThisContact

               if ((obj1 != previous1) || (obj2 != previous2)) {
                  // compute collision velocity (must be done before
                  // returning contact)
                  Vector3f actualBounceVel = tmpBounceVel.set(0, 0, 0);
                  if (obj1 != null && !obj1.isStatic()) {
                     actualBounceVel.subtractLocal(((DynamicPhysicsNode) obj1).getLinearVelocity(tmp1));
                  }
                  if (obj2 != null && !obj2.isStatic()) {
                     actualBounceVel.addLocal(((DynamicPhysicsNode) obj2).getLinearVelocity(tmp1));
                  }
                  actualBounceVel.multLocal(odeContact.getNormal(tmp2));
                  // TODO: allow to trash contacts if results are not
                  // needed
                  // Erick CODE MOVED... SEE BELOW...
                  // contactInfos.add( info );
               }
            } // Erick end of contact.isIgnored()
            
            // TODO Erick - Here this will generate event... for all contacts... Even ignored ones, like GHOST Material...
            ContactInfo info = reusableContactInfo(contact);
            collisionEvent(info);
         }
      }
   }



You can see the modification at the end... I moved the copy contact info and event generation outside of some IF-ELSES... Since you did it Irrisor you can say I this is safe... Until now it's working perfecly here... But I didn't test much.

No it's not safe this way. You don't have a chance to avoid collision events this way. I'll have a look how it can be done properly.



And please create a patch next time, it's much easier to see what has changed then - a lot less to read.



edit: typo

You don't have a change to avoid collision events this way


I just didn't got into it too much, but I can try to understand the implications and work it out. I didn't understand what you meant by "CHANGE to avoid"... Did you mean "chance"? If it's just this I can try the other one I was working: Setting one more boolean attribute at Material.

yep, chance not change, sorry



I introduced a new boolean flag isApplied() to the contact handling details, as you suggested. This solution is fine, I think. Please check if that works for you.

Hi… is it possible, that the isApplied-Flag is not working right?



I added a simple check in OdePhysicsSpace at Line 834:


private boolean iterateContacts( boolean applyContacts ) {
....
           if(obj1.getMaterial().getContactHandlingDetails(obj2.getMaterial()).isApplied()  != contact.isApplied())
                  System.out.println("Error! isApplied not returning the right value");
....
}


I created one object with the material IRON and another with GHOST.
The message is printed out every time something collides with the GHOST object.

Thanks for help :)

Problem solved:

I added following line to my ContactCallback so contact.isApplied() returns the right value:

c.setApplied(c.getNode1().getMaterial().getContactHandlingDetails(c.getNode2().getMaterial()).isApplied());


Is this the way how it should be done?

Sorry for getting back to you that late.


JackNeil said:

Is this the way how it should be done?

No. You should not need that line. Can you double-check that the problem still exists with the current CVS version, please. If yes, please post a small example, as I cannot reproduce it locally.