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);
  }
Beispiel #2
0
	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;
	}