csg 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/src/bsp.h ADDED
@@ -0,0 +1,40 @@
1
+ #include "klist.h"
2
+ #include "poly.h"
3
+
4
+ #ifndef __BSP_H
5
+ #define __BSP_H
6
+
7
+ typedef struct s_bsp_node {
8
+ klist_t(poly) *polygons;
9
+ poly_t *divider;
10
+
11
+ struct s_bsp_node *front;
12
+ struct s_bsp_node *back;
13
+ } bsp_node_t;
14
+
15
+ bsp_node_t *alloc_bsp_node(void);
16
+ bsp_node_t *clone_bsp_tree(bsp_node_t *tree);
17
+
18
+ void free_bsp_node(bsp_node_t *node);
19
+ void free_bsp_tree(bsp_node_t *tree);
20
+
21
+ int bsp_subdivide(poly_t *divider, poly_t *poly,
22
+ poly_t **coplanar_front, int *n_cp_front,
23
+ poly_t **coplanar_back, int *n_cp_back,
24
+ poly_t **front, int *n_front,
25
+ poly_t **back, int *n_back);
26
+
27
+ bsp_node_t *bsp_build(bsp_node_t *node, klist_t(poly) *polygons, int copy);
28
+ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys);
29
+ klist_t(poly) *bsp_to_polygons(bsp_node_t *tree, int make_triangles, klist_t(poly) *dst);
30
+
31
+ bsp_node_t *bsp_invert(bsp_node_t *tree);
32
+ bsp_node_t *bsp_clip(bsp_node_t *us, bsp_node_t *them);
33
+ klist_t(poly) *bsp_clip_polygons(bsp_node_t *node, klist_t(poly) *polygons, klist_t(poly) *dst);
34
+
35
+ // CSG Operations
36
+ bsp_node_t *bsp_union(bsp_node_t *a, bsp_node_t *b);
37
+ bsp_node_t *bsp_subtract(bsp_node_t *a, bsp_node_t *b);
38
+ bsp_node_t *bsp_intersect(bsp_node_t *a, bsp_node_t *b);
39
+
40
+ #endif
data/src/dbg.c ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ *
3
+ * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ *
13
+ * * Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
18
+ * of its contributors may be used to endorse or promote products
19
+ * derived from this software without specific prior written
20
+ * permission.
21
+ *
22
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+
35
+ #include "dbg.h"
36
+
37
+ FILE *LOG_FILE = NULL;
38
+
39
+ void dbg_set_log(FILE *log_file)
40
+ {
41
+ LOG_FILE = log_file;
42
+ }
43
+
44
+
45
+ FILE *dbg_get_log()
46
+ {
47
+ return LOG_FILE != NULL ? LOG_FILE : stderr;
48
+ }
data/src/dbg.h ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ *
3
+ * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ *
13
+ * * Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
18
+ * of its contributors may be used to endorse or promote products
19
+ * derived from this software without specific prior written
20
+ * permission.
21
+ *
22
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+
35
+ #ifndef __dbg_h__
36
+ #define __dbg_h__
37
+
38
+ #include <stdio.h>
39
+ #include <errno.h>
40
+ #include <string.h>
41
+
42
+ void dbg_set_log(FILE *log_file);
43
+ FILE *dbg_get_log();
44
+
45
+ #ifdef NDEBUG
46
+ #define debug(M, ...)
47
+ #else
48
+ #define debug(M, ...) fprintf(dbg_get_log(), "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
49
+ #endif
50
+
51
+
52
+ // do not try to be smart and make this go away on NDEBUG, the _debug
53
+ // here means that it just doesn't print a message, it still does the
54
+ // check. MKAY?
55
+ #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
56
+
57
+ #define clean_errno() (errno == 0 ? "None" : strerror(errno))
58
+
59
+ #ifdef NO_LINENOS
60
+ // versions that don't feature line numbers
61
+ #define log_err(M, ...) fprintf(dbg_get_log(), "[ERROR] (errno: %s) " M "\n", clean_errno(), ##__VA_ARGS__)
62
+ #define log_warn(M, ...) fprintf(dbg_get_log(), "[WARN] (errno: %s) " M "\n", clean_errno(), ##__VA_ARGS__)
63
+ #define log_info(M, ...) fprintf(dbg_get_log(), "[INFO] " M "\n", ##__VA_ARGS__)
64
+ #else
65
+ #define log_err(M, ...) fprintf(dbg_get_log(), "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
66
+ #define log_warn(M, ...) fprintf(dbg_get_log(), "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
67
+ #define log_info(M, ...) fprintf(dbg_get_log(), "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
68
+ #endif
69
+
70
+ #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
71
+
72
+ #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
73
+
74
+ #define check_mem(A) check((A), "Out of memory.")
75
+
76
+ #endif
data/src/export.c ADDED
@@ -0,0 +1,68 @@
1
+ #include "export.h"
2
+
3
+ stl_object *stl_from_polys(klist_t(poly) *polygons) {
4
+ stl_object *stl = stl_alloc(NULL, polygons->size);
5
+ check_mem(stl);
6
+
7
+ kliter_t(poly) *iter = kl_begin(polygons);
8
+ stl_facet *facet = stl->facets;
9
+ poly_t *poly = NULL;
10
+ for(; iter != kl_end(polygons); iter = kl_next(iter), facet++) {
11
+ poly = kl_val(iter);
12
+ check(poly_vertex_count(poly) == 3, "Polygon is not a triangle.");
13
+ memcpy(facet->normal, poly->normal, sizeof(float3));
14
+ memcpy(facet->vertices, poly->vertices, sizeof(facet->vertices));
15
+ }
16
+
17
+ return stl;
18
+ error:
19
+ if(stl) stl_free(stl);
20
+ return NULL;
21
+ }
22
+
23
+ stl_object *bsp_to_stl(bsp_node_t *tree) {
24
+ stl_object *stl = NULL;
25
+ klist_t(poly) *polys = NULL;
26
+
27
+ polys = bsp_to_polygons(tree, 1, NULL);
28
+ check(polys != NULL, "Failed to generate polygons from bsp_node_t(%p)", tree);
29
+ check(polys->size > 0, "No polygons returned from tree(%p)", tree);
30
+
31
+ stl = stl_from_polys(polys);
32
+ check(stl != NULL, "Failed to build stl from %zd polygons", polys->size);
33
+ strcpy(stl->header, "[csgtool BSP output]");
34
+
35
+ kl_destroy(poly, polys);
36
+ return stl;
37
+ error:
38
+ if(polys) kl_destroy(poly, polys);
39
+ if(stl) stl_free(stl);
40
+ return NULL;
41
+ }
42
+
43
+ bsp_node_t *stl_to_bsp(stl_object *stl) {
44
+ bsp_node_t *tree = NULL;
45
+ klist_t(poly) *polys = kl_init(poly);
46
+ poly_t *poly = NULL;
47
+
48
+ for(int i = 0; i < stl->facet_count; i++) {
49
+ poly = poly_make_triangle(stl->facets[i].vertices[0],
50
+ stl->facets[i].vertices[1],
51
+ stl->facets[i].vertices[2]);
52
+ check_mem(polys);
53
+ *kl_pushp(poly, polys) = poly;
54
+ }
55
+ check(polys->size == stl->facet_count, "Wrong number of faces generated.");
56
+
57
+ tree = bsp_build(NULL, polys, 1);
58
+ check_mem(tree);
59
+
60
+ kl_destroy(poly, polys);
61
+ return tree;
62
+ error:
63
+ if(polys != NULL) kl_destroy(poly, polys);
64
+ if(tree != NULL) {
65
+ free_bsp_tree(tree);
66
+ }
67
+ return NULL;
68
+ }
data/src/export.h ADDED
@@ -0,0 +1,16 @@
1
+ #include <string.h>
2
+
3
+ #include "dbg.h"
4
+
5
+ #include "stl.h"
6
+ #include "poly.h"
7
+ #include "bsp.h"
8
+
9
+ #ifndef __EXPORT_H
10
+ #define __EXPORT_H
11
+
12
+ stl_object *stl_from_polys(klist_t(poly) *polygons);
13
+ stl_object *bsp_to_stl(bsp_node_t *tree);
14
+ bsp_node_t *stl_to_bsp(stl_object *stl);
15
+
16
+ #endif
data/src/klist.h ADDED
@@ -0,0 +1,121 @@
1
+ /* The MIT License
2
+
3
+ Copyright (c) 2008-2009, by Attractive Chaos <attractor@live.co.uk>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
25
+
26
+ #ifndef _AC_KLIST_H
27
+ #define _AC_KLIST_H
28
+
29
+ #include <stdlib.h>
30
+
31
+ #define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \
32
+ typedef struct { \
33
+ size_t cnt, n, max; \
34
+ kmptype_t **buf; \
35
+ } kmp_##name##_t; \
36
+ static inline kmp_##name##_t *kmp_init_##name() { \
37
+ return calloc(1, sizeof(kmp_##name##_t)); \
38
+ } \
39
+ static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \
40
+ size_t k; \
41
+ for (k = 0; k < mp->n; ++k) { \
42
+ kmpfree_f(mp->buf[k]); free(mp->buf[k]); \
43
+ } \
44
+ free(mp->buf); free(mp); \
45
+ } \
46
+ static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \
47
+ ++mp->cnt; \
48
+ if (mp->n == 0) return calloc(1, sizeof(kmptype_t)); \
49
+ return mp->buf[--mp->n]; \
50
+ } \
51
+ static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \
52
+ --mp->cnt; \
53
+ if (mp->n == mp->max) { \
54
+ mp->max = mp->max? mp->max<<1 : 16; \
55
+ mp->buf = realloc(mp->buf, sizeof(void*) * mp->max); \
56
+ } \
57
+ mp->buf[mp->n++] = p; \
58
+ }
59
+
60
+ #define kmempool_t(name) kmp_##name##_t
61
+ #define kmp_init(name) kmp_init_##name()
62
+ #define kmp_destroy(name, mp) kmp_destroy_##name(mp)
63
+ #define kmp_alloc(name, mp) kmp_alloc_##name(mp)
64
+ #define kmp_free(name, mp, p) kmp_free_##name(mp, p)
65
+
66
+ #define KLIST_INIT(name, kltype_t, kmpfree_t) \
67
+ struct __kl1_##name { \
68
+ kltype_t data; \
69
+ struct __kl1_##name *next; \
70
+ }; \
71
+ typedef struct __kl1_##name kl1_##name; \
72
+ KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \
73
+ typedef struct { \
74
+ kl1_##name *head, *tail; \
75
+ kmp_##name##_t *mp; \
76
+ size_t size; \
77
+ } kl_##name##_t; \
78
+ static inline kl_##name##_t *kl_init_##name() { \
79
+ kl_##name##_t *kl = calloc(1, sizeof(kl_##name##_t)); \
80
+ kl->mp = kmp_init(name); \
81
+ kl->head = kl->tail = kmp_alloc(name, kl->mp); \
82
+ kl->head->next = 0; \
83
+ return kl; \
84
+ } \
85
+ static inline void kl_destroy_##name(kl_##name##_t *kl) { \
86
+ kl1_##name *p; \
87
+ for (p = kl->head; p != kl->tail; p = p->next) \
88
+ kmp_free(name, kl->mp, p); \
89
+ kmp_free(name, kl->mp, p); \
90
+ kmp_destroy(name, kl->mp); \
91
+ free(kl); \
92
+ } \
93
+ static inline kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \
94
+ kl1_##name *q, *p = kmp_alloc(name, kl->mp); \
95
+ q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \
96
+ ++kl->size; \
97
+ return &q->data; \
98
+ } \
99
+ static inline int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \
100
+ kl1_##name *p; \
101
+ if (kl->head->next == 0) return -1; \
102
+ --kl->size; \
103
+ p = kl->head; kl->head = kl->head->next; \
104
+ if (d) *d = p->data; \
105
+ kmp_free(name, kl->mp, p); \
106
+ return 0; \
107
+ }
108
+
109
+ #define kliter_t(name) kl1_##name
110
+ #define klist_t(name) kl_##name##_t
111
+ #define kl_val(iter) ((iter)->data)
112
+ #define kl_next(iter) ((iter)->next)
113
+ #define kl_begin(kl) ((kl)->head)
114
+ #define kl_end(kl) ((kl)->tail)
115
+
116
+ #define kl_init(name) kl_init_##name()
117
+ #define kl_destroy(name, kl) kl_destroy_##name(kl)
118
+ #define kl_pushp(name, kl) kl_pushp_##name(kl)
119
+ #define kl_shift(name, kl, d) kl_shift_##name(kl, d)
120
+
121
+ #endif
data/src/poly.c ADDED
@@ -0,0 +1,206 @@
1
+ #include <assert.h>
2
+
3
+ #include "poly.h"
4
+
5
+ poly_t *alloc_poly(void) {
6
+ poly_t *poly = malloc(sizeof(poly_t));
7
+ check_mem(poly);
8
+ poly_init(poly);
9
+ return poly;
10
+ error:
11
+ return NULL;
12
+ }
13
+
14
+ void free_poly(poly_t *p, int free_self) {
15
+ if(p == NULL) return;
16
+ if(free_self) free(p);
17
+ }
18
+
19
+ poly_t *poly_init(poly_t *poly) {
20
+ poly->vertex_count = 0;
21
+ return poly;
22
+ }
23
+
24
+ poly_t *clone_poly(poly_t *poly) {
25
+ poly_t *copy = NULL;
26
+ check_mem(copy = alloc_poly());
27
+ memcpy(copy, poly, sizeof(poly_t));
28
+ return copy;
29
+ error:
30
+ return NULL;
31
+ }
32
+
33
+ int poly_update(poly_t *poly) {
34
+ if(poly_vertex_count(poly) < 3) return -1;
35
+
36
+ float3 *a = &poly->vertices[0];
37
+ float3 *b = &poly->vertices[1];
38
+ float3 *c = &poly->vertices[2];
39
+
40
+ float3 b_a;
41
+ float3 c_a;
42
+ f3_sub(&b_a, *b, *a);
43
+ f3_sub(&c_a, *c, *a);
44
+
45
+ f3_cross(&poly->normal, b_a, c_a);
46
+ f3_normalize(&poly->normal);
47
+
48
+ poly->w = f3_dot(poly->normal, *a);
49
+ return 0;
50
+ }
51
+
52
+ int poly_vertex_count(poly_t *poly) {
53
+ return poly->vertex_count;
54
+ }
55
+
56
+ // Add a vertex to the end of the polygon vertex list
57
+ int poly_push_vertex(poly_t *poly, float3 v) {
58
+ // TODO: Don't assert, grow
59
+ assert(poly->vertex_count < POLY_MAX_VERTS);
60
+
61
+ // Dat assignment copy
62
+ poly->vertices[poly->vertex_count][0] = v[0];
63
+ poly->vertices[poly->vertex_count][1] = v[1];
64
+ poly->vertices[poly->vertex_count][2] = v[2];
65
+
66
+ // Update the poly if we can
67
+ if(++poly->vertex_count > 2) {
68
+ check(poly_update(poly) == 0, "Failed to update polygon during poly_push_vertex(%p)", poly);
69
+ }
70
+
71
+ return 0;
72
+ error:
73
+ return -1;
74
+ }
75
+
76
+ int poly_classify_vertex(poly_t *poly, float3 v) {
77
+ float side = f3_dot(poly->normal, v) - poly->w;
78
+ if(side < -EPSILON) return BACK;
79
+ if(side > EPSILON) return FRONT;
80
+ return COPLANAR;
81
+ }
82
+
83
+ int poly_classify_poly(poly_t *this, poly_t *other) {
84
+ int front, back;
85
+ int count = poly_vertex_count(other);
86
+
87
+ front = 0;
88
+ back = 0;
89
+
90
+ for(int i = 0; i < count; i++) {
91
+ switch(poly_classify_vertex(this, other->vertices[i])) {
92
+ case FRONT:
93
+ front += 1;
94
+ break;
95
+ case BACK:
96
+ back += 1;
97
+ break;
98
+ }
99
+ }
100
+ if(front > 0 && back == 0) return FRONT;
101
+ if(back > 0 && front == 0) return BACK;
102
+ if(front == 0 && back == 0) return COPLANAR;
103
+ return SPANNING;
104
+ }
105
+
106
+ int poly_split(poly_t *divider, poly_t *poly, poly_t **front, poly_t **back) {
107
+ // Create polygons if we were not passed allocated ones
108
+ if(*front == NULL) {
109
+ *front = alloc_poly();
110
+ }
111
+ if(*back == NULL) {
112
+ *back = alloc_poly();
113
+ }
114
+
115
+ // Current and next vertex
116
+ float3 v_cur = FLOAT3_INIT;
117
+ float3 v_next = FLOAT3_INIT;
118
+ // Classifications of the above
119
+ int c_cur, c_next;
120
+ // Loop indexes
121
+ int i, j;
122
+ int count = poly_vertex_count(poly);
123
+ for(i = 0; i < count; i++) {
124
+ j = (i + 1) % count;
125
+ for(int k = 0; k < 3; k++) {
126
+ v_cur[k] = poly->vertices[i][k];
127
+ v_next[k] = poly->vertices[j][k];
128
+ }
129
+
130
+ // Classify the first and next vertex
131
+ c_cur = poly_classify_vertex(divider, v_cur);
132
+ c_next = poly_classify_vertex(divider, v_next);
133
+
134
+ if(c_cur != BACK) {
135
+ poly_push_vertex(*front, v_cur);
136
+ }
137
+ if(c_cur != FRONT) {
138
+ poly_push_vertex(*back, v_cur);
139
+ }
140
+
141
+ // Interpolate a midpoint if we found a spanning edge
142
+ if((c_cur | c_next) == SPANNING) {
143
+ float3 diff = FLOAT3_INIT;
144
+ f3_sub(&diff, v_next, v_cur);
145
+
146
+ float t = divider->w;
147
+ t = t - f3_dot(divider->normal, v_cur);
148
+ t = t / f3_dot(divider->normal, diff);
149
+
150
+ float3 mid_f = {v_cur[0], v_cur[1], v_cur[2]};
151
+ f3_interpolate(&mid_f, v_cur, v_next, t);
152
+
153
+ check(poly_push_vertex(*front, mid_f) == 0,
154
+ "Failed to push midpoint to front poly(%p)", front);
155
+ check(poly_push_vertex(*back, mid_f) == 0,
156
+ "Failed to push midpoint to back poly(%p):", back);
157
+ }
158
+ }
159
+
160
+ return 0;
161
+ error:
162
+ return -1;
163
+ }
164
+
165
+ poly_t *poly_make_triangle(float3 a, float3 b, float3 c) {
166
+ poly_t *p = NULL;
167
+ check_mem(p = alloc_poly());
168
+
169
+ check(poly_push_vertex(p, a) == 0,
170
+ "Failed to add vertex a to poly(%p): (%f, %f, %f)", p, FLOAT3_FORMAT(a));
171
+ check(poly_push_vertex(p, b) == 0,
172
+ "Failed to add vertex b to poly(%p): (%f, %f, %f)", p, FLOAT3_FORMAT(b));
173
+ check(poly_push_vertex(p, c) == 0,
174
+ "Failed to add vertex c to poly(%p): (%f, %f, %f)", p, FLOAT3_FORMAT(c));
175
+
176
+ return p;
177
+ error:
178
+ if(p) free_poly(p, 1);
179
+ return NULL;
180
+ }
181
+
182
+ poly_t *poly_invert(poly_t *poly) {
183
+ f3_scale(&poly->normal, -1.0);
184
+ poly->w *= -1.0;
185
+
186
+ // We walk the list from the back to the midway point
187
+ // and flip the opposite ends to reverse the poly list.
188
+ int last = poly_vertex_count(poly) - 1;
189
+ int first = 0;
190
+ float3 temp = FLOAT3_INIT;
191
+ for(; first < last; first++, last--) {
192
+ temp[0] = poly->vertices[last][0];
193
+ temp[1] = poly->vertices[last][1];
194
+ temp[2] = poly->vertices[last][2];
195
+
196
+ poly->vertices[last][0] = poly->vertices[first][0];
197
+ poly->vertices[last][1] = poly->vertices[first][1];
198
+ poly->vertices[last][2] = poly->vertices[first][2];
199
+
200
+ poly->vertices[first][0] = temp[0];
201
+ poly->vertices[first][1] = temp[1];
202
+ poly->vertices[first][2] = temp[2];
203
+ }
204
+
205
+ return poly;
206
+ }