Oolite 1.91.0.7645-241119-222d325
Loading...
Searching...
No Matches
OOMeshToOctreeConverter.m File Reference
import "OOMeshToOctreeConverter.h"
import "OOMaths.h"
import "Octree.h"
import "OOLogging.h"
+ Include dependency graph for OOMeshToOctreeConverter.m:

Go to the source code of this file.

Macros

#define DECL_GEOMETRY(NAME, CAP)
 

Typedefs

typedef struct OOMeshToOctreeConverterInternalData GeometryData
 

Functions

OOINLINE void InitGeometryData (GeometryData *data, uint_fast32_t capacity)
 
OOINLINE void DestroyGeometryData (GeometryData *data)
 
OOINLINE void AddTriangle (GeometryData *data, Triangle tri)
 
static NO_INLINE_FUNC void AddTriangle_slow (GeometryData *data, Triangle tri)
 
static OOScalar MaxDimensionFromOrigin (GeometryData *data)
 
void BuildSubOctree (GeometryData *data, OOOctreeBuilder *builder, OOScalar halfWidth, NSUInteger depth)
 
static void SplitGeometryX (GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar x)
 
static void SplitGeometryY (GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar y)
 
static void SplitGeometryZ (GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar z)
 
static void TranslateGeometryX (GeometryData *data, OOScalar offset)
 
static void TranslateGeometryY (GeometryData *data, OOScalar offset)
 
static void TranslateGeometryZ (GeometryData *data, OOScalar offset)
 

Macro Definition Documentation

◆ DECL_GEOMETRY

#define DECL_GEOMETRY ( NAME,
CAP )
Value:
GeometryData NAME; InitGeometryData(&NAME, CAP);
OOINLINE void InitGeometryData(GeometryData *data, uint_fast32_t capacity)
struct OOMeshToOctreeConverterInternalData GeometryData

Referenced by BuildSubOctree().

Typedef Documentation

◆ GeometryData

typedef struct OOMeshToOctreeConverterInternalData GeometryData

Definition at line 111 of file OOMeshToOctreeConverter.m.

Function Documentation

◆ AddTriangle()

OOINLINE void AddTriangle ( GeometryData * data,
Triangle tri )

Definition at line 217 of file OOMeshToOctreeConverter.m.

218{
219 NSCParameterAssert(data != NULL);
220
221 if (data->count < data->capacity)
222 {
223 data->triangles[data->count++] = tri;
224 }
225 else
226 {
227 AddTriangle_slow(data, tri);
228 }
229}
static NO_INLINE_FUNC void AddTriangle_slow(GeometryData *data, Triangle tri)

References AddTriangle_slow().

Referenced by SplitGeometryX(), SplitGeometryY(), and SplitGeometryZ().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddTriangle_slow()

static NO_INLINE_FUNC void AddTriangle_slow ( GeometryData * data,
Triangle tri )
static

Definition at line 903 of file OOMeshToOctreeConverter.m.

904{
905 NSCParameterAssert(data != NULL);
906 NSCParameterAssert(data->count == data->capacity);
907
908 if (data->capacity == kOOMeshToOctreeConverterSmallDataCapacity)
909 {
910 data->capacity = MAX(data->pendingCapacity, (uint_fast32_t)kOOMeshToOctreeConverterSmallDataCapacity * 2);
911 data->triangles = malloc(data->capacity * sizeof(Triangle));
912 memcpy(data->triangles, data->smallData, sizeof data->smallData);
913 }
914 else
915 {
916 // create more space by doubling the capacity of this geometry.
917 data->capacity = 1 + data->capacity * 2;
918 data->triangles = realloc(data->triangles, data->capacity * sizeof(Triangle));
919
920 // N.b.: we leak here if realloc() failed, but we're about to abort anyway.
921 }
922
923 if (EXPECT_NOT(data->triangles == NULL))
924 {
925 OOLog(kOOLogAllocationFailure, @"%@", @"!!!!! Ran out of memory to allocate more geometry!");
926 exit(EXIT_FAILURE);
927 }
928
929 data->triangles[data->count++] = tri;
930}
#define EXPECT_NOT(x)
#define OOLog(class, format,...)
Definition OOLogging.h:88
NSString *const kOOLogAllocationFailure
Definition OOLogging.m:649
#define MAX(A, B)
Definition OOMaths.h:114
@ kOOMeshToOctreeConverterSmallDataCapacity

