scummvm/matrix3.cpp

182 lines
4.0 KiB
C++
Raw Normal View History

// Residual - Virtual machine to run LucasArts' 3D adventure games
2005-01-01 10:23:18 +00:00
// Copyright (C) 2003-2005 The ScummVM-Residual Team (www.scummvm.org)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "matrix3.h"
2005-01-01 12:27:57 +00:00
#include <math.h>
2004-02-25 08:45:56 +00:00
void Matrix3::setAsIdentity() {
2004-12-09 23:55:43 +00:00
_right.set(1.f, 0.f, 0.f);
_up.set(0.f, 1.f, 0.f);
_at.set(0.f, 0.f, 0.f);
}
2004-02-25 08:45:56 +00:00
void Matrix3::buildFromPitchYawRoll(float pitch, float yaw, float roll) {
Matrix3 temp1, temp2;
2004-02-25 08:45:56 +00:00
temp1.constructAroundPitch(pitch);
constructAroundRoll(roll);
(*this) *= temp1;
2004-02-25 08:45:56 +00:00
temp2.constructAroundYaw(yaw);
(*this) *= temp2;
}
2004-02-25 08:45:56 +00:00
#define MYPI 3.14159265358979323846
#define DEGTORAD(a) (a * MYPI / 180.0)
#define RADTODEG(a) (a * 180.0 / MYPI)
2004-02-25 08:45:56 +00:00
float RadianToDegree(float rad) {
2004-10-06 18:59:23 +00:00
return (float)RADTODEG(rad);
}
2004-02-25 08:45:56 +00:00
float DegreeToRadian(float degrees) {
2004-10-06 18:59:23 +00:00
return (float)DEGTORAD(degrees);
}
// right
2004-02-25 08:45:56 +00:00
void Matrix3::constructAroundPitch(float pitch) {
float cosa;
float sina;
2004-02-25 08:45:56 +00:00
cosa = (float)cos(DegreeToRadian(pitch));
sina = (float)sin(DegreeToRadian(pitch));
2004-12-09 23:55:43 +00:00
_right.set(1.f, 0.f, 0.f);
_up.set(0.f, cosa, -sina);
_at.set(0.f, sina, cosa);
}
// up
2004-02-25 08:45:56 +00:00
void Matrix3::constructAroundYaw(float yaw) {
float cosa;
float sina;
2004-02-25 08:45:56 +00:00
cosa = (float)cos(DegreeToRadian(yaw));
sina = (float)sin(DegreeToRadian(yaw));
2004-12-09 23:55:43 +00:00
_right.set(cosa, 0.f, sina);
_up.set(0.f, 1.f, 0.f);
_at.set(-sina, 0.f, cosa);
}
// at
2004-02-25 08:45:56 +00:00
void Matrix3::constructAroundRoll(float roll) {
float cosa;
float sina;
2004-02-25 08:45:56 +00:00
cosa = (float)cos(DegreeToRadian(roll));
sina = (float)sin(DegreeToRadian(roll));
2004-12-09 23:55:43 +00:00
_right.set(cosa, -sina, 0.f);
_up.set(sina, cosa, 0.f);
_at.set(0.f, 0.f, 1.f);
}
/*
0 1 2 3
4 5 6 7
8 9 10 11
*/
// WARNING: Still buggy in some occasions.
2004-02-25 08:45:56 +00:00
void Matrix3::getPitchYawRoll(float* pPitch, float* pYaw, float* pRoll) {
float D;
float C;
float ftrx;
float ftry;
float angle_x;
float angle_y;
float angle_z;
2004-12-09 23:55:43 +00:00
angle_y = D = asin(_right.z()); /* Calculate Y-axis angle */
2004-02-25 08:45:56 +00:00
C = cos(angle_y);
angle_y = RadianToDegree(angle_y);
2004-02-25 08:45:56 +00:00
if (fabs( C ) > 0.005) { /* Gimball lock? */
2004-12-09 23:55:43 +00:00
ftrx = _at.z() / C; /* No, so get X-axis angle */
ftry = -_up.z() / C;
2004-12-09 23:55:43 +00:00
angle_x = RadianToDegree(atan2(ftry, ftrx));
2004-12-09 23:55:43 +00:00
ftrx = _right.x() / C; /* Get Z-axis angle */
ftry = -_right.y() / C;
2004-12-09 23:55:43 +00:00
angle_z = RadianToDegree(atan2(ftry, ftrx));
} else { /* Gimball lock has occurred */
angle_x = 0; /* Set X-axis angle to zqero */
2004-12-09 23:55:43 +00:00
ftrx = _up.y(); /* And calculate Z-axis angle */
ftry = _up.x();
2004-02-25 08:45:56 +00:00
angle_z = RadianToDegree(atan2(ftry, ftrx));
}
/* return only positive angles in [0,360] */
if (angle_x < 0) angle_x += 360;
if (angle_y < 0) angle_y += 360;
if (angle_z < 0) angle_z += 360;
2004-12-09 23:55:43 +00:00
if (pPitch)
*pPitch = angle_x;
2004-12-09 23:55:43 +00:00
if (pYaw)
*pYaw = angle_y;
2004-12-09 23:55:43 +00:00
if (pRoll)
*pRoll = angle_z;
}
float Matrix3::getPitch() {
float pitch;
2004-02-25 08:45:56 +00:00
getPitchYawRoll(&pitch, 0, 0);
return pitch;
}
float Matrix3::getYaw() {
float yaw;
2004-02-25 08:45:56 +00:00
getPitchYawRoll(0, &yaw, 0);
return yaw;
}
float Matrix3::getRoll() {
float roll;
2004-02-25 08:45:56 +00:00
getPitchYawRoll(0, 0, &roll);
return roll;
}
2004-02-25 08:45:56 +00:00
void Matrix3::transform(Vector3d* v) {
float x;
float y;
float z;
2004-12-09 23:55:43 +00:00
x = v->dotProduct(_right.x(), _up.x(), _at.x());
y = v->dotProduct(_right.x(), _up.x(), _at.x());
z = v->dotProduct(_right.x(), _up.x(), _at.x());
2004-02-25 08:45:56 +00:00
v->set(x, y, z);
}
2003-08-28 02:01:48 +00:00