|
|
|
@ -130,31 +130,52 @@ namespace MWWorld
|
|
|
|
|
position.z += halfExtents.z;
|
|
|
|
|
|
|
|
|
|
waterlevel -= halfExtents.z * 0.5;
|
|
|
|
|
/*
|
|
|
|
|
* A 3/4 submerged example
|
|
|
|
|
*
|
|
|
|
|
* +---+
|
|
|
|
|
* | |
|
|
|
|
|
* | | <- (original waterlevel)
|
|
|
|
|
* | |
|
|
|
|
|
* | | <- position <- waterlevel
|
|
|
|
|
* | |
|
|
|
|
|
* | |
|
|
|
|
|
* | |
|
|
|
|
|
* +---+ <- (original position)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
OEngine::Physic::ActorTracer tracer;
|
|
|
|
|
bool wasOnGround = false;
|
|
|
|
|
bool isOnGround = false;
|
|
|
|
|
Ogre::Vector3 inertia(0.0f);
|
|
|
|
|
Ogre::Vector3 velocity;
|
|
|
|
|
if(position.z < waterlevel || isFlying)
|
|
|
|
|
|
|
|
|
|
bool canWalk = ptr.getClass().canWalk(ptr);
|
|
|
|
|
bool isBipedal = ptr.getClass().isBipedal(ptr);
|
|
|
|
|
bool isNpc = ptr.getClass().isNpc();
|
|
|
|
|
|
|
|
|
|
if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly
|
|
|
|
|
{
|
|
|
|
|
// TODO: Shouldn't water have higher drag in calculating velocity?
|
|
|
|
|
velocity = (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(refpos.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)) * movement;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
velocity = Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * movement;
|
|
|
|
|
// not in water nor can fly, so need to deal with gravity
|
|
|
|
|
if(!physicActor->getOnGround())
|
|
|
|
|
{
|
|
|
|
|
// If falling, add part of the incoming velocity with the current inertia
|
|
|
|
|
velocity = velocity*time + physicActor->getInertialForce();
|
|
|
|
|
velocity = velocity * time + physicActor->getInertialForce();
|
|
|
|
|
}
|
|
|
|
|
inertia = velocity;
|
|
|
|
|
inertia = velocity; // REM velocity is for z axis only in this code block
|
|
|
|
|
|
|
|
|
|
if(!(movement.z > 0.0f))
|
|
|
|
|
{
|
|
|
|
|
wasOnGround = physicActor->getOnGround();
|
|
|
|
|
tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,2), engine);
|
|
|
|
|
// TODO: Find out if there is a significance with the value 2 used here
|
|
|
|
|
tracer.doTrace(colobj, position, position - Ogre::Vector3(0,0,2), engine);
|
|
|
|
|
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
|
|
|
|
|
isOnGround = true;
|
|
|
|
|
}
|
|
|
|
@ -163,24 +184,38 @@ namespace MWWorld
|
|
|
|
|
if(isOnGround)
|
|
|
|
|
{
|
|
|
|
|
// if we're on the ground, don't try to fall
|
|
|
|
|
velocity.z = std::max(0.0f, velocity.z);
|
|
|
|
|
velocity.z = std::max(0.0f, velocity.z); // NOTE: two different velocity assignments above
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ogre::Vector3 newPosition = position;
|
|
|
|
|
/*
|
|
|
|
|
* A loop to find newPosition using tracer, if successful different from the starting position.
|
|
|
|
|
* nextpos is the local variable used to find potential newPosition, using velocity and remainingTime
|
|
|
|
|
* The initial velocity was set earlier (see above).
|
|
|
|
|
*/
|
|
|
|
|
float remainingTime = time;
|
|
|
|
|
for(int iterations = 0;iterations < sMaxIterations && remainingTime > 0.01f;++iterations)
|
|
|
|
|
for(int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f; ++iterations)
|
|
|
|
|
{
|
|
|
|
|
Ogre::Vector3 nextpos = newPosition + velocity*remainingTime;
|
|
|
|
|
|
|
|
|
|
if(newPosition.z < waterlevel && !isFlying &&
|
|
|
|
|
nextpos.z > waterlevel && newPosition.z <= waterlevel)
|
|
|
|
|
Ogre::Vector3 nextpos = newPosition + velocity * remainingTime;
|
|
|
|
|
|
|
|
|
|
// If not able to fly, walk or bipedal don't allow to move out of water
|
|
|
|
|
// TODO: this if condition may not work for large creatures or situations
|
|
|
|
|
// where the creature gets above the waterline for some reason
|
|
|
|
|
if(newPosition.z < waterlevel && // started 3/4 under water
|
|
|
|
|
!isFlying && // can't fly
|
|
|
|
|
!canWalk && // can't walk
|
|
|
|
|
!isBipedal && // not bipedal (assume bipedals can walk)
|
|
|
|
|
!isNpc && // FIXME: shouldn't really need this
|
|
|
|
|
nextpos.z > waterlevel && // but about to go above water
|
|
|
|
|
newPosition.z <= waterlevel)
|
|
|
|
|
{
|
|
|
|
|
const Ogre::Vector3 down(0,0,-1);
|
|
|
|
|
Ogre::Real movelen = velocity.normalise();
|
|
|
|
|
Ogre::Vector3 reflectdir = velocity.reflect(down);
|
|
|
|
|
reflectdir.normalise();
|
|
|
|
|
velocity = slide(reflectdir, down)*movelen;
|
|
|
|
|
continue;
|
|
|
|
|
// NOTE: remainingTime is unchanged before the loop continues
|
|
|
|
|
continue; // velocity updated, calculate nextpos again
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// trace to where character would go if there were no obstructions
|
|
|
|
@ -189,13 +224,14 @@ namespace MWWorld
|
|
|
|
|
// check for obstructions
|
|
|
|
|
if(tracer.mFraction >= 1.0f)
|
|
|
|
|
{
|
|
|
|
|
newPosition = tracer.mEndPos;
|
|
|
|
|
remainingTime *= (1.0f-tracer.mFraction);
|
|
|
|
|
newPosition = tracer.mEndPos; // ok to move, so set newPosition
|
|
|
|
|
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We hit something. Try to step up onto it.
|
|
|
|
|
if(stepMove(colobj, newPosition, velocity, remainingTime, engine))
|
|
|
|
|
// NOTE: May need to stop slaughterfish step out of the water.
|
|
|
|
|
if((canWalk || isBipedal || isNpc) && stepMove(colobj, newPosition, velocity, remainingTime, engine))
|
|
|
|
|
isOnGround = !(newPosition.z < waterlevel || isFlying); // Only on the ground if there's gravity
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -214,7 +250,7 @@ namespace MWWorld
|
|
|
|
|
|
|
|
|
|
if(isOnGround || wasOnGround)
|
|
|
|
|
{
|
|
|
|
|
tracer.doTrace(colobj, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+2.0f), engine);
|
|
|
|
|
tracer.doTrace(colobj, newPosition, newPosition - Ogre::Vector3(0,0,sStepSize+2.0f), engine);
|
|
|
|
|
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
|
|
|
|
|
{
|
|
|
|
|
newPosition.z = tracer.mEndPos.z + 1.0f;
|
|
|
|
@ -236,7 +272,7 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
physicActor->setOnGround(isOnGround);
|
|
|
|
|
|
|
|
|
|
newPosition.z -= halfExtents.z;
|
|
|
|
|
newPosition.z -= halfExtents.z; // remove what was added at the beggining
|
|
|
|
|
return newPosition;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|