mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-19 00:00:29 +02:00
942 lines
24 KiB
C
942 lines
24 KiB
C
/*
|
|
OBJECT_LIGHTS.C
|
|
|
|
symbols in this file:
|
|
00128730 0030:
|
|
_texture_cache_bitmap_load (0000)
|
|
00128760 0020:
|
|
_code_00128760 (0000)
|
|
00128780 0040:
|
|
_code_00128780 (0000)
|
|
001287C0 0060:
|
|
_shade_vector3d (0000)
|
|
00128820 0100:
|
|
_sample_lightmap (0000)
|
|
00128920 00f0:
|
|
_sample_diffuse_texture (0000)
|
|
00128A10 0020:
|
|
_code_00128a10 (0000)
|
|
00128A30 00c0:
|
|
_lights_initialize (0000)
|
|
00128AF0 0010:
|
|
_lights_dispose (0000)
|
|
00128B00 0030:
|
|
_lights_initialize_for_new_map (0000)
|
|
00128B30 0020:
|
|
_lights_dispose_from_old_map (0000)
|
|
00128B50 0010:
|
|
_lights_enable (0000)
|
|
00128B60 0040:
|
|
_light_delete (0000)
|
|
00128BA0 0060:
|
|
_light_build_cluster_array (0000)
|
|
00128C00 00d0:
|
|
_object_get_self_illumination (0000)
|
|
00128CD0 0260:
|
|
_light_particle (0000)
|
|
00128F30 0060:
|
|
_light_disconnect_from_map (0000)
|
|
00128F90 00b0:
|
|
_lights_disconnect_from_structure_bsp (0000)
|
|
00129040 0020:
|
|
_light_attenuation (0000)
|
|
00129060 00a0:
|
|
_brighten_real_rgb_color (0000)
|
|
00129100 0020:
|
|
_cluster_get_first_light (0000)
|
|
00129120 0020:
|
|
_cluster_get_next_light (0000)
|
|
00129140 0040:
|
|
_light_marker_begin (0000)
|
|
00129180 0060:
|
|
_light_unmarked (0000)
|
|
001291E0 0060:
|
|
_light_mark (0000)
|
|
00129240 0040:
|
|
_light_marker_end (0000)
|
|
00129280 0110:
|
|
_render_debug_light (0000)
|
|
00129390 00e0:
|
|
_lights_queue_lens_flare (0000)
|
|
00129470 0230:
|
|
_find_point_lights_for_object_in_cluster (0000)
|
|
001296A0 0400:
|
|
_build_distant_lights (0000)
|
|
00129AA0 00f0:
|
|
_light_compute_bounding_sphere (0000)
|
|
00129B90 00e0:
|
|
_light_get_bounding_sphere (0000)
|
|
00129C70 01d0:
|
|
_lights_render_diffuse (0000)
|
|
00129E40 0150:
|
|
_lights_render_specular (0000)
|
|
00129F90 02d0:
|
|
_lights_illumination_at_point (0000)
|
|
0012A260 0110:
|
|
_lights_prepare_for_object_dynamic (0000)
|
|
0012A370 03b0:
|
|
_lights_distant_lighting_at_point (0000)
|
|
0012A720 0280:
|
|
_light_reconnect_to_map (0000)
|
|
0012A9A0 0060:
|
|
_lights_reconnect_to_structure_bsp (0000)
|
|
0012AA00 00e0:
|
|
_light_new (0000)
|
|
0012AAE0 00f0:
|
|
_light_new_unattached (0000)
|
|
0012ABD0 0960:
|
|
_lights_preprocess_scene (0000)
|
|
0012B530 0340:
|
|
_lights_prepare_for_object_static (0000)
|
|
002896C0 00b0:
|
|
_default_object_lighting (0000)
|
|
00289770 0021:
|
|
??_C@_0CB@NDAECIIM@c?3?2halo?2source?2objects?2objects?4h@ (0000)
|
|
00289798 00b9:
|
|
??_C@_0LJ@HECDDFBP@material?9?$DOlightmap_vertices?4type@ (0000)
|
|
00289854 0027:
|
|
??_C@_0CH@GHJLLMCD@c?3?2halo?2SOURCE?2objects?2object_li@ (0000)
|
|
00289880 0095:
|
|
??_C@_0JF@BFHNCHBA@material?9?$DOvertices?4type?$DN?$DN_raster@ (0000)
|
|
00289918 002c:
|
|
??_C@_0CM@CCFOPHPG@couldn?8t?5allocate?5memory?5for?5obj@ (0000)
|
|
00289944 0014:
|
|
??_C@_0BE@MMBBLMKK@lights_game_globals?$AA@ (0000)
|
|
00289958 000b:
|
|
??_C@_0L@PNIBKHKO@light_data?$AA@ (0000)
|
|
00289964 000f:
|
|
??_C@_0P@MLOLKFEJ@lights?5globals?$AA@ (0000)
|
|
00289974 0007:
|
|
??_C@_06IDBEMGIK@lights?$AA@ (0000)
|
|
0028997C 003b:
|
|
??_C@_0DL@OAOFOGFN@TEST_FLAG?$CIlight?9?$DOflags?0?5_point_l@ (0000)
|
|
002899B8 0023:
|
|
??_C@_0CD@CEANBCDI@?$CBlights_globals?4marker_initializ@ (0000)
|
|
002899DC 0022:
|
|
??_C@_0CC@DMOOLGHL@lights_globals?4marker_initialize@ (0000)
|
|
00289A00 0004:
|
|
__real@3f34fdf4 (0000)
|
|
00289A04 003c:
|
|
??_C@_0DM@NOKGCMAM@?$CBTEST_FLAG?$CIlight?9?$DOflags?0?5_point_@ (0000)
|
|
00289A40 002a:
|
|
??_C@_0CK@JMHDKADE@lens_flare_parameters?4light_iden@ (0000)
|
|
00289A6C 0035:
|
|
??_C@_0DF@MMLEIBDB@light?9?$DOcolor?4blue?5?$DO?$DN0?40f?5?$CG?$CG?5ligh@ (0000)
|
|
00289AA4 0035:
|
|
??_C@_0DF@KFPEGOCE@light?9?$DOcolor?4green?$DO?$DN0?40f?5?$CG?$CG?5ligh@ (0000)
|
|
00289ADC 0033:
|
|
??_C@_0DD@NIPJINKE@light?9?$DOcolor?4red?5?$DO?$DN0?40f?5?$CG?$CG?5light@ (0000)
|
|
00289B10 0004:
|
|
__real@bf3504f3 (0000)
|
|
0030B388 0605:
|
|
_data_0030b388 (0000)
|
|
_object_light_ambient_base (05f8)
|
|
_object_light_ambient_scale (05fc)
|
|
_object_light_secondary_scale (0600)
|
|
_object_light_interpolate (0604)
|
|
00456E94 0004:
|
|
_lights_game_globals (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries/cseries.h"
|
|
#include "cseries/errors.h"
|
|
#include "cseries/profile.h"
|
|
#include "bitmaps/bitmaps.h"
|
|
#include "effects/decals.h"
|
|
#include "math/real_math.h"
|
|
#include "cache/texture_cache.h"
|
|
#include "game/game.h"
|
|
#include "game/game_engine.h"
|
|
#include "memory/data.h"
|
|
#include "objects/light_definitions.h"
|
|
#include "objects/object_lights.h"
|
|
#include "objects/objects.h"
|
|
#include "render/render.h"
|
|
#include "rasterizer/rasterizer_geometry.h"
|
|
#include "saved games/game_state.h"
|
|
#include "scenario/scenario.h"
|
|
#include "structures/cluster_partitions.h"
|
|
#include "tag_files/tag_groups.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
_light_definition_dynamic_bit = 0,
|
|
_light_definition_no_specular_bit,
|
|
_light_definition_dont_light_own_object_bit,
|
|
_light_definition_supersize_in_first_person_bit,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_point_light_dynamic_bit = 0,
|
|
_point_light_connects_to_map_bit = 1,
|
|
_point_light_connected_to_map_bit = 2,
|
|
};
|
|
|
|
enum
|
|
{
|
|
LENS_FLARE_DEFINITION_TAG = 'lens',
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
#define light_get(index) \
|
|
((struct light_datum *)datum_get(light_data, (index)))
|
|
|
|
#define light_definition_get(index) \
|
|
((struct light_definition *)tag_get(LIGHT_DEFINITION_TAG, (index)))
|
|
|
|
#define lens_flare_definition_get(index) \
|
|
((struct lens_flare_definition *)tag_get(LENS_FLARE_DEFINITION_TAG, (index)))
|
|
|
|
/* ---------- structures */
|
|
|
|
struct lights_game_globals
|
|
{
|
|
boolean render_lights;
|
|
byte reserved01[3];
|
|
};
|
|
|
|
struct light_definition
|
|
{
|
|
long flags;
|
|
real radius;
|
|
real radius_modifier_lower_bound;
|
|
real radius_modifier_upper_bound;
|
|
real falloff_angle;
|
|
real cutoff_angle;
|
|
real lens_flare_radius;
|
|
real runtime_cosine_falloff_angle;
|
|
real runtime_cosine_cutoff_angle;
|
|
real specular_radius_multiplier;
|
|
real runtime_sine_cutoff_angle;
|
|
byte reserved2C[0x80];
|
|
struct tag_reference lens_flare;
|
|
};
|
|
|
|
struct light_datum
|
|
{
|
|
struct datum_header header;
|
|
unsigned short flags;
|
|
long definition_index;
|
|
long rasterizer_light_index;
|
|
long marker;
|
|
long cluster_reference;
|
|
real_rgb_color current_color;
|
|
byte reserved20[0xC];
|
|
long object_index;
|
|
real_point3d position;
|
|
real_vector3d forward;
|
|
real_vector3d up;
|
|
real radius;
|
|
long parent_light_index;
|
|
short attachment_marker_index;
|
|
short function_index;
|
|
union
|
|
{
|
|
short color_function_index;
|
|
struct
|
|
{
|
|
real_point3d relative_position;
|
|
real_vector3d relative_forward;
|
|
} node;
|
|
};
|
|
real intensity_scale;
|
|
};
|
|
|
|
struct rasterizer_lens_flare_submit_parameters
|
|
{
|
|
struct lens_flare_definition *definition;
|
|
real_point3d position;
|
|
unsigned long compressed_direction;
|
|
unsigned long compressed_up;
|
|
unsigned long compressed_light_color;
|
|
short light_identifier;
|
|
short light_index;
|
|
short lens_flare_index;
|
|
byte compressed_window_index;
|
|
byte compressed_light_scale;
|
|
long internal_occlusion_pixels;
|
|
};
|
|
|
|
struct lights_globals
|
|
{
|
|
boolean marker_initialized;
|
|
byte pad1[3];
|
|
long marker;
|
|
short scene_point_light_count;
|
|
short padA;
|
|
long scene_point_lights[128];
|
|
struct rasterizer_lens_flare_submit_parameters queued_lens_flares[8];
|
|
short queued_lens_flare_count;
|
|
short pad34E;
|
|
};
|
|
|
|
typedef char verify_lights_game_globals_size[
|
|
sizeof(struct lights_game_globals) == 0x4 ? 1 : -1];
|
|
typedef char verify_light_datum_flags_offset[
|
|
offsetof(struct light_datum, flags) == 0x2 ? 1 : -1];
|
|
typedef char verify_light_datum_cluster_reference_offset[
|
|
offsetof(struct light_datum, cluster_reference) == 0x10 ? 1 : -1];
|
|
typedef char verify_light_definition_lens_flare_offset[
|
|
offsetof(struct light_definition, lens_flare) == 0xAC ? 1 : -1];
|
|
typedef char verify_light_datum_size[
|
|
sizeof(struct light_datum) == 0x7C ? 1 : -1];
|
|
typedef char verify_lights_globals_size[
|
|
sizeof(struct lights_globals) == 0x350 ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static boolean light_unmarked(
|
|
long light_index);
|
|
static void find_point_lights_for_object_in_cluster(
|
|
long object_index,
|
|
short cluster_index,
|
|
real_point3d const *center,
|
|
real radius,
|
|
long *light_indices,
|
|
real *light_intensities,
|
|
real *light_attenuations,
|
|
short *light_count,
|
|
short maximum_light_count);
|
|
static void light_compute_bounding_sphere(
|
|
long light_index,
|
|
boolean maximum,
|
|
boolean specular,
|
|
boolean lens_flare_only,
|
|
real_point3d *position,
|
|
real *radius);
|
|
|
|
/* ---------- globals */
|
|
|
|
extern struct data_array *light_data;
|
|
extern struct cluster_partition light_cluster_partition;
|
|
extern struct lights_game_globals *lights_game_globals;
|
|
static struct lights_globals lights_globals;
|
|
|
|
/* ---------- public code */
|
|
|
|
void *texture_cache_bitmap_load(
|
|
struct bitmap_data *bitmap)
|
|
{
|
|
void *hardware_format;
|
|
|
|
profile_texture_start();
|
|
hardware_format = _texture_cache_bitmap_get_hardware_format(
|
|
bitmap,
|
|
TRUE,
|
|
TRUE);
|
|
profile_texture_end();
|
|
|
|
return hardware_format;
|
|
}
|
|
|
|
void lights_initialize(
|
|
void)
|
|
{
|
|
light_data = game_state_data_new(
|
|
"lights",
|
|
MAXIMUM_LIGHTS_PER_MAP,
|
|
sizeof(struct light_datum));
|
|
lights_game_globals = game_state_malloc(
|
|
"lights globals",
|
|
NULL,
|
|
sizeof(struct lights_game_globals));
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0xC2,
|
|
light_data);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0xC3,
|
|
lights_game_globals);
|
|
lights_game_globals->render_lights = TRUE;
|
|
if (light_data)
|
|
{
|
|
cluster_partition_new(&light_cluster_partition, "light");
|
|
}
|
|
else
|
|
{
|
|
error(_error_silent, "couldn't allocate memory for object lights.");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_dispose(
|
|
void)
|
|
{
|
|
cluster_partition_delete(&light_cluster_partition);
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_initialize_for_new_map(
|
|
void)
|
|
{
|
|
data_make_valid(light_data);
|
|
lights_game_globals->render_lights = TRUE;
|
|
cluster_partition_make_valid(&light_cluster_partition);
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_dispose_from_old_map(
|
|
void)
|
|
{
|
|
data_make_invalid(light_data);
|
|
cluster_partition_make_invalid(&light_cluster_partition);
|
|
|
|
return;
|
|
}
|
|
|
|
boolean lights_enable(
|
|
boolean enable)
|
|
{
|
|
lights_game_globals->render_lights = enable;
|
|
|
|
return enable;
|
|
}
|
|
|
|
long light_new(
|
|
long definition_index,
|
|
long object_index,
|
|
short object_attachment_index,
|
|
short object_function_index,
|
|
short object_change_color_index)
|
|
{
|
|
struct light_definition *definition = light_definition_get(definition_index);
|
|
long light_index = NONE;
|
|
|
|
if (TEST_FLAG(definition->flags, _light_definition_dynamic_bit)
|
|
|| definition->lens_flare.index != NONE)
|
|
{
|
|
light_index = datum_new(light_data);
|
|
if (light_index != NONE)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
|
|
light->definition_index = definition_index;
|
|
light->object_index = object_index;
|
|
light->attachment_marker_index = object_attachment_index;
|
|
light->function_index = object_function_index;
|
|
light->color_function_index = object_change_color_index;
|
|
light->flags = 0;
|
|
SET_FLAG(light->flags, _point_light_dynamic_bit,
|
|
TEST_FLAG(definition->flags, _light_definition_dynamic_bit));
|
|
SET_FLAG(light->flags, _point_light_connects_to_map_bit,
|
|
TEST_FLAG(light->flags, _point_light_dynamic_bit)
|
|
|| definition->lens_flare.index != NONE);
|
|
light->cluster_reference = NONE;
|
|
light->parent_light_index = NONE;
|
|
light_reconnect_to_map(light_index);
|
|
light->marker = lights_globals.marker - 1;
|
|
}
|
|
}
|
|
|
|
return light_index;
|
|
}
|
|
|
|
long light_new_unattached(
|
|
long definition_index,
|
|
long object_index,
|
|
short object_node_index,
|
|
real_point3d const *position,
|
|
real_vector3d const *direction,
|
|
real scale)
|
|
{
|
|
long light_index = datum_new(light_data);
|
|
|
|
if (light_index != NONE)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
struct light_definition *definition = light_definition_get(definition_index);
|
|
|
|
light->flags = 0;
|
|
light->parent_light_index = game_time_get();
|
|
light->definition_index = definition_index;
|
|
light->object_index = object_index;
|
|
light->intensity_scale = scale;
|
|
light->cluster_reference = NONE;
|
|
SET_FLAG(light->flags, _point_light_dynamic_bit, TRUE);
|
|
SET_FLAG(light->flags, _point_light_connects_to_map_bit, TRUE);
|
|
if (object_index == NONE)
|
|
{
|
|
light->position = *position;
|
|
light->forward = *direction;
|
|
}
|
|
else
|
|
{
|
|
light->attachment_marker_index = object_node_index;
|
|
light->node.relative_position = *position;
|
|
light->node.relative_forward = *direction;
|
|
}
|
|
light_reconnect_to_map(light_index);
|
|
light->marker = lights_globals.marker - 1;
|
|
}
|
|
|
|
return light_index;
|
|
}
|
|
|
|
void light_delete(
|
|
long light_index)
|
|
{
|
|
struct light_datum *light = datum_get(light_data, light_index);
|
|
|
|
cluster_partition_disconnect(
|
|
&light_cluster_partition,
|
|
light_index,
|
|
&light->cluster_reference);
|
|
datum_delete(light_data, light_index);
|
|
|
|
return;
|
|
}
|
|
|
|
real object_get_self_illumination(
|
|
long object_index)
|
|
{
|
|
struct object_datum *object = object_get(object_index);
|
|
struct object_definition *definition = object_definition_get(object->definition_index);
|
|
short attachment_index = 0;
|
|
real illumination = 0.0f;
|
|
|
|
if (definition->object.attachments.count > 0)
|
|
{
|
|
do
|
|
{
|
|
if (object->object.attachment_types[attachment_index] == _object_attachment_type_light
|
|
&& object->object.attachment_indices[attachment_index] != NONE)
|
|
{
|
|
struct light_datum *light = light_get(object->object.attachment_indices[attachment_index]);
|
|
illumination += real_rgb_color_brightness(&light->current_color);
|
|
}
|
|
attachment_index++;
|
|
}
|
|
while (attachment_index < definition->object.attachments.count);
|
|
}
|
|
|
|
if (object->object.first_child_object_index != NONE)
|
|
{
|
|
illumination += object_get_self_illumination(object->object.first_child_object_index);
|
|
}
|
|
if (object->object.next_object_index != NONE)
|
|
{
|
|
illumination += object_get_self_illumination(object->object.next_object_index);
|
|
}
|
|
|
|
return illumination;
|
|
}
|
|
|
|
void lights_queue_lens_flare(
|
|
long lens_flare_definition_index,
|
|
real_point3d const *position,
|
|
real_vector3d const *direction,
|
|
real_vector3d const *up,
|
|
real_rgb_color const *color,
|
|
real scale)
|
|
{
|
|
if (lights_globals.queued_lens_flare_count < MAXIMUM_QUEUED_LENS_FLARES
|
|
&& (color->red != 0.0f || color->green != 0.0f || color->blue != 0.0f))
|
|
{
|
|
struct rasterizer_lens_flare_submit_parameters *lens_flare_parameters =
|
|
&lights_globals.queued_lens_flares[lights_globals.queued_lens_flare_count];
|
|
|
|
lens_flare_parameters->compressed_light_color = real_a_rgb_color_to_pixel32(1.0f, color);
|
|
lens_flare_parameters->compressed_light_scale = compress_real_to_int8(scale);
|
|
lens_flare_parameters->definition = lens_flare_definition_get(lens_flare_definition_index);
|
|
lens_flare_parameters->position = *position;
|
|
lens_flare_parameters->compressed_direction = compress_real_vector3d_to_int32_clamp(direction);
|
|
lens_flare_parameters->compressed_up = compress_real_vector3d_to_int32_clamp(up);
|
|
lens_flare_parameters->compressed_window_index = (byte)render.window_index;
|
|
lens_flare_parameters->light_index = NONE;
|
|
lens_flare_parameters->light_identifier = NONE;
|
|
lens_flare_parameters->lens_flare_index = lights_globals.queued_lens_flare_count;
|
|
lights_globals.queued_lens_flare_count++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void light_disconnect_from_map(
|
|
long light_index)
|
|
{
|
|
struct light_datum *light = datum_get(light_data, light_index);
|
|
|
|
if (TEST_FLAG(light->flags, _point_light_connects_to_map_bit))
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x4D0,
|
|
TEST_FLAG(light->flags, _point_light_connected_to_map_bit));
|
|
cluster_partition_disconnect(
|
|
&light_cluster_partition,
|
|
light_index,
|
|
&light->cluster_reference);
|
|
SET_FLAG(light->flags, _point_light_connected_to_map_bit, FALSE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_disconnect_from_structure_bsp(
|
|
void)
|
|
{
|
|
long light_index;
|
|
|
|
for (light_index = data_next_index(light_data, NONE);
|
|
light_index != NONE;
|
|
light_index = data_next_index(light_data, light_index))
|
|
{
|
|
struct light_datum *light = datum_get(light_data, light_index);
|
|
|
|
if (TEST_FLAG(light->flags, _point_light_connected_to_map_bit))
|
|
{
|
|
light_disconnect_from_map(light_index);
|
|
SET_FLAG(light->flags, _point_light_connected_to_map_bit, TRUE);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_reconnect_to_structure_bsp(
|
|
void)
|
|
{
|
|
long light_index;
|
|
|
|
for (light_index = data_next_index(light_data, NONE);
|
|
light_index != NONE;
|
|
light_index = data_next_index(light_data, light_index))
|
|
{
|
|
struct light_datum *light = datum_get(light_data, light_index);
|
|
|
|
if (TEST_FLAG(light->flags, _point_light_connected_to_map_bit))
|
|
{
|
|
SET_FLAG(light->flags, _point_light_connected_to_map_bit, FALSE);
|
|
light_reconnect_to_map(light_index);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void light_marker_begin(
|
|
void)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x664,
|
|
!lights_globals.marker_initialized);
|
|
lights_globals.marker++;
|
|
lights_globals.marker_initialized = TRUE;
|
|
|
|
return;
|
|
}
|
|
|
|
static boolean light_mark(
|
|
long light_index)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x67F,
|
|
lights_globals.marker_initialized);
|
|
if (light->marker != lights_globals.marker)
|
|
{
|
|
light->marker = lights_globals.marker;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static boolean light_unmarked(
|
|
long light_index)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x66F,
|
|
lights_globals.marker_initialized);
|
|
|
|
return lights_globals.marker != light->marker;
|
|
}
|
|
|
|
static void light_marker_end(
|
|
void)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x68E,
|
|
lights_globals.marker_initialized);
|
|
lights_globals.marker_initialized = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
real light_attenuation(
|
|
real radius,
|
|
real distance)
|
|
{
|
|
return 1.0f - (distance * distance) / (radius * radius);
|
|
}
|
|
|
|
long cluster_get_first_light(
|
|
long *reference_index,
|
|
short cluster_index)
|
|
{
|
|
return cluster_partition_get_first_datum(
|
|
&light_cluster_partition,
|
|
reference_index,
|
|
cluster_index);
|
|
}
|
|
|
|
long cluster_get_next_light(
|
|
long *reference_index)
|
|
{
|
|
return cluster_partition_get_next_datum(
|
|
&light_cluster_partition,
|
|
reference_index);
|
|
}
|
|
|
|
static void light_compute_bounding_sphere(
|
|
long light_index,
|
|
boolean maximum,
|
|
boolean specular,
|
|
boolean lens_flare_only,
|
|
real_point3d *position,
|
|
real *radius)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
struct light_definition *definition = light_definition_get(light->definition_index);
|
|
real light_radius = maximum
|
|
? definition->radius_modifier_upper_bound * definition->radius
|
|
: light->radius;
|
|
|
|
if (!TEST_FLAG(definition->flags, _light_definition_no_specular_bit)
|
|
&& (specular || maximum))
|
|
{
|
|
light_radius *= definition->specular_radius_multiplier;
|
|
}
|
|
|
|
if (lens_flare_only && light_radius < definition->lens_flare_radius)
|
|
{
|
|
*position = light->position;
|
|
*radius = definition->lens_flare_radius;
|
|
}
|
|
else if (definition->cutoff_angle >= _pi / 2)
|
|
{
|
|
*position = light->position;
|
|
*radius = light_radius;
|
|
}
|
|
else if (definition->cutoff_angle >= _pi / 4)
|
|
{
|
|
*radius = light_radius * definition->runtime_sine_cutoff_angle;
|
|
light_radius *= definition->runtime_cosine_cutoff_angle;
|
|
position->x = light_radius * light->forward.i + light->position.x;
|
|
position->y = light_radius * light->forward.j + light->position.y;
|
|
position->z = light_radius * light->forward.k + light->position.z;
|
|
}
|
|
else
|
|
{
|
|
light_radius /= definition->runtime_cosine_cutoff_angle;
|
|
*radius = light_radius;
|
|
position->x = light_radius * light->forward.i + light->position.x;
|
|
position->y = light_radius * light->forward.j + light->position.y;
|
|
position->z = light_radius * light->forward.k + light->position.z;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void light_reconnect_to_map(
|
|
long light_index)
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
struct object_marker markers[1];
|
|
struct location location;
|
|
real_point3d position;
|
|
real radius;
|
|
|
|
if (light->parent_light_index == NONE)
|
|
{
|
|
object_get_marker_by_name(
|
|
light->object_index,
|
|
object_get_attachment_marker_name(light->object_index, light->attachment_marker_index),
|
|
markers,
|
|
1);
|
|
light->position = markers[0].matrix.position;
|
|
light->forward = markers[0].matrix.forward;
|
|
light->up = markers[0].matrix.up;
|
|
}
|
|
else if (object_try_and_get(light->object_index))
|
|
{
|
|
real_matrix4x3 *node_matrix = object_get_node_matrix(light->object_index, light->attachment_marker_index);
|
|
|
|
matrix4x3_transform_point(node_matrix, &light->node.relative_position, &light->position);
|
|
matrix4x3_transform_normal(node_matrix, &light->node.relative_forward, &light->forward);
|
|
perpendicular3d(&light->forward, &light->up);
|
|
normalize3d(&light->up);
|
|
}
|
|
|
|
if (TEST_FLAG(light->flags, _point_light_connects_to_map_bit))
|
|
{
|
|
light_compute_bounding_sphere(
|
|
light_index,
|
|
TRUE,
|
|
FALSE,
|
|
TRUE,
|
|
&position,
|
|
&radius);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x4F9,
|
|
!TEST_FLAG(light->flags, _point_light_connected_to_map_bit));
|
|
if (light->object_index != NONE && object_try_and_get(light->object_index))
|
|
{
|
|
object_get_location(light->object_index, &location);
|
|
}
|
|
else
|
|
{
|
|
scenario_location_from_point(&location, &position);
|
|
}
|
|
cluster_partition_reconnect(
|
|
&light_cluster_partition,
|
|
light_index,
|
|
&light->cluster_reference,
|
|
&position,
|
|
radius,
|
|
&location);
|
|
SET_FLAG(light->flags, _point_light_connected_to_map_bit, TRUE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void find_point_lights_for_object_in_cluster(
|
|
long object_index,
|
|
short cluster_index,
|
|
real_point3d const *center,
|
|
real radius,
|
|
long *light_indices,
|
|
real *light_intensities,
|
|
real *light_attenuations,
|
|
short *light_count,
|
|
short maximum_light_count)
|
|
{
|
|
long light_index;
|
|
long reference_index;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\objects\\object_lights.c",
|
|
0x544,
|
|
lights_globals.marker_initialized);
|
|
for (light_index = cluster_partition_get_first_datum(&light_cluster_partition, &reference_index, cluster_index);
|
|
light_index != NONE;
|
|
light_index = cluster_partition_get_next_datum(&light_cluster_partition, &reference_index))
|
|
{
|
|
if (light_unmarked(light_index))
|
|
{
|
|
struct light_datum *light = light_get(light_index);
|
|
|
|
if (light->rasterizer_light_index != NONE
|
|
&& (light->object_index != object_index
|
|
|| !TEST_FLAG(light_definition_get(light->definition_index)->flags,
|
|
_light_definition_dont_light_own_object_bit)))
|
|
{
|
|
real_point3d const *light_position = &light->position;
|
|
real distance = distance3d(light_position, center);
|
|
|
|
if (distance < radius + light->radius)
|
|
{
|
|
real attenuation = light_attenuation(light->radius, distance);
|
|
real intensity = real_rgb_color_brightness(&light->current_color) * attenuation;
|
|
short index;
|
|
|
|
if (*light_count < maximum_light_count)
|
|
{
|
|
index = (*light_count)++;
|
|
}
|
|
else
|
|
{
|
|
real minimum_intensity = REAL_MAX;
|
|
short dimmest_index = NONE;
|
|
|
|
for (index = 0; index < *light_count; index++)
|
|
{
|
|
if (minimum_intensity > light_intensities[index])
|
|
{
|
|
minimum_intensity = light_intensities[index];
|
|
dimmest_index = index;
|
|
}
|
|
}
|
|
|
|
if (minimum_intensity < intensity)
|
|
{
|
|
index = dimmest_index;
|
|
}
|
|
}
|
|
|
|
if (index < maximum_light_count)
|
|
{
|
|
light_indices[index] = light_index;
|
|
light_intensities[index] = intensity;
|
|
light_attenuations[index] = attenuation;
|
|
}
|
|
}
|
|
}
|
|
light_mark(light_index);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void lights_prepare_for_object_dynamic(
|
|
long object_index,
|
|
struct render_lighting *lighting)
|
|
{
|
|
struct object_cluster_iterator iterator;
|
|
real_point3d center;
|
|
real radius;
|
|
real light_intensities[MAXIMUM_RENDERED_POINT_LIGHTS];
|
|
real light_attenuations[MAXIMUM_RENDERED_POINT_LIGHTS];
|
|
short cluster_index;
|
|
short light_index;
|
|
|
|
object_get_bounding_sphere(object_index, ¢er, &radius);
|
|
lighting->point_light_count = 0;
|
|
light_marker_begin();
|
|
for (cluster_index = object_get_first_cluster(&iterator, object_index);
|
|
cluster_index != NONE;
|
|
cluster_index = object_get_next_cluster(&iterator, object_index))
|
|
{
|
|
find_point_lights_for_object_in_cluster(
|
|
object_index,
|
|
cluster_index,
|
|
¢er,
|
|
radius,
|
|
lighting->point_light_indices,
|
|
light_intensities,
|
|
light_attenuations,
|
|
&lighting->point_light_count,
|
|
MAXIMUM_RENDERED_POINT_LIGHTS);
|
|
}
|
|
light_marker_end();
|
|
for (light_index = 0; light_index < lighting->point_light_count; light_index++)
|
|
{
|
|
lighting->point_light_indices[light_index] =
|
|
light_get(lighting->point_light_indices[light_index])->rasterizer_light_index;
|
|
}
|
|
|
|
return;
|
|
}
|