Referenced by AddTriangle().

+ Here is the caller graph for this function:

◆ BuildSubOctree()

void BuildSubOctree ( GeometryData * data,
OOOctreeBuilder * builder,
OOScalar halfWidth,
NSUInteger depth )

Definition at line 308 of file OOMeshToOctreeConverter.m.

309{
310 NSCParameterAssert(data != NULL);
311
312 OOScalar subHalfWidth = 0.5f * halfWidth;
313
314 if (data->count == 0)
315 {
316 // No geometry here.
317 [builder writeEmpty];
318 return;
319 }
320
321 if (halfWidth <= OCTREE_MIN_HALF_WIDTH || depth <= 0)
322 {
323 // Maximum resolution reached and not full.
324 [builder writeSolid];
325 return;
326 }
327
328 /*
329 To avoid reallocations, we want a reasonably pessimistic estimate of
330 sub-data size.
331
332 This table shows observed performance for several heuristics using
333 vanilla Oolite r5352 (plus instrumentation). Values aren't precisely
334 reproducible, but are reasonably stable.
335
336 Heuristic: expression used to initialize subCapacity.
337
338 PER: number of geometries per reallocation; in other words, a realloc
339 is needed one time per PER geometries.
340
341 MEM: high water mark for total memory consumption (triangles arrays
342 only) across all live Geometries.
343
344 Heuristic PER MEM
345 n_triangles 3-4 71856
346 n_triangles * 2 100 111384
347 MAX(n_triangles * 2, 16) 300 111384
348 MAX(n_triangles * 2, 21) 500 148512
349 n_triangles * 3 500 165744
350 MAX(n_triangles * 3, 16) 12000 165744
351 MAX(n_triangles * 3, 21) 20000 165744
352
353 The value 21 was chosen for reasons which, on reflection, were entirely
354 wrong. Performance profiling shows no discernible difference between
355 2,16 and 3,21.
356
357 As of r5374, up to 16 entries are stored on the stack and there is no
358 benefit to specifying a minimum here any longer.
359 */
360 enum
361 {
362 kFactor = 2
363 };
364 uint_fast32_t subCapacity = data->count * kFactor;
365
366#define DECL_GEOMETRY(NAME, CAP) GeometryData NAME; InitGeometryData(&NAME, CAP);
367
368 DECL_GEOMETRY(g_000, subCapacity);
369 DECL_GEOMETRY(g_001, subCapacity);
370 DECL_GEOMETRY(g_010, subCapacity);
371 DECL_GEOMETRY(g_011, subCapacity);
372 DECL_GEOMETRY(g_100, subCapacity);
373 DECL_GEOMETRY(g_101, subCapacity);
374 DECL_GEOMETRY(g_110, subCapacity);
375 DECL_GEOMETRY(g_111, subCapacity);
376
377 DECL_GEOMETRY(g_xx1, subCapacity);
378 DECL_GEOMETRY(g_xx0, subCapacity);
379
380 SplitGeometryZ(data, &g_xx1, &g_xx0, subHalfWidth);
381 if (g_xx0.count != 0)
382 {
383 DECL_GEOMETRY(g_x00, subCapacity);
384 DECL_GEOMETRY(g_x10, subCapacity);
385
386 SplitGeometryY(&g_xx0, &g_x10, &g_x00, subHalfWidth);
387 if (g_x00.count != 0)
388 {
389 SplitGeometryX(&g_x00, &g_100, &g_000, subHalfWidth);
390 }
391 if (g_x10.count != 0)
392 {
393 SplitGeometryX(&g_x10, &g_110, &g_010, subHalfWidth);
394 }
395 DestroyGeometryData(&g_x00);
396 DestroyGeometryData(&g_x10);
397 }
398 if (g_xx1.count != 0)
399 {
400 DECL_GEOMETRY(g_x01, subCapacity);
401 DECL_GEOMETRY(g_x11, subCapacity);
402
403 SplitGeometryY(&g_xx1, &g_x11, &g_x01, subHalfWidth);
404 if (g_x01.count != 0)
405 {
406 SplitGeometryX(&g_x01, &g_101, &g_001, subHalfWidth);
407 }
408 if (g_x11.count != 0)
409 {
410 SplitGeometryX(&g_x11, &g_111, &g_011, subHalfWidth);
411 }
412 DestroyGeometryData(&g_x01);
413 DestroyGeometryData(&g_x11);
414 }
415 DestroyGeometryData(&g_xx0);
416 DestroyGeometryData(&g_xx1);
417
418 [builder beginInnerNode];
419 depth--;
420 BuildSubOctree(&g_000, builder, subHalfWidth, depth);
421 BuildSubOctree(&g_001, builder, subHalfWidth, depth);
422 BuildSubOctree(&g_010, builder, subHalfWidth, depth);
423 BuildSubOctree(&g_011, builder, subHalfWidth, depth);
424 BuildSubOctree(&g_100, builder, subHalfWidth, depth);
425 BuildSubOctree(&g_101, builder, subHalfWidth, depth);
426 BuildSubOctree(&g_110, builder, subHalfWidth, depth);
427 BuildSubOctree(&g_111, builder, subHalfWidth, depth);
428 [builder endInnerNode];
429
430 DestroyGeometryData(&g_000);
431 DestroyGeometryData(&g_001);
432 DestroyGeometryData(&g_010);
433 DestroyGeometryData(&g_011);
434 DestroyGeometryData(&g_100);
435 DestroyGeometryData(&g_101);
436 DestroyGeometryData(&g_110);
437 DestroyGeometryData(&g_111);
438}
GLfloat OOScalar
Definition OOMaths.h:64
static void SplitGeometryX(GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar x)
#define DECL_GEOMETRY(NAME, CAP)
OOINLINE void DestroyGeometryData(GeometryData *data)
static void SplitGeometryY(GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar y)
void BuildSubOctree(GeometryData *data, OOOctreeBuilder *builder, OOScalar halfWidth, NSUInteger depth)
static void SplitGeometryZ(GeometryData *data, GeometryData *dPlus, GeometryData *dMinus, OOScalar z)
#define OCTREE_MIN_HALF_WIDTH
Definition Octree.h:31
void writeSolid()
Definition Octree.m:879
void beginInnerNode()
Definition Octree.m:891
void endInnerNode()
Definition Octree.m:915
void writeEmpty()
Definition Octree.m:885

