Files
Cesarus85--mjolnir-vr/source/physics/collision_debug.c
T

634 lines
22 KiB
C

/*
COLLISION_DEBUG.C
symbols in this file:
00139530 1060:
_collision_debug_render (0000)
0028B2A8 0060:
_rdata_0028b2a8 (0000)
0028B308 000a:
??_C@_09PCOGIILP@count?$DM?$DN14?$AA@ (0000)
0028B314 0031:
??_C@_0DB@EBGLDBDO@plane?5?$CD?$CFd?$CFs?$HMnsurface?5?$CD?$CFd?$CFs?$CFs?$CFs?$CFs@ (0000)
0028B348 0004:
__real@42652ee0 (0000)
0028B34C 0009:
??_C@_08JNJLEJIF@?5negated?$AA@ (0000)
0028B358 000b:
??_C@_0L@DMHIANBO@?5two?9sided?$AA@ (0000)
0028B364 000b:
??_C@_0L@OFKNNBE@?5invisible?$AA@ (0000)
0028B370 000b:
??_C@_0L@JOKAPIDA@?5climbable?$AA@ (0000)
0028B37C 000b:
??_C@_0L@KCGACEBO@?5breakable?$AA@ (0000)
0028B388 000c:
??_C@_0M@CIBLPKPA@phantom?5bsp?$AA@ (0000)
0028B394 0004:
__real@3e162051 (0000)
0028B398 0004:
__real@bd962051 (0000)
0028B3A0 0008:
__real@401921fb60000000 (0000)
0028B3A8 0029:
??_C@_0CJ@OKHLJDEM@c?3?2halo?2SOURCE?2physics?2collision@ (0000)
0030CD44 0010:
_collision_debug_flag_front_facing_surfaces (0000)
_collision_debug_flag_ignore_invisible_surfaces (0001)
_collision_debug_flag_structure (0002)
_collision_debug_flag_media (0003)
_collision_debug_flag_objects (0004)
_collision_debug_length (0008)
_collision_debug_ignore_object_index (000c)
00456EC0 7122:
_bss_00456ec0 (0000)
_collision_debug_width (7118)
_collision_debug_height (711c)
_collision_debug_phantom_bsp (7120)
_collision_debug_phantom_bsp_found (7121)
*/
/* ---------- headers */
#include "cseries.h"
#include "collision_debug.h"
#include "breakable_surfaces.h"
#include "collision_bsp.h"
#include "collision_bsp_definitions.h"
#include "collision_features.h"
#include "collisions.h"
#include "collision_usage.h"
#include "objects.h"
#include "tag_files/tag_files.h"
#include "collision_model_definitions.h"
#include "collision_models.h"
#include "game/game.h"
#include "game/game_globals.h"
#include "game/players.h"
#include "memory/data.h"
#include "render/render.h"
#include "render/render_cameras_internal.h"
#include "render/render_debug.h"
#include "scenario/scenario.h"
#include "tag_files/tag_groups.h"
/* ---------- constants */
enum
{
MAXIMUM_COLLISION_DEBUG_RESULTS = 14,
MAXIMUM_COLLISION_DEBUG_PATH_POINTS = MAXIMUM_COLLISION_DEBUG_RESULTS + 2,
COLLISION_DEBUG_SPRAY_COLUMNS = 40,
COLLISION_DEBUG_SPRAY_ROWS = 30,
COLLISION_DEBUG_SPRAY_COUNT = COLLISION_DEBUG_SPRAY_COLUMNS * COLLISION_DEBUG_SPRAY_ROWS,
};
enum collision_surface_flags
{
_collision_surface_two_sided_bit = 0,
_collision_surface_invisible_bit,
_collision_surface_climbable_bit,
_collision_surface_breakable_bit,
};
/* ---------- macros */
/* ---------- structures */
struct collision_debug_spray_cache
{
real_vector3d normals[COLLISION_DEBUG_SPRAY_COUNT];
real_point3d points[COLLISION_DEBUG_SPRAY_COUNT];
unsigned long hit_flags[BIT_VECTOR_SIZE_IN_LONGS(COLLISION_DEBUG_SPRAY_COUNT)];
};
typedef char collision_debug_spray_cache_size_assert[
sizeof(struct collision_debug_spray_cache) == 0x7118 ? 1 : -1];
/* ---------- prototypes */
/* ---------- globals */
extern boolean collision_debug;
extern boolean collision_debug_features;
extern unsigned long collision_debug_flags;
extern real_point3d collision_debug_phantom_bsp_point;
extern real_point3d collision_debug_point;
extern boolean collision_debug_repeat;
extern boolean collision_debug_spray;
extern real_vector3d collision_debug_vector;
extern boolean collision_debug_flag_back_facing_surfaces;
extern boolean collision_debug_flag_ignore_breakable_surfaces;
extern boolean collision_debug_flag_ignore_two_sided_surfaces;
extern boolean collision_debug_flag_objects_bipeds;
extern boolean collision_debug_flag_objects_controls;
extern boolean collision_debug_flag_objects_equipment;
extern boolean collision_debug_flag_objects_light_fixtures;
extern boolean collision_debug_flag_objects_machines;
extern boolean collision_debug_flag_objects_placeholders;
extern boolean collision_debug_flag_objects_projectiles;
extern boolean collision_debug_flag_objects_scenery;
extern boolean collision_debug_flag_objects_vehicles;
extern boolean collision_debug_flag_objects_weapons;
extern boolean collision_debug_flag_skip_passthrough_bipeds;
extern boolean collision_debug_flag_try_to_keep_location_valid;
extern boolean collision_debug_flag_use_vehicle_physics;
static const real_point3d collision_debug_cube_vertices[NUMBER_OF_VERTICES_PER_CUBE] =
{
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f },
{ -1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f },
{ 1.0f, -1.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f },
{ 1.0f, 1.0f, 1.0f },
};
boolean collision_debug_flag_front_facing_surfaces = TRUE;
boolean collision_debug_flag_ignore_invisible_surfaces = TRUE;
boolean collision_debug_flag_structure = TRUE;
boolean collision_debug_flag_media = TRUE;
boolean collision_debug_flag_objects = TRUE;
real collision_debug_length = 100.0f;
long collision_debug_ignore_object_index = NONE;
static struct collision_debug_spray_cache collision_debug_spray_globals = { 0 };
real collision_debug_width = 0.0f;
real collision_debug_height = 0.0f;
boolean collision_debug_phantom_bsp = FALSE;
boolean collision_debug_phantom_bsp_found = FALSE;
/* ---------- public code */
void collision_debug_render(
void)
{
char buffer[1000];
match_assert(
"c:\\halo\\SOURCE\\physics\\collision_debug.c",
76,
global_current_collision_user_depth < MAXIMUM_COLLISION_USER_STACK_DEPTH);
global_current_collision_users[global_current_collision_user_depth++] = _collision_user_debugging;
if (collision_debug || collision_debug_spray || collision_debug_features || collision_debug_phantom_bsp)
{
unsigned long flags;
real length;
real_point3d debug_point;
real_vector3d debug_vector;
long ignore_object_index;
flags = collision_debug_flag_front_facing_surfaces != FALSE;
SET_FLAG(flags, _collision_test_back_facing_surfaces_bit, collision_debug_flag_back_facing_surfaces);
SET_FLAG(flags, _collision_test_ignore_two_sided_surfaces_bit, collision_debug_flag_ignore_two_sided_surfaces);
SET_FLAG(flags, _collision_test_ignore_invisible_surfaces_bit, collision_debug_flag_ignore_invisible_surfaces);
SET_FLAG(flags, _collision_test_ignore_breakable_surfaces_bit, collision_debug_flag_ignore_breakable_surfaces);
SET_FLAG(flags, _collision_test_structure_bit, collision_debug_flag_structure);
SET_FLAG(flags, _collision_test_media_bit, collision_debug_flag_media);
SET_FLAG(flags, _collision_test_objects_bit, collision_debug_flag_objects);
SET_FLAG(flags, _collision_test_objects_bipeds_bit, collision_debug_flag_objects_bipeds);
SET_FLAG(flags, _collision_test_objects_vehicles_bit, collision_debug_flag_objects_vehicles);
SET_FLAG(flags, _collision_test_objects_weapons_bit, collision_debug_flag_objects_weapons);
SET_FLAG(flags, _collision_test_objects_equipment_bit, collision_debug_flag_objects_equipment);
SET_FLAG(flags, _collision_test_objects_projectiles_bit, collision_debug_flag_objects_projectiles);
SET_FLAG(flags, _collision_test_objects_scenery_bit, collision_debug_flag_objects_scenery);
SET_FLAG(flags, _collision_test_objects_machines_bit, collision_debug_flag_objects_machines);
SET_FLAG(flags, _collision_test_objects_controls_bit, collision_debug_flag_objects_controls);
SET_FLAG(flags, _collision_test_objects_light_fixtures_bit, collision_debug_flag_objects_light_fixtures);
SET_FLAG(flags, _collision_test_objects_placeholders_bit, collision_debug_flag_objects_placeholders);
SET_FLAG(flags, _collision_test_try_to_keep_location_valid_bit, collision_debug_flag_try_to_keep_location_valid);
SET_FLAG(flags, _collision_test_skip_passthrough_bipeds_bit, collision_debug_flag_skip_passthrough_bipeds);
SET_FLAG(flags, _collision_test_use_vehicle_physics_bit, collision_debug_flag_use_vehicle_physics);
if (collision_debug_flags)
flags = collision_debug_flags;
if (!collision_debug_repeat)
{
long player_index = local_player_get_player_index(render.local_player_index);
if (player_index == NONE)
collision_debug_ignore_object_index = NONE;
else
collision_debug_ignore_object_index = player_get(local_player_get_player_index(render.local_player_index))->unit_index;
collision_debug_point = render.camera.position;
collision_debug_vector = render.camera.forward;
}
length = (real)fabs(collision_debug_length);
debug_point = collision_debug_point;
debug_vector.i = collision_debug_vector.i * length;
debug_vector.j = collision_debug_vector.j * length;
debug_vector.k = collision_debug_vector.k * length;
ignore_object_index = collision_debug_ignore_object_index;
if (collision_debug_phantom_bsp)
{
struct collision_bsp_test_vector_result collision;
if (collision_bsp_test_vector(
flags,
global_collision_bsp_get(),
MAXIMUM_BREAKABLE_SURFACES_PER_MAP,
breakable_surface_flags_get(),
&debug_point,
&debug_vector,
1.0f,
&collision))
{
real_point3d point;
struct collision_feature_list features;
point.x = debug_point.x + debug_vector.i * collision.t;
point.y = debug_point.y + debug_vector.j * collision.t;
point.z = debug_point.z + debug_vector.k * collision.t;
if (!collision_get_features_in_sphere(
flags,
&point,
0.01f,
0.0f,
0.01f,
ignore_object_index,
&features))
{
collision_debug_phantom_bsp_found = TRUE;
collision_debug_phantom_bsp_point = point;
}
}
if (collision_debug_phantom_bsp_found)
{
real yaw;
real pitch;
real roll;
real_matrix4x3 rotation;
real_point3d points[8];
short point_index;
yaw = (real)fmod((real)game_time_get() * 0.104719758f, 6.2831854820251465);
pitch = (real)fmod((real)game_time_get() * -0.073303826f, 6.2831854820251465);
roll = (real)fmod((real)game_time_get() * 0.146607652f, 6.2831854820251465);
render_debug_string_at_point(
TRUE,
&collision_debug_phantom_bsp_point,
"phantom bsp",
global_real_argb_pink);
matrix4x3_rotation_from_angles(&rotation, yaw, pitch, roll);
for (point_index = 0; point_index < NUMBEROF(points); point_index++)
{
real_vector3d transformed;
matrix4x3_transform_vector(
&rotation,
(real_vector3d const *)&collision_debug_cube_vertices[point_index],
&transformed);
points[point_index].x = collision_debug_phantom_bsp_point.x + transformed.i * 0.15f;
points[point_index].y = collision_debug_phantom_bsp_point.y + transformed.j * 0.15f;
points[point_index].z = collision_debug_phantom_bsp_point.z + transformed.k * 0.15f;
}
render_debug_line(TRUE, &points[0], &points[1], global_real_argb_pink);
render_debug_line(TRUE, &points[1], &points[3], global_real_argb_pink);
render_debug_line(TRUE, &points[3], &points[2], global_real_argb_pink);
render_debug_line(TRUE, &points[2], &points[0], global_real_argb_pink);
render_debug_line(TRUE, &points[4], &points[5], global_real_argb_pink);
render_debug_line(TRUE, &points[5], &points[7], global_real_argb_pink);
render_debug_line(TRUE, &points[7], &points[6], global_real_argb_pink);
render_debug_line(TRUE, &points[6], &points[4], global_real_argb_pink);
render_debug_line(TRUE, &points[0], &points[4], global_real_argb_pink);
render_debug_line(TRUE, &points[1], &points[5], global_real_argb_pink);
render_debug_line(TRUE, &points[2], &points[6], global_real_argb_pink);
render_debug_line(TRUE, &points[3], &points[7], global_real_argb_pink);
}
}
if (collision_debug)
{
if (collision_debug_length <= 0.0f)
{
debug_point.x += debug_vector.i;
debug_point.y += debug_vector.j;
debug_point.z += debug_vector.k;
if (collision_debug_width <= 0.0f)
{
if (collision_test_point(flags, &debug_point, ignore_object_index))
render_debug_point(TRUE, &debug_point, 0.1f, global_real_argb_red);
else
render_debug_point(TRUE, &debug_point, 0.1f, global_real_argb_green);
}
else
{
if (collision_test_sphere(&debug_point, collision_debug_width, ignore_object_index))
render_debug_sphere(TRUE, &debug_point, collision_debug_width, global_real_argb_red);
else
render_debug_sphere(TRUE, &debug_point, collision_debug_width, global_real_argb_green);
}
}
else if (collision_debug_width <= 0.0f)
{
struct collision_result collision;
if (collision_test_vector(flags, &debug_point, &debug_vector, ignore_object_index, &collision))
{
struct collision_bsp *bsp = NULL;
real_matrix4x3 const *matrix = NULL;
struct collision_surface const *surface = NULL;
render_debug_vector(TRUE, &debug_point, &debug_vector, collision.t, global_real_argb_red);
render_debug_point(TRUE, &collision.point, 0.125f, global_real_argb_red);
render_debug_vector(TRUE, &collision.point, &collision.plane.n, 0.25f, global_real_argb_red);
if (collision.type == _collision_result_structure)
{
bsp = global_collision_bsp_get();
}
else if (collision.type == _collision_result_object && collision.node_index != NONE)
{
struct collision_model_instance instance;
if (collision_model_instance_new(&instance, collision.object_index))
{
struct collision_node *node = TAG_BLOCK_GET_ELEMENT(
&instance.model->nodes,
collision.node_index,
struct collision_node);
bsp = TAG_BLOCK_GET_ELEMENT(&node->bsps, collision.bsp_index, struct collision_bsp);
matrix = &instance.matrices[collision.node_index];
}
}
if (bsp)
{
surface = TAG_BLOCK_GET_ELEMENT(&bsp->surfaces, collision.surface_index, struct collision_surface);
render_debug_collision_surface(bsp, collision.surface_index, matrix, global_real_argb_red);
/*
* Original January bug: the destination is 1000 bytes, but the
* historical call advertises 2048. Preserve it for byte matching.
* A safe non-matching build should pass sizeof(buffer) instead.
*/
_snprintf(
buffer,
2048,
"plane #%d%s|nsurface #%d%s%s%s%s|n%s|n%f degrees",
surface->plane_designator & LONG_MAX,
surface->plane_designator < 0 ? " negated" : "",
collision.surface_index,
TEST_FLAG(collision.flags, _collision_surface_two_sided_bit) ? " two-sided" : "",
TEST_FLAG(collision.flags, _collision_surface_invisible_bit) ? " invisible" : "",
TEST_FLAG(collision.flags, _collision_surface_climbable_bit) ? " climbable" : "",
TEST_FLAG(collision.flags, _collision_surface_breakable_bit) ? " breakable" : "",
material_get_name(collision.material_type),
(real)acos(collision.plane.n.k) * 57.295776f);
render_debug_string(TRUE, buffer);
}
}
else
{
real_point3d endpoint;
endpoint.x = debug_point.x + debug_vector.i;
endpoint.y = debug_point.y + debug_vector.j;
endpoint.z = debug_point.z + debug_vector.k;
render_debug_line(TRUE, &debug_point, &endpoint, global_real_argb_green);
render_debug_point(TRUE, &endpoint, 0.125f, global_real_argb_green);
}
}
else
{
short count;
short collision_index;
real_point3d clipped_position;
real_vector3d clipped_velocity;
struct collision_plane collisions[MAXIMUM_COLLISION_DEBUG_PATH_POINTS];
clipped_position = debug_point;
clipped_velocity = debug_vector;
if (collision_debug_height > 0.0f)
{
count = collision_move_pill(
flags,
&debug_point,
&debug_vector,
collision_debug_height,
collision_debug_width,
ignore_object_index,
&clipped_position,
&clipped_velocity,
MAXIMUM_COLLISION_DEBUG_RESULTS,
collisions);
}
else
{
count = collision_move_sphere(
flags,
&debug_point,
&debug_vector,
collision_debug_width,
ignore_object_index,
&clipped_position,
&clipped_velocity,
MAXIMUM_COLLISION_DEBUG_RESULTS,
collisions);
}
render_debug_vector(TRUE, &debug_point, &debug_vector, 1.0f, global_real_argb_blue);
match_assert(
"c:\\halo\\SOURCE\\physics\\collision_debug.c",
297,
count <= MAXIMUM_COLLISION_DEBUG_RESULTS);
memmove(&collisions[1], &collisions[0], count * sizeof(collisions[0]));
collisions[0].point = debug_point;
memset(&collisions[0].plane, 0, sizeof(collisions[0].plane));
collisions[count + 1].point = clipped_position;
memset(&collisions[count + 1].plane, 0, sizeof(collisions[0].plane));
for (collision_index = 0; collision_index < count + 2; collision_index++)
{
render_debug_point(TRUE, &collisions[collision_index].point, 0.0625f, global_real_argb_red);
if (collision_index > 0)
render_debug_line(TRUE, &collisions[collision_index - 1].point, &collisions[collision_index].point, global_real_argb_red);
render_debug_vector(TRUE, &collisions[collision_index].point, &collisions[collision_index].plane.n, 0.125f, global_real_argb_red);
}
render_debug_vector(TRUE, &clipped_position, &clipped_velocity, 1.0f, global_real_argb_green);
}
}
if (collision_debug_spray)
{
if (collision_debug_length <= 0.0f)
{
real_point3d point;
real minimum_x = render.camera.position.x + render.camera.forward.i + render.camera.forward.i - 0.125f;
real maximum_x = render.camera.position.x + render.camera.forward.i + render.camera.forward.i + 0.125f;
real minimum_y = render.camera.position.y + render.camera.forward.j + render.camera.forward.j - 0.125f;
real maximum_y = render.camera.position.y + render.camera.forward.j + render.camera.forward.j + 0.125f;
real minimum_z = render.camera.position.z + render.camera.forward.k + render.camera.forward.k - 0.125f;
real maximum_z = render.camera.position.z + render.camera.forward.k + render.camera.forward.k + 0.125f;
for (point.z = minimum_z; point.z < maximum_z; point.z += 0.0625f)
{
for (point.y = minimum_y; point.y < maximum_y; point.y += 0.0625f)
{
for (point.x = minimum_x; point.x < maximum_x; point.x += 0.0625f)
{
real_argb_color const *color = collision_test_point(flags, &point, NONE)
? global_real_argb_red
: global_real_argb_green;
render_debug_point(TRUE, &point, 0.03125f, color);
}
}
}
}
else
{
if (!collision_debug_repeat)
{
long row;
long column;
long spray_index;
long rows_remaining;
long columns_remaining;
real_rectangle2d projection_bounds;
real_vector3d horizontal_step;
real_vector3d vertical_step;
real_vector3d base_vector;
render_frustum_get_projection_bounds(&render.frustum, &projection_bounds);
horizontal_step.i = (projection_bounds.x1 - projection_bounds.x0) * collision_debug_length * 0.025f;
horizontal_step.j = 0.0f;
horizontal_step.k = 0.0f;
vertical_step.i = 0.0f;
vertical_step.j = (projection_bounds.y1 - projection_bounds.y0) * collision_debug_length * (1.0f / 30.0f);
vertical_step.k = 0.0f;
base_vector.i = projection_bounds.x0 * collision_debug_length;
base_vector.j = projection_bounds.y0 * collision_debug_length;
base_vector.k = -collision_debug_length;
matrix4x3_transform_vector(&render.frustum.view_to_world, &horizontal_step, &horizontal_step);
matrix4x3_transform_vector(&render.frustum.view_to_world, &vertical_step, &vertical_step);
matrix4x3_transform_vector(&render.frustum.view_to_world, &base_vector, &base_vector);
row = 0;
rows_remaining = COLLISION_DEBUG_SPRAY_ROWS;
do
{
spray_index = row * COLLISION_DEBUG_SPRAY_COLUMNS;
column = 0;
columns_remaining = COLLISION_DEBUG_SPRAY_COLUMNS;
do
{
boolean hit;
struct collision_result collision;
real_vector3d direction;
direction.i = base_vector.i + horizontal_step.i * column + vertical_step.i * row;
direction.j = base_vector.j + horizontal_step.j * column + vertical_step.j * row;
direction.k = base_vector.k + horizontal_step.k * column + vertical_step.k * row;
hit = collision_test_vector(flags, &render.camera.position, &direction, ignore_object_index, &collision);
if (hit)
{
BIT_VECTOR_SET_FLAG(collision_debug_spray_globals.hit_flags, spray_index, TRUE);
collision_debug_spray_globals.points[spray_index] = collision.point;
collision_debug_spray_globals.normals[spray_index] = collision.plane.n;
}
else
{
BIT_VECTOR_SET_FLAG(collision_debug_spray_globals.hit_flags, spray_index, FALSE);
}
column++;
spray_index++;
} while (--columns_remaining);
row++;
} while (--rows_remaining);
}
{
long row;
long spray_index;
long rows_remaining;
long columns_remaining;
row = 0;
rows_remaining = COLLISION_DEBUG_SPRAY_ROWS;
do
{
spray_index = row * COLLISION_DEBUG_SPRAY_COLUMNS;
columns_remaining = COLLISION_DEBUG_SPRAY_COLUMNS;
do
{
if (BIT_VECTOR_TEST_FLAG(collision_debug_spray_globals.hit_flags, spray_index))
{
render_debug_point(TRUE, &collision_debug_spray_globals.points[spray_index], 0.03125f, global_real_argb_red);
render_debug_vector(
TRUE,
&collision_debug_spray_globals.points[spray_index],
&collision_debug_spray_globals.normals[spray_index],
0.0625f,
global_real_argb_red);
}
spray_index++;
} while (--columns_remaining);
row++;
} while (--rows_remaining);
}
}
}
if (collision_debug_features)
{
real radius;
real_point3d center;
struct collision_feature_list features;
center.x = collision_debug_point.x + collision_debug_vector.i * 0.5f;
center.y = collision_debug_point.y + collision_debug_vector.j * 0.5f;
center.z = collision_debug_point.z + collision_debug_vector.k * 0.5f + collision_debug_height * 0.5f;
radius = (real)sqrt(
collision_debug_vector.i * collision_debug_vector.i
+ collision_debug_vector.j * collision_debug_vector.j
+ collision_debug_vector.k * collision_debug_vector.k) * 0.5f
+ collision_debug_height * 0.5f
+ collision_debug_width;
if (collision_get_features_in_sphere(
flags,
&center,
radius,
collision_debug_height,
collision_debug_width,
collision_debug_ignore_object_index,
&features))
{
render_debug_collision_features(&features);
}
}
}
match_assert(
"c:\\halo\\SOURCE\\physics\\collision_debug.c",
443,
global_current_collision_user_depth > 1);
--global_current_collision_user_depth;
return;
}
/* ---------- private code */