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