References OOOctreeBuilder::beginInnerNode, BuildSubOctree(), DECL_GEOMETRY, DestroyGeometryData(), OOOctreeBuilder::endInnerNode, OCTREE_MIN_HALF_WIDTH, SplitGeometryX(), SplitGeometryY(), SplitGeometryZ(), OOOctreeBuilder::writeEmpty, and OOOctreeBuilder::writeSolid.

Referenced by BuildSubOctree().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DestroyGeometryData()

OOINLINE void DestroyGeometryData ( GeometryData * data)

Definition at line 196 of file OOMeshToOctreeConverter.m.

197{
198 NSCParameterAssert(data != 0 && data->capacity >= kOOMeshToOctreeConverterSmallDataCapacity);
199
200#if OO_DEBUG
201 Triangle * const kScribbleValue = (Triangle *)-1L;
202 NSCAssert(data->triangles != kScribbleValue, @"Attempt to destroy a GeometryData twice.");
203#endif
204
205 if (data->capacity != kOOMeshToOctreeConverterSmallDataCapacity)
206 {
207 // If capacity is kOOMeshToOctreeConverterSmallDataCapacity, triangles points to smallData.
208 free(data->triangles);
209 }
210
211#if OO_DEBUG
212 data->triangles = kScribbleValue;
213#endif
214}

References kOOMeshToOctreeConverterSmallDataCapacity.

Referenced by BuildSubOctree().

+ Here is the caller graph for this function:

◆ InitGeometryData()

void InitGeometryData ( GeometryData * data,
uint_fast32_t capacity )

