Blender  V2.93
octree.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #ifndef __OCTREE_H__
18 #define __OCTREE_H__
19 
20 #include "GeoCommon.h"
21 #include "MemoryAllocator.h"
22 #include "ModelReader.h"
23 #include "Projections.h"
24 #include "Queue.h"
25 #include "cubes.h"
26 #include "dualcon.h"
27 #include "manifold_table.h"
28 #include <cassert>
29 #include <cstring>
30 #include <math.h>
31 #include <stdio.h>
32 
40 /* Global defines */
41 /* Uncomment to see debug information */
42 // #define IN_DEBUG_MODE
43 
44 /* Uncomment to see more output messages during repair */
45 // #define IN_VERBOSE_MODE
46 
47 /* Set scan convert params */
48 
49 #define EDGE_FLOATS 4
50 
51 union Node;
52 struct LeafNode;
53 
54 struct InternalNode {
55  /* Initialized in Octree::BuildTable */
56  static int numChildrenTable[256];
57  static int childrenCountTable[256][8];
58  static int childrenIndexTable[256][8];
59 
60  /* Bit N indicates whether child N exists or not */
61  unsigned char has_child_bitfield;
62  /* Bit N indicates whether child N is a leaf or not */
63  unsigned char child_is_leaf_bitfield;
64 
65  /* Can have up to eight children */
67 
69  int is_child_leaf(int index) const
70  {
71  return (child_is_leaf_bitfield >> index) & 1;
72  }
73 
75  int has_child(int index) const
76  {
77  return (has_child_bitfield >> index) & 1;
78  }
79 
82  {
83  return children[count];
84  }
85 
86  const Node *get_child(int count) const
87  {
88  return children[count];
89  }
90 
92  int get_num_children() const
93  {
95  }
96 
98  int get_child_count(int index) const
99  {
100  return childrenCountTable[has_child_bitfield][index];
101  }
103  {
105  }
106  const int *get_child_counts() const
107  {
109  }
110 
112  void fill_children(Node *children[8], int leaf[8])
113  {
114  int count = 0;
115  for (int i = 0; i < 8; i++) {
116  leaf[i] = is_child_leaf(i);
117  if (has_child(i)) {
118  children[i] = get_child(count);
119  count++;
120  }
121  else {
122  children[i] = NULL;
123  leaf[i] = 0;
124  }
125  }
126  }
127 
129  void set_child(int count, Node *chd)
130  {
131  children[count] = chd;
132  }
133  void set_internal_child(int index, int count, InternalNode *chd)
134  {
135  set_child(count, (Node *)chd);
136  has_child_bitfield |= (1 << index);
137  }
138  void set_leaf_child(int index, int count, LeafNode *chd)
139  {
140  set_child(count, (Node *)chd);
141  has_child_bitfield |= (1 << index);
142  child_is_leaf_bitfield |= (1 << index);
143  }
144 };
145 
157 struct LeafNode /* TODO: remove this attribute once everything is fixed */ {
158  unsigned short edge_parity : 12;
159  unsigned short primary_edge_intersections : 3;
160 
161  /* XXX: maybe actually unused? */
162  unsigned short in_process : 1;
163 
164  /* bitfield */
165  char signs;
166 
168 
169  unsigned short flood_fill;
170 
172 };
173 
174 /* Doesn't get directly allocated anywhere, just used for passing
175  pointers to nodes that could be internal or leaf. */
176 union Node {
177  InternalNode internal;
179 };
180 
181 /* Global variables */
182 extern const int edgemask[3];
183 extern const int faceMap[6][4];
184 extern const int cellProcFaceMask[12][3];
185 extern const int cellProcEdgeMask[6][5];
186 extern const int faceProcFaceMask[3][4][3];
187 extern const int edgeProcEdgeMask[3][2][5];
188 extern const int faceProcEdgeMask[3][4][6];
189 extern const int processEdgeMask[3][4];
190 extern const int dirCell[3][4][3];
191 extern const int dirEdge[3][4];
192 
197 struct PathElement {
198  /* Origin */
199  int pos[3];
200 
201  /* link */
203 };
204 
205 struct PathList {
206  /* Head */
209 
210  /* Length of the list */
211  int length;
212 
213  /* Next list */
215 };
216 
220 class Octree {
221  public:
222  /* Public members */
223 
227 
230 
233 
236 
238  int dimen;
240 
242  int maxDepth;
243 
245  float origin[3];
246  float range;
247 
251  int nodeCounts[9];
252 
254 
256 
258  int outType; /* 0 for OFF, 1 for PLY, 2 for VOL */
259 
260  /* For flood filling */
262  float thresh;
263 
265 
266  float hermite_num;
267 
269 
270  public:
274  Octree(ModelReader *mr,
275  DualConAllocOutput alloc_output_func,
276  DualConAddVert add_vert_func,
277  DualConAddQuad add_quad_func,
278  DualConFlags flags,
280  int depth,
281  float threshold,
282  float hermite_num);
283 
287  ~Octree();
288 
292  void scanConvert();
293 
295  {
296  return output_mesh;
297  }
298 
299  private:
300  /* Helper functions */
301 
305  void initMemory();
306 
310  void freeMemory();
311 
315  void printMemUsage();
316 
320  void resetMinimalEdges();
321 
322  void cellProcParity(Node *node, int leaf, int depth);
323  void faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir);
324  void edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir);
325 
326  void processEdgeParity(LeafNode *node[4], int depths[4], int maxdep, int dir);
327 
331  void addAllTriangles();
332  void addTriangle(Triangle *trian, int triind);
333  InternalNode *addTriangle(InternalNode *node, CubeTriangleIsect *p, int height);
334 
338  LeafNode *updateCell(LeafNode *node, CubeTriangleIsect *p);
339 
340  /* Routines to detect and patch holes */
341  int numRings;
342  int totRingLengths;
343  int maxRingLength;
344 
348  void trace();
352  Node *trace(Node *node, int *st, int len, int depth, PathList *&paths);
356  void findPaths(
357  Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths);
362  void combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings);
366  PathList *combineSinglePath(PathList *&head1,
367  PathList *pre1,
368  PathList *&list1,
369  PathList *&head2,
370  PathList *pre2,
371  PathList *&list2);
372 
376  Node *patch(Node *node, int st[3], int len, PathList *rings);
377  Node *patchSplit(Node *node,
378  int st[3],
379  int len,
380  PathList *rings,
381  int dir,
382  PathList *&nrings1,
383  PathList *&nrings2);
384  Node *patchSplitSingle(Node *node,
385  int st[3],
386  int len,
387  PathElement *head,
388  int dir,
389  PathList *&nrings1,
390  PathList *&nrings2);
391  Node *connectFace(Node *node, int st[3], int len, int dir, PathElement *f1, PathElement *f2);
392  Node *locateCell(InternalNode *node,
393  int st[3],
394  int len,
395  int ori[3],
396  int dir,
397  int side,
398  Node *&rleaf,
399  int rst[3],
400  int &rlen);
401  void compressRing(PathElement *&ring);
402  void getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q);
403  LeafNode *patchAdjacent(InternalNode *node,
404  int len,
405  int st1[3],
406  LeafNode *leaf1,
407  int st2[3],
408  LeafNode *leaf2,
409  int walkdir,
410  int inc,
411  int dir,
412  int side,
413  float alpha);
414  int findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2);
415  int getSide(PathElement *e, int pos, int dir);
416  int isEqual(PathElement *e1, PathElement *e2);
417  void preparePrimalEdgesMask(InternalNode *node);
418  void testFacePoint(PathElement *e1, PathElement *e2);
419 
423  void deletePath(PathList *&head, PathList *pre, PathList *&curr);
424  void printPath(PathList *path);
425  void printPath(PathElement *path);
426  void printElement(PathElement *ele);
427  void printPaths(PathList *path);
428  void checkElement(PathElement *ele);
429  void checkPath(PathElement *path);
430 
435  void buildSigns();
436  void buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8]);
437 
438  /************************************************************************/
439  /* To remove disconnected components */
440  /************************************************************************/
441  void floodFill();
442  void clearProcessBits(Node *node, int height);
443  int floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold);
444  int floodFill(Node *node, int st[3], int len, int height, int threshold);
445 
449  void writeOut();
450 
451  void countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface);
452  void generateMinimizer(Node *node, int st[3], int len, int height, int &offset);
453  void computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const;
458  void cellProcContour(Node *node, int leaf, int depth);
459  void faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir);
460  void edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir);
461  void processEdgeWrite(Node *node[4], int depths[4], int maxdep, int dir);
462 
463  /* output callbacks/data */
464  DualConAllocOutput alloc_output;
465  DualConAddVert add_vert;
466  DualConAddQuad add_quad;
467  void *output_mesh;
468 
469  private:
470  /************ Operators for all nodes ************/
471 
473  int numEdgeTable[8];
474  int edgeCountTable[8][3];
475 
477  void buildTable()
478  {
479  for (int i = 0; i < 256; i++) {
481  int count = 0;
482  for (int j = 0; j < 8; j++) {
483  InternalNode::numChildrenTable[i] += ((i >> j) & 1);
486  count += ((i >> j) & 1);
487  }
488  }
489 
490  for (int i = 0; i < 8; i++) {
491  numEdgeTable[i] = 0;
492  int count = 0;
493  for (int j = 0; j < 3; j++) {
494  numEdgeTable[i] += ((i >> j) & 1);
495  edgeCountTable[i][j] = count;
496  count += ((i >> j) & 1);
497  }
498  }
499  }
500 
501  int getSign(Node *node, int height, int index)
502  {
503  if (height == 0) {
504  return getSign(&node->leaf, index);
505  }
506  else {
507  if (node->internal.has_child(index)) {
508  return getSign(
509  node->internal.get_child(node->internal.get_child_count(index)), height - 1, index);
510  }
511  else {
512  return getSign(
513  node->internal.get_child(0), height - 1, 7 - node->internal.get_child_index(0));
514  }
515  }
516  }
517 
518  /************ Operators for leaf nodes ************/
519 
520  void printInfo(int st[3])
521  {
522  printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift);
523  LeafNode *leaf = (LeafNode *)locateLeafCheck(st);
524  if (leaf)
525  printInfo(leaf);
526  else
527  printf("Leaf not exists!\n");
528  }
529 
530  void printInfo(const LeafNode *leaf)
531  {
532  /*
533  printf("Edge mask: ");
534  for(int i = 0; i < 12; i ++)
535  {
536  printf("%d ", getEdgeParity(leaf, i));
537  }
538  printf("\n");
539  printf("Stored edge mask: ");
540  for(i = 0; i < 3; i ++)
541  {
542  printf("%d ", getStoredEdgesParity(leaf, i));
543  }
544  printf("\n");
545  */
546  printf("Sign mask: ");
547  for (int i = 0; i < 8; i++) {
548  printf("%d ", getSign(leaf, i));
549  }
550  printf("\n");
551  }
552 
554  int getSign(const LeafNode *leaf, int index)
555  {
556  return ((leaf->signs >> index) & 1);
557  }
558 
560  void setSign(LeafNode *leaf, int index)
561  {
562  leaf->signs |= (1 << index);
563  }
564 
565  void setSign(LeafNode *leaf, int index, int sign)
566  {
567  leaf->signs &= (~(1 << index));
568  leaf->signs |= ((sign & 1) << index);
569  }
570 
571  int getSignMask(const LeafNode *leaf) const
572  {
573  return leaf->signs;
574  }
575 
576  void setInProcessAll(int st[3], int dir)
577  {
578  int nst[3], eind;
579  for (int i = 0; i < 4; i++) {
580  nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
581  nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
582  nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
583  eind = dirEdge[dir][i];
584 
585  LeafNode *cell = locateLeafCheck(nst);
586  assert(cell);
587 
588  setInProcess(cell, eind);
589  }
590  }
591 
592  void flipParityAll(int st[3], int dir)
593  {
594  int nst[3], eind;
595  for (int i = 0; i < 4; i++) {
596  nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
597  nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
598  nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
599  eind = dirEdge[dir][i];
600 
601  LeafNode *cell = locateLeaf(nst);
602  flipEdge(cell, eind);
603  }
604  }
605 
606  void setInProcess(LeafNode *leaf, int eind)
607  {
608  assert(eind >= 0 && eind <= 11);
609 
610  leaf->flood_fill |= (1 << eind);
611  }
612 
613  void setOutProcess(LeafNode *leaf, int eind)
614  {
615  assert(eind >= 0 && eind <= 11);
616 
617  leaf->flood_fill &= ~(1 << eind);
618  }
619 
620  int isInProcess(LeafNode *leaf, int eind)
621  {
622  assert(eind >= 0 && eind <= 11);
623 
624  return (leaf->flood_fill >> eind) & 1;
625  }
626 
628  void generateSigns(LeafNode *leaf, unsigned char table[], int start)
629  {
630  leaf->signs = table[leaf->edge_parity];
631 
632  if ((start ^ leaf->signs) & 1) {
633  leaf->signs = ~(leaf->signs);
634  }
635  }
636 
638  int getEdgeParity(const LeafNode *leaf, int index) const
639  {
640  assert(index >= 0 && index <= 11);
641 
642  return (leaf->edge_parity >> index) & 1;
643  }
644 
646  int getFaceParity(LeafNode *leaf, int index)
647  {
648  int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) +
649  getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]);
650  return (a & 1);
651  }
652  int getFaceEdgeNum(LeafNode *leaf, int index)
653  {
654  int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) +
655  getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]);
656  return a;
657  }
658 
660  void flipEdge(LeafNode *leaf, int index)
661  {
662  assert(index >= 0 && index <= 11);
663 
664  leaf->edge_parity ^= (1 << index);
665  }
666 
668  void setEdge(LeafNode *leaf, int index)
669  {
670  assert(index >= 0 && index <= 11);
671 
672  leaf->edge_parity |= (1 << index);
673  }
674 
676  void resetEdge(LeafNode *leaf, int index)
677  {
678  assert(index >= 0 && index <= 11);
679 
680  leaf->edge_parity &= ~(1 << index);
681  }
682 
684  void createPrimalEdgesMask(LeafNode *leaf)
685  {
686  leaf->primary_edge_intersections = getPrimalEdgesMask2(leaf);
687  }
688 
689  void setStoredEdgesParity(LeafNode *leaf, int pindex)
690  {
691  assert(pindex <= 2 && pindex >= 0);
692 
693  leaf->primary_edge_intersections |= (1 << pindex);
694  }
695 
696  int getStoredEdgesParity(const LeafNode *leaf, int pindex) const
697  {
698  assert(pindex <= 2 && pindex >= 0);
699 
700  return (leaf->primary_edge_intersections >> pindex) & 1;
701  }
702 
703  LeafNode *flipEdge(LeafNode *leaf, int index, float alpha)
704  {
705  flipEdge(leaf, index);
706 
707  if ((index & 3) == 0) {
708  int ind = index / 4;
709  if (getEdgeParity(leaf, index) && !getStoredEdgesParity(leaf, ind)) {
710  /* Create a new node */
711  int num = getNumEdges(leaf) + 1;
712  setStoredEdgesParity(leaf, ind);
713  int count = getEdgeCount(leaf, ind);
714  LeafNode *nleaf = createLeaf(num);
715  *nleaf = *leaf;
716 
717  setEdgeOffset(nleaf, alpha, count);
718 
719  if (num > 1) {
720  float *pts = leaf->edge_intersections;
721  float *npts = nleaf->edge_intersections;
722  for (int i = 0; i < count; i++) {
723  for (int j = 0; j < EDGE_FLOATS; j++) {
724  npts[i * EDGE_FLOATS + j] = pts[i * EDGE_FLOATS + j];
725  }
726  }
727  for (int i = count + 1; i < num; i++) {
728  for (int j = 0; j < EDGE_FLOATS; j++) {
729  npts[i * EDGE_FLOATS + j] = pts[(i - 1) * EDGE_FLOATS + j];
730  }
731  }
732  }
733 
734  removeLeaf(num - 1, (LeafNode *)leaf);
735  leaf = nleaf;
736  }
737  }
738 
739  return leaf;
740  }
741 
743  void updateParent(InternalNode *node, int len, int st[3], LeafNode *leaf)
744  {
745  /* First, locate the parent */
746  int count;
747  InternalNode *parent = locateParent(node, len, st, count);
748 
749  /* Update */
750  parent->set_child(count, (Node *)leaf);
751  }
752 
753  void updateParent(InternalNode *node, int len, int st[3])
754  {
755  if (len == dimen) {
756  root = (Node *)node;
757  return;
758  }
759 
760  /* First, locate the parent */
761  int count;
762  InternalNode *parent = locateParent(len, st, count);
763 
764  /* Update */
765  parent->set_child(count, (Node *)node);
766  }
767 
769  int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const
770  {
771  /* First, locat the leaf */
772  const LeafNode *leaf;
773  if (check) {
774  leaf = locateLeafCheck(st);
775  }
776  else {
777  leaf = locateLeaf(st);
778  }
779 
780  if (leaf && getStoredEdgesParity(leaf, index)) {
781  float off = getEdgeOffset(leaf, getEdgeCount(leaf, index));
782  pt[0] = (float)st[0];
783  pt[1] = (float)st[1];
784  pt[2] = (float)st[2];
785  pt[index] += off * mindimen;
786 
787  return 1;
788  }
789  else {
790  return 0;
791  }
792  }
793 
795  int getPrimalEdgesMask(const LeafNode *leaf) const
796  {
797  return leaf->primary_edge_intersections;
798  }
799 
800  int getPrimalEdgesMask2(LeafNode *leaf)
801  {
802  return (((leaf->edge_parity & 0x1) >> 0) | ((leaf->edge_parity & 0x10) >> 3) |
803  ((leaf->edge_parity & 0x100) >> 6));
804  }
805 
807  int getEdgeCount(const LeafNode *leaf, int index) const
808  {
809  return edgeCountTable[getPrimalEdgesMask(leaf)][index];
810  }
811  int getNumEdges(LeafNode *leaf)
812  {
813  return numEdgeTable[getPrimalEdgesMask(leaf)];
814  }
815 
816  int getNumEdges2(LeafNode *leaf)
817  {
818  return numEdgeTable[getPrimalEdgesMask2(leaf)];
819  }
820 
822  void setEdgeOffset(LeafNode *leaf, float pt, int count)
823  {
824  float *pts = leaf->edge_intersections;
825  pts[EDGE_FLOATS * count] = pt;
826  pts[EDGE_FLOATS * count + 1] = 0;
827  pts[EDGE_FLOATS * count + 2] = 0;
828  pts[EDGE_FLOATS * count + 3] = 0;
829  }
830 
832  void setEdgeOffsets(LeafNode *leaf, float pt[3], int len)
833  {
834  float *pts = leaf->edge_intersections;
835  for (int i = 0; i < len; i++) {
836  pts[i] = pt[i];
837  }
838  }
839 
841  float getEdgeOffset(const LeafNode *leaf, int count) const
842  {
843  return leaf->edge_intersections[4 * count];
844  }
845 
847  LeafNode *updateEdgeOffsets(LeafNode *leaf, int oldlen, int newlen, float offs[3])
848  {
849  /* First, create a new leaf node */
850  LeafNode *nleaf = createLeaf(newlen);
851  *nleaf = *leaf;
852 
853  /* Next, fill in the offsets */
854  setEdgeOffsets(nleaf, offs, newlen);
855 
856  /* Finally, delete the old leaf */
857  removeLeaf(oldlen, leaf);
858 
859  return nleaf;
860  }
861 
863  void setMinimizerIndex(LeafNode *leaf, int index)
864  {
865  leaf->minimizer_index = index;
866  }
867 
869  int getMinimizerIndex(LeafNode *leaf)
870  {
871  return leaf->minimizer_index;
872  }
873 
874  int getMinimizerIndex(LeafNode *leaf, int eind)
875  {
876  int add = manifold_table[getSignMask(leaf)].pairs[eind][0] - 1;
877  assert(add >= 0);
878  return leaf->minimizer_index + add;
879  }
880 
881  void getMinimizerIndices(LeafNode *leaf, int eind, int inds[2])
882  {
883  const int *add = manifold_table[getSignMask(leaf)].pairs[eind];
884  inds[0] = leaf->minimizer_index + add[0] - 1;
885  if (add[0] == add[1]) {
886  inds[1] = -1;
887  }
888  else {
889  inds[1] = leaf->minimizer_index + add[1] - 1;
890  }
891  }
892 
894  void setEdgeOffsetNormal(LeafNode *leaf, float pt, float a, float b, float c, int count)
895  {
896  float *pts = leaf->edge_intersections;
897  pts[4 * count] = pt;
898  pts[4 * count + 1] = a;
899  pts[4 * count + 2] = b;
900  pts[4 * count + 3] = c;
901  }
902 
903  float getEdgeOffsetNormal(LeafNode *leaf, int count, float &a, float &b, float &c)
904  {
905  float *pts = leaf->edge_intersections;
906  a = pts[4 * count + 1];
907  b = pts[4 * count + 2];
908  c = pts[4 * count + 3];
909  return pts[4 * count];
910  }
911 
913  void setEdgeOffsetsNormals(
914  LeafNode *leaf, const float pt[], const float a[], const float b[], const float c[], int len)
915  {
916  float *pts = leaf->edge_intersections;
917  for (int i = 0; i < len; i++) {
918  if (pt[i] > 1 || pt[i] < 0) {
919  printf("\noffset: %f\n", pt[i]);
920  }
921  pts[i * 4] = pt[i];
922  pts[i * 4 + 1] = a[i];
923  pts[i * 4 + 2] = b[i];
924  pts[i * 4 + 3] = c[i];
925  }
926  }
927 
929  void getEdgeIntersectionByIndex(
930  const LeafNode *leaf, int index, int st[3], int len, float pt[3], float nm[3]) const
931  {
932  int count = getEdgeCount(leaf, index);
933  const float *pts = leaf->edge_intersections;
934 
935  float off = pts[4 * count];
936 
937  pt[0] = (float)st[0];
938  pt[1] = (float)st[1];
939  pt[2] = (float)st[2];
940  pt[index] += (off * len);
941 
942  nm[0] = pts[4 * count + 1];
943  nm[1] = pts[4 * count + 2];
944  nm[2] = pts[4 * count + 3];
945  }
946 
947  float getEdgeOffsetNormalByIndex(LeafNode *leaf, int index, float nm[3])
948  {
949  int count = getEdgeCount(leaf, index);
950  float *pts = leaf->edge_intersections;
951 
952  float off = pts[4 * count];
953 
954  nm[0] = pts[4 * count + 1];
955  nm[1] = pts[4 * count + 2];
956  nm[2] = pts[4 * count + 3];
957 
958  return off;
959  }
960 
961  void fillEdgeIntersections(
962  const LeafNode *leaf, int st[3], int len, float pts[12][3], float norms[12][3]) const
963  {
964  int i;
965  // int stt[3] = {0, 0, 0};
966 
967  // The three primal edges are easy
968  int pmask[3] = {0, 4, 8};
969  for (i = 0; i < 3; i++) {
970  if (getEdgeParity(leaf, pmask[i])) {
971  // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
972  getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
973  }
974  }
975 
976  // 3 face adjacent cubes
977  int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
978  int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
979  for (i = 0; i < 3; i++) {
980  int e1 = getEdgeParity(leaf, fmask[i][0]);
981  int e2 = getEdgeParity(leaf, fmask[i][1]);
982  if (e1 || e2) {
983  int nst[3] = {st[0], st[1], st[2]};
984  nst[i] += len;
985  // int nstt[3] = {0, 0, 0};
986  // nstt[i] += 1;
987  const LeafNode *node = locateLeaf(nst);
988 
989  if (e1) {
990  // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]],
991  // norms[fmask[i][0]]);
992  getEdgeIntersectionByIndex(
993  node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
994  }
995  if (e2) {
996  // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]],
997  // norms[fmask[i][1]]);
998  getEdgeIntersectionByIndex(
999  node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
1000  }
1001  }
1002  }
1003 
1004  // 3 edge adjacent cubes
1005  int emask[3] = {3, 7, 11};
1006  int eemask[3] = {0, 1, 2};
1007  for (i = 0; i < 3; i++) {
1008  if (getEdgeParity(leaf, emask[i])) {
1009  int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
1010  nst[i] -= len;
1011  // int nstt[3] = {1, 1, 1};
1012  // nstt[i] -= 1;
1013  const LeafNode *node = locateLeaf(nst);
1014 
1015  // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
1016  getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
1017  }
1018  }
1019  }
1020 
1021  void fillEdgeIntersections(const LeafNode *leaf,
1022  int st[3],
1023  int len,
1024  float pts[12][3],
1025  float norms[12][3],
1026  int parity[12]) const
1027  {
1028  int i;
1029  for (i = 0; i < 12; i++) {
1030  parity[i] = 0;
1031  }
1032  // int stt[3] = {0, 0, 0};
1033 
1034  // The three primal edges are easy
1035  int pmask[3] = {0, 4, 8};
1036  for (i = 0; i < 3; i++) {
1037  if (getStoredEdgesParity(leaf, i)) {
1038  // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
1039  getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
1040  parity[pmask[i]] = 1;
1041  }
1042  }
1043 
1044  // 3 face adjacent cubes
1045  int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
1046  int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
1047  for (i = 0; i < 3; i++) {
1048  {
1049  int nst[3] = {st[0], st[1], st[2]};
1050  nst[i] += len;
1051  // int nstt[3] = {0, 0, 0};
1052  // nstt[i] += 1;
1053  const LeafNode *node = locateLeafCheck(nst);
1054  if (node == NULL) {
1055  continue;
1056  }
1057 
1058  int e1 = getStoredEdgesParity(node, femask[i][0]);
1059  int e2 = getStoredEdgesParity(node, femask[i][1]);
1060 
1061  if (e1) {
1062  // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]],
1063  // norms[fmask[i][0]]);
1064  getEdgeIntersectionByIndex(
1065  node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
1066  parity[fmask[i][0]] = 1;
1067  }
1068  if (e2) {
1069  // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]],
1070  // norms[fmask[i][1]]);
1071  getEdgeIntersectionByIndex(
1072  node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
1073  parity[fmask[i][1]] = 1;
1074  }
1075  }
1076  }
1077 
1078  // 3 edge adjacent cubes
1079  int emask[3] = {3, 7, 11};
1080  int eemask[3] = {0, 1, 2};
1081  for (i = 0; i < 3; i++) {
1082  // if(getEdgeParity(leaf, emask[i]))
1083  {
1084  int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
1085  nst[i] -= len;
1086  // int nstt[3] = {1, 1, 1};
1087  // nstt[i] -= 1;
1088  const LeafNode *node = locateLeafCheck(nst);
1089  if (node == NULL) {
1090  continue;
1091  }
1092 
1093  if (getStoredEdgesParity(node, eemask[i])) {
1094  // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
1095  getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
1096  parity[emask[i]] = 1;
1097  }
1098  }
1099  }
1100  }
1101 
1102  void fillEdgeOffsetsNormals(
1103  LeafNode *leaf, int st[3], int len, float pts[12], float norms[12][3], int parity[12])
1104  {
1105  int i;
1106  for (i = 0; i < 12; i++) {
1107  parity[i] = 0;
1108  }
1109  // int stt[3] = {0, 0, 0};
1110 
1111  // The three primal edges are easy
1112  int pmask[3] = {0, 4, 8};
1113  for (i = 0; i < 3; i++) {
1114  if (getStoredEdgesParity(leaf, i)) {
1115  pts[pmask[i]] = getEdgeOffsetNormalByIndex(leaf, i, norms[pmask[i]]);
1116  parity[pmask[i]] = 1;
1117  }
1118  }
1119 
1120  // 3 face adjacent cubes
1121  int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
1122  int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
1123  for (i = 0; i < 3; i++) {
1124  {
1125  int nst[3] = {st[0], st[1], st[2]};
1126  nst[i] += len;
1127  // int nstt[3] = {0, 0, 0};
1128  // nstt[i] += 1;
1129  LeafNode *node = locateLeafCheck(nst);
1130  if (node == NULL) {
1131  continue;
1132  }
1133 
1134  int e1 = getStoredEdgesParity(node, femask[i][0]);
1135  int e2 = getStoredEdgesParity(node, femask[i][1]);
1136 
1137  if (e1) {
1138  pts[fmask[i][0]] = getEdgeOffsetNormalByIndex(node, femask[i][0], norms[fmask[i][0]]);
1139  parity[fmask[i][0]] = 1;
1140  }
1141  if (e2) {
1142  pts[fmask[i][1]] = getEdgeOffsetNormalByIndex(node, femask[i][1], norms[fmask[i][1]]);
1143  parity[fmask[i][1]] = 1;
1144  }
1145  }
1146  }
1147 
1148  // 3 edge adjacent cubes
1149  int emask[3] = {3, 7, 11};
1150  int eemask[3] = {0, 1, 2};
1151  for (i = 0; i < 3; i++) {
1152  // if(getEdgeParity(leaf, emask[i]))
1153  {
1154  int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
1155  nst[i] -= len;
1156  // int nstt[3] = {1, 1, 1};
1157  // nstt[i] -= 1;
1158  LeafNode *node = locateLeafCheck(nst);
1159  if (node == NULL) {
1160  continue;
1161  }
1162 
1163  if (getStoredEdgesParity(node, eemask[i])) {
1164  pts[emask[i]] = getEdgeOffsetNormalByIndex(node, eemask[i], norms[emask[i]]);
1165  parity[emask[i]] = 1;
1166  }
1167  }
1168  }
1169  }
1170 
1172  LeafNode *updateEdgeOffsetsNormals(
1173  LeafNode *leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3])
1174  {
1175  /* First, create a new leaf node */
1176  LeafNode *nleaf = createLeaf(newlen);
1177  *nleaf = *leaf;
1178 
1179  /* Next, fill in the offsets */
1180  setEdgeOffsetsNormals(nleaf, offs, a, b, c, newlen);
1181 
1182  /* Finally, delete the old leaf */
1183  removeLeaf(oldlen, leaf);
1184 
1185  return nleaf;
1186  }
1187 
1191  LeafNode *locateLeaf(int st[3])
1192  {
1193  Node *node = (Node *)root;
1194  for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
1195  int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
1196  node = node->internal.get_child(node->internal.get_child_count(index));
1197  }
1198 
1199  return &node->leaf;
1200  }
1201 
1202  const LeafNode *locateLeaf(int st[3]) const
1203  {
1204  const Node *node = root;
1205  for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
1206  int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
1207  node = node->internal.get_child(node->internal.get_child_count(index));
1208  }
1209 
1210  return &node->leaf;
1211  }
1212 
1213  LeafNode *locateLeaf(InternalNode *parent, int len, int st[3])
1214  {
1215  Node *node = (Node *)parent;
1216  int index;
1217  for (int i = len / 2; i >= mindimen; i >>= 1) {
1218  index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
1219  node = node->internal.get_child(node->internal.get_child_count(index));
1220  }
1221 
1222  return &node->leaf;
1223  }
1224 
1225  LeafNode *locateLeafCheck(int st[3])
1226  {
1227  Node *node = (Node *)root;
1228  for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
1229  int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
1230  if (!node->internal.has_child(index)) {
1231  return NULL;
1232  }
1233  node = node->internal.get_child(node->internal.get_child_count(index));
1234  }
1235 
1236  return &node->leaf;
1237  }
1238 
1239  const LeafNode *locateLeafCheck(int st[3]) const
1240  {
1241  const Node *node = root;
1242  for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
1243  int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
1244  if (!node->internal.has_child(index)) {
1245  return NULL;
1246  }
1247  node = node->internal.get_child(node->internal.get_child_count(index));
1248  }
1249 
1250  return &node->leaf;
1251  }
1252 
1253  InternalNode *locateParent(int len, int st[3], int &count)
1254  {
1256  InternalNode *pre = NULL;
1257  int index = 0;
1258  for (int i = dimen / 2; i >= len; i >>= 1) {
1259  index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
1260  pre = node;
1261  node = &node->get_child(node->get_child_count(index))->internal;
1262  }
1263 
1264  count = pre->get_child_count(index);
1265  return pre;
1266  }
1267 
1268  InternalNode *locateParent(InternalNode *parent, int len, int st[3], int &count)
1269  {
1270  InternalNode *node = parent;
1271  InternalNode *pre = NULL;
1272  int index = 0;
1273  for (int i = len / 2; i >= mindimen; i >>= 1) {
1274  index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
1275  pre = node;
1276  node = &node->get_child(node->get_child_count(index))->internal;
1277  }
1278 
1279  count = pre->get_child_count(index);
1280  return pre;
1281  }
1282 
1283  /************ Operators for internal nodes ************/
1284 
1286  InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf)
1287  {
1288  // Create new internal node
1289  int num = node->get_num_children();
1290  InternalNode *rnode = createInternal(num + 1);
1291 
1292  // Establish children
1293  int i;
1294  int count1 = 0, count2 = 0;
1295  for (i = 0; i < 8; i++) {
1296  if (i == index) {
1297  if (aLeaf) {
1298  rnode->set_leaf_child(i, count2, &child->leaf);
1299  }
1300  else {
1301  rnode->set_internal_child(i, count2, &child->internal);
1302  }
1303  count2++;
1304  }
1305  else if (node->has_child(i)) {
1306  if (node->is_child_leaf(i)) {
1307  rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf);
1308  }
1309  else {
1310  rnode->set_internal_child(i, count2, &node->get_child(count1)->internal);
1311  }
1312  count1++;
1313  count2++;
1314  }
1315  }
1316 
1317  removeInternal(num, node);
1318  return rnode;
1319  }
1320 
1322  InternalNode *createInternal(int length)
1323  {
1324  InternalNode *inode = (InternalNode *)alloc[length]->allocate();
1325  inode->has_child_bitfield = 0;
1326  inode->child_is_leaf_bitfield = 0;
1327  return inode;
1328  }
1329 
1330  LeafNode *createLeaf(int length)
1331  {
1332  assert(length <= 3);
1333 
1334  LeafNode *lnode = (LeafNode *)leafalloc[length]->allocate();
1335  lnode->edge_parity = 0;
1336  lnode->primary_edge_intersections = 0;
1337  lnode->signs = 0;
1338 
1339  return lnode;
1340  }
1341 
1342  void removeInternal(int num, InternalNode *node)
1343  {
1344  alloc[num]->deallocate(node);
1345  }
1346 
1347  void removeLeaf(int num, LeafNode *leaf)
1348  {
1349  assert(num >= 0 && num <= 3);
1350  leafalloc[num]->deallocate(leaf);
1351  }
1352 
1354  InternalNode *addLeafChild(InternalNode *par, int index, int count, LeafNode *leaf)
1355  {
1356  int num = par->get_num_children() + 1;
1357  InternalNode *npar = createInternal(num);
1358  *npar = *par;
1359 
1360  if (num == 1) {
1361  npar->set_leaf_child(index, 0, leaf);
1362  }
1363  else {
1364  int i;
1365  for (i = 0; i < count; i++) {
1366  npar->set_child(i, par->get_child(i));
1367  }
1368  npar->set_leaf_child(index, count, leaf);
1369  for (i = count + 1; i < num; i++) {
1370  npar->set_child(i, par->get_child(i - 1));
1371  }
1372  }
1373 
1374  removeInternal(num - 1, par);
1375  return npar;
1376  }
1377 
1378  InternalNode *addInternalChild(InternalNode *par, int index, int count, InternalNode *node)
1379  {
1380  int num = par->get_num_children() + 1;
1381  InternalNode *npar = createInternal(num);
1382  *npar = *par;
1383 
1384  if (num == 1) {
1385  npar->set_internal_child(index, 0, node);
1386  }
1387  else {
1388  int i;
1389  for (i = 0; i < count; i++) {
1390  npar->set_child(i, par->get_child(i));
1391  }
1392  npar->set_internal_child(index, count, node);
1393  for (i = count + 1; i < num; i++) {
1394  npar->set_child(i, par->get_child(i - 1));
1395  }
1396  }
1397 
1398  removeInternal(num - 1, par);
1399  return npar;
1400  }
1401 
1402 #ifdef WITH_CXX_GUARDEDALLOC
1403  MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Octree")
1404 #endif
1405 };
1406 
1407 #endif /* __OCTREE_H__ */
typedef float(TangentPoint)[2]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
#define GRID_DIMENSION
Definition: Projections.h:24
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
Definition: cubes.h:23
unsigned short flood_fill
Definition: octree.h:169
unsigned short primary_edge_intersections
Definition: octree.h:159
char signs
Definition: octree.h:165
float edge_intersections[0]
Definition: octree.h:171
unsigned short in_process
Definition: octree.h:162
unsigned short edge_parity
Definition: octree.h:158
int minimizer_index
Definition: octree.h:167
Definition: octree.h:220
int nodeCounts[9]
Definition: octree.h:251
int use_flood_fill
Definition: octree.h:261
int use_manifold
Definition: octree.h:264
int dimen
Definition: octree.h:238
float range
Definition: octree.h:246
int maxTrianglePerCell
Definition: octree.h:257
float thresh
Definition: octree.h:262
ModelReader * reader
Definition: octree.h:232
void * getOutputMesh()
Definition: octree.h:294
VirtualMemoryAllocator * alloc[9]
Definition: octree.h:225
int maxDepth
Definition: octree.h:242
int nodeSpace
Definition: octree.h:250
VirtualMemoryAllocator * leafalloc[4]
Definition: octree.h:226
~Octree()
Definition: octree.cpp:105
float origin[3]
Definition: octree.h:245
Cubes * cubes
Definition: octree.h:235
int nodeCount
Definition: octree.h:249
float hermite_num
Definition: octree.h:266
int minshift
Definition: octree.h:239
int actualQuads
Definition: octree.h:253
DualConMode mode
Definition: octree.h:268
void scanConvert()
Definition: octree.cpp:111
int outType
Definition: octree.h:258
int mindimen
Definition: octree.h:239
Octree(ModelReader *mr, DualConAllocOutput alloc_output_func, DualConAddVert add_vert_func, DualConAddQuad add_quad_func, DualConFlags flags, DualConMode mode, int depth, float threshold, float hermite_num)
Definition: octree.cpp:45
Node * root
Definition: octree.h:229
PathList * ringList
Definition: octree.h:255
int actualVerts
Definition: octree.h:253
virtual void deallocate(void *obj)=0
OperationNode * node
static CCL_NAMESPACE_BEGIN const double alpha
DualConMode
Definition: dualcon.h:61
void(* DualConAddQuad)(void *output, const int vert_indices[4])
Definition: dualcon.h:55
void(* DualConAddVert)(void *output, const float co[3])
Definition: dualcon.h:53
DualConFlags
Definition: dualcon.h:57
void *(* DualConAllocOutput)(int totvert, int totquad)
Definition: dualcon.h:51
uint pos
int count
const ManifoldIndices manifold_table[256]
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
double sign(double arg)
Definition: utility.h:250
const int processEdgeMask[3][4]
Definition: octree.cpp:2875
const int edgeProcEdgeMask[3][2][5]
Definition: octree.cpp:2869
const int faceProcFaceMask[3][4][3]
Definition: octree.cpp:2860
const int cellProcFaceMask[12][3]
Definition: octree.cpp:2836
const int faceMap[6][4]
Definition: octree.cpp:2827
const int faceProcEdgeMask[3][4][6]
Definition: octree.cpp:2864
const int cellProcEdgeMask[6][5]
Definition: octree.cpp:2851
#define EDGE_FLOATS
Definition: octree.h:49
const int dirEdge[3][4]
Definition: octree.cpp:2885
const int dirCell[3][4][3]
Definition: octree.cpp:2881
const int edgemask[3]
Definition: octree.cpp:2825
unsigned char child_is_leaf_bitfield
Definition: octree.h:63
Node * get_child(int count)
Definition: octree.h:81
unsigned char has_child_bitfield
Definition: octree.h:61
static int childrenCountTable[256][8]
Definition: octree.h:57
void set_leaf_child(int index, int count, LeafNode *chd)
Definition: octree.h:138
int get_child_index(int count)
Definition: octree.h:102
static int numChildrenTable[256]
Definition: octree.h:56
int has_child(int index) const
Definition: octree.h:75
const int * get_child_counts() const
Definition: octree.h:106
static int childrenIndexTable[256][8]
Definition: octree.h:58
int get_num_children() const
Definition: octree.h:92
void fill_children(Node *children[8], int leaf[8])
Definition: octree.h:112
int is_child_leaf(int index) const
Definition: octree.h:69
void set_internal_child(int index, int count, InternalNode *chd)
Definition: octree.h:133
void set_child(int count, Node *chd)
Definition: octree.h:129
const Node * get_child(int count) const
Definition: octree.h:86
Node * children[0]
Definition: octree.h:66
int get_child_count(int index) const
Definition: octree.h:98
int pairs[12][2]
Definition: node.h:98
LeafNode leaf
Definition: octree.h:178
InternalNode internal
Definition: octree.h:177
PathElement * next
Definition: octree.h:202
int pos[3]
Definition: octree.h:199
int length
Definition: octree.h:211
PathElement * tail
Definition: octree.h:208
PathList * next
Definition: octree.h:214
PathElement * head
Definition: octree.h:207
uint len