Files

2334 lines
73 KiB
C

/*
PHYSICS.C
symbols in this file:
0013FF60 0080:
_pin_fraction (0000)
0013FFE0 00b0:
_physics_get_features_in_sphere (0000)
00140090 0070:
_code_00140090 (0000)
00140100 0110:
_render_debug_physics (0000)
00140210 0100:
_physics_instance_new (0000)
00140310 00a0:
_physics_test_point (0000)
001403B0 0120:
_physics_test_vector (0000)
001404D0 0150:
_code_001404d0 (0000)
00140620 0100:
_code_00140620 (0000)
00140720 0b80:
_physics_compute_new (0000)
001412A0 0470:
_code_001412a0 (0000)
00141710 0490:
_code_00141710 (0000)
00141BA0 0180:
_code_00141ba0 (0000)
00141D20 01b0:
_code_00141d20 (0000)
00141ED0 07c0:
_physics_update_new (0000)
00142690 1430:
_code_00142690 (0000)
00143AC0 0260:
_physics_update (0000)
0028BC20 008d:
??_C@_0IN@ODNFDOFI@mass_point?9?$DOground_material_type@ (0000)
0028BCB0 0021:
??_C@_0CB@OHGIJBLL@c?3?2halo?2SOURCE?2physics?2physics?4c@ (0000)
0028BCD4 0004:
__real@45ea6000 (0000)
0028BCD8 0057:
??_C@_0FH@DDOACPI@unit_definition?9?$DOunit?4blip_type?$DO@ (0000)
0028BD30 0015:
??_C@_0BF@GMDJIBPD@model_instance_valid?$AA@ (0000)
0028BD48 0010:
??_C@_0BA@LNKGLGKJ@rotated_forward?$AA@ (0000)
0028BD58 000b:
??_C@_0L@GBBDLPMF@rotated_up?$AA@ (0000)
0028BD64 000f:
??_C@_0P@OGJNHPDG@up?$CB?$DNrotated_up?$AA@ (0000)
0028BD74 0019:
??_C@_0BJ@GEGCJHGH@forward?$CB?$DNrotated_forward?$AA@ (0000)
0028BD90 0004:
__real@364c6ce0 (0000)
0028BD94 0004:
__real@34a5b36e (0000)
0028BD98 0004:
__real@3b33abb1 (0000)
0028BDA0 0008:
__real@3f80000000000000 (0000)
0028BDA8 0012:
??_C@_0BC@MDPNAJDL@?$CGangular_velocity?$AA@ (0000)
0028BDBC 0016:
??_C@_0BG@NPNNHCFI@?$CGangular_acceleration?$AA@ (0000)
0028BDD4 0011:
??_C@_0BB@IHCLBKLO@?$CGlinear_velocity?$AA@ (0000)
0028BDE8 0015:
??_C@_0BF@LNOJMOGI@?$CGlinear_acceleration?$AA@ (0000)
0028BE00 001d:
??_C@_0BN@FOPAIIBD@instance?9?$DOphysics?9?$DOmass?$DO0?40f?$AA@ (0000)
0028BE20 0018:
??_C@_0BI@HOJEHDKE@?$CGobject?9?$DOobject?4forward?$AA@ (0000)
0028BE38 0013:
??_C@_0BD@JHPMDDBM@?$CGobject?9?$DOobject?4up?$AA@ (0000)
0028BE4C 001c:
??_C@_0BM@EKBNDJOG@?$CGtranslational_acceleration?$AA@ (0000)
0028BE68 000d:
??_C@_0N@EMPCNLII@magic_torque?$AA@ (0000)
0028BE78 000c:
??_C@_0M@LNGNIFCJ@magic_force?$AA@ (0000)
0030CEB4 002c:
_global_gravity (0000)
_global_water_density (0004)
_global_air_density (0008)
_global_physics_collision_depth (000c)
_depths_of_hell (0010)
0045E01A 0001:
_debug_physics_disable_penetration_freeze (0000)
*/
/* ---------- headers */
#include "cseries.h"
#include "cseries/errors.h" /* port: error */
#include "physics.h"
#include "collision_features.h"
#include "collision_models.h"
#include "collisions.h"
#include "effects/material_effect_definitions.h"
#include "game/game.h"
#include "game/game_globals.h"
#include "math/real_math.h"
#include "objects/damage.h"
#include "objects/object_definitions.h"
#include "objects/object_types.h"
#include "objects/objects.h"
#include "collision_model_definitions.h"
#include "physics_definitions.h"
#include "render/render_debug.h"
#include "scenario/scenario.h"
#include "structures/structure_bsp_definitions.h"
#include "units/bipeds.h"
#include "units/unit_definitions.h"
#include "units/vehicles.h"
/* ---------- constants */
enum
{
_collision_surface_two_sided_bit = 0,
_collision_surface_invisible_bit,
_collision_surface_climbable_bit,
_collision_surface_breakable_bit,
};
enum
{
_friction_type_point = 0,
_friction_type_forward,
_friction_type_left,
_friction_type_up,
NUMBER_OF_FRICTION_TYPES
};
enum
{
_point_at_rest_bit = 0,
_point_on_ground_bit,
_point_on_volatile_surface_bit,
_point_in_water_bit,
_point_antigraving_bit,
NUMBER_OF_MASS_POINT_FLAGS
};
enum
{
_powered_mass_point_ground_friction_bit = 0,
_powered_mass_point_water_friction_bit,
_powered_mass_point_air_friction_bit,
_powered_mass_point_water_lift_bit,
_powered_mass_point_air_lift_bit,
_powered_mass_point_thrust_bit,
_powered_mass_point_antigrav_bit,
NUMBER_OF_POWERED_MASS_POINT_FLAGS
};
/* ---------- macros */
/* January's physics.c expands point_from_line3d in place for points and
* vectors alike; this scalar expansion preserves that inline schedule without
* selecting the external point_from_line3d COMDAT for this object (the same
* emitted-symbol invariant as COLLISION_POINT_FROM_LINE3D in collisions.c). */
#define PHYSICS_POINT_FROM_LINE3D(point, vector, distance, result) \
do \
{ \
real *line_result = (result)->n; \
real line_distance = (distance); \
real const *line_vector = (vector)->n; \
real const *line_point = (point)->n; \
line_result[0] = line_vector[0] * line_distance + line_point[0]; \
line_result[1] = line_vector[1] * line_distance + line_point[1]; \
line_result[2] = line_vector[2] * line_distance + line_point[2]; \
} while (0)
/* ---------- structures */
struct powered_mass_point_definition
{
char name[32];
unsigned long flags;
real antigrav_strength;
real antigrav_offset;
real antigrav_height;
real antigrav_damp_fraction;
real antigrav_normal_k1;
real antigrav_normal_k0;
real unused[17];
};
#include "friction_datum.h"
#include "powered_mass_point_datum.h"
#include "mass_point_datum.h"
#include "units/vehicle_datum.h"
/* TU-local copy: no shared header declares the game globals falling-damage
* block yet; identical complete copies live in objects/damage.c and
* units/bipeds.c. */
struct game_globals_falling_damage
{
long unused0[2];
real falling_distance_lower_bound;
real falling_distance_upper_bound;
struct tag_reference falling_damage;
long terminal_velocity_unused[2];
real maximum_distance;
struct tag_reference maximum_distance_damage;
struct tag_reference vehicle_hit_environment_damage_effect;
struct tag_reference vehicle_killed_unit_damage_effect;
struct tag_reference vehicle_collision_damage;
struct tag_reference flaming_death_damage;
long unused7c[4];
real runtime_maximum_falling_velocity;
real runtime_minimum_damage_velocity;
real runtime_maximum_damage_velocity;
};
typedef char game_globals_falling_damage_size_assert[
sizeof(struct game_globals_falling_damage) == 0x98 ? 1 : -1];
typedef char powered_mass_point_definition_size_assert[
sizeof(struct powered_mass_point_definition) == 0x80 ? 1 : -1];
typedef char powered_mass_point_datum_size_assert[
sizeof(struct powered_mass_point_datum) == 0x60 ? 1 : -1];
typedef char mass_point_datum_size_assert[
sizeof(struct mass_point_datum) == 0x130 ? 1 : -1];
/* ---------- prototypes */
static short physics_mass_point_count(
struct physics_definition const *physics);
static short physics_powered_mass_point_count(
struct physics_definition const *physics);
static short physics_powered_mass_point_index(
struct physics_definition const *physics,
struct mass_point_definition const *mass_point_definition);
static short get_material_type(
long object_index,
short material_index);
static void compute_ground_plane(
long object_index,
struct mass_point_datum *mass_point,
struct mass_point_definition const *mass_point_definition);
static void friction_evaluate(
short friction_type,
real parallel_scale,
real perpendicular_scale,
struct friction_datum *friction,
real_vector3d const *forward,
real_vector3d const *up);
static boolean physics_compute_biped_collision(
struct collision_model_instance *instance,
long biped_index);
static boolean physics_compute_vehicle_collision(
struct physics_instance const *instance0,
struct physics_instance const *instance1);
static void physics_compute_unit_collisions(
long vehicle_index);
void physics_update_new(
struct physics_instance const *instance,
struct powered_mass_point_datum const *powered_mass_points,
struct mass_point_datum const *mass_points,
real_vector3d const *total_force,
real_vector3d const *total_torque);
static void physics_update_old(
long object_index,
struct powered_mass_point_datum *powered_mass_points,
struct mass_point_datum *mass_points,
real_vector3d const *magic_force,
real_vector3d const *magic_torque);
static void rotate_vectors3d_by_angular_velocity(
real_vector3d const *forward,
real_vector3d const *up,
real_vector3d const *angular_velocity,
real_vector3d *rotated_forward,
real_vector3d *rotated_up);
/* ---------- globals */
real global_gravity = 0.0035651792f;
real global_water_density = 1.0f;
real global_air_density = 0.0011f;
real global_physics_collision_depth = 0.2f;
real_plane3d depths_of_hell =
{
{ 0.0f, 0.0f, 1.0f },
-256.0f
};
boolean debug_physics_disable_penetration_freeze = FALSE;
/* port: whether a map's malformed physics was reported (once) */
static boolean warned_about_physics_mass_points;
static boolean warned_about_physics_inertial_matrix;
/* ---------- public code */
real pin_fraction(
real value,
real begin,
real end)
{
if (begin < end)
{
if (value <= begin)
return 0.0f;
else if (value >= end)
return 1.0f;
else
return (value - begin) / (end - begin);
}
else
{
if (value <= end)
return 1.0f;
else if (value >= begin)
return 0.0f;
else
return (begin - value) / (begin - end);
}
}
/* port: how many of a physics' mass points (from the map) are used: at
most MAXIMUM_MASS_POINTS_PER_PHYSICS (the rest are not, reported once) */
static short physics_mass_point_count(
struct physics_definition const *physics)
{
long count = physics->mass_points.count;
if (count > MAXIMUM_MASS_POINTS_PER_PHYSICS)
{
if (!warned_about_physics_mass_points)
{
error(_error_silent, "a physics has %ld mass points (maximum %d)",
count,
MAXIMUM_MASS_POINTS_PER_PHYSICS);
warned_about_physics_mass_points = TRUE;
}
count = MAXIMUM_MASS_POINTS_PER_PHYSICS;
}
return (short)MAX(count, 0);
}
/* port: (as physics_mass_point_count, with
MAXIMUM_POWERED_MASS_POINTS_PER_PHYSICS) */
static short physics_powered_mass_point_count(
struct physics_definition const *physics)
{
long count = physics->powered_mass_points.count;
if (count > MAXIMUM_POWERED_MASS_POINTS_PER_PHYSICS)
{
if (!warned_about_physics_mass_points)
{
error(_error_silent, "a physics has %ld powered mass points (maximum %d)",
count,
MAXIMUM_POWERED_MASS_POINTS_PER_PHYSICS);
warned_about_physics_mass_points = TRUE;
}
count = MAXIMUM_POWERED_MASS_POINTS_PER_PHYSICS;
}
return (short)MAX(count, 0);
}
/* port: a mass point's powered mass point (from the map), NONE if it
names none of the physics' used ones (physics_powered_mass_point_count) */
static short physics_powered_mass_point_index(
struct physics_definition const *physics,
struct mass_point_definition const *mass_point_definition)
{
short powered_mass_point_index = mass_point_definition->powered_mass_point_index;
if (powered_mass_point_index != NONE &&
(powered_mass_point_index < 0 ||
powered_mass_point_index >= physics_powered_mass_point_count(physics)))
{
if (!warned_about_physics_mass_points)
{
error(_error_silent, "a mass point's powered mass point #%d is not one of its physics' %ld",
powered_mass_point_index,
physics->powered_mass_points.count);
warned_about_physics_mass_points = TRUE;
}
powered_mass_point_index = NONE;
}
return powered_mass_point_index;
}
boolean physics_get_features_in_sphere(
struct physics_instance const *instance,
real_point3d const *center,
real radius,
real height,
real width,
struct collision_feature_list *features)
{
short mass_point_index;
real scaled_radius;
/* port: (physics_mass_point_count) */
short mass_point_count = physics_mass_point_count(instance->physics);
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point = TAG_BLOCK_GET_ELEMENT(
&instance->physics->mass_points,
mass_point_index,
struct mass_point_definition);
real_point3d point;
matrix4x3_transform_point(&instance->world_matrix, &mass_point->position, &point);
scaled_radius = mass_point->radius * instance->world_matrix.scale;
collision_features_from_point(
&point,
height,
scaled_radius + width,
instance->object_index,
NONE,
0,
NONE,
NONE,
features);
}
return features->count[_collision_feature_sphere] ||
features->count[_collision_feature_cylinder] ||
features->count[_collision_feature_prism];
}
static short get_material_type(
long object_index,
short material_index)
{
short material_type = NONE;
if (material_index != NONE)
{
if (object_index != NONE)
{
struct object_datum *object = object_get(object_index);
struct object_definition *definition = object_definition_get(object->definition_index);
/* port: (as in collision_model_get_material_type) */
if (definition->object.collision_model.index != NONE)
{
material_type = (short)collision_model_get_material_type(
collision_model_definition_get(definition->object.collision_model.index),
material_index);
}
}
else
{
struct structure_bsp *structure_bsp = global_structure_bsp_get();
/* port: a material (from the map) that is no material of the
bsp, or whose type is no material type, is none */
if (material_index >= 0 && material_index < structure_bsp->collision_materials.count)
{
material_type = TAG_BLOCK_GET_ELEMENT(
&structure_bsp->collision_materials,
material_index,
struct structure_collision_material)->runtime_physics_material_type;
}
if (material_type < 0 || material_type >= NUMBER_OF_MATERIAL_TYPES)
{
material_type = NONE;
}
}
}
return material_type;
}
void render_debug_physics(
struct physics_instance *instance)
{
struct object_datum *object = object_get(instance->object_index);
struct object_definition *definition = object_definition_get(object->definition_index);
real_point3d center_of_mass;
short mass_point_index;
/* port: (physics_mass_point_count) */
short mass_point_count = physics_mass_point_count(instance->physics);
matrix4x3_transform_point(
&instance->world_matrix,
&instance->physics->center_of_mass,
&center_of_mass);
render_debug_vectors(
TRUE,
&center_of_mass,
&instance->world_matrix.forward,
&instance->world_matrix.up,
definition->object.bounding_radius);
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point = TAG_BLOCK_GET_ELEMENT(
&instance->physics->mass_points,
mass_point_index,
struct mass_point_definition);
real_point3d position;
real_vector3d forward;
real_vector3d up;
matrix4x3_transform_point(
&instance->world_matrix,
&mass_point->position,
&position);
matrix4x3_transform_normal(
&instance->world_matrix,
&mass_point->forward,
&forward);
matrix4x3_transform_normal(
&instance->world_matrix,
&mass_point->up,
&up);
render_debug_sphere(
TRUE,
&position,
mass_point->radius,
global_real_argb_white);
render_debug_vectors(
TRUE,
&position,
&forward,
&up,
mass_point->radius * 0.5f);
}
}
boolean physics_instance_new(
struct physics_instance *instance,
long object_index)
{
struct object_datum *object = object_get(object_index);
struct object_definition *definition = object_definition_get(object->definition_index);
real_point3d center_of_mass;
if (definition->object.physics.index != NONE)
{
instance->object_index = object_index;
instance->physics = physics_definition_get(definition->object.physics.index);
instance->world_matrix.scale = 1.0f;
object_get_origin(object_index, &instance->world_matrix.position);
object_get_orientation(object_index, &instance->world_matrix.forward, &instance->world_matrix.up);
cross_product3d(&instance->world_matrix.up, &instance->world_matrix.forward, &instance->world_matrix.left);
set_real_point3d(&center_of_mass,
-instance->physics->center_of_mass.x,
-instance->physics->center_of_mass.y,
-instance->physics->center_of_mass.z);
matrix4x3_transform_point(&instance->world_matrix, &center_of_mass, &center_of_mass);
instance->world_matrix.position = center_of_mass;
return TRUE;
}
return FALSE;
}
boolean physics_test_point(
struct physics_instance const *instance,
real_point3d const *point)
{
real_point3d local_point;
struct physics_definition const *physics;
short mass_point_index;
short mass_point_count;
matrix4x3_inverse_transform_point(&instance->world_matrix, point, &local_point);
physics = instance->physics;
/* port: (physics_mass_point_count) */
mass_point_count = physics_mass_point_count(physics);
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point = TAG_BLOCK_GET_ELEMENT(
&physics->mass_points,
mass_point_index,
struct mass_point_definition);
if (point_in_sphere(&local_point, &mass_point->position, mass_point->radius))
return TRUE;
physics = instance->physics;
}
return FALSE;
}
boolean physics_test_vector(
struct physics_instance const *instance,
real_point3d const *point,
real_vector3d const *vector,
struct physics_test_vector_result *result)
{
boolean hit = FALSE;
real_point3d local_point;
real_vector3d local_vector;
real_vector3d normal;
short mass_point_index;
short mass_point_count;
result->t = REAL_MAX;
matrix4x3_inverse_transform_point(&instance->world_matrix, point, &local_point);
matrix4x3_inverse_transform_vector(&instance->world_matrix, vector, &local_vector);
/* port: (physics_mass_point_count) */
mass_point_count = physics_mass_point_count(instance->physics);
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point = TAG_BLOCK_GET_ELEMENT(
&instance->physics->mass_points,
mass_point_index,
struct mass_point_definition);
real t;
if (sphere_test_vector3d(
&mass_point->position,
mass_point->radius,
&local_point,
&local_vector,
&t,
&normal) &&
result->t > t)
{
real_point3d intersection;
result->t = t;
// Preserve the January inline schedule without emitting a point_from_line3d COMDAT.
intersection.x = local_vector.i*t + local_point.x;
intersection.y = local_vector.j*t + local_point.y;
intersection.z = local_vector.k*t + local_point.z;
plane3d_from_point_and_normal(
&result->plane,
&intersection,
&normal);
hit = TRUE;
}
}
if (hit)
matrix4x3_transform_plane(&instance->world_matrix, &result->plane, &result->plane);
return hit;
}
static void compute_ground_plane(
long object_index,
struct mass_point_datum *mass_point,
struct mass_point_definition const *mass_point_definition)
{
struct collision_feature_list features;
struct collision_plane collision;
mass_point->ground_plane = depths_of_hell;
mass_point->ground_material_type = NONE;
mass_point->ground_depth = mass_point_definition->radius -
plane3d_distance_to_point(&mass_point->ground_plane, &mass_point->position);
if (collision_get_features_in_sphere(
_collision_test_for_bipeds_dead_flags,
&mass_point->position,
mass_point_definition->radius,
0.0f,
mass_point_definition->radius,
object_index,
&features) &&
collision_features_test_point(&features, &mass_point->position, &collision))
{
mass_point->ground_plane = collision.plane;
mass_point->ground_depth = collision.t;
mass_point->ground_material_type = get_material_type(
collision.object_index,
collision.material_index);
SET_FLAG(
mass_point->flags,
_point_on_volatile_surface_bit,
TEST_FLAG(collision.flags, _collision_surface_breakable_bit) ||
(collision.object_index != NONE &&
!TEST_FLAG(_object_mask_scenery, object_get_type(collision.object_index))));
if (collision.object_index != NONE)
object_deplete_shield(collision.object_index);
}
match_assert(
"c:\\halo\\SOURCE\\physics\\physics.c",
338,
mass_point->ground_material_type==NONE || (mass_point->ground_material_type>=0 && mass_point->ground_material_type<NUMBER_OF_MATERIAL_TYPES));
return;
}
static void friction_evaluate(
short friction_type,
real parallel_scale,
real perpendicular_scale,
struct friction_datum *friction,
real_vector3d const *forward,
real_vector3d const *up)
{
real_vector3d left;
if (friction_type == _friction_type_point)
{
friction->parallel = friction->friction;
set_real_vector3d(&friction->perpendicular, 0.0f, 0.0f, 0.0f);
return;
}
switch (friction_type)
{
case _friction_type_forward:
component_vectors_from_normal3d(
&friction->friction,
forward,
&friction->parallel,
&friction->perpendicular);
break;
case _friction_type_left:
cross_product3d(up, forward, &left);
component_vectors_from_normal3d(
&friction->friction,
&left,
&friction->parallel,
&friction->perpendicular);
break;
case _friction_type_up:
component_vectors_from_normal3d(
&friction->friction,
up,
&friction->parallel,
&friction->perpendicular);
break;
default:
match_vassert("c:\\halo\\SOURCE\\physics\\physics.c", 383, FALSE, NULL);
break;
}
scale_vector3d(&friction->parallel, parallel_scale, &friction->parallel);
scale_vector3d(&friction->perpendicular, perpendicular_scale, &friction->perpendicular);
add_vectors3d(&friction->parallel, &friction->perpendicular, &friction->friction);
return;
}
void physics_compute_new(
struct physics_instance const *instance,
struct powered_mass_point_datum const *powered_mass_points,
struct mass_point_datum *mass_points,
real_vector3d *total_force,
real_vector3d *total_torque)
{
struct object_datum *object = object_get(instance->object_index);
struct physics_definition const *physics = instance->physics;
real gravity = physics->gravity_scale*global_gravity;
short mass_point_index;
/* port: no more mass points than the caller's arrays hold, nor a
powered one the physics does not have (physics_mass_point_count,
physics_powered_mass_point_index) */
short mass_point_count = physics_mass_point_count(physics);
set_real_vector3d(total_force, 0.0f, 0.0f, -physics->mass*gravity);
set_real_vector3d(total_torque, 0.0f, 0.0f, 0.0f);
memset(mass_points, 0, sizeof(struct mass_point_datum)*mass_point_count);
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&physics->mass_points,
mass_point_index,
struct mass_point_definition);
struct mass_point_datum *mass_point = mass_points + mass_point_index;
struct powered_mass_point_definition const *powered_mass_point_definition = NULL;
struct powered_mass_point_datum const *powered_mass_point = NULL;
real_vector3d powered_velocity;
short powered_mass_point_index = physics_powered_mass_point_index(physics, mass_point_definition);
if (powered_mass_point_index != NONE && powered_mass_points)
{
powered_mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&physics->powered_mass_points,
powered_mass_point_index,
struct powered_mass_point_definition);
powered_mass_point = powered_mass_points + powered_mass_point_index;
}
mass_point->flags = 0;
matrix4x3_transform_point(
&instance->world_matrix,
&mass_point_definition->position,
&mass_point->position);
if (powered_mass_point)
{
real_matrix4x3 powered_world_matrix;
matrix4x3_multiply(&instance->world_matrix, &powered_mass_point->rotation_matrix, &powered_world_matrix);
matrix4x3_transform_normal(&powered_world_matrix, &mass_point_definition->forward, &mass_point->forward);
matrix4x3_transform_normal(&powered_world_matrix, &mass_point_definition->up, &mass_point->up);
}
else
{
matrix4x3_transform_normal(&instance->world_matrix, &mass_point_definition->forward, &mass_point->forward);
matrix4x3_transform_normal(&instance->world_matrix, &mass_point_definition->up, &mass_point->up);
}
scenario_location_from_point(&mass_point->location, &mass_point->position);
vector_from_points3d(&object->object.position, &mass_point->position, &mass_point->radius);
cross_product3d(&object->object.angular_velocity, &mass_point->radius, &mass_point->velocity);
add_vectors3d(&object->object.translational_velocity, &mass_point->velocity, &mass_point->velocity);
compute_ground_plane(instance->object_index, mass_point, mass_point_definition);
mass_point->water_depth = scenario_location_water_depth(&mass_point->location, &mass_point->position);
if (mass_point->ground_depth > 0.0f)
{
struct material_definition const *material = scenario_material_definition_get(
mass_point->ground_material_type);
real ground_friction = physics->ground_friction;
real ground_normal_k1 = physics->ground_normal_k1;
real ground_normal_k0 = physics->ground_normal_k0;
real ground_depth = physics->ground_depth;
real ground_damp_fraction = physics->ground_damp_fraction;
real normal_velocity;
real ground_scale;
if (material->physics_ground_friction_scale > 0.0f && physics->mass <= 7500.0f)
ground_friction *= material->physics_ground_friction_scale;
if (material->physics_ground_friction_normal_k1_scale > 0.0f)
ground_normal_k1 *= material->physics_ground_friction_normal_k1_scale;
if (material->physics_ground_friction_normal_k0_scale > 0.0f)
ground_normal_k0 *= material->physics_ground_friction_normal_k0_scale;
if (material->physics_ground_depth_scale > 0.0f)
ground_depth *= material->physics_ground_depth_scale;
if (material->physics_ground_damp_fraction_scale > 0.0f)
ground_damp_fraction *= material->physics_ground_damp_fraction_scale;
normal_velocity = dot_product3d(&mass_point->velocity, &mass_point->ground_plane.n);
mass_point->normal_force_magnitude = physics->mass*
(global_gravity/ground_depth*mass_point->ground_depth - normal_velocity*ground_damp_fraction);
scale_vector3d(&mass_point->ground_plane.n, mass_point->normal_force_magnitude, &mass_point->normal_force);
scale_vector3d(&mass_point->ground_plane.n, -normal_velocity, &mass_point->velocity_relative_to_ground);
add_vectors3d(&mass_point->velocity_relative_to_ground, &mass_point->velocity, &mass_point->velocity_relative_to_ground);
ground_scale = -mass_point_definition->mass*ground_friction;
scale_vector3d(&mass_point->velocity_relative_to_ground, ground_scale, &mass_point->ground_friction.friction);
if (powered_mass_point_definition &&
TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_ground_friction_bit) &&
powered_mass_point->ground_friction_velocity != 0.0f)
{
real fraction = pin_fraction(mass_point->ground_plane.n.k, ground_normal_k0, ground_normal_k1);
real alignment = PIN(dot_product3d(&mass_point->up, &mass_point->ground_plane.n), 0.0f, 1.0f);
real weight = alignment*alignment*fraction*fraction*ground_scale;
real_vector3d projected_velocity;
scale_vector3d(&mass_point->forward, -powered_mass_point->ground_friction_velocity, &powered_velocity);
scale_vector3d(
&mass_point->ground_plane.n,
-dot_product3d(&powered_velocity, &mass_point->ground_plane.n),
&projected_velocity);
add_vectors3d(&projected_velocity, &powered_velocity, &projected_velocity);
add_vectors3d(&mass_point->velocity_relative_to_ground, &projected_velocity, &mass_point->velocity_relative_to_ground);
scale_vector3d(&projected_velocity, weight, &projected_velocity);
add_vectors3d(&mass_point->ground_friction.friction, &projected_velocity, &mass_point->ground_friction.friction);
}
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->ground_friction,
&mass_point->forward,
&mass_point->up);
}
if (mass_point->water_depth > 0.0f)
{
real depth_fraction = mass_point->water_depth < physics->water_depth ?
mass_point->water_depth/physics->water_depth : 1.0f;
real water_scale = -mass_point_definition->mass*physics->water_friction;
if (mass_point_definition->density > 0.0f && physics->water_depth > 0.0f)
{
mass_point->water_pressure_magnitude = mass_point_definition->mass/mass_point_definition->density*
physics->water_density*depth_fraction*gravity;
set_real_vector3d(&mass_point->water_pressure, 0.0f, 0.0f, mass_point->water_pressure_magnitude);
}
if (powered_mass_point_definition &&
TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_water_friction_bit) &&
powered_mass_point->water_friction_velocity != 0.0f)
{
scale_vector3d(&mass_point->forward, -powered_mass_point->water_friction_velocity, &powered_velocity);
add_vectors3d(&powered_velocity, &mass_point->velocity, &powered_velocity);
scale_vector3d(&powered_velocity, water_scale, &mass_point->water_friction.friction);
}
else
{
scale_vector3d(&mass_point->velocity, water_scale, &mass_point->water_friction.friction);
}
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->water_friction,
&mass_point->forward,
&mass_point->up);
if (powered_mass_point_definition &&
TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_water_lift_bit) &&
powered_mass_point->water_lift_ratio != 0.0f)
{
real lift = fabs(dot_product3d(&mass_point->forward, &mass_point->velocity))*
powered_mass_point->water_lift_ratio*physics->mass*depth_fraction;
real_vector3d lift_force;
scale_vector3d(&mass_point->up, lift, &lift_force);
add_vectors3d(&mass_point->powered_force, &lift_force, &mass_point->powered_force);
}
}
{
real air_scale = -mass_point_definition->mass*physics->air_friction;
if (powered_mass_point_definition &&
TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_air_friction_bit) &&
powered_mass_point->air_friction_velocity != 0.0f)
{
scale_vector3d(&mass_point->forward, -powered_mass_point->air_friction_velocity, &powered_velocity);
add_vectors3d(&powered_velocity, &mass_point->velocity, &powered_velocity);
scale_vector3d(&powered_velocity, air_scale, &mass_point->air_friction.friction);
}
else
{
scale_vector3d(&mass_point->velocity, air_scale, &mass_point->air_friction.friction);
}
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->air_friction,
&mass_point->forward,
&mass_point->up);
if (powered_mass_point_definition &&
TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_air_lift_bit) &&
powered_mass_point->air_lift_ratio != 0.0f)
{
real lift = fabs(dot_product3d(&mass_point->forward, &mass_point->velocity))*
physics->mass*powered_mass_point->air_lift_ratio;
real_vector3d lift_force;
scale_vector3d(&mass_point->up, lift, &lift_force);
add_vectors3d(&mass_point->powered_force, &lift_force, &mass_point->powered_force);
}
}
SET_FLAG(mass_point->flags, _point_at_rest_bit, magnitude_squared3d(&mass_point->velocity) < 0.0011111111f);
SET_FLAG(mass_point->flags, _point_on_ground_bit, mass_point->ground_depth > 0.0f);
SET_FLAG(mass_point->flags, _point_in_water_bit, mass_point->water_depth > 0.0f);
if (powered_mass_point_definition)
{
if (TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_thrust_bit))
{
real_vector3d thrust;
scale_vector3d(&mass_point->forward, powered_mass_point->thrust_fraction*physics->mass, &thrust);
add_vectors3d(&mass_point->powered_force, &thrust, &mass_point->powered_force);
}
if (TEST_FLAG(powered_mass_point_definition->flags, _powered_mass_point_antigrav_bit))
{
real probe_length = mass_point_definition->radius + powered_mass_point_definition->antigrav_height;
real_point3d point = mass_point->position;
real_vector3d probe_vector;
struct collision_result collision;
scale_vector3d(global_down3d, probe_length, &probe_vector);
if (collision_test_vector(
_collision_test_for_bipeds_dead_flags,
&point,
&probe_vector,
instance->object_index,
&collision))
{
real height = probe_length*collision.t - mass_point_definition->radius;
real alignment = pin_fraction(
mass_point->up.k,
powered_mass_point_definition->antigrav_normal_k0,
powered_mass_point_definition->antigrav_normal_k1);
real ground_effect = height > 0.0f ?
1.0f - height/powered_mass_point_definition->antigrav_height : 1.0f;
real magnitude = (ground_effect*ground_effect*global_gravity -
dot_product3d(&collision.plane.n, &mass_point->velocity)*
powered_mass_point_definition->antigrav_damp_fraction)*
powered_mass_point->antigrav_fraction*
powered_mass_point_definition->antigrav_strength*
physics->mass*alignment;
real_vector3d antigrav_force;
scale_vector3d(&collision.plane.n, magnitude, &antigrav_force);
add_vectors3d(&mass_point->powered_force, &antigrav_force, &mass_point->powered_force);
SET_FLAG(mass_point->flags, _point_antigraving_bit, TRUE);
}
}
}
add_vectors3d(&mass_point->normal_force, &mass_point->ground_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->water_pressure, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->water_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->air_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->powered_force, &mass_point->force);
cross_product3d(&mass_point->radius, &mass_point->force, &mass_point->torque);
add_vectors3d(total_force, &mass_point->force, total_force);
add_vectors3d(total_torque, &mass_point->torque, total_torque);
}
return;
}
static boolean physics_compute_biped_collision(
struct collision_model_instance *instance,
long biped_index)
{
static real scales[] = { 0.5f, 0.25f, 1.0f };
boolean collision = FALSE;
real_point3d base;
real height;
real width;
biped_get_physics_pill(biped_index, &base, &height, &width);
if (collision_model_test_point(instance, &base))
{
collision = TRUE;
}
else
{
struct collision_feature_list features;
struct collision_plane collision_plane;
real_point3d center;
real radius;
real feature_width;
collision_features_new(&features);
set_real_point3d(&center, base.x, base.y, base.z + height*0.5f);
radius = height*0.5f + width;
feature_width = MAX(width - 0.015625f, 0.015625f);
collision_model_get_features_in_sphere(
instance,
&center,
radius,
height,
feature_width,
&features);
if (collision_features_test_point(&features, &base, &collision_plane))
collision = TRUE;
}
if (collision)
{
struct unit_datum *vehicle = vehicle_get(instance->object_index);
struct biped_datum *biped = biped_get(biped_index);
real vehicle_speed = magnitude3d(&vehicle->object.translational_velocity);
real_vector3d acceleration;
real_point3d new_position;
boolean cause_damage = TRUE;
vector_from_points3d(
&vehicle->object.bounding_sphere_center,
&biped->object.bounding_sphere_center,
&acceleration);
normalize3d(&acceleration);
acceleration.k += 0.8f;
normalize3d(&acceleration);
scale_vector3d(&acceleration, MAX(vehicle_speed, 0.1f), &acceleration);
add_vectors3d(&acceleration, &vehicle->object.translational_velocity, &acceleration);
scale_vector3d(&acceleration, 0.5f, &acceleration);
biped_accelerate(biped_index, &acceleration);
base.x += acceleration.i*2.0f;
base.y += acceleration.j*2.0f;
base.z += acceleration.k*2.0f;
if (collision_fix_pill(
_collision_test_for_bipeds_living_flags,
&base,
width*2.0f,
height,
width,
biped_index,
&new_position))
{
new_position.z -= width;
object_translate(biped_index, &new_position, NULL);
cause_damage =
(instance->object_index != biped->unit.last_vehicle_index ||
game_time_get() > biped->unit.game_time_at_last_vehicle_exit + 90) &&
(vehicle_speed > 0.06666667f ||
distance_squared3d(
(real_point3d const *)&vehicle->object.translational_velocity,
(real_point3d const *)&biped->object.translational_velocity) > 0.0011111111f);
}
if (cause_damage)
{
struct game_globals_falling_damage *falling_damage = TAG_BLOCK_GET_ELEMENT(
&scenario_get_game_globals()->falling_damage,
0,
struct game_globals_falling_damage);
if (falling_damage->vehicle_collision_damage.index != NONE)
{
long responsible_object_index = instance->object_index;
struct object_datum *responsible_object = (struct object_datum *)vehicle;
struct damage_data damage;
if (vehicle->unit.driver_object_index != NONE)
{
responsible_object_index = vehicle->unit.driver_object_index;
responsible_object = object_get(responsible_object_index);
}
damage_data_new(&damage, falling_damage->vehicle_collision_damage.index);
damage.scale = 1.0f;
SET_FLAG(damage.flags, _damage_area_of_effect_bit, TRUE);
damage.owner_player_index = responsible_object->object.owner_player_index;
damage.owner_object_index = responsible_object->object.owner_object_index != NONE ?
responsible_object->object.owner_object_index : responsible_object_index;
damage.owner_team_index = responsible_object->object.owner_team_index;
damage.origin = biped->object.bounding_sphere_center;
damage.epicenter = vehicle->object.bounding_sphere_center;
damage.direction = acceleration;
normalize3d(&damage.direction);
object_cause_damage(&damage, biped_index, NONE, NONE, NONE, NULL);
}
if (falling_damage->vehicle_killed_unit_damage_effect.index != NONE)
{
struct unit_definition *unit_definition = unit_definition_get(biped->definition_index);
struct damage_data damage;
damage_data_new(&damage, falling_damage->vehicle_killed_unit_damage_effect.index);
match_assert(
"c:\\halo\\SOURCE\\physics\\physics.c",
830,
unit_definition->unit.blip_type>=0 && unit_definition->unit.blip_type<NUMBEROF(scales));
damage.scale = scales[unit_definition->unit.blip_type];
damage.origin = biped->object.bounding_sphere_center;
scale_vector3d(&acceleration, -1.0f, &damage.direction);
object_cause_damage(&damage, instance->object_index, NONE, NONE, NONE, NULL);
}
}
}
return collision;
}
static boolean physics_compute_vehicle_collision(
struct physics_instance const *instance0,
struct physics_instance const *instance1)
{
boolean collision = FALSE;
struct vehicle_datum *object0 = vehicle_datum_get(instance0->object_index);
struct vehicle_datum *object1 = vehicle_datum_get(instance1->object_index);
real mass_scale = square_root(instance0->physics->mass * instance1->physics->mass);
real_vector3d force0;
real_vector3d force1;
real_vector3d torque0;
real_vector3d torque1;
short mass_point0_index;
short mass_point0_count;
short mass_point1_count;
set_real_vector3d(&force0, 0.0f, 0.0f, 0.0f);
set_real_vector3d(&force1, 0.0f, 0.0f, 0.0f);
set_real_vector3d(&torque0, 0.0f, 0.0f, 0.0f);
set_real_vector3d(&torque1, 0.0f, 0.0f, 0.0f);
/* port: (physics_mass_point_count) */
mass_point0_count = physics_mass_point_count(instance0->physics);
mass_point1_count = physics_mass_point_count(instance1->physics);
for (mass_point0_index = 0;
mass_point0_index < mass_point0_count;
mass_point0_index++)
{
struct mass_point_definition const *mass_point0 = TAG_BLOCK_GET_ELEMENT(
&instance0->physics->mass_points,
mass_point0_index,
struct mass_point_definition);
real_point3d point0;
short mass_point1_index;
matrix4x3_transform_point(&instance0->world_matrix, &mass_point0->position, &point0);
for (mass_point1_index = 0;
mass_point1_index < mass_point1_count;
mass_point1_index++)
{
struct mass_point_definition const *mass_point1 = TAG_BLOCK_GET_ELEMENT(
&instance1->physics->mass_points,
mass_point1_index,
struct mass_point_definition);
real radius = mass_point0->radius + mass_point1->radius;
real_point3d point1;
real_vector3d direction;
real distance;
matrix4x3_transform_point(&instance1->world_matrix, &mass_point1->position, &point1);
vector_from_points3d(&point0, &point1, &direction);
distance = normalize3d(&direction);
if (distance < radius && distance > 0.0f)
{
real penetration = (radius - distance) * 0.5f;
real force_magnitude = 2.0f * mass_scale * global_gravity /
global_physics_collision_depth * penetration;
real_vector3d collision_force0;
real_vector3d collision_force1;
real_point3d collision_point;
real_vector3d radius0;
real_vector3d radius1;
real_vector3d collision_torque0;
real_vector3d collision_torque1;
scale_vector3d(&direction, -force_magnitude, &collision_force0);
scale_vector3d(&direction, force_magnitude, &collision_force1);
point_from_line3d(&point0, &direction, mass_point0->radius - penetration, &collision_point);
vector_from_points3d(&object0->object.position, &collision_point, &radius0);
vector_from_points3d(&object1->object.position, &collision_point, &radius1);
cross_product3d(&radius0, &collision_force0, &collision_torque0);
cross_product3d(&radius1, &collision_force1, &collision_torque1);
add_vectors3d(&force0, &collision_force0, &force0);
add_vectors3d(&force1, &collision_force1, &force1);
add_vectors3d(&torque0, &collision_torque0, &torque0);
add_vectors3d(&torque1, &collision_torque1, &torque1);
collision = TRUE;
}
}
}
if (collision)
{
add_vectors3d(&object0->vehicle.collision_force, &force0, &object0->vehicle.collision_force);
add_vectors3d(&object0->vehicle.collision_torque, &torque0, &object0->vehicle.collision_torque);
SET_FLAG(object0->object.flags, _object_at_rest_bit, FALSE);
if (!(instance1->physics->radius > 0.0f))
{
add_vectors3d(&object1->vehicle.collision_force, &force1, &object1->vehicle.collision_force);
add_vectors3d(&object1->vehicle.collision_torque, &torque1, &object1->vehicle.collision_torque);
SET_FLAG(object1->object.flags, _object_at_rest_bit, FALSE);
}
}
return collision;
}
static void physics_compute_unit_collisions(
long vehicle_index)
{
struct collision_model_instance collision_instance;
struct physics_instance vehicle_physics;
long object_indices[2048];
boolean model_instance_valid = collision_model_instance_new(
&collision_instance,
vehicle_index);
struct unit_datum *vehicle;
short object_count;
short object_number;
if (!physics_instance_new(&vehicle_physics, vehicle_index))
return;
vehicle = vehicle_get(vehicle_index);
object_count = objects_in_sphere(
_object_mask_biped,
_object_mask_vehicle + (model_instance_valid ? _object_mask_biped : 0),
&vehicle->object.location,
&vehicle->object.bounding_sphere_center,
vehicle->object.bounding_sphere_radius,
object_indices,
NUMBEROF(object_indices));
for (object_number = 0; object_number < object_count; object_number++)
{
long object_index = object_indices[object_number];
struct object_header_datum *object_header = object_header_get(object_index);
switch (object_header->type)
{
case _object_type_biped:
{
struct biped_datum *biped = biped_get(object_index);
match_assert(
"c:\\halo\\SOURCE\\physics\\physics.c",
669,
model_instance_valid);
if (!TEST_FLAG(biped->object.damage_flags, _object_dead_bit))
physics_compute_biped_collision(&collision_instance, object_index);
break;
}
case _object_type_vehicle:
{
if (object_index != vehicle_index)
{
struct physics_instance other_physics;
if (physics_instance_new(&other_physics, object_index))
{
struct unit_datum *other_vehicle = vehicle_get(object_index);
if (DATUM_INDEX_TO_ABSOLUTE_INDEX(object_index) <
DATUM_INDEX_TO_ABSOLUTE_INDEX(vehicle_index) ||
TEST_FLAG(other_vehicle->object.flags, _object_at_rest_bit) ||
other_physics.physics->radius > 0.0f)
{
physics_compute_vehicle_collision(&vehicle_physics, &other_physics);
}
}
}
break;
}
default:
break;
}
}
return;
}
static void rotate_vectors3d_by_angular_velocity(
real_vector3d const *forward,
real_vector3d const *up,
real_vector3d const *angular_velocity,
real_vector3d *rotated_forward,
real_vector3d *rotated_up)
{
real_vector3d axis = *angular_velocity;
real magnitude = normalize3d(&axis);
match_assert("c:\\halo\\SOURCE\\physics\\physics.c", 944, forward!=rotated_forward);
match_assert("c:\\halo\\SOURCE\\physics\\physics.c", 945, up!=rotated_up);
if (magnitude != 0.0f)
{
real_matrix4x3 rotation;
real dot;
matrix4x3_rotation_from_axis_and_angle(
&rotation,
&axis,
sine(magnitude),
cosine(magnitude));
matrix4x3_transform_vector(&rotation, forward, rotated_forward);
matrix4x3_transform_vector(&rotation, up, rotated_up);
normalize3d(rotated_forward);
dot = -dot_product3d(rotated_up, rotated_forward);
rotated_up->i += dot*rotated_forward->i;
rotated_up->j += dot*rotated_forward->j;
rotated_up->k += dot*rotated_forward->k;
normalize3d(rotated_up);
}
else
{
*rotated_forward = *forward;
*rotated_up = *up;
}
match_assert_valid_real_vector3d_axes2(
"c:\\halo\\SOURCE\\physics\\physics.c",
965,
rotated_forward,
rotated_up);
return;
}
void physics_update_new(
struct physics_instance const *instance,
struct powered_mass_point_datum const *powered_mass_points,
struct mass_point_datum const *mass_points,
real_vector3d const *total_force,
real_vector3d const *total_torque)
{
struct vehicle_datum *vehicle = vehicle_datum_get(instance->object_index);
real_vector3d linear_acceleration;
real_vector3d linear_velocity;
real_point3d position;
real_vector3d angular_acceleration;
real_vector3d angular_velocity;
real_vector3d forward;
real_vector3d up;
short mass_point_index;
/* port: (as in physics_compute_new) */
short mass_point_count = physics_mass_point_count(instance->physics);
match_assert(
"c:\\halo\\SOURCE\\physics\\physics.c",
986,
instance->physics->mass>0.0f);
scale_vector3d(total_force, 1.0f/instance->physics->mass, &linear_acceleration);
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
990,
&linear_acceleration);
add_vectors3d(&linear_acceleration, &vehicle->object.translational_velocity, &linear_velocity);
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
994,
&linear_velocity);
position.x = vehicle->object.position.x + linear_velocity.i;
position.y = vehicle->object.position.y + linear_velocity.j;
position.z = vehicle->object.position.z + linear_velocity.k;
/* port: a physics (from the map) without its inverse inertia matrix
(the second of its two; the retail ones all have both) turns no faster */
if (instance->physics->inertial_matrix.count < 2)
{
if (!warned_about_physics_inertial_matrix)
{
error(_error_silent, "a physics has %ld inertial matrices (2 expected)",
instance->physics->inertial_matrix.count);
warned_about_physics_inertial_matrix = TRUE;
}
set_real_vector3d(&angular_acceleration, 0.0f, 0.0f, 0.0f);
}
else
{
real_matrix3x3 frame;
real_matrix3x3 world_inverse_inertia;
matrix3x3_from_forward_and_up(
&frame,
&vehicle->object.forward,
&vehicle->object.up);
matrix3x3_multiply(
&frame,
TAG_BLOCK_GET_ELEMENT(
&instance->physics->inertial_matrix,
1,
real_matrix3x3),
&world_inverse_inertia);
matrix3x3_multiply(
&world_inverse_inertia,
matrix3x3_transpose(&frame, &frame),
&world_inverse_inertia);
matrix3x3_transform_vector(
&world_inverse_inertia,
total_torque,
&angular_acceleration);
}
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1008,
&angular_acceleration);
add_vectors3d(&angular_acceleration, &vehicle->object.angular_velocity, &angular_velocity);
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1012,
&angular_velocity);
rotate_vectors3d_by_angular_velocity(
&vehicle->object.forward,
&vehicle->object.up,
&angular_velocity,
&forward,
&up);
vehicle->object.translational_velocity = linear_velocity;
vehicle->object.angular_velocity = angular_velocity;
if (debug_physics_disable_penetration_freeze)
{
object_set_position(instance->object_index, &position, &forward, &up);
}
else
{
short passes_remaining = 4;
unsigned long stuck_mass_point_flags;
while (passes_remaining-- > 0)
{
boolean found_collision = FALSE;
real_vector3d worst_delta;
struct collision_result worst_collision;
real_matrix4x3 world_matrix;
real_point3d center_of_mass;
stuck_mass_point_flags = 0;
matrix4x3_from_point_and_vectors(&world_matrix, &position, &forward, &up);
set_real_point3d(&center_of_mass,
-instance->physics->center_of_mass.x,
-instance->physics->center_of_mass.y,
-instance->physics->center_of_mass.z);
matrix4x3_transform_point(&world_matrix, &center_of_mass, &center_of_mass);
world_matrix.position = center_of_mass;
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&instance->physics->mass_points,
mass_point_index,
struct mass_point_definition);
struct mass_point_datum const *mass_point = mass_points + mass_point_index;
real_point3d swept_position;
real_vector3d delta;
struct collision_result collision;
matrix4x3_transform_point(
&world_matrix,
&mass_point_definition->position,
&swept_position);
vector_from_points3d(&mass_point->position, &swept_position, &delta);
if (collision_test_vector(
_collision_test_for_vehicles_flags |
FLAG(_collision_test_front_facing_surfaces_bit),
&mass_point->position,
&delta,
instance->object_index,
&collision))
{
SET_FLAG(stuck_mass_point_flags, mass_point_index, TRUE);
if (!found_collision || worst_collision.t > collision.t)
{
found_collision = TRUE;
worst_delta = delta;
worst_collision = collision;
}
}
}
if (!found_collision)
{
object_set_position(instance->object_index, &position, &forward, &up);
break;
}
else
{
real normal_dot_delta = dot_product3d(&worst_delta, &worst_collision.plane.n);
real epsilon = (real)(normal_dot_delta != 0.0f ?
0.0078125/fabs(normal_dot_delta) : 0.03125);
real t = MAX(worst_collision.t - epsilon, 0.0f);
real normal_dot_velocity = dot_product3d(&worst_collision.plane.n, &linear_velocity);
if (normal_dot_velocity < 0.0f)
{
PHYSICS_POINT_FROM_LINE3D(
&linear_velocity,
&worst_collision.plane.n,
(t - 1.0f)*normal_dot_velocity,
&linear_velocity);
vehicle->object.translational_velocity = linear_velocity;
position.x = vehicle->object.position.x + linear_velocity.i;
position.y = vehicle->object.position.y + linear_velocity.j;
position.z = vehicle->object.position.z + linear_velocity.k;
}
scale_vector3d(&angular_velocity, t, &angular_velocity);
vehicle->object.angular_velocity = angular_velocity;
rotate_vectors3d_by_angular_velocity(
&vehicle->object.forward,
&vehicle->object.up,
&angular_velocity,
&forward,
&up);
}
}
vehicle->vehicle.stuck_mass_point_flags = stuck_mass_point_flags;
}
{
short at_rest_count = 0;
short on_ground_count = 0;
short on_volatile_surface_count = 0;
short in_water_count = 0;
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_datum const *mass_point = mass_points + mass_point_index;
at_rest_count += TEST_FLAG(mass_point->flags, _point_at_rest_bit);
on_ground_count += TEST_FLAG(mass_point->flags, _point_on_ground_bit);
on_volatile_surface_count += TEST_FLAG(mass_point->flags, _point_on_volatile_surface_bit);
in_water_count += TEST_FLAG(mass_point->flags, _point_in_water_bit);
}
SET_FLAG(
vehicle->object.flags,
_object_at_rest_bit,
at_rest_count == mass_point_count &&
on_ground_count >= 3 &&
on_volatile_surface_count == 0 &&
magnitude_squared3d(&linear_velocity) <= 0.0011111111f &&
magnitude_squared3d(&angular_velocity) <= 0.0027415568f &&
magnitude_squared3d(&linear_acceleration) <= 0.00000030864197f &&
magnitude_squared3d(&angular_acceleration) <= 0.0000030461742f);
SET_FLAG(vehicle->object.flags, _object_on_ground_bit, on_ground_count > 0);
SET_FLAG(vehicle->object.flags, _object_on_media_bit, in_water_count > 0);
SET_FLAG(vehicle->object.flags, _object_partially_under_media_bit, in_water_count > 0);
SET_FLAG(
vehicle->object.flags,
_object_wholly_under_media_bit,
in_water_count == mass_point_count);
}
return;
}
/* NonMatching: the owner-safe natural reconstruction is 0x1500 bytes with 116
* relocations versus the January target's 0x1430 bytes and 115 relocations.
* Its final axes predicate also falls out of line after the earlier codegen
* divergence, so this coherent candidate is parked without schedule tuning. */
static void physics_update_old(
long object_index,
struct powered_mass_point_datum *powered_mass_points,
struct mass_point_datum *mass_points,
real_vector3d const *magic_force,
real_vector3d const *magic_torque)
{
struct object_datum *object = object_get(object_index);
struct object_definition const *object_definition = object_definition_get(object->definition_index);
struct physics_definition const *physics = physics_definition_get(
object_definition->object.physics.index);
real gravity = physics->gravity_scale*global_gravity;
real_matrix4x3 world_matrix;
real_vector3d total_force = { 0.0f, 0.0f, -physics->mass*gravity };
real_vector3d total_torque = { 0.0f, 0.0f, 0.0f };
real_vector3d translational_acceleration = { 0.0f, 0.0f, 0.0f };
real_vector3d angular_acceleration = { 0.0f, 0.0f, 0.0f };
short stopped_mass_point_count = 0;
short grounded_mass_point_count = 0;
short volatile_mass_point_count = 0;
short submerged_mass_point_count = 0;
short mass_point_index;
/* port: (as in physics_compute_new) */
short mass_point_count = physics_mass_point_count(physics);
matrix4x3_from_point_and_vectors(
&world_matrix,
&object->object.position,
&object->object.forward,
&object->object.up);
if (powered_mass_points)
{
short powered_mass_point_index;
/* port: (physics_powered_mass_point_count) */
for (powered_mass_point_index = 0;
powered_mass_point_index < physics_powered_mass_point_count(physics);
powered_mass_point_index++)
{
struct powered_mass_point_datum *powered_mass_point =
powered_mass_points + powered_mass_point_index;
matrix4x3_rotation_from_quaternion(
&powered_mass_point->rotation_matrix,
&powered_mass_point->rotation);
matrix4x3_transpose(&powered_mass_point->rotation_matrix);
}
}
memset(mass_points, 0, sizeof(struct mass_point_datum)*mass_point_count);
if (magic_force)
{
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1255,
magic_force);
add_vectors3d(&total_force, magic_force, &total_force);
}
if (magic_torque)
{
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1261,
magic_torque);
total_torque = *magic_torque;
}
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&physics->mass_points,
mass_point_index,
struct mass_point_definition);
struct mass_point_datum *mass_point = mass_points + mass_point_index;
struct powered_mass_point_definition const *powered_mass_point_definition = NULL;
struct powered_mass_point_datum *powered_mass_point = NULL;
real_point3d local_position;
/* port: (physics_powered_mass_point_index) */
short powered_mass_point_index = physics_powered_mass_point_index(physics, mass_point_definition);
if (powered_mass_point_index != NONE && powered_mass_points)
{
powered_mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&physics->powered_mass_points,
powered_mass_point_index,
struct powered_mass_point_definition);
if (powered_mass_point_definition)
{
powered_mass_point =
powered_mass_points + powered_mass_point_index;
}
}
mass_point->flags = 0;
local_position.x = mass_point_definition->position.x - physics->center_of_mass.x;
local_position.y = mass_point_definition->position.y - physics->center_of_mass.y;
local_position.z = mass_point_definition->position.z - physics->center_of_mass.z;
matrix4x3_transform_point(&world_matrix, &local_position, &mass_point->position);
if (powered_mass_point)
{
real_matrix4x3 powered_world_matrix;
matrix4x3_multiply(
&world_matrix,
&powered_mass_point->rotation_matrix,
&powered_world_matrix);
matrix4x3_transform_normal(
&powered_world_matrix,
&mass_point_definition->forward,
&mass_point->forward);
matrix4x3_transform_normal(
&powered_world_matrix,
&mass_point_definition->up,
&mass_point->up);
}
else
{
matrix4x3_transform_normal(
&world_matrix,
&mass_point_definition->forward,
&mass_point->forward);
matrix4x3_transform_normal(
&world_matrix,
&mass_point_definition->up,
&mass_point->up);
}
scenario_location_from_point(&mass_point->location, &mass_point->position);
vector_from_points3d(&object->object.position, &mass_point->position, &mass_point->radius);
cross_product3d(&object->object.angular_velocity, &mass_point->radius, &mass_point->velocity);
add_vectors3d(
&object->object.translational_velocity,
&mass_point->velocity,
&mass_point->velocity);
compute_ground_plane(object_index, mass_point, mass_point_definition);
mass_point->water_depth = scenario_location_water_depth(
&mass_point->location,
&mass_point->position);
if (mass_point->ground_depth > 0.0f && physics->ground_depth > 0.0f)
{
real normal_velocity = dot_product3d(
&mass_point->velocity,
&mass_point->ground_plane.n);
real ground_scale = -mass_point_definition->mass*physics->ground_friction;
mass_point->normal_force_magnitude = physics->mass*(
global_gravity/physics->ground_depth*mass_point->ground_depth -
normal_velocity*physics->ground_damp_fraction);
scale_vector3d(
&mass_point->ground_plane.n,
mass_point->normal_force_magnitude,
&mass_point->normal_force);
scale_vector3d(
&mass_point->ground_plane.n,
-normal_velocity,
&mass_point->velocity_relative_to_ground);
add_vectors3d(
&mass_point->velocity_relative_to_ground,
&mass_point->velocity,
&mass_point->velocity_relative_to_ground);
scale_vector3d(
&mass_point->velocity_relative_to_ground,
ground_scale,
&mass_point->ground_friction.friction);
if (powered_mass_point_definition &&
TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_ground_friction_bit) &&
powered_mass_point->ground_friction_velocity != 0.0f)
{
real fraction = pin_fraction(
mass_point->ground_plane.n.k,
physics->ground_normal_k0,
physics->ground_normal_k1);
real alignment = PIN(
dot_product3d(&mass_point->up, &mass_point->ground_plane.n),
0.0f,
1.0f);
real weight = alignment*alignment*fraction*fraction*ground_scale;
real_vector3d powered_velocity;
real_vector3d projected_velocity;
scale_vector3d(
&mass_point->forward,
-powered_mass_point->ground_friction_velocity,
&powered_velocity);
scale_vector3d(
&mass_point->ground_plane.n,
-dot_product3d(&powered_velocity, &mass_point->ground_plane.n),
&projected_velocity);
add_vectors3d(&projected_velocity, &powered_velocity, &projected_velocity);
add_vectors3d(
&mass_point->velocity_relative_to_ground,
&projected_velocity,
&mass_point->velocity_relative_to_ground);
scale_vector3d(&projected_velocity, weight, &projected_velocity);
add_vectors3d(
&mass_point->ground_friction.friction,
&projected_velocity,
&mass_point->ground_friction.friction);
}
if (mass_point->ground_material_type == _material_ice)
{
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale*0.125f,
mass_point_definition->friction_perpendicular_scale*0.125f,
&mass_point->ground_friction,
&mass_point->forward,
&mass_point->up);
}
else
{
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->ground_friction,
&mass_point->forward,
&mass_point->up);
}
}
if (mass_point->water_depth > 0.0f)
{
real depth_fraction = mass_point->water_depth < physics->water_depth ?
mass_point->water_depth/physics->water_depth : 1.0f;
real water_scale = -mass_point_definition->mass*physics->water_friction;
if (mass_point_definition->density > 0.0f && physics->water_depth > 0.0f)
{
mass_point->water_pressure_magnitude =
mass_point_definition->mass/mass_point_definition->density*
physics->water_density*depth_fraction*gravity;
set_real_vector3d(
&mass_point->water_pressure,
0.0f,
0.0f,
mass_point->water_pressure_magnitude);
}
if (powered_mass_point_definition &&
TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_water_friction_bit) &&
powered_mass_point->water_friction_velocity != 0.0f)
{
real_vector3d powered_velocity;
scale_vector3d(
&mass_point->forward,
-powered_mass_point->water_friction_velocity,
&powered_velocity);
add_vectors3d(&powered_velocity, &mass_point->velocity, &powered_velocity);
scale_vector3d(
&powered_velocity,
water_scale,
&mass_point->water_friction.friction);
}
else
{
scale_vector3d(
&mass_point->velocity,
water_scale,
&mass_point->water_friction.friction);
}
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->water_friction,
&mass_point->forward,
&mass_point->up);
if (powered_mass_point_definition &&
TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_water_lift_bit) &&
powered_mass_point->water_lift_ratio != 0.0f)
{
real lift = fabs(dot_product3d(&mass_point->forward, &mass_point->velocity))*
powered_mass_point->water_lift_ratio*physics->mass*depth_fraction;
real_vector3d lift_force;
scale_vector3d(&mass_point->up, lift, &lift_force);
add_vectors3d(&mass_point->powered_force, &lift_force, &mass_point->powered_force);
}
}
{
real air_scale = -mass_point_definition->mass*physics->air_friction;
if (powered_mass_point_definition &&
TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_air_friction_bit) &&
powered_mass_point->air_friction_velocity != 0.0f)
{
real_vector3d powered_velocity;
scale_vector3d(
&mass_point->forward,
-powered_mass_point->air_friction_velocity,
&powered_velocity);
add_vectors3d(&powered_velocity, &mass_point->velocity, &powered_velocity);
scale_vector3d(
&powered_velocity,
air_scale,
&mass_point->air_friction.friction);
}
else
{
scale_vector3d(
&mass_point->velocity,
air_scale,
&mass_point->air_friction.friction);
}
friction_evaluate(
mass_point_definition->friction_type,
mass_point_definition->friction_parallel_scale,
mass_point_definition->friction_perpendicular_scale,
&mass_point->air_friction,
&mass_point->forward,
&mass_point->up);
if (powered_mass_point_definition &&
TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_air_lift_bit) &&
powered_mass_point->air_lift_ratio != 0.0f)
{
real lift = fabs(dot_product3d(&mass_point->forward, &mass_point->velocity))*
powered_mass_point->air_lift_ratio*physics->mass;
real_vector3d lift_force;
scale_vector3d(&mass_point->up, lift, &lift_force);
add_vectors3d(&mass_point->powered_force, &lift_force, &mass_point->powered_force);
}
}
SET_FLAG(
mass_point->flags,
_point_at_rest_bit,
magnitude_squared3d(&mass_point->velocity) < 0.0011111111f);
SET_FLAG(mass_point->flags, _point_on_ground_bit, mass_point->ground_depth > 0.0f);
SET_FLAG(mass_point->flags, _point_in_water_bit, mass_point->water_depth > 0.0f);
stopped_mass_point_count += TEST_FLAG(mass_point->flags, _point_at_rest_bit);
grounded_mass_point_count += TEST_FLAG(mass_point->flags, _point_on_ground_bit);
volatile_mass_point_count += TEST_FLAG(
mass_point->flags,
_point_on_volatile_surface_bit);
submerged_mass_point_count += TEST_FLAG(mass_point->flags, _point_in_water_bit);
if (powered_mass_point_definition)
{
if (TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_thrust_bit))
{
real_vector3d thrust;
scale_vector3d(
&mass_point->forward,
powered_mass_point->thrust_fraction*physics->mass,
&thrust);
add_vectors3d(&mass_point->powered_force, &thrust, &mass_point->powered_force);
}
if (TEST_FLAG(
powered_mass_point_definition->flags,
_powered_mass_point_antigrav_bit))
{
real probe_length =
mass_point_definition->radius + powered_mass_point_definition->antigrav_height;
real_point3d point = mass_point->position;
real_vector3d probe_vector;
struct collision_result collision;
scale_vector3d(global_down3d, probe_length, &probe_vector);
if (collision_test_vector(
_collision_test_for_bipeds_dead_flags,
&point,
&probe_vector,
object_index,
&collision))
{
real height = probe_length*collision.t - mass_point_definition->radius;
real alignment = pin_fraction(
mass_point->up.k,
powered_mass_point_definition->antigrav_normal_k0,
powered_mass_point_definition->antigrav_normal_k1);
real ground_effect = height > 0.0f ?
1.0f - height/powered_mass_point_definition->antigrav_height : 1.0f;
real magnitude = (ground_effect*ground_effect*global_gravity -
dot_product3d(&collision.plane.n, &mass_point->velocity)*
powered_mass_point_definition->antigrav_damp_fraction)*
powered_mass_point->antigrav_fraction*
powered_mass_point_definition->antigrav_strength*
physics->mass*alignment;
real_vector3d antigrav_force;
scale_vector3d(&collision.plane.n, magnitude, &antigrav_force);
add_vectors3d(
&mass_point->powered_force,
&antigrav_force,
&mass_point->powered_force);
}
}
}
add_vectors3d(&mass_point->normal_force, &mass_point->ground_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->water_pressure, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->water_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->air_friction.friction, &mass_point->force);
add_vectors3d(&mass_point->force, &mass_point->powered_force, &mass_point->force);
cross_product3d(&mass_point->radius, &mass_point->force, &mass_point->torque);
add_vectors3d(&total_force, &mass_point->force, &total_force);
add_vectors3d(&total_torque, &mass_point->torque, &total_torque);
}
if (physics->mass != 0.0f)
scale_vector3d(&total_force, 1.0f/physics->mass, &translational_acceleration);
{
real_vector3d torque_axis = total_torque;
real torque_magnitude = normalize3d(&torque_axis);
if (torque_magnitude != 0.0f)
{
real moment_of_inertia = 0.0f;
for (mass_point_index = 0;
mass_point_index < mass_point_count;
mass_point_index++)
{
struct mass_point_definition const *mass_point_definition = TAG_BLOCK_GET_ELEMENT(
&physics->mass_points,
mass_point_index,
struct mass_point_definition);
struct mass_point_datum const *mass_point = mass_points + mass_point_index;
real projection = -dot_product3d(&mass_point->radius, &torque_axis);
real_vector3d perpendicular_radius;
scale_vector3d(&torque_axis, projection, &perpendicular_radius);
add_vectors3d(
&perpendicular_radius,
&mass_point->radius,
&perpendicular_radius);
moment_of_inertia += (
magnitude_squared3d(&perpendicular_radius) +
mass_point_definition->radius*mass_point_definition->radius*0.4f)*
mass_point_definition->mass*physics->moment;
}
if (moment_of_inertia != 0.0f)
{
scale_vector3d(
&total_torque,
1.0f/moment_of_inertia,
&angular_acceleration);
}
}
}
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1539,
&translational_acceleration);
add_vectors3d(
&object->object.translational_velocity,
&translational_acceleration,
&object->object.translational_velocity);
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
1543,
&angular_acceleration);
add_vectors3d(
&object->object.angular_velocity,
&angular_acceleration,
&object->object.angular_velocity);
{
real_point3d new_position;
struct location new_location;
real_vector3d rotation_axis;
real angular_speed;
new_position.x = object->object.position.x + object->object.translational_velocity.i;
new_position.y = object->object.position.y + object->object.translational_velocity.j;
new_position.z = object->object.position.z + object->object.translational_velocity.k;
scenario_location_from_line(
&new_location,
&object->object.location,
&object->object.position,
&new_position);
object_translate(object_index, &new_position, &new_location);
rotation_axis = object->object.angular_velocity;
angular_speed = normalize3d(&rotation_axis);
if (angular_speed != 0.0f)
{
real sine_value = sine(angular_speed);
real cosine_value = cosine(angular_speed);
real orthogonalization;
rotate_vector_about_axis(
&object->object.forward,
&rotation_axis,
sine_value,
cosine_value);
rotate_vector_about_axis(
&object->object.up,
&rotation_axis,
sine_value,
cosine_value);
normalize3d(&object->object.forward);
orthogonalization = -dot_product3d(
&object->object.up,
&object->object.forward);
object->object.up.i += orthogonalization*object->object.forward.i;
object->object.up.j += orthogonalization*object->object.forward.j;
object->object.up.k += orthogonalization*object->object.forward.k;
normalize3d(&object->object.up);
}
}
SET_FLAG(
object->object.flags,
_object_at_rest_bit,
stopped_mass_point_count == mass_point_count &&
grounded_mass_point_count >= 3 &&
volatile_mass_point_count == 0 &&
magnitude_squared3d(&object->object.translational_velocity) <= 0.0011111111f &&
magnitude_squared3d(&object->object.angular_velocity) <= 0.0027415568f &&
magnitude_squared3d(&translational_acceleration) <= 0.00000030864197f &&
magnitude_squared3d(&angular_acceleration) <= 0.0000030461742f);
SET_FLAG(object->object.flags, _object_on_ground_bit, grounded_mass_point_count > 0);
SET_FLAG(object->object.flags, _object_on_media_bit, submerged_mass_point_count > 0);
SET_FLAG(object->object.flags, _object_partially_under_media_bit, submerged_mass_point_count > 0);
SET_FLAG(
object->object.flags,
_object_wholly_under_media_bit,
submerged_mass_point_count == mass_point_count);
match_assert_valid_real_vector3d_axes2(
"c:\\halo\\SOURCE\\physics\\physics.c",
1595,
&object->object.forward,
&object->object.up);
return;
}
void physics_update(
long object_index,
struct powered_mass_point_datum *powered_mass_points,
struct mass_point_datum *mass_points,
real_vector3d const *magic_force,
real_vector3d const *magic_torque)
{
struct object_datum *object = object_get(object_index);
struct object_definition *object_definition = object_definition_get(object->definition_index);
struct physics_definition *physics = physics_definition_get(
object_definition->object.physics.index);
struct physics_instance instance;
real_vector3d total_force;
real_vector3d total_torque;
short powered_mass_point_index;
if (physics->radius > 0.0f)
{
physics_update_old(
object_index,
powered_mass_points,
mass_points,
magic_force,
magic_torque);
return;
}
physics_instance_new(&instance, object_index);
if (powered_mass_points)
{
/* port: (physics_powered_mass_point_count) */
for (powered_mass_point_index = 0;
powered_mass_point_index < physics_powered_mass_point_count(physics);
powered_mass_point_index++)
{
struct powered_mass_point_datum *powered_mass_point =
powered_mass_points + powered_mass_point_index;
matrix4x3_rotation_from_quaternion(
&powered_mass_point->rotation_matrix,
&powered_mass_point->rotation);
matrix4x3_transpose(&powered_mass_point->rotation_matrix);
}
}
physics_compute_new(
&instance,
powered_mass_points,
mass_points,
&total_force,
&total_torque);
{
struct vehicle_datum *vehicle = vehicle_datum_get(object_index);
total_force.i += vehicle->vehicle.collision_force.i;
total_force.j += vehicle->vehicle.collision_force.j;
total_force.k += vehicle->vehicle.collision_force.k;
total_torque.i += vehicle->vehicle.collision_torque.i;
total_torque.j += vehicle->vehicle.collision_torque.j;
total_torque.k += vehicle->vehicle.collision_torque.k;
vehicle->vehicle.collision_force.i = 0.0f;
vehicle->vehicle.collision_force.j = 0.0f;
vehicle->vehicle.collision_force.k = 0.0f;
vehicle->vehicle.collision_torque.i = 0.0f;
vehicle->vehicle.collision_torque.j = 0.0f;
vehicle->vehicle.collision_torque.k = 0.0f;
}
if (magic_force)
{
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
270,
magic_force);
total_force.i += magic_force->i;
total_force.j += magic_force->j;
total_force.k += magic_force->k;
}
if (magic_torque)
{
match_assert_valid_real_vector3d(
"c:\\halo\\SOURCE\\physics\\physics.c",
276,
magic_torque);
total_torque.i += magic_torque->i;
total_torque.j += magic_torque->j;
total_torque.k += magic_torque->k;
}
physics_update_new(
&instance,
powered_mass_points,
mass_points,
&total_force,
&total_torque);
physics_compute_unit_collisions(object_index);
return;
}
/* ---------- private code */