mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-21 00:00:29 +02:00
540 lines
12 KiB
C
540 lines
12 KiB
C
/*
|
|
COLLISIONS.C
|
|
|
|
symbols in this file:
|
|
0013D2D0 0030:
|
|
_collision_model_get_material_type (0000)
|
|
0013D300 0060:
|
|
_collision_test_sphere (0000)
|
|
0013D360 0120:
|
|
_code_0013d360 (0000)
|
|
0013D480 00b0:
|
|
_collision_test_point (0000)
|
|
0013D530 0290:
|
|
_code_0013d530 (0000)
|
|
0013D7C0 06d0:
|
|
_collision_test_vector (0000)
|
|
0013DE90 0190:
|
|
_collision_test_vector_exit (0000)
|
|
0013E020 0170:
|
|
_collision_test_pill (0000)
|
|
0013E190 00d0:
|
|
_collision_test_pill_new (0000)
|
|
0013E260 0220:
|
|
_code_0013e260 (0000)
|
|
0013E480 0200:
|
|
_collision_get_features_in_sphere (0000)
|
|
0013E680 0040:
|
|
_code_0013e680 (0000)
|
|
0013E6C0 0040:
|
|
_code_0013e6c0 (0000)
|
|
0013E700 0080:
|
|
_code_0013e700 (0000)
|
|
0013E780 0050:
|
|
_code_0013e780 (0000)
|
|
0013E7D0 00a0:
|
|
_code_0013e7d0 (0000)
|
|
0013E870 02a0:
|
|
_collision_fix_pill (0000)
|
|
0013EB10 1290:
|
|
_collision_move_point (0000)
|
|
0013FDA0 0180:
|
|
_collision_move_pill (0000)
|
|
0013FF20 0040:
|
|
_collision_move_sphere (0000)
|
|
0028BAB8 0008:
|
|
__real@3fa0000000000000 (0000)
|
|
0028BAC0 0008:
|
|
__real@3f30000000000000 (0000)
|
|
0028BAC8 0004:
|
|
__real@3d000000 (0000)
|
|
0028BACC 0004:
|
|
__real@3f441b7d (0000)
|
|
0028BAD0 0024:
|
|
??_C@_0CE@BAGBGBHP@c?3?2halo?2SOURCE?2physics?2collision@ (0000)
|
|
0028BAF4 000d:
|
|
??_C@_0N@LANGNGIH@new_velocity?$AA@ (0000)
|
|
0028BB04 000c:
|
|
??_C@_0M@HGHPBCFN@?$CGclip_plane?$AA@ (0000)
|
|
0028BB10 000c:
|
|
??_C@_0M@KHLCGDHC@?$CGclip_point?$AA@ (0000)
|
|
0028BB1C 0012:
|
|
??_C@_0BC@GFMKCLPO@?$CGclip_line_vector?$AA@ (0000)
|
|
0028BB30 0011:
|
|
??_C@_0BB@IPCKNOKM@?$CGclip_line_point?$AA@ (0000)
|
|
0028BB44 000d:
|
|
??_C@_0N@HNOBANOD@clip_count?$DM3?$AA@ (0000)
|
|
0028BB54 002f:
|
|
??_C@_0CP@BCIJNMNG@?$CFs?3?5assert_valid_real_plane3d?$CI?$CFf@ (0000)
|
|
0028BB84 0012:
|
|
??_C@_0BC@KMBJNJFM@?$CGcollision?9?$DOplane?$AA@ (0000)
|
|
0028BB98 000a:
|
|
??_C@_09MFIJNMKH@?$CGvelocity?$AA@ (0000)
|
|
0028BBA4 000a:
|
|
??_C@_09KHKMDFEK@?$CGposition?$AA@ (0000)
|
|
0028BBB0 0012:
|
|
??_C@_0BC@JCEJOAFB@?$CGclipped_velocity?$AA@ (0000)
|
|
0028BBC4 0012:
|
|
??_C@_0BC@PAGMAJLM@?$CGclipped_position?$AA@ (0000)
|
|
0028BBD8 0028:
|
|
??_C@_0CI@OLDCDOIO@collision_count?$DMmaximum_collisio@ (0000)
|
|
0028BC00 000d:
|
|
??_C@_0N@MHPNJHFJ@old_velocity?$AA@ (0000)
|
|
0028BC10 000d:
|
|
??_C@_0N@KFNIHOLE@old_position?$AA@ (0000)
|
|
0030CDE8 00cc:
|
|
_data_0030cde8 (0000)
|
|
0045E000 001a:
|
|
_bss_0045e000 (0000)
|
|
_debug_collision_skip_objects (0018)
|
|
_debug_collision_skip_vectors (0019)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries.h"
|
|
#include "collisions.h"
|
|
|
|
#include "breakable_surfaces.h"
|
|
#include "bsp3d.h"
|
|
#include "collision_bsp.h"
|
|
#include "collision_features.h"
|
|
#include "collision_model_definitions.h"
|
|
#include "collision_models.h"
|
|
#include "collision_usage.h"
|
|
#include "physics.h"
|
|
#include "objects/object_types.h"
|
|
#include "objects/objects.h"
|
|
#include "scenario/scenario.h"
|
|
#include "structures/structure_bsp_definitions.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
/* ---------- prototypes */
|
|
|
|
boolean collision_bsp_test_pill_new(
|
|
struct collision_bsp const *bsp,
|
|
short breakable_surface_count,
|
|
byte const *breakable_surface_flags,
|
|
real_point3d const *point,
|
|
real_vector3d const *vector,
|
|
real radius,
|
|
real *t,
|
|
real_vector3d *normal);
|
|
boolean collision_bsp_test_pill(
|
|
struct collision_bsp const *bsp,
|
|
real_point3d const *point,
|
|
real_vector3d const *vector,
|
|
real radius,
|
|
real maximum_t,
|
|
struct collision_bsp_test_pill_result *result);
|
|
boolean code_0013d360(
|
|
long object_index,
|
|
unsigned long flags,
|
|
real_point3d const *point,
|
|
long ignore_object_index);
|
|
boolean collision_get_features_in_sphere(
|
|
unsigned long flags,
|
|
real_point3d const *center,
|
|
real enclosing_radius,
|
|
real height,
|
|
real radius,
|
|
long ignore_object_index,
|
|
struct collision_feature_list *features);
|
|
short collision_move_point(
|
|
real_point3d const *position,
|
|
real_vector3d const *velocity,
|
|
struct collision_feature_list const *features,
|
|
real_point3d *clipped_position,
|
|
real_vector3d *clipped_velocity,
|
|
struct collision_result *collisions,
|
|
short *collision_count);
|
|
|
|
/* ---------- globals */
|
|
|
|
extern boolean debug_collision_skip_objects;
|
|
|
|
/* ---------- public code */
|
|
|
|
long collision_model_get_material_type(
|
|
struct collision_model const *model,
|
|
short material_index)
|
|
{
|
|
long material_type;
|
|
|
|
if (material_index != NONE)
|
|
{
|
|
material_type = TAG_BLOCK_GET_ELEMENT(
|
|
&model->resistance.materials,
|
|
material_index,
|
|
struct damage_resistance_material)->material_type;
|
|
}
|
|
else
|
|
{
|
|
material_type = NONE;
|
|
}
|
|
|
|
return material_type;
|
|
}
|
|
|
|
boolean collision_test_sphere(
|
|
real_point3d const *center,
|
|
real radius)
|
|
{
|
|
boolean result;
|
|
struct collision_bsp_test_sphere_result sphere_result;
|
|
|
|
if (bsp3d_test_point(global_bsp3d_get(), 0, center) != NONE)
|
|
{
|
|
result = collision_bsp_test_sphere(
|
|
global_collision_bsp_get(),
|
|
MAXIMUM_BREAKABLE_SURFACES_PER_MAP,
|
|
breakable_surface_flags_get(),
|
|
center,
|
|
radius,
|
|
&sphere_result);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
boolean collision_test_point(
|
|
unsigned long flags,
|
|
real_point3d const *point,
|
|
long ignore_object_index)
|
|
{
|
|
unsigned long collision_flags = flags;
|
|
long leaf_index;
|
|
long reference_index;
|
|
boolean test_objects;
|
|
|
|
if (!(collision_flags & _collision_test_environment_flags))
|
|
{
|
|
goto no_collision;
|
|
}
|
|
|
|
leaf_index = bsp3d_test_point(global_bsp3d_get(), 0, point);
|
|
test_objects = TEST_FLAG(collision_flags, _collision_test_objects_bit);
|
|
if (debug_collision_skip_objects)
|
|
{
|
|
test_objects = FALSE;
|
|
}
|
|
|
|
if (leaf_index == NONE)
|
|
{
|
|
goto collision;
|
|
}
|
|
|
|
if (!test_objects)
|
|
{
|
|
goto no_collision;
|
|
}
|
|
|
|
{
|
|
short cluster_index = TAG_BLOCK_GET_ELEMENT(
|
|
&global_structure_bsp_get()->leaves,
|
|
leaf_index & LONG_MAX,
|
|
struct structure_leaf)->cluster_index;
|
|
long object_index;
|
|
|
|
for (object_index = cluster_get_first_collideable_object(&reference_index, cluster_index);
|
|
object_index != NONE;
|
|
object_index = cluster_get_next_collideable_object(&reference_index))
|
|
{
|
|
if (code_0013d360(object_index, collision_flags, point, ignore_object_index))
|
|
{
|
|
goto collision;
|
|
}
|
|
}
|
|
}
|
|
|
|
no_collision:
|
|
return FALSE;
|
|
|
|
collision:
|
|
return TRUE;
|
|
}
|
|
|
|
boolean collision_test_pill(
|
|
unsigned long flags,
|
|
real_point3d const *point,
|
|
real_vector3d const *vector,
|
|
real radius,
|
|
long ignore_object_index,
|
|
struct collision_result *collision)
|
|
{
|
|
boolean hit = FALSE;
|
|
struct collision_bsp_test_pill_result bsp_result;
|
|
|
|
collision->type = NONE;
|
|
collision->t = REAL_MAX;
|
|
|
|
if (collision_bsp_test_pill(
|
|
global_collision_bsp_get(),
|
|
point,
|
|
vector,
|
|
radius,
|
|
REAL_MAX,
|
|
&bsp_result))
|
|
{
|
|
collision->t = bsp_result.t;
|
|
if (flags & FLAG(_collision_test_structure_bit))
|
|
{
|
|
collision->plane = bsp_result.plane;
|
|
collision->flags = 0;
|
|
collision->breakable_surface_index = 0;
|
|
collision->type = 2;
|
|
collision->material_type = bsp_result.material_index;
|
|
collision->surface_index = bsp_result.surface_index;
|
|
collision->plane_designator = NONE;
|
|
collision->material_index = bsp_result.material_index;
|
|
hit = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bsp_result.leaf_count > 0)
|
|
{
|
|
long leaf_index = bsp_result.leaf_indices[0];
|
|
long cluster_index;
|
|
|
|
collision->start_location.leaf_index = leaf_index;
|
|
if (leaf_index == NONE)
|
|
{
|
|
cluster_index = NONE;
|
|
}
|
|
else
|
|
{
|
|
cluster_index = TAG_BLOCK_GET_ELEMENT(
|
|
&global_structure_bsp_get()->leaves,
|
|
leaf_index & LONG_MAX,
|
|
struct structure_leaf)->cluster_index;
|
|
}
|
|
collision->start_location.cluster_index = cluster_index;
|
|
|
|
leaf_index = bsp_result.leaf_indices[bsp_result.leaf_count - 1];
|
|
collision->location.leaf_index = leaf_index;
|
|
if (leaf_index == NONE)
|
|
{
|
|
cluster_index = NONE;
|
|
}
|
|
else
|
|
{
|
|
cluster_index = TAG_BLOCK_GET_ELEMENT(
|
|
&global_structure_bsp_get()->leaves,
|
|
leaf_index & LONG_MAX,
|
|
struct structure_leaf)->cluster_index;
|
|
}
|
|
collision->location.cluster_index = cluster_index;
|
|
}
|
|
|
|
if (!hit)
|
|
{
|
|
collision->t = 1.0f;
|
|
}
|
|
|
|
point_from_line3d(point, vector, collision->t, &collision->point);
|
|
scenario_location_from_point(&collision->location, &collision->point);
|
|
|
|
return hit;
|
|
}
|
|
|
|
boolean collision_test_pill_new(
|
|
unsigned long flags,
|
|
real_point3d const *point,
|
|
real_vector3d const *vector,
|
|
real radius,
|
|
long ignore_object_index,
|
|
struct collision_result *collision)
|
|
{
|
|
boolean result = FALSE;
|
|
real t;
|
|
real_vector3d normal;
|
|
|
|
collision->type = NONE;
|
|
collision->start_location.leaf_index = NONE;
|
|
collision->start_location.cluster_index = NONE;
|
|
collision->location.leaf_index = NONE;
|
|
collision->location.cluster_index = NONE;
|
|
collision->t = 1.0f;
|
|
|
|
if (collision_bsp_test_pill_new(
|
|
global_collision_bsp_get(),
|
|
0,
|
|
NULL,
|
|
point,
|
|
vector,
|
|
radius,
|
|
&t,
|
|
&normal))
|
|
{
|
|
collision->t = t;
|
|
collision->plane.n = normal;
|
|
collision->type = 2;
|
|
collision->plane.d = REAL_MAX;
|
|
collision->material_type = NONE;
|
|
collision->surface_index = NONE;
|
|
collision->plane_designator = NONE;
|
|
collision->flags = 0;
|
|
collision->breakable_surface_index = 0;
|
|
collision->material_index = NONE;
|
|
result = TRUE;
|
|
}
|
|
|
|
point_from_line3d(point, vector, collision->t, &collision->point);
|
|
collision->plane.n.i = 0.0f;
|
|
collision->plane.n.j = 0.0f;
|
|
collision->plane.n.k = 0.0f;
|
|
|
|
return result;
|
|
}
|
|
|
|
short collision_move_sphere(
|
|
unsigned long flags,
|
|
real_point3d const *position,
|
|
real_vector3d const *velocity,
|
|
real radius,
|
|
long ignore_object_index,
|
|
real_point3d *clipped_position,
|
|
real_vector3d *clipped_velocity,
|
|
struct collision_result *collisions,
|
|
short *collision_count)
|
|
{
|
|
return collision_move_pill(
|
|
flags,
|
|
position,
|
|
velocity,
|
|
0.0f,
|
|
radius,
|
|
ignore_object_index,
|
|
clipped_position,
|
|
clipped_velocity,
|
|
collisions,
|
|
collision_count);
|
|
}
|
|
|
|
short collision_move_pill(
|
|
unsigned long flags,
|
|
real_point3d const *position,
|
|
real_vector3d const *velocity,
|
|
real height,
|
|
real radius,
|
|
long ignore_object_index,
|
|
real_point3d *clipped_position,
|
|
real_vector3d *clipped_velocity,
|
|
struct collision_result *collisions,
|
|
short *collision_count)
|
|
{
|
|
short result = FALSE;
|
|
struct collision_feature_list features;
|
|
real_point3d center;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\physics\\collisions.c", 1214, global_current_collision_user_depth < MAXIMUM_COLLISION_USER_STACK_DEPTH);
|
|
global_current_collision_users[global_current_collision_user_depth++] = 7;
|
|
|
|
center.x = position->x + velocity->i * 0.5f;
|
|
center.y = position->y + velocity->j * 0.5f;
|
|
center.z = height * 0.5f + (position->z + velocity->k * 0.5f);
|
|
|
|
if (collision_get_features_in_sphere(
|
|
flags,
|
|
¢er,
|
|
magnitude3d(velocity) * 0.5f + height * 0.5f + radius,
|
|
height,
|
|
radius,
|
|
ignore_object_index,
|
|
&features))
|
|
{
|
|
result = collision_move_point(
|
|
position,
|
|
velocity,
|
|
&features,
|
|
clipped_position,
|
|
clipped_velocity,
|
|
collisions,
|
|
collision_count);
|
|
}
|
|
else
|
|
{
|
|
add_vectors3d(
|
|
(real_vector3d const *)position,
|
|
velocity,
|
|
(real_vector3d *)clipped_position);
|
|
*clipped_velocity = *velocity;
|
|
}
|
|
|
|
match_assert("c:\\halo\\SOURCE\\physics\\collisions.c", 1230, global_current_collision_user_depth > 1);
|
|
--global_current_collision_user_depth;
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
boolean code_0013d360(
|
|
long object_index,
|
|
unsigned long flags,
|
|
real_point3d const *point,
|
|
long ignore_object_index)
|
|
{
|
|
do
|
|
{
|
|
struct object_datum const *object = object_get(object_index);
|
|
|
|
if (object_index != ignore_object_index &&
|
|
!(object->object.flags & FLAG(_object_invisible_bit)))
|
|
{
|
|
long object_type = object->object.type;
|
|
|
|
if ((flags & FLAG(object_type + _collision_test_objects_first_type_bit)) &&
|
|
point_in_sphere(point, &object->object.bounding_sphere_center, object->object.bounding_sphere_radius))
|
|
{
|
|
boolean hit;
|
|
|
|
if ((FLAG(object_type) & _object_mask_vehicle) &&
|
|
(flags & FLAG(_collision_test_use_vehicle_physics_bit)))
|
|
{
|
|
struct physics_instance instance;
|
|
|
|
hit = physics_instance_new(&instance, object_index) &&
|
|
physics_test_point(&instance, point);
|
|
}
|
|
else
|
|
{
|
|
struct collision_model_instance instance;
|
|
|
|
hit = collision_model_instance_new(&instance, object_index) &&
|
|
collision_model_test_point(&instance, point);
|
|
}
|
|
|
|
if (hit)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (object->object.first_child_object_index != NONE &&
|
|
code_0013d360(
|
|
object->object.first_child_object_index,
|
|
flags,
|
|
point,
|
|
ignore_object_index))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
object_index = object->object.next_object_index;
|
|
}
|
|
while (object_index != NONE);
|
|
|
|
return FALSE;
|
|
}
|