GRIM: Make an actor orient its pitch and roll too if requested. Fix #368

This commit is contained in:
Giulio Camuffo 2013-01-13 10:54:36 +01:00
parent 71b528d933
commit 3b9a59dc93
3 changed files with 90 additions and 33 deletions

View File

@ -459,11 +459,48 @@ void Actor::setPos(const Math::Vector3d &position) {
}
}
Math::Vector3d Actor::actorForward() const {
if (g_grim->getGameType() == GType_GRIM) {
return Math::Vector3d(0.f, 1.f, 0.f);
}
return Math::Vector3d(0.f, 0.f, 1.f);
}
Math::Vector3d Actor::actorUp() const {
if (g_grim->getGameType() == GType_GRIM) {
return Math::Vector3d(0.f, 0.f, 1.f);
}
return Math::Vector3d(0.f, 1.f, 0.f);
}
void Actor::turnTo(const Math::Vector3d &pos) {
Math::Vector3d lookVector = pos - _pos;
lookVector.normalize();
Math::Vector3d up = actorUp();
if (_puckOrient) {
Sector *s = NULL;
g_grim->getCurrSet()->findClosestSector(_pos, &s, NULL);
if (s) {
up = s->getNormal();
}
}
Math::Matrix4 m;
m.buildFromTargetDir(actorForward(), lookVector, actorUp(), up);
if (_puckOrient) {
turnTo(m.getPitch(), m.getYaw(), m.getRoll());
} else {
turnTo(_pitch, m.getYaw(), _roll);
}
}
void Actor::turnTo(const Math::Angle &pitchParam, const Math::Angle &yawParam, const Math::Angle &rollParam) {
_pitch = pitchParam;
_roll = rollParam;
_movePitch = pitchParam;
_moveRoll = rollParam;
_moveYaw = yawParam;
if (_yaw != yawParam) {
if (_yaw != yawParam || _pitch != pitchParam || _roll != rollParam) {
_turning = true;
} else
_turning = false;
@ -1216,15 +1253,33 @@ void Actor::updateWalk() {
}
}
destPos = handleCollisionTo(_pos, destPos);
Math::Angle y = getYawTo(destPos);
turnTo(_pitch, y, _roll);
turnTo(destPos);
dir = destPos - _pos;
dir.normalize();
_pos += dir * walkAmt;
}
static int animTurn(float turnAmt, const Math::Angle &dest, Math::Angle *cur) {
Math::Angle d = dest - *cur;
d.normalize(-180);
// If the actor won't turn because the rate is set to zero then
// have the actor turn all the way to the destination yaw.
// Without this some actors will lock the interface on changing
// scenes, this affects the Bone Wagon in particular.
if (turnAmt == 0 || turnAmt >= fabsf(d.getDegrees())) {
*cur = dest;
} else if (d > 0) {
*cur += turnAmt;
} else {
*cur -= turnAmt;
}
if (d != 0) {
return (d > 0 ? 1 : -1);
}
return 0;
}
void Actor::update(uint frameTime) {
// Snap actor to walkboxes if following them. This might be
// necessary for example after activating/deactivating
@ -1234,23 +1289,12 @@ void Actor::update(uint frameTime) {
}
if (_turning) {
float turnAmt = g_grim->getPerSecond(_turnRate) * 5.f;
Math::Angle dyaw = _moveYaw - _yaw;
dyaw.normalize(-180);
// If the actor won't turn because the rate is set to zero then
// have the actor turn all the way to the destination yaw.
// Without this some actors will lock the interface on changing
// scenes, this affects the Bone Wagon in particular.
if (turnAmt == 0 || turnAmt >= fabsf(dyaw.getDegrees())) {
setYaw(_moveYaw);
float turnAmt = g_grim->getPerSecond(_turnRate)*5;
_currTurnDir = animTurn(turnAmt, _moveYaw, &_yaw);
int p = animTurn(turnAmt, _movePitch, &_pitch);
int r = animTurn(turnAmt, _moveRoll, &_roll);
if (_currTurnDir == 0 && p == 0 && r == 0) {
_turning = false;
} else if (dyaw > 0) {
setYaw(_yaw + turnAmt);
} else {
setYaw(_yaw - turnAmt);
}
if (dyaw != 0) {
_currTurnDir = (dyaw > 0 ? 1 : -1);
}
}

View File

@ -183,6 +183,16 @@ public:
* @see isTurning
*/
void turnTo(const Math::Angle &pitch, const Math::Angle &yaw, const Math::Angle &roll);
/**
* Turn the actor towards a point in space.
* The effect is not immediate, the actor will slowly rotate
* to the destination orientation.
*
* @param pos The position the actor should turn to.
* @see turnTo
* @see setRot
*/
void turnTo(const Math::Vector3d &pos);
/**
* Returns true if the actor is turning.
*
@ -472,6 +482,15 @@ public:
void detach();
Math::Quaternion getRotationQuat() const;
/**
* Returns the forward direction in the local space of the actor.
*/
Math::Vector3d actorForward() const;
/**
* Returns the up direction in the local space of the actor.
*/
Math::Vector3d actorUp() const;
void setInOverworld(bool inOverworld) { _inOverworld = inOverworld; }
bool isInOverworld() { return _inOverworld; }
@ -537,6 +556,8 @@ private:
// turning animation while still allowing the actor to move in a
// new direction immediately after reflecting off a wall.
Math::Angle _moveYaw;
Math::Angle _movePitch;
Math::Angle _moveRoll;
// Variables for walking to a point
bool _walking;

View File

@ -1173,20 +1173,12 @@ void Lua_V1::TurnActorTo() {
z = lua_getnumber(zObj);
}
// TODO turning stuff below is not complete
// Find the vector pointing from the actor to the desired location
Math::Vector3d turnToVector(x, y, z);
Math::Vector3d lookVector = turnToVector - actor->getPos();
// find the angle the requested position is around the unit circle
Math::Angle yaw = lookVector.unitCircleAngle();
// yaw is offset from forward by 90 degrees
yaw -= 90.0f;
actor->turnTo(0, yaw, 0);
actor->turnTo(turnToVector);
// Return true if the actor is still turning and its yaw is not the target one.
// Return true if the actor is still turning
// This allows manny to have the right yaw when he exits the elevator in the garage
pushbool(actor->getYaw() != yaw);
pushbool(actor->isTurning());
}
void Lua_V1::PointActorAt() {