CARLA
 
载入中...
搜索中...
未找到
Cube.h
浏览该文件的文档.
1#pragma once
2#include "DataStructs.h"
3
5{
6// 定义一个名为IntersectInfo的结构体,用于存储相交信息
8 {
9 // 0 - 255
11
12 // 如果存在,则第i条边的顶点存储在第i个位置
13 //关于边的编号和位置,请参见numberings.png
14 std::array<Vec3, 12> edgeVertIndices;
15 };
16//这段代码定义了一个名为 Cube 的类这段代码定义了一个名为 Cube 的类
17 class Cube
18 {
19 Vec3 pos[8];// 存储立方体的8个顶点的位置。
20 double sdf[8];
21// 线性插值计算顶点位置的私有函数,根据给定的等值面水平(isoLevel)和两个顶点索引i1、i2来计算插值后的顶点位置
22 Vec3 LerpVertex(double isoLevel, int i1, int i2) const;
23 int SignConfig(double isoLevel) const;
24
25 public:
26// Cube类的构造函数,接受一个三维空间范围(Rect3类型)和一个三维标量函数(Fun3s类型)作为参数来初始化立方体相关属性
27 Cube(Rect3 const &space, Fun3s const &sdf);
28
29 // 找出曲面与立方体相交的顶点。
30 IntersectInfo Intersect(double isoLevel = 0) const;
31 };
32
33 namespace
34 {
35 // Cube有8个顶点。每个顶点可以有正号或负号
36 // 在每种情况下,2^8=256种可能的配置映射到相交的边
37 // 这12条边被编号为1,2,4,2048,并为每个配置存储为一个12位的位串
38 const int signConfigToIntersectedEdges[256] = {
39 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
40 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
41 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
42 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
43 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
44 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
45 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
46 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
47 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
48 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
49 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
50 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
51 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
52 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
53 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
54 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
55 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
56 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
57 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
58 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
59 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
60 0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
61 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
62 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
63 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
64 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
65 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
66 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
67 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
68 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
69 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
70 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0};
71
72 // 定义一个名为Edge的结构体,用于表示立方体的边相关信息
73 struct Edge
74 {
75 int edgeFlag : 12; // flag: 1, 2, 4, ... 2048
76 int vert0; // 0-7
77 int vert1; // 0-7
78 };
79
80 const Edge edges[12] =
81 {
82 {1, 0, 1}, // edge 0
83 {2, 1, 2}, // edge 1
84 {4, 2, 3}, // ...
85 {8, 3, 0},
86 {16, 4, 5},
87 {32, 5, 6},
88 {64, 6, 7},
89 {128, 7, 4},
90 {256, 0, 4},
91 {512, 1, 5},
92 {1024, 2, 6},
93 {2048, 3, 7} // edge 11
94 };
95 }
96// 线性插值计算顶点位置的函数实现
97 Vec3 Cube::LerpVertex(double isoLevel, int i1, int i2) const
98 {
99 auto const Eps = 1e-5; // 定义一个用于比较浮点数的精度阈值
100 auto const v1 = sdf[i1]; // 定义一个用于比较浮点数的精度阈值
101 auto const v2 = sdf[i2];
102 auto const &p1 = pos[i1]; // 定义一个用于比较浮点数的精度阈值
103 auto const &p2 = pos[i2];
104 // 如果isoLevel与其中一个顶点的SDF值非常接近,则直接返回该顶点位置
105 if (abs(isoLevel - v1) < Eps)
106 return p1;
107 if (abs(isoLevel - v2) < Eps)
108 return p2;
109 if (abs(v1 - v2) < Eps)
110 return p1;
111
112 auto mu = (isoLevel - v1) / (v2 - v1); // 计算线性插值参数
113 return p1 + (p2 - p1) * mu; // 返回插值后的位置
114 }
115// Cube类的构造函数实现,用于初始化立方体的顶点位置和每个顶点对应的SDF值
116 Cube::Cube(Rect3 const &space, Fun3s const &sdf)
117// 定义一个名为 Cube 的构造函数,接受两个参数:space 和 sdf
118 {
119 auto mx = space.min.x;
120 auto my = space.min.y;
121 auto mz = space.min.z;
122
123 auto sx = space.size.x;
124 auto sy = space.size.y;
125 auto sz = space.size.z;
126 // 初始化立方体的8个顶点位置
127 pos[0] = space.min;
128 pos[1] = {mx + sx, my, mz};
129 pos[2] = {mx + sx, my, mz + sz};
130 pos[3] = {mx, my, mz + sz};
131 pos[4] = {mx, my + sy, mz};
132 pos[5] = {mx + sx, my + sy, mz};
133 pos[6] = {mx + sx, my + sy, mz + sz};
134 pos[7] = {mx, my + sy, mz + sz};
135 // 计算每个顶点的SDF值
136 for (auto i = 0; i < 8; ++i)
137 {
138 auto sd = sdf(pos[i]);
139 if (sd == 0)
140 sd += 1e-6; // 避免除以零
141 this->sdf[i] = sd;
142 }
143 }
144// 根据给定的等值面水平(isoLevel)计算符号配置的函数实现
145 int Cube::SignConfig(double isoLevel) const
146 {
147 auto edgeIndex = 0;
148
149 for (auto i = 0; i < 8; ++i)
150 {
151 if (sdf[i] < isoLevel)
152 {
153 edgeIndex |= 1 << i; // 将对应的顶点标记为穿过
154 }
155 }
156
157 return edgeIndex;
158 }
159// 找出曲面与立方体相交的顶点的函数实现,返回包含相交信息的IntersectInfo结构体
161 {
162 // idea:
163 // 从立方体的8个角的符号中计算出一个符号配置(256个可能的)
164 // 这个配置可以用来索引到一个表中,这个表告诉12条边中哪条是相交的
165 // 找到与边相邻的顶点并插值切割顶点并将其存储在Intersectionlnfo对象中
166
167 IntersectInfo intersect;
168 intersect.signConfig = SignConfig(iso);
169
170 for (auto e = 0; e < 12; ++e)
171 {
172 if (signConfigToIntersectedEdges[intersect.signConfig] & edges[e].edgeFlag)
173 {
174 auto v0 = edges[e].vert0;
175 auto v1 = edges[e].vert1;
176 auto vert = LerpVertex(iso, v0, v1);
177 intersect.edgeVertIndices[e] = vert;
178 }
179 }
180
181 return intersect;
182 }
183
184}
int vert1
Definition Cube.h:77
int edgeFlag
Definition Cube.h:75
int vert0
Definition Cube.h:76
int SignConfig(double isoLevel) const
Definition Cube.h:145
Vec3 LerpVertex(double isoLevel, int i1, int i2) const
Definition Cube.h:97
Cube(Rect3 const &space, Fun3s const &sdf)
Definition Cube.h:116
IntersectInfo Intersect(double isoLevel=0) const
Definition Cube.h:160
std::function< double(Vec3 const &)> Fun3s
Definition DataStructs.h:75
static double sd[6]
Definition odrSpiral.cpp:56
std::array< Vec3, 12 > edgeVertIndices
Definition Cube.h:14