EMI: Refactor to use a matrix for the camera.

This commit is contained in:
Joseph Jezak 2014-08-05 15:43:39 -04:00
parent 94dd10cb11
commit ff9f26981c
10 changed files with 109 additions and 93 deletions

View file

@ -47,7 +47,7 @@ namespace Grim {
GfxBase::GfxBase() :
_renderBitmaps(true), _renderZBitmaps(true), _shadowModeActive(false),
_currentPos(0, 0, 0), _currentQuat(0, 0, 0, 1), _dimLevel(0.0f),
_currentPos(0, 0, 0), _dimLevel(0.0f),
_screenWidth(0), _screenHeight(0), _isFullscreen(false),
_scaleW(1.0f), _scaleH(1.0f), _currentShadowArray(nullptr),
_shadowColorR(255), _shadowColorG(255), _shadowColorB(255) {

View file

@ -105,6 +105,7 @@ public:
virtual void setupCameraFrustum(float fov, float nclip, float fclip) = 0;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) = 0;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) = 0;
virtual Math::Matrix4 getModelView() = 0;
virtual Math::Matrix4 getProjection() = 0;
@ -299,7 +300,7 @@ protected:
bool _shadowModeActive;
Graphics::PixelFormat _pixelFormat;
Math::Vector3d _currentPos;
Math::Quaternion _currentQuat;
Math::Matrix4 _currentRot;
float _dimLevel;
};

View file

