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