1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "engines/stark/scene.h"
24
25 #include "engines/stark/gfx/driver.h"
26 #include "engines/stark/gfx/renderentry.h"
27
28 #include "common/system.h"
29
30 #include "math/glmath.h"
31
32 namespace Stark {
33
Scene(Gfx::Driver * gfx)34 Scene::Scene(Gfx::Driver *gfx) :
35 _gfx(gfx),
36 _fov(45.0),
37 _nearClipPlane(100.0),
38 _farClipPlane(64000.0),
39 _fadeLevel(0.0),
40 _floatOffset(0.0) {
41 }
42
~Scene()43 Scene::~Scene() {
44 }
45
initCamera(const Math::Vector3d & position,const Math::Vector3d & lookDirection,float fov,Common::Rect viewSize,float nearClipPlane,float farClipPlane)46 void Scene::initCamera(const Math::Vector3d &position, const Math::Vector3d &lookDirection,
47 float fov, Common::Rect viewSize, float nearClipPlane, float farClipPlane) {
48 _cameraPosition = position;
49 _cameraLookDirection = lookDirection;
50 _fov = fov;
51 _viewSize = viewSize;
52 _nearClipPlane = nearClipPlane;
53 _farClipPlane = farClipPlane;
54
55 _viewMatrix = Math::makeLookAtMatrix(_cameraPosition, _cameraPosition + _cameraLookDirection, Math::Vector3d(0.0, 0.0, 1.0));
56 _viewMatrix.transpose(); // Math::makeLookAtMatrix outputs transposed matrices ...
57 _viewMatrix.translate(-_cameraPosition);
58
59 setSwayAngle(0);
60 setFadeLevel(1.0);
61 setFloatOffset(0);
62 }
63
scrollCamera(const Common::Rect & viewport)64 void Scene::scrollCamera(const Common::Rect &viewport) {
65 _viewport = viewport;
66
67 float xmin, xmax, ymin, ymax;
68 computeClippingRect(&xmin, &xmax, &ymin, &ymax);
69
70 // The amounts by which translate to clipping planes to account for one pixel
71 // of camera scrolling movement
72 float scollXFactor = (xmax - xmin) / _viewport.width();
73 float scollYFactor = (ymax - ymin) / _viewport.height();
74
75 int32 distanceToRight = _viewport.right - _viewSize.width();
76 int32 distanceToTop = -_viewport.top;
77
78 xmin += distanceToRight * scollXFactor;
79 xmax += distanceToRight * scollXFactor;
80 ymin += distanceToTop * scollYFactor;
81 ymax += distanceToTop * scollYFactor;
82
83 _projectionMatrix = Math::makeFrustumMatrix(xmin, xmax, ymin, ymax, _nearClipPlane, _farClipPlane);
84 _projectionMatrix.transpose(); // Math::makeFrustumMatrix outputs transposed matrices ...
85 }
86
computeClippingRect(float * xmin,float * xmax,float * ymin,float * ymax)87 void Scene::computeClippingRect(float *xmin, float *xmax, float *ymin, float *ymax) {
88 float aspectRatio = _viewSize.width() / (float) _viewSize.height();
89 float xmaxValue = _nearClipPlane * tan(_fov * M_PI / 360.0);
90 float ymaxValue = xmaxValue / aspectRatio;
91
92 float xminValue = xmaxValue - 2 * xmaxValue * (_viewport.width() / (float) _viewSize.width());
93 float yminValue = ymaxValue - 2 * ymaxValue * (_viewport.height() / (float) _viewSize.height());
94
95 if (xmin) *xmin = xminValue;
96 if (xmax) *xmax = xmaxValue;
97 if (ymin) *ymin = yminValue;
98 if (ymax) *ymax = ymaxValue;
99 }
100
makeRayFromMouse(const Common::Point & mouse) const101 Math::Ray Scene::makeRayFromMouse(const Common::Point &mouse) const {
102 Common::Rect gameViewport = _gfx->gameViewport();
103
104 Math::Vector4d in;
105 in.x() = (mouse.x - gameViewport.left) * 2 / (float) gameViewport.width() - 1.0;
106 in.y() = (g_system->getHeight() - mouse.y - gameViewport.top) * 2 / (float) gameViewport.height() - 1.0;
107 in.z() = 1.0;
108 in.w() = 1.0;
109
110 Math::Matrix4 view = _viewMatrix;
111 view.translate(_cameraPosition);
112
113 Math::Matrix4 A = _projectionMatrix * view;
114 A.inverse();
115
116 Math::Vector4d out = A * in;
117
118 Math::Vector3d origin = _cameraPosition;
119 Math::Vector3d direction = Math::Vector3d(out.x(), out.y(), out.z());
120 direction.normalize();
121
122 return Math::Ray(origin, direction);
123 }
124
convertPosition3DToGameScreenOriginal(const Math::Vector3d & obj) const125 Common::Point Scene::convertPosition3DToGameScreenOriginal(const Math::Vector3d &obj) const {
126 Math::Vector4d in;
127 in.set(obj.x(), obj.y(), obj.z(), 1.0);
128
129 Math::Vector4d out = _projectionMatrix * _viewMatrix * in;
130
131 out.x() /= out.w();
132 out.y() /= out.w();
133
134 Common::Point point;
135 point.x = (1 + out.x()) * Gfx::Driver::kGameViewportWidth / 2;
136 point.y = -Gfx::Driver::kTopBorderHeight + Gfx::Driver::kOriginalHeight - (1 + out.y()) * Gfx::Driver::kGameViewportHeight / 2;
137
138 return point;
139 }
140
setFadeLevel(float fadeLevel)141 void Scene::setFadeLevel(float fadeLevel) {
142 _fadeLevel = fadeLevel;
143 }
144
getFadeLevel() const145 float Scene::getFadeLevel() const {
146 return _fadeLevel;
147 }
148
setSwayAngle(const Math::Angle & angle)149 void Scene::setSwayAngle(const Math::Angle &angle) {
150 _swayAngle = angle;
151 }
152
getSwayAngle() const153 Math::Angle Scene::getSwayAngle() const {
154 return _swayAngle;
155 }
156
getSwayDirection() const157 Math::Vector3d Scene::getSwayDirection() const {
158 // Actor sway is always along the camera direction, so that
159 // the rotation is not affected by the direction they are facing.
160 return _cameraLookDirection;
161 }
162
setFloatOffset(float floatOffset)163 void Scene::setFloatOffset(float floatOffset) {
164 _floatOffset = floatOffset;
165 }
166
getFloatOffset() const167 float Scene::getFloatOffset() const {
168 return _floatOffset;
169 }
170
171 } // End of namespace Stark
172