@ -240,23 +240,22 @@ void GfxOpenGL::setupCameraFrustum(float fov, float nclip, float fclip) {
}
void GfxOpenGL::positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) {
if (g_grim->getGameType() == GType_MONKEY4) {
glScaled(1, 1, -1);
Math::Vector3d up_vec(0, 0, 1);
_currentPos = pos;
_currentQuat = Math::Quaternion(interest.x(), interest.y(), interest.z(), roll);
} else {
Math::Vector3d up_vec(0, 0, 1);
glRotatef(roll, 0, 0, -1);
glRotatef(roll, 0, 0, -1);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
Math::Matrix4 lookMatrix = Math::makeLookAtMatrix(pos, interest, up_vec);
glMultMatrixf(lookMatrix.getData());
glTranslated(-pos.x(), -pos.y(), -pos.z());
}
Math::Matrix4 lookMatrix = Math::makeLookAtMatrix(pos, interest, up_vec);
glMultMatrixf(lookMatrix.getData());
glTranslated(-pos.x(), -pos.y(), -pos.z());
}
void GfxOpenGL::positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) {
glScaled(1, 1, -1);
_currentPos = pos;
_currentRot = rot;
}
Math::Matrix4 GfxOpenGL::getModelView() {
@ -266,8 +265,7 @@ Math::Matrix4 GfxOpenGL::getModelView() {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
Math::Matrix4 worldRot = _currentQuat.toMatrix();
glMultMatrixf(worldRot.getData());
glMultMatrixf(_currentRot.getData());
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
glGetFloatv(GL_MODELVIEW_MATRIX, modelView.getData());
@ -508,7 +506,7 @@ void GfxOpenGL::getActorScreenBBox(const Actor *actor, Common::Point &p1, Common
// Set up the camera coordinate system
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
Math::Matrix4 worldRot = _currentQuat.toMatrix();
Math::Matrix4 worldRot = _currentRot;
glMultMatrixf(worldRot.getData());
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
@ -568,8 +566,7 @@ void GfxOpenGL::startActorDraw(const Actor *actor) {
if (g_grim->getGameType() == GType_MONKEY4 && !actor->isInOverworld()) {
// Apply the view transform.
Math::Matrix4 worldRot = _currentQuat.toMatrix();
glMultMatrixf(worldRot.getData());
glMultMatrixf(_currentRot.getData());
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
}
@ -684,8 +681,7 @@ void GfxOpenGL::drawShadowPlanes() {
if (g_grim->getGameType() == GType_MONKEY4) {
// Apply the view transform.
Math::Matrix4 worldRot = _currentQuat.toMatrix();
glMultMatrixf(worldRot.getData());
glMultMatrixf(_currentRot.getData());
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
}

View file

@ -51,6 +51,7 @@ public:
void setupCameraFrustum(float fov, float nclip, float fclip) override;
void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) override;
void positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) override;
Math::Matrix4 getModelView() override;
Math::Matrix4 getProjection() override;

View file

@ -437,39 +437,39 @@ void GfxOpenGLS::setupCameraFrustum(float fov, float nclip, float fclip) {
}
void GfxOpenGLS::positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) {
Math::Matrix4 viewMatrix = makeRotationMatrix(Math::Angle(roll), Math::Vector3d(0, 0, 1));
Math::Vector3d up_vec(0, 0, 1);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
Math::Matrix4 lookMatrix = makeLookMatrix(pos, interest, up_vec);
_viewMatrix = viewMatrix * lookMatrix;
_viewMatrix.transpose();
}
void GfxOpenGLS::positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) {
Math::Matrix4 projMatrix = _projMatrix;
projMatrix.transpose();
if (g_grim->getGameType() == GType_MONKEY4) {
_currentPos = pos;
_currentQuat = Math::Quaternion(interest.x(), interest.y(), interest.z(), roll);
_currentPos = pos;
_currentRot = rot;
Math::Matrix4 invertZ;
invertZ(2, 2) = -1.0f;
Math::Matrix4 invertZ;
invertZ(2, 2) = -1.0f;
Math::Matrix4 viewMatrix = _currentQuat.toMatrix();
viewMatrix.transpose();
Math::Matrix4 viewMatrix = _currentRot;
viewMatrix.transpose();
Math::Matrix4 camPos;
camPos(0, 3) = -_currentPos.x();
camPos(1, 3) = -_currentPos.y();
camPos(2, 3) = -_currentPos.z();
Math::Matrix4 camPos;
camPos(0, 3) = -_currentPos.x();
camPos(1, 3) = -_currentPos.y();
camPos(2, 3) = -_currentPos.z();
_viewMatrix = invertZ * viewMatrix * camPos;
_mvpMatrix = projMatrix * _viewMatrix;
_viewMatrix.transpose();
} else {
Math::Matrix4 viewMatrix = makeRotationMatrix(Math::Angle(roll), Math::Vector3d(0, 0, 1));
Math::Vector3d up_vec(0, 0, 1);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
Math::Matrix4 lookMatrix = makeLookMatrix(pos, interest, up_vec);
_viewMatrix = viewMatrix * lookMatrix;
_viewMatrix.transpose();
}
_viewMatrix = invertZ * viewMatrix * camPos;
_mvpMatrix = projMatrix * _viewMatrix;
_viewMatrix.transpose();
}
@ -478,7 +478,7 @@ Math::Matrix4 GfxOpenGLS::getModelView() {
Math::Matrix4 invertZ;
invertZ(2, 2) = -1.0f;
Math::Matrix4 viewMatrix = _currentQuat.toMatrix();
Math::Matrix4 viewMatrix = _currentRot;
viewMatrix.transpose();
Math::Matrix4 camPos;
@ -594,7 +594,7 @@ void GfxOpenGLS::getActorScreenBBox(const Actor *actor, Common::Point &p1, Commo
bboxPos = bboxPos + actor->getWorldPos();
// Set up the camera coordinate system
Math::Matrix4 modelView = _currentQuat.toMatrix();
Math::Matrix4 modelView = _currentRot;
Math::Matrix4 zScale;
zScale.setValue(2, 2, -1.0);
modelView = modelView * zScale;
@ -668,7 +668,7 @@ void GfxOpenGLS::startActorDraw(const Actor *actor) {
Math::Vector4d color(1.0f, 1.0f, 1.0f, actor->getEffectiveAlpha());
const Math::Matrix4 &viewRot = _currentQuat.toMatrix();
const Math::Matrix4 &viewRot = _currentRot;
Math::Matrix4 modelMatrix = actor->getFinalMatrix();
Math::Matrix4 normalMatrix = viewMatrix * modelMatrix;

View file

@ -54,6 +54,7 @@ public:
virtual bool supportsShaders() override { return true; }
virtual void setupCameraFrustum(float fov, float nclip, float fclip) override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) override;
virtual Math::Matrix4 getModelView() override;
virtual Math::Matrix4 getProjection() override;

View file

@ -125,23 +125,22 @@ void GfxTinyGL::setupCameraFrustum(float fov, float nclip, float fclip) {
}
void GfxTinyGL::positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) {
if (g_grim->getGameType() == GType_MONKEY4) {
tglScalef(1.0, 1.0, -1.0);
Math::Vector3d up_vec(0, 0, 1);
_currentPos = pos;
_currentQuat = Math::Quaternion(interest.x(), interest.y(), interest.z(), roll);
} else {
Math::Vector3d up_vec(0, 0, 1);
tglRotatef(roll, 0, 0, -1);
tglRotatef(roll, 0, 0, -1);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Math::Vector3d(0, 1, 0);
Math::Matrix4 lookMatrix = Math::makeLookAtMatrix(pos, interest, up_vec);
tglMultMatrixf(lookMatrix.getData());
tglTranslatef(-pos.x(), -pos.y(), -pos.z());
}
Math::Matrix4 lookMatrix = Math::makeLookAtMatrix(pos, interest, up_vec);
tglMultMatrixf(lookMatrix.getData());
tglTranslatef(-pos.x(), -pos.y(), -pos.z());
}
void GfxTinyGL::positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) {
tglScalef(1.0, 1.0, -1.0);
_currentPos = pos;
_currentRot = rot;
}
Math::Matrix4 GfxTinyGL::getModelView() {
@ -151,8 +150,7 @@ Math::Matrix4 GfxTinyGL::getModelView() {
tglMatrixMode(TGL_MODELVIEW);
tglPushMatrix();
Math::Matrix4 worldRot = _currentQuat.toMatrix();
tglMultMatrixf(worldRot.getData());
tglMultMatrixf(_currentRot.getData());
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
tglGetFloatv(TGL_MODELVIEW_MATRIX, modelView.getData());
@ -448,7 +446,7 @@ void GfxTinyGL::getActorScreenBBox(const Actor *actor, Common::Point &p1, Common
tglPushMatrix();
// Apply the view transform.
Math::Matrix4 worldRot = _currentQuat.toMatrix();
Math::Matrix4 worldRot = _currentRot;
tglMultMatrixf(worldRot.getData());
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
@ -508,8 +506,7 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
if (g_grim->getGameType() == GType_MONKEY4 && !actor->isInOverworld()) {
// Apply the view transform.
Math::Matrix4 worldRot = _currentQuat.toMatrix();
tglMultMatrixf(worldRot.getData());
tglMultMatrixf(_currentRot.getData());
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
}
@ -608,8 +605,7 @@ void GfxTinyGL::drawShadowPlanes() {
if (g_grim->getGameType() == GType_MONKEY4) {
// Apply the view transform.
Math::Matrix4 worldRot = _currentQuat.toMatrix();
tglMultMatrixf(worldRot.getData());
tglMultMatrixf(_currentRot.getData());
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
}

View file

@ -49,6 +49,7 @@ public:
void setupCameraFrustum(float fov, float nclip, float fclip) override;
void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest, float roll) override;
void positionCamera(const Math::Vector3d &pos, const Math::Matrix4 &rot) override;
Math::Matrix4 getModelView() override;
Math::Matrix4 getProjection() override;

View file

@ -381,18 +381,18 @@ void Set::Setup::loadBinary(Common::SeekableReadStream *data) {
_bkgndZBm = nullptr;
_bkgndBm = loadBackground(fileName);
char v[4 * 4];
data->read(v, 4 * 3);
char v[sizeof(float) * 4];
data->read(v, sizeof(float) * 3);
_pos = Math::Vector3d::getVector3d(v);
data->read(v, 4 * 3);
_interest = Math::Vector3d::getVector3d(v);
data->read(v, sizeof(float) * 4);
Math::Quaternion q(get_float(v), get_float(v + 4), get_float(v + 8), get_float(v + 12));
q.toMatrix(_rot);
data->read(v, 4 * 4);
_roll = get_float(v);
_fov = get_float(v + 4);
_nclip = get_float(v + 8);
_fclip = get_float(v + 12);
data->read(v, sizeof(float) * 3);
_fov = get_float(v);
_nclip = get_float(v + 4);
_fclip = get_float(v + 8);
delete[] fileName;
}
@ -416,8 +416,17 @@ void Set::Setup::saveState(SaveGame *savedState) const {
}
savedState->writeVector3d(_pos);
savedState->writeVector3d(_interest);
savedState->writeFloat(_roll);
if (g_grim->getGameType() == GType_MONKEY4) {
// Get the rotation matrix as a quaternion and write it out
Math::Quaternion q(_rot);
savedState->writeFloat(q.x());
savedState->writeFloat(q.y());
savedState->writeFloat(q.z());
savedState->writeFloat(q.w());
} else {
savedState->writeVector3d(_interest);
savedState->writeFloat(_roll);
}
savedState->writeFloat(_fov);
savedState->writeFloat(_nclip);
savedState->writeFloat(_fclip);
@ -430,8 +439,17 @@ bool Set::Setup::restoreState(SaveGame *savedState) {
_bkgndZBm = Bitmap::getPool().getObject(savedState->readLESint32());
_pos = savedState->readVector3d();
_interest = savedState->readVector3d();
_roll = savedState->readFloat();
if (g_grim->getGameType() == GType_MONKEY4) {
float x = savedState->readFloat();
float y = savedState->readFloat();
float z = savedState->readFloat();
float w = savedState->readFloat();
Math::Quaternion q(x, y, z, w);
_rot = q.toMatrix();
} else {
_interest = savedState->readVector3d();
_roll = savedState->readFloat();
}
_fov = savedState->readFloat();
_nclip = savedState->readFloat();
_fclip = savedState->readFloat();
@ -656,7 +674,7 @@ void SetShadow::restoreState(SaveGame *savedState) {
}
void Set::Setup::setupCamera() const {
// Ignore nclip_ and fclip_ for now. This fixes:
// Ignore nclip_ and fclip_ for now in Grim. This fixes:
// (a) Nothing was being displayed in the Land of the Living
// diner because lr.set set nclip to 0.
// (b) The zbuffers for setups with different nclip or
@ -664,15 +682,13 @@ void Set::Setup::setupCamera() const {
// are important at some point, we'll need to modify the
// zbuffer transformation in bitmap.cpp to take nclip_ and
// fclip_ into account.
float nclip = this->_nclip;
float fclip = this->_fclip;
if (g_grim->getGameType() != GType_MONKEY4) {
nclip = 0.01f;
fclip = 3276.8f;
if (g_grim->getGameType() == GType_GRIM) {
g_driver->setupCameraFrustum(_fov, 0.01f, 3276.8f);
g_driver->positionCamera(_pos, _interest, _roll);
} else {
g_driver->setupCameraFrustum(_fov, _nclip, _fclip);
g_driver->positionCamera(_pos, _rot);
}
g_driver->setupCameraFrustum(_fov, nclip, fclip);
g_driver->positionCamera(_pos, _interest, _roll);
}
class Sorter {

View file

@ -112,6 +112,7 @@ public:
ObjectState *addObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, bool transparency);
ObjectState *findState(const Common::String &filename);
// Setups contain the camera information and background for all views in a Set
struct Setup { // Camera setup data
void load(Set *set, int id, TextSplitter &ts);
void loadBinary(Common::SeekableReadStream *data);
@ -121,7 +122,10 @@ public:
Common::String _name;
Bitmap::Ptr _bkgndBm, _bkgndZBm;
// Camera settings
Math::Vector3d _pos, _interest;
Math::Matrix4 _rot;
float _roll, _fov, _nclip, _fclip;
};