Definition at line 185 of file OOMeshToOctreeConverter.m.

186{
187 NSCParameterAssert(data != NULL);
188
189 data->count = 0;
191 data->pendingCapacity = capacity;
192 data->triangles = data->smallData;
193}

References kOOMeshToOctreeConverterSmallDataCapacity.

◆ MaxDimensionFromOrigin()

static OOScalar MaxDimensionFromOrigin ( GeometryData * data)
static

Definition at line 290 of file OOMeshToOctreeConverter.m.

291{
292 NSCParameterAssert(data != NULL);
293
294 OOScalar result = 0.0f;
295 uint_fast32_t i, j;
296 for (i = 0; i < data->count; i++) for (j = 0; j < 3; j++)
297 {
298 Vector v = data->triangles[i].v[j];
299
300 result = fmax(result, fabs(v.x));
301 result = fmax(result, fabs(v.y));
302 result = fmax(result, fabs(v.z));
303 }
304 return result;
305}

◆ SplitGeometryX()

static void SplitGeometryX ( GeometryData * data,
GeometryData * dPlus,
GeometryData * dMinus,
OOScalar x )
static

Definition at line 489 of file OOMeshToOctreeConverter.m.

490{
491 NSCParameterAssert(data != NULL && dPlus != NULL && dMinus != NULL);
492
493 // test each triangle splitting against x == 0.0
494 uint_fast32_t i, count = data->count;
495 for (i = 0; i < count; i++)
496 {
497 bool done_tri = false;
498 Vector v0 = data->triangles[i].v[0];
499 Vector v1 = data->triangles[i].v[1];
500 Vector v2 = data->triangles[i].v[2];
501
502 if (v0.x >= 0.0f && v1.x >= 0.0f && v2.x >= 0.0f)
503 {
504 AddTriangle(dPlus, data->triangles[i]);
505 done_tri = true;
506 }
507 else if (v0.x <= 0.0f && v1.x <= 0.0f && v2.x <= 0.0f)
508 {
509 AddTriangle(dMinus, data->triangles[i]);
510 done_tri = true;
511 }
512 if (!done_tri) // triangle must cross x == 0.0
513 {
514 OOScalar i01, i12, i20;
515 if (v0.x == v1.x)
516 i01 = -1.0f;
517 else
518 i01 = v0.x / (v0.x - v1.x);
519 if (v1.x == v2.x)
520 i12 = -1.0f;
521 else
522 i12 = v1.x / (v1.x - v2.x);
523 if (v2.x == v0.x)
524 i20 = -1.0f;
525 else
526 i20 = v2.x / (v2.x - v0.x);
527
528 Vector v01 = make_vector(0.0f, i01 * (v1.y - v0.y) + v0.y, i01 * (v1.z - v0.z) + v0.z);
529 Vector v12 = make_vector(0.0f, i12 * (v2.y - v1.y) + v1.y, i12 * (v2.z - v1.z) + v1.z);
530 Vector v20 = make_vector(0.0f, i20 * (v0.y - v2.y) + v2.y, i20 * (v0.z - v2.z) + v2.z);
531
532 // cases where a vertex is on the split.
533 if (v0.x == 0.0f)
534 {
535 if (v1.x > 0)
536 {
537 AddTriangle(dPlus, make_triangle(v0, v1, v12));
538 AddTriangle(dMinus, make_triangle(v0, v12, v2));
539 }
540 else
541 {
542 AddTriangle(dMinus, make_triangle(v0, v1, v12));
543 AddTriangle(dPlus, make_triangle(v0, v12, v2));
544 }
545 }
546 if (v1.x == 0.0f)
547 {
548 if (v2.x > 0)
549 {
550 AddTriangle(dPlus, make_triangle(v1, v2, v20));
551 AddTriangle(dMinus, make_triangle(v1, v20, v0));
552 }
553 else
554 {
555 AddTriangle(dMinus, make_triangle(v1, v2, v20));
556 AddTriangle(dPlus, make_triangle(v1, v20, v0));
557 }
558 }
559 if (v2.x == 0.0f)
560 {
561 if (v0.x > 0)
562 {
563 AddTriangle(dPlus, make_triangle(v2, v0, v01));
564 AddTriangle(dMinus, make_triangle(v2, v01, v1));
565 }
566 else
567 {
568 AddTriangle(dMinus, make_triangle(v2, v0, v01));
569 AddTriangle(dPlus, make_triangle(v2, v01, v1));
570 }
571 }
572
573 if (v0.x > 0.0f && v1.x > 0.0f && v2.x < 0.0f)
574 {
575 AddTriangle(dPlus, make_triangle(v0, v12, v20));
576 AddTriangle(dPlus, make_triangle(v0, v1, v12));
577 AddTriangle(dMinus, make_triangle(v20, v12, v2));
578 }
579
580 if (v0.x > 0.0f && v1.x < 0.0f && v2.x > 0.0f)
581 {
582 AddTriangle(dPlus, make_triangle(v2, v01, v12));
583 AddTriangle(dPlus, make_triangle(v2, v0, v01));
584 AddTriangle(dMinus, make_triangle(v12, v01, v1));
585 }
586
587 if (v0.x > 0.0f && v1.x < 0.0f && v2.x < 0.0f)
588 {
589 AddTriangle(dPlus, make_triangle(v20, v0, v01));
590 AddTriangle(dMinus, make_triangle(v2, v20, v1));
591 AddTriangle(dMinus, make_triangle(v20, v01, v1));
592 }
593
594 if (v0.x < 0.0f && v1.x > 0.0f && v2.x > 0.0f)
595 {
596 AddTriangle(dMinus, make_triangle(v01, v20, v0));
597 AddTriangle(dPlus, make_triangle(v1, v20, v01));
598 AddTriangle(dPlus, make_triangle(v1, v2, v20));
599 }
600
601 if (v0.x < 0.0f && v1.x > 0.0f && v2.x < 0.0f)
602 {
603 AddTriangle(dPlus, make_triangle(v01, v1, v12));
604 AddTriangle(dMinus, make_triangle(v0, v01, v2));
605 AddTriangle(dMinus, make_triangle(v01, v12, v2));
606 }
607
608 if (v0.x < 0.0f && v1.x < 0.0f && v2.x > 0.0f)
609 {
610 AddTriangle(dPlus, make_triangle(v12, v2, v20));
611 AddTriangle(dMinus, make_triangle(v1, v12, v0));
612 AddTriangle(dMinus, make_triangle(v12, v20, v0));
613 }
614 }
615 }
616 TranslateGeometryX(dPlus, -x);
617 TranslateGeometryX(dMinus, x);
618}
static void TranslateGeometryX(GeometryData *data, OOScalar offset)
unsigned count
float x

