@@ -69,7 +69,9 @@ int bsp_subdivide(poly_t *divider, poly_t *poly,
69
69
poly_t * * coplanar_front , int * n_cp_front ,
70
70
poly_t * * coplanar_back , int * n_cp_back ,
71
71
poly_t * * front , int * n_front ,
72
- poly_t * * back , int * n_back ) {
72
+ poly_t * * back , int * n_back ,
73
+ poly_t * * unused , int * n_unused ,
74
+ poly_t * * created , int * n_created ) {
73
75
switch (poly_classify_poly (divider , poly )) {
74
76
case FRONT :
75
77
front [* n_front ] = poly ;
@@ -99,6 +101,21 @@ int bsp_subdivide(poly_t *divider, poly_t *poly,
99
101
100
102
back [* n_back ] = b ;
101
103
* n_back += 1 ;
104
+
105
+ // Do we care about telling the caller about polygons
106
+ // who's pointers are not in any of the "real" lists?
107
+ if (unused != NULL ) {
108
+ unused [* n_unused ] = poly ;
109
+ * n_unused += 1 ;
110
+ }
111
+
112
+ // How about polygons that we just made?
113
+ if (created != NULL ) {
114
+ created [* n_created ] = f ;
115
+ * n_created += 1 ;
116
+ created [* n_created ] = b ;
117
+ * n_created += 1 ;
118
+ }
102
119
break ;
103
120
}
104
121
}
@@ -122,7 +139,7 @@ bsp_node_t *bsp_build(bsp_node_t *node, klist_t(poly) *polygons, int copy) {
122
139
polys [i ] = poly ;
123
140
}
124
141
125
- check ((node = bsp_build_array (node , polys , polygons -> size )),
142
+ check ((node = bsp_build_array (node , polys , polygons -> size , copy )),
126
143
"Failed to build node from list(%p) of %zd polys" , polygons , polygons -> size );
127
144
free (polys );
128
145
@@ -131,7 +148,8 @@ bsp_node_t *bsp_build(bsp_node_t *node, klist_t(poly) *polygons, int copy) {
131
148
if (polys ) free (polys );
132
149
return NULL ;
133
150
}
134
- bsp_node_t * bsp_build_array (bsp_node_t * node , poly_t * * polygons , size_t n_polys ) {
151
+
152
+ bsp_node_t * bsp_build_array (bsp_node_t * node , poly_t * * polygons , size_t n_polys , int free_unused ) {
135
153
int rc = 0 ;
136
154
137
155
// Polygon lists and counters
@@ -142,6 +160,14 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
142
160
poly_t * * front_p = NULL ;
143
161
poly_t * * back_p = NULL ;
144
162
163
+ // List and counter of unused polygons
164
+ // These will get freed after the build
165
+ // because they will not appear with identity
166
+ // in coplanar, front_p, or back_p if free_unused
167
+ // is true
168
+ int n_unused = 0 ;
169
+ poly_t * * unused = NULL ;
170
+
145
171
// Iterators
146
172
poly_t * poly = NULL ;
147
173
size_t poly_i = 0 ;
@@ -172,20 +198,34 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
172
198
check_mem (coplanar = malloc (sizeof (poly_t * ) * n_polys ));
173
199
check_mem (front_p = malloc (sizeof (poly_t * ) * n_polys ));
174
200
check_mem (back_p = malloc (sizeof (poly_t * ) * n_polys ));
201
+ check_mem (unused = malloc (sizeof (poly_t * ) * n_polys ));
175
202
for (; poly_i < n_polys ; poly_i ++ ) {
176
203
poly = polygons [poly_i ];
177
204
rc = bsp_subdivide (node -> divider , poly ,
178
205
coplanar , & n_coplanar ,
179
206
coplanar , & n_coplanar ,
180
207
front_p , & n_front ,
181
- back_p , & n_back );
208
+ back_p , & n_back ,
209
+ unused , & n_unused ,
210
+ NULL , NULL );
182
211
check (rc == 0 , "Failed to subdivide: %p => %p" , node -> divider , poly );
183
212
}
184
213
214
+ // Destroy the unused polygons now, if we're asked,
215
+ // otherwise we'll lose the references
216
+ int i = 0 ;
217
+ if (free_unused != 0 ) {
218
+ for (i = 0 ; i < n_unused ; i ++ ) {
219
+ free_poly (unused [i ], 1 );
220
+ }
221
+ }
222
+ // Free now and mark NULL to make sure it's not double free'd on `error:`
223
+ free (unused );
224
+ unused = NULL ;
225
+
185
226
// Store the coplanar nodes in this node's polygon list
186
227
// and free the container, letting the list destructor
187
228
// clean up
188
- int i = 0 ;
189
229
for (i = 0 ; i < n_coplanar ; i ++ ) {
190
230
* kl_pushp (poly , node -> polygons ) = coplanar [i ];
191
231
}
@@ -195,13 +235,13 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
195
235
if ((n_front > 0 )) {
196
236
if (node -> front == NULL ) node -> front = alloc_bsp_node ();
197
237
check_mem (node -> front );
198
- check (bsp_build_array (node -> front , front_p , n_front ) != NULL ,
238
+ check (bsp_build_array (node -> front , front_p , n_front , free_unused ) != NULL ,
199
239
"Failed to build front tree of bsp_node_array(%p)" , node );
200
240
}
201
241
if ((n_back > 0 )) {
202
242
if (node -> back == NULL ) node -> back = alloc_bsp_node ();
203
243
check_mem (node -> back );
204
- check (bsp_build_array (node -> back , back_p , n_back ) != NULL ,
244
+ check (bsp_build_array (node -> back , back_p , n_back , free_unused ) != NULL ,
205
245
"Failed to build back tree of bsp_node(%p)" , node );
206
246
}
207
247
free (front_p );
@@ -213,6 +253,7 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
213
253
if (coplanar ) free (coplanar );
214
254
if (back_p ) free (back_p );
215
255
if (front_p ) free (front_p );
256
+ if (unused ) free (unused );
216
257
return NULL ;
217
258
}
218
259
@@ -316,24 +357,28 @@ klist_t(poly) *bsp_clip_polygon_array(bsp_node_t *node, poly_t **polygons, size_
316
357
poly_t * * poly_buffer = static_poly_buffer ;
317
358
poly_t * * front_array = NULL ;
318
359
poly_t * * back_array = NULL ;
360
+ poly_t * * created_array = NULL ;
319
361
int n_front = 0 ;
320
362
int n_back = 0 ;
363
+ int n_created = 0 ;
321
364
322
365
// Let's end this quick if there's nothing to do.
323
366
if (n_polys == 0 ) return result ;
324
367
325
368
if (node -> divider != NULL ) {
326
- if ((n_polys * 2 ) > STATIC_POLY_BUFFER_SIZE ) {
327
- check_mem (poly_buffer = malloc ((sizeof (poly_t * ) * n_polys ) * 2 ));
369
+ if ((n_polys * 3 ) > STATIC_POLY_BUFFER_SIZE ) {
370
+ check_mem (poly_buffer = malloc ((sizeof (poly_t * ) * n_polys ) * 3 ));
328
371
}
329
372
front_array = poly_buffer ;
330
373
back_array = poly_buffer + n_polys ;
374
+ created_array = poly_buffer + (n_polys * 2 );
331
375
// Sort this node's polygons into the front or back
332
376
for (i = 0 ; i < n_polys ; i ++ ) {
333
377
p = polygons [i ];
334
378
rc = bsp_subdivide (node -> divider , p ,
335
379
front_array , & n_front , back_array , & n_back ,
336
- front_array , & n_front , back_array , & n_back );
380
+ front_array , & n_front , back_array , & n_back ,
381
+ NULL , NULL , created_array , & n_created );
337
382
check (rc != -1 , "Failed to subdivide poly %p" , p );
338
383
}
339
384
@@ -358,8 +403,15 @@ klist_t(poly) *bsp_clip_polygon_array(bsp_node_t *node, poly_t **polygons, size_
358
403
check (result != NULL , "Failed to clip back tree" );
359
404
}
360
405
361
- if (poly_buffer != static_poly_buffer ) free (poly_buffer );
406
+ // Free all the polygons in 'created_array` since they would have
407
+ // been cloned if they were important, and the input set is not our
408
+ // responsibility
409
+ for (int j = 0 ; j < n_created ; j ++ ) {
410
+ free_poly (created_array [j ], 1 );
411
+ }
412
+
362
413
// Clean up the result halves, now that they're copied into `result`
414
+ if (poly_buffer != static_poly_buffer ) free (poly_buffer );
363
415
}
364
416
else {
365
417
// If we don't have a divider we just copy out the polygons
@@ -386,23 +438,27 @@ klist_t(poly) *bsp_clip_polygons(bsp_node_t *node, klist_t(poly) *polygons, klis
386
438
poly_t * * poly_buffer = static_poly_buffer ;
387
439
poly_t * * front_array = NULL ;
388
440
poly_t * * back_array = NULL ;
441
+ poly_t * * created_array = NULL ;
389
442
int n_front = 0 ;
390
443
int n_back = 0 ;
444
+ int n_created = 0 ;
391
445
392
446
// Let's end this quick if there's nothing to do.
393
447
if (polygons -> size == 0 ) return result ;
394
448
395
449
if (node -> divider != NULL ) {
396
- if ((polygons -> size * 2 ) > STATIC_POLY_BUFFER_SIZE ) {
397
- check_mem (poly_buffer = malloc (sizeof (poly_t * ) * polygons -> size * 2 ));
450
+ if ((polygons -> size * 3 ) > STATIC_POLY_BUFFER_SIZE ) {
451
+ check_mem (poly_buffer = malloc (sizeof (poly_t * ) * polygons -> size * 3 ));
398
452
}
399
453
front_array = poly_buffer ;
400
454
back_array = poly_buffer + polygons -> size ;
455
+ created_array = poly_buffer + (polygons -> size * 2 );
401
456
// Sort this node's polygons into the front or back
402
457
for (iter = kl_begin (polygons ); iter != kl_end (polygons ); iter = kl_next (iter )) {
403
458
rc = bsp_subdivide (node -> divider , kl_val (iter ),
404
459
front_array , & n_front , back_array , & n_back ,
405
- front_array , & n_front , back_array , & n_back );
460
+ front_array , & n_front , back_array , & n_back ,
461
+ NULL , NULL , created_array , & n_created );
406
462
check (rc != -1 , "Failed to subdivide poly %p" , kl_val (iter ));
407
463
}
408
464
@@ -427,8 +483,15 @@ klist_t(poly) *bsp_clip_polygons(bsp_node_t *node, klist_t(poly) *polygons, klis
427
483
check (result != NULL , "Failed to clip back tree" );
428
484
}
429
485
486
+ // Free all the polygons in 'created_array` since they would have
487
+ // been cloned if they were important, and the input set is not our
488
+ // responsibility
489
+ for (int j = 0 ; j < n_created ; j ++ ) {
490
+ free_poly (created_array [j ], 1 );
491
+ }
492
+
493
+
430
494
if (poly_buffer != static_poly_buffer ) free (poly_buffer );
431
- // Clean up the result halves, now that they're copied into `result`
432
495
}
433
496
else {
434
497
// If we don't have a divider we just copy out the polygons
0 commit comments