CARLA
Cube.h
Go to the documentation of this file.
1 #pragma once
2 #include "DataStructs.h"
3 
5 {
6  struct IntersectInfo
7  {
8  // 0 - 255
9  int signConfig;
10 
11  // If it exists, vertex on edge i is stored at position i.
12  // For edge numbering and location see numberings.png.
13  std::array<Vec3, 12> edgeVertIndices;
14  };
15 
16  class Cube
17  {
18  Vec3 pos[8];
19  double sdf[8];
20 
21  Vec3 LerpVertex(double isoLevel, int i1, int i2) const;
22  int SignConfig(double isoLevel) const;
23 
24  public:
25  Cube(Rect3 const &space, Fun3s const &sdf);
26 
27  // Find the vertices where the surface intersects the cube.
28  IntersectInfo Intersect(double isoLevel = 0) const;
29  };
30 
31  namespace
32  {
33  // Cube has 8 vertices. Each vertex can have positive or negative sign.
34  // 2^8 = 256 possible configurations mapped to intersected edges in each case.
35  // The 12 edges are numbered as 1, 2, 4, ..., 2048 and are stored as a 12-bit bitstring for each configuration.
36  const int signConfigToIntersectedEdges[256] = {
37  0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
38  0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
39  0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
40  0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
41  0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
42  0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
43  0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
44  0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
45  0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
46  0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
47  0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
48  0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
49  0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
50  0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
51  0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
52  0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
53  0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
54  0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
55  0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
56  0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
57  0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
58  0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
59  0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
60  0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
61  0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
62  0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
63  0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
64  0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
65  0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
66  0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
67  0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
68  0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0};
69 
70  struct Edge
71  {
72  int edgeFlag : 12; // flag: 1, 2, 4, ... 2048
73  int vert0; // 0-7
74  int vert1; // 0-7
75  };
76 
77  const Edge edges[12] =
78  {
79  {1, 0, 1}, // edge 0
80  {2, 1, 2}, // edge 1
81  {4, 2, 3}, // ...
82  {8, 3, 0},
83  {16, 4, 5},
84  {32, 5, 6},
85  {64, 6, 7},
86  {128, 7, 4},
87  {256, 0, 4},
88  {512, 1, 5},
89  {1024, 2, 6},
90  {2048, 3, 7} // edge 11
91  };
92  }
93 
94  Vec3 Cube::LerpVertex(double isoLevel, int i1, int i2) const
95  {
96  auto const Eps = 1e-5;
97  auto const v1 = sdf[i1];
98  auto const v2 = sdf[i2];
99  auto const &p1 = pos[i1];
100  auto const &p2 = pos[i2];
101 
102  if (abs(isoLevel - v1) < Eps)
103  return p1;
104  if (abs(isoLevel - v2) < Eps)
105  return p2;
106  if (abs(v1 - v2) < Eps)
107  return p1;
108 
109  auto mu = (isoLevel - v1) / (v2 - v1);
110  return p1 + (p2 - p1) * mu;
111  }
112 
113  Cube::Cube(Rect3 const &space, Fun3s const &sdf)
114  {
115  auto mx = space.min.x;
116  auto my = space.min.y;
117  auto mz = space.min.z;
118 
119  auto sx = space.size.x;
120  auto sy = space.size.y;
121  auto sz = space.size.z;
122 
123  pos[0] = space.min;
124  pos[1] = {mx + sx, my, mz};
125  pos[2] = {mx + sx, my, mz + sz};
126  pos[3] = {mx, my, mz + sz};
127  pos[4] = {mx, my + sy, mz};
128  pos[5] = {mx + sx, my + sy, mz};
129  pos[6] = {mx + sx, my + sy, mz + sz};
130  pos[7] = {mx, my + sy, mz + sz};
131 
132  for (auto i = 0; i < 8; ++i)
133  {
134  auto sd = sdf(pos[i]);
135  if (sd == 0)
136  sd += 1e-6;
137  this->sdf[i] = sd;
138  }
139  }
140 
141  int Cube::SignConfig(double isoLevel) const
142  {
143  auto edgeIndex = 0;
144 
145  for (auto i = 0; i < 8; ++i)
146  {
147  if (sdf[i] < isoLevel)
148  {
149  edgeIndex |= 1 << i;
150  }
151  }
152 
153  return edgeIndex;
154  }
155 
156  IntersectInfo Cube::Intersect(double iso) const
157  {
158  // idea:
159  // from signs at 8 corners of cube a sign configuration (256 possible ones) is computed
160  // this configuration can be used to index into a table that tells which of the 12 edges are intersected
161  // find vertices adjacent to edges and interpolate cut vertex and store it in IntersectionInfo object
162 
163  IntersectInfo intersect;
164  intersect.signConfig = SignConfig(iso);
165 
166  for (auto e = 0; e < 12; ++e)
167  {
168  if (signConfigToIntersectedEdges[intersect.signConfig] & edges[e].edgeFlag)
169  {
170  auto v0 = edges[e].vert0;
171  auto v1 = edges[e].vert1;
172  auto vert = LerpVertex(iso, v0, v1);
173  intersect.edgeVertIndices[e] = vert;
174  }
175  }
176 
177  return intersect;
178  }
179 
180 }
int vert1
Definition: Cube.h:74
std::function< double(Vec3 const &)> Fun3s
Definition: DataStructs.h:54
static double sd[6]
Definition: odrSpiral.cpp:55
std::array< Vec3, 12 > edgeVertIndices
Definition: Cube.h:13
Cube(Rect3 const &space, Fun3s const &sdf)
Definition: Cube.h:113
int edgeFlag
Definition: Cube.h:72
IntersectInfo Intersect(double isoLevel=0) const
Definition: Cube.h:156
int SignConfig(double isoLevel) const
Definition: Cube.h:141
Vec3 LerpVertex(double isoLevel, int i1, int i2) const
Definition: Cube.h:94
int vert0
Definition: Cube.h:73