1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
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 "titanic/star_control/viewport.h"
24 #include "titanic/star_control/fvector.h"
25 #include "titanic/debugger.h"
26 #include "titanic/support/simple_file.h"
27 #include "titanic/titanic.h"
28 
29 #include "common/math.h"
30 
31 namespace Titanic {
32 
CViewport()33 CViewport::CViewport() {
34 	_fieldC = 0; // doesn't get used
35 	_field10 = 800.0; // doesn't get used
36 	_field14 = 10000.0; // doesn't get used
37 	_centerYAngleDegrees = 20.0;
38 	_centerZAngleDegrees = 20.0;
39 	_width = 600;
40 	_height = 340;
41 	_starColor = PINK; // default for starview
42 	_poseUpToDate = false;
43 	Common::fill(&_valArray[0], &_valArray[2], 0.0);
44 	_isZero = 0.0; // seems to always be zero
45 	_pixel1OffSetX = 0.0;
46 	_pixel2OffSetX = 0.0;
47 }
48 
CViewport(CViewport * src)49 CViewport::CViewport(CViewport *src) :
50 		_orientation(src->_orientation), _currentPose(src->_currentPose), _rawPose(src->_rawPose) {
51 	_position = src->_position;
52 	_fieldC = src->_fieldC;
53 	_field10 = src->_field10;
54 	_field14 = src->_field14;
55 	_centerYAngleDegrees = src->_centerYAngleDegrees;
56 	_centerZAngleDegrees = src->_centerZAngleDegrees;
57 	_width = src->_width;
58 	_height = src->_height;
59 
60 	_center = src->_center;
61 	_centerVector = src->_centerVector;
62 	_starColor = src->_starColor;
63 
64 	Common::copy(&src->_valArray[0], &src->_valArray[2], &_valArray[0]);
65 	_isZero = src->_isZero;
66 	_pixel1OffSetX = src->_pixel1OffSetX;
67 	_pixel2OffSetX = src->_pixel2OffSetX;
68 	_poseUpToDate = false;
69 }
70 
copyFrom(const CViewport * src)71 void CViewport::copyFrom(const CViewport *src) {
72 	error("Unused function");
73 }
74 
load(SimpleFile * file,int param)75 void CViewport::load(SimpleFile *file, int param) {
76 	_position._x = file->readFloat();
77 	_position._y = file->readFloat();
78 	_position._z = file->readFloat();
79 	_fieldC = file->readFloat();
80 	_field10 = file->readFloat();
81 	_field14 = file->readFloat();
82 	_centerYAngleDegrees = file->readFloat();
83 	_centerZAngleDegrees = file->readFloat();
84 
85 	int widthHeight = file->readNumber();
86 	_width = widthHeight & 0xffff;
87 	_height = widthHeight >> 16;
88 	int field24 = file->readNumber(); //0 = White, 2 = Pink
89 	_starColor = (StarColor) field24;
90 
91 	for (int idx = 0; idx < 2; ++idx)
92 		_valArray[idx] = file->readFloat();
93 
94 	_isZero = file->readFloat();
95 	_pixel1OffSetX = file->readFloat();
96 	_pixel2OffSetX = file->readFloat();
97 
98 	_orientation.load(file, param);
99 	_poseUpToDate = false;
100 }
101 
save(SimpleFile * file,int indent)102 void CViewport::save(SimpleFile *file, int indent) {
103 	file->writeFloatLine(_position._x, indent);
104 	file->writeFloatLine(_position._y, indent);
105 	file->writeFloatLine(_position._z, indent);
106 	file->writeFloatLine(_fieldC, indent);
107 	file->writeFloatLine(_field10, indent);
108 	file->writeFloatLine(_field14, indent);
109 	file->writeFloatLine(_centerYAngleDegrees, indent);
110 	file->writeFloatLine(_centerZAngleDegrees, indent);
111 	file->writeNumberLine(_width | (_height << 16), indent);
112 	int field24 = (int)_starColor;
113 	file->writeNumberLine(field24, indent);
114 
115 	for (int idx = 0; idx < 2; ++idx)
116 		file->writeFloatLine(_valArray[idx], indent);
117 
118 	file->writeFloatLine(_isZero, indent);
119 	file->writeFloatLine(_pixel1OffSetX, indent);
120 	file->writeFloatLine(_pixel2OffSetX, indent);
121 
122 	_orientation.save(file, indent);
123 }
124 
setPosition(const FVector & v)125 void CViewport::setPosition(const FVector &v) {
126 	debugC(DEBUG_INTERMEDIATE, kDebugStarfield, "Setting starmap position to %s", v.toString().c_str());
127 	_position = v;
128 	_poseUpToDate = false;
129 }
130 
setPosition(const FPose & pose)131 void CViewport::setPosition(const FPose &pose) {
132 	_position = _position.matProdRowVect(pose);
133 	_poseUpToDate = false;
134 }
135 
setOrientation(const FMatrix & m)136 void CViewport::setOrientation(const FMatrix &m) {
137 	_orientation = m;
138 	_poseUpToDate = false;
139 }
140 
setOrientation(const FVector & v)141 void CViewport::setOrientation(const FVector &v) {
142 	_orientation.set(v);
143 	_poseUpToDate = false;
144 }
145 
146 // This never gets called
setC(double v)147 void CViewport::setC(double v) {
148 	_fieldC = v;
149 	_poseUpToDate = false;
150 }
151 
152 // This never gets called
set10(double v)153 void CViewport::set10(double v) {
154 	_field10 = v;
155 	_poseUpToDate = false;
156 }
157 
158 // This never gets called
set14(double v)159 void CViewport::set14(double v) {
160 	_field10 = v;
161 }
162 
setCenterYAngle(double angleDegrees)163 void CViewport::setCenterYAngle(double angleDegrees) {
164 	_centerYAngleDegrees = angleDegrees;
165 	_poseUpToDate = false;
166 }
167 
setCenterZAngle(double angleDegrees)168 void CViewport::setCenterZAngle(double angleDegrees) {
169 	_centerZAngleDegrees = angleDegrees;
170 	_poseUpToDate = false;
171 }
172 
randomizeOrientation()173 void CViewport::randomizeOrientation() {
174 	_orientation.identity();
175 
176 	double ranRotAngleX = g_vm->getRandomNumber(359);
177 	double ranRotAngleY = g_vm->getRandomNumber(359);
178 	double ranRotAngleZ = g_vm->getRandomNumber(359);
179 
180 	FPose m1(X_AXIS, ranRotAngleX);
181 	FPose m2(Y_AXIS, ranRotAngleY);
182 	FPose m3(Z_AXIS, ranRotAngleZ);
183 
184 	FPose s1(m1, m2);
185 	FPose s2(s1, m3);
186 
187 	_orientation.matRProd(s2);
188 	_poseUpToDate = false;
189 }
190 
changeStarColorPixel(StarMode mode,double pixelOffSet)191 void CViewport::changeStarColorPixel(StarMode mode, double pixelOffSet) {
192 	// pixelOffset is usually 0.0, 30.0, or 28000.0
193 	if (mode == MODE_PHOTO) {
194 		_valArray[0] = pixelOffSet;
195 		_valArray[1] = -pixelOffSet;
196 	} else {
197 		_pixel1OffSetX = pixelOffSet;
198 		_pixel2OffSetX = -pixelOffSet;
199 	}
200 
201 	_isZero = 0.0;
202 	_starColor = pixelOffSet ? PINK : WHITE;
203 }
204 
reposition(double factor)205 void CViewport::reposition(double factor) {
206 	_position._x = _orientation._row3._x * factor + _position._x;
207 	_position._y = _orientation._row3._y * factor + _position._y;
208 	_position._z = _orientation._row3._z * factor + _position._z;
209 	_poseUpToDate = false;
210 }
211 
changeOrientation(const FMatrix & matrix)212 void CViewport::changeOrientation(const FMatrix &matrix) {
213 	_orientation.matLProd(matrix);
214 	_poseUpToDate = false;
215 }
216 
getPose()217 FPose CViewport::getPose() {
218 	if (!_poseUpToDate)
219 		reset();
220 
221 	return _currentPose;
222 }
223 
getRawPose()224 FPose CViewport::getRawPose() {
225 	if (!_poseUpToDate)
226 		reset();
227 
228 	return _rawPose;
229 }
230 
231 
232 // TODO: should index be used here like
233 // getRelativePosCentering/getRelativePosCentering2?
234 // CStarCamera::getRelativePosCentering is calling this with an index of
235 // 2 which corresponds to _isZero which has value 0.
getRelativePosNoCentering(int index,const FVector & src)236 FVector CViewport::getRelativePosNoCentering(int index, const FVector &src) {
237 	FPose current_pose = getPose();
238 	FVector dest = src.matProdRowVect(current_pose);
239 	return dest;
240 }
241 
getRelativePosCentering(int index,const FVector & src)242 FVector CViewport::getRelativePosCentering(int index, const FVector &src) {
243 	FVector dest;
244 	FPose pose = getPose();
245 	FVector tv = src.matProdRowVect(pose);
246 
247 	double val;
248 	if (index <2) {
249 		val = _valArray[index];
250 	} else if (index == 2) {
251 		val = _isZero;
252 	} else if (index == 3) {
253 		val = _pixel1OffSetX;
254 	} else {
255 		val = _pixel2OffSetX;
256 	}
257 
258 	dest._x = (val + tv._x)
259 		* _centerVector._x / (_centerVector._y * tv._z);
260 	dest._y = (tv._y * _centerVector._x) / (_centerVector._z * tv._z);
261 	dest._z = tv._z;
262 	return dest;
263 }
264 
265 // Similar to getRelativePosCentering, but uses the raw/transpose version of Pose
getRelativePosCenteringRaw(int index,const FVector & src)266 FVector CViewport::getRelativePosCenteringRaw(int index, const FVector &src) {
267 	FVector dest;
268 	FPose pose = getRawPose();
269 	FVector tv = src.matProdRowVect(pose);
270 
271 	double val;
272 	if (index <2) {
273 		val = _valArray[index];
274 	} else if (index == 2) {
275 		val = _isZero;
276 	} else if (index == 3) {
277 		val = _pixel1OffSetX;
278 	} else {
279 		val = _pixel2OffSetX;
280 	}
281 
282 	dest._x = (val + tv._x)
283 		* _centerVector._x / (_centerVector._y * tv._z);
284 	dest._y = (tv._y * _centerVector._x) / (_centerVector._z * tv._z);
285 	dest._z = tv._z;
286 	return dest;
287 }
288 
getRelativeXCenterPixels(double * v1,double * v2,double * v3,double * v4)289 void CViewport::getRelativeXCenterPixels(double *v1, double *v2, double *v3, double *v4) {
290 	*v1 = _centerVector._x / _centerVector._y;
291 	*v2 = _centerVector._x / _centerVector._z;
292 	*v3 = _pixel1OffSetX;
293 	*v4 = _pixel2OffSetX;
294 }
295 
reset()296 void CViewport::reset() {
297 	_rawPose.copyFrom(_orientation);
298 	_rawPose._vector = _position;
299 	_currentPose = _rawPose.inverseTransform();
300 	_poseUpToDate = true;
301 
302 	_center = FPoint((double)_width * 0.5, (double)_height * 0.5);
303 	_centerVector._x = MIN(_center._x, _center._y);
304 	_centerVector._y = tan(Common::deg2rad<double>(_centerYAngleDegrees));
305 	_centerVector._z = tan(Common::deg2rad<double>(_centerZAngleDegrees));
306 }
307 
getOrientation() const308 const FMatrix &CViewport::getOrientation() const {
309 	return _orientation;
310 }
311 
312 } // End of namespace Titanic
313