From 2db34d2913882feab4095738ce1dab600496718e Mon Sep 17 00:00:00 2001 From: Dethrace Engineering Department <78985374+dethrace-labs@users.noreply.github.com> Date: Tue, 3 May 2022 14:05:15 +1200 Subject: [PATCH] Implements "noncar" physics (#122) * Noncar physics * Noncar collision detection * Noncar bending and snap-off working --- src/BRSRC13/include/brender/br_inline_funcs.h | 14 +- src/BRSRC13/include/brender/br_types.h | 701 ++++---- src/DETHRACE/common/car.c | 1550 +++++++++++++++-- src/DETHRACE/common/crush.c | 6 +- src/DETHRACE/common/displays.c | 2 - src/DETHRACE/common/finteray.c | 44 +- src/DETHRACE/common/loading.c | 27 +- src/DETHRACE/common/world.c | 61 +- src/DETHRACE/constants.h | 30 +- src/DETHRACE/macros.h | 9 + src/harness/renderers/gl/gl_renderer.c | 11 +- 11 files changed, 1885 insertions(+), 570 deletions(-) diff --git a/src/BRSRC13/include/brender/br_inline_funcs.h b/src/BRSRC13/include/brender/br_inline_funcs.h index 4b5d77bf..d44cab0e 100644 --- a/src/BRSRC13/include/brender/br_inline_funcs.h +++ b/src/BRSRC13/include/brender/br_inline_funcs.h @@ -3,9 +3,10 @@ #include "br_defs.h" -#define BrVector2Set(v1, s1, s2) do { \ - (v1)->v[0] = (s1); \ - (v1)->v[1] = (s2); \ +#define BrVector2Set(v1, s1, s2) \ + do { \ + (v1)->v[0] = (s1); \ + (v1)->v[1] = (s2); \ } while (0) #define BrVector3Length(v1) BR_LENGTH3((v1)->v[0], (v1)->v[1], (v1)->v[2]) @@ -54,6 +55,13 @@ (v1)->v[2] = (v2)->v[2] - (v3)->v[2]; \ } while (0) +#define BrVector3Mul(v1, v2, v3) \ + do { \ + (v1)->v[0] = (v2)->v[0] * (v3)->v[0]; \ + (v1)->v[1] = (v2)->v[1] * (v3)->v[1]; \ + (v1)->v[2] = (v2)->v[2] * (v3)->v[2]; \ + } while (0) + #define BrVector3Accumulate(v1, v2) \ do { \ (v1)->v[0] += (v2)->v[0]; \ diff --git a/src/BRSRC13/include/brender/br_types.h b/src/BRSRC13/include/brender/br_types.h index 5e62c5e0..5905f35d 100644 --- a/src/BRSRC13/include/brender/br_types.h +++ b/src/BRSRC13/include/brender/br_types.h @@ -715,11 +715,11 @@ typedef br_pixelmap* dev_clone_cbfn(br_device*, br_pixelmap*); typedef void dev_free_cbfn(br_device*, br_pixelmap*); typedef struct br_resource_class { // size: 20 - br_uint_32 reserved; // @0 - char* identifier; // @4 - br_uint_8 res_class; // @8 + br_uint_32 reserved; // @0 + char* identifier; // @4 + br_uint_8 res_class; // @8 br_resourcefree_cbfn* free_cb; // @12 - br_uint_32 alignment; // @16 + br_uint_32 alignment; // @16 } br_resource_class; typedef struct br_filesystem { @@ -957,31 +957,31 @@ typedef struct br_quat { br_scalar w; } br_quat; -typedef struct br_transform { // size: 0x34 - br_uint_16 type; // @0x0 - union { // size: 0x30 - br_matrix34 mat; // @0x0 - struct { // size: 0x30 - br_euler e; // @0x0 +typedef struct br_transform { // size: 0x34 + br_uint_16 type; // @0x0 + union { // size: 0x30 + br_matrix34 mat; // @0x0 + struct { // size: 0x30 + br_euler e; // @0x0 br_scalar _pad[7]; // @0x8 - br_vector3 t; // @0x24 - } euler; // @0x0 - struct { // size: 0x30 - br_quat q; // @0x0 + br_vector3 t; // @0x24 + } euler; // @0x0 + struct { // size: 0x30 + br_quat q; // @0x0 br_scalar _pad[5]; // @0x10 - br_vector3 t; // @0x24 - } quat; // @0x0 - struct { // size: 0x30 - br_vector3 look; // @0x0 - br_vector3 up; // @0xc + br_vector3 t; // @0x24 + } quat; // @0x0 + struct { // size: 0x30 + br_vector3 look; // @0x0 + br_vector3 up; // @0xc br_scalar _pad[3]; // @0x18 - br_vector3 t; // @0x24 - } look_up; // @0x0 - struct { // size: 0x30 + br_vector3 t; // @0x24 + } look_up; // @0x0 + struct { // size: 0x30 br_scalar _pad[9]; // @0x0 - br_vector3 t; // @0x24 - } translate; // @0x0 - } t; // @0x4 + br_vector3 t; // @0x24 + } translate; // @0x0 + } t; // @0x4 } br_transform; typedef struct br_pixelmap { @@ -1127,24 +1127,24 @@ typedef struct br_associative_array_tag { br_uint_16 max_elements; } br_associative_array; -typedef struct br_device { // size: 68 - br_uint_32 magic; // @0 - char* identifier; // @4 - br_font* default_font; // @8 - br_uint_32 qualifier; // @12 - dev_fill_cbfn* fill; // @16 - dev_rectangle_copy_cbfn* rectangle_copy; // @20 - dev_rectangle_fill_cbfn* rectangle_fill; // @24 +typedef struct br_device { // size: 68 + br_uint_32 magic; // @0 + char* identifier; // @4 + br_font* default_font; // @8 + br_uint_32 qualifier; // @12 + dev_fill_cbfn* fill; // @16 + dev_rectangle_copy_cbfn* rectangle_copy; // @20 + dev_rectangle_fill_cbfn* rectangle_fill; // @24 dev_dirty_rectangle_copy_cbfn* dirty_rectangle_copy; // @28 dev_dirty_rectangle_fill_cbfn* dirty_rectangle_fill; // @32 - dev_plot_cbfn* plot; // @36 - dev_copy_cbfn* copy; // @40 - dev_line_cbfn* line; // @44 - dev_copy_bits_cbfn* copy_bits; // @48 - dev_double_buffer_cbfn* double_buffer; // @52 - dev_match_cbfn* match; // @56 - dev_clone_cbfn* clone; // @60 - dev_free_cbfn* free; // @64 + dev_plot_cbfn* plot; // @36 + dev_copy_cbfn* copy; // @40 + dev_line_cbfn* line; // @44 + dev_copy_bits_cbfn* copy_bits; // @48 + dev_double_buffer_cbfn* double_buffer; // @52 + dev_match_cbfn* match; // @56 + dev_clone_cbfn* clone; // @60 + dev_free_cbfn* free; // @64 } br_device; typedef struct br_outfcty_desc { @@ -1163,28 +1163,28 @@ typedef struct br_outfcty_desc { typedef struct br_renderer_facility br_renderer_facility; typedef struct br_device_pixelmap_dispatch br_device_pixelmap_dispatch; -typedef struct br_device_pixelmap { // size: 0x44 +typedef struct br_device_pixelmap { // size: 0x44 br_device_pixelmap_dispatch* dispatch; // @0x0 - char* pm_identifier; // @0x4 - void* pm_pixels; // @0x8 - br_uint_32 pm_pixels_qualifier; // @0xc - br_pixelmap* pm_map; // @0x10 - br_colour_range pm_src_key; // @0x14 - br_colour_range pm_dst_key; // @0x1c - br_uint_32 pm_key; // @0x24 - br_int_16 pm_row_bytes; // @0x28 - br_int_16 pm_mip_offset; // @0x2a - br_uint_8 pm_type; // @0x2c - br_uint_8 pm_flags; // @0x2d - br_uint_16 pm_copy_function; // @0x2e - br_uint_16 pm_base_x; // @0x30 - br_uint_16 pm_base_y; // @0x32 - br_uint_16 pm_width; // @0x34 - br_uint_16 pm_height; // @0x36 - br_int_16 pm_origin_x; // @0x38 - br_int_16 pm_origin_y; // @0x3a - void* pm_user; // @0x3c - void* pm_stored; // @0x40 + char* pm_identifier; // @0x4 + void* pm_pixels; // @0x8 + br_uint_32 pm_pixels_qualifier; // @0xc + br_pixelmap* pm_map; // @0x10 + br_colour_range pm_src_key; // @0x14 + br_colour_range pm_dst_key; // @0x1c + br_uint_32 pm_key; // @0x24 + br_int_16 pm_row_bytes; // @0x28 + br_int_16 pm_mip_offset; // @0x2a + br_uint_8 pm_type; // @0x2c + br_uint_8 pm_flags; // @0x2d + br_uint_16 pm_copy_function; // @0x2e + br_uint_16 pm_base_x; // @0x30 + br_uint_16 pm_base_y; // @0x32 + br_uint_16 pm_width; // @0x34 + br_uint_16 pm_height; // @0x36 + br_int_16 pm_origin_x; // @0x38 + br_int_16 pm_origin_y; // @0x3a + void* pm_user; // @0x3c + void* pm_stored; // @0x40 } br_device_pixelmap; typedef struct br_primitive_library br_primitive_library; @@ -1197,41 +1197,32 @@ typedef struct br_renderer { br_renderer_dispatch* dispatch; } br_renderer; -typedef struct br_material { // size: 0x9c - br_uint_32 _reserved; // @0x0 - char* identifier; // @0x4 - br_colour colour; // @0x8 - br_uint_8 opacity; // @0xc - br_ufraction ka; // @0x10 - br_ufraction kd; // @0x14 - br_ufraction ks; // @0x18 - br_scalar power; // @0x1c - br_uint_32 flags; // @0x20 - br_matrix23 map_transform; // @0x24 - br_uint_8 index_base; // @0x3c - br_uint_8 index_range; // @0x3d - br_pixelmap* colour_map; // @0x40 - br_pixelmap* screendoor; // @0x44 - br_pixelmap* index_shade; // @0x48 - br_pixelmap* index_blend; // @0x4c - br_pixelmap* index_fog; // @0x50 - br_token_value* extra_surf; // @0x54 - br_token_value* extra_prim; // @0x58 - br_scalar fog_min; // @0x5c - br_scalar fog_max; // @0x60 - br_colour fog_colour; // @0x64 - br_uint_32 flags_ext; // @0x68 - br_pixelmap* colour_map_1; // @0x6c - br_matrix23 map_transform_1; // @0x70 - br_int_8 mip_modifier; // @0x88 - br_uint_8 min_mip; // @0x89 - br_uint_8 max_mip; // @0x8a - br_uint_8 alpha_mode; // @0x8b - br_uint_8 zbuffer_mode; // @0x8c - br_uint_8 zbuffer_compare; // @0x8d - br_int_32 subdivide_tolerance; // @0x90 - void* user; // @0x94 - void* stored; // @0x98 +typedef struct br_material { // size: 0x74 + br_uint_32 _reserved; // @0x0 + char* identifier; // @0x4 + br_colour colour; // @0x8 + br_uint_8 opacity; // @0xc + br_ufraction ka; // @0x10 + br_ufraction kd; // @0x14 + br_ufraction ks; // @0x18 + br_scalar power; // @0x1c + br_uint_32 flags; // @0x20 + br_matrix23 map_transform; // @0x24 + br_uint_8 index_base; // @0x3c + br_uint_8 index_range; // @0x3d + br_pixelmap* colour_map; // @0x40 + br_pixelmap* screendoor; // @0x44 + br_pixelmap* index_shade; // @0x48 + br_pixelmap* index_blend; // @0x4c + br_pixelmap* index_fog; // @0x50 + br_token_value* extra_surf; // @0x54 + br_token_value* extra_prim; // @0x58 + br_scalar fog_min; // @0x5c + br_scalar fog_max; // @0x60 + br_colour fog_colour; // @0x64 + br_int_32 subdivide_tolerance; // @0x68 + void* user; // @0x6c + void* stored; // @0x70 } br_material; typedef struct br_vertex { @@ -1370,41 +1361,39 @@ typedef struct br_tri_strip { br_strip_face_data* face_data; } br_tri_strip; -typedef struct br_actor { // size: 0x64 - br_actor* next; // @0x0 - br_actor** prev; // @0x4 - br_actor* children; // @0x8 - br_actor* parent; // @0xc - br_uint_16 depth; // @0x10 - br_uint_8 type; // @0x12 - char* identifier; // @0x14 - br_model* model; // @0x18 - br_material* material; // @0x1c +typedef struct br_actor { // size: 0x64 + br_actor* next; // @0x0 + br_actor** prev; // @0x4 + br_actor* children; // @0x8 + br_actor* parent; // @0xc + br_uint_16 depth; // @0x10 + br_uint_8 type; // @0x12 + char* identifier; // @0x14 + br_model* model; // @0x18 + br_material* material; // @0x1c br_uint_8 render_style; // @0x20 - void* render_data; // @0x24 - br_transform t; // @0x28 - void* type_data; // @0x5c - void* user; // @0x60 + void* render_data; // @0x24 + br_transform t; // @0x28 + void* type_data; // @0x5c + void* user; // @0x60 } br_actor; -typedef struct br_model { // size: 0x5c - br_uint_32 _reserved; // @0x0 - char* identifier; // @0x4 - br_vertex* vertices; // @0x8 - br_face* faces; // @0xc - br_uint_16 nvertices; // @0x10 - br_uint_16 nfaces; // @0x12 - br_vector3 pivot; // @0x14 - br_uint_16 flags; // @0x20 +typedef struct br_model { // size: 0x54 + br_uint_32 _reserved; // @0x0 + char* identifier; // @0x4 + br_vertex* vertices; // @0x8 + br_face* faces; // @0xc + br_uint_16 nvertices; // @0x10 + br_uint_16 nfaces; // @0x12 + br_vector3 pivot; // @0x14 + br_uint_16 flags; // @0x20 br_model_custom_cbfn* custom; // @0x24 - void* user; // @0x28 - br_angle crease_angle; // @0x2c - br_scalar radius; // @0x30 - br_bounds bounds; // @0x34 - void* prepared; // @0x4c - void* stored; // @0x50 - br_uint_16 nprimitive_lists; // @0x54 - br_primitive_list* primitive_list; // @0x58 + void* user; // @0x28 + br_angle crease_angle; // @0x2c + br_scalar radius; // @0x30 + br_bounds bounds; // @0x34 + void* prepared; // @0x4c + void* stored; // @0x50 } br_model; typedef struct br_camera { @@ -1499,13 +1488,13 @@ typedef struct br_simple_list { } br_simple_list; typedef struct br_registry_entry { // size: 12 - br_node node; // @0 - char** item; // @8 + br_node node; // @0 + char** item; // @8 } br_registry_entry; -typedef struct br_registery { // size: 20 - br_list list; // @0 - int count; // @12 +typedef struct br_registery { // size: 20 + br_list list; // @0 + int count; // @12 br_find_failed_cbfn* find_failed_hook; // @16 } br_registry; @@ -1573,91 +1562,91 @@ typedef struct br_open_device { br_image* image; } br_open_device; -typedef struct br_framework_state { // size: 1136 - br_boolean active; // @0 - br_registry reg_resource_classes; // @4 +typedef struct br_framework_state { // size: 1136 + br_boolean active; // @0 + br_registry reg_resource_classes; // @4 br_resource_class* resource_class_index[256]; // @24 - br_list tokens; // @1048 - br_token next_free_token; // @1060 - br_filesystem* fsys; // @1064 - br_allocator* mem; // @1068 - br_diaghandler* diag; // @1072 - int open_mode; // @1076 - void* res; // @1080 - void* scratch_ptr; // @1084 - br_size_t scratch_size; // @1088 - br_size_t scratch_last; // @1092 - int scratch_inuse; // @1096 - br_error last_error_type; // @1100 - void** last_error_value; // @1104 - br_list images; // @1108 - br_open_device* dev_slots; // @1120 - br_int_32 ndev_slots; // @1124 - br_associative_array* sys_config; // @1128 - br_boolean bAlreadyLoadedDrivers; // @1132 + br_list tokens; // @1048 + br_token next_free_token; // @1060 + br_filesystem* fsys; // @1064 + br_allocator* mem; // @1068 + br_diaghandler* diag; // @1072 + int open_mode; // @1076 + void* res; // @1080 + void* scratch_ptr; // @1084 + br_size_t scratch_size; // @1088 + br_size_t scratch_last; // @1092 + int scratch_inuse; // @1096 + br_error last_error_type; // @1100 + void** last_error_value; // @1104 + br_list images; // @1108 + br_open_device* dev_slots; // @1120 + br_int_32 ndev_slots; // @1124 + br_associative_array* sys_config; // @1128 + br_boolean bAlreadyLoadedDrivers; // @1132 } br_framework_state; // br_framework_state defined by "C:\DETHRACE\source\common\finteray.c" module -typedef struct br_framework_state2 { // size: 0x14d4 - br_surface_fn* surface_fn; // @0x0 - br_surface_fn* surface_fn_after_map; // @0x4 - br_surface_fn* surface_fn_after_copy; // @0x8 - br_face_surface_fn* face_surface_fn; // @0xc - br_matrix23 map_transform; // @0x10 - br_scalar index_base; // @0x28 - br_scalar index_range; // @0x2c - br_matrix4 model_to_screen; // @0x30 - br_matrix4 view_to_screen; // @0x70 - br_matrix34 model_to_view; // @0xb0 - br_matrix34 view_to_model; // @0xe0 - br_matrix34 model_to_environment; // @0x110 - struct { // size: 0x34 - br_matrix34 m; // @0x0 - br_actor* a; // @0x30 - } camera_path[16]; // @0x140 - int vtos_type; // @0x480 - br_vector3 eye_m; // @0x484 - br_vector3 eye_m_normalised; // @0x490 - br_material* material; // @0x49c - br_active_light active_lights_model[16]; // @0x4a0 - br_active_light active_lights_view[16]; // @0x9e0 - br_uint_16 nactive_lights_model; // @0xf20 - br_uint_16 nactive_lights_view; // @0xf22 - int light_is_1md; // @0xf24 - br_vector3 eye_l; // @0xf28 - br_active_clip_plane active_clip_planes[6]; // @0xf34 - br_uint_16 nactive_clip_planes; // @0xf94 - br_actor* enabled_lights[16]; // @0xf98 - br_actor* enabled_clip_planes[6]; // @0xfd8 - br_actor* enabled_environment; // @0xff0 - br_pixelmap* output; // @0xff4 - br_scalar vp_width; // @0xff8 - br_scalar vp_height; // @0xffc - br_scalar vp_ox; // @0x1000 - br_scalar vp_oy; // @0x1004 - int rendering; // @0x1008 - br_registry reg_models; // @0x100c - br_registry reg_materials; // @0x1020 - br_registry reg_textures; // @0x1034 - br_registry reg_tables; // @0x1048 - br_registry reg_resource_classes; // @0x105c +typedef struct br_framework_state2 { // size: 0x14d4 + br_surface_fn* surface_fn; // @0x0 + br_surface_fn* surface_fn_after_map; // @0x4 + br_surface_fn* surface_fn_after_copy; // @0x8 + br_face_surface_fn* face_surface_fn; // @0xc + br_matrix23 map_transform; // @0x10 + br_scalar index_base; // @0x28 + br_scalar index_range; // @0x2c + br_matrix4 model_to_screen; // @0x30 + br_matrix4 view_to_screen; // @0x70 + br_matrix34 model_to_view; // @0xb0 + br_matrix34 view_to_model; // @0xe0 + br_matrix34 model_to_environment; // @0x110 + struct { // size: 0x34 + br_matrix34 m; // @0x0 + br_actor* a; // @0x30 + } camera_path[16]; // @0x140 + int vtos_type; // @0x480 + br_vector3 eye_m; // @0x484 + br_vector3 eye_m_normalised; // @0x490 + br_material* material; // @0x49c + br_active_light active_lights_model[16]; // @0x4a0 + br_active_light active_lights_view[16]; // @0x9e0 + br_uint_16 nactive_lights_model; // @0xf20 + br_uint_16 nactive_lights_view; // @0xf22 + int light_is_1md; // @0xf24 + br_vector3 eye_l; // @0xf28 + br_active_clip_plane active_clip_planes[6]; // @0xf34 + br_uint_16 nactive_clip_planes; // @0xf94 + br_actor* enabled_lights[16]; // @0xf98 + br_actor* enabled_clip_planes[6]; // @0xfd8 + br_actor* enabled_environment; // @0xff0 + br_pixelmap* output; // @0xff4 + br_scalar vp_width; // @0xff8 + br_scalar vp_height; // @0xffc + br_scalar vp_ox; // @0x1000 + br_scalar vp_oy; // @0x1004 + int rendering; // @0x1008 + br_registry reg_models; // @0x100c + br_registry reg_materials; // @0x1020 + br_registry reg_textures; // @0x1034 + br_registry reg_tables; // @0x1048 + br_registry reg_resource_classes; // @0x105c br_resource_class* resource_class_index[256]; // @0x1070 - br_model_update_cbfn* model_update; // @0x1470 - br_material_update_cbfn* material_update; // @0x1474 - br_table_update_cbfn* table_update; // @0x1478 - br_map_update_cbfn* map_update; // @0x147c - br_filesystem* fsys; // @0x1480 - br_allocator* mem; // @0x1484 - br_errorhandler* err; // @0x1488 - int open_mode; // @0x148c - void* res; // @0x1490 - br_model* default_model; // @0x1494 - br_material* default_material; // @0x1498 - fw_fn_table fn_table; // @0x149c - void* scratch_ptr; // @0x14c4 - br_size_t scratch_size; // @0x14c8 - br_size_t scratch_last; // @0x14cc - int scratch_inuse; // @0x14d0 + br_model_update_cbfn* model_update; // @0x1470 + br_material_update_cbfn* material_update; // @0x1474 + br_table_update_cbfn* table_update; // @0x1478 + br_map_update_cbfn* map_update; // @0x147c + br_filesystem* fsys; // @0x1480 + br_allocator* mem; // @0x1484 + br_errorhandler* err; // @0x1488 + int open_mode; // @0x148c + void* res; // @0x1490 + br_model* default_model; // @0x1494 + br_material* default_material; // @0x1498 + fw_fn_table fn_table; // @0x149c + void* scratch_ptr; // @0x14c4 + br_size_t scratch_size; // @0x14c8 + br_size_t scratch_last; // @0x14cc + int scratch_inuse; // @0x14d0 } br_framework_state2; typedef br_error br_exception; @@ -1807,63 +1796,63 @@ typedef struct br_buffer_stored { br_buffer_stored_dispatch* dispatch; } br_buffer_stored; -typedef struct br_device_pixelmap_dispatch { // size: 0xe0 - void (*__reserved0)(br_object*); // @0x0 - void (*__reserved1)(br_object*); // @0x4 - void (*__reserved2)(br_object*); // @0x8 - void (*__reserved3)(br_object*); // @0xc - void (*_free)(br_object*); // @0x10 - char* (*_identifier)(br_object*); // @0x14 - br_token (*_type)(br_object*); // @0x18 - br_boolean (*_isType)(br_object*, br_token); // @0x1c - br_device* (*_device)(br_object*); // @0x20 - br_int_32 (*_space)(br_object*); // @0x24 - br_tv_template* (*_templateQuery)(br_object*); // @0x28 - br_error (*_query)(br_object*, br_uint_32*, br_token); // @0x2c - br_error (*_queryBuffer)(br_object*, br_uint_32*, void*, br_size_t, br_token); // @0x30 - br_error (*_queryMany)(br_object*, br_token_value*, void*, br_size_t, br_int_32*); // @0x34 - br_error (*_queryManySize)(br_object*, br_size_t*, br_token_value*); // @0x38 - br_error (*_queryAll)(br_object*, br_token_value*, br_size_t); // @0x3c - br_error (*_queryAllSize)(br_object*, br_size_t*); // @0x40 - br_error (*_validSource)(br_device_pixelmap*, br_boolean*, br_object*); // @0x44 - br_error (*_resize)(br_device_pixelmap*, br_int_32, br_int_32); // @0x48 - br_error (*_match)(br_device_pixelmap*, br_device_pixelmap**, br_token_value*); // @0x4c - br_error (*_allocateSub)(br_device_pixelmap*, br_device_pixelmap**, br_rectangle*); // @0x50 - br_error (*_copy)(br_device_pixelmap*, br_device_pixelmap*); // @0x54 - br_error (*_copyTo)(br_device_pixelmap*, br_device_pixelmap*); // @0x58 - br_error (*_copyFrom)(br_device_pixelmap*, br_device_pixelmap*); // @0x5c - br_error (*_fill)(br_device_pixelmap*, br_uint_32); // @0x60 - br_error (*_doubleBuffer)(br_device_pixelmap*, br_device_pixelmap*); // @0x64 - br_error (*_copyDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x68 - br_error (*_copyToDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x6c - br_error (*_copyFromDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x70 - br_error (*_fillDirty)(br_device_pixelmap*, br_uint_32, br_rectangle*, br_int_32); // @0x74 - br_error (*_doubleBufferDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x78 - br_error (*_rectangle)(br_device_pixelmap*, br_rectangle*, br_uint_32); // @0x7c - br_error (*_rectangle2)(br_device_pixelmap*, br_rectangle*, br_uint_32, br_uint_32); // @0x80 - br_error (*_rectangleCopy)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x84 - br_error (*_rectangleCopyTo)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x88 - br_error (*_rectangleCopyFrom)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x8c - br_error (*_rectangleStretchCopy)(br_device_pixelmap*, br_rectangle*, br_device_pixelmap*, br_rectangle*); // @0x90 - br_error (*_rectangleStretchCopyTo)(br_device_pixelmap*, br_rectangle*, br_device_pixelmap*, br_rectangle*); // @0x94 +typedef struct br_device_pixelmap_dispatch { // size: 0xe0 + void (*__reserved0)(br_object*); // @0x0 + void (*__reserved1)(br_object*); // @0x4 + void (*__reserved2)(br_object*); // @0x8 + void (*__reserved3)(br_object*); // @0xc + void (*_free)(br_object*); // @0x10 + char* (*_identifier)(br_object*); // @0x14 + br_token (*_type)(br_object*); // @0x18 + br_boolean (*_isType)(br_object*, br_token); // @0x1c + br_device* (*_device)(br_object*); // @0x20 + br_int_32 (*_space)(br_object*); // @0x24 + br_tv_template* (*_templateQuery)(br_object*); // @0x28 + br_error (*_query)(br_object*, br_uint_32*, br_token); // @0x2c + br_error (*_queryBuffer)(br_object*, br_uint_32*, void*, br_size_t, br_token); // @0x30 + br_error (*_queryMany)(br_object*, br_token_value*, void*, br_size_t, br_int_32*); // @0x34 + br_error (*_queryManySize)(br_object*, br_size_t*, br_token_value*); // @0x38 + br_error (*_queryAll)(br_object*, br_token_value*, br_size_t); // @0x3c + br_error (*_queryAllSize)(br_object*, br_size_t*); // @0x40 + br_error (*_validSource)(br_device_pixelmap*, br_boolean*, br_object*); // @0x44 + br_error (*_resize)(br_device_pixelmap*, br_int_32, br_int_32); // @0x48 + br_error (*_match)(br_device_pixelmap*, br_device_pixelmap**, br_token_value*); // @0x4c + br_error (*_allocateSub)(br_device_pixelmap*, br_device_pixelmap**, br_rectangle*); // @0x50 + br_error (*_copy)(br_device_pixelmap*, br_device_pixelmap*); // @0x54 + br_error (*_copyTo)(br_device_pixelmap*, br_device_pixelmap*); // @0x58 + br_error (*_copyFrom)(br_device_pixelmap*, br_device_pixelmap*); // @0x5c + br_error (*_fill)(br_device_pixelmap*, br_uint_32); // @0x60 + br_error (*_doubleBuffer)(br_device_pixelmap*, br_device_pixelmap*); // @0x64 + br_error (*_copyDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x68 + br_error (*_copyToDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x6c + br_error (*_copyFromDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x70 + br_error (*_fillDirty)(br_device_pixelmap*, br_uint_32, br_rectangle*, br_int_32); // @0x74 + br_error (*_doubleBufferDirty)(br_device_pixelmap*, br_device_pixelmap*, br_rectangle*, br_int_32); // @0x78 + br_error (*_rectangle)(br_device_pixelmap*, br_rectangle*, br_uint_32); // @0x7c + br_error (*_rectangle2)(br_device_pixelmap*, br_rectangle*, br_uint_32, br_uint_32); // @0x80 + br_error (*_rectangleCopy)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x84 + br_error (*_rectangleCopyTo)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x88 + br_error (*_rectangleCopyFrom)(br_device_pixelmap*, br_point*, br_device_pixelmap*, br_rectangle*); // @0x8c + br_error (*_rectangleStretchCopy)(br_device_pixelmap*, br_rectangle*, br_device_pixelmap*, br_rectangle*); // @0x90 + br_error (*_rectangleStretchCopyTo)(br_device_pixelmap*, br_rectangle*, br_device_pixelmap*, br_rectangle*); // @0x94 br_error (*_rectangleStretchCopyFrom)(br_device_pixelmap*, br_rectangle*, br_device_pixelmap*, br_rectangle*); // @0x98 - br_error (*_rectangleFill)(br_device_pixelmap*, br_rectangle*, br_uint_32); // @0x9c - br_error (*_pixelSet)(br_device_pixelmap*, br_point*, br_uint_32); // @0xa0 - br_error (*_line)(br_device_pixelmap*, br_point*, br_point*, br_uint_32); // @0xa4 - br_error (*_copyBits)(br_device_pixelmap*, br_point*, br_uint_8*, br_uint_16, br_rectangle*, br_uint_32); // @0xa8 - br_error (*_text)(br_device_pixelmap*, br_point*, br_font*, char*, br_uint_32); // @0xac - br_error (*_textBounds)(br_device_pixelmap*, br_rectangle*, br_font*, char*); // @0xb0 - br_error (*_rowSize)(br_device_pixelmap*, br_size_t*); // @0xb4 - br_error (*_rowSet)(br_device_pixelmap*, void*, br_size_t, br_uint_32); // @0xb8 - br_error (*_rowQuery)(br_device_pixelmap*, void*, br_size_t, br_uint_32); // @0xbc - br_error (*_pixelQuery)(br_device_pixelmap*, br_uint_32*, br_point*); // @0xc0 - br_error (*_pixelAddressQuery)(br_device_pixelmap*, void**, br_uint_32*, br_point*); // @0xc4 - br_error (*_pixelAddressSet)(br_device_pixelmap*, void*, br_uint_32*); // @0xc8 - br_error (*_originSet)(br_device_pixelmap*, br_point*); // @0xcc - br_error (*_flush)(br_device_pixelmap*); // @0xd0 - br_error (*_synchronise)(br_device_pixelmap*, br_token, br_boolean); // @0xd4 - br_error (*_directLock)(br_device_pixelmap*, br_boolean); // @0xd8 - br_error (*_directUnlock)(br_device_pixelmap*); // @0xdc + br_error (*_rectangleFill)(br_device_pixelmap*, br_rectangle*, br_uint_32); // @0x9c + br_error (*_pixelSet)(br_device_pixelmap*, br_point*, br_uint_32); // @0xa0 + br_error (*_line)(br_device_pixelmap*, br_point*, br_point*, br_uint_32); // @0xa4 + br_error (*_copyBits)(br_device_pixelmap*, br_point*, br_uint_8*, br_uint_16, br_rectangle*, br_uint_32); // @0xa8 + br_error (*_text)(br_device_pixelmap*, br_point*, br_font*, char*, br_uint_32); // @0xac + br_error (*_textBounds)(br_device_pixelmap*, br_rectangle*, br_font*, char*); // @0xb0 + br_error (*_rowSize)(br_device_pixelmap*, br_size_t*); // @0xb4 + br_error (*_rowSet)(br_device_pixelmap*, void*, br_size_t, br_uint_32); // @0xb8 + br_error (*_rowQuery)(br_device_pixelmap*, void*, br_size_t, br_uint_32); // @0xbc + br_error (*_pixelQuery)(br_device_pixelmap*, br_uint_32*, br_point*); // @0xc0 + br_error (*_pixelAddressQuery)(br_device_pixelmap*, void**, br_uint_32*, br_point*); // @0xc4 + br_error (*_pixelAddressSet)(br_device_pixelmap*, void*, br_uint_32*); // @0xc8 + br_error (*_originSet)(br_device_pixelmap*, br_point*); // @0xcc + br_error (*_flush)(br_device_pixelmap*); // @0xd0 + br_error (*_synchronise)(br_device_pixelmap*, br_token, br_boolean); // @0xd4 + br_error (*_directLock)(br_device_pixelmap*, br_boolean); // @0xd8 + br_error (*_directUnlock)(br_device_pixelmap*); // @0xdc } br_device_pixelmap_dispatch; typedef struct br_buffer_stored_dispatch { @@ -1997,11 +1986,11 @@ typedef struct br_file_struct { } br_file_struct; typedef struct br_file_primitives br_file_primitives; -typedef struct br_datafile { // size: 0x10 - void* h; // @0x0 +typedef struct br_datafile { // size: 0x10 + void* h; // @0x0 br_file_primitives* prims; // @0x4 - br_token scalar_type; // @0x8 - void* res; // @0xc + br_token scalar_type; // @0x8 + void* res; // @0xc } br_datafile; typedef struct br_file_primitives { @@ -2128,52 +2117,52 @@ typedef struct br_v1db_enable { br_actor** enabled; } br_v1db_enable; -typedef struct br_v1db_state { // size: 0x504 - br_boolean active; // @0x0 - br_boolean zs_active; // @0x4 - br_boolean zb_active; // @0x8 - br_int_32 rendering; // @0xc - br_renderer* renderer; // @0x10 - br_renderer* query_renderer; // @0x14 - br_geometry* format_model; // @0x18 - br_geometry* format_buckets; // @0x1c +typedef struct br_v1db_state { // size: 0x504 + br_boolean active; // @0x0 + br_boolean zs_active; // @0x4 + br_boolean zb_active; // @0x8 + br_int_32 rendering; // @0xc + br_renderer* renderer; // @0x10 + br_renderer* query_renderer; // @0x14 + br_geometry* format_model; // @0x18 + br_geometry* format_buckets; // @0x1c br_geometry_lighting* format_lighting; // @0x20 - br_matrix4 model_to_screen; // @0x24 - br_matrix34 model_to_view; // @0x64 - br_boolean model_to_screen_valid; // @0x94 - br_uint_32 ttype; // @0x98 - br_actor* render_root; // @0x9c - struct { // size: 0x38 - br_matrix34 m; // @0x0 - br_actor* a; // @0x30 - br_uint_8 transform_type; // @0x34 - } camera_path[16]; // @0xa0 - br_v1db_enable enabled_lights; // @0x420 - br_v1db_enable enabled_clip_planes; // @0x434 + br_matrix4 model_to_screen; // @0x24 + br_matrix34 model_to_view; // @0x64 + br_boolean model_to_screen_valid; // @0x94 + br_uint_32 ttype; // @0x98 + br_actor* render_root; // @0x9c + struct { // size: 0x38 + br_matrix34 m; // @0x0 + br_actor* a; // @0x30 + br_uint_8 transform_type; // @0x34 + } camera_path[16]; // @0xa0 + br_v1db_enable enabled_lights; // @0x420 + br_v1db_enable enabled_clip_planes; // @0x434 br_v1db_enable enabled_horizon_planes; // @0x448 - br_int_32 max_light; // @0x45c - br_int_32 max_clip; // @0x460 - br_actor* enabled_environment; // @0x464 - br_registry reg_models; // @0x468 - br_registry reg_materials; // @0x47c - br_registry reg_textures; // @0x490 - br_registry reg_tables; // @0x4a4 - void* res; // @0x4b8 - br_model* default_model; // @0x4bc - br_material* default_material; // @0x4c0 - void* default_render_data; // @0x4c4 - br_order_table* default_order_table; // @0x4c8 - br_order_table* primary_order_table; // @0x4cc - br_order_table* order_table_list; // @0x4d0 - br_primitive_heap heap; // @0x4d4 - br_primitive_cbfn* primitive_call; // @0x4e0 - br_renderbounds_cbfn* bounds_call; // @0x4e4 - br_vector2 origin; // @0x4e8 - br_scalar vp_ox; // @0x4f0 - br_scalar vp_oy; // @0x4f4 - br_scalar vp_width; // @0x4f8 - br_scalar vp_height; // @0x4fc - br_pixelmap* colour_buffer; // @0x500 + br_int_32 max_light; // @0x45c + br_int_32 max_clip; // @0x460 + br_actor* enabled_environment; // @0x464 + br_registry reg_models; // @0x468 + br_registry reg_materials; // @0x47c + br_registry reg_textures; // @0x490 + br_registry reg_tables; // @0x4a4 + void* res; // @0x4b8 + br_model* default_model; // @0x4bc + br_material* default_material; // @0x4c0 + void* default_render_data; // @0x4c4 + br_order_table* default_order_table; // @0x4c8 + br_order_table* primary_order_table; // @0x4cc + br_order_table* order_table_list; // @0x4d0 + br_primitive_heap heap; // @0x4d4 + br_primitive_cbfn* primitive_call; // @0x4e0 + br_renderbounds_cbfn* bounds_call; // @0x4e4 + br_vector2 origin; // @0x4e8 + br_scalar vp_ox; // @0x4f0 + br_scalar vp_oy; // @0x4f4 + br_scalar vp_width; // @0x4f8 + br_scalar vp_height; // @0x4fc + br_pixelmap* colour_buffer; // @0x500 } br_v1db_state; typedef struct br_renderer_facility_dispatch { @@ -2426,11 +2415,11 @@ typedef struct br_tv_custom { } br_tv_custom; typedef struct br_token_entry { // size: 24 - br_node node; // @0 - char* identifier; // @8 - br_int_32 type; // @12 - br_token token; // @16 - br_int_32 base_length; // @20 + br_node node; // @0 + char* identifier; // @8 + br_int_32 type; // @12 + br_token token; // @16 + br_int_32 base_length; // @20 } br_token_entry; typedef struct br_exception_handler br_exception_handler; @@ -2652,14 +2641,14 @@ typedef struct section_header { #pragma pack(push, 1) typedef struct resource_header { // size: 24 - br_simple_node node; // @0 - br_simple_list children; // @8 - br_uint_8 size_l; // @12 - br_uint_8 size_m; // @13 - br_uint_8 size_h; // @14 - br_uint_8 class; // @15 - void* magic_ptr; // @16 - br_uint_32 magic_num; // @20 + br_simple_node node; // @0 + br_simple_list children; // @8 + br_uint_8 size_l; // @12 + br_uint_8 size_m; // @13 + br_uint_8 size_h; // @14 + br_uint_8 class; // @15 + void* magic_ptr; // @16 + br_uint_32 magic_num; // @20 } resource_header; #pragma pack(pop) @@ -2892,42 +2881,42 @@ enum { */ enum { /* - * Each pixel is an index into a colour map - */ + * Each pixel is an index into a colour map + */ BR_PMT_INDEX_1, BR_PMT_INDEX_2, BR_PMT_INDEX_4, BR_PMT_INDEX_8, /* - * True colour RGB - */ - BR_PMT_RGB_555, /* 16 bits per pixel */ - BR_PMT_RGB_565, /* 16 bits per pixel */ - BR_PMT_RGB_888, /* 24 bits per pixel */ - BR_PMT_RGBX_888, /* 32 bits per pixel */ + * True colour RGB + */ + BR_PMT_RGB_555, /* 16 bits per pixel */ + BR_PMT_RGB_565, /* 16 bits per pixel */ + BR_PMT_RGB_888, /* 24 bits per pixel */ + BR_PMT_RGBX_888, /* 32 bits per pixel */ BR_PMT_RGBA_8888, /* 32 bits per pixel */ /* - * YUV - */ + * YUV + */ BR_PMT_YUYV_8888, /* YU YV YU YV ... */ BR_PMT_YUV_888, /* - * Depth - */ + * Depth + */ BR_PMT_DEPTH_16, BR_PMT_DEPTH_32, /* - * Opacity - */ + * Opacity + */ BR_PMT_ALPHA_8, /* - * Opacity + Index - */ + * Opacity + Index + */ BR_PMT_INDEXA_88 }; @@ -2996,17 +2985,17 @@ enum { * Bits for br_model->flags */ enum { - BR_MODF_DONT_WELD = 0x0001, /* Vertices with same x,y,z cannot be merged */ - BR_MODF_KEEP_ORIGINAL = 0x0002, /* Don't release model->faces/vertices during ModelUpdate() */ - BR_MODF_GENERATE_TAGS = 0x0004, /* Allocate and fill in the face and vertex tag structures */ - BR_MODF_QUICK_UPDATE = 0x0010, /* ModelUpdate is fast - but may produce slower models */ - BR_MODF_CUSTOM = 0x0020, /* Invoke custom callback for this model */ - BR_MODF_PREPREPARED = 0x0040, /* Model structure is pre-prepared - update performs no work */ - BR_MODF_UPDATEABLE = 0x0080, /* Added by Jeff from Errols code */ - BR_MODF_CREASE = 0x0100, /* Create creases in smoothing along edges if face<->face angle is g.t model->crease */ + BR_MODF_DONT_WELD = 0x0001, /* Vertices with same x,y,z cannot be merged */ + BR_MODF_KEEP_ORIGINAL = 0x0002, /* Don't release model->faces/vertices during ModelUpdate() */ + BR_MODF_GENERATE_TAGS = 0x0004, /* Allocate and fill in the face and vertex tag structures */ + BR_MODF_QUICK_UPDATE = 0x0010, /* ModelUpdate is fast - but may produce slower models */ + BR_MODF_CUSTOM = 0x0020, /* Invoke custom callback for this model */ + BR_MODF_PREPREPARED = 0x0040, /* Model structure is pre-prepared - update performs no work */ + BR_MODF_UPDATEABLE = 0x0080, /* Added by Jeff from Errols code */ + BR_MODF_CREASE = 0x0100, /* Create creases in smoothing along edges if face<->face angle is g.t model->crease */ BR_MODF_CUSTOM_NORMALS = 0x0200, /* Uses vertex normals from br_vertex structure */ - BR_MODF_CUSTOM_BOUNDS = 0x0400, /* Bounding box is already set up */ - //BR_MODF_FACES_ONLY = 0x0800, /* Model will only be used to render faces (not edges or points) */ + BR_MODF_CUSTOM_BOUNDS = 0x0400, /* Bounding box is already set up */ + // BR_MODF_FACES_ONLY = 0x0800, /* Model will only be used to render faces (not edges or points) */ MODF_USES_DEFAULT = 0x8000 }; diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 395e9f71..5a3c1099 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -2,6 +2,7 @@ #include "car.h" #include "brender/brender.h" +#include "brucetrk.h" #include "car.h" #include "constants.h" #include "controls.h" @@ -65,7 +66,7 @@ int gMetal_scrape_sound_id__car[3] = { 5011, 5012, }; -int gCar_car_collisions; +int gCar_car_collisions = 1; int gFreeze_mechanics; tU32 gLast_cunning_stunt; tU32 gWild_start; @@ -546,7 +547,32 @@ void SetInitialPositions(tRace_info* pThe_race) { void InitialiseNonCar(tNon_car_spec* non_car) { tCollision_info* c; LOG_TRACE("(%p)", non_car); - NOT_IMPLEMENTED(); + + c = &non_car->collision_info; + BrMatrix34Copy(&c->oldmat, &c->car_master_actor->t.t.mat); + non_car->collision_info.box_face_ref = gFace_num__car - 2; + non_car->collision_info.doing_nothing_flag = 1; + non_car->collision_info.disabled = 0; + BrVector3SetFloat(&c->v, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&c->omega, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&c->oldomega, 0.0f, 0.0f, 0.0f); + non_car->collision_info.box_face_ref = gFace_num__car - 2; + c->collision_flag = 0; + c->who_last_hit_me = NULL; + if (c->car_master_actor->identifier[3] == '!') { + c->M = non_car->free_mass; + c->min_torque_squared = 0.0f; + c->cmpos = non_car->free_cmpos; + } else { + c->M = non_car->attached_mass; + c->cmpos = non_car->attached_cmpos; + c->min_torque_squared = non_car->min_torque_squared; + } + BrVector3Scale(&c->I, &non_car->I_over_M, c->M); + c->message.type = 0; + c->message.time = 0; + c->dt = -1.0f; + c->last_car_car_collision = 1; } // IDA: void __usercall GetFacesInBox(tCollision_info *c@) @@ -1085,7 +1111,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) { gDoing_physics = 1; PrepareCars(last_frame_time); - gDt = harness_game_config.physics_step_time / 1000.0; // 0.039999999; + gDt = harness_game_config.physics_step_time / 1000.0; // 0.04; gMechanics_time_sync = pTime_difference - (gLast_mechanics_time - last_frame_time); while (gLast_mechanics_time < frame_end_time && step_number < 5) { step_number++; @@ -1129,12 +1155,12 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) { } } } - for (i = 0; i < gNum_active_non_cars; ++i) { + for (i = 0; i < gNum_active_non_cars; i++) { non_car = gActive_non_car_list[i]; if (!non_car->collision_info.doing_nothing_flag) { non_car->collision_info.dt = -1.0; if (non_car->collision_info.message.type == 16 && non_car->collision_info.message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= non_car->collision_info.message.time) { - non_car->collision_info.dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0; + non_car->collision_info.dt = (gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0f; GetNetPos((tCar_spec*)non_car); } if (non_car->collision_info.box_face_ref != gFace_num__car @@ -1142,7 +1168,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) { || non_car->collision_info.box_face_start <= gFace_count)) { GetFacesInBox(&non_car->collision_info); } - if (non_car->collision_info.dt != 0.0) { + if (non_car->collision_info.dt != 0.0f) { MoveAndCollideNonCar(non_car, gDt); } } @@ -1181,7 +1207,25 @@ void ResetCarSpecialVolume(tCollision_info* pCar) { tSpecial_volume* new_special_volume; br_material* material; LOG_TRACE("(%p)", pCar); - NOT_IMPLEMENTED(); + + new_special_volume = NULL; + cast_v.v[0] = 0.0f; + cast_v.v[1] = 200.0f; + cast_v.v[2] = 0.0f; + DisablePlingMaterials(); + FindFace(&pCar->car_master_actor->t.t.translate.t, &cast_v, &norm, &t, &material); + EnablePlingMaterials(); + if (t < 100.0f && material != NULL) { + mat_id = material->identifier; + if (mat_id) { + id_len = strlen(mat_id); + if (id_len > 0 && (*mat_id == '!' || *mat_id == '#')) { + new_special_volume = GetDefaultSpecialVolumeForWater(); + } + } + } + pCar->auto_special_volume = new_special_volume; + pCar->water_depth_factor = 1.0f; } // IDA: void __usercall TestAutoSpecialVolume(tCollision_info *pCar@) @@ -1245,7 +1289,21 @@ void MoveAndCollideCar(tCar_spec* car, br_scalar dt) { void MoveAndCollideNonCar(tNon_car_spec* non_car, br_scalar dt) { tCollision_info* car_info; LOG_TRACE("(%p, %f)", non_car, dt); - NOT_IMPLEMENTED(); + + car_info = &non_car->collision_info; + if (car_info->water_d != 10000.0f) { + TestAutoSpecialVolume(&non_car->collision_info); + } + MungeSpecialVolume(&non_car->collision_info); + if (car_info->dt >= 0.0) { + dt = car_info->dt; + } + NonCarCalcForce(non_car, dt); + RotateCar(&non_car->collision_info, dt); + TranslateCar(&non_car->collision_info, dt); + CollideCarWithWall(&non_car->collision_info, dt); + BrMatrix34ApplyP(&car_info->pos, &car_info->cmpos, &car_info->car_master_actor->t.t.mat); + BrVector3InvScale(&car_info->pos, &car_info->pos, WORLD_SCALE); } // IDA: int __usercall CollideCarWithWall@(tCollision_info *car@, br_scalar dt) @@ -1562,7 +1620,47 @@ void NonCarCalcForce(tNon_car_spec* nc, br_scalar dt) { br_vector3 tv; br_vector3 v; LOG_TRACE("(%p, %f)", nc, dt); - NOT_IMPLEMENTED(); + + c = &nc->collision_info; + vol = nc->collision_info.last_special_volume; + if (nc->collision_info.car_master_actor->identifier[3] != '!') { + if (c->car_master_actor->t.t.mat.m[1][1] < nc->snap_off_cosine || c->min_torque_squared == 0.0f) { + c->car_master_actor->identifier[3] = '!'; + c->M = nc->free_mass; + c->min_torque_squared = 0.0f; + BrVector3Sub(&v, &nc->free_cmpos, &c->cmpos); + BrVector3Cross(&tv, &c->omega, &v); + BrMatrix34ApplyV(&v, &tv, &c->car_master_actor->t.t.mat); + BrVector3Accumulate(&c->v, &v); + c->cmpos = nc->free_cmpos; + } else { + BrVector3SetFloat(&c->v, 0.0f, 0.0f, 0.0f); + ts = BrVector3LengthSquared(&c->omega); + BrVector3SetFloat(&c->omega, 0.0f, 0.0f, 0.0f); + c->doing_nothing_flag = 1; + } + } + if (c->car_master_actor->identifier[3] == '!') { + if (vol != NULL) { + c->v.v[1] = c->v.v[1] - dt * 10.0f * vol->gravity_multiplier; + } else { + c->v.v[1] = c->v.v[1] - dt * 10.0f; + } + ts = BrVector3Length(&c->v); + if (vol != NULL) { + ts = vol->viscosity_multiplier * ts; + } + ts = -(dt * 0.0005f * ts) / c->M; + BrVector3Scale(&v, &c->v, ts); + BrVector3Accumulate(&c->v, &v); + ts = BrVector3Length(&c->omega); + if (vol != NULL) { + ts = vol->viscosity_multiplier * ts; + } + ts = -(dt * 0.0005 * ts); + BrVector3Scale(&v, &c->omega, ts); + ApplyTorque(CAR(c), &v); + } } // IDA: void __usercall AddDrag(tCar_spec *c@, br_scalar dt) @@ -2660,28 +2758,25 @@ int CollCheck(tCollision_info* c, br_scalar dt) { BrVector3Scale(&normal_force, &normal_force, gDefensive_powerup_factor[car_spec->power_up_levels[0]]); } if (c->driver < eDriver_net_human) { - BrVector3Scale(&normal_force, &normal_force, 0.0099999998); + BrVector3Scale(&normal_force, &normal_force, 0.01f); } else { - BrVector3Scale(&normal_force, &normal_force, 0.75); + BrVector3Scale(&normal_force, &normal_force, 0.75f); } - v_diff = (car_spec->pre_car_col_velocity.v[1] - c->v.v[1]) * gDefensive_powerup_factor[car_spec->power_up_levels[0]]; - if (car_spec->invulnerable - || (c->driver < eDriver_net_human && (c->driver != eDriver_oppo || PointOutOfSight(&c->pos, 150.0))) - || (v_diff >= -20.0) - || car_spec->number_of_wheels_on_ground >= 3) { - CrushAndDamageCar(car_spec, &dir, &normal_force, NULL); - } else { - if (c->driver == eDriver_oppo && c->index == 4 && v_diff < -40.0) { - KnackerThisCar(car_spec); - StealCar(car_spec); - v_diff = v_diff * 5.0; - } - for (i = 0; i < ((tCar_spec*)c)->car_actor_count; i++) { - ts2 = (v_diff + 20.0) * -0.01; - TotallySpamTheModel(car_spec, i, car_spec->car_model_actors[i].actor, &car_spec->car_model_actors[i].crush_data, ts2); - } - for (i = 0; i < 12; i++) { - DamageUnit(car_spec, i, IRandomPosNeg(5) + (v_diff + 20.0) * -1.5); + if ((c->driver >= eDriver_net_human || (c->driver == eDriver_oppo && !PointOutOfSight(&c->pos, 150.0))) && !CAR(c)->invulnerable) { + v_diff = (CAR(c)->pre_car_col_velocity.v[1] - c->v.v[1]) * gDefensive_powerup_factor[CAR(c)->power_up_levels[0]]; + if (v_diff < -20.0f && CAR(c)->number_of_wheels_on_ground < 3) { + if (c->driver == eDriver_oppo && c->index == 4 && v_diff < -40.0) { + KnackerThisCar(CAR(c)); + StealCar(CAR(c)); + v_diff = v_diff * 5.0; + } + for (i = 0; i < CAR(c)->car_actor_count; i++) { + ts2 = (v_diff + 20.0) * -0.01; + TotallySpamTheModel(CAR(c), i, CAR(c)->car_model_actors[i].actor, &CAR(c)->car_model_actors[i].crush_data, ts2); + } + for (i = 0; i < COUNT_OF(CAR(c)->damage_units); i++) { + DamageUnit(CAR(c), i, IRandomPosNeg(5) + (v_diff + 20.0) * -1.5); + } } } if (!noise_defeat) { @@ -2785,7 +2880,54 @@ void AddFrictionCarToCar(tCollision_info* car1, tCollision_info* car2, br_vector br_scalar total_friction; int i; LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %f, %p)", car1, car2, vel1, vel2, normal_force1, pos1, pos2, total_force, max_friction); - NOT_IMPLEMENTED(); + + BrMatrix34TApplyV(&tv, vel2, &car2->oldmat); + BrMatrix34ApplyV(&vel2_in_frame_1, &tv, &car1->oldmat); + BrVector3Sub(&v_diff1, &vel2_in_frame_1, vel1); + ts = BrVector3LengthSquared(normal_force1); + ts2 = BrVector3Dot(normal_force1, &v_diff1) / ts; + BrVector3Scale(&tv, normal_force1, ts2); + BrVector3Sub(&v_diff1, &v_diff1, &tv); + v_diff = BrVector3Length(&v_diff1); + if (v_diff < 0.01f) { + max_friction->v[0] = 0.0f; + max_friction->v[1] = 0.0f; + max_friction->v[2] = 0.0f; + } else { + BrVector3InvScale(&v_diff1, &v_diff1, v_diff); + BrMatrix34ApplyV(&tv, &v_diff1, &car1->oldmat); + BrMatrix34TApplyV(&v_diff2, &tv, &car2->oldmat); + BrVector3Negate(&v_diff2, &v_diff2); + BrVector3Cross(&tau1, pos1, &v_diff1); + BrVector3Cross(&tau2, pos2, &v_diff2); + for (i = 0; i < 3; ++i) { + tau1.v[i] /= car1->I.v[i]; + tau2.v[i] /= car2->I.v[i]; + } + BrVector3Cross(&tv, &tau1, pos1); + BrVector3Cross(&tv2, &tau2, pos2); + ts = BrVector3Dot(&tv, &v_diff1) + BrVector3Dot(&tv2, &v_diff2) + 1.0 / car2->M + 1.0 / car1->M; + if (ts < 0.0001f) { + max_friction->v[0] = 0.0; + max_friction->v[1] = 0.0; + max_friction->v[2] = 0.0; + } else { + stopping_impulse = v_diff / ts; + total_friction = total_force * 0.35f; + if (stopping_impulse < total_friction) { + total_friction = stopping_impulse; + } + if (!car1->infinite_mass) { + BrVector3Scale(&tau1, &tau1, total_friction); + BrVector3Accumulate(&car1->omega, &tau1); + } + if (!car2->infinite_mass) { + BrVector3Scale(&tau2, &tau2, total_friction); + BrVector3Accumulate(&car2->omega, &tau2); + } + BrVector3Scale(max_friction, &v_diff1, total_friction); + } + } } // IDA: void __cdecl ScrapeNoise(br_scalar vel, br_vector3 *position, int material) @@ -2918,83 +3060,84 @@ void CrushAndDamageCar(tCar_spec* c, br_vector3* pPosition, br_vector3* pForce_c car2->who_last_hit_me = c; c->who_last_hit_me = car2; } - if (c->driver > eDriver_non_car) { - fudge_multiplier = gNet_mode == eNet_mode_none || gNet_softness[gCurrent_net_game->type] == 1.0f ? 1.0f : gNet_softness[gCurrent_net_game->type]; - BrVector3Sub(&car_to_cam, &c->pos, (br_vector3*)gCamera_to_world.m[3]); - ts = BrVector3LengthSquared(&car_to_cam); - if (c->driver != eDriver_oppo || ts <= 200.0f) { - if (car2) { - if (car2->driver > eDriver_non_car) { - TwoCarsHitEachOther(c, car2); - } - if (c->driver >= eDriver_net_human) { - fudge_multiplier = gDefensive_powerup_factor[c->power_up_levels[0]] * 1.2f * fudge_multiplier; - } - if (car2->driver >= eDriver_net_human) { - if (gNet_mode - && (gCurrent_net_game->type == eNet_game_type_fight_to_death || gCurrent_net_game->type == eNet_game_type_car_crusher)) { - fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * gNet_offensive[gCurrent_net_game->type] * car2->damage_multiplier * fudge_multiplier; - } else { - fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * car2->damage_multiplier * fudge_multiplier; - } - } - if (c->driver == eDriver_oppo && car2->driver == eDriver_oppo) { - fudge_multiplier = fudge_multiplier * 0.2f; - } - if (car2->driver <= eDriver_non_car) { - car2 = NULL; + if (c->driver <= eDriver_non_car) { + return; + } + fudge_multiplier = gNet_mode == eNet_mode_none || gNet_softness[gCurrent_net_game->type] == 1.0f ? 1.0f : gNet_softness[gCurrent_net_game->type]; + BrVector3Sub(&car_to_cam, &c->pos, (br_vector3*)gCamera_to_world.m[3]); + ts = BrVector3LengthSquared(&car_to_cam); + if (c->driver != eDriver_oppo || ts <= 200.0f) { + if (car2) { + if (car2->driver > eDriver_non_car) { + TwoCarsHitEachOther(c, car2); + } + if (c->driver >= eDriver_net_human) { + fudge_multiplier = gDefensive_powerup_factor[c->power_up_levels[0]] * 1.2f * fudge_multiplier; + } + if (car2->driver >= eDriver_net_human) { + if (gNet_mode + && (gCurrent_net_game->type == eNet_game_type_fight_to_death || gCurrent_net_game->type == eNet_game_type_car_crusher)) { + fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * gNet_offensive[gCurrent_net_game->type] * car2->damage_multiplier * fudge_multiplier; } else { - fudge_multiplier = fudge_multiplier / ((car2->car_model_actors[car2->principal_car_actor].crush_data.softness_factor + 0.7f) / 0.7f); + fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * car2->damage_multiplier * fudge_multiplier; } } - BrVector3InvScale(&position, pPosition, WORLD_SCALE); - BrVector3Scale(&force, pForce_car_space, fudge_multiplier * 0.03f); - ts = BrVector3LengthSquared(&force); - if (c->driver <= eDriver_non_car || !c->invulnerable) { - c->damage_magnitude_accumulator = c->damage_magnitude_accumulator + ts; + if (c->driver == eDriver_oppo && car2->driver == eDriver_oppo) { + fudge_multiplier = fudge_multiplier * 0.2f; } - if (c->driver < eDriver_net_human) { - BrVector3Scale(&force_for_bodywork, &force, 1.5f); + if (car2->driver <= eDriver_non_car) { + car2 = NULL; } else { - if (c->collision_mass_multiplier != 1.0) { - BrVector3InvScale(&force, &force, c->collision_mass_multiplier); + fudge_multiplier = fudge_multiplier / ((car2->car_model_actors[car2->principal_car_actor].crush_data.softness_factor + 0.7f) / 0.7f); + } + } + BrVector3InvScale(&position, pPosition, WORLD_SCALE); + BrVector3Scale(&force, pForce_car_space, fudge_multiplier * 0.03f); + ts = BrVector3LengthSquared(&force); + if (c->driver <= eDriver_non_car || !c->invulnerable) { + c->damage_magnitude_accumulator = c->damage_magnitude_accumulator + ts; + } + if (c->driver < eDriver_net_human) { + BrVector3Scale(&force_for_bodywork, &force, 1.5f); + } else { + if (c->collision_mass_multiplier != 1.0) { + BrVector3InvScale(&force, &force, c->collision_mass_multiplier); + } + BrVector3Scale(&force_for_bodywork, &force, 0.5f); + if (c->driver == eDriver_local_human) { + DoPratcamHit(&force); + } + } + if (gNet_mode == eNet_mode_host && (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) && car2 + && c->driver >= eDriver_net_human && car2->driver >= eDriver_net_human) { + if (gNet_players[gIt_or_fox].car != c || car2->knackered) { + if (gNet_players[gIt_or_fox].car == car2 && !c->knackered) { + CarInContactWithItOrFox(NetPlayerFromCar(c)); } - BrVector3Scale(&force_for_bodywork, &force, 0.5f); - if (c->driver == eDriver_local_human) { - DoPratcamHit(&force); + } else { + CarInContactWithItOrFox(NetPlayerFromCar(car2)); + } + } + if (gNet_mode != eNet_mode_client || !car2) { + DamageSystems(c, &position, &force, car2 != NULL); + } + if (c->driver <= eDriver_non_car || !c->invulnerable) { + for (i = 0; i < c->car_actor_count; i++) { + if (c->car_model_actors[i].min_distance_squared != -1.0f || (pForce_car_space->v[1] >= 0.0f && pForce_car_space->v[2] >= 0.0f)) { + CrushModel(c, i, c->car_model_actors[i].actor, &position, &force_for_bodywork, &c->car_model_actors[i].crush_data); } } - if (gNet_mode == eNet_mode_host && (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) && car2 - && c->driver >= eDriver_net_human && car2->driver >= eDriver_net_human) { - if (gNet_players[gIt_or_fox].car != c || car2->knackered) { - if (gNet_players[gIt_or_fox].car == car2 && !c->knackered) { - CarInContactWithItOrFox(NetPlayerFromCar(c)); - } - } else { - CarInContactWithItOrFox(NetPlayerFromCar(car2)); - } - } - if (gNet_mode != eNet_mode_client || !car2) { - DamageSystems(c, &position, &force, car2 != NULL); - } - if (c->driver <= eDriver_non_car || !c->invulnerable) { - for (i = 0; i < c->car_actor_count; i++) { - if (c->car_model_actors[i].min_distance_squared != -1.0f || (pForce_car_space->v[1] >= 0.0f && pForce_car_space->v[2] >= 0.0f)) { - CrushModel(c, i, c->car_model_actors[i].actor, &position, &force_for_bodywork, &c->car_model_actors[i].crush_data); - } - } - } - if (car2 && car2->driver == eDriver_local_human && ts > 0.003f) { - PipeSingleCarIncident(ts, c, &position); - } - if (!car2 && c->driver == eDriver_local_human && ts > 0.003f) { - BrMatrix34Copy(&m, &c->car_master_actor->t.t.mat); - m.m[3][0] /= WORLD_SCALE; - m.m[3][1] /= WORLD_SCALE; - m.m[3][2] /= WORLD_SCALE; - BrMatrix34ApplyP(&pos_w, &position, &m); - PipeSingleWallIncident(ts, &pos_w); - } + } + if (car2 && car2->driver == eDriver_local_human && ts > 0.003f) { + PipeSingleCarIncident(ts, c, &position); + } + if (!car2 && c->driver == eDriver_local_human && ts > 0.003f) { + BrMatrix34Copy(&m, &c->car_master_actor->t.t.mat); + m.m[3][0] /= WORLD_SCALE; + m.m[3][1] /= WORLD_SCALE; + m.m[3][2] /= WORLD_SCALE; + BrMatrix34ApplyP(&pos_w, &position, &m); + PipeSingleWallIncident(ts, &pos_w); } } } @@ -3149,11 +3292,11 @@ void AddCollPoint(br_scalar dist, br_vector3* p, br_vector3* norm, br_vector3* r br_scalar SinglePointColl(br_scalar* f, br_matrix4* m, br_scalar* d) { LOG_TRACE("(%p, %p, %p)", f, m, d); - *f = *d / m->m[0][0]; - if (*f < 0.0) { - *f = 0.0; + f[0] = d[0] / m->m[0][0]; + if (f[0] < 0.0f) { + f[0] = 0.0; } - return fabs(m->m[0][0]); + return fabsf(m->m[0][0]); } // IDA: br_scalar __usercall TwoPointColl@(br_scalar *f@, br_matrix4 *m@, br_scalar *d@, br_vector3 *tau@, br_vector3 *n) @@ -3163,15 +3306,15 @@ br_scalar TwoPointColl(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* ta ts = m->m[1][1] * m->m[0][0] - m->m[0][1] * m->m[1][0]; if (fabs(ts) >= 0.000001) { - *f = (m->m[1][1] * *d - m->m[0][1] * d[1]) / ts; - f[1] = (m->m[1][0] * *d - m->m[0][0] * d[1]) / -ts; + f[0] = (m->m[1][1] * d[0] - m->m[0][1] * d[1]) / ts; + f[1] = (m->m[1][0] * d[0] - m->m[0][0] * d[1]) / -ts; } - if (f[1] >= 0.0 && fabs(ts) >= 0.000001) { - if (*f < 0.0) { + if (f[1] >= 0.0f && fabs(ts) >= 0.000001f) { + if (f[0] < 0.0f) { m->m[0][0] = m->m[1][1]; - *tau = tau[1]; - *n = n[1]; - *d = d[1]; + tau[0] = tau[1]; + n[0] = n[1]; + d[0] = d[1]; ts = SinglePointColl(f, m, d); f[1] = 0.0; } @@ -3426,7 +3569,7 @@ int FindFloorInBoxBU2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* if (!gEliminate_faces || SLOBYTE(face_ref->flags) >= 0) { CheckSingleFace(face_ref, a, b, &nor2, &dist); if (*d > dist) { - if (face_ref->material->colour_map_1 == DOUBLESIDED_FLAG_COLOR_MAP || (face_ref->material->flags & 0x1800) != 0) { + if (face_ref->material->user == DOUBLESIDED_USER_FLAG || (face_ref->material->flags & 0x1800) != 0) { tv.v[0] = c->pos.v[0] - a->v[0]; tv.v[1] = c->pos.v[1] - a->v[1]; tv.v[2] = c->pos.v[2] - a->v[2]; @@ -5217,7 +5360,22 @@ void CrashCarsTogether(br_scalar dt) { tCollison_data collide_list[32]; LOG_TRACE("(%f)", dt); - STUB_ONCE(); + for (i = 0; i < gNum_cars_and_non_cars; i++) { + collide_list[i].car = NULL; + collide_list[i].ref = gNum_cars_and_non_cars - 1; + gActive_car_list[i]->infinite_mass = 0; + } + for (pass = 0; pass < 5; pass++) { + k = CrashCarsTogetherSinglePass(dt, pass, collide_list); + if (k <= 0) { + break; + } + } + if (k > 0) { + for (i = 0; i < gNum_cars_and_non_cars; i++) { + BringCarToAGrindingHalt((tCollision_info*)gActive_car_list[i]); + } + } } // IDA: int __cdecl CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data *collide_list) @@ -5239,25 +5397,245 @@ int CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data* collide tCollision_info* car_in_middle; tCollision_info* car_on_wall; LOG_TRACE("(%f, %d, %p)", dt, pPass, collide_list); - NOT_IMPLEMENTED(); + + collided = 0; + for (i = 0; i < gNum_cars_and_non_cars - 1; i++) { + car_1 = (tCollision_info*)gActive_car_list[i]; + for (j = i + 1; j < gNum_cars_and_non_cars; j++) { + car_2 = (tCollision_info*)gActive_car_list[j]; + if (collide_list[i].ref > 0 || collide_list[j].ref > 0) { + collide_list[i].ref--; + collide_list[j].ref--; + if (SimpleCarCarCollisionTest(car_1, car_2)) { + if (car_1->infinite_mass == -1 && car_2->infinite_mass > 0) { + if (CollideTwoCars(car_1, car_2, -1)) { + if (car_2->infinite_mass >= 256 || pPass >= 4) { + BringCarToAGrindingHalt(car_2); + } else { + car_2->infinite_mass = 0; + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + car_2->infinite_mass = 256; + if (k < 0) { + BringCarToAGrindingHalt(car_2); + } + } + collide_list[j].ref = gNum_cars_and_non_cars - 2; + collide_list[j].car = car_1; + collided++; + } + } else if (car_2->infinite_mass == -1 && car_1->infinite_mass > 0) { + if (CollideTwoCars(car_1, car_2, -1)) { + if (car_1->infinite_mass >= 256 || pPass >= 4) { + BringCarToAGrindingHalt(car_1); + } else { + car_1->infinite_mass = 0; + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + car_1->infinite_mass = 256; + if (k < 0) { + BringCarToAGrindingHalt(car_1); + } + } + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[i].car = car_2; + collided++; + } + } else if (collide_list[i].car || collide_list[j].car) { + if ((collide_list[j].car == NULL) == (collide_list[i].car == NULL)) { + if (collide_list[j].car != collide_list[i].car || (car_1->infinite_mass && car_2->infinite_mass)) { + if (collide_list[i].car && collide_list[j].car) { + if (car_1->infinite_mass && car_2->infinite_mass) { + if ((car_1->infinite_mass != -1 || car_2->infinite_mass != -1) && CollideTwoCars(car_1, car_2, -1)) { + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + if (car_1->infinite_mass && car_2->infinite_mass) { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + } else { + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + if (k >= 0) { + if (k) { + if (car_1->infinite_mass >= 0) { + car_1->infinite_mass++; + } + if (car_2->infinite_mass >= 0) { + car_2->infinite_mass++; + } + collided++; + } + } else { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + collided++; + } + } + collided++; + } + } else { + c1im = car_1->infinite_mass; + c2im = car_2->infinite_mass; + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + if (k > -1) { + if (k) { + if (!c2im) { + collide_list[j].ref = gNum_cars_and_non_cars - 2; + } + if (!c1im) { + collide_list[i].ref = gNum_cars_and_non_cars - 2; + } + collided++; + if (car_1->infinite_mass >= 0) { + car_1->infinite_mass++; + } + if (car_2->infinite_mass >= 0) { + car_2->infinite_mass++; + } + } + } else { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + if (c1im >= 0) { + collide_list[i].ref = gNum_cars_and_non_cars - 2; + } + if (c2im >= 0) { + collide_list[j].ref = gNum_cars_and_non_cars - 2; + } + collided++; + } + } + } + } else { + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + if (k) { + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + if (k == -1) { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + } + collided++; + if (car_1->infinite_mass >= 0) { + car_1->infinite_mass++; + } + if (car_2->infinite_mass >= 0) { + car_2->infinite_mass++; + } + } + } + } else { + c1im = car_1->infinite_mass; + c2im = car_2->infinite_mass; + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + if (k == -1) { + if (collide_list[i].car) { + car_3 = collide_list[i].car; + } else { + car_3 = collide_list[j].car; + } + if (collide_list[i].car) { + car_in_middle = car_1; + } else { + car_in_middle = car_2; + } + if (car_3->infinite_mass > 1 || car_3->infinite_mass == -1 || (tU8)(car_in_middle->infinite_mass) > 1 || car_in_middle->infinite_mass == -1) { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + } else { + if (collide_list[i].car) { + car_on_wall = car_2; + } else { + car_on_wall = car_1; + } + car_in_middle->infinite_mass = 0; + car_3->infinite_mass = 0; + k = CollideTwoCarsWithWalls(car_on_wall, car_in_middle, dt); + car_in_middle->infinite_mass = 2; + car_on_wall->infinite_mass++; + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + if (k < 0) { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + } + } + collide_list[i].car = car_2; + collide_list[j].car = car_1; + collided++; + } else if (k) { + collide_list[i].car = car_2; + collide_list[j].car = car_1; + if (!c2im) { + collide_list[j].ref = gNum_cars_and_non_cars - 2; + } + if (!c1im) { + collide_list[i].ref = gNum_cars_and_non_cars - 2; + } + collided++; + if (car_1->infinite_mass >= 0) { + car_1->infinite_mass++; + } + if (car_2->infinite_mass >= 0) { + car_2->infinite_mass++; + } + } + } + } else { + k = CollideTwoCarsWithWalls(car_1, car_2, dt); + if (k) { + collide_list[i].car = car_2; + collide_list[j].car = car_1; + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + if (k == -1) { + BringCarToAGrindingHalt(car_1); + BringCarToAGrindingHalt(car_2); + collide_list[i].ref = gNum_cars_and_non_cars - 2; + collide_list[j].ref = gNum_cars_and_non_cars - 2; + } + collided++; + } + } + CrashEarnings((tCar_spec*)car_1, (tCar_spec*)car_2); + } + } + } + } + return collided; } // IDA: void __usercall BringCarToAGrindingHalt(tCollision_info *car@) void BringCarToAGrindingHalt(tCollision_info* car) { LOG_TRACE("(%p)", car); - NOT_IMPLEMENTED(); + + BrVector3SetFloat(&car->v, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&car->omega, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&car->oldomega, 0.0f, 0.0f, 0.0f); + BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->oldmat); + car->infinite_mass = -1; } // IDA: int __usercall BoundsOverlapTest@(br_bounds *b1@, br_bounds *b2@) int BoundsOverlapTest_car(br_bounds* b1, br_bounds* b2) { LOG_TRACE("(%p, %p)", b1, b2); - NOT_IMPLEMENTED(); + + return b2->max.v[0] >= b1->min.v[0] + && b1->max.v[0] >= b2->min.v[0] + && b2->max.v[1] >= b1->min.v[1] + && b1->max.v[1] >= b2->min.v[1] + && b2->max.v[2] >= b1->min.v[2] + && b1->max.v[2] >= b2->min.v[2]; } // IDA: int __usercall SimpleCarCarCollisionTest@(tCollision_info *car1@, tCollision_info *car2@) int SimpleCarCarCollisionTest(tCollision_info* car1, tCollision_info* car2) { LOG_TRACE("(%p, %p)", car1, car2); - NOT_IMPLEMENTED(); + + if (car1->bounds_ws_type == eBounds_ws && car2->bounds_ws_type == eBounds_ws) { + return BoundsOverlapTest_car(&car1->bounds_world_space, &car2->bounds_world_space); + } else { + return 1; + } } // IDA: int __usercall CollideTwoCarsWithWalls@(tCollision_info *car1@, tCollision_info *car2@, br_scalar dt) @@ -5271,7 +5649,72 @@ int CollideTwoCarsWithWalls(tCollision_info* car1, tCollision_info* car2, br_sca int im1; int im2; LOG_TRACE("(%p, %p, %f)", car1, car2, dt); - NOT_IMPLEMENTED(); + + l = 0; + m = 0; + p = 0; + im1 = car1->infinite_mass; + im2 = car2->infinite_mass; + do { + n = CollideTwoCarsRepeatedly(car1, car2, dt); + if (n <= 0) { + if (n == -1) { + return -1; + } + l = 0; + m = 0; + } else { + ++p; + if (n >= 5) { + if (p >= 10 || car1->infinite_mass || car2->infinite_mass) { + return -1; + } + BrVector3Set(&car1->omega, 0.0f, 0.0f, 0.0f); + BrVector3Set(&car2->omega, 0.0f, 0.0f, 0.0f); + BrVector3Scale(&mom1, &car1->v, car1->M); + BrVector3Scale(&mom2, &car2->v, car2->M); + BrVector3Accumulate(&mom1, &mom2); + BrVector3InvScale(&car1->v, &mom1, car2->M + car1->M); + car2->v = car1->v; + RotateCar(car1, dt); + TranslateCar(car1, dt); + RotateCar(car2, dt); + TranslateCar(car2, dt); + if (CollideTwoCars(car1, car2, -1)) { + return -1; + } + if (im1 || im2) { + return -1; + } + } + if (!im1) { + l = CollideCarWithWall(car1, dt); + } + if (!im2) { + m = CollideCarWithWall(car2, dt); + } + if (p < 3) { + car1->infinite_mass = im1; + car2->infinite_mass = im2; + } + if (p > 5) { + if (l) { + car1->infinite_mass |= 0x100u; + } + if (m) { + car2->infinite_mass |= 0x100u; + } + } + if (car1->infinite_mass && car2->infinite_mass) { + return -1; + } + } + } while ((l || m) && p < 10); + if (p < 10) { + return p; + } else { + return -1; + } } // IDA: int __usercall CollideTwoCarsRepeatedly@(tCollision_info *car1@, tCollision_info *car2@, br_scalar dt) @@ -5280,7 +5723,36 @@ int CollideTwoCarsRepeatedly(tCollision_info* car1, tCollision_info* car2, br_sc int collide; br_scalar ts; LOG_TRACE("(%p, %p, %f)", car1, car2, dt); - NOT_IMPLEMENTED(); + + l = 0; + ModifyCarsMass(car1, car2); + while (1) { + collide = CollideTwoCars(car1, car2, l); + if (!collide) { + break; + } + if (collide == -1) { + ResetCarsMass(car1, car2); + return -1; + } + if (++l >= 5) { + break; + } + RotateCar(car1, dt); + TranslateCar(car1, dt); + RotateCar(car2, dt); + TranslateCar(car2, dt); + } + if (l > 0) { + car1->frame_collision_flag += 256; + car2->frame_collision_flag += 256; + if (gNet_mode == eNet_mode_host) { + car1->last_car_car_collision = gLast_mechanics_time + 40; + car2->last_car_car_collision = gLast_mechanics_time + 40; + } + } + ResetCarsMass(car1, car2); + return l; } // IDA: int __usercall CollideTwoCars@(tCollision_info *car1@, tCollision_info *car2@, int pPass@) @@ -5319,7 +5791,149 @@ int CollideTwoCars(tCollision_info* car1, tCollision_info* car2, int pPass) { static br_vector3 oldn2; static int is_old_point_available; LOG_TRACE("(%p, %p, %d)", car1, car2, pPass); - NOT_IMPLEMENTED(); + + if (!gCar_car_collisions) { + return 0; + } + if (pPass < 0 && !SimpleCarCarCollisionTest(car1, car2)) { + return 0; + } + + mat1 = &car1->car_master_actor->t.t.mat; + mat2 = &car2->car_master_actor->t.t.mat; + oldmat1 = &car1->oldmat; + oldmat2 = &car2->oldmat; + BrMatrix34LPInverse(&inv_oldmat1, &car1->oldmat); + BrMatrix34LPInverse(&inv_oldmat2, &car2->oldmat); + BrMatrix34Mul(&car1_to_old_car1, mat1, &inv_oldmat1); + BrMatrix34Mul(&car2_to_old_car2, mat2, &inv_oldmat2); + BrMatrix34Mul(&old_car2_to_car1, oldmat2, &inv_oldmat1); + GetNewBoundingBox(&new_car1_bnds, &car1->bounds[1], &car1_to_old_car1); + GetNewBoundingBox(&new_car2_bnds, &car2->bounds[1], &car2_to_old_car2); + + for (i = 0; i < 3; ++i) { + new_car1_bnds.min.v[i] = MIN(car1->bounds[1].min.v[i], new_car1_bnds.min.v[i]); + new_car1_bnds.max.v[i] = MAX(car1->bounds[1].max.v[i], new_car1_bnds.max.v[i]); + + new_car2_bnds.min.v[i] = MIN(car2->bounds[1].min.v[i], new_car2_bnds.min.v[i]); + new_car2_bnds.max.v[i] = MAX(car2->bounds[1].max.v[i], new_car2_bnds.max.v[i]); + } + GetNewBoundingBox(&bnds, &new_car2_bnds, &old_car2_to_car1); + + if (new_car1_bnds.max.v[0] < bnds.min.v[0] + || bnds.max.v[0] < new_car1_bnds.min.v[0] + || new_car1_bnds.max.v[1] < bnds.min.v[1] + || bnds.max.v[1] < new_car1_bnds.min.v[1] + || new_car1_bnds.max.v[2] < bnds.min.v[2] + || bnds.max.v[2] < new_car1_bnds.min.v[2]) { + return 0; + } + BrMatrix34LPInverse(&inv_mat1, mat1); + BrMatrix34LPInverse(&inv_mat2, mat2); + BrMatrix34Mul(&car2_to_car1, mat2, &inv_mat1); + BrMatrix34Mul(&car1_to_car2, mat1, &inv_mat2); + BrMatrix34Mul(&old_car2_to_car1, oldmat2, &inv_oldmat1); + BrMatrix34Mul(&old_car1_to_car2, oldmat1, &inv_oldmat2); + BrMatrix34Mul(&car1_to_old_car1, mat1, &inv_oldmat1); + BrMatrix34Mul(&car2_to_old_car2, mat2, &inv_oldmat2); + do { + k = 0; + k += FacePointCarCarCollide(car1, car2, &car2_to_car1, &old_car2_to_car1, &car1_to_old_car1, r, n, 8, 0); + k += FacePointCarCarCollide(car2, car1, &car1_to_car2, &old_car1_to_car2, &car2_to_old_car2, &r[2 * k], &n[2 * k], 8 - k, 1); + old_k = k; + + if (k < 3 || add_point) { + k += GetEdgeEdgeCollisions(&car1->bounds[1], &car2->bounds[1], &car2_to_car1, &car1_to_car2, &old_car2_to_car1, &old_car1_to_car2, &car1_to_old_car1, &r[2 * k], &n[2 * k], 8 - k); + } + if (k == -1) { + TestOldMats(car1, car2, 1); + } + if (!k) { + return 0; + } + if (k > 4) { + i = old_k; + j = old_k; + while (i < k) { + if (BrVector3Dot(&n[2 * i + 1], &r[2 * i + 1]) <= 0.0f || i - j >= k - 4) { + if (j != i) { + r[2 * j] = r[2 * i]; + } + n[2 * j] = n[2 * i]; + r[2 * j + 1] = r[2 * i + 1]; + n[2 * j + 1] = n[2 * i + 1]; + } else { + j--; + } + i++; + j++; + } + k = j; + } + for (i = 0; i < k; ++i) { + BrVector3Sub(&r[2 * i], &r[2 * i], &car1->cmpos); + BrVector3Sub(&r[2 * i + 1], &r[2 * i + 1], &car2->cmpos); + } + if (add_point == -1) { + return k; + } + car1->doing_nothing_flag = 0; + car2->doing_nothing_flag = 0; + if (k < 3 && add_point) { + for (i = 0; i < k; i++) { + BrVector3Sub(&tv, &r[2 * i], &oldr1); + if (BrVector3LengthSquared(&tv) < 0.01f) { + add_point = 0; + } + } + if (add_point) { + r[2 * k] = oldr1; + r[2 * k + 1] = oldr2; + n[2 * k] = oldn1; + n[2 * k + 1] = oldn2; + k++; + } + } + oldr1 = r[0]; + oldr2 = r[1]; + oldn1 = n[0]; + oldn2 = n[1]; + if (k < 3) { + if (car1->collision_flag && !car1->infinite_mass) { + + for (i = 0; i < k; i++) { + if (BrVector3Dot(&n[2 * i], &car1->old_norm) < -0.9f) { + car1->infinite_mass |= 0x100u; + } + } + if (!car1->infinite_mass) { + r[2 * k] = car1->old_point; + n[2 * k] = car1->old_norm; + BrVector3SetFloat(&n[2 * k + 1], 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&r[2 * k + 1], 0.0f, 0.0f, 0.0f); + k++; + } + } + if (car2->collision_flag && !car2->infinite_mass) { + for (i = 0; i < k; i++) { + if (BrVector3Dot(&n[2 * i + 1], &car2->old_norm) < -0.9f) { + car2->infinite_mass |= 0x100u; + } + } + if (!car2->infinite_mass) { + r[2 * k + 1] = car2->old_point; + n[2 * k + 1] = car2->old_norm; + BrVector3SetFloat(&n[2 * k], 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&r[2 * k], 0.0f, 0.0f, 0.0f); + k++; + } + } + } + if (car1->infinite_mass && car2->infinite_mass) { + return -1; + } + } while (DoCollide(car1, car2, r, n, k, pPass, &car1_to_car2)); + return k; } // IDA: int __usercall GetEdgeEdgeCollisions@(br_bounds *pB1@, br_bounds *pB2@, br_matrix34 *pM21@, br_matrix34 *pM12@, br_matrix34 *pMo21, br_matrix34 *pMo12, br_matrix34 *pM1o1, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax) @@ -5343,7 +5957,129 @@ int GetEdgeEdgeCollisions(br_bounds* pB1, br_bounds* pB2, br_matrix34* pM21, br_ int j; int n; LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %p, %p, %d)", pB1, pB2, pM21, pM12, pMo21, pMo12, pM1o1, pPoint_list, pNorm_list, pMax); - NOT_IMPLEMENTED(); + + // EdgeEdge final version + n = 0; + if (pMax < 1) { + return 0; + } + for (i = 0; i < 4; i++) { + if (i == 3) { + tp1 = pB2->min; + } else { + tp1 = pB2->max; + tp1.v[i] = pB2->min.v[i]; + } + for (j = 0; j < 3; j++) { + tp2 = tp1; + if (pB2->max.v[j] == tp2.v[j]) { + tp2.v[j] = pB2->min.v[j]; + } else { + tp2.v[j] = pB2->max.v[j]; + } + + BrMatrix34ApplyP(&p1, &tp1, pM21); + BrMatrix34ApplyP(&p2, &tp2, pM21); + plane1 = LineBoxColl(&p1, &p2, pB1, &hp1); + if (plane1 == 0) { + continue; + } + plane2 = LineBoxColl(&p2, &p1, pB1, &hp2); + if (plane1 == 8 || plane2 == 8 || plane2 == 0) { + continue; + } + BrVector3Add(&p1, &hp1, &hp2); + BrVector3Scale(&p1, &p1, 0.5f); + BrMatrix34ApplyP(&tp3, &p1, pM12); + BrMatrix34ApplyP(&p2, &tp3, pMo21); + plane3 = LineBoxColl(&p2, &p1, pB1, &hp3); + // if (plane3 != 8 && plane3 != 0) { + // goto LABEL_25; + // } + if (plane3 == 8 || plane3 == 0) { + BrVector3Sub(&tp3, &p2, &p1); + ts = BrVector3Length(&tp3); + ts = ts / 0.01f; + if (ts == 0.0f) { + continue; + } + BrVector3InvScale(&tp3, &tp3, ts); + BrVector3Accumulate(&p2, &tp3); + plane3 = LineBoxColl(&p2, &p1, pB1, &hp3); + if (plane3 == 8) { + continue; + } + } + if (plane3 == 0) { + continue; + } + + BrMatrix34ApplyP(&shp1, &hp1, pM12); + BrMatrix34ApplyP(&shp2, &hp2, pM12); + if ((plane1 ^ plane2) != 4 && (plane3 == plane1 || plane3 == plane2)) { + if (n >= pMax) { + return n; + } + GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane2, &p2, &hp1, &hp2, 0); + BrVector3Accumulate(&shp1, &shp2); + BrVector3Scale(&pPoint_list[2 * n + 1], &shp1, 0.5f); + BrVector3Sub(&p1, &hp1, &hp2); + BrVector3Cross(&p2, &edge, &p1); + BrVector3Normalise(&p2, &p2); + BrVector3Add(&p1, &pB1->max, &pB1->min); + BrVector3Scale(&p1, &p1, 0.5f); + BrVector3Sub(&p1, &pPoint_list[2 * n], &p1); + if (BrVector3Dot(&p1, &p2) > 0.0) { + BrVector3Negate(&p2, &p2); + } + BrMatrix34ApplyV(&p1, &p2, pM12); + BrMatrix34TApplyV(&pNorm_list[2 * n], &p1, pMo12); + BrMatrix34TApplyV(&pNorm_list[2 * n + 1], &p2, pMo21); + BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]); + n++; + } else if ((plane1 ^ plane2) == 4) { + if (pMax - 1 <= n) { + return n; + } + GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane3, &p2, &hp1, &hp2, 0); + GetBoundsEdge(&pPoint_list[2 * n + 2], &edge, pB1, plane2, plane3, &p2, &hp1, &hp2, 0); + pPoint_list[2 * n + 1] = shp1; + pPoint_list[2 * n + 3] = shp2; + BrVector3Sub(&p1, &hp1, &hp2); + BrMatrix34ApplyV(&p2, &p1, pM12); + BrMatrix34ApplyV(&p1, &p2, pMo21); + BrVector3Cross(&p2, &edge, &p1); + BrVector3Normalise(&pNorm_list[2 * n], &p2); + GetPlaneNormal(&edge, plane3); + if (BrVector3Dot(&pNorm_list[2 * n], &edge) < 0.0f) { + BrVector3Negate(&pNorm_list[2 * n], &pNorm_list[2 * n]); + } + BrMatrix34ApplyV(&pNorm_list[2 * n + 1], &pNorm_list[2 * n], pMo12); + BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]); + BrMatrix34ApplyV(&tp3, &pNorm_list[2 * n], pM12); + BrMatrix34ApplyV(&pNorm_list[2 * n], &tp3, pMo21); + pNorm_list[2 * n + 2] = pNorm_list[2 * n]; + pNorm_list[2 * n + 3] = pNorm_list[2 * n + 1]; + n += 2; + } else { + if (pMax - 1 <= n) { + return n; + } + GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane3, &p2, &hp1, &hp2, 0); + GetBoundsEdge(&pPoint_list[2 * n + 2], &edge, pB1, plane2, plane3, &p2, &hp1, &hp2, 0); + BrMatrix34ApplyP(&pPoint_list[2 * n + 1], &hp1, pM12); + BrMatrix34ApplyP(&pPoint_list[2 * n + 3], &hp2, pM12); + GetPlaneNormal(&pNorm_list[2 * n], plane3); + BrMatrix34ApplyV(&pNorm_list[2 * n + 2], &pNorm_list[2 * n], pM1o1); + BrMatrix34ApplyV(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 2], pMo12); + pNorm_list[2 * n] = pNorm_list[2 * n + 2]; + BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]); + pNorm_list[2 * n + 3] = pNorm_list[2 * n + 1]; + n += 2; + } + } + } + return n; } // IDA: int __usercall FacePointCarCarCollide@(tCollision_info *car1@, tCollision_info *car2@, br_matrix34 *pMms@, br_matrix34 *pMoms@, br_matrix34 *pMsos, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax, int order) @@ -5364,25 +6100,81 @@ int FacePointCarCarCollide(tCollision_info* car1, tCollision_info* car2, br_matr br_bounds* pStat_box; br_bounds* pMove_box; LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %d, %d)", car1, car2, pMms, pMoms, pMsos, pPoint_list, pNorm_list, pMax, order); - NOT_IMPLEMENTED(); + + k = 0; + pStat_box = &car2->bounds[1]; + BrVector3Add(¢re, &car2->bounds[1].max, &car2->bounds[1].min); + BrVector3InvScale(¢re, ¢re, 2.0f); + for (i = 0; i < car2->extra_point_num + 8; i++) { + if (i >= 8) { + a = car2->extra_points[i - 8]; + } else { + a.v[0] = ((i & 2) == 0) * pStat_box->min.v[0] + ((i & 2) >> 1) * pStat_box->max.v[0]; + a.v[1] = ((i & 1) == 0) * pStat_box->min.v[1] + (i & 1) * pStat_box->max.v[1]; + a.v[2] = ((i & 4) == 0) * pStat_box->max.v[2] + ((i & 4) >> 2) * pStat_box->min.v[2]; + } + BrMatrix34ApplyP(&aa, &a, pMms); + BrMatrix34ApplyP(&bb, &a, pMoms); + BrVector3Sub(&aa, &aa, &bb); + dist = BrVector3Length(&aa); + if (dist >= 0.00001f) { + BrVector3Scale(&a1, &aa, (0.05f / WORLD_SCALE) / dist); // 0.0072463769 * 6.9 = 0.05 + BrVector3Accumulate(&aa, &a1); + BrVector3Accumulate(&aa, &bb); + plane = LineBoxCollWithSphere(&bb, &aa, &car1->bounds[1], &hp); + if ((plane & 7) != 0) { + GetPlaneNormal(&norm, plane); + + j = 2 * k + order; + l = 2 * k + (order == 0); + BrMatrix34ApplyV(&pNorm_list[j], &norm, pMsos); + BrMatrix34TApplyV(&pNorm_list[l], &pNorm_list[j], pMoms); + BrVector3Negate(&pNorm_list[l], &pNorm_list[l]); + if (pNorm_list[l].v[0] >= 0.0f != centre.v[0] <= a.v[0] || pNorm_list[l].v[1] >= 0.0f != centre.v[1] <= a.v[1] || pNorm_list[l].v[2] >= 0.0f != a.v[2] >= centre.v[2] + || !TestOldMats(car1, car2, 0)) { + pPoint_list[l] = a; + pPoint_list[j] = hp; + k++; + if (pMax == k) { + return k; + } + } + } + } + } + return k; } // IDA: void __usercall MungeCarsMass(tCollision_info *pCar@, br_scalar pFactor) void MungeCarsMass(tCollision_info* pCar, br_scalar pFactor) { LOG_TRACE("(%p, %f)", pCar, pFactor); - NOT_IMPLEMENTED(); + + pCar->M = pCar->M * pFactor; + BrVector3Scale(&pCar->I, &pCar->I, pFactor); } // IDA: void __usercall ModifyCarsMass(tCollision_info *pCar_1@, tCollision_info *pCar_2@) void ModifyCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) { LOG_TRACE("(%p, %p)", pCar_1, pCar_2); - NOT_IMPLEMENTED(); + + if (pCar_1->driver > eDriver_non_car && ((tCar_spec*)pCar_1)->collision_mass_multiplier != 1.0f) { + MungeCarsMass(pCar_1, ((tCar_spec*)pCar_1)->collision_mass_multiplier); + } + if (pCar_2->driver > eDriver_non_car && ((tCar_spec*)pCar_2)->collision_mass_multiplier != 1.0f) { + MungeCarsMass(pCar_2, ((tCar_spec*)pCar_2)->collision_mass_multiplier); + } } // IDA: void __usercall ResetCarsMass(tCollision_info *pCar_1@, tCollision_info *pCar_2@) void ResetCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) { LOG_TRACE("(%p, %p)", pCar_1, pCar_2); - NOT_IMPLEMENTED(); + + if (pCar_1->driver > eDriver_non_car && ((tCar_spec*)pCar_1)->collision_mass_multiplier != 1.0f) { + MungeCarsMass(pCar_1, 1.0f / ((tCar_spec*)pCar_1)->collision_mass_multiplier); + } + if (pCar_2->driver > eDriver_non_car && ((tCar_spec*)pCar_2)->collision_mass_multiplier != 1.0f) { + MungeCarsMass(pCar_2, 1.0f / ((tCar_spec*)pCar_2)->collision_mass_multiplier); + } } // IDA: int __usercall DoCollide@(tCollision_info *car1@, tCollision_info *car2@, br_vector3 *r@, br_vector3 *n@, int k, int pPass, br_matrix34 *mat1_to_mat2) @@ -5425,14 +6217,289 @@ int DoCollide(tCollision_info* car1, tCollision_info* car2, br_vector3* r, br_ve br_scalar factor; int need_to_fudge; LOG_TRACE("(%p, %p, %p, %p, %d, %d, %p)", car1, car2, r, n, k, pPass, mat1_to_mat2); - NOT_IMPLEMENTED(); + + mat1 = &car1->car_master_actor->t.t.mat; + mat2 = &car2->car_master_actor->t.t.mat; + oldmat1 = &car1->oldmat; + oldmat2 = &car2->oldmat; + tau2 = &tau1[4]; + move_car1 = !car1->infinite_mass && car1->min_torque_squared == 0.0f; + move_car2 = !car2->infinite_mass && car2->min_torque_squared == 0.0f; + if (k > 4) { + k = 4; + } + BrMatrix34Copy(mat1, oldmat1); + BrMatrix34Copy(mat2, oldmat2); + car1->omega = car1->oldomega; + car2->omega = car2->oldomega; + BrMatrix34TApplyV(&car1->velocity_car_space, &car1->v, mat1); + BrMatrix34TApplyV(&car2->velocity_car_space, &car2->v, mat2); + need_to_fudge = 1; + for (i = 0; i < k; ++i) { + BrVector3Cross(&tau1[i], &r[2 * i], &n[2 * i]); + BrVector3Cross(&tau2[i], &r[2 * i + 1], &n[2 * i + 1]); + Vector3Div(&tau1[i], &tau1[i], &car1->I); + Vector3Div(&tau2[i], &tau2[i], &car2->I); + BrVector3Cross(&tv, &car1->omega, &r[2 * i]); + BrVector3Accumulate(&tv, &car1->velocity_car_space); + d[i] = -BrVector3Dot(&n[2 * i], &tv); + BrVector3Cross(&tv, &car2->omega, &r[2 * i + 1]); + BrVector3Accumulate(&tv, &car2->velocity_car_space); + d[i] -= BrVector3Dot(&n[2 * i + 1], &tv); + if (d[i] > 0.0f) { + need_to_fudge = 0; + } + } + if (need_to_fudge) { + d[0] = 0.5f; + } + factor = 0.0f; + if (move_car1) { + factor = car1->M + factor; + } + if (move_car2) { + factor = car2->M + factor; + } + for (i = 0; i < k; i++) { + for (j = 0; j < k; j++) { + if (move_car1) { + BrVector3Cross(&tv, &tau1[j], &r[2 * i]); + BrVector3InvScale(&norm, &n[2 * j], car1->M); + BrVector3Accumulate(&tv, &norm); + M.m[i][j] = BrVector3Dot(&n[2 * i], &tv); + } else { + M.m[i][j] = 0.0f; + } + if (move_car2) { + BrVector3Cross(&tv, &tau2[j], &r[2 * i + 1]); + BrVector3InvScale(&norm, &n[2 * j + 1], car2->M); + BrVector3Accumulate(&tv, &norm); + M.m[i][j] += BrVector3Dot(&n[2 * i + 1], &tv); + } + M.m[i][j] *= factor; + } + } + switch (k) { + case 1: + ts = SinglePointColl(f, &M, d); + break; + case 2: + ts = TwoPointCollB(f, &M, d, tau1, n); + break; + case 3: + d[3] = 0.0; + ts = ThreePointCollRecB(f, &M, d, tau1, n); + break; + case 4: + ts = FourPointCollB(f, &M, d, tau1, n); + break; + default: + ts = 0; + break; + } + if (k > 3) { + k = 3; + } + if (fabs(ts) <= 0.000001f) { + return 0; + } + BrVector3SetFloat(&f1, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&f2, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&pos1, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&pos2, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&torque1, 0.0f, 0.0f, 0.0f); + BrVector3SetFloat(&torque2, 0.0f, 0.0f, 0.0f); + tforce = 0.0f; + car1_point = -1; + car2_point = -1; + for (i = 0; i < k; i++) { + f[i] = f[i] * factor; + if (f[i] == 0.0f && k != 0) { + break; + } + if (f[i] < 0.001f) { + f[i] = 0.001f; + } + if (f[i] > 10.0f) { + ts = 0.0f; + } + f[i] = f[i] + 0.1f; + BrVector3Scale(&tau1[i], &tau1[i], f[i]); + BrVector3Scale(&tau2[i], &tau2[i], f[i]); + BrVector3Accumulate(&torque1, &tau1[i]); + BrVector3Accumulate(&torque2, &tau2[i]); + if (!pPass && n[2 * i].v[0] == 0.0f && n[2 * i].v[1] == 0.0f && n[2 * i].v[2] == 0.0f) { + car2_point = i; + } else if (!pPass && n[2 * i + 1].v[0] == 0.0f && n[2 * i + 1].v[1] == 0.0f && n[2 * i + 1].v[2] == 0.0f) { + car1_point = i; + } else { + ts = f[i] / car1->M; + BrVector3Scale(&tv2, &n[2 * i], ts); + BrVector3Accumulate(&f1, &tv2); + ts = f[i] / car2->M; + BrVector3Scale(&tv2, &n[2 * i + 1], ts); + BrVector3Accumulate(&f2, &tv2); + BrVector3Scale(&tv2, &r[2 * i], f[i]); + BrVector3Accumulate(&pos1, &tv2); + BrVector3Scale(&tv2, &r[2 * i + 1], f[i]); + BrVector3Accumulate(&pos2, &tv2); + tforce = f[i] + tforce; + } + } + if (car1->min_torque_squared != 0.0f && !car1->infinite_mass && BrVector3LengthSquared(&torque1) > car1->min_torque_squared) { + BrVector3Scale(&car1->omega, &car1->omega, gDt); + car1->omega.v[0] += torque1.v[0] * 0.04f; + car1->omega.v[2] += torque1.v[2] * 0.04f; + if (BrVector3LengthSquared(&car1->omega) > car1->break_off_radians_squared) { + car1->min_torque_squared = 0.0f; + return 1; + } + BrVector3InvScale(&car1->omega, &car1->omega, gDt); + } + if (car2->min_torque_squared != 0.0f && !car2->infinite_mass && BrVector3LengthSquared(&torque2) > car2->min_torque_squared) { + BrVector3Scale(&car2->omega, &car2->omega, gDt); + car2->omega.v[0] += torque2.v[0] * 0.04f; + car2->omega.v[2] += torque2.v[2] * 0.04f; + if (BrVector3LengthSquared(&car2->omega) > car2->break_off_radians_squared) { + car2->min_torque_squared = 0.0f; + return 1; + } + BrVector3InvScale(&car2->omega, &car2->omega, gDt); + } + if (move_car1) { + BrVector3Accumulate(&car1->omega, &torque1); + } + if (move_car2) { + BrVector3Accumulate(&car2->omega, &torque2); + } + BrVector3InvScale(&pos1, &pos1, tforce); + BrVector3InvScale(&pos2, &pos2, tforce); + if (pPass == 0) { + if (car1_point > -1 && move_car1) { + f[car1_point] = f[car1_point] / car1->M; + BrVector3Scale(&n[2 * car1_point], &n[2 * car1_point], f[car1_point]); + BrVector3Cross(&tv2, &car1->oldomega, &r[2 * car1_point]); + BrVector3Accumulate(&tv2, &car1->velocity_car_space); + ts = BrVector3Length(&tv2); + if (ts > 0.0001f && (car1->driver <= eDriver_non_car || !CAR(car1)->wall_climber_mode)) { + AddFriction(car1, &tv2, &n[2 * car1_point], &r[2 * car1_point], f[car1_point], &max_friction); + BrVector3Accumulate(&n[2 * car1_point], &max_friction); + } + BrMatrix34ApplyV(&tv, &n[2 * car1_point], mat1); + BrVector3Accumulate(&car1->v, &tv); + } + if (car2_point > -1 && move_car2) { + f[car2_point] = f[car2_point] / car2->M; + BrVector3Scale(&n[2 * car2_point + 1], &n[2 * car2_point + 1], f[car2_point]); + BrVector3Cross(&tv2, &car2->oldomega, &r[2 * car2_point + 1]); + BrVector3Accumulate(&tv2, &car2->velocity_car_space); + ts = BrVector3Length(&tv2); + + if (ts > 0.0001f && (car1->driver <= eDriver_non_car || !(CAR(car1)->wall_climber_mode))) { + AddFriction(car2, &tv2, &n[2 * car2_point + 1], &r[2 * car2_point + 1], f[car2_point], &max_friction); + BrVector3Accumulate(&n[2 * car2_point + 1], &max_friction); + } + BrMatrix34ApplyV(&tv, &n[2 * car2_point + 1], mat2); + BrVector3Accumulate(&car2->v, &tv); + } + if (tforce != 0.0f) { + BrVector3Cross(&point_vel1, &car1->oldomega, &pos1); + BrVector3Sub(&a, &car1->v, &car2->v); + BrMatrix34TApplyV(&tv2, &a, mat1); + BrVector3Accumulate(&point_vel1, &tv2); + BrVector3Cross(&point_vel2, &car2->oldomega, &pos2); + AddFrictionCarToCar(car1, car2, &point_vel1, &point_vel2, &f1, &pos1, &pos2, tforce, &max_friction); + if (TestForNan(max_friction.v) || TestForNan(&max_friction.v[1]) || TestForNan(&max_friction.v[2])) { + BrVector3SetFloat(&max_friction, 0.0f, 0.0f, 0.0f); + } + BrVector3InvScale(&tv2, &max_friction, car1->M); + BrVector3Accumulate(&f1, &tv2); + BrMatrix34ApplyV(&tv2, &max_friction, mat1); + BrMatrix34TApplyV(&max_friction, &tv2, mat2); + BrVector3InvScale(&tv2, &max_friction, car2->M); + BrVector3Accumulate(&f2, &tv2); + } + } + if (tforce == 0.0f) { + return 0; + } + BrMatrix34ApplyV(&tv, &f1, mat1); + if (move_car1) { + BrVector3Accumulate(&car1->v, &tv); + } + CrushAndDamageCar((tCar_spec*)car1, &pos1, &f1, (tCar_spec*)car2); + if ((car1->infinite_mass & 0x100) != 0) { + BrVector3Sub(&tv2, &car1->cmpos, &pos1); + BrVector3Accumulate(&tv2, &car1->cmpos); + ts = BrVector3Length(&f1); + if (ts > 0.0001f) { + ts = 5.0f / ts; + BrVector3Scale(&a, &f1, ts); + BrVector3Accumulate(&tv2, &a); + plane = LineBoxColl(&tv2, &pos1, &car1->bounds[1], &a); + if (plane) { + BrVector3Negate(&f12, &f1); + CrushAndDamageCar(CAR(car1), &a, &f12, CAR(car2)); + } + } + } + BrMatrix34ApplyV(&tv, &f2, mat2); + if (move_car2) { + BrVector3Accumulate(&car2->v, &tv); + } + CrushAndDamageCar(CAR(car2), &pos2, &f2, CAR(car1)); + if ((car2->infinite_mass & 0x100) != 0) { + BrVector3Sub(&tv2, &car2->cmpos, &pos2); + BrVector3Accumulate(&tv2, &car2->cmpos); + ts = BrVector3Length(&f2); + if (ts > 0.0001f) { + ts = 5.0 / ts; + BrVector3Scale(&a, &f2, ts); + BrVector3Accumulate(&tv2, &a); + plane = LineBoxColl(&tv2, &pos2, &car2->bounds[1], &a); + if (plane) { + BrVector3Negate(&f22, &f2); + CrushAndDamageCar(CAR(car2), &a, &f22, CAR(car1)); + } + } + } + BrMatrix34ApplyP(&tv2, &pos1, mat1); + BrVector3InvScale(&tv2, &tv2, WORLD_SCALE); + BrVector3Scale(&f1, &f1, 5.0f); + CrashNoise(&f1, &tv2, 0); + BrVector3Add(&a, &car2->v, &car1->v); + BrVector3Scale(&a, &a, 0.25f / WORLD_SCALE); + BrVector3Scale(&tv, &tv, car2->M * 3.0f); + CreateSparkShower(&tv2, &a, &tv, CAR(car1), CAR(car2)); + return 0; } // IDA: br_scalar __usercall TwoPointCollB@(br_scalar *f@, br_matrix4 *m@, br_scalar *d@, br_vector3 *tau@, br_vector3 *n) br_scalar TwoPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) { br_scalar ts; LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n); - NOT_IMPLEMENTED(); + + ts = m->m[1][1] * m->m[0][0] - m->m[0][1] * m->m[1][0]; + if (fabsf(ts) > 0.000001f) { + f[0] = (m->m[1][1] * d[0] - m->m[0][1] * d[1]) / ts; + f[1] = (m->m[1][0] * d[0] - m->m[0][0] * d[1]) / -ts; + } + if (f[1] >= 0.0f) { + if (f[0] < 0.0f) { + m->m[0][0] = m->m[1][1]; + tau[0] = tau[1]; + tau[4] = tau[5]; + n[0] = n[2]; + n[1] = n[3]; + d[0] = d[1]; + ts = SinglePointColl(f, m, d); + f[1] = 0.0f; + } + } else { + ts = SinglePointColl(f, m, d); + f[1] = 0.0; + } + return ts; } // IDA: br_scalar __usercall ThreePointCollRecB@(br_scalar *f@, br_matrix4 *m@, br_scalar *d@, br_vector3 *tau@, br_vector3 *n) @@ -5441,7 +6508,43 @@ br_scalar ThreePointCollRecB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vecto int j; br_scalar ts; LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n); - NOT_IMPLEMENTED(); + + ts = ThreePointColl(f, m, d); + if (f[0] >= 0.0f && f[1] >= 0.0f && f[2] >= 0.0f) { + return ts; + } + if (f[2] >= 0.0f) { + if (f[1] >= 0.0f) { + if (f[0] >= 0.0f) { + return 0.0f; + } + i = 1; + j = 2; + } else { + i = 0; + j = 2; + } + } else { + i = 0; + j = 1; + } + m->m[0][0] = m->m[0][5 * i]; + m->m[1][0] = m->m[j][i]; + m->m[0][1] = m->m[i][j]; + m->m[1][1] = m->m[0][5 * j]; + tau[0] = tau[i]; + tau[1] = tau[j]; + tau[4] = tau[i + 4]; + tau[5] = tau[j + 4]; + n[0] = n[2 * i]; + n[2] = n[2 * j]; + n[1] = n[2 * i + 1]; + n[3] = n[2 * j + 1]; + d[0] = d[i]; + d[1] = d[j]; + ts = TwoPointCollB(f, m, d, tau, n); + f[2] = 0.0; + return ts; } // IDA: br_scalar __usercall FourPointCollB@(br_scalar *f@, br_matrix4 *m@, br_scalar *d@, br_vector3 *tau@, br_vector3 *n) @@ -5451,15 +6554,45 @@ br_scalar FourPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* int l; br_scalar ts; LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n); - NOT_IMPLEMENTED(); + + ts = ThreePointColl(f, m, d); + if (f[0] >= 0.0f && f[1] >= 0.0f && f[2] >= 0.0f) { + return ts; + } + if (f[0] < 0.0f) { + l = 0; + } else if (f[1] < 0.0f) { + l = 1; + } else { + l = 2; + } + for (i = l; i < 3; i++) { + for (j = 0; j < 4; j++) { + m->m[i][j] = m->m[i + 1][j]; + } + d[i] = d[i + 1]; + tau[i] = tau[i + 1]; + tau[i + 4] = tau[i + 5]; + n[2 * i] = n[2 * i + 2]; + n[2 * i + 1] = n[2 * i + 3]; + d[i] = d[i + 1]; + } + for (i = l; i < 3; i++) { + for (j = 0; j < 3; j++) { + m->m[j][i] = m->m[j][i + 1]; + } + } + return ThreePointCollRecB(f, m, d, tau, n); } // IDA: int __usercall TestForNan@(float *f@) int TestForNan(float* f) { tU32 i; LOG_TRACE("(%p)", f); - i = *f; - return (~i & 0x7F800000) == 0; + // i = *f; + // LOG_DEBUG("i %x", i); + return isnan(*f); + // return (~i & 0x7F800000) == 0; } // IDA: void __cdecl CheckCameraHither() @@ -5618,7 +6751,39 @@ int TestOldMats(tCollision_info* c1, tCollision_info* c2, int newmats) { br_matrix34 invmat1; br_matrix34 mat21; LOG_TRACE("(%p, %p, %d)", c1, c2, newmats); - NOT_IMPLEMENTED(); + + n = 0; + b1 = &c1->bounds[1]; + b2 = &c2->bounds[1]; + if (newmats) { + BrMatrix34LPInverse(&invmat1, &c1->car_master_actor->t.t.mat); + BrMatrix34Mul(&mat21, &c2->car_master_actor->t.t.mat, &invmat1); + } else { + BrMatrix34LPInverse(&invmat1, &c1->oldmat); + BrMatrix34Mul(&mat21, &c2->oldmat, &invmat1); + } + for (i = 0; i < 4; ++i) { + if (i == 3) { + edge = b2->min; + } else { + edge = b2->max; + edge.v[i] = b2->min.v[i]; + } + for (j = 0; j < 3; ++j) { + tp1 = edge; + if (b2->max.v[j] == tp1.v[j]) { + tp1.v[j] = b2->min.v[j]; + } else { + tp1.v[j] = b2->max.v[j]; + } + BrMatrix34ApplyP(&p1, &edge, &mat21); + BrMatrix34ApplyP(&p2, &tp1, &mat21); + if (LineBoxColl(&p1, &p2, &c1->bounds[1], &hp1)) { + n++; + } + } + } + return n; } // IDA: int __usercall PullActorFromWorld@(br_actor *pActor@) @@ -5639,8 +6804,55 @@ int DoPullActorFromWorld(br_actor* pActor) { tNon_car_spec* non_car; LOG_TRACE("(%p)", pActor); - STUB(); - return 0; + non_car = NULL; + num = 10 * (pActor->identifier[1] - '0') + 1 * (pActor->identifier[2] - '0'); + if (gNon_car_spec_list[num]) { + non_car = &gProgram_state.non_cars[gNon_car_spec_list[num] + 4]; + } + if (non_car && non_car->collision_info.driver == eDriver_non_car) { + non_car = gProgram_state.non_cars; + for (i = 0; i < NONCAR_UNUSED_SLOTS; i++) { + if (non_car->collision_info.driver == eDriver_non_car_unused_slot) { + break; + } + non_car++; + } + if (i == NONCAR_UNUSED_SLOTS) { + non_car = NULL; + } else { + memcpy(non_car, &gProgram_state.non_cars[gNon_car_spec_list[num] + 4], sizeof(tNon_car_spec)); + } + } + if (non_car != NULL) { + pActor->type_data = non_car; + c = &non_car->collision_info; + c->driver = eDriver_non_car; + c->doing_nothing_flag = 1; + BrActorRemove(pActor); + BrActorAdd(gNon_track_actor, pActor); + c->car_master_actor = pActor; + c->car_ID = 100 * (pActor->identifier[5] - '0') + 10 * (pActor->identifier[6] - '0') + 1 * (pActor->identifier[7] - '0'); + gActive_non_car_list[gNum_active_non_cars] = non_car; + gNum_active_non_cars++; + gActive_car_list[gNum_cars_and_non_cars] = (tCar_spec*)non_car; + gNum_cars_and_non_cars++; + GetNewBoundingBox(&c->bounds_world_space, c->bounds, &pActor->t.t.mat); + non_car->collision_info.bounds_ws_type = eBounds_ws; + InitialiseNonCar(non_car); + ResetCarSpecialVolume((tCollision_info*)non_car); + if (gDoing_physics) { + BrVector3Scale((br_vector3*)&pActor->t.t.mat.m[3][0], (br_vector3*)&pActor->t.t.mat.m[3][0], WORLD_SCALE); + } + BrMatrix34Copy(&c->oldmat, &pActor->t.t.mat); + if (!gDoing_physics) { + BrVector3Scale((br_vector3*)&c->oldmat.m[3][0], (br_vector3*)&c->oldmat.m[3][0], WORLD_SCALE); + } + PipeSingleNonCar((tCollision_info*)non_car); + return 1; + } else { + pActor->identifier[1] = 'x'; + return 0; + } } // IDA: void __usercall CheckForDeAttachmentOfNonCars(tU32 pTime@) @@ -5660,7 +6872,74 @@ void CheckForDeAttachmentOfNonCars(tU32 pTime) { br_matrix34 mat; LOG_TRACE("(%d)", pTime); - STUB_ONCE(); + if (gNum_active_non_cars == 0) { + return; + } + + last_free_slot = 0; + track_spec = &gProgram_state.track_spec; + + StartPipingSession(ePipe_chunk_non_car); + for (i = 0; i < gNum_active_non_cars; i++) { + if (!gActive_non_car_list[i]->collision_info.doing_nothing_flag) { + AddNonCarToPipingSession(gActive_non_car_list[i]->collision_info.car_ID, gActive_non_car_list[i]->collision_info.car_master_actor); + } + } + EndPipingSession(); + + total_time += pTime; + if (total_time < 1000) { + return; + } + total_time = 0; + for (i = 0; i < gNum_active_non_cars; i++) { + c = &gActive_non_car_list[i]->collision_info; + if (c->car_master_actor->t.t.mat.m[3][1] < (double)gMin_world_y) { + c->doing_nothing_flag = 1; + } + if (TestForNan(&c->car_master_actor->t.t.mat.m[3][1])) { + BrVector3Set(&c->omega, 0.0f, 0.0f, 0.0f); + BrMatrix34Identity(&c->car_master_actor->t.t.mat); + c->car_master_actor->t.t.mat.m[3][0] = 2000.0f; + c->car_master_actor->t.t.mat.m[3][1] = 0.0f; + c->car_master_actor->t.t.mat.m[3][2] = 0.0f; + c->doing_nothing_flag = 1; + } + actor = c->car_master_actor; + gActive_non_car_list[last_free_slot] = gActive_non_car_list[i]; + if (c->doing_nothing_flag) { + drop = 1; + for (j = 0; j < gNum_cars_and_non_cars; j++) { + c2 = (tCollision_info*)gActive_car_list[j]; + if (c2 != c && !c2->doing_nothing_flag) { + BrMatrix34Mul(&mat, &actor->t.t.mat, &c2->last_box_inv_mat); + GetNewBoundingBox(&bnds, &actor->model->bounds, &mat); + if (c2->last_box.max.v[0] >= bnds.min.v[0] + && c2->last_box.max.v[1] >= bnds.min.v[1] + && c2->last_box.max.v[2] >= bnds.min.v[2] + && c2->last_box.min.v[0] <= bnds.max.v[0] + && c2->last_box.min.v[1] <= bnds.max.v[1] + && c2->last_box.min.v[2] <= bnds.max.v[2]) { + drop = 0; + break; + } + } + } + if (drop) { + BrActorRemove(actor); + c->driver = eDriver_non_car_unused_slot; + last_free_slot--; + XZToColumnXZ(&cx, &cz, actor->t.t.mat.m[3][0], actor->t.t.mat.m[3][2], track_spec); + if (track_spec->columns[cz][cx]) { + BrActorAdd(track_spec->columns[cz][cx], actor); + } else { + BrActorAdd(gTrack_actor, actor); + } + } + } + last_free_slot++; + } + gNum_active_non_cars = last_free_slot; } // IDA: void __usercall AdjustNonCar(br_actor *pActor@, br_matrix34 *pMat@) @@ -5675,7 +6954,8 @@ void AdjustNonCar(br_actor* pActor, br_matrix34* pMat) { // IDA: void __usercall PipeSingleNonCar(tCollision_info *c@) void PipeSingleNonCar(tCollision_info* c) { LOG_TRACE("(%p)", c); - NOT_IMPLEMENTED(); + + STUB_ONCE(); } // IDA: int __usercall GetPrecalculatedFacesUnderCar@(tCar_spec *pCar@, tFace_ref **pFace_refs@) diff --git a/src/DETHRACE/common/crush.c b/src/DETHRACE/common/crush.c index c615ad03..48294c11 100644 --- a/src/DETHRACE/common/crush.c +++ b/src/DETHRACE/common/crush.c @@ -21,7 +21,7 @@ float gWobble_spam_y[8] = { 0.0f, -0.15f, 0.4f, 0.15f, -0.4f, 0.25f, 0.0f, -0.25 float gWobble_spam_z[8] = { 0.4f, -0.25f, 0.0f, 0.25f, 0.0f, 0.15f, -0.4f, -0.15f }; br_scalar gWheel_circ_to_width = 0.16f; tU8 gSmoke_damage_step[12] = { 20u, 20u, 0u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u }; -int gSteal_ranks[5]; +int gSteal_ranks[5] = { 0, 89, 72, 55, 38 }; // IDA: int __usercall ReadCrushData@(FILE *pF@, tCrush_data *pCrush_data@) int ReadCrushData(FILE* pF, tCrush_data* pCrush_data) { @@ -541,7 +541,7 @@ void CheckPiledriverBonus(tCar_spec* pCar, br_vector3* pImpact_point, br_vector3 br_scalar dp; LOG_TRACE("(%p, %p, %p)", pCar, pImpact_point, pEnergy); - STUB(); + STUB_ONCE(); } // IDA: tImpact_location __usercall CalcModifiedLocation@(tCar_spec *pCar@) @@ -837,7 +837,7 @@ int DoCrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) { tNet_message* message; LOG_TRACE("(%p, %p)", pCar1, pCar2); - STUB(); + STUB_ONCE(); } // IDA: void __usercall DoWheelDamage(tU32 pFrame_period@) diff --git a/src/DETHRACE/common/displays.c b/src/DETHRACE/common/displays.c index f81514e0..982da07e 100644 --- a/src/DETHRACE/common/displays.c +++ b/src/DETHRACE/common/displays.c @@ -811,8 +811,6 @@ int NewTextHeadupSlot2(int pSlot_index, int pFlash_rate, int pLifetime, int pFon int NewTextHeadupSlot(int pSlot_index, int pFlash_rate, int pLifetime, int pFont_index, char* pText) { LOG_TRACE("(%d, %d, %d, %d, \"%s\")", pSlot_index, pFlash_rate, pLifetime, pFont_index, pText); - LOG_DEBUG("(%d, %d, %d, %d, \"%s\")", pSlot_index, pFlash_rate, pLifetime, pFont_index, pText); - return NewTextHeadupSlot2(pSlot_index, pFlash_rate, pLifetime, pFont_index, pText, 1); } diff --git a/src/DETHRACE/common/finteray.c b/src/DETHRACE/common/finteray.c index 66c0ee66..ae82d9c3 100644 --- a/src/DETHRACE/common/finteray.c +++ b/src/DETHRACE/common/finteray.c @@ -24,7 +24,7 @@ tFace_ref* gPling_face; // IDA: int __cdecl BadDiv(br_scalar a, br_scalar b) // Suffix added to avoid duplicate symbol int BadDiv__finteray(br_scalar a, br_scalar b) { - //LOG_TRACE("(%f, %f)", a, b); + // LOG_TRACE("(%f, %f)", a, b); return fabs(b) < 1.0 && fabs(a) > fabs(b) * BR_SCALAR_MAX; } @@ -38,8 +38,8 @@ void DRVector2AccumulateScale__finteray(br_vector2* a, br_vector2* b, br_scalar a->v[1] = b->v[1] * s + a->v[1]; } -//IDA: int __usercall PickBoundsTestRay@(br_bounds *b@, br_vector3 *rp@, br_vector3 *rd@, br_scalar t_near, br_scalar t_far, br_scalar *new_t_near, br_scalar *new_t_far) -// Suffix added to avoid duplicate symbol +// IDA: int __usercall PickBoundsTestRay@(br_bounds *b@, br_vector3 *rp@, br_vector3 *rd@, br_scalar t_near, br_scalar t_far, br_scalar *new_t_near, br_scalar *new_t_far) +// Suffix added to avoid duplicate symbol int PickBoundsTestRay__finteray(br_bounds* b, br_vector3* rp, br_vector3* rd, br_scalar t_near, br_scalar t_far, br_scalar* new_t_near, br_scalar* new_t_far) { int i; float s; @@ -182,8 +182,8 @@ int DRSceneRayPick2D(br_actor* world, br_vector3* pPosition, br_vector3* pDir, d return ActorRayPick2D(world, pPosition, pDir, NULL, NULL, callback); } -//IDA: int __usercall DRModelPick2D@(br_model *model@, br_material *material@, br_vector3 *ray_pos@, br_vector3 *ray_dir@, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn *callback, void *arg) -// Suffix added to avoid duplicate symbol +// IDA: int __usercall DRModelPick2D@(br_model *model@, br_material *material@, br_vector3 *ray_pos@, br_vector3 *ray_dir@, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn *callback, void *arg) +// Suffix added to avoid duplicate symbol int DRModelPick2D__finteray(br_model* model, br_material* material, br_vector3* ray_pos, br_vector3* ray_dir, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn* callback, void* arg) { DR_FACE* fp; int f; @@ -388,7 +388,7 @@ void FindFace(br_vector3* pPosition, br_vector3* pDir, br_vector3* nor, br_scala // IDA: void __cdecl EnablePlingMaterials() void EnablePlingMaterials() { LOG_TRACE("()"); - + gPling_materials = 1; } @@ -1205,7 +1205,19 @@ int SphereBoxIntersection(br_bounds* pB, br_vector3* pC, br_scalar pR_squared, b int i; br_scalar d; LOG_TRACE("(%p, %p, %f, %p)", pB, pC, pR_squared, pHit_point); - NOT_IMPLEMENTED(); + + d = 0.0f; + for (i = 0; i < 3; ++i) { + if (pC->v[i] <= pB->min.v[i]) { + pHit_point->v[i] = pB->min.v[i]; + } else if (pC->v[i] > pB->max.v[i]) { + pHit_point->v[i] = pB->max.v[i]; + } else { + pHit_point->v[i] = pC->v[i]; + } + d += (pC->v[i] - pHit_point->v[i]) * (pC->v[i] - pHit_point->v[i]); + } + return pR_squared >= d; } // IDA: int __usercall LineBoxCollWithSphere@(br_vector3 *o@, br_vector3 *p@, br_bounds *pB@, br_vector3 *pHit_point@) @@ -1213,7 +1225,23 @@ int LineBoxCollWithSphere(br_vector3* o, br_vector3* p, br_bounds* pB, br_vector int i; int plane; LOG_TRACE("(%p, %p, %p, %p)", o, p, pB, pHit_point); - NOT_IMPLEMENTED(); + + plane = LineBoxColl(o, p, pB, pHit_point); + if (plane) { + return plane; + } + if (!SphereBoxIntersection(pB, p, 0.000025f, pHit_point)) { + return 0; + } + for (i = 0; i < 3; ++i) { + if (pB->max.v[i] == pHit_point->v[i] && p->v[i] <= o->v[i]) { + return i + 1; + } + if (pHit_point->v[i] == pB->min.v[i] && p->v[i] >= (o->v[i])) { + return i + 5; + } + } + return 0; } // IDA: int __usercall CompVert@(int v1@, int v2@) diff --git a/src/DETHRACE/common/loading.c b/src/DETHRACE/common/loading.c index 081b2b5f..e33d89c0 100644 --- a/src/DETHRACE/common/loading.c +++ b/src/DETHRACE/common/loading.c @@ -20,6 +20,9 @@ #include "globvrpb.h" #include "grafdata.h" #include "graphics.h" +#include "harness/config.h" +#include "harness/hooks.h" +#include "harness/trace.h" #include "init.h" #include "input.h" #include "newgame.h" @@ -31,16 +34,14 @@ #include "spark.h" #include "utility.h" #include "world.h" -#include "harness/config.h" -#include "harness/hooks.h" -#include "harness/trace.h" #include #define HITHER_MULTIPLIER 2.0f #define AMBIENT_MULTIPLIER 0.01f #define NBR_FUNK_GROVE_FLAGS 30 -tHeadup_info gHeadup_image_info[32] = { // Modified by DethRace to fit the "demo timeout" fancy head-up. +tHeadup_info gHeadup_image_info[32] = { + // Modified by DethRace to fit the "demo timeout" fancy head-up. { "LADY.PIX", eNet_or_otherwise }, { "GENT.PIX", eNet_or_otherwise }, { "CODGER.PIX", eNet_or_otherwise }, @@ -72,7 +73,7 @@ tHeadup_info gHeadup_image_info[32] = { // Modified by DethRace to fit the "dem { "UBROKE.PIX", eNet_only }, { "ULOST.PIX", eNet_only }, { "UWON.PIX", eNet_only }, - { "DTIMEOUT.PIX", eNot_net }, // Only used by the demo, not present in the full version + { "DTIMEOUT.PIX", eNot_net }, // Only used by the demo, not present in the full version }; char* gYour_car_names[2][6]; char* gDrivable_car_names[6]; @@ -809,7 +810,7 @@ tS8* ConvertPixToStripMap(br_pixelmap* pThe_br_map) { for (i = 0; i < pThe_br_map->height; i++) { next_byte = (tU8*)pThe_br_map->pixels + i * pThe_br_map->row_bytes; // points to start of this line - new_line_length = 2; // leave space at the start of the line to store number of chunks and first chunk length + new_line_length = 2; // leave space at the start of the line to store number of chunks and first chunk length j = 0; counter = 0; total = 0; @@ -1194,7 +1195,7 @@ void ReadNonCarMechanicsData(FILE* pF, tNon_car_spec* non_car) { GetThreeFloats(pF, &non_car->free_cmpos.v[0], &non_car->free_cmpos.v[1], &non_car->free_cmpos.v[2]); GetThreeFloats(pF, &non_car->attached_cmpos.v[0], &non_car->attached_cmpos.v[1], &non_car->attached_cmpos.v[2]); GetThreeFloats(pF, &non_car->collision_info.bounds[1].min.v[0], &non_car->collision_info.bounds[1].min.v[1], &non_car->collision_info.bounds[1].min.v[2]); - GetThreeFloats(pF, &non_car->collision_info.bounds[1].max.v[0], &non_car->collision_info.bounds[1].max.v[1], &non_car->collision_info.bounds[1].max.v[1]); + GetThreeFloats(pF, &non_car->collision_info.bounds[1].max.v[0], &non_car->collision_info.bounds[1].max.v[1], &non_car->collision_info.bounds[1].max.v[2]); non_car->collision_info.extra_point_num = GetAnInt(pF); if (non_car->collision_info.extra_point_num > 6) { sprintf(s, "%d", non_car->collision_info.index); @@ -1596,19 +1597,18 @@ int RemoveDoubleSided(br_model* pModel) { for (i = 0; i < pModel->nfaces; i++) { face = &pModel->faces[i]; if (face->material) { - if (face->material->colour_map_1 == DOUBLESIDED_FLAG_COLOR_MAP) { + if (face->material->user == DOUBLESIDED_USER_FLAG) { num_double_sided_faces++; } } } if (num_double_sided_faces > 0) { - LOG_DEBUG("nbr dbl side %d, %p", num_double_sided_faces, pModel); faces = BrResAllocate(pModel, sizeof(br_face) * (num_double_sided_faces + pModel->nfaces), kMem_misc); memcpy(faces, pModel->faces, sizeof(br_face) * pModel->nfaces); orig_nfaces = pModel->nfaces; face = pModel->faces; for (i = 0; i < orig_nfaces; i++) { - if (face->material && face->material->colour_map_1 == DOUBLESIDED_FLAG_COLOR_MAP) { + if (face->material && face->material->user == DOUBLESIDED_USER_FLAG) { faces[pModel->nfaces].vertices[0] = face->vertices[1]; faces[pModel->nfaces].vertices[1] = face->vertices[0]; faces[pModel->nfaces].vertices[2] = face->vertices[2]; @@ -1616,7 +1616,7 @@ int RemoveDoubleSided(br_model* pModel) { faces[pModel->nfaces].material = face->material; pModel->nfaces++; } - ++face; + face++; } BrResFree(pModel->faces); pModel->faces = faces; @@ -2040,12 +2040,12 @@ void LoadCar(char* pCar_name, tDriver pDriver, tCar_spec* pCar_spec, int pOwner, } } if (!its_a_floorpan) { - pStorage_space->materials[i]->colour_map_1 = DOUBLESIDED_FLAG_COLOR_MAP; + pStorage_space->materials[i]->user = DOUBLESIDED_USER_FLAG; } pStorage_space->materials[i]->flags &= 0xFFFFEFFF; } pStorage_space->materials[i]->index_shade = gShade_list[0]; - BrMaterialUpdate(pStorage_space->materials[i], 0x7FFF); + BrMaterialUpdate(pStorage_space->materials[i], BR_MATU_ALL); } PossibleService(); } @@ -2082,7 +2082,6 @@ void LoadCar(char* pCar_name, tDriver pDriver, tCar_spec* pCar_spec, int pOwner, if (!pCar_spec->car_model_actors[i].actor) { FatalError(71); } - // LOG_DEBUG("actor %s, model %s", pCar_spec->car_model_actors[i].actor->identifier, pCar_spec->car_model_actors[i].actor->model->identifier); LinkModelsToActor( pCar_spec->car_model_actors[i].actor, &pStorage_space->models[old_model_count], diff --git a/src/DETHRACE/common/world.c b/src/DETHRACE/common/world.c index c3b6342c..a8856803 100644 --- a/src/DETHRACE/common/world.c +++ b/src/DETHRACE/common/world.c @@ -22,7 +22,6 @@ #include "spark.h" #include "trig.h" #include "utility.h" -#include "brender/brender.h" #include @@ -659,7 +658,6 @@ int LoadNTrackModels(tBrender_storage* pStorage_space, FILE* pF, int pCount) { } for (j = 0; j < total; j++) { if (temp_array[j]) { - LOG_DEBUG("adding track model %s %d, %d", temp_array[j]->identifier, temp_array[j]->nfaces, temp_array[j]->nvertices); switch (AddModelToStorage(pStorage_space, temp_array[j])) { case eStorage_not_enough_room: FatalError(70); @@ -682,9 +680,8 @@ int LoadNTrackModels(tBrender_storage* pStorage_space, FILE* pF, int pCount) { default: break; } - //RemoveDoubleSided(temp_array[j]); + RemoveDoubleSided(temp_array[j]); BrModelAdd(temp_array[j]); - LOG_DEBUG("added track model %s %d, %d", temp_array[j]->identifier, temp_array[j]->nfaces, temp_array[j]->nvertices); new_ones++; } } @@ -1960,9 +1957,21 @@ void SetWallTexturingLevel(tWall_texturing_level pLevel) { // IDA: void __usercall ReallySetWallTexturingLevel(tWall_texturing_level pLevel@) void ReallySetWallTexturingLevel(tWall_texturing_level pLevel) { static tPMFMCB* tweaker[3][3] = { - { NULL, WallUntexToLinear, WallUntexToPersp, }, - { WallLinearToUntex, NULL, WallLinearToPersp, }, - { WallPerspToUntex, WallPerspToLinear, NULL, }, + { + NULL, + WallUntexToLinear, + WallUntexToPersp, + }, + { + WallLinearToUntex, + NULL, + WallLinearToPersp, + }, + { + WallPerspToUntex, + WallPerspToLinear, + NULL, + }, }; LOG_TRACE("(%d)", pLevel); @@ -2005,7 +2014,7 @@ void DisposeTexturingMaterials() { default: break; } - + if (gWall_texturing_level != eWTL_full || gRoad_texturing_level != eRTL_full) { ProcessFaceMaterials(gProgram_state.track_spec.the_actor, DisposeSuffixedMaterials); } @@ -2265,11 +2274,11 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf } for (i = 0; gTrack_storage_space.materials_count > i; ++i) { PossibleService(); - if (gTrack_storage_space.materials[i]->flags & 7) { - gTrack_storage_space.materials[i]->flags &= 0xFFFFFFF8; - if (gTrack_storage_space.materials[i]->flags & 0x1000) { - gTrack_storage_space.materials[i]->colour_map_1 = (br_pixelmap*)12345; - gTrack_storage_space.materials[i]->flags &= 0xFFFFEFFF; + if (gTrack_storage_space.materials[i]->flags & (BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH)) { + gTrack_storage_space.materials[i]->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH); + if (gTrack_storage_space.materials[i]->flags & BR_MATF_TWO_SIDED) { + gTrack_storage_space.materials[i]->user = DOUBLESIDED_USER_FLAG; + gTrack_storage_space.materials[i]->flags &= ~BR_MATF_TWO_SIDED; } BrMaterialUpdate(gTrack_storage_space.materials[i], BR_MATU_RENDERING); } @@ -2583,7 +2592,7 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf gProgram_state.non_cars = non_car; gProgram_state.num_non_car_spaces = num_non_cars + NONCAR_UNUSED_SLOTS; for (i = 0; i < COUNT_OF(gNon_car_spec_list); ++i) { - gNon_car_spec_list[i] = 0; + gNon_car_spec_list[i] = '\0'; } for (i = 0; i < NONCAR_UNUSED_SLOTS; i++) { non_car->collision_info.driver = eDriver_non_car_unused_slot; @@ -3625,12 +3634,9 @@ tSpecial_volume* FindSpecialVolume(br_vector3* pP, tSpecial_volume* pLast_vol) { LOG_TRACE("(%p, %p)", pP, pLast_vol); for (i = 0, v = gProgram_state.special_volumes; i < gProgram_state.special_volume_count; i++, v++) { - if (!v->no_mat && - v->bounds.min.v[0] < pP->v[0] && pP->v[0] < v->bounds.max.v[0] && - v->bounds.min.v[1] < pP->v[1] && pP->v[1] < v->bounds.max.v[1] && - v->bounds.min.v[2] < pP->v[2] && pP->v[2] < v->bounds.max.v[2]) { + if (!v->no_mat && v->bounds.min.v[0] < pP->v[0] && pP->v[0] < v->bounds.max.v[0] && v->bounds.min.v[1] < pP->v[1] && pP->v[1] < v->bounds.max.v[1] && v->bounds.min.v[2] < pP->v[2] && pP->v[2] < v->bounds.max.v[2]) { BrMatrix34ApplyP(&p, pP, &v->inv_mat); - if (-1.f < p.v[0] && p.v[0] < 1.f && -1.f < p.v[1] && p.v[1] < 1.f && -1.f < p.v[2] && p.v[2] < 1.f) { + if (-1.f < p.v[0] && p.v[0] < 1.f && -1.f < p.v[1] && p.v[1] < 1.f && -1.f < p.v[2] && p.v[2] < 1.f) { return v; } } @@ -4129,11 +4135,12 @@ br_material* GetExternalMat() { return BrMaterialFind("SPECVOL2.MAT"); } -#define DrVertexSet(V, X, Y, Z) do { \ - (V)[0] = (X); \ - (V)[1] = (Y); \ - (V)[2] = (Z); \ -} while (0) +#define DrVertexSet(V, X, Y, Z) \ + do { \ + (V)[0] = (X); \ + (V)[1] = (Y); \ + (V)[2] = (Z); \ + } while (0) // IDA: void __usercall BuildSpecVolModel(tSpecial_volume *pSpec@, int pIndex@, br_material *pInt_mat@, br_material *pExt_mat@) void BuildSpecVolModel(tSpecial_volume* pSpec, int pIndex, br_material* pInt_mat, br_material* pExt_mat) { @@ -4194,9 +4201,9 @@ void BuildSpecVolModel(tSpecial_volume* pSpec, int pIndex, br_material* pInt_mat model->faces[i].vertices[0] = model->faces[i].vertices[1]; model->faces[i].vertices[1] = temp; } - model->faces[ 5].material = model->faces[ 4].material = model->faces[ 1].material = model->faces[ 0].material = DRMaterialClone(pExt_mat); - model->faces[11].material = model->faces[10].material = model->faces[ 9].material = model->faces[ 8].material = DRMaterialClone(pExt_mat); - model->faces[ 7].material = model->faces[ 6].material = model->faces[ 3].material = model->faces[ 2].material = DRMaterialClone(pExt_mat); + model->faces[5].material = model->faces[4].material = model->faces[1].material = model->faces[0].material = DRMaterialClone(pExt_mat); + model->faces[11].material = model->faces[10].material = model->faces[9].material = model->faces[8].material = DRMaterialClone(pExt_mat); + model->faces[7].material = model->faces[6].material = model->faces[3].material = model->faces[2].material = DRMaterialClone(pExt_mat); model->faces[17].material = model->faces[16].material = model->faces[13].material = model->faces[12].material = DRMaterialClone(pInt_mat); model->faces[23].material = model->faces[22].material = model->faces[21].material = model->faces[20].material = DRMaterialClone(pInt_mat); model->faces[19].material = model->faces[18].material = model->faces[15].material = model->faces[14].material = DRMaterialClone(pInt_mat); diff --git a/src/DETHRACE/constants.h b/src/DETHRACE/constants.h index 41eae03e..0703cfe8 100644 --- a/src/DETHRACE/constants.h +++ b/src/DETHRACE/constants.h @@ -261,20 +261,20 @@ typedef enum keymapcodes { // The following items are meant to be used standalone // - KEYMAP_COCKPIT = 45, // default C - KEYMAP_SAVE = 28, // default F2 - KEYMAP_LOAD = 29, // default F3 - KEYMAP_MOVE_UP = 30, // default UP - KEYMAP_MOVE_DOWN = 31, // default DOWN - KEYMAP_MOVE_LEFT = 32, // default LEFT - KEYMAP_MOVE_RIGHT = 33, // default RIGHT - KEYMAP_MIRROR = 34, // default M - KEYMAP_PRATCAM = 35, // default P - KEYMAP_LOOK_LEFT = 50, // default Q - KEYMAP_LOOK_FORWARD = 51, // default W - KEYMAP_LOOK_RIGHT = 52, // default E - KEYMAP_SOUND = 36, // default S - KEYMAP_REPAIR = 44, // default BACKSPACE + KEYMAP_COCKPIT = 45, // default C + KEYMAP_SAVE = 28, // default F2 + KEYMAP_LOAD = 29, // default F3 + KEYMAP_MOVE_UP = 30, // default UP + KEYMAP_MOVE_DOWN = 31, // default DOWN + KEYMAP_MOVE_LEFT = 32, // default LEFT + KEYMAP_MOVE_RIGHT = 33, // default RIGHT + KEYMAP_MIRROR = 34, // default M + KEYMAP_PRATCAM = 35, // default P + KEYMAP_LOOK_LEFT = 50, // default Q + KEYMAP_LOOK_FORWARD = 51, // default W + KEYMAP_LOOK_RIGHT = 52, // default E + KEYMAP_SOUND = 36, // default S + KEYMAP_REPAIR = 44, // default BACKSPACE KEYMAP_PEDESTRIANS = 54, // default KP_MINUS KEYMAP_F4 = 17, // default F4 KEYMAP_F5 = 18, // default F5 @@ -351,6 +351,6 @@ typedef enum keymapcodes { #define SHADOW_MAX_RENDER_DISTANCE 36.0f -#define DOUBLESIDED_FLAG_COLOR_MAP (br_pixelmap*)12345 +#define DOUBLESIDED_USER_FLAG (void*)12345 #endif diff --git a/src/DETHRACE/macros.h b/src/DETHRACE/macros.h index 4f4f9c7a..472cf8bc 100644 --- a/src/DETHRACE/macros.h +++ b/src/DETHRACE/macros.h @@ -10,6 +10,7 @@ #define STR_STARTS_WITH(haystack, needle) strncmp(haystack, needle, strlen(needle)) #define STR_ENDS_WITH(haystack, needle) strcmp(haystack + strlen(haystack) - strlen(needle), needle) +#define MIN(a, b) ((a) < (b) ? a : b) #define MAX(a, b) ((a) > (b) ? a : b) #define COUNT_OF(array) (sizeof((array)) / sizeof((array)[0])) #define LEN(array) (sizeof((array)) / sizeof((array)[0])) @@ -17,5 +18,13 @@ #define DEG_TO_RAD(degrees) ((degrees)*3.141592653589793 / 180.0) #define V11MODEL(model) (((v11model*)model->prepared)) +#define CAR(c) ((tCar_spec*)c) + +#define Vector3Div(v1, v2, v3) \ + do { \ + (v1)->v[0] = (v2)->v[0] / (v3)->v[0]; \ + (v1)->v[1] = (v2)->v[1] / (v3)->v[1]; \ + (v1)->v[2] = (v2)->v[2] / (v3)->v[2]; \ + } while (0) #endif \ No newline at end of file diff --git a/src/harness/renderers/gl/gl_renderer.c b/src/harness/renderers/gl/gl_renderer.c index df09dec8..8763ed47 100644 --- a/src/harness/renderers/gl/gl_renderer.c +++ b/src/harness/renderers/gl/gl_renderer.c @@ -138,13 +138,13 @@ void SetupFullScreenRectGeometry() { float vertices[] = { // positions // colors // texture coords 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right - 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right + 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left }; unsigned int indices[] = { 0, 1, 3, // first triangle - 1, 2, 3 // second triangle + 1, 2, 3 // second triangle }; GLuint vbo; @@ -195,6 +195,7 @@ void GLRenderer_Init(int width, int height, int pRender_width, int pRender_heigh glDepthFunc(GL_LESS); glClearColor(0, 0, 0, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_CULL_FACE); // textures glGenTextures(1, &screen_texture); @@ -463,17 +464,13 @@ void setActiveMaterial(tStored_material* material) { if (material->shade_table) { GLRenderer_SetShadeTable(material->shade_table); } + if ((material->flags & BR_MATF_LIGHT) && !(material->flags & BR_MATF_PRELIT) && material->shade_table) { // TODO: light value shouldn't always be 0? Works for shadows, not sure about other things. glUniform1i(uniforms_3d.light_value, 0); } else { glUniform1i(uniforms_3d.light_value, -1); } - if (material->flags & BR_MATF_ALWAYS_VISIBLE) { - glDisable(GL_CULL_FACE); - } else { - glEnable(GL_CULL_FACE); - } if (material->pixelmap) { tStored_pixelmap* stored_px = material->pixelmap->stored;