diff --git a/engines/grim/gfx_base.cpp b/engines/grim/gfx_base.cpp index 89f57bf7fdb..734841464b6 100644 --- a/engines/grim/gfx_base.cpp +++ b/engines/grim/gfx_base.cpp @@ -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) { diff --git a/engines/grim/gfx_base.h b/engines/grim/gfx_base.h index 02e845dad8a..e00eb52da5a 100644 --- a/engines/grim/gfx_base.h +++ b/engines/grim/gfx_base.h @@ -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; }; diff --git a/engines/grim/gfx_opengl.cpp b/engines/grim/gfx_opengl.cpp index 7604f0c9adc..50da59001a6 100644 --- a/engines/grim/gfx_opengl.cpp +++ b/engines/grim/gfx_opengl.cpp @@ -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()); } diff --git a/engines/grim/gfx_opengl.h b/engines/grim/gfx_opengl.h index 6e7200fadce..215aac1c012 100644 --- a/engines/grim/gfx_opengl.h +++ b/engines/grim/gfx_opengl.h @@ -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; diff --git a/engines/grim/gfx_opengl_shaders.cpp b/engines/grim/gfx_opengl_shaders.cpp index 5958a5399a9..9cd00f26629 100644 --- a/engines/grim/gfx_opengl_shaders.cpp +++ b/engines/grim/gfx_opengl_shaders.cpp @@ -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; diff --git a/engines/grim/gfx_opengl_shaders.h b/engines/grim/gfx_opengl_shaders.h index b34f4ab1fa6..e68695bb72a 100644 --- a/engines/grim/gfx_opengl_shaders.h +++ b/engines/grim/gfx_opengl_shaders.h @@ -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; diff --git a/engines/grim/gfx_tinygl.cpp b/engines/grim/gfx_tinygl.cpp index 3bd6b5f2e02..7be84530c15 100644 --- a/engines/grim/gfx_tinygl.cpp +++ b/engines/grim/gfx_tinygl.cpp @@ -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()); } diff --git a/engines/grim/gfx_tinygl.h b/engines/grim/gfx_tinygl.h index b94c34e10e6..ee88b317bdc 100644 --- a/engines/grim/gfx_tinygl.h +++ b/engines/grim/gfx_tinygl.h @@ -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; diff --git a/engines/grim/set.cpp b/engines/grim/set.cpp index 06412595a77..5438fb9992e 100644 --- a/engines/grim/set.cpp +++ b/engines/grim/set.cpp @@ -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 { diff --git a/engines/grim/set.h b/engines/grim/set.h index 7c3e4252679..c38de6d58db 100644 --- a/engines/grim/set.h +++ b/engines/grim/set.h @@ -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; };