/* STRUCTURES.C symbols in this file: 00187C10 0010: _structures_initialize (0000) 00187C20 0010: _structures_initialize_for_new_map (0000) 00187C30 0010: _structures_dispose_from_old_map (0000) 00187C40 0010: _structures_dispose (0000) 00187C50 0040: _structure_cluster_marker_begin (0000) 00187C90 0080: _structure_cluster_unmarked (0000) 00187D10 0080: _structure_cluster_mark (0000) 00187D90 0040: _structure_cluster_marker_end (0000) 00187DD0 01b0: _structure_render_surface_from_point_and_leaf (0000) 00187F80 00d0: _structure_get_planar_fog_definition_index (0000) 00188050 01b0: _sphere_intersects_cluster_portal (0000) 00188200 0120: _code_00188200 (0000) 00188320 01e0: _structure_clusters_in_cone (0000) 00188500 0260: _structure_test_vector (0000) 00188760 01c0: _structure_get_planar_fog (0000) 00188920 0160: _render_debug_fog_planes (0000) 00188A80 0130: _structure_clusters_in_sphere (0000) 002A1E54 002e: ??_C@_0CO@IAFCMJGA@?$CBstructure_globals?4cluster_marke@ (0000) 002A1E84 0027: ??_C@_0CH@MEPFLBCJ@c?3?2halo?2SOURCE?2structures?2struct@ (0000) 002A1EAC 002d: ??_C@_0CN@MDKOILJF@structure_globals?4cluster_marker@ (0000) 002A1EDC 002b: ??_C@_0CL@OOHBKJHI@stack_depth?$DMMAXIMUM_CLUSTERS_PER@ (0000) 002A1F08 0002: ??_C@_01LKDEMHDF@s?$AA@ (0000) 002A1F0C 000e: ??_C@_0O@GNJLHEFA@surface_index?$AA@ (0000) 002A1F1C 000f: ??_C@_0P@MLEINILI@material_index?$AA@ (0000) 002A1F2C 0014: ??_C@_0BE@GKJHHJJB@intersected_indices?$AA@ (0000) 004C1100 0808: _bss_004c1100 (0000) */ /* ---------- headers */ #include "cseries/cseries.h" #include "math/real_math.h" #include "physics/collision_bsp_definitions.h" #include "physics/collisions.h" #include "physics/collision_usage.h" #include "rasterizer/rasterizer.h" #include "rasterizer/rasterizer_debug.h" #include "rasterizer/rasterizer_geometry_environment.h" #include "render/render.h" #include "scenario/scenario.h" #include "scenario/fog_definitions.h" #include "scenario/sky_definitions.h" #include "structure_bsp_definitions.h" #include "structure_vector_tests.h" #include "structures.h" /* ---------- constants */ enum { _render_planar_fog_mode_off = 0, _render_planar_fog_mode_normal = 1, _render_planar_fog_mode_fully_fogged, _render_fog_runtime_screen_use_sky_interpolator_bit = 0, _collision_surface_two_sided_bit = 0, }; /* ---------- macros */ #define structure_material_get_vertex(material, vertex_index) \ ((struct environment_vertex_compressed const *) \ (material)->compressed_vertex_data.address + (vertex_index)) /* ---------- structures */ struct structure_runtime_globals { boolean initialized; boolean cluster_marker_initialized; byte reserved0002[2]; long cluster_marker; long cluster_magic_numbers[MAXIMUM_CLUSTERS_PER_STRUCTURE]; }; struct structure_fog_plane_render { short region_index; word pad; real_plane3d plane; struct tag_block vertices; }; struct structure_cluster_graph { short sky_index; short fog_designator; short background_sound_palette_index; short sound_environment_palette_index; short weather_palette_index; short transition_structure_bsp_index; short first_runtime_decal_index; word runtime_decal_count; long unused[6]; struct tag_block predicted_resources; struct tag_block subclusters; word first_lens_flare_marker_index; word lens_flare_marker_count; struct tag_block surface_indices; struct tag_block mirrors; struct tag_block portal_indices; }; struct structure_cluster_portal { short cluster_indices[2]; long plane_index; real_point3d centroid; real bounding_radius; unsigned long flags; long unused[6]; struct tag_block vertices; }; struct structure_surface_reference { long surface_index; long bsp3d_node_index; }; struct environment_vertex_compressed { real_point3d position; unsigned long normal; unsigned long binormal; unsigned long tangent; real_point2d texcoord; }; struct fog_screen { word flags; short layer_count; real near_distance; real far_distance; real near_density; real far_density; real start_distance_from_fog_plane; byte reserved18[4]; pixel32 color; real rotation_multiplier; real strafing_multiplier; real zoom_multiplier; byte reserved2C[8]; real map_scale; struct tag_reference map; }; struct structure_planar_fog_definition { word flags; word pad; real animation_distance; byte unused08[0x50]; real maximum_density; byte unused5C[4]; real maximum_distance; byte unused64[4]; real maximum_depth; byte unused6C[0xC]; real_rgb_color color; struct fog_screen screen; }; typedef char verify_structure_fog_plane_render_size[ sizeof(struct structure_fog_plane_render) == 0x20 ? 1 : -1]; typedef char verify_structure_cluster_graph_size[ sizeof(struct structure_cluster_graph) == 0x68 ? 1 : -1]; typedef char verify_structure_cluster_graph_portal_indices_offset[ offsetof(struct structure_cluster_graph, portal_indices) == 0x5C ? 1 : -1]; typedef char verify_structure_cluster_portal_size[ sizeof(struct structure_cluster_portal) == 0x40 ? 1 : -1]; typedef char verify_structure_surface_reference_size[ sizeof(struct structure_surface_reference) == 0x8 ? 1 : -1]; typedef char verify_environment_vertex_compressed_size[ sizeof(struct environment_vertex_compressed) == 0x20 ? 1 : -1]; typedef char verify_structure_planar_fog_definition_screen_offset[ offsetof(struct structure_planar_fog_definition, screen) == 0x84 ? 1 : -1]; typedef char verify_structure_cluster_marker_initialized_offset[ offsetof( struct structure_runtime_globals, cluster_marker_initialized) == 0x1 ? 1 : -1]; typedef char verify_structure_cluster_marker_offset[ offsetof( struct structure_runtime_globals, cluster_marker) == 0x4 ? 1 : -1]; typedef char verify_structure_cluster_magic_numbers_offset[ offsetof( struct structure_runtime_globals, cluster_magic_numbers) == 0x8 ? 1 : -1]; typedef char verify_structure_runtime_globals_size[ sizeof(struct structure_runtime_globals) == 0x808 ? 1 : -1]; /* ---------- prototypes */ /* ---------- globals */ static struct structure_runtime_globals structure_globals; extern boolean debug_fog_planes; /* ---------- public code */ void structures_initialize( void) { structure_detail_objects_initialize(); structure_decals_initialize(); return; } void structures_initialize_for_new_map( void) { structure_detail_objects_initialize_for_new_map(); structure_decals_initialize_for_new_map(); return; } void structures_dispose_from_old_map( void) { structure_decals_dispose_from_old_map(); structure_detail_objects_dispose_from_old_map(); return; } void structures_dispose( void) { structure_decals_dispose(); structure_detail_objects_dispose(); return; } void structure_cluster_marker_begin( void) { match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x103, !structure_globals.cluster_marker_initialized); structure_globals.cluster_marker++; structure_globals.cluster_marker_initialized = TRUE; return; } void structure_cluster_marker_end( void) { match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x130, structure_globals.cluster_marker_initialized); structure_globals.cluster_marker_initialized = FALSE; return; } boolean structure_cluster_unmarked( short cluster_index) { match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x10E, structure_globals.cluster_marker_initialized); match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x10F, cluster_index>=0 && cluster_index=0 && cluster_indexleaves, leaf_index & LONG_MAX, struct structure_leaf); long surface_reference_index; for (surface_reference_index = leaf->first_surface_reference_index; surface_reference_index < leaf->first_surface_reference_index + leaf->surface_reference_count; surface_reference_index++) { struct structure_surface_reference *surface_reference = TAG_BLOCK_GET_ELEMENT( &structure->surface_references, surface_reference_index, struct structure_surface_reference); long bsp3d_node_index = surface_reference->bsp3d_node_index; if (bsp3d_node_index != NONE) { struct collision_bsp *collision_bsp = TAG_BLOCK_GET_ELEMENT( &structure->collision_bsp, 0, struct collision_bsp); struct bsp3d_node *node = TAG_BLOCK_GET_ELEMENT( &collision_bsp->bsp3d.nodes, bsp3d_node_index, struct bsp3d_node); if (node->plane_designator == plane_index) { struct structure_surface *surface = TAG_BLOCK_GET_ELEMENT( &structure->surfaces, surface_reference->surface_index, struct structure_surface); struct structure_lightmap *lightmap; struct structure_material *material; structure_bsp_find_material_for_surface( structure, surface_reference->surface_index, lightmap_index, material_index); lightmap = TAG_BLOCK_GET_ELEMENT( &structure->lightmaps, *lightmap_index, struct structure_lightmap); material = TAG_BLOCK_GET_ELEMENT( &lightmap->materials, *material_index, struct structure_material); if (material->vertices.type == _rasterizer_vertex_type_environment_uncompressed || material->vertices.type == _rasterizer_vertex_type_environment_compressed) { real_point3d triangle_points[NUMBER_OF_VERTICES_PER_TRIANGLE]; environment_vertex_compressed_get_point( structure_material_get_vertex( material, surface->vertex_indices[0]), &triangle_points[0]); environment_vertex_compressed_get_point( structure_material_get_vertex( material, surface->vertex_indices[1]), &triangle_points[1]); environment_vertex_compressed_get_point( structure_material_get_vertex( material, surface->vertex_indices[2]), &triangle_points[2]); if (point_in_triangle3d( point, &triangle_points[0], &triangle_points[1], &triangle_points[2], s, t)) { *surface_index = surface_reference->surface_index; return TRUE; } } } } } return FALSE; } void render_debug_fog_planes( void) { if (debug_fog_planes && render.fog.planar_mode == _render_planar_fog_mode_normal && render.cluster_index != NONE) { struct structure_bsp *structure = global_structure_bsp_get(); struct structure_cluster *cluster = TAG_BLOCK_GET_ELEMENT( &structure->clusters, render.cluster_index, struct structure_cluster); struct structure_fog_plane_render *fog_plane = TAG_BLOCK_GET_ELEMENT( &structure->fog_planes, cluster->fog_reference & SHORT_MAX, struct structure_fog_plane_render); long vertex_count = fog_plane->vertices.count; if (vertex_count > 0) { short vertex_index = 0; do { short next_vertex_index = (short)((vertex_index + 1) % vertex_count); real_point3d *point0 = TAG_BLOCK_GET_ELEMENT( &fog_plane->vertices, vertex_index, real_point3d); real_point3d *point1 = TAG_BLOCK_GET_ELEMENT( &fog_plane->vertices, next_vertex_index, real_point3d); real offset = -render.fog.planar_maximum_distance; real_point3d offset_point0; real_point3d offset_point1; offset_point0.x = point0->x + fog_plane->plane.n.i * offset; offset_point0.y = point0->y + fog_plane->plane.n.j * offset; offset_point0.z = point0->z + fog_plane->plane.n.k * offset; offset_point1.x = point1->x + fog_plane->plane.n.i * offset; offset_point1.y = point1->y + fog_plane->plane.n.j * offset; offset_point1.z = point1->z + fog_plane->plane.n.k * offset; rasterizer_debug_line(point0, point1, global_real_argb_white); rasterizer_debug_line( &offset_point0, &offset_point1, global_real_argb_black); rasterizer_debug_line_shaded( point0, &offset_point0, global_real_argb_white, global_real_argb_black); rasterizer_debug_line_shaded( point1, &offset_point1, global_real_argb_white, global_real_argb_black); vertex_count = fog_plane->vertices.count; vertex_index++; } while (vertex_index < vertex_count); } } return; } short structure_clusters_in_cone( short position_cluster_index, real_point3d const *position, real_vector3d const *direction, real distance, real sine, real cosine, short maximum_cluster_count, short *cluster_indices) { short cluster_stack[MAXIMUM_CLUSTERS_PER_STRUCTURE]; short stack_depth; short cluster_count = 0; struct structure_bsp *structure; structure_cluster_marker_begin(); structure = global_structure_bsp_get(); structure_cluster_mark(position_cluster_index); cluster_stack[0] = position_cluster_index; stack_depth = 1; while (cluster_count < maximum_cluster_count && stack_depth > 0) { short cluster_index = cluster_stack[--stack_depth]; struct structure_cluster_graph *cluster = TAG_BLOCK_GET_ELEMENT( &structure->clusters, cluster_index, struct structure_cluster_graph); short portal_index; cluster_indices[cluster_count++] = cluster_index; for (portal_index = 0; portal_index < cluster->portal_indices.count; portal_index++) { short structure_portal_index = *TAG_BLOCK_GET_ELEMENT( &cluster->portal_indices, portal_index, short); struct structure_cluster_portal *portal = TAG_BLOCK_GET_ELEMENT( &structure->cluster_portals, structure_portal_index, struct structure_cluster_portal); short adjacent_cluster_index = portal->cluster_indices[0] == cluster_index ? portal->cluster_indices[1] : portal->cluster_indices[0]; if (structure_cluster_unmarked(adjacent_cluster_index) && sphere_intersects_cone3d( &portal->centroid, portal->bounding_radius, position, direction, distance, sine, cosine)) { structure_cluster_mark(adjacent_cluster_index); match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0xF5, stack_depthlightmaps, *lightmap_index, struct structure_lightmap)->bitmap_index != NONE) { found = TRUE; } else if (TEST_FLAG( collision.flags, _collision_surface_two_sided_bit)) { done = FALSE; collision_point->x += v->i * (1.0f / 4096.0f); collision_point->y += v->j * (1.0f / 4096.0f); collision_point->z += v->k * (1.0f / 4096.0f); } } match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x1AA, global_current_collision_user_depth > 1); --global_current_collision_user_depth; } while (!done); return found; } long structure_get_planar_fog_definition_index( struct structure_bsp const *structure, short cluster_index, boolean get_fog_from_sky) { long fog_definition_index = NONE; if (cluster_index != NONE) { struct structure_cluster *cluster = TAG_BLOCK_GET_ELEMENT( &structure->clusters, cluster_index, struct structure_cluster); if (get_fog_from_sky) { struct sky *sky = scenario_get_sky(0); if (sky) { fog_definition_index = sky->indoor_fog_screen.index; } } else { short fog_designator = cluster->fog_reference; if (fog_designator != NONE) { short fog_region_index; if (TEST_FLAG((word)fog_designator, SHORT_BITS - 1)) { struct structure_fog_plane_render *fog_plane = TAG_BLOCK_GET_ELEMENT( &structure->fog_planes, fog_designator & SHORT_MAX, struct structure_fog_plane_render); fog_region_index = fog_plane->region_index; } else { fog_region_index = fog_designator & SHORT_MAX; } if (fog_region_index != NONE) { struct structure_fog_region *fog_region = TAG_BLOCK_GET_ELEMENT( &structure->fog_regions, fog_region_index, struct structure_fog_region); if (fog_region->fog_palette_index != NONE) { struct structure_fog_palette_entry *fog_palette = TAG_BLOCK_GET_ELEMENT( &structure->fog_palette, fog_region->fog_palette_index, struct structure_fog_palette_entry); fog_definition_index = fog_palette->fog.index; } } } } } return fog_definition_index; } void structure_get_planar_fog( short cluster_index, struct render_fog *fog) { struct structure_bsp *structure = global_structure_bsp_get(); boolean screen_fog = FALSE; long fog_definition_index; match_assert( "c:\\halo\\SOURCE\\structures\\structures.c", 0x1F1, fog); fog->planar_mode = _render_planar_fog_mode_off; fog->fog_definition_flags = 0; fog->screen = NULL; fog_definition_index = structure_get_planar_fog_definition_index( structure, cluster_index, FALSE); if (fog_definition_index == NONE) { fog_definition_index = structure_get_planar_fog_definition_index( structure, cluster_index, TRUE); screen_fog = TRUE; } if (fog_definition_index != NONE) { struct structure_cluster *cluster = TAG_BLOCK_GET_ELEMENT( &global_structure_bsp_get()->clusters, cluster_index, struct structure_cluster); struct structure_planar_fog_definition *definition = (struct structure_planar_fog_definition *)fog_definition_get( fog_definition_index); if (screen_fog) { SET_FLAG( fog->runtime_flags, _render_fog_runtime_screen_use_sky_interpolator_bit, TRUE); } else { if (TEST_FLAG((word)cluster->fog_reference, SHORT_BITS - 1)) { struct structure_fog_plane_render *fog_plane = TAG_BLOCK_GET_ELEMENT( &structure->fog_planes, cluster->fog_reference & SHORT_MAX, struct structure_fog_plane_render); fog->planar_mode = _render_planar_fog_mode_normal; fog->plane = fog_plane->plane; } else { fog->planar_mode = _render_planar_fog_mode_fully_fogged; } fog->planar_color = definition->color; fog->planar_maximum_density = definition->maximum_density; fog->planar_maximum_distance = definition->maximum_distance; fog->planar_maximum_depth = definition->maximum_depth; if (TEST_FLAG((word)cluster->fog_reference, SHORT_BITS - 1)) { /* BUG: January and two independent later reconstructions scale * the authored animation distance by a literal zero, disabling * planar-fog motion. */ real offset = definition->animation_distance * 0.0f; real_vector3d offset_vector; fog->plane.d += offset; offset_vector.i = fog->plane.n.i * offset; offset_vector.j = fog->plane.n.j * offset; offset_vector.k = fog->plane.n.k * offset; structure_render_set_fog_offset(&offset_vector); } } fog->fog_definition_flags = definition->flags; fog->screen = &definition->screen; } return; } /* ---------- private code */