mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-18 15:00:26 +02:00
561 lines
18 KiB
C
561 lines
18 KiB
C
/*
|
|
LIGHTNING.C
|
|
|
|
symbols in this file:
|
|
00124B70 0040:
|
|
_lightnings_initialize (0000)
|
|
00124BB0 0010:
|
|
_lightnings_dispose (0000)
|
|
00124BC0 0020:
|
|
_lightnings_initialize_for_new_map (0000)
|
|
00124BE0 0020:
|
|
_lightnings_dispose_from_old_map (0000)
|
|
00124C00 0040:
|
|
_lightning_new (0000)
|
|
00124C40 0020:
|
|
_lightning_delete (0000)
|
|
00124C60 0010:
|
|
_lightning_render (0000)
|
|
00124C70 00f0:
|
|
_lightning_offset_marker_position (0000)
|
|
00124D60 0a10:
|
|
_lightning_submit (0000)
|
|
00289208 0021:
|
|
??_C@_0CB@BNDAIAGI@lightning_globals?4lightning_data@ (0000)
|
|
0028922C 002b:
|
|
??_C@_0CL@PEKNBFKF@c?3?2halo?2SOURCE?2objects?2widgets?2l@ (0000)
|
|
00289258 000b:
|
|
??_C@_0L@PEMAMKLL@lightnings?$AA@ (0000)
|
|
00289264 0017:
|
|
??_C@_0BH@PECODGGH@random_position_bounds?$AA@ (0000)
|
|
0028927C 001b:
|
|
??_C@_0BL@JLLGKOIH@points?$FLvertex_index?$FN?4valid?$AA@ (0000)
|
|
00289298 002f:
|
|
??_C@_0CP@DDEILNHB@?$CBpoints?$FLpoint_count?$CLsegment_poin@ (0000)
|
|
002892C8 001c:
|
|
??_C@_0BM@GBNGDLFN@segment_point_start_index?$DO0?$AA@ (0000)
|
|
002892E4 002f:
|
|
??_C@_0CP@ODBOIENA@?$CBpoints?$FLpoint_count?$CLsegment_poin@ (0000)
|
|
00456E44 0004:
|
|
_lightning_globals (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "objects/widgets/lightning.h"
|
|
|
|
#include "bitmaps/bitmap_group.h"
|
|
#include "cache/texture_cache.h"
|
|
#include "cseries/cseries.h"
|
|
#include "interface/hud_draw.h"
|
|
#include "math/real_math.h"
|
|
#include "objects/objects.h"
|
|
#include "rasterizer/rasterizer.h"
|
|
#include "rasterizer/rasterizer_geometry.h"
|
|
#include "render/render.h"
|
|
#include "saved games/game_state.h"
|
|
#include "shaders/shader_definitions.h"
|
|
#include "shaders/shaders.h"
|
|
#include "tag_files/tag_groups.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
LIGHTNING_TAG = 'elec',
|
|
MAXIMUM_LIGHTNING_POINTS = 4097,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_lightning_marker_not_connected_to_next_marker_bit = 0,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_rasterizer_lock_none = 0,
|
|
_rasterizer_lock_lightning = 12,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
#define lightning_definition_get(definition_index) \
|
|
((struct lightning_definition *)tag_get(LIGHTNING_TAG, (definition_index)))
|
|
|
|
/* ---------- structures */
|
|
|
|
struct lightning_marker_definition
|
|
{
|
|
char attachment_marker[32];
|
|
word flags;
|
|
short type;
|
|
short octaves_to_next_marker;
|
|
word pad26;
|
|
byte reserved28[0x4C];
|
|
real_vector3d random_position_bounds;
|
|
real random_jitter_offset;
|
|
real thickness;
|
|
real_argb_color tint;
|
|
byte reserved98[0x4C];
|
|
};
|
|
|
|
struct lightning_definition
|
|
{
|
|
word flags;
|
|
short count;
|
|
byte reserved04[0x10];
|
|
real near_fade_distance;
|
|
real far_fade_distance;
|
|
byte reserved1C[0x10];
|
|
short jitter_scale_source;
|
|
short thickness_scale_source;
|
|
short tint_modulation_source;
|
|
short brightness_scale_source;
|
|
struct tag_reference map;
|
|
byte reserved44[0x54];
|
|
struct tag_block markers;
|
|
struct tag_block shaders;
|
|
byte reservedB0[0x58];
|
|
};
|
|
|
|
struct intermediate_lightning_point
|
|
{
|
|
real_point3d position;
|
|
real width;
|
|
real_argb_color color;
|
|
boolean valid;
|
|
byte pad21[3];
|
|
};
|
|
|
|
struct lightning_vertex
|
|
{
|
|
real_point3d point;
|
|
real_point2d texture;
|
|
pixel32 color;
|
|
};
|
|
|
|
typedef char lightning_marker_definition_size_assert[
|
|
sizeof(struct lightning_marker_definition) == 0xE4 ? 1 : -1];
|
|
typedef char lightning_definition_size_assert[
|
|
sizeof(struct lightning_definition) == 0x108 ? 1 : -1];
|
|
typedef char intermediate_lightning_point_size_assert[
|
|
sizeof(struct intermediate_lightning_point) == 0x24 ? 1 : -1];
|
|
typedef char lightning_vertex_size_assert[
|
|
sizeof(struct lightning_vertex) == 0x18 ? 1 : -1];
|
|
typedef char lightning_marker_definition_random_position_bounds_offset_assert[
|
|
offsetof(struct lightning_marker_definition, random_position_bounds) == 0x74 ? 1 : -1];
|
|
typedef char lightning_marker_definition_thickness_offset_assert[
|
|
offsetof(struct lightning_marker_definition, thickness) == 0x84 ? 1 : -1];
|
|
typedef char lightning_definition_jitter_scale_source_offset_assert[
|
|
offsetof(struct lightning_definition, jitter_scale_source) == 0x2C ? 1 : -1];
|
|
typedef char lightning_definition_map_offset_assert[
|
|
offsetof(struct lightning_definition, map) == 0x34 ? 1 : -1];
|
|
typedef char lightning_definition_markers_offset_assert[
|
|
offsetof(struct lightning_definition, markers) == 0x98 ? 1 : -1];
|
|
typedef char lightning_definition_shaders_offset_assert[
|
|
offsetof(struct lightning_definition, shaders) == 0xA4 ? 1 : -1];
|
|
typedef char intermediate_lightning_point_valid_offset_assert[
|
|
offsetof(struct intermediate_lightning_point, valid) == 0x20 ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static void lightning_offset_marker_position(
|
|
real_point3d *position,
|
|
real_matrix4x3 const *matrix,
|
|
real_vector3d const *random_position_bounds);
|
|
|
|
/* ---------- globals */
|
|
|
|
struct lightning_globals lightning_globals = {0};
|
|
|
|
/* ---------- public code */
|
|
|
|
void lightnings_initialize(
|
|
void)
|
|
{
|
|
lightning_globals.lightning_data = game_state_data_new("lightnings", 256, 8);
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 50, lightning_globals.lightning_data);
|
|
|
|
return;
|
|
}
|
|
|
|
void lightnings_dispose(
|
|
void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void lightnings_initialize_for_new_map(
|
|
void)
|
|
{
|
|
if (lightning_globals.lightning_data)
|
|
data_make_valid(lightning_globals.lightning_data);
|
|
|
|
return;
|
|
}
|
|
|
|
void lightnings_dispose_from_old_map(
|
|
void)
|
|
{
|
|
if (lightning_globals.lightning_data)
|
|
data_make_invalid(lightning_globals.lightning_data);
|
|
|
|
return;
|
|
}
|
|
|
|
long lightning_new(
|
|
long definition_index)
|
|
{
|
|
long lightning_index = datum_new(lightning_globals.lightning_data);
|
|
|
|
if (lightning_index != NONE)
|
|
lightning_get(lightning_index)->definition_index = definition_index;
|
|
|
|
return lightning_index;
|
|
}
|
|
|
|
void lightning_delete(
|
|
long lightning_index)
|
|
{
|
|
if (lightning_index != NONE)
|
|
datum_delete(lightning_globals.lightning_data, lightning_index);
|
|
|
|
return;
|
|
}
|
|
|
|
void lightning_render(
|
|
void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static void lightning_offset_marker_position(
|
|
real_point3d *position,
|
|
real_matrix4x3 const *matrix,
|
|
real_vector3d const *random_position_bounds)
|
|
{
|
|
real random_x;
|
|
real random_y;
|
|
real random_z;
|
|
real_vector3d offset;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 116, position);
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 117, matrix);
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 118, random_position_bounds);
|
|
|
|
random_z = real_seed_random(get_global_local_random_seed_address());
|
|
random_y = real_seed_random(get_global_local_random_seed_address());
|
|
random_x = real_seed_random(get_global_local_random_seed_address());
|
|
|
|
offset.i = (2.f*random_x - 1.f)*random_position_bounds->i;
|
|
offset.j = (2.f*random_y - 1.f)*random_position_bounds->j;
|
|
offset.k = (2.f*random_z - 1.f)*random_position_bounds->k;
|
|
matrix4x3_transform_vector(matrix, &offset, &offset);
|
|
|
|
position->x += offset.i;
|
|
position->y += offset.j;
|
|
position->z += offset.k;
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- public code */
|
|
|
|
void lightning_submit(
|
|
long object_index,
|
|
long lightning_index,
|
|
struct render_lighting const *lighting,
|
|
struct render_animation const *animation)
|
|
{
|
|
(void)lighting;
|
|
if (object_index != NONE && lightning_index != NONE)
|
|
{
|
|
struct lightning_datum *lightning = lightning_get(lightning_index);
|
|
struct lightning_definition *definition = lightning_definition_get(lightning->definition_index);
|
|
struct object_marker marker;
|
|
|
|
if (definition->markers.count > 0 &&
|
|
object_get_marker_by_name(
|
|
object_index,
|
|
TAG_BLOCK_GET_ELEMENT(&definition->markers, 0, struct lightning_marker_definition)->attachment_marker,
|
|
&marker,
|
|
1) > 0)
|
|
{
|
|
struct bitmap_data *bitmap = TAG_BLOCK_GET_ELEMENT(
|
|
&bitmap_group_get(definition->map.index)->bitmap_data,
|
|
0,
|
|
struct bitmap_data);
|
|
|
|
if (_texture_cache_bitmap_get_hardware_format(bitmap, FALSE, TRUE))
|
|
{
|
|
struct intermediate_lightning_point points[MAXIMUM_LIGHTNING_POINTS];
|
|
short instance_index;
|
|
|
|
for (instance_index = 0; instance_index < definition->count; instance_index++)
|
|
{
|
|
short point_count = 0;
|
|
real jitter_scale = 1.f;
|
|
boolean first_marker = TRUE;
|
|
short marker_index;
|
|
|
|
if (animation)
|
|
{
|
|
if (animation->values)
|
|
{
|
|
short source = definition->jitter_scale_source;
|
|
if (source >= _object_function_reference_a && source <= _object_function_reference_d)
|
|
jitter_scale = animation->values[source - 1];
|
|
}
|
|
}
|
|
|
|
for (marker_index = 0; marker_index < definition->markers.count; marker_index++)
|
|
{
|
|
struct lightning_marker_definition *marker_definition = TAG_BLOCK_GET_ELEMENT(
|
|
&definition->markers,
|
|
marker_index,
|
|
struct lightning_marker_definition);
|
|
|
|
if (first_marker)
|
|
{
|
|
point_count = 0;
|
|
csmemset(points, 0, sizeof(points));
|
|
object_get_marker_by_name(object_index, marker_definition->attachment_marker, &marker, 1);
|
|
points[0].position = marker.matrix.position;
|
|
lightning_offset_marker_position(
|
|
&points[0].position,
|
|
&marker.matrix,
|
|
&marker_definition->random_position_bounds);
|
|
points[0].width = marker_definition->thickness;
|
|
points[0].color = marker_definition->tint;
|
|
points[0].valid = TRUE;
|
|
first_marker = FALSE;
|
|
}
|
|
|
|
if (TEST_FLAG(marker_definition->flags, _lightning_marker_not_connected_to_next_marker_bit) ||
|
|
marker_index == definition->markers.count - 1)
|
|
{
|
|
rasterizer_globals.current_lock_operation = _rasterizer_lock_lightning;
|
|
if (point_count > 2)
|
|
{
|
|
long vertex_buffer_index;
|
|
|
|
point_count++;
|
|
vertex_buffer_index = rasterizer_dynamic_vertices_new(
|
|
_rasterizer_vertex_type_dynamic_unlit,
|
|
2*point_count);
|
|
if (vertex_buffer_index != NONE)
|
|
{
|
|
struct lightning_vertex *vertices = rasterizer_dynamic_vertices_lock(vertex_buffer_index);
|
|
real one_over_point_count = 1.f/point_count;
|
|
real u_offset = real_seed_random(get_global_local_random_seed_address());
|
|
real thickness_scale = 1.f;
|
|
real_rgb_color const *tint = global_real_rgb_white;
|
|
real brightness_scale = 1.f;
|
|
real_rectangle3d bounds;
|
|
real_point3d centroid;
|
|
struct shader const *shader;
|
|
short vertex_index;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 239, vertices);
|
|
|
|
if (animation)
|
|
{
|
|
if (animation->values)
|
|
{
|
|
short source = definition->thickness_scale_source;
|
|
if (source >= _object_function_reference_a && source <= _object_function_reference_d)
|
|
thickness_scale = animation->values[source - 1];
|
|
}
|
|
if (animation->colors)
|
|
{
|
|
short source = definition->tint_modulation_source;
|
|
if (source >= _object_function_reference_a && source <= _object_function_reference_d)
|
|
tint = &animation->colors[source - 1];
|
|
}
|
|
if (animation->values)
|
|
{
|
|
short source = definition->brightness_scale_source;
|
|
if (source >= _object_function_reference_a && source <= _object_function_reference_d)
|
|
brightness_scale = animation->values[source - 1];
|
|
}
|
|
}
|
|
|
|
for (vertex_index = 0; vertex_index < point_count; vertex_index++)
|
|
{
|
|
real_point3d *position = &points[vertex_index].position;
|
|
real_point3d *previous_position = vertex_index > 0 ? &points[vertex_index - 1].position : position;
|
|
real_point3d *next_position = vertex_index < point_count - 1 ? &points[vertex_index + 1].position : position;
|
|
real width = points[vertex_index].width*thickness_scale;
|
|
real u = vertex_index*one_over_point_count;
|
|
real_vector3d up;
|
|
real_argb_color color;
|
|
pixel32 pixel;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 280, points[vertex_index].valid);
|
|
|
|
vector_from_points3d(previous_position, next_position, &up);
|
|
cross_product3d(&up, &render.camera.forward, &up);
|
|
fast_normalize3d(&up);
|
|
|
|
color.alpha = points[vertex_index].color.alpha*brightness_scale;
|
|
color.red = points[vertex_index].color.red*tint->red;
|
|
color.green = points[vertex_index].color.green*tint->green;
|
|
color.blue = points[vertex_index].color.blue*tint->blue;
|
|
pixel = real_argb_color_to_pixel32(&color);
|
|
|
|
vertices->point.x = position->x + up.i*width;
|
|
vertices->point.y = position->y + up.j*width;
|
|
vertices->point.z = position->z + up.k*width;
|
|
vertices->texture.x = u + u_offset;
|
|
vertices->color = pixel;
|
|
vertices->texture.y = 0.f;
|
|
vertices++;
|
|
|
|
width = -width;
|
|
vertices->point.x = position->x + up.i*width;
|
|
vertices->point.y = position->y + up.j*width;
|
|
vertices->point.z = position->z + up.k*width;
|
|
vertices->texture.x = u + u_offset;
|
|
vertices->color = pixel;
|
|
vertices->texture.y = 1.f;
|
|
vertices++;
|
|
|
|
if (vertex_index == 0)
|
|
{
|
|
bounds.x0 = bounds.x1 = position->x;
|
|
bounds.y0 = bounds.y1 = position->y;
|
|
bounds.z0 = bounds.z1 = position->z;
|
|
}
|
|
else
|
|
{
|
|
bounds.x0 = MIN(position->x, bounds.x0);
|
|
bounds.y0 = MIN(position->y, bounds.y0);
|
|
bounds.z0 = MIN(position->z, bounds.z0);
|
|
bounds.x1 = MAX(position->x, bounds.x1);
|
|
bounds.y1 = MAX(position->y, bounds.y1);
|
|
bounds.z1 = MAX(position->z, bounds.z1);
|
|
}
|
|
}
|
|
|
|
centroid.x = (bounds.x0 + bounds.x1)*0.5f;
|
|
centroid.y = (bounds.y0 + bounds.y1)*0.5f;
|
|
centroid.z = (bounds.z0 + bounds.z1)*0.5f;
|
|
|
|
if (definition->shaders.count > 0)
|
|
shader = &TAG_BLOCK_GET_ELEMENT(&definition->shaders, 0, struct shader_effect_definition)->shader;
|
|
else
|
|
shader = &global_shader_effect_additive.shader;
|
|
|
|
rasterizer_dynamic_vertices_unlock(vertex_buffer_index);
|
|
rasterizer_dynamic_unlit_geometry_draw(
|
|
shader,
|
|
bitmap,
|
|
animation,
|
|
-2*point_count,
|
|
vertex_buffer_index,
|
|
2*point_count - 2,
|
|
¢roid,
|
|
0);
|
|
rasterizer_dynamic_vertices_delete(vertex_buffer_index);
|
|
}
|
|
first_marker = TRUE;
|
|
}
|
|
rasterizer_globals.current_lock_operation = _rasterizer_lock_none;
|
|
}
|
|
else
|
|
{
|
|
struct lightning_marker_definition *next_marker_definition = TAG_BLOCK_GET_ELEMENT(
|
|
&definition->markers,
|
|
marker_index + 1,
|
|
struct lightning_marker_definition);
|
|
short segment_point_count = 1 << marker_definition->octaves_to_next_marker;
|
|
short octaves = marker_definition->octaves_to_next_marker;
|
|
real scale = 1.f;
|
|
real_vector3d up;
|
|
short octave_index;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 383, !points[point_count+segment_point_count].valid);
|
|
|
|
object_get_marker_by_name(object_index, next_marker_definition->attachment_marker, &marker, 1);
|
|
points[point_count+segment_point_count].position = marker.matrix.position;
|
|
lightning_offset_marker_position(
|
|
&points[point_count+segment_point_count].position,
|
|
&marker.matrix,
|
|
&next_marker_definition->random_position_bounds);
|
|
points[point_count+segment_point_count].width = next_marker_definition->thickness;
|
|
points[point_count+segment_point_count].color = next_marker_definition->tint;
|
|
points[point_count+segment_point_count].valid = TRUE;
|
|
|
|
vector_from_points3d(
|
|
&points[point_count].position,
|
|
&points[point_count+segment_point_count].position,
|
|
&up);
|
|
cross_product3d(&up, &render.camera.forward, &up);
|
|
if (normalize3d(&up) == 0.f)
|
|
{
|
|
up.i = global_z_axis3d->x;
|
|
up.j = global_z_axis3d->y;
|
|
up.k = global_z_axis3d->z;
|
|
}
|
|
|
|
for (octave_index = 1; octave_index <= octaves; octave_index++)
|
|
{
|
|
short segment_point_start_index = 1 << (octaves - octave_index);
|
|
short segment_point_index_increment = 2*segment_point_start_index;
|
|
short segment_point_index;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 408, segment_point_start_index>0);
|
|
|
|
for (segment_point_index = segment_point_start_index;
|
|
segment_point_index < segment_point_count;
|
|
segment_point_index += segment_point_index_increment)
|
|
{
|
|
struct intermediate_lightning_point *previous_point =
|
|
&points[point_count + segment_point_index - segment_point_start_index];
|
|
struct intermediate_lightning_point *next_point =
|
|
&points[point_count + segment_point_index + segment_point_start_index];
|
|
struct intermediate_lightning_point *point = &points[point_count + segment_point_index];
|
|
real segment_fraction = (real)segment_point_index/segment_point_count;
|
|
real jitter_offset =
|
|
(segment_fraction*
|
|
(next_marker_definition->random_jitter_offset - marker_definition->random_jitter_offset) +
|
|
marker_definition->random_jitter_offset)*scale*jitter_scale;
|
|
real jitter;
|
|
real_vector3d offset;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\objects\\widgets\\lightning.c", 426, !points[point_count+segment_point_index].valid);
|
|
|
|
jitter = real_seed_random_range(
|
|
get_global_local_random_seed_address(),
|
|
-1.f,
|
|
1.f)*jitter_offset;
|
|
scale_vector3d(&up, jitter, &offset);
|
|
set_real_point3d(
|
|
&point->position,
|
|
(previous_point->position.x + next_point->position.x)*0.5f + offset.i,
|
|
(previous_point->position.y + next_point->position.y)*0.5f + offset.j,
|
|
(previous_point->position.z + next_point->position.z)*0.5f + offset.k);
|
|
point->width = (previous_point->width + next_point->width)*0.5f;
|
|
point->color.alpha = (previous_point->color.alpha + next_point->color.alpha)*0.5f;
|
|
point->color.red = (previous_point->color.red + next_point->color.red)*0.5f;
|
|
point->color.green = (previous_point->color.green + next_point->color.green)*0.5f;
|
|
point->color.blue = (previous_point->color.blue + next_point->color.blue)*0.5f;
|
|
point->valid = TRUE;
|
|
}
|
|
|
|
scale *= 0.5f;
|
|
}
|
|
|
|
point_count += 1 << marker_definition->octaves_to_next_marker;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|