References AddTriangle(), count, TranslateGeometryX(), and x.

Referenced by BuildSubOctree().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SplitGeometryY()

static void SplitGeometryY ( GeometryData * data,
GeometryData * dPlus,
GeometryData * dMinus,
OOScalar y )
static

Definition at line 621 of file OOMeshToOctreeConverter.m.

622{
623 NSCParameterAssert(data != NULL && dPlus != NULL && dMinus != NULL);
624
625 // test each triangle splitting against y == 0.0
626 uint_fast32_t i, count = data->count;
627 for (i = 0; i < count; i++)
628 {
629 bool done_tri = false;
630 Vector v0 = data->triangles[i].v[0];
631 Vector v1 = data->triangles[i].v[1];
632 Vector v2 = data->triangles[i].v[2];
633
634 if (v0.y >= 0.0f && v1.y >= 0.0f && v2.y >= 0.0f)
635 {
636 AddTriangle(dPlus, data->triangles[i]);
637 done_tri = true;
638 }
639 if (v0.y <= 0.0f && v1.y <= 0.0f && v2.y <= 0.0f)
640 {
641 AddTriangle(dMinus, data->triangles[i]);
642 done_tri = true;
643 }
644 if (!done_tri) // triangle must cross y == 0.0
645 {
646 OOScalar i01, i12, i20;
647
648 if (v0.y == v1.y)
649 i01 = -1.0f;
650 else
651 i01 = v0.y / (v0.y - v1.y);
652 if (v1.y == v2.y)
653 i12 = -1.0f;
654 else
655 i12 = v1.y / (v1.y - v2.y);
656 if (v2.y == v0.y)
657 i20 = -1.0f;
658 else
659 i20 = v2.y / (v2.y - v0.y);
660
661 Vector v01 = make_vector(i01 * (v1.x - v0.x) + v0.x, 0.0f, i01 * (v1.z - v0.z) + v0.z);
662 Vector v12 = make_vector(i12 * (v2.x - v1.x) + v1.x, 0.0f, i12 * (v2.z - v1.z) + v1.z);
663 Vector v20 = make_vector(i20 * (v0.x - v2.x) + v2.x, 0.0f, i20 * (v0.z - v2.z) + v2.z);
664
665 // cases where a vertex is on the split.
666 if (v0.y == 0.0f)
667 {
668 if (v1.y > 0)
669 {
670 AddTriangle(dPlus, make_triangle(v0, v1, v12));
671 AddTriangle(dMinus, make_triangle(v0, v12, v2));
672 }
673 else
674 {
675 AddTriangle(dMinus, make_triangle(v0, v1, v12));
676 AddTriangle(dPlus, make_triangle(v0, v12, v2));
677 }
678 }
679 if (v1.y == 0.0f)
680 {
681 if (v2.y > 0)
682 {
683 AddTriangle(dPlus, make_triangle(v1, v2, v20));
684 AddTriangle(dMinus, make_triangle(v1, v20, v0));
685 }
686 else
687 {
688 AddTriangle(dMinus, make_triangle(v1, v2, v20));
689 AddTriangle(dPlus, make_triangle(v1, v20, v0));
690 }
691 }
692 if (v2.y == 0.0f)
693 {
694 if (v0.y > 0)
695 {
696 AddTriangle(dPlus, make_triangle(v2, v0, v01));
697 AddTriangle(dMinus, make_triangle(v2, v01, v1));
698 }
699 else
700 {
701 AddTriangle(dMinus, make_triangle(v2, v0, v01));
702 AddTriangle(dPlus, make_triangle(v2, v01, v1));
703 }
704 }
705
706 if (v0.y > 0.0f && v1.y > 0.0f && v2.y < 0.0f)
707 {
708 AddTriangle(dPlus, make_triangle(v0, v12, v20));
709 AddTriangle(dPlus, make_triangle(v0, v1, v12));
710 AddTriangle(dMinus, make_triangle(v20, v12, v2));
711 }
712
713 if (v0.y > 0.0f && v1.y < 0.0f && v2.y > 0.0f)
714 {
715 AddTriangle(dPlus, make_triangle(v2, v01, v12));
716 AddTriangle(dPlus, make_triangle(v2, v0, v01));
717 AddTriangle(dMinus, make_triangle(v12, v01, v1));
718 }
719
720 if (v0.y > 0.0f && v1.y < 0.0f && v2.y < 0.0f)
721 {
722 AddTriangle(dPlus, make_triangle(v20, v0, v01));
723 AddTriangle(dMinus, make_triangle(v2, v20, v1));
724 AddTriangle(dMinus, make_triangle(v20, v01, v1));
725 }
726
727 if (v0.y < 0.0f && v1.y > 0.0f && v2.y > 0.0f)
728 {
729 AddTriangle(dMinus, make_triangle(v01, v20, v0));
730 AddTriangle(dPlus, make_triangle(v1, v20, v01));
731 AddTriangle(dPlus, make_triangle(v1, v2, v20));
732 }
733
734 if (v0.y < 0.0f && v1.y > 0.0f && v2.y < 0.0f)
735 {
736 AddTriangle(dPlus, make_triangle(v01, v1, v12));
737 AddTriangle(dMinus, make_triangle(v0, v01, v2));
738 AddTriangle(dMinus, make_triangle(v01, v12, v2));
739 }
740
741 if (v0.y < 0.0f && v1.y < 0.0f && v2.y > 0.0f)
742 {
743 AddTriangle(dPlus, make_triangle(v12, v2, v20));
744 AddTriangle(dMinus, make_triangle(v1, v12, v0));
745 AddTriangle(dMinus, make_triangle(v12, v20, v0));
746 }
747 }
748 }
749 TranslateGeometryY(dPlus, -y);
750 TranslateGeometryY(dMinus, y);
751}
static void TranslateGeometryY(GeometryData *data, OOScalar offset)
float y

