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 "trecision/actor.h"
24 #include "trecision/sound.h"
25 #include "trecision/pathfinding3d.h"
26 #include "trecision/scheduler.h"
27 #include "trecision/defines.h"
28 #include "trecision/graphics.h"
29 #include "trecision/trecision.h"
30 
31 namespace Trecision {
32 
Actor(TrecisionEngine * vm)33 Actor::Actor(TrecisionEngine *vm) : _vm(vm) {
34 	_vertex = nullptr;
35 	_face = nullptr;
36 	_light = nullptr;
37 	_camera = nullptr;
38 	_textures = nullptr;
39 	_textureData = nullptr;
40 
41 	_vertexNum = 0;
42 	_faceNum = 0;
43 	_lightNum = 0;
44 
45 	_px = _pz = 0.0f;
46 	_dx = _dz = 0.0f;
47 	_theta = 0.0f;
48 
49 	for (uint8 i = 0; i < 6; ++i)
50 		_lim[i] = 0;
51 
52 	_curFrame = 0;
53 	_curAction = 0;
54 
55 	for (uint16 i = 0; i < MAXFACE; ++i) {
56 		for (uint8 j = 0; j < 3; ++j) {
57 			_textureCoord[i][j][0] = 0;
58 			_textureCoord[i][j][1] = 0;
59 		}
60 	}
61 
62 	_characterArea = nullptr;
63 	_textureData = _vm->readData("textur.bm");
64 
65 	initTextures();
66 	readModel("jm.om");
67 
68 	for (int i = 0; i < MAXLIGHT; ++i)
69 		_lightArea[i].clear();
70 
71 	_cameraArea.clear();
72 
73 	_light = (SLight *)&_lightArea;
74 	_camera = (SCamera *)&_cameraArea;
75 }
76 
~Actor()77 Actor::~Actor() {
78 	delete[] _characterArea;
79 	delete[] _face;
80 	delete[] _textureData;
81 }
82 
initTextures()83 void Actor::initTextures() {
84 	for (int i = 0; i < MAXMAT; ++i)
85 		_textureArea[i].clear();
86 
87 	// head
88 	_textureArea[0].set(300 / 2, 208 / 2, _textureData);
89 
90 	// body
91 	_textureArea[1].set(300, 300, _textureData + (300 * 208 / 4));
92 
93 	// arms
94 	_textureArea[2].set(300, 150, _textureData + (300 * 208 / 4) + (300 * 300));
95 
96 	_textures = (STexture *)&_textureArea[0];
97 }
98 
updateStepSound()99 void Actor::updateStepSound() {
100 	_vm->_soundMgr->soundStep((_lim[1] + _lim[0]) / 2, (_lim[5] + _lim[4]) / 2, _curAction, _curFrame);
101 }
102 
103 static const float _vertsCorr[104][3] = {
104 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
105 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
106 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
107 	{0.000000f, 0.000001f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
108 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
109 	{0.000000f, -0.061717f, 0.833191f}, {0.000000f, -0.120163f, 0.330445f},
110 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
111 	{0.000000f, -0.432022f, 0.216004f}, {0.000000f, -0.030041f, 0.360489f},
112 	{0.310895f, 0.000000f, 0.000000f}, {0.312943f, 0.000000f, 0.000000f},
113 	{0.114858f, 0.000000f, 0.000000f}, {0.000000f, 1.051431f, 0.300415f},
114 	{0.000000f, 0.000000f, 0.246856f}, {0.000000f, 0.120163f, 0.480652f},
115 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
116 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
117 	{0.000000f, 0.180247f, 0.600815f}, {0.000000f, 0.000000f, 0.000000f},
118 	{0.530074f, 0.041892f, 0.670273f}, {0.000000f, 0.000000f, 0.000000f},
119 	{0.000000f, 0.060081f, 0.540726f}, {0.000000f, -0.318127f, -0.249817f},
120 	{0.000000f, 0.180244f, 0.540741f}, {0.000000f, 0.000000f, 0.000000f},
121 	{0.000000f, -0.922172f, 0.201188f}, {0.000000f, -0.442684f, -0.328400f},
122 	{0.353384f, 1.047291f, -1.005401f}, {0.000000f, -0.646931f, -0.933030f},
123 	{0.000000f, 2.283107f, -0.420562f}, {0.412281f, -1.633775f, -1.193909f},
124 	{0.312389f, 0.000000f, 0.000000f}, {0.000000f, 0.020947f, -0.083786f},
125 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, -1.021390f, -1.141556f},
126 	{0.000000f, 0.020946f, -0.146637f}, {0.000000f, 0.000000f, 0.000000f},
127 	{0.000000f, 0.020946f, -0.146637f}, {0.000000f, 0.020947f, -0.146637f},
128 	{0.000000f, 0.020946f, -0.083786f}, {0.000000f, 0.020946f, -0.125687f},
129 	{0.000000f, 0.020947f, -0.146637f}, {0.000000f, 0.020947f, -0.125687f},
130 	{0.000000f, 0.020946f, -0.083786f}, {0.000000f, 0.000000f, 0.000000f},
131 	{0.000000f, 0.020947f, -0.125687f}, {0.000000f, 0.000000f, 0.000000f},
132 	{0.000000f, 0.020947f, -0.125686f}, {0.000000f, 0.020946f, -0.125687f},
133 	{0.000000f, 0.020946f, -0.083786f}, {0.000000f, 0.020946f, -0.146637f},
134 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
135 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
136 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
137 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
138 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
139 	{0.000000f, -0.061717f, 0.833191f}, {0.000000f, -0.090122f, 0.330460f},
140 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, -0.432022f, 0.185150f},
141 	{-0.310895f, 0.000000f, 0.000000f}, {-0.312943f, 0.000001f, 0.000000f},
142 	{-0.114858f, 0.000000f, 0.000000f}, {0.000000f, 1.051431f, 0.270371f},
143 	{0.000000f, -0.030858f, 0.246856f}, {0.000000f, 0.000000f, 0.000000f},
144 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f},
145 	{-0.647869f, 0.041892f, 0.628372f}, {0.000000f, 0.000000f, 0.000000f},
146 	{0.000000f, -0.442684f, -0.328400f}, {-0.294485f, 1.026345f, -1.005401f},
147 	{-0.353383f, -1.633775f, -1.214859f}, {-0.312389f, 0.000000f, 0.000000f},
148 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.020947f, -0.146637f},
149 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.020946f, -0.146637f},
150 	{0.000000f, 0.020946f, -0.083786f}, {0.000000f, 0.020947f, -0.146637f},
151 	{0.000000f, 0.020947f, -0.125687f}, {0.000000f, 0.020947f, -0.083786f},
152 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.020947f, -0.125687f},
153 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.020946f, -0.125687f},
154 	{0.000000f, 0.020946f, -0.146637f}, {0.000000f, 0.000000f, 0.000000f},
155 	{0.000000f, 0.000000f, 0.000000f}, {0.000000f, 0.000000f, 0.000000f}};
156 
157 static const int _vertsCorrList[84] = {
158 	289, 290, 293, 294, 295, 296, 297, 298,
159 	299, 300, 300, 302, 303, 304, 305, 305,
160 	307, 307, 309, 310, 311, 312, 313, 314,
161 	315, 316, 317, 318, 319, 320, 321, 322,
162 	323, 324, 325, 326, 327, 328, 329, 330,
163 	331, 332, 333, 334, 335, 336, 337, 338,
164 	339, 340, 341, 349, 350, 352, 353, 354,
165 	355, 356, 357, 358, 359, 360, 361, 362,
166 	363, 364, 365, 366, 367, 368, 369, 370,
167 	371, 372, 373, 374, 375, 376, 377, 378,
168 	379, 380, 381, 382};
169 
170 /**********************************************
171   Microprose head correction
172 **********************************************/
microproseHeadFix(uint32 actionNum)173 void Actor::microproseHeadFix(uint32 actionNum) {
174 	static const uint16 idx1 = 306;
175 	static const uint16 idx2 = 348;
176 	static const uint16 idx3 = 288;
177 
178 	double v1[3], v2[3], v[3], q[3], m1[3][3], m2[3][3];
179 
180 	v1[0] = _vertex[idx2]._x - _vertex[idx1]._x;
181 	v1[1] = _vertex[idx2]._y - _vertex[idx1]._y;
182 	v1[2] = _vertex[idx2]._z - _vertex[idx1]._z;
183 	double s = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
184 	v1[0] /= s;
185 	v1[1] /= s;
186 	v1[2] /= s;
187 
188 	v2[0] = _vertex[idx3]._x - _vertex[idx1]._x;
189 	v2[1] = _vertex[idx3]._y - _vertex[idx1]._y;
190 	v2[2] = _vertex[idx3]._z - _vertex[idx1]._z;
191 	s = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
192 	v2[0] /= s;
193 	v2[1] /= s;
194 	v2[2] /= s;
195 
196 	m1[1][0] = v2[1] * v1[2] - v1[1] * v2[2];
197 	m1[1][1] = v2[2] * v1[0] - v1[2] * v2[0];
198 	m1[1][2] = v2[0] * v1[1] - v1[0] * v2[1];
199 	s = sqrt(m1[1][0] * m1[1][0] + m1[1][1] * m1[1][1] + m1[1][2] * m1[1][2]);
200 	m1[1][0] /= s;
201 	m1[1][1] /= s;
202 	m1[1][2] /= s;
203 
204 	m1[2][0] = m1[1][1] * v1[2] - v1[1] * m1[1][2];
205 	m1[2][1] = m1[1][2] * v1[0] - v1[2] * m1[1][0];
206 	m1[2][2] = m1[1][0] * v1[1] - v1[0] * m1[1][1];
207 	s = sqrt(m1[2][0] * m1[2][0] + m1[2][1] * m1[2][1] + m1[2][2] * m1[2][2]);
208 	m1[2][0] /= s;
209 	m1[2][1] /= s;
210 	m1[2][2] /= s;
211 
212 	m1[0][0] = v1[0];
213 	m1[0][1] = v1[1];
214 	m1[0][2] = v1[2];
215 
216 	for (uint i = 0; i < actionNum; ++i) {
217 		SVertex *sv = &_vertex[i * _vertexNum];
218 
219 		v1[0] = sv[idx2]._x - sv[idx1]._x;
220 		v1[1] = sv[idx2]._y - sv[idx1]._y;
221 		v1[2] = sv[idx2]._z - sv[idx1]._z;
222 		s = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
223 		v1[0] /= s;
224 		v1[1] /= s;
225 		v1[2] /= s;
226 
227 		v2[0] = sv[idx3]._x - sv[idx1]._x;
228 		v2[1] = sv[idx3]._y - sv[idx1]._y;
229 		v2[2] = sv[idx3]._z - sv[idx1]._z;
230 		s = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
231 		v2[0] /= s;
232 		v2[1] /= s;
233 		v2[2] /= s;
234 
235 		m2[1][0] = v2[1] * v1[2] - v1[1] * v2[2];
236 		m2[1][1] = v2[2] * v1[0] - v1[2] * v2[0];
237 		m2[1][2] = v2[0] * v1[1] - v1[0] * v2[1];
238 		s = sqrt(m2[1][0] * m2[1][0] + m2[1][1] * m2[1][1] + m2[1][2] * m2[1][2]);
239 		m2[1][0] /= s;
240 		m2[1][1] /= s;
241 		m2[1][2] /= s;
242 
243 		m2[2][0] = m2[1][1] * v1[2] - v1[1] * m2[1][2];
244 		m2[2][1] = m2[1][2] * v1[0] - v1[2] * m2[1][0];
245 		m2[2][2] = m2[1][0] * v1[1] - v1[0] * m2[1][1];
246 		s = sqrt(m2[2][0] * m2[2][0] + m2[2][1] * m2[2][1] + m2[2][2] * m2[2][2]);
247 		m2[2][0] /= s;
248 		m2[2][1] /= s;
249 		m2[2][2] /= s;
250 
251 		m2[0][0] = v1[0];
252 		m2[0][1] = v1[1];
253 		m2[0][2] = v1[2];
254 
255 		v2[0] = sv[idx1]._x;
256 		v2[1] = sv[idx1]._y;
257 		v2[2] = sv[idx1]._z;
258 
259 		v1[0] = _vertex[idx1]._x;
260 		v1[1] = _vertex[idx1]._y;
261 		v1[2] = _vertex[idx1]._z;
262 
263 		for (int j = 279; j < 383; ++j) {
264 			int f;
265 			for (f = 0; f < 84; ++f) {
266 				if (_vertsCorrList[f] == j)
267 					break;
268 			}
269 			if (f == 84)
270 				continue;
271 
272 			v[0] = _vertsCorr[j - 279][0];
273 			v[1] = _vertsCorr[j - 279][2];
274 			v[2] = _vertsCorr[j - 279][1];
275 
276 			q[0] = 0.0;
277 			q[1] = 0.0;
278 			q[2] = 0.0;
279 			for (int d = 0; d < 3; ++d) {
280 				for (int c = 0; c < 3; ++c)
281 					q[c] += m1[c][d] * v[d];
282 			}
283 			v[0] = 0.0;
284 			v[1] = 0.0;
285 			v[2] = 0.0;
286 			for (int d = 0; d < 3; ++d) {
287 				for (int c = 0; c < 3; ++c)
288 					v[c] += m2[d][c] * q[d];
289 			}
290 
291 			if (i < 42) {
292 				sv[j]._x += _vertsCorr[j - 279][0];
293 				sv[j]._y += _vertsCorr[j - 279][2];
294 				sv[j]._z += _vertsCorr[j - 279][1];
295 			} else {
296 				sv[j]._x += v[0];
297 				sv[j]._y += v[1];
298 				sv[j]._z += v[2];
299 			}
300 		}
301 	}
302 }
303 
readModel(const char * filename)304 void Actor::readModel(const char *filename) {
305 	Common::SeekableReadStreamEndian *ff = _vm->readEndian(_vm->_dataFile.createReadStreamForMember(filename));
306 	if (ff == nullptr)
307 		error("readModel - Error opening file %s", filename);
308 
309 	uint32 actionNum = ff->readUint32();
310 	_vertexNum = ff->readUint32();
311 
312 	_characterArea = new SVertex[_vertexNum * actionNum];
313 	for (uint i = 0; i < _vertexNum * actionNum; ++i) {
314 		_characterArea[i]._x = ff->readFloat();
315 		_characterArea[i]._y = ff->readFloat();
316 		_characterArea[i]._z = ff->readFloat();
317 		_characterArea[i]._nx = ff->readFloat();
318 		_characterArea[i]._ny = ff->readFloat();
319 		_characterArea[i]._nz = ff->readFloat();
320 	}
321 	_vertex = _characterArea;
322 	_faceNum = ff->readUint32();
323 	delete ff;
324 
325 	ff = _vm->readEndian(_vm->_dataFile.createReadStreamForMember("mat.tex"));
326 	if (ff == nullptr)
327 		error("readModel - Error opening file mat.tex");
328 
329 	_vm->_graphicsMgr->readTexture(ff);
330 
331 	for (uint16 i = 0; i < MAXFACE; ++i) {
332 		for (uint16 j = 0; j < 3; ++j) {
333 			_textureCoord[i][j][0] = ff->readSint16();
334 			_textureCoord[i][j][1] = ff->readSint16();
335 		}
336 	}
337 
338 	_face = new SFace[_faceNum];
339 	for (uint i = 0; i < _faceNum; ++i) {
340 		_face[i]._a = ff->readUint16();
341 		_face[i]._b = ff->readUint16();
342 		_face[i]._c = ff->readUint16();
343 		_face[i]._mat = ff->readUint16();
344 	}
345 
346 	delete ff;
347 
348 	_curFrame = 0;
349 	_curAction = hSTAND;
350 
351 	microproseHeadFix(actionNum);
352 }
353 
syncGameStream(Common::Serializer & ser)354 void Actor::syncGameStream(Common::Serializer &ser) {
355 	float unused = 0;
356 
357 	ser.syncAsFloatLE(_px);
358 	ser.syncAsFloatLE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX);
359 	ser.syncAsFloatLE(_pz);
360 	ser.syncAsFloatLE(_dx);
361 	ser.syncAsFloatLE(_dz);
362 	ser.syncAsFloatLE(_theta);
363 }
364 
actorDoAction(int action)365 void Actor::actorDoAction(int action) {
366 	if (action > hLAST)
367 		error("error in actorDoAction, invalid action (should be called as an animation)");
368 
369 	_vm->_pathFind->_curStep = 1;
370 	float px = _px + _dx;
371 	float pz = _pz + _dz;
372 	float theta = _theta;
373 
374 	_vm->_pathFind->reset(0, px, pz, theta);
375 
376 	float t = ((270.0f - theta) * PI2) / 360.0f;
377 	float ox = cos(t);
378 	float oz = sin(t);
379 
380 	SVertex *v = _characterArea;
381 	float firstFrame = frameCenter(v);
382 
383 	int cfp = 0;
384 	int cur = 0;
385 
386 	while (cur < action)
387 		cfp += defActionLen[cur++];
388 	v = &_characterArea[cfp * _vertexNum];
389 
390 	if (action == hWALKOUT)
391 		v = &_characterArea[_vertexNum];
392 	else if (action == hLAST)
393 		v = _characterArea;
394 
395 	int len = defActionLen[action];
396 
397 	int stepIdx;
398 	for (stepIdx = _vm->_pathFind->_curStep; stepIdx < len + _vm->_pathFind->_curStep; ++stepIdx) {
399 		float curLen = frameCenter(v) - firstFrame;
400 
401 		SStep *curStep = &_vm->_pathFind->_step[stepIdx];
402 		curStep->_dx = curLen * ox;
403 		curStep->_dz = curLen * oz;
404 		curStep->_px = px;
405 		curStep->_pz = pz;
406 		curStep->_curAction = action;
407 		curStep->_curFrame = stepIdx - _vm->_pathFind->_curStep;
408 		curStep->_theta = theta;
409 		curStep->_curPanel = _vm->_pathFind->_curPanel;
410 
411 		v += _vertexNum;
412 
413 		if (action == hLAST)
414 			v = _characterArea;
415 	}
416 
417 	_vm->_pathFind->reset(stepIdx, px, pz, theta);
418 
419 	_vm->_pathFind->_lastStep = stepIdx; // Last step
420 
421 	// Starts action
422 	if (_vm->_obj[_vm->_curObj].isFlagRoomOut())
423 		_vm->_scheduler->doEvent(MC_CHARACTER, ME_CHARACTERGOTOEXIT, MP_DEFAULT, _vm->_obj[_vm->_curObj]._goRoom, 0, _vm->_obj[_vm->_curObj]._ninv, _vm->_curObj);
424 	else
425 		_vm->_scheduler->doEvent(MC_CHARACTER, ME_CHARACTERDOACTION, MP_DEFAULT, 0, 0, 0, 0);
426 }
427 
actorStop()428 void Actor::actorStop() {
429 	_vm->_pathFind->reset(0, _px + _dx, _pz + _dz, _theta);
430 	_vm->_pathFind->_characterGoToPosition = -1;
431 	_vm->_pathFind->_curStep = 0;
432 	_vm->_pathFind->_lastStep = 0;
433 }
434 
read3D(Common::SeekableReadStreamEndian * ff)435 void Actor::read3D(Common::SeekableReadStreamEndian *ff) {
436 	// read rooms and lights
437 	SCamera *cam = _camera;
438 	cam->_ex = ff->readFloat();
439 	cam->_ey = ff->readFloat();
440 	cam->_ez = ff->readFloat();
441 	for (int i = 0; i < 3; ++i)
442 		cam->_e1[i] = ff->readFloat();
443 	for (int i = 0; i < 3; ++i)
444 		cam->_e2[i] = ff->readFloat();
445 	for (int i = 0; i < 3; ++i)
446 		cam->_e3[i] = ff->readFloat();
447 	cam->_fovX = ff->readFloat();
448 	cam->_fovY = ff->readFloat();
449 
450 	_lightNum = ff->readUint32();
451 	if (_lightNum > MAXLIGHT)
452 		error("read3D(): Too many lights");
453 
454 	for (uint32 i = 0; i < _lightNum; ++i) {
455 		_light[i]._x = ff->readFloat();
456 		_light[i]._y = ff->readFloat();
457 		_light[i]._z = ff->readFloat();
458 		_light[i]._dx = ff->readFloat();
459 		_light[i]._dy = ff->readFloat();
460 		_light[i]._dz = ff->readFloat();
461 		_light[i]._inr = ff->readFloat();
462 		_light[i]._outr = ff->readFloat();
463 		_light[i]._hotspot = ff->readByte();
464 		_light[i]._fallOff = ff->readByte();
465 		_light[i]._inten = ff->readSByte();
466 		_light[i]._position = ff->readSByte();
467 	}
468 }
469 
frameCenter(SVertex * v)470 float Actor::frameCenter(SVertex *v) {
471 	return (-v[86]._z - v[164]._z) / 2.0;
472 }
473 
actorRectIsValid() const474 bool Actor::actorRectIsValid() const {
475 	return _lim[0] < _lim[1] && _lim[2] < _lim[3];
476 }
477 
getActorRect() const478 Common::Rect Actor::getActorRect() const {
479 	return Common::Rect(_lim[0], _lim[2], _lim[1], _lim[3]);
480 }
481 
482 } // End of namespace Trecision
483