1 #ifndef H_DEBUG
2 #define H_DEBUG
3 
4 #include "core.h"
5 #include "format.h"
6 #include "controller.h"
7 #include "mesh.h"
8 
9 namespace Debug {
10 
11     static GLuint font;
12 
init()13     void init() {
14         #ifdef _OS_WIN
15             font = glGenLists(256);
16             HDC hdc = GetDC(0);
17             HFONT hfont = CreateFontA(-MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0,
18                                      0, 0, FW_BOLD, 0, 0, 0,
19                                      ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
20                                      ANTIALIASED_QUALITY, DEFAULT_PITCH, "Courier New");
21             SelectObject(hdc, hfont);
22             wglUseFontBitmaps(hdc, 0, 256, font);
23             DeleteObject(hfont);
24         #elif _OS_LINUX
25             XFontStruct *fontInfo;
26             Font id;
27             unsigned int first, last;
28             fontInfo = XLoadQueryFont(glXGetCurrentDisplay(), "-adobe-times-medium-r-normal--17-120-100-100-p-88-iso8859-1");
29 
30             if (fontInfo == NULL) {
31                 LOG("no font found\n");
32             }
33 
34             id = fontInfo->fid;
35             first = fontInfo->min_char_or_byte2;
36             last = fontInfo->max_char_or_byte2;
37 
38             font = glGenLists(last + 1);
39             if (font == 0) {
40                 LOG("out of display lists\n");
41             }
42             glXUseXFont(id, first, last - first + 1, font + first);
43         #endif
44     }
45 
deinit()46     void deinit() {
47         glDeleteLists(font, 256);
48     }
49 
begin()50     void begin() {
51     #ifndef FFP
52         glActiveTexture(GL_TEXTURE0);
53         glUseProgram(0);
54     #endif
55         glDisable(GL_TEXTURE_2D);
56         glMatrixMode(GL_PROJECTION);
57         glLoadMatrixf((GLfloat*)&Core::mProj);
58         glMatrixMode(GL_MODELVIEW);
59         glLoadIdentity();
60         glLoadMatrixf((GLfloat*)&Core::mView);
61 
62         glLineWidth(3);
63         glPointSize(32);
64 
65         Core::active.shader = NULL;
66         Core::active.textures[0] = NULL;
67         Core::validateRenderState();
68     }
69 
end()70     void end() {
71         glEnable(GL_TEXTURE_2D);
72     }
73 
74     namespace Draw {
75 
box(const vec3 & min,const vec3 & max,const vec4 & color)76         void box(const vec3 &min, const vec3 &max, const vec4 &color) {
77             glColor4fv((GLfloat*)&color);
78             glBegin(GL_LINES);
79                 glVertex3f(min.x, min.y, min.z);
80                 glVertex3f(max.x, min.y, min.z);
81                 glVertex3f(min.x, max.y, min.z);
82                 glVertex3f(max.x, max.y, min.z);
83 
84                 glVertex3f(min.x, min.y, max.z);
85                 glVertex3f(max.x, min.y, max.z);
86                 glVertex3f(min.x, max.y, max.z);
87                 glVertex3f(max.x, max.y, max.z);
88 
89                 glVertex3f(min.x, min.y, min.z);
90                 glVertex3f(min.x, min.y, max.z);
91                 glVertex3f(min.x, max.y, min.z);
92                 glVertex3f(min.x, max.y, max.z);
93 
94                 glVertex3f(max.x, min.y, min.z);
95                 glVertex3f(max.x, min.y, max.z);
96                 glVertex3f(max.x, max.y, min.z);
97                 glVertex3f(max.x, max.y, max.z);
98 
99                 glVertex3f(min.x, min.y, min.z);
100                 glVertex3f(min.x, max.y, min.z);
101 
102                 glVertex3f(max.x, min.y, min.z);
103                 glVertex3f(max.x, max.y, min.z);
104                 glVertex3f(min.x, min.y, min.z);
105                 glVertex3f(min.x, max.y, min.z);
106 
107                 glVertex3f(max.x, min.y, max.z);
108                 glVertex3f(max.x, max.y, max.z);
109                 glVertex3f(min.x, min.y, max.z);
110                 glVertex3f(min.x, max.y, max.z);
111             glEnd();
112         }
113 
box(const mat4 & m,const vec3 & min,const vec3 & max,const vec4 & color)114         void box(const mat4 &m, const vec3 &min, const vec3 &max, const vec4 &color) {
115             glPushMatrix();
116             glMultMatrixf((GLfloat*)&m);
117             box(min, max, color);
118             glPopMatrix();
119         }
120 
sphere(const vec3 & center,const float radius,const vec4 & color)121         void sphere(const vec3 &center, const float radius, const vec4 &color) {
122             const float k = PI * 2.0f / 18.0f;
123 
124             glColor4fv((GLfloat*)&color);
125             for (int j = 0; j < 3; j++) {
126                 glBegin(GL_LINE_STRIP);
127                 for (int i = 0; i < 19; i++) {
128                     vec3 p = vec3(sinf(i * k), cosf(i * k), 0.0f) * radius;
129                     glVertex3f(p[j] + center.x, p[(j + 1) % 3] + center.y, p[(j + 2) % 3] + center.z);
130                 }
131                 glEnd();
132             }
133         }
134 
mesh(vec3 * vertices,Index * indices,int iCount)135         void mesh(vec3 *vertices, Index *indices, int iCount) {
136             glBegin(GL_LINES);
137             for (int i = 0; i < iCount; i += 3) {
138                 vec3 &a = vertices[indices[i + 0]];
139                 vec3 &b = vertices[indices[i + 1]];
140                 vec3 &c = vertices[indices[i + 2]];
141                 glVertex3fv((GLfloat*)&a);
142                 glVertex3fv((GLfloat*)&b);
143 
144                 glVertex3fv((GLfloat*)&b);
145                 glVertex3fv((GLfloat*)&c);
146 
147                 glVertex3fv((GLfloat*)&c);
148                 glVertex3fv((GLfloat*)&a);
149             }
150             glEnd();
151         }
152 
axes(float size)153         void axes(float size) {
154             glBegin(GL_LINES);
155                 glColor3f(1, 0, 0); glVertex3f(0, 0, 0); glVertex3f(size,    0,    0);
156                 glColor3f(0, 1, 0); glVertex3f(0, 0, 0); glVertex3f(   0, size,    0);
157                 glColor3f(0, 0, 1); glVertex3f(0, 0, 0); glVertex3f(   0,    0, size);
158             glEnd();
159         }
160 
point(const vec3 & p,const vec4 & color)161         void point(const vec3 &p, const vec4 &color) {
162             glColor4fv((GLfloat*)&color);
163             glBegin(GL_POINTS);
164                 glVertex3fv((GLfloat*)&p);
165             glEnd();
166         }
167 
line(const vec3 & a,const vec3 & b,const vec4 & color)168         void line(const vec3 &a, const vec3 &b, const vec4 &color) {
169             glBegin(GL_LINES);
170                 glColor4fv((GLfloat*)&color);
171                 glVertex3fv((GLfloat*)&a);
172                 glVertex3fv((GLfloat*)&b);
173             glEnd();
174         }
175 
textColor(const vec2 & pos,const vec4 & color,const char * str)176         void textColor(const vec2 &pos, const vec4 &color, const char *str) {
177             glMatrixMode(GL_MODELVIEW);
178             glPushMatrix();
179             glLoadIdentity();
180 
181             glMatrixMode(GL_PROJECTION);
182             glPushMatrix();
183             glLoadIdentity();
184             glOrtho(0, Core::width, Core::height, 0, 0, 1);
185 
186             Core::setDepthTest(false);
187             Core::setCullMode(cmNone);
188             Core::validateRenderState();
189 
190             glColor4fv((GLfloat*)&color);
191             glRasterPos2f(pos.x, pos.y);
192             glListBase(font);
193             glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
194             Core::setDepthTest(true);
195             Core::setCullMode(cmFront);
196 
197             glPopMatrix();
198             glMatrixMode(GL_MODELVIEW);
199             glPopMatrix();
200         }
201 
text(const vec2 & pos,const vec4 & color,const char * str)202         void text(const vec2 &pos, const vec4 &color, const char *str) {
203             textColor(pos + vec2(1.0f), vec4(0.0f, 0.0f, 0.0f, 1.0f), str);
204             textColor(pos, color, str);
205         }
206 
text(const vec3 & pos,const vec4 & color,const char * str)207         void text(const vec3 &pos, const vec4 &color, const char *str) {
208             vec4 p = Core::mViewProj * vec4(pos, 1);
209             if (p.w > 0) {
210                 p.xyz() = p.xyz() * (1.0f / p.w);
211                 p.y = -p.y;
212                 p.xyz() = (p.xyz() * 0.5f + vec3(0.5f)) * vec3(float(Core::width), float(Core::height), 1.0f);
213                 text(vec2(p.x, p.y), color, str);
214             }
215         }
216     }
217 
218     namespace Level {
219 
220         #define case_name(a,b) case a::b : return #b
221 
getTriggerType(const TR::Level & level,const TR::Level::Trigger::Type & trigger)222         const char *getTriggerType(const TR::Level &level, const TR::Level::Trigger::Type &trigger) {
223             switch (trigger) {
224                 case_name(TR::Level::Trigger, ACTIVATE );
225                 case_name(TR::Level::Trigger, PAD      );
226                 case_name(TR::Level::Trigger, SWITCH   );
227                 case_name(TR::Level::Trigger, KEY      );
228                 case_name(TR::Level::Trigger, PICKUP   );
229                 case_name(TR::Level::Trigger, HEAVY    );
230                 case_name(TR::Level::Trigger, ANTIPAD  );
231                 case_name(TR::Level::Trigger, COMBAT   );
232                 case_name(TR::Level::Trigger, DUMMY    );
233             }
234             return "UNKNOWN";
235         }
236 
getTriggerAction(const TR::Level & level,uint16 action)237         const char *getTriggerAction(const TR::Level &level, uint16 action) {
238             switch (action) {
239                 case_name(TR::Action, ACTIVATE      );
240                 case_name(TR::Action, CAMERA_SWITCH );
241                 case_name(TR::Action, FLOW          );
242                 case_name(TR::Action, FLIP          );
243                 case_name(TR::Action, FLIP_ON       );
244                 case_name(TR::Action, FLIP_OFF      );
245                 case_name(TR::Action, CAMERA_TARGET );
246                 case_name(TR::Action, END           );
247                 case_name(TR::Action, SOUNDTRACK    );
248                 case_name(TR::Action, EFFECT        );
249                 case_name(TR::Action, SECRET        );
250             }
251             return "UNKNOWN";
252         }
253 
254         const char *TR_TYPE_NAMES[] = { TR_TYPES(DECL_STR) };
255 
getEntityName(const TR::Level & level,const TR::Entity & entity)256         const char *getEntityName(const TR::Level &level, const TR::Entity &entity) {
257             if (entity.type < TR::Entity::TR1_TYPE_MAX)
258                 return TR_TYPE_NAMES[entity.type - TR1_TYPES_START];
259             if (entity.type < TR::Entity::TR2_TYPE_MAX)
260                 return TR_TYPE_NAMES[entity.type - TR2_TYPES_START + (TR::Entity::TR1_TYPE_MAX - TR1_TYPES_START) + 1];
261             if (entity.type < TR::Entity::TR3_TYPE_MAX)
262                 return TR_TYPE_NAMES[entity.type - TR3_TYPES_START + (TR::Entity::TR1_TYPE_MAX - TR1_TYPES_START) + (TR::Entity::TR2_TYPE_MAX - TR2_TYPES_START) + 2];
263             if (entity.type < TR::Entity::TR4_TYPE_MAX)
264                 return TR_TYPE_NAMES[entity.type - TR4_TYPES_START + (TR::Entity::TR1_TYPE_MAX - TR1_TYPES_START) + (TR::Entity::TR2_TYPE_MAX - TR2_TYPES_START) + (TR::Entity::TR3_TYPE_MAX - TR3_TYPES_START) + 3];
265 
266             return "UNKNOWN";
267         }
268 
269         void debugFloor(IGame *game, int roomIndex, int x, int y, int z, int zone = -1) {
270             TR::Level *level = game->getLevel();
271 
272             if (zone != -1) {
273                 int dx, dz;
274                 TR::Room::Sector &s = level->getSector(roomIndex, x, z, dx, dz);
275                 if (zone != level->zones[0].ground1[s.boxIndex])
276                     return;
277             }
278 
279             TR::Level::FloorInfo info;
280 
281             vec3 rf[4], rc[4], f[4], c[4];
282 
283             int offsets[4][2] = { { 1, 1 }, { 1023, 1 }, { 1023, 1023 }, { 1, 1023 } };
284 
285             for (int i = 0; i < 4; i++) {
286                 game->getLara()->getFloorInfo(roomIndex, vec3(float(x + offsets[i][0]), float(y), float(z + offsets[i][1])), info);
287                 rf[i] = vec3( float(x + offsets[i][0]), info.roomFloor - 4,   float(z + offsets[i][1]) );
288                 rc[i] = vec3( float(x + offsets[i][0]), info.roomCeiling + 4, float(z + offsets[i][1]) );
289                 f[i]  = vec3( float(x + offsets[i][0]), info.floor - 4,       float(z + offsets[i][1]) );
290                 c[i]  = vec3( float(x + offsets[i][0]), info.ceiling + 4,     float(z + offsets[i][1]) );
291 
292                 /*
293                 int px = x + offsets[i][0];
294                 int py = y;
295                 int pz = z + offsets[i][1];
296 
297                 int dx, dz;
298 
299                 int16 ridx = roomIndex;
300                 TR::Room::Sector *sector = game->getLevel()->getSectorNext(ridx, px, py, pz);
301                 int floor = game->getLevel()->getFloor(sector, px, py, pz);
302                 int ceiling = game->getLevel()->getCeiling(sector, px, py, pz);
303 
304                 f[i]  = vec3( px, floor - 4,   pz );
305                 c[i]  = vec3( px, ceiling + 4, pz );
306                 */
307                 if (info.roomBelow == TR::NO_ROOM) rf[i].y = f[i].y;
308                 if (info.roomAbove == TR::NO_ROOM) rc[i].y = c[i].y;
309             }
310 
311             if (info.roomNext != 0xFF) {
312                 glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
313                 glBegin(GL_QUADS);
314                     glVertex3fv((GLfloat*)&f[3]);
315                     glVertex3fv((GLfloat*)&f[2]);
316                     glVertex3fv((GLfloat*)&f[1]);
317                     glVertex3fv((GLfloat*)&f[0]);
318                 glEnd();
319             } else {
320 
321                 glColor4f(0.0f, 1.0f, 0.0f, 0.1f);
322                 glBegin(GL_QUADS);
323                     glVertex3fv((GLfloat*)&f[3]);
324                     glVertex3fv((GLfloat*)&f[2]);
325                     glVertex3fv((GLfloat*)&f[1]);
326                     glVertex3fv((GLfloat*)&f[0]);
327                 glEnd();
328 
329                 if (info.trigCmdCount > 0)
330                     glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
331                 else
332                     glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
333                 glBegin(GL_LINE_STRIP);
334                     for (int i = 0; i < 5; i++)
335                         glVertex3fv((GLfloat*)&rf[i % 4]);
336                 glEnd();
337             }
338 
339             glColor4f(1.0f, 0.0f, 0.0f, 0.1f);
340             glBegin(GL_QUADS);
341                 glVertex3fv((GLfloat*)&c[0]);
342                 glVertex3fv((GLfloat*)&c[1]);
343                 glVertex3fv((GLfloat*)&c[2]);
344                 glVertex3fv((GLfloat*)&c[3]);
345             glEnd();
346 
347             if (info.trigCmdCount > 0)
348                 glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
349             else
350                 glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
351             glBegin(GL_LINE_STRIP);
352                 for (int i = 0; i < 5; i++)
353                     glVertex3fv((GLfloat*)&rc[i % 4]);
354             glEnd();
355 
356 
357             glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
358 
359             /*
360             if (boxIndex == 0xFFFF) {
361                 glBegin(GL_LINES);
362                     float x = f.x + 512.0f, z = f.z + 512.0f;
363                     glVertex3f(x, f.y, z);
364                     glVertex3f(x, c.y, z);
365                 glEnd();
366             }*/
367         }
368 
debugBox(const TR::Box & b)369         void debugBox(const TR::Box &b) {
370             glBegin(GL_QUADS);
371                 float y = b.floor - 16.0f;
372                 glVertex3f(float(b.minX), y, float(b.maxZ));
373                 glVertex3f(float(b.maxX), y, float(b.maxZ));
374                 glVertex3f(float(b.maxX), y, float(b.minZ));
375                 glVertex3f(float(b.minX), y, float(b.minZ));
376             glEnd();
377         }
378 
blocks(const TR::Level & level)379         void blocks(const TR::Level &level) {
380             Core::setDepthTest(false);
381             char buf[64];
382 
383             for (int j = 0; j < level.roomsCount; j++) {
384                 TR::Room &r = level.rooms[j];
385 
386                 for (int z = 0; z < r.zSectors; z++)
387                     for (int x = 0; x < r.xSectors; x++) {
388                         TR::Room::Sector &s = r.sectors[x * r.zSectors + z];
389                         if (s.boxIndex != 0xFFFF) {
390                             bool blockable = level.boxes[s.boxIndex].overlap.blockable;
391                             bool block     = level.boxes[s.boxIndex].overlap.block;
392                             int  floor     = level.boxes[s.boxIndex].floor;
393 
394                             if (blockable || block) {
395                                 sprintf(buf, "blocked: %s", block ? "true" : "false");
396                                 Debug::Draw::text(vec3(float(r.info.x + x * 1024 + 512), float(floor), float(r.info.z + z * 1024 + 512)), vec4(1, 1, 0, 1), buf);
397                             }
398                         }
399                     }
400             }
401 
402             Core::setDepthTest(true);
403         }
404 
debugOverlaps(const TR::Level & level,int boxIndex)405         void debugOverlaps(const TR::Level &level, int boxIndex) {
406             char str[64];
407 
408             TR::Box &b = level.boxes[boxIndex];
409             sprintf(str, "%d", boxIndex);
410             Draw::text(vec3((b.maxX + b.minX) * 0.5f, b.floor, (b.maxZ + b.minZ) * 0.5f), vec4(0, 1, 0, 1), str);
411             glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
412             Core::setBlendMode(bmAlpha);
413             debugBox(b);
414 
415             TR::Overlap *o = &level.overlaps[level.boxes[boxIndex].overlap.index];
416             do {
417                 TR::Box &b = level.boxes[o->boxIndex];
418                 sprintf(str, "%d", o->boxIndex);
419                 Draw::text(vec3((b.maxX + b.minX) * 0.5f, b.floor, (b.maxZ + b.minZ) * 0.5f), vec4(0, 0, 1, 1), str);
420                 glColor4f(0.0f, 0.0f, 1.0f, 0.25f);
421                 Core::setBlendMode(bmAlpha);
422                 debugBox(b);
423             } while (!(o++)->end);
424         }
425 
debugBoxes(const TR::Level & level,uint16 * boxes,int count)426         void debugBoxes(const TR::Level &level, uint16 *boxes, int count) {
427             if (!boxes) return;
428 
429             glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
430             Core::setBlendMode(bmAlpha);
431             Core::setDepthTest(false);
432             Core::validateRenderState();
433             for (int i = 0; i < count; i++)
434                 debugBox(level.boxes[boxes[i]]);
435             Core::setDepthTest(true);
436         }
437 
438         void sectors(IGame *game, int roomIndex, int y, int zone = -1) {
439             TR::Room &room = game->getLevel()->rooms[roomIndex];
440 
441             for (int z = 0; z < room.zSectors; z++)
442                 for (int x = 0; x < room.xSectors; x++)
443                     debugFloor(game, roomIndex, room.info.x + x * 1024, y, room.info.z + z * 1024, zone);
444         }
445 
rooms(const TR::Level & level,const vec3 & pos,int roomIndex)446         void rooms(const TR::Level &level, const vec3 &pos, int roomIndex) {
447             glDepthMask(GL_FALSE);
448 
449             for (int i = 0; i < level.roomsCount; i++) {
450                 TR::Room &r = level.rooms[i];
451                 vec3 p = vec3(float(r.info.x), float(r.info.yTop), float(r.info.z));
452 
453                 if (i == roomIndex) {
454                 //if (lara->insideRoom(Core::viewPos, i)) {
455                    // sectors(level, i);
456                     glColor3f(0, 1, 0);
457                 } else
458                     glColor3f(1, 1, 1);
459 
460             //    Debug::Draw::box(p, p + vec3(r.xSectors * 1024, r.info.yBottom - r.info.yTop, r.zSectors * 1024));
461             }
462 
463             glDepthMask(GL_TRUE);
464         }
465 
portals(const TR::Level & level)466         void portals(const TR::Level &level) {
467             Core::setBlendMode(bmAdd);
468             glColor3f(0, 0.25f, 0.25f);
469             glDepthMask(GL_FALSE);
470 
471             glBegin(GL_QUADS);
472             for (int i = 0; i < level.roomsCount; i++) {
473                 TR::Room &r = level.rooms[i];
474                 for (int j = 0; j < r.portalsCount; j++) {
475                     TR::Room::Portal &p = r.portals[j];
476                     for (int k = 0; k < 4; k++) {
477                         short3 &v = p.vertices[k];
478                         glVertex3f(float(v.x + r.info.x), float(v.y), float(v.z + r.info.z));
479                     }
480                 }
481             }
482             glEnd();
483 
484             glDepthMask(GL_TRUE);
485             Core::setBlendMode(bmNone);
486         }
487 
entities(const TR::Level & level)488         void entities(const TR::Level &level) {
489             char buf[255];
490 
491             for (int i = 0; i < level.entitiesCount; i++) {
492                 TR::Entity &e = level.entities[i];
493                 Controller *controller = (Controller*)e.controller;
494                 if (!controller) continue;
495 
496                 sprintf(buf, "%s (%d) %s", getEntityName(level, e), i, controller->flags.invisible ? "INVISIBLE" : "");
497                 Debug::Draw::text(controller->getPos() + randf() * 64.0f, controller->flags.active ? vec4(0, 0, 0.8f, 1) : vec4(0.8f, 0, 0, 1), buf);
498             }
499 
500             for (int i = 0; i < level.camerasCount; i++) {
501                 TR::Camera &c = level.cameras[i];
502 
503                 sprintf(buf, "%d (%d)", i, c.room);
504                 Debug::Draw::text(vec3(float(c.x), float(c.y), float(c.z)), vec4(0, 0.8f, 0, 1), buf);
505             }
506         }
507 
path(TR::Level & level,Enemy * enemy)508         void path(TR::Level &level, Enemy *enemy) {
509             Enemy::Path *path = enemy->path;
510 
511             if (!path || !enemy->target) return;
512             for (int i = 0; i < path->count; i++) {
513                 TR::Box &b = level.boxes[path->boxes[i]];
514                 if (i == path->index)
515                     glColor4f(0.5, 0.5, 0.0, 0.5);
516                 else
517                     glColor4f(0.0, 0.5, 0.0, 0.5);
518                 debugBox(b);
519             }
520 
521             Core::setDepthTest(false);
522             Draw::point(enemy->waypoint, vec4(1.0));
523             Core::setDepthTest(true);
524         }
525 
zones(IGame * game,Lara * lara)526         void zones(IGame *game, Lara *lara) {
527             TR::Level *level = game->getLevel();
528 
529             Core::setDepthTest(false);
530             for (int i = 0; i < level->roomsCount; i++)
531                 sectors(game, i, int(lara->pos.y), lara->zone);
532             Core::setDepthTest(true);
533 
534             char buf[64];
535             for (int i = 0; i < level->entitiesCount; i++) {
536                 TR::Entity &e = level->entities[i];
537 
538                 if (!e.controller || !e.isEnemy()) continue;
539 
540                 Character *controller = (Character*)e.controller;
541                 sprintf(buf, "zone: %d", controller->zone);
542                 Debug::Draw::text(controller->pos - vec3(0, 128, 0), vec4(0, 1, 0.8f, 1), buf);
543             }
544         }
545 
lights(const TR::Level & level,int room,Controller * lara)546         void lights(const TR::Level &level, int room, Controller *lara) {
547             glPointSize(8);
548             for (int i = 0; i < level.roomsCount; i++)
549                 for (int j = 0; j < level.rooms[i].lightsCount; j++) {
550                     TR::Room::Light &l = level.rooms[i].lights[j];
551                     vec3 p = vec3(float(l.x), float(l.y), float(l.z));
552                     vec4 color = vec4(l.color.r, l.color.g, l.color.b, 255) * (1.0f / 255.0f);
553 
554 //                    if (i == room) color.x = color.z = 0;
555                     Debug::Draw::point(p, color);
556                     //if (i == roomIndex && j == lightIndex)
557                     //    color = vec4(0, 1, 0, 1);
558                     Debug::Draw::sphere(p, float(l.radius), color);
559                 }
560 
561             vec4 color = vec4(lara->mainLightColor.xyz(), 1.0f);
562             Debug::Draw::point(lara->mainLightPos, color);
563             Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, color);
564         }
565 
meshes(const TR::Level & level)566         void meshes(const TR::Level &level) {
567         // static objects
568             for (int i = 0; i < level.roomsCount; i++) {
569                 TR::Room &r = level.rooms[i];
570 
571                 for (int j = 0; j < r.meshesCount; j++) {
572                     TR::Room::Mesh &m  = r.meshes[j];
573                     TR::StaticMesh *sm = &level.staticMeshes[m.meshIndex];
574 
575                     Box box;
576                     vec3 offset = vec3(float(m.x), float(m.y), float(m.z));
577                     sm->getBox(false, m.rotation, box); // visible box
578 
579                     Debug::Draw::box(offset + box.min, offset + box.max, vec4(1, 1, 0, 0.25));
580 
581                     if (sm->flags == 2) { // collision box
582                         sm->getBox(true, m.rotation, box);
583                         Debug::Draw::box(offset + box.min - vec3(10.0f), offset + box.max + vec3(10.0f), vec4(1, 0, 0, 0.50));
584                     }
585 
586                     if (!level.meshOffsets[sm->mesh]) continue;
587                     const TR::Mesh &mesh = level.meshes[level.meshOffsets[sm->mesh]];
588                     /*
589                     {
590                         char buf[255];
591                         sprintf(buf, "flags %d", (int)mesh.flags.value);
592                         Debug::Draw::text(offset + (box.min + box.max) * 0.5f, vec4(0.5, 0.5, 1.0, 1), buf);
593                     }
594                     */
595 
596                 }
597             }
598         // dynamic objects
599             for (int i = 0; i < level.entitiesCount; i++) {
600                 TR::Entity &e = level.entities[i];
601                 Controller *controller = (Controller*)e.controller;
602                 if (!controller) continue;
603 
604                 mat4 matrix = controller->getMatrix();
605                 Basis basis(matrix);
606 
607                 const TR::Model *m = controller->getModel();
608                 if (!m) continue;
609 
610                 bool bboxIntersect = false;
611 
612                 ASSERT(m->mCount <= 34);
613 
614                 int mask = 0;
615                 for (int j = 0; j < level.entitiesCount; j++) {
616                     TR::Entity &t = level.entities[j];
617                     Controller *enemy = (Controller*)t.controller;
618                     if (!enemy) continue;
619                     if (j == i || ((!t.isEnemy() || !enemy->flags.active) && !t.isLara())) continue;
620                     if (!enemy || !controller->getBoundingBox().intersect(enemy->getBoundingBox()))
621                         continue;
622                     bboxIntersect = true;
623                     mask |= controller->collide(enemy);
624                 }
625 
626                 Box box = controller->getBoundingBoxLocal();
627                 Debug::Draw::box(matrix, box.min, box.max, bboxIntersect ? vec4(1, 0, 0, 1): vec4(1));
628 
629                 Sphere spheres[MAX_JOINTS];
630                 int count = controller->getSpheres(spheres);
631 
632                 for (int joint = 0; joint < count; joint++) {
633                     Sphere &sphere = spheres[joint];
634                     Debug::Draw::sphere(sphere.center, sphere.radius, (mask & (1 << joint)) ? vec4(1, 0, 0, 0.5f) : vec4(0, 1, 1, 0.5f));
635                     /*
636                     { //if (e.id != 0) {
637                         char buf[255];
638                         sprintf(buf, "(%d) radius %d flags %d", (int)e.type, (int)mesh->radius, (int)mesh->flags.value);
639                         Debug::Draw::text(sphere.center, vec4(0.5, 1, 0.5, 1), buf);
640                     }
641                     */
642                 }
643             }
644         }
645 
dumpSample(TR::Level * level,int index)646         void dumpSample(TR::Level *level, int index) {
647             char buf[255];
648             sprintf(buf, "samples_PSX/%03d.wav", index);
649             FILE *f = fopen(buf, "wb");
650 
651             if (level->version == TR::VER_TR1_PSX) {
652                 uint32 dataSize = level->soundSize[index] / 16 * 28 * 2 * 4;
653 
654                 struct Header {
655                     uint32 RIFF;
656                     uint32 rSize;
657                     uint32 WAVE;
658                     uint32 fmt;
659                     uint32 wSize;
660                     struct {
661                         uint16  format;
662                         uint16  channels;
663                         uint32  samplesPerSec;
664                         uint32  bytesPerSec;
665                         uint16  block;
666                         uint16  sampleBits;
667                     } fmtHeader;
668                     uint32 data;
669                     uint32 dataSize;
670                 } header = {
671                         FOURCC("RIFF"), sizeof(Header) - 8 + dataSize,
672                         FOURCC("WAVE"), FOURCC("fmt "), 16,
673                         { 1, 1, 44100, 44100 * 16 / 8, 0, 16 },
674                         FOURCC("data"), dataSize
675                     };
676 
677                 fwrite(&header, sizeof(header), 1, f);
678 
679                 Sound::VAG vag(new Stream(NULL, &level->soundData[level->soundOffsets[index]], dataSize));
680                 Sound::Frame frames[4 * 28];
681                 while (int count = vag.decode(frames, 4 * 28))
682                     for (int i = 0; i < count; i++)
683                         fwrite(&frames[i].L, 2, 1, f);
684             }
685 
686             if (level->version == TR::VER_TR1_PC) {
687                 uint32 *data = (uint32*)&level->soundData[level->soundOffsets[index]];
688                 fwrite(data, data[1] + 8, 1, f);
689             }
690 
691             fclose(f);
692         }
693 
info(IGame * game,Controller * controller,Animation & anim)694         void info(IGame *game, Controller *controller, Animation &anim) {
695             TR::Level &level = *game->getLevel();
696 
697             if (level.isCutsceneLevel()) return;
698 
699             float y = 0.0f;
700 
701             int activeCount = 0;
702             Controller *c = Controller::first;
703             while (c) {
704                 activeCount++;
705                 c = c->next;
706             }
707 
708             vec3 viewPos = ((Lara*)controller)->camera->frustum->pos;
709 
710             char buf[255];
711             sprintf(buf, "DIP = %d, TRI = %d, SND = %d, active = %d", Core::stats.dips, Core::stats.tris, Sound::channelsCount, activeCount);
712             Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
713             vec3 angle = controller->angle * RAD2DEG;
714             sprintf(buf, "pos = (%d, %d, %d), angle = (%d, %d), room = %d (camera: %d [%d, %d, %d])", int(controller->pos.x), int(controller->pos.y), int(controller->pos.z), (int)angle.x, (int)angle.y, controller->getRoomIndex(), game->getCamera()->getRoomIndex(), int(viewPos.x), int(viewPos.y), int(viewPos.z));
715             Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
716             int rate = anim.anims[anim.index].frameRate;
717             sprintf(buf, "state = %d, anim = %d, next = %d, rate = %d, frame = %.2f / %d (%f)", anim.state, anim.index, anim.next, rate, anim.time * 30.0f, anim.framesCount, anim.delta);
718             Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
719 
720             TR::Level::FloorInfo info;
721             controller->getFloorInfo(controller->getRoomIndex(), controller->pos, info);
722             sprintf(buf, "floor = %d, roomBelow = %d, roomAbove = %d, roomNext = %d, height = %d", info.floorIndex, info.roomBelow, info.roomAbove, info.roomNext, int(info.floor - info.ceiling));
723             Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
724 
725             sprintf(buf, "stats: time = %d, distance = %d, secrets = %c%c%c, pickups = %d, mediUsed = %d, ammoUsed = %d, kills = %d", saveStats.time, saveStats.distance,
726                 (saveStats.secrets & 4) ? '1' : '0',
727                 (saveStats.secrets & 2) ? '1' : '0',
728                 (saveStats.secrets & 1) ? '1' : '0', saveStats.pickups, saveStats.mediUsed, saveStats.ammoUsed, saveStats.kills);
729             Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
730 
731             y += 16;
732             if (info.lava)
733                 Debug::Draw::text(vec2(16, y += 16), vec4(1.0f, 0.5f, 0.3f, 1.0f), "LAVA");
734 
735             if (info.climb) {
736                 sprintf(buf, "climb mask:");
737                 if (info.climb & 0x01) strcat(buf, " +Z");
738                 if (info.climb & 0x02) strcat(buf, " +X");
739                 if (info.climb & 0x04) strcat(buf, " -Z");
740                 if (info.climb & 0x08) strcat(buf, " -X");
741                 Debug::Draw::text(vec2(16, y += 16), vec4(0.5f, 0.8f, 0.5f, 1.0f), buf);
742             }
743 
744             if (info.trigCmdCount > 0) {
745                 sprintf(buf, "trigger: %s%s mask: %d timer: %d", getTriggerType(level, info.trigger), info.trigInfo.once ? " (once)" : "", info.trigInfo.mask, info.trigInfo.timer);
746                 Debug::Draw::text(vec2(16, y += 16), vec4(0.5f, 0.8f, 0.5f, 1.0f), buf);
747 
748                 for (int i = 0; i < info.trigCmdCount; i++) {
749                     TR::FloorData::TriggerCommand &cmd = info.trigCmd[i];
750 
751                     const char *ent = (cmd.action == TR::Action::ACTIVATE || cmd.action == TR::Action::CAMERA_TARGET) ? (cmd.args < level.entitiesBaseCount ? getEntityName(level, level.entities[cmd.args]) : "BAD_ENTITY_INDEX") : "";
752                     sprintf(buf, "%s -> %s (%d)", getTriggerAction(level, cmd.action), ent, cmd.args);
753                     if (cmd.action == TR::Action::CAMERA_SWITCH || cmd.action == TR::Action::FLYBY || cmd.action == TR::Action::CUTSCENE) {
754                         i++;
755                         sprintf(buf, "%s delay: %d speed: %d", buf, int(info.trigCmd[i].timer), int(info.trigCmd[i].speed));
756                     }
757 
758                     Debug::Draw::text(vec2(16, y += 16), vec4(0.1f, 0.6f, 0.1f, 1.0f), buf);
759                 }
760             }
761         }
762     }
763 }
764 
765 #endif