References AddTriangle(), count, TranslateGeometryY(), and y.

Referenced by BuildSubOctree().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SplitGeometryZ()

static void SplitGeometryZ ( GeometryData * data,
GeometryData * dPlus,
GeometryData * dMinus,
OOScalar z )
static

Definition at line 754 of file OOMeshToOctreeConverter.m.

755{
756 NSCParameterAssert(data != NULL && dPlus != NULL && dMinus != NULL);
757
758 // test each triangle splitting against z == 0.0
759 uint_fast32_t i, count = data->count;
760 for (i = 0; i < count; i++)
761 {
762 bool done_tri = false;
763 Vector v0 = data->triangles[i].v[0];
764 Vector v1 = data->triangles[i].v[1];
765 Vector v2 = data->triangles[i].v[2];
766
767 if (v0.z >= 0.0f && v1.z >= 0.0f && v2.z >= 0.0f)
768 {
769 AddTriangle(dPlus, data->triangles[i]);
770 done_tri = true;
771 }
772 else if (v0.z <= 0.0f && v1.z <= 0.0f && v2.z <= 0.0f)
773 {
774 AddTriangle(dMinus, data->triangles[i]);
775 done_tri = true;
776 }
777 if (!done_tri) // triangle must cross z == 0.0
778 {
779 OOScalar i01, i12, i20;
780
781 if (v0.z == v1.z)
782 i01 = -1.0f;
783 else
784 i01 = v0.z / (v0.z - v1.z);
785 if (v1.z == v2.z)
786 i12 = -1.0f;
787 else
788 i12 = v1.z / (v1.z - v2.z);
789 if (v2.z == v0.z)
790 i20 = -1.0f;
791 else
792 i20 = v2.z / (v2.z - v0.z);
793
794 Vector v01 = make_vector(i01 * (v1.x - v0.x) + v0.x, i01 * (v1.y - v0.y) + v0.y, 0.0f);
795 Vector v12 = make_vector(i12 * (v2.x - v1.x) + v1.x, i12 * (v2.y - v1.y) + v1.y, 0.0f);
796 Vector v20 = make_vector(i20 * (v0.x - v2.x) + v2.x, i20 * (v0.y - v2.y) + v2.y, 0.0f);
797
798 // cases where a vertex is on the split.
799 if (v0.z == 0.0f)
800 {
801 if (v1.z > 0)
802 {
803 AddTriangle(dPlus, make_triangle(v0, v1, v12));
804 AddTriangle(dMinus, make_triangle(v0, v12, v2));
805 }
806 else
807 {
808 AddTriangle(dMinus, make_triangle(v0, v1, v12));
809 AddTriangle(dPlus, make_triangle(v0, v12, v2));
810 }
811 }
812 if (v1.z == 0.0f)
813 {
814 if (v2.z > 0)
815 {
816 AddTriangle(dPlus, make_triangle(v1, v2, v20));
817 AddTriangle(dMinus, make_triangle(v1, v20, v0));
818 }
819 else
820 {
821 AddTriangle(dMinus, make_triangle(v1, v2, v20));
822 AddTriangle(dPlus, make_triangle(v1, v20, v0));
823 }
824 }
825 if (v2.z == 0.0f)
826 {
827 if (v0.z > 0)
828 {
829 AddTriangle(dPlus, make_triangle(v2, v0, v01));
830 AddTriangle(dMinus, make_triangle(v2, v01, v1));
831 }
832 else
833 {
834 AddTriangle(dMinus, make_triangle(v2, v0, v01));
835 AddTriangle(dPlus, make_triangle(v2, v01, v1));
836 }
837 }
838
839 if (v0.z > 0.0f && v1.z > 0.0f && v2.z < 0.0f)
840 {
841 AddTriangle(dPlus, make_triangle(v0, v12, v20));
842 AddTriangle(dPlus, make_triangle(v0, v1, v12));
843 AddTriangle(dMinus, make_triangle(v20, v12, v2));
844 }
845
846 if (v0.z > 0.0f && v1.z < 0.0f && v2.z > 0.0f)
847 {
848 AddTriangle(dPlus, make_triangle(v2, v01, v12));
849 AddTriangle(dPlus, make_triangle(v2, v0, v01));
850 AddTriangle(dMinus, make_triangle(v12, v01, v1));
851 }
852
853 if (v0.z > 0.0f && v1.z < 0.0f && v2.z < 0.0f)
854 {
855 AddTriangle(dPlus, make_triangle(v20, v0, v01));
856 AddTriangle(dMinus, make_triangle(v2, v20, v1));
857 AddTriangle(dMinus, make_triangle(v20, v01, v1));
858 }
859
860 if (v0.z < 0.0f && v1.z > 0.0f && v2.z > 0.0f)
861 {
862 AddTriangle(dMinus, make_triangle(v01, v20, v0));
863 AddTriangle(dPlus, make_triangle(v1, v20, v01));
864 AddTriangle(dPlus, make_triangle(v1, v2, v20));
865 }
866
867 if (v0.z < 0.0f && v1.z > 0.0f && v2.z < 0.0f)
868 {
869 AddTriangle(dPlus, make_triangle(v01, v1, v12));
870 AddTriangle(dMinus, make_triangle(v0, v01, v2));
871 AddTriangle(dMinus, make_triangle(v01, v12, v2));
872 }
873
874 if (v0.z < 0.0f && v1.z < 0.0f && v2.z > 0.0f)
875 {
876 AddTriangle(dPlus, make_triangle(v12, v2, v20));
877 AddTriangle(dMinus, make_triangle(v1, v12, v0));
878 AddTriangle(dMinus, make_triangle(v12, v20, v0));
879 }
880 }
881 }
882 TranslateGeometryZ(dPlus, -z);
883 TranslateGeometryZ(dMinus, z);
884}
static void TranslateGeometryZ(GeometryData *data, OOScalar offset)

