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 ¢er, 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