Files
Cesarus85--mjolnir-vr/source/tool/connected_geometry.c
T

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;
}