Ogre::Vector3 CharacterController::_collideWithWorld(int recursionDepth, const Ogre::Vector3& pos, const Ogre::Vector3& vel, CollisionPacket& colData, bool gravityStep, const Ogre::Degree& slopeSlideThresold) { // do we need to worry? if (recursionDepth > 5) return pos; // Ok, we need to worry: colData.velocity = vel; colData.normalizedVelocity = vel; colData.normalizedVelocity.normalise(); colData.basePoint = pos; colData.foundCollision = false; // ---------------------------- // OgreOpcode part begin _doOgreOpcodeCollision(colData, mVeryCloseDistance); // OgreOpcode part end // ---------------------------- // If no collision we just move along the velocity if (colData.foundCollision == false) { return pos + vel; } // *** Collision occured *** // The original destination point Ogre::Vector3 destinationPoint = pos + vel; Ogre::Vector3 newBasePoint = pos; // only update if we are not already very close // and if so we only move very close to intersection..not // to the exact spot. if (colData.nearestDistance >= mVeryCloseDistance) { Ogre::Vector3 V = vel; V.normalise(); V = V * (colData.nearestDistance - mVeryCloseDistance); newBasePoint = colData.basePoint + V; // Adjust polygon intersection point (so sliding // plane will be unaffected by the fact that we // move slightly less than collision tells us) V.normalise(); colData.intersectionPoint -= mVeryCloseDistance * V; } // Determine the sliding plane Ogre::Vector3 slidePlaneOrigin = colData.intersectionPoint; Ogre::Vector3 slidePlaneNormal = newBasePoint - colData.intersectionPoint; slidePlaneNormal.normalise(); Ogre::Plane slidingPlane(slidePlaneNormal, slidePlaneOrigin); Ogre::Vector3 newDestinationPoint = destinationPoint - slidingPlane.getDistance(destinationPoint) * slidePlaneNormal; // Generate the slide vector, which will become our new // velocity vector for the next iteration Ogre::Vector3 newVelocityVector = newDestinationPoint - colData.intersectionPoint; // Recurse: // dont recurse if the new velocity is very small if (newVelocityVector.length() < mVeryCloseDistance) { return newBasePoint; } // simulate "friction" if (gravityStep) { // apply gravity only if slope is steep enough const Ogre::Radian tolerance = Ogre::Radian(slopeSlideThresold); Ogre::Vector3 gravity = vel; gravity.normalise(); if (slidePlaneNormal.directionEquals(-gravity, tolerance)) { return newBasePoint; } } return _collideWithWorld(recursionDepth++, newBasePoint, newVelocityVector, colData, gravityStep, slopeSlideThresold); }
void QCharacterController::update(float delta) { mAccumulation += delta; while(mAccumulation>=mTimeStep) { btVector3 upVectorFinal = QVector3Nx(mPhysicsManager->getLocalGravity(Vector3(NxVector3(mController->getPosition()))));//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition())); NxVec3 GravityVector = upVectorFinal; upVectorFinal.normalize(); upVectorFinal*=-1; bool testing = false; NxVec3 opo = NxVec3(0,0,0); NxVec3 fpo = NxVec3(0,0,0); float abbc = mPhysicsManager->getLocalGravity(NxVector3(mController->getPosition()+mController->getUpVector())).length();//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition()+mController->getUpVector())).magnitude(); q_1 = q_2; if(mController->getUpVector()!=upVectorFinal&&Ogre::Degree(NxVector3(mController->getUpVector()).angleBetween(NxVector3(upVectorFinal)))>Ogre::Degree(0.075f)&&abbc>0.2f) { testing = true; Ogre::Vector3 up1 = NxVector3(mController->getUpVector()); //std::cout<<"pos1: "<<mController->cctp[0]->getPosition().x()<<"\n"; mController->setUpVector(upVectorFinal,mTimeStep); //std::cout<<"pos2: "<<mController->cctp[0]->getPosition().x()<<"\n"; Ogre::Vector3 up2 = NxVector3(mController->getUpVector()); Ogre::Quaternion q2 = up1.getRotationTo(up2,Ogre::Vector3::UNIT_X); q_2 = Quaternion(q2*q_1.toOgre()); } //dnode02->setOrientation(Ogre::Quaternion::IDENTITY); //dnode02->setDirection(NxVector3(mController->getUpVector()),Ogre::SceneNode::TS_LOCAL,Ogre::Vector3::UNIT_Y); opo = mController->position; bool mMidair = false;// = inAir(); float playerSpeed = 0; if(mController->move_) { Ogre::Vector3 v3 = Ogre::Vector3(moveV.x,moveV.y,moveV.z); Ogre::Plane pln = Ogre::Plane(NxVector3(mController->getUpVector()),0); pln.projectVector(v3); v3.normalise(); moveV = Ogre::Vector3(moveV.x,moveV.y,moveV.z); /// run = 6.225 /// walk = 2.225 float spdd = mPlayerSpeedStart*(1-mPlayerSpeedInterpolation)+mPlayerSpeedTop*(mPlayerSpeedInterpolation);//7.0f;//2.225f*(1-runTimer) + 6.225*runTimer if(abbc<0.2) { mController->move(NxVec3(moveV.x,moveV.y,moveV.z)*mTimeStep*spdd,true,mTimeStep,true); } else { //std::cout<<"Try move....\n"; mController->move(NxVec3(moveV.x,moveV.y,moveV.z)*mTimeStep*spdd,true,mTimeStep); } fpo = mController->position; playerSpeed = Ogre::Math::Abs((fpo-opo).length()); //playerMotionDir = NxVector3(fpo-opo); //std::cout<<"Speed: "<<playerSpeed/(gmgr->tmgr->getTimeSpeed()/60.0f)<<"\n"; } else { playerSpeed = 0; //playerMotionDir = Ogre::Vector3(0,0,0); } mMidair = inAir(); float lastSpeed = mPlayerSpeedLast; mPlayerSpeedLast = playerSpeed; if(mPlayerSpeedLast>lastSpeed) { mPlayerSpeedInterpolation+=(mTimeStep/mPlayerSpeedAccel); mGracePeriod = 0; } else if((mPlayerSpeedLast<mPlayerSpeedStart*mTimeStep||mHittingGround)&&!mMidair) { // we give a little bit of padding so if a gravity issue ir something stops it for a frame // it doesn't slow abruptly. ++mGracePeriod; if(mGracePeriod>=2) { mPlayerSpeedInterpolation=0; } } else { mGracePeriod = 0; } if(mMidair) { //mPlayerSpeedLast = 0; } if(mPlayerSpeedInterpolation<0) { mPlayerSpeedInterpolation = 0; } if(mPlayerSpeedInterpolation>1) { mPlayerSpeedInterpolation = 1; } NxVec3 gravityCont = QVector3Nx(mPhysicsManager->getLocalGravity(NxVector3(mController->getPosition()+mController->getUpVector())))*0.9f;//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition()+mController->getUpVector()))*0.9f; NxVec3 gcN = gravityCont; gcN.normalize(); if(NxVector3(gcN).angleBetween(Ogre::Vector3(0,1,0))<Ogre::Degree(1)) { gravityCont = NxVec3(0,1,0)*gravityCont.length(); } if(NxVector3(gcN).angleBetween(Ogre::Vector3(0,-1,0))<Ogre::Degree(1)) { gravityCont = NxVec3(0,-1,0)*gravityCont.length(); } //||NxVector3(gravityCont).angleBetween(Ogre::Vector3(0,-1,0))<Ogre::Degree(1)) if(mIsJumping) { gravityCont = gravityCont - gravityCont*mJumpFactor; mJumpFactor -= 1.f*static_cast<Real>(mTimeStep); if(mJumpFactor<0) { mJumpFactor = 0; mIsJumping = false; } } NxVec3 ogp = mController->getPosition(); float ff = 1.0; if(testing ) { ff=0.5f*(1-mController->mUpInterp)+(mController->mUpInterp*1.0f); mPlayerGravityInterpolation = mPlayerGravityInterpolation/5; } if(abbc>0.2f) { mController->move(ff*((gravityCont*(mPlayerGravityBase*(1-mPlayerGravityInterpolation)+mPlayerGravityTerminal*(mPlayerGravityInterpolation)))*mTimeStep),false,mTimeStep); } NxVec3 pogp = mController->getPosition(); float lastGravity = mPlayerGravityLast; mPlayerGravityLast = btVector3(ogp-pogp).length(); if(mMidair&&!mHittingGround) { mGroundImpact = mPlayerGravityLast/mTimeStep*1.45f; } if(mPlayerGravityLast>lastGravity) { mPlayerGravityInterpolation+=(mTimeStep/mPlayerGravityAccel); } else if(mPlayerGravityLast<mPlayerGravityBase*mTimeStep) { mPlayerGravityInterpolation=0; } if(mPlayerGravityInterpolation<0) { mPlayerGravityInterpolation = 0; } if(mPlayerGravityInterpolation>1) { mPlayerGravityInterpolation = 1; } if(mIsJumping&&mJumpFactor>1) { NxVec3 fgp = mController->getPosition(); Ogre::Vector3 dirT = NxVector3(fgp-ogp); dirT.normalise(); Ogre::Vector3 upVC = NxVector3(gravityCont*mTimeStep*ff); upVC.normalise(); if(!dirT.directionEquals(upVC,Ogre::Radian(Ogre::Degree(45.0f)))) { mJumpFactor = 1; } } //Ogre::Vector3 pMoDir = NxVector3(opo - player->position); // takes gravity into account //Ogre::Vector3 velocity = pMoDir/deltaTT; //float vel[] = {velocity.x,velocity.y,velocity.z}; //alListenerfv(AL_VELOCITY,vel); if(mCrouching) { if(mCrouched) { float oldCrouch = mController->offset; mCrouchLevel+=mTimeStep*1.f; if(mCrouchLevel>mOffset) { mCrouchLevel = mOffset; mCrouched = false; mCrouching = false; } mController->offset = mCrouchLevel; if(!mController->setPosition(mController->getPosition(),false,mController->getUpVector(),false)) { mController->offset = oldCrouch; mCrouchLevel = oldCrouch; } else { } } else { float oldCrouch = mController->offset; mCrouchLevel-=mTimeStep*0.5f; if(mCrouchLevel<0.06f) { mCrouchLevel = 0.06f; mCrouched = true; mCrouching = false; } mController->offset = mCrouchLevel; if(!mController->setPosition(mController->getPosition(),false,mController->getUpVector(),false)) { mController->offset = oldCrouch; mCrouchLevel = oldCrouch; } else { } } } if(mInAirLast2&&!mHittingGround) { mHittingGround = true; if(mGroundImpact>0.05&&false) { mGroundImpactSpd = mGroundImpact; mGroundImpact/=40.f; } else { mHittingGround = false; mGroundImpactSpd = 0.f; mGroundImpact = 0.f; } //mGroundImpact } if(mImpactLevel>0) { //float recoverSpeed = 1.0f; mImpactLevel-=mTimeStep*1.6f; if(mImpactLevel<0) { mImpactLevel = 0; } } if(mHittingGround) { float spdC = 1.0f; spdC = 0.9f*((mGroundImpact/(mGroundImpactSpd/40)))+(0.095f*(1-(mGroundImpact/(mGroundImpactSpd/40)))); mImpactLevel+=mTimeStep*mGroundImpactSpd*spdC; if(mImpactLevel>0.8f) { mImpactLevel = 0.8f; } mGroundImpact-=mTimeStep*(mGroundImpactSpd*0.5f)*spdC; if(mGroundImpact<0) { mGroundImpact = 0; mHittingGround = false; } } if(mBobSwap) { if(!mMidair) mBobPeriod+=mPlayerSpeedLast*1.2f; } else { if(!mMidair) mBobPeriod-=mPlayerSpeedLast*1.2f; } if(abs(mBobPeriod)>=1.0f) { if(mBobPeriod>0) { mBobPeriod = 0.99f; } else { mBobPeriod = -0.99f; mBobLR = !mBobLR; if(mBobLRPeriod>0) { mBobLRPeriod = 1.99f; } else { mBobLRPeriod = -1.99f; } } mBobSwap = !mBobSwap; } NxVec3 upvv = mController->getUpVector(); upvv*=(mImpactLevel+mBobPeriod*0.f); Vector3 right1 = Ogre::Root::getSingletonPtr()->getSceneManager("mSceneManager")->getCamera("mMainCam")->getDerivedRight(); if(mBobLR) { if(!mMidair) mBobLRPeriod -= mPlayerSpeedLast*1.2f; } else { if(!mMidair) mBobLRPeriod += mPlayerSpeedLast*1.2f; } if(mBobLRPeriod>0) { right1*=(0.0625f*((mBobLRPeriod))); } else { right1*=(0.0625f*((mBobLRPeriod))); } right1*=0; p_2 = p_1; //p_1 = Vector3(mController->getEyePosition().x(),mController->getEyePosition().y(),mController->getEyePosition().z()); p_1 = Vector3(mController->getEyePosition().x()-upvv.x()-right1.x,mController->getEyePosition().y()-upvv.y()-right1.y,mController->getEyePosition().z()-upvv.z()-right1.z); // if our speed has gone up then increment the interpolation thingy mAccumulation -= mTimeStep; } mInterpolation = mAccumulation/mTimeStep; }