void Controller::move(SweptVolume& volume, const NxVec3& disp, NxU32 activeGroups, NxF32 minDist, NxU32& collisionFlags, NxF32 sharpness, const NxGroupsMask* groupsMask, bool constrainedClimbingMode) { // Dynamic-load the utility library if(!gUtilLib) gUtilLib = NxGetUtilLib(); assert(gUtilLib); if(!gUtilLib) return; SweepTest* ST = &cctModule; // Init CCT with per-controller settings ST->debugData = manager->debugData; ST->mSkinWidth = skinWidth; ST->mStepOffset = stepOffset; ST->mUpDirection = upDirection; ST->mHandleSlope = handleSlope; ST->mSlopeLimit = slopeLimit; ST->mFirstUpdate = true; /////////// Controller** boxUserData = NULL; NxExtendedBounds3* boxes = NULL; NxU32 nbBoxes = 0; Controller** capsuleUserData = NULL; NxExtendedCapsule* capsules = NULL; NxU32 nbCapsules = 0; if(1) { // Experiment - to do better NxU32 nbControllers = manager->getNbControllers(); Controller** controllers = manager->getControllers(); boxes = (NxExtendedBounds3*)NxAlloca(nbControllers*sizeof(NxExtendedBounds3)); capsules = (NxExtendedCapsule*)NxAlloca(nbControllers*sizeof(NxExtendedCapsule)); // It's evil to waste that ram boxUserData = (Controller**)NxAlloca(nbControllers*sizeof(Controller*)); capsuleUserData = (Controller**)NxAlloca(nbControllers*sizeof(Controller*)); while(nbControllers--) { Controller* currentController = *controllers++; if(currentController==this) continue; NxActor* pActor = currentController->getActor(); int nbShapes = pActor->getNbShapes(); NX_ASSERT( nbShapes == 1 ); NxShape* pCurrentShape= pActor->getShapes()[0]; // Depending on user settings the current controller can be: // - discarded // - always kept // - or tested against filtering flags NxCCTInteractionFlag interactionFlag = currentController->getInteraction(); bool keepController = true; if(interactionFlag==NXIF_INTERACTION_EXCLUDE) keepController = false; else if(interactionFlag==NXIF_INTERACTION_USE_FILTER) keepController = (activeGroups & ( 1 << pCurrentShape->getGroup()))!=0; if(keepController) { if(currentController->type==NX_CONTROLLER_BOX) { currentController->getWorldBox(boxes[nbBoxes]); boxUserData[nbBoxes++] = currentController; } else if(currentController->type==NX_CONTROLLER_CAPSULE) { CapsuleController* CC = static_cast<CapsuleController*>(currentController); NxExtendedVec3 p0 = CC->position; NxExtendedVec3 p1 = CC->position; p0[ST->mUpDirection] -= CC->height*0.5f; p1[ST->mUpDirection] += CC->height*0.5f; capsules[nbCapsules].p0 = p0; capsules[nbCapsules].p1 = p1; capsules[nbCapsules].radius = CC->radius; capsuleUserData[nbCapsules++] = currentController; } else ASSERT(0); } } } /////////// ST->mWalkExperiment = false; NxExtendedVec3 Backup = volume.mCenter; ST->MoveCharacter(scene, (Controller*)this, volume, disp, nbBoxes, nbBoxes ? boxes : NULL, nbBoxes ? (const void**)boxUserData : NULL, nbCapsules, nbCapsules ? capsules : NULL, nbCapsules ? (const void**)capsuleUserData : NULL, activeGroups, minDist, collisionFlags, groupsMask, constrainedClimbingMode); if(ST->mHitNonWalkable) { // A bit slow, but everything else I tried was less convincing... ST->mWalkExperiment = true; volume.mCenter = Backup; ST->MoveCharacter(scene, (Controller*)this, volume, disp, nbBoxes, nbBoxes ? boxes : NULL, nbBoxes ? (const void**)boxUserData : NULL, nbCapsules, nbCapsules ? capsules : NULL, nbCapsules ? (const void**)capsuleUserData : NULL, activeGroups, minDist, collisionFlags, groupsMask, constrainedClimbingMode); ST->mWalkExperiment = false; } if(sharpness<0.0f) volume.mCenter = Backup; // Copy results back position = volume.mCenter; NxVec3 Delta = Backup - volume.mCenter; NxF32 deltaM2 = Delta.magnitudeSquared(); if(deltaM2!=0.0f) { // Update kinematic actor if(kineActor) kineActor->moveGlobalPosition(NxVec3((float)position.x, (float)position.y, (float)position.z)); } filteredPosition = position; sharpness = fabsf(sharpness); // Apply feedback filter if needed if(sharpness<1.0f) filteredPosition[upDirection] = feedbackFilter(position[upDirection], memory, sharpness); // if(manager->debugData) // manager->debugData->addAABB(cctModule.mCachedTBV, NX_ARGB_YELLOW); }
//---------------------------------------------------------------------------- bool Input::update( void) { // XTRACE(); bool isDown; Trigger trigger; static float nextTime = Timer::getTime()+0.5f; float thisTime = Timer::getTime(); if( thisTime > nextTime) { updateMouseSettings(); nextTime = thisTime+0.5f; } _valDX = 0.0f; _valDY = 0.0f; while( tryGetTrigger( trigger, isDown)) { if( trigger.type == eUnknownTrigger) { //for unkown trigger we don't need to do a lookup continue; } if( _interceptor) { //feed trigger to interceptor instead of normal callback mechanism _interceptor->input( trigger, isDown); continue; } if( !_bindMode) { //find callback for this trigger //i.e. the action bound to this key Callback * cb = findHash( trigger, _callbackMap); if( cb) { // LOG_INFO << "Callback for [" << cb->getActionName() << "]" << endl; cb->performAction( trigger, isDown); } } else if( _callback && (trigger.type!=eMotionTrigger)) { //Note: motion triggers can't be bound //we are in bind-mode, so bind this trigger to callback bind( trigger, _callback); //go back to normal mode _bindMode = false; } else if( !_callback) { LOG_ERROR << "Input is in bind mode, but callback is 0" << endl; _bindMode = false; } } _valDX = feedbackFilter( _valDX, _dampVal, _memoryDX); _valDY = feedbackFilter( _valDY, _dampVal, _memoryDY); if( (fabs(_valDX)>1.0e-10) || (fabs(_valDY)>1.0e-10)) { trigger.type = eMotionTrigger; trigger.fData1 = _valDX; trigger.fData2 = _valDY; if( _interceptor) { //feed trigger to interceptor instead of normal callback mechanism _interceptor->input( trigger, true); } else { Callback * cb = findHash( trigger, _callbackMap); if( cb) { // LOG_INFO << "Callback for [" << cb->getActionName() << "]" << endl; cb->performAction( trigger, isDown); } } } return true; }