diff --git a/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp b/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp index c59b5f4f..235c3450 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp +++ b/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp @@ -133,8 +133,10 @@ void plWalkingController::RecalcVelocity(double timeNow, double timePrev, hsBool if (fController && !fWalkingStrategy->IsOnGround()) { + // PhysX Hack: AchievedLinearVelocity is a Cyanic fix for superjumps. LinearVelocity is + // always (0,0,0) outside of the controller update proc fImpactTime = fWalkingStrategy->GetAirTime(); - fImpactVelocity = fController->GetLinearVelocity(); + fImpactVelocity = fController->GetAchievedLinearVelocity(); fClearImpact = false; } else diff --git a/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp b/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp index f43af2ec..66c0cc7a 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp +++ b/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp @@ -323,48 +323,7 @@ void plWalkingStrategy::Apply(float delSecs) LinearVelocity.fX = AchievedLinearVelocity.fX; LinearVelocity.fY = AchievedLinearVelocity.fY; } - if (!IsOnGround() || IsOnFalseGround()) - { - // We're not on solid ground, so we should be sliding against whatever - // we're hitting (like a rock cliff). Each vector in fSlidingNormals is - // the surface normal of a collision that's too steep to be ground, so - // we project our current velocity onto that plane and slide along the - // wall. - // - // Also, sometimes PhysX reports a bunch of collisions from the wall, - // but nothing from underneath (when there should be). So if we're not - // touching ground, we offset the avatar in the direction of the - // surface normal(s). This doesn't fix the issue 100%, but it's a hell - // of a lot better than nothing, and suitable duct tape until a future - // PhysX revision fixes the issue. - // - // Yes, there's room for optimization here if we care. - hsVector3 offset(0.f, 0.f, 0.f); - for (int i = 0; i < fContactNormals.GetCount(); i++) - { - offset += fContactNormals[i]; - hsVector3 velNorm = LinearVelocity; - - if (velNorm.MagnitudeSquared() > 0) - velNorm.Normalize(); - if (velNorm * fContactNormals[i] < 0) - { - hsVector3 proj = (velNorm % fContactNormals[i]) % fContactNormals[i]; - if (velNorm * proj < 0) - proj *= -1.f; - LinearVelocity = LinearVelocity.Magnitude() * proj; - } - } - if (offset.MagnitudeSquared() > 0) - { - // 5 ft/sec is roughly the speed we walk backwards. - // The higher the value, the less likely you'll trip - // the bug, and this seems reasonable. - offset.Normalize(); - LinearVelocity += offset * 5.0f; - } - } //make terminal velocity equal to k. it is wrong but has been this way and //don't want to break any puzzles. on top of that it will reduce tunneling behavior if(LinearVelocity.fZ gControllers; static bool gRebuildCache=false; -#define AvatarMass 200.f - class PXControllerHitReportWalk : public NxUserControllerHitReport { public: @@ -99,9 +93,9 @@ public: plPXPhysicalControllerCore* ac = plPXPhysicalControllerCore::FindController(hit.controller); NxActor& actor = hit.shape->getActor(); plPXPhysical* phys = (plPXPhysical*)actor.userData; - static float SlopeLimit = kSLOPELIMIT; hsVector3 normal = plPXConvert::Vector(hit.worldNormal); ac->fMovementInterface->IAddContactNormals(normal); + #ifndef PLASMA_EXTERNAL_RELEASE plDbgCollisionInfo info; info.fNormal = normal; @@ -124,6 +118,7 @@ public: } ac->fDbgCollisionInfo.Append(info); #endif PLASMA_EXTERNAL_RELEASE + // If the avatar hit a movable physical, apply some force to it. hsVector3 dir = plPXConvert::Vector(hit.dir); float dirdotup=dir.fZ; @@ -131,15 +126,16 @@ public: NxExtendedVec3 controllerPos=hit.controller->getPosition(); hsVector3 bottomOfTheCapsule((float)controllerPos.x,(float)controllerPos.y,(float)controllerPos.z); bottomOfTheCapsule.fZ=bottomOfTheCapsule.fZ-(ac->fHeight/2.0f + ac->fRadius); - if (actor.isDynamic() ) + if (actor.isDynamic() && phys ) { if((hit.worldPos.z- bottomOfTheCapsule.fZ)<=ac->fRadius)//bottom hemisphere { - //onTopOfSlopeLimit - if (phys && phys->GetProperty(plSimulationInterface::kPhysAnim)) + // If this is an animated physical, we can stand on it + if (phys->GetProperty(plSimulationInterface::kPhysAnim)) { if(normal.fZ>=0) - {//we consider this ground + { + //we consider this ground ac->fMovementInterface->AddOnTopOfObject(phys); } } @@ -161,52 +157,22 @@ public: setNetGroupID->Send(obj->GetKey()); } plSimulationMgr::GetInstance()->ConsiderSynch(phys, nil); - // We only allow horizontal pushes. Vertical pushes when we stand on - // dynamic objects creates useless stress on the solver. - - hsVector3 vel=ac->GetLinearVelocity()- plPXConvert::Vector( actor.getLinearVelocity()); - if(dirdotup>=0)vel.fZ=0.001f; - else vel.fZ=0.0f; - static float kAvieMass = 140.f/32.f; - if (!vel.IsEmpty()) - { - static float kForceScale = 140.0f; - NxF32 coeff; - NxExtendedVec3 norm2=hit.controller->getPosition(); - norm2.x=hit.worldPos.x-bottomOfTheCapsule.fX; - norm2.y=hit.worldPos.y-bottomOfTheCapsule.fY; - if((hit.worldPos.z- bottomOfTheCapsule.fZ)fRadius)//bottom hemisphere - { - norm2.normalize(); - norm2.z=0.01f; - } - else if((hit.worldPos.z- bottomOfTheCapsule.fZ)<(ac->fRadius+ac->fHeight)) - { - norm2.z=0.0f; - norm2.normalize(); - } - else - {//must be the top so the normal is displacement from the pos - center - //of top hemisphere - norm2.z=hit.worldPos.z - ((ac->fRadius+ac->fHeight + bottomOfTheCapsule.fZ)); - norm2.normalize(); - } - - - float proj=(float)(norm2.x*dir.fX+dir.fY*norm2.y+dir.fZ*norm2.z); - coeff =abs(proj*kForceScale*vel.Magnitude()); - vel.fZ=(float)norm2.z; - vel.fY=(float)norm2.y; - vel.fX=(float)norm2.x; - phys->SetHitForce(vel*coeff, pos); - } + + // Now, let's impart some force, fool. + // Note: This is a VERY simple implementation. The old one was too hacky and caused weird stuff to happen. + hsVector3 acceleration = (ac->GetLinearVelocity() - plPXConvert::Vector(actor.getLinearVelocity())); + hsVector3 force2impart = acceleration * kAvatarMass; + // Bad things happen if we impart force directly on top of the actor, so let's allow the avatar to run + // over those physicals and not break them. This is mostly an issue with stuff smaller than step size. + if (!force2impart.IsEmpty() && normal.fZ < .90f) + phys->SetHitForce(force2impart, pos); } } else // else if the avatar hit a static { return NX_ACTION_NONE; } - if (phys && phys->GetProperty(plSimulationInterface::kAvAnimPushable)) + if (phys->GetProperty(plSimulationInterface::kAvAnimPushable)) { hsQuat inverseRotation = ac->fLocalRotation.Inverse(); hsVector3 normal = plPXConvert::Vector(hit.worldNormal); @@ -546,7 +512,7 @@ NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey); capDesc.materialIndex= plSimulationMgr::GetInstance()->GetMaterialIdx(scene, 0.0,0.0); actorDesc.shapes.pushBack(&capDesc); NxBodyDesc bodyDesc; - bodyDesc.mass = AvatarMass;//1.f; + bodyDesc.mass = kAvatarMass; actorDesc.body = &bodyDesc; bodyDesc.flags = NX_BF_KINEMATIC; bodyDesc.flags |=NX_BF_DISABLE_GRAVITY ; @@ -619,7 +585,7 @@ void plPXPhysicalControllerCore::ICreateController(const hsPoint3& pos) capDesc.materialIndex= plSimulationMgr::GetInstance()->GetMaterialIdx(scene, 0.0,0.0); actorDesc.globalPose=actor->getGlobalPose(); NxBodyDesc bodyDesc; - bodyDesc.mass = AvatarMass; + bodyDesc.mass = kAvatarMass; actorDesc.body = &bodyDesc; bodyDesc.flags = NX_BF_KINEMATIC; bodyDesc.flags |=NX_BF_DISABLE_GRAVITY ; diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp index 051c4761..97454212 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp @@ -156,7 +156,7 @@ class SensorReport : public NxUserTriggerReport { if (plSimulationMgr::fExtraProfile) DetectorLogRed("-->Send Collision (CH) %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit"); - SendCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true); + plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true); } else if (status & NX_TRIGGER_ON_ENTER) { @@ -167,7 +167,7 @@ class SensorReport : public NxUserTriggerReport { if (plSimulationMgr::fExtraProfile) DetectorLogRed("-->Send Collision (CH) %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit"); - SendCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false); + plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false); } else if (status & NX_TRIGGER_ON_LEAVE) { @@ -187,13 +187,13 @@ class SensorReport : public NxUserTriggerReport { if (plSimulationMgr::fExtraProfile) DetectorLogRed("-->Send Collision %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit"); - SendCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true); + plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true); } if (status & NX_TRIGGER_ON_LEAVE) { if (plSimulationMgr::fExtraProfile) DetectorLogRed("-->Send Collision %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit"); - SendCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false); + plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false); } if (!(status & NX_TRIGGER_ON_ENTER) && !(status & NX_TRIGGER_ON_LEAVE) ) { @@ -205,18 +205,6 @@ class SensorReport : public NxUserTriggerReport #endif // USE_PHYSX_CONVEXHULL_WORKAROUND } } - - void SendCollisionMsg(plKey receiver, plKey hitter, hsBool entering) - { - DetectorLogYellow("Collision: %s was triggered by %s. Sending an %s msg", receiver->GetName().c_str(), - hitter ? hitter->GetName().c_str() : "(nil)" , entering ? "'enter'" : "'exit'"); - plCollideMsg* msg = new plCollideMsg; - msg->fOtherKey = hitter; - msg->fEntering = entering; - msg->AddReceiver(receiver); - plgDispatch::Dispatch()->MsgQueue(msg); // Sends the msg on the next client update - } - } gSensorReport; // This gets called by PhysX whenever two actor groups that are set to report @@ -599,6 +587,34 @@ void plSimulationMgr::UpdateAvatarInDetector(plKey world, plPXPhysical* detector } } +void plSimulationMgr::AddCollisionMsg(plKey hitee, plKey hitter, bool enter) +{ + // First, make sure we have no dupes + for (CollisionVec::iterator it = fCollideMsgs.begin(); it != fCollideMsgs.end(); ++it) + { + plCollideMsg* pMsg = *it; + + // Should only ever be one receiver. + // Oh, it seems we should update the hit status. The latest might be different than the older... + // Even in the same frame >.< + if (pMsg->fOtherKey == hitter && pMsg->GetReceiver(0) == hitee) + { + pMsg->fEntering = enter; + DetectorLogRed("DUPLICATE COLLISION: %s hit %s", + (hitter ? hitter->GetName().c_str() : "(nil)"), + (hitee ? hitee->GetName().c_str() : "(nil)")); + return; + } + } + + // Still here? Then this must be a unique hit! + plCollideMsg* pMsg = new plCollideMsg; + pMsg->AddReceiver(hitee); + pMsg->fOtherKey = hitter; + pMsg->fEntering = enter; + fCollideMsgs.push_back(pMsg); +} + void plSimulationMgr::Advance(float delSecs) { if (fSuspended) @@ -693,6 +709,15 @@ void plSimulationMgr::Advance(float delSecs) void plSimulationMgr::ISendUpdates() { + for (CollisionVec::iterator it = fCollideMsgs.begin(); it != fCollideMsgs.end(); ++it) + { + plCollideMsg* pMsg = *it; + DetectorLogYellow("Collision: %s was triggered by %s. Sending an %s msg", pMsg->GetReceiver(0)->GetName().c_str(), + pMsg->fOtherKey ? pMsg->fOtherKey->GetName().c_str() : "(nil)" , pMsg->fEntering ? "'enter'" : "'exit'"); + plgDispatch::Dispatch()->MsgSend(pMsg); + } + fCollideMsgs.clear(); + SceneMap::iterator it = fScenes.begin(); for (; it != fScenes.end(); it++) { diff --git a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h index 2a75d943..d25ae4ac 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h +++ b/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h @@ -102,11 +102,14 @@ public: // PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering); void UpdateAvatarInDetector(plKey world, plPXPhysical* detector); + //Fix to Move collision messages and their handling out of the simulation step - void AddCollisionMsg(plCollideMsg* msg); + void AddCollisionMsg(plKey hitee, plKey hitter, bool entering); + #ifndef PLASMA_EXTERNAL_RELEASE static bool fDisplayAwakeActors; #endif //PLASMA_EXTERNAL_RELEASE + protected: friend class ContactReport; @@ -125,6 +128,10 @@ protected: plPhysicsSoundMgr* fSoundMgr; + // Pending collision messages + typedef std::vector CollisionVec; + CollisionVec fCollideMsgs; + // A mapping from a key to a PhysX scene. The key is either the // SimulationMgr key, for the main world, or a SceneObject key if it's a // subworld. diff --git a/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp b/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp index 84ef6799..57a3648d 100644 --- a/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp +++ b/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp @@ -236,103 +236,56 @@ void plCollisionDetector::Write(hsStream* stream, hsResMgr* mgr) plCameraRegionDetector::~plCameraRegionDetector() { - for(int i = 0; i < fMessages.Count(); i++) - { - plMessage* pMsg = fMessages[i]; - fMessages.Remove(i); - delete(pMsg); - } - fMessages.SetCountAndZero(0); + for (plCameraMsgVec::iterator it = fMessages.begin(); it != fMessages.end(); ++it) + hsRefCnt_SafeUnRef(*it); } void plCameraRegionDetector::ITrigger(plKey hitter, bool entering, bool immediate) { - -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame - if (entering && fNumEvals - fLastExitEval <= 1 && fSavingSendMsg) - { - DetectorLog("%s: Skipping Camera Entering volume", GetKeyName().c_str()); - fLastEnterEval = fNumEvals; - if (fSavingSendMsg) - { - DetectorLog("%s: Dumping saved Camera Exiting volume", GetKeyName().c_str()); - } - fSavingSendMsg = false; - return; - } - if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavingSendMsg) - { - DetectorLog("%s: Skipping Exiting volume", GetKeyName().c_str()); - fLastExitEval = fNumEvals; - if (fSavingSendMsg) - { - DetectorLog("%s: Dumping saved Camera Entering volume", GetKeyName().c_str()); - } - fSavingSendMsg = false; - return; - } - - // get rid of any saved messages... this should happen though if (fSavingSendMsg) - { - DetectorLog("%s: Killing saved camera message... shouldn't happen", GetKeyName().c_str()); - } - // end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND + DetectorLogRed("%s: Stale messages on ITrigger. This should never happen!", GetKeyName().c_str()); + if (fIsInside && entering) + DetectorLogRed("%s: Duplicate enter! Did we miss an exit?", GetKeyName().c_str()); + else if (!fIsInside && !entering) + DetectorLogRed("%s: Duplicate exit! Did we miss an enter?", GetKeyName().c_str()); fSavingSendMsg = true; fSavedMsgEnterFlag = entering; if (entering) { - //DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName().c_str(),fNumEvals); + DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName().c_str(),fNumEvals); fLastEnterEval = fNumEvals; } else { - //DetectorLog("%s: Saving camera Exiting volume - Evals=%d", GetKeyName().c_str(),fNumEvals); + DetectorLog("%s: Saving camera Exiting volume - Evals=%d", GetKeyName().c_str(),fNumEvals); fLastExitEval = fNumEvals; } -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame - // we're saving the message to be dispatched later... if (immediate) - { -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - ISendSavedTriggerMsgs(); - -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - } -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - - } void plCameraRegionDetector::ISendSavedTriggerMsgs() { if (fSavingSendMsg) { - for (int i = 0; i < fMessages.Count(); i++) + for (size_t i = 0; i < fMessages.size(); ++i) { - char str[256]; - hsRefCnt_SafeRef(fMessages[i]); if (fSavedMsgEnterFlag) { fMessages[i]->SetCmd(plCameraMsg::kEntering); - sprintf(str, "Entering cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.Count()); + DetectorLog("Entering cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.size()); fIsInside = true; } else { fMessages[i]->ClearCmd(plCameraMsg::kEntering); - sprintf(str, "Exiting cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.Count()); + DetectorLog("Exiting cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.size()); fIsInside = false; } plgDispatch::MsgSend(fMessages[i]); - DetectorLog("%s", str); } } fSavingSendMsg = false; @@ -342,38 +295,23 @@ void plCameraRegionDetector::ISendSavedTriggerMsgs() hsBool plCameraRegionDetector::MsgReceive(plMessage* msg) { plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg); - if (pCollMsg) { // camera collisions are only for the local player if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey) return true; - - -#ifdef USE_PHYSX_MULTIPLE_CAMREGION_ENTER - // first determine if this is a multiple camera region enter (PHYSX BUG WORKAROUND) - if (!fWaitingForEval) - {//plObjectInVolumeCollisionDetector::MsgReceive() will flip fWaitingForEval - // and registers for the Eval, child objects of plObjectInVolumeCollisionDetector - //must decide when they are no longer interested in Evals. I suggest using IHandleEvals() - - fNumEvals = 0; - fLastEnterEval=-999; - fLastExitEval=-999; - } - - // end of (PHYSX BUG WORKAROUND) -#endif // USE_PHYSX_MULTIPLE_CAMREG_ENTER - + // Fall through to plObjectInVolumeDetector, which will register us for plEvalMsg + // and handle it for us. (Hint: See ISendSavedTriggerMsgs) } + return plObjectInVolumeDetector::MsgReceive(msg); } void plCameraRegionDetector::Read(hsStream* stream, hsResMgr* mgr) { plDetectorModifier::Read(stream, mgr); int n = stream->ReadLE32(); - fMessages.SetCountAndZero(n); - for(int i = 0; i < n; i++ ) + fMessages.resize(n); + for(size_t i = 0; i < n; i++ ) { plCameraMsg* pMsg = plCameraMsg::ConvertNoRef(mgr->ReadCreatable(stream)); fMessages[i] = pMsg; @@ -383,27 +321,10 @@ void plCameraRegionDetector::Read(hsStream* stream, hsResMgr* mgr) void plCameraRegionDetector::Write(hsStream* stream, hsResMgr* mgr) { plDetectorModifier::Write(stream, mgr); - stream->WriteLE32(fMessages.GetCount()); - for(int i = 0; i < fMessages.GetCount(); i++ ) - mgr->WriteCreatable( stream, fMessages[i] ); - -} -void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval) -{ - fNumEvals++; - if (fNumEvals - fLastEnterEval > 1 && fNumEvals-fLastExitEval>1) - { - ISendSavedTriggerMsgs(); - plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey()); - fWaitingForEval = false; - } - else - { - if(fSavedActivatorMsg) - DetectorLog("%s didn't send its message. fNumEvals=%d fLastEnterEval=%d, fLastExit=%d", - GetKeyName().c_str(),fNumEvals, fLastEnterEval, fLastExitEval); + stream->WriteLE32(fMessages.size()); + for(plCameraMsgVec::iterator it = fMessages.begin(); it != fMessages.end(); ++it) + mgr->WriteCreatable( stream, *it ); - } } ///////////////////////////////// @@ -414,127 +335,8 @@ void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval) void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immediate) { -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame -/* if (entering && fNumEvals - fLastExitEval <= 1 && fSavedActivatorMsg) - { - //DetectorLog("%s: Skipping Entering volume", GetKeyName()); - fLastEnterEval = fNumEvals; - if (fSavedActivatorMsg) - { - //DetectorLog("%s: Dumping saved Exiting volume", GetKeyName()); - delete fSavedActivatorMsg; - } - fSavedActivatorMsg = nil; - return; - } - if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavedActivatorMsg) - { - //DetectorLog("%s: Skipping Exiting volume", GetKeyName()); - fLastExitEval = fNumEvals; - if (fSavedActivatorMsg) - { - //DetectorLog("%s: Dumping saved Entering volume", GetKeyName()); - delete fSavedActivatorMsg; - } - fSavedActivatorMsg = nil; - return; - } - - // get rid of any saved messages... this should happen though - if (fSavedActivatorMsg) - { - delete fSavedActivatorMsg; - DetectorLog("%s: Killing saved message... shouldn't happen", GetKeyName()); - } - // end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame -*/ - if(!immediate) - { - - bookKeepingList::iterator curit=fCollisionList.begin(); - while(curit!=fCollisionList.end()) - { - if(hitter==(*curit)->hitter) - {//hey the object is already in my list - //try and figure out what my real state is - if(entering) - { - (*curit)->enters++; - if(!(*curit)->fSubStepCurState) - {//We weren't already in - (*curit)->fSubStepCurState =true; - } - } - else - { - (*curit)->exits++; - if((*curit)->fSubStepCurState) - {//We were already in - (*curit)->fSubStepCurState =false; - } - } - //get out - break; - } - curit++; - } - if(curit==fCollisionList.end()) - { - //hitter was not in the list add him in - //hitter was not in the current frame list - //lets find out its state in the begining of the frame - ResidentSet::iterator curres = fCurrentResidents.find(hitter); - bool initialState; - if(curres != fCurrentResidents.end()) - initialState =true; - else - initialState =false; - - plCollisionBookKeepingInfo* BookKeeper=new plCollisionBookKeepingInfo(hitter); - if(entering) - { - BookKeeper->enters++; - BookKeeper->fSubStepCurState =true; - } - else - { - BookKeeper->exits++; - BookKeeper->fSubStepCurState =false; - } - fCollisionList.push_front(BookKeeper); - } - - - } - else - { - plActivatorMsg* ActivatorMsg = new plActivatorMsg; - ActivatorMsg->AddReceivers(fReceivers); - if (fProxyKey) - ActivatorMsg->fHiteeObj = fProxyKey; - else - ActivatorMsg->fHiteeObj = GetTarget()->GetKey(); - - ActivatorMsg->fHitterObj = hitter; - ActivatorMsg->SetSender(GetKey()); - if (entering) - { - ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter); - } - else - { - ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit); - } - - plgDispatch::MsgSend(ActivatorMsg); - - - } -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - -/* fSavedActivatorMsg = new plActivatorMsg; - + hsRefCnt_SafeUnRef(fSavedActivatorMsg); + fSavedActivatorMsg = new plActivatorMsg; fSavedActivatorMsg->AddReceivers(fReceivers); if (fProxyKey) @@ -547,47 +349,36 @@ void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immedi if (entering) { - //DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName(),fNumEvals); + DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName().c_str(), fNumEvals); fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter); fLastEnterEval = fNumEvals; } else { - //DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName(),fNumEvals); + DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName().c_str(), fNumEvals); fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit); fLastExitEval = fNumEvals; } -*/ -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame - // we're saving the message to be dispatched later... - if (immediate) - { -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - - // fSavedActivatorMsg = nil; - -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - } -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND + if (immediate) + ISendSavedTriggerMsgs(); } -/* + void plObjectInVolumeDetector::ISendSavedTriggerMsgs() { if (fSavedActivatorMsg) { if (fSavedActivatorMsg->fTriggerType == plActivatorMsg::kVolumeEnter) - DetectorLog("%s: Sending Entering volume - Evals=%d", GetKeyName(),fNumEvals); + DetectorLog("%s: Sending Entering volume - Evals=%d", GetKeyName().c_str(), fNumEvals); else - DetectorLog("%s: Sending Exiting volume - Evals=%d", GetKeyName(),fNumEvals); + DetectorLog("%s: Sending Exiting volume - Evals=%d", GetKeyName().c_str(), fNumEvals); // we're saving the message to be dispatched later... plgDispatch::MsgSend(fSavedActivatorMsg); } fSavedActivatorMsg = nil; } -*/ + hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg) { plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg); @@ -596,36 +387,18 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg) // If the avatar is disabled (flying around), don't trigger if (IIsDisabledAvatar(pCollMsg->fOtherKey)) return false; - -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame - if (!fWaitingForEval) - { - plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey()); - fWaitingForEval = true; - } - // end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0)); - + plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey()); return true; } -#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND - // PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame - plEvalMsg* pEval = plEvalMsg::ConvertNoRef(msg); - if (pEval) + plEvalMsg* pEvalMsg = plEvalMsg::ConvertNoRef(msg); + if (pEvalMsg) { - - //if (fSavedActivatorMsg) - // DetectorLog("%s: InVolumeEval=%d with saved message", GetKeyName(), fNumEvals); - //else - // DetectorLog("%s: InVolumeEval=%d without saved message", GetKeyName(), fNumEvals); - IHandleEval(pEval); - + fNumEvals++; + ISendSavedTriggerMsgs(); + plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey()); } - // end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame -#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg); if (pageMsg && pageMsg->fUnload) @@ -636,75 +409,6 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg) return plCollisionDetector::MsgReceive(msg); } -void plObjectInVolumeDetector::IHandleEval(plEvalMsg* pEval) -{ - plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey()); - fWaitingForEval = false; - for(bookKeepingList::reverse_iterator it= fCollisionList.rbegin();it!=fCollisionList.rend(); it++) - { - bool alreadyInside; - ResidentSet::iterator HitIt; - HitIt = fCurrentResidents.find((*it)->hitter); - if(HitIt != fCurrentResidents.end()) alreadyInside = true; - else alreadyInside=false; - plActivatorMsg* actout=new plActivatorMsg; - actout->fHitterObj=((*it)->hitter); - actout->SetSender(GetKey()); - if (fProxyKey) - actout->fHiteeObj = fProxyKey; - else - actout->fHiteeObj = GetTarget()->GetKey(); - if((*it)->fSubStepCurState)//current substate says we are entered - {//different enters and exits - //figure out what to do - if(!alreadyInside) - {//we are actuall entering - actout->SetTriggerType(plActivatorMsg::kVolumeEnter); - fCurrentResidents.insert((*it)->hitter); - actout->AddReceivers(fReceivers); - actout->Send(); - DetectorLog("%s sent an Enter ActivatorMsg. To: %s", GetKeyName().c_str(), GetTarget()->GetKeyName().c_str() ); - } - else - { - DetectorLog("%s squelched an Enter ActivatorMsg.", GetKeyName().c_str()); - delete actout; - } - } - else - { - //fSubStepCurState says we are outside - if(alreadyInside) - {//we are actuall exiting - actout->SetTriggerType(plActivatorMsg::kVolumeExit); - fCurrentResidents.erase((*it)->hitter); - actout->AddReceivers(fReceivers); - actout->Send(); - DetectorLog("%s sent an Exit ActivatorMsg. To: %s", GetKeyName().c_str(), GetTarget()->GetKeyName().c_str()); - } - else - { - DetectorLog("%s squelched an Exit ActivatorMsg.", GetKeyName().c_str()); - delete actout; - } - } - } - DetectorLog("*********"); - for(bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); it ++) - { - delete (*it); - } - DetectorLog("This is the regions inhabitants after the op"); - for(ResidentSet::iterator it = fCurrentResidents.begin(); it!= fCurrentResidents.end(); it++) - { - DetectorLog("%s", (*it)->GetName().c_str()); - } - DetectorLog("*********"); - - fCollisionList.clear(); - -} - void plObjectInVolumeDetector::SetTarget(plSceneObject* so) { plCollisionDetector::SetTarget(so); @@ -730,6 +434,7 @@ void plObjectInVolumeDetector::Write(hsStream* stream, hsResMgr* mgr) plObjectInVolumeAndFacingDetector::plObjectInVolumeAndFacingDetector() : + plObjectInVolumeDetector(), fFacingTolerance(0), fNeedWalkingForward(false), fAvatarInVolume(false), diff --git a/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h b/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h index 8333b663..f2fa65ea 100644 --- a/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h +++ b/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h @@ -73,7 +73,8 @@ public: kTypeBump = 0x20, }; - plCollisionDetector() : fType(0), fTriggered(false), fBumped(false){;} + plCollisionDetector() : fType(0), fTriggered(false), fBumped(false){ } + plCollisionDetector(int8_t type) : fType(type), fTriggered(false), fBumped(false) { } virtual ~plCollisionDetector(){;} virtual hsBool MsgReceive(plMessage* msg); @@ -90,48 +91,26 @@ public: // sub type for object-in-volume detectors class plObjectInVolumeDetector : public plCollisionDetector { -public: - class plCollisionBookKeepingInfo - { - friend class plObjectInVolumeDetector; - public: - plCollisionBookKeepingInfo(plKey& hit) - { - hitter=hit; - enters=0; - exits=0; - } - ~plCollisionBookKeepingInfo() - { - hitter=nil; - } - protected: - plKey hitter; - int enters,exits; - bool fSubStepCurState; - }; protected: virtual void ITrigger(plKey hitter, bool entering, bool immediate=false); - //virtual void ISendSavedTriggerMsgs(); - virtual void IHandleEval(plEvalMsg* pEval); - bool fWaitingForEval; + virtual void ISendSavedTriggerMsgs(); plActivatorMsg* fSavedActivatorMsg; - - typedef std::list bookKeepingList; - bookKeepingList fCollisionList; - typedef std::set ResidentSet; - ResidentSet fCurrentResidents; + uint32_t fNumEvals; + uint32_t fLastEnterEval; + uint32_t fLastExitEval; public: - plObjectInVolumeDetector() - { - fWaitingForEval=false;fSavedActivatorMsg=nil; - - } - plObjectInVolumeDetector(int8_t i){fType = i;fWaitingForEval=false;fSavedActivatorMsg=nil;} - virtual ~plObjectInVolumeDetector(){;} + plObjectInVolumeDetector() + : plCollisionDetector(), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0) + { } + + plObjectInVolumeDetector(int8_t type) + : plCollisionDetector(type), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0) + { } + + virtual ~plObjectInVolumeDetector() { } virtual hsBool MsgReceive(plMessage* msg); @@ -177,23 +156,23 @@ public: class plCameraRegionDetector : public plObjectInVolumeDetector { protected: - hsTArray fMessages; + typedef std::vector plCameraMsgVec; + + plCameraMsgVec fMessages; bool fIsInside; bool fSavingSendMsg; bool fSavedMsgEnterFlag; - int fNumEvals; - int fLastEnterEval; - int fLastExitEval; virtual void ITrigger(plKey hitter, bool entering, bool immediate=false); virtual void ISendSavedTriggerMsgs(); - virtual void IHandleEval(plEvalMsg* pEval); public: - plCameraRegionDetector(){ fIsInside = false; fSavingSendMsg = false; } + plCameraRegionDetector() + : plObjectInVolumeDetector(), fIsInside(false), fSavingSendMsg(false) + { } ~plCameraRegionDetector(); virtual hsBool MsgReceive(plMessage* msg); - void AddMessage(plCameraMsg* pMsg) { fMessages.Append(pMsg); } + void AddMessage(plCameraMsg* pMsg) { fMessages.push_back(pMsg); } CLASSNAME_REGISTER( plCameraRegionDetector ); GETINTERFACE_ANY( plCameraRegionDetector, plCollisionDetector );