References AddTriangle(), count, and TranslateGeometryZ().

Referenced by BuildSubOctree().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TranslateGeometryX()

static void TranslateGeometryX ( GeometryData * data,
OOScalar offset )
static

Definition at line 441 of file OOMeshToOctreeConverter.m.

442{
443 NSCParameterAssert(data != NULL);
444
445 // Optimization note: offset is never zero, so no early return.
446
447 uint_fast32_t i, count = data->count;
448 for (i = 0; i < count; i++)
449 {
450 data->triangles[i].v[0].x += offset;
451 data->triangles[i].v[1].x += offset;
452 data->triangles[i].v[2].x += offset;
453 }
454}
voidpf uLong offset
Definition ioapi.h:140

References count.

Referenced by SplitGeometryX().

+ Here is the caller graph for this function:

◆ TranslateGeometryY()

static void TranslateGeometryY ( GeometryData * data,
OOScalar offset )
static

Definition at line 457 of file OOMeshToOctreeConverter.m.

458{
459 NSCParameterAssert(data != NULL);
460
461 // Optimization note: offset is never zero, so no early return.
462
463 uint_fast32_t i, count = data->count;
464 for (i = 0; i < count; i++)
465 {
466 data->triangles[i].v[0].y += offset;
467 data->triangles[i].v[1].y += offset;
468 data->triangles[i].v[2].y += offset;
469 }
470}

References count.

Referenced by SplitGeometryY().

+ Here is the caller graph for this function:

◆ TranslateGeometryZ()

static void TranslateGeometryZ ( GeometryData * data,
OOScalar offset )
static

Definition at line 473 of file OOMeshToOctreeConverter.m.

474{
475 NSCParameterAssert(data != NULL);
476
477 // Optimization note: offset is never zero, so no early return.
478
479 uint_fast32_t i, count = data->count;
480 for (i = 0; i < count; i++)
481 {
482 data->triangles[i].v[0].z += offset;
483 data->triangles[i].v[1].z += offset;
484 data->triangles[i].v[2].z += offset;
485 }
486}

References count.

Referenced by SplitGeometryZ().

+ Here is the caller graph for this function: