我使用Marching Cubes(或者marching squares,因为这是2D)来渲染等值面,并且想要进行集合操作,如差集、交集和并集。我以为这很容易实现,只需从两个不同的隐式表面中选择两个顶点标量即可,但事实并非如此。
在我的初始测试中,我尝试了两个球圆形,并进行了集合操作difference,即A-B。一个圆形在移动,另一个圆形保持静止。在选择顶点标量和将角落顶点分类为内部或外部时,我尝试了以下方法。代码是用C++编写的,OpenGL用于渲染,但这并不重要。没有任何CSG操作的正常渲染会给出预期结果。
这给我带来了奇怪的锯齿形:![here](https://istack.dev59.com/LHyJc.webp)
(来源: mechcore.net)
看起来CSG操作是没有插值完成的。它只是“丢弃”整个三角形。我需要用其他方式进行插值,或者组合顶点标量值吗?我需要一些帮助。 完整的测试用例可以在此处下载。 编辑:基本上,我的 marching squares 实现运行良好。它是我的 标量场 出了问题,我想知道正确的方法是什么。最好是我正在寻找一种通用方法来实现我上面讨论的三种集合操作,适用于常见的基元(圆形、矩形/正方形、平面)。 编辑 2:这里是实现答案白皮书后的一些新图像:
在我的初始测试中,我尝试了两个
void march(const vec2& cmin, //min x and y for the grid cell
const vec2& cmax, //max x and y for the grid cell
std::vector<vec2>& tri,
float iso,
float (*cmp1)(const vec2&), //distance from stationary circle
float (*cmp2)(const vec2&) //distance from moving circle
)
{
unsigned int squareindex = 0;
float scalar[4];
vec2 verts[8];
/* initial setup of the grid cell */
verts[0] = vec2(cmax.x, cmax.y);
verts[2] = vec2(cmin.x, cmax.y);
verts[4] = vec2(cmin.x, cmin.y);
verts[6] = vec2(cmax.x, cmin.y);
float s1,s2;
/**********************************
********For-loop of interest******
*******Set difference between ****
*******two implicit surfaces******
**********************************/
for(int i=0,j=0; i<4; ++i, j+=2){
s1 = cmp1(verts[j]);
s2 = cmp2(verts[j]);
if((s1 < iso)){ //if inside circle1
if((s2 < iso)){ //if inside circle2
scalar[i] = s2; //then set the scalar to the moving circle
} else {
scalar[i] = s1; //only inside circle1
squareindex |= (1<<i); //mark as inside
}
}
else {
scalar[i] = s1; //inside neither circle
}
}
if(squareindex == 0)
return;
/* Usual interpolation between edge points to compute
the new intersection points */
verts[1] = mix(iso, verts[0], verts[2], scalar[0], scalar[1]);
verts[3] = mix(iso, verts[2], verts[4], scalar[1], scalar[2]);
verts[5] = mix(iso, verts[4], verts[6], scalar[2], scalar[3]);
verts[7] = mix(iso, verts[6], verts[0], scalar[3], scalar[0]);
for(int i=0; i<10; ++i){ //10 = maxmimum 3 triangles, + one end token
int index = triTable[squareindex][i]; //look up our indices for triangulation
if(index == -1)
break;
tri.push_back(verts[index]);
}
}
这给我带来了奇怪的锯齿形:
![here](https://istack.dev59.com/LHyJc.webp)
(来源: mechcore.net)
看起来CSG操作是没有插值完成的。它只是“丢弃”整个三角形。我需要用其他方式进行插值,或者组合顶点标量值吗?我需要一些帮助。 完整的测试用例可以在此处下载。 编辑:基本上,我的 marching squares 实现运行良好。它是我的 标量场 出了问题,我想知道正确的方法是什么。最好是我正在寻找一种通用方法来实现我上面讨论的三种集合操作,适用于常见的基元(圆形、矩形/正方形、平面)。 编辑 2:这里是实现答案白皮书后的一些新图像:
1.Difference
2.Intersection
3.Union
编辑3:我还将其实现为3D,具有适当的阴影/光照:
1.大球和小球之间的区别
2.中心为小球的大球与两侧被剪切平面夹住的大球的区别,然后与中心的球联合。
3.两个圆柱体的并集。