mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-24 20:00:27 +02:00
364 lines
10 KiB
C
364 lines
10 KiB
C
/*
|
|
CONNECTED_GEOMETRY.C
|
|
|
|
symbols in this file:
|
|
000F2CD0 0030:
|
|
_connected_geometry_new (0000)
|
|
000F2D00 0050:
|
|
_connected_geometry_delete (0000)
|
|
000F2D50 00d0:
|
|
_connected_geometry_group_recursive (0000)
|
|
000F2E20 00c0:
|
|
_code_000f2e20 (0000)
|
|
000F2EE0 00f0:
|
|
_code_000f2ee0 (0000)
|
|
000F2FD0 00b0:
|
|
_plane3d_from_points (0000)
|
|
000F3080 01a0:
|
|
_connected_geometry_add_triangle (0000)
|
|
000F3220 0180:
|
|
_code_000f3220 (0000)
|
|
000F33A0 0080:
|
|
_connected_geometry_add_intermediate_triangle (0000)
|
|
000F3420 0130:
|
|
_connected_geometry_group_coplanar (0000)
|
|
00279CB0 0079:
|
|
??_C@_0HJ@CCKALPEO@?$CD?$CD?$CD?5WARNING?3?5found?5duplicate?5tri@ (0000)
|
|
00279D30 0008:
|
|
__real@3f847ae140000000 (0000)
|
|
004561B3 0001:
|
|
_bss_004561b3 (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "tool/connected_geometry.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
struct intermediate_geometry_triangle
|
|
{
|
|
long unused_before_vertex_indices[2];
|
|
long vertex_indices[3];
|
|
long unused_after_vertex_indices[8];
|
|
};
|
|
|
|
struct intermediate_geometry_vertex
|
|
{
|
|
long unused_before_point[2];
|
|
real_point3d point;
|
|
long unused_after_point[15];
|
|
};
|
|
|
|
struct intermediate_geometry
|
|
{
|
|
long unused_before_triangles[77];
|
|
struct dynamic_array triangles;
|
|
struct dynamic_array vertices;
|
|
};
|
|
|
|
typedef boolean (*connected_geometry_group_predicate)(
|
|
void *predicate_data,
|
|
struct connected_geometry *geometry,
|
|
struct connected_geometry_triangle *triangle,
|
|
long group_index);
|
|
|
|
typedef char connected_geometry_dynamic_array_size_assert[
|
|
sizeof(struct dynamic_array) == 0xC ? 1 : -1];
|
|
typedef char connected_geometry_point_size_assert[
|
|
sizeof(real_point3d) == 0xC ? 1 : -1];
|
|
typedef char connected_geometry_plane_size_assert[
|
|
sizeof(real_plane3d) == 0x10 ? 1 : -1];
|
|
typedef char connected_geometry_edge_size_assert[
|
|
sizeof(struct connected_geometry_edge) == 0x1C ? 1 : -1];
|
|
typedef char connected_geometry_edge_point_indices_offset_assert[
|
|
offsetof(struct connected_geometry_edge, point_indices) == 0xC ? 1 : -1];
|
|
typedef char connected_geometry_triangle_size_assert[
|
|
sizeof(struct connected_geometry_triangle) == 0x18 ? 1 : -1];
|
|
typedef char connected_geometry_size_assert[
|
|
sizeof(struct connected_geometry) == 0x24 ? 1 : -1];
|
|
typedef char connected_geometry_edges_offset_assert[
|
|
offsetof(struct connected_geometry, edges) == 0xC ? 1 : -1];
|
|
typedef char connected_geometry_triangles_offset_assert[
|
|
offsetof(struct connected_geometry, triangles) == 0x18 ? 1 : -1];
|
|
typedef char intermediate_geometry_triangle_size_assert[
|
|
sizeof(struct intermediate_geometry_triangle) == 0x34 ? 1 : -1];
|
|
typedef char intermediate_geometry_triangle_vertex_indices_offset_assert[
|
|
offsetof(struct intermediate_geometry_triangle, vertex_indices) == 0x8 ? 1 : -1];
|
|
typedef char intermediate_geometry_vertex_size_assert[
|
|
sizeof(struct intermediate_geometry_vertex) == 0x50 ? 1 : -1];
|
|
typedef char intermediate_geometry_vertex_point_offset_assert[
|
|
offsetof(struct intermediate_geometry_vertex, point) == 0x8 ? 1 : -1];
|
|
typedef char intermediate_geometry_triangles_offset_assert[
|
|
offsetof(struct intermediate_geometry, triangles) == 0x134 ? 1 : -1];
|
|
typedef char intermediate_geometry_vertices_offset_assert[
|
|
offsetof(struct intermediate_geometry, vertices) == 0x140 ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
/* ---------- globals */
|
|
|
|
/* ---------- public code */
|
|
|
|
void connected_geometry_new(
|
|
struct connected_geometry *geometry)
|
|
{
|
|
dynamic_array_new(&geometry->points, sizeof(real_point3d));
|
|
dynamic_array_new(&geometry->edges, sizeof(struct connected_geometry_edge));
|
|
dynamic_array_new(&geometry->triangles, sizeof(struct connected_geometry_triangle));
|
|
|
|
return;
|
|
}
|
|
|
|
void connected_geometry_delete(
|
|
struct connected_geometry *geometry)
|
|
{
|
|
long edge_index;
|
|
|
|
for (edge_index = 0; edge_index < geometry->edges.count; edge_index++)
|
|
{
|
|
struct connected_geometry_edge *edge = dynamic_array_get_element(
|
|
&geometry->edges,
|
|
edge_index,
|
|
sizeof(*edge));
|
|
dynamic_array_delete(&edge->triangle_indices);
|
|
}
|
|
|
|
dynamic_array_delete(&geometry->points);
|
|
dynamic_array_delete(&geometry->edges);
|
|
dynamic_array_delete(&geometry->triangles);
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
void connected_geometry_group_recursive(
|
|
struct connected_geometry *geometry,
|
|
connected_geometry_group_predicate predicate,
|
|
void *predicate_data,
|
|
long group_index,
|
|
long triangle_index)
|
|
{
|
|
struct connected_geometry_triangle *triangle;
|
|
long *edge_designator;
|
|
struct connected_geometry_edge *edge;
|
|
long edge_triangle_index;
|
|
short edge_triangle_counter;
|
|
long edge_designator_count;
|
|
|
|
triangle = dynamic_array_get_element(
|
|
&geometry->triangles,
|
|
triangle_index,
|
|
sizeof(*triangle));
|
|
if (triangle->coplanar_group_index == NONE &&
|
|
(predicate == NULL ||
|
|
predicate(predicate_data, geometry, triangle, group_index)))
|
|
{
|
|
triangle->coplanar_group_index = group_index;
|
|
edge_designator = triangle->edge_designators;
|
|
edge_designator_count = 3;
|
|
do
|
|
{
|
|
if (*edge_designator != NONE)
|
|
{
|
|
edge = dynamic_array_get_element(
|
|
&geometry->edges,
|
|
*edge_designator & LONG_MAX,
|
|
sizeof(*edge));
|
|
edge_triangle_counter = 0;
|
|
if (edge->triangle_indices.count > 0)
|
|
{
|
|
edge_triangle_index = 0;
|
|
do
|
|
{
|
|
connected_geometry_group_recursive(
|
|
geometry,
|
|
predicate,
|
|
predicate_data,
|
|
group_index,
|
|
*(long *)dynamic_array_get_element(
|
|
&edge->triangle_indices,
|
|
edge_triangle_index,
|
|
sizeof(long)));
|
|
edge_triangle_counter++;
|
|
edge_triangle_index = (long)edge_triangle_counter;
|
|
}
|
|
while (edge_triangle_index < edge->triangle_indices.count);
|
|
}
|
|
}
|
|
edge_designator++;
|
|
edge_designator_count--;
|
|
}
|
|
while (edge_designator_count != 0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static boolean triangle_coplanar(
|
|
void *predicate_data,
|
|
struct connected_geometry *geometry,
|
|
struct connected_geometry_triangle *triangle,
|
|
long group_index)
|
|
{
|
|
real_plane3d *plane = predicate_data;
|
|
real_point3d *point0 = dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
&geometry->edges,
|
|
triangle->edge_designators[0] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[0] & LONG_MIN) != 0],
|
|
sizeof(real_point3d));
|
|
real_point3d *point1 = dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
&geometry->edges,
|
|
triangle->edge_designators[1] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[1] & LONG_MIN) != 0],
|
|
sizeof(real_point3d));
|
|
real_point3d *point2 = dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
&geometry->edges,
|
|
triangle->edge_designators[2] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[2] & LONG_MIN) != 0],
|
|
sizeof(real_point3d));
|
|
real_plane3d triangle_plane;
|
|
real point_distance;
|
|
real point_product;
|
|
real facing;
|
|
|
|
if (fabs(
|
|
point0->y*plane->n.j +
|
|
point0->z*plane->n.k +
|
|
point0->x*plane->n.i -
|
|
plane->d) < 0.01f &&
|
|
fabs(
|
|
point1->y*plane->n.j +
|
|
point1->z*plane->n.k +
|
|
point1->x*plane->n.i -
|
|
plane->d) < 0.01f)
|
|
{
|
|
point_distance = point2->y*plane->n.j;
|
|
point_distance += point2->z*plane->n.k;
|
|
point_product = point2->x*plane->n.i;
|
|
point_distance += point_product;
|
|
if (fabs(point_distance - plane->d) < 0.01f &&
|
|
plane3d_from_points(&triangle_plane, point0, point2, point1) != NULL)
|
|
{
|
|
facing = triangle_plane.n.i*plane->n.i;
|
|
facing += triangle_plane.n.k*plane->n.k;
|
|
facing += triangle_plane.n.j*plane->n.j;
|
|
if (facing > 0.0f)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void connected_geometry_add_intermediate_triangle(
|
|
struct connected_geometry *geometry,
|
|
struct intermediate_geometry *intermediate_geometry,
|
|
long triangle_index,
|
|
boolean report_duplicates)
|
|
{
|
|
struct intermediate_geometry_triangle *triangle;
|
|
|
|
triangle = dynamic_array_get_element(
|
|
&intermediate_geometry->triangles,
|
|
triangle_index,
|
|
sizeof(*triangle));
|
|
connected_geometry_add_triangle(
|
|
geometry,
|
|
&((struct intermediate_geometry_vertex *)dynamic_array_get_element(
|
|
&intermediate_geometry->vertices,
|
|
triangle->vertex_indices[0],
|
|
sizeof(struct intermediate_geometry_vertex)))->point,
|
|
&((struct intermediate_geometry_vertex *)dynamic_array_get_element(
|
|
&intermediate_geometry->vertices,
|
|
triangle->vertex_indices[1],
|
|
sizeof(struct intermediate_geometry_vertex)))->point,
|
|
&((struct intermediate_geometry_vertex *)dynamic_array_get_element(
|
|
&intermediate_geometry->vertices,
|
|
triangle->vertex_indices[2],
|
|
sizeof(struct intermediate_geometry_vertex)))->point,
|
|
report_duplicates);
|
|
|
|
return;
|
|
}
|
|
|
|
long connected_geometry_group_coplanar(
|
|
struct connected_geometry *geometry)
|
|
{
|
|
struct dynamic_array *edges;
|
|
struct connected_geometry_triangle *triangle;
|
|
long group_count;
|
|
long triangle_index;
|
|
real_plane3d plane;
|
|
|
|
group_count = 0;
|
|
triangle_index = 0;
|
|
if (geometry->triangles.count > 0)
|
|
{
|
|
edges = &geometry->edges;
|
|
do
|
|
{
|
|
triangle = dynamic_array_get_element(
|
|
&geometry->triangles,
|
|
triangle_index,
|
|
sizeof(*triangle));
|
|
plane3d_from_points(
|
|
&plane,
|
|
dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
edges,
|
|
triangle->edge_designators[0] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[0] & LONG_MIN) != 0],
|
|
sizeof(real_point3d)),
|
|
dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
edges,
|
|
triangle->edge_designators[2] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[2] & LONG_MIN) != 0],
|
|
sizeof(real_point3d)),
|
|
dynamic_array_get_element(
|
|
&geometry->points,
|
|
((struct connected_geometry_edge *)dynamic_array_get_element(
|
|
edges,
|
|
triangle->edge_designators[1] & LONG_MAX,
|
|
sizeof(struct connected_geometry_edge)))->point_indices[
|
|
(triangle->edge_designators[1] & LONG_MIN) != 0],
|
|
sizeof(real_point3d)));
|
|
if (triangle->coplanar_group_index == NONE)
|
|
{
|
|
connected_geometry_group_recursive(
|
|
geometry,
|
|
triangle_coplanar,
|
|
&plane,
|
|
group_count,
|
|
triangle_index);
|
|
group_count++;
|
|
}
|
|
triangle_index++;
|
|
}
|
|
while (triangle_index < geometry->triangles.count);
|
|
}
|
|
|
|
return group_count;
|
|
}
|