virtual void onContactNotify(NxContactPair& pair, NxU32 events) { NxU32 carIndex = 0; if (isCar(pair.actors[0])) carIndex = 0; else if (isCar(pair.actors[1])) carIndex = 1; else return; //ignore the 'both are cars' case for now. // Iterate through contact points NxContactStreamIterator i(pair.stream); //user can call getNumPairs() here while (i.goNextPair()) { //user can also call getShape() and getNumPatches() here NxShape * s = i.getShape(carIndex); while (i.goNextPatch()) { //user can also call getPatchNormal() and getNumPoints() here const NxVec3& contactNormal = i.getPatchNormal(); while (i.goNextPoint()) { //user can also call getPoint() and getSeparation() here const NxVec3& contactPoint = i.getPoint(); NxVec3 contactNormalForce = pair.sumNormalForce; NxVec3 contactFrictionForce = pair.sumFrictionForce; //add forces: //assuming front wheel drive we need to apply a force at the wheels. if (s->is(NX_SHAPE_CAPSULE)) //assuming only the wheels of the car are capsules, otherwise we need more checks. //this branch can't be pulled out of loops because we have to do a full iteration through the stream { CarWheelContact cwc; cwc.car = pair.actors[carIndex]; cwc.wheel = s; cwc.contactPoint = contactPoint; cwc.contactNormalForce = contactNormalForce; cwc.contactFrictionForce = contactFrictionForce; wheelContactPoints.pushBack(cwc); //#error too bad this is illegal (reentry) and also technically busted because the accumulators get zeroed after this returns. //pair.actors[carIndex]->addForceAtPos(NxVec3(100,0,0),contactPoint); } } } } }
void NxVehicle::handleContactPair(NxContactPair& pair, NxU32 carIndex) { NxContactStreamIterator i(pair.stream); while(i.goNextPair()) { NxShape * s = i.getShape(carIndex); while(i.goNextPatch()) { const NxVec3& contactNormal = i.getPatchNormal(); while(i.goNextPoint()) { //user can also call getPoint() and getSeparation() here const NxVec3& contactPoint = i.getPoint(); //add forces: //assuming front wheel drive we need to apply a force at the wheels. if (s->is(NX_SHAPE_CAPSULE) && s->userData != NULL) { //assuming only the wheels of the car are capsules, otherwise we need more checks. //this branch can't be pulled out of loops because we have to do a full iteration through the stream NxQuat local2global = s->getActor().getGlobalOrientationQuat(); NxWheel* w = (NxWheel*)s->userData; if (!w->getWheelFlag(NX_WF_USE_WHEELSHAPE)) { NxWheel1 * wheel = static_cast<NxWheel1*>(w); wheel->contactInfo.otherActor = pair.actors[1-carIndex]; wheel->contactInfo.contactPosition = contactPoint; wheel->contactInfo.contactPositionLocal = contactPoint; wheel->contactInfo.contactPositionLocal -= _bodyActor->getGlobalPosition(); local2global.inverseRotate(wheel->contactInfo.contactPositionLocal); wheel->contactInfo.contactNormal = contactNormal; if (wheel->contactInfo.otherActor->isDynamic()) { NxVec3 globalV = s->getActor().getLocalPointVelocity(wheel->getWheelPos()); globalV -= wheel->contactInfo.otherActor->getLinearVelocity(); local2global.inverseRotate(globalV); wheel->contactInfo.relativeVelocity = globalV.x; //printf("%2.3f (%2.3f %2.3f %2.3f)\n", wheel->contactInfo.relativeVelocity, // globalV.x, globalV.y, globalV.z); } else { NxVec3 vel = s->getActor().getLocalPointVelocity(wheel->getWheelPos()); local2global.inverseRotate(vel); wheel->contactInfo.relativeVelocity = vel.x; wheel->contactInfo.relativeVelocitySide = vel.z; } NX_ASSERT(wheel->hasGroundContact()); //printf(" Wheel %x is touching\n", wheel); } } } } } //printf("----\n"); }