我正在尝试使用两个(或更多)剖面来查找切割3D对象的算法。只应切割两个截面均为切割的对象。因此,请考虑以下与两个剖面相交的abcd矩形:s0和s1; s1向右切,s0向右切。我想要的是产生ajikcd形状。
. |s1
. a______j_________b ^
. | | | |
. |- - - i - - - - |k- - s0
. | | |
. d----------------c
. |->
这是一个非常简单的例子,但我希望它能说明我想要完成的事情。此外,这应该在3D中完成。
有没有人知道任何这样做的库,还是算法呢?这似乎是一个非常微不足道的问题,有人必须在我之前解决! :)
我必须补充一点,我知道如何做基础(平面与面/平面/边缘的交点)。我无法看到的是,是否有一种聪明的方法来解决所有可能的情况(在这一个中,必须添加两个面,但在其他一些面上可能只创建一个面,等等),或者如果你应该处理它们分开。
我应该添加的另一件事是我不关心渲染部分,我知道如何使用剪切平面的OpenGL来完成它。我想要的是能够计算对象的新拓扑。
答案 0 :(得分:0)
我认为通过将对象切片,移除不需要的部分,然后通过合并面部将剩余的部分粘合在一起,可以很容易地解决这个问题。
假设您正在将对象建模为完全链接的图形
只要您小心维护和操作此图表,它就会包含快速剪切和合并对象所需的所有信息。
您可以使用this answer中描述的算法来计算剪切产生的新面孔。
所以:你对算法的输入是一个切割平面列表和一个对象列表 - 最初只有一个。 对于每个切割平面,将列表对象中的每个对象切成两个并将它们放回列表中。 添加的两个面(每个新对象上一个)应该保持对生成它们的切割平面的引用。 对于由平面切成两半的面,请记住生成的两个新面应该继承此引用(如果存在)。 新对象应该记录它们所在平面的哪一侧(只是一个布尔意思是“保持”或“丢弃”) - 这些记录也应该在对象进一步细分时保持。
一旦完成所有切割,您将拥有一个对象列表,每个对象都有一个记录列表,详细说明它们所在的切割平面的哪一侧。 找到所有这些记录都被“丢弃”的对象并扔掉它们。
我们现在必须将这些物品重新组合在一起。
从简单地合并对象图开始 - 简单地将所有顶点,边和面列表组合到一个对象中。我们现在检查由同一切割平面创建的两个面:
您现在应该有一个合并对象,但有一些无关的顶点。简单地遍历顶点并删除那些只有两个相关边的顶点。
以下是切割如何工作的示例:
:
a---1-:---b
| : |
2 X : 3
| : |
| : |
c---4-:---d
:
:s
我们从一个对象开始(?表示某些边或面未显示):
verts:
a:1,2,?
b:1,3,?
c:2,4,?
d:3,4,?
edges:
1:a,b X,?
2:a,c X,?
3:b,d X,?
4:c,d X,?
faces:
X:1,2,3,4
?:...
当我们用平面切割时,我们最终得到两个物体:
a--1--e-7-b
| | |
2 X 5 Y 3
| 6 |
| | |
c--4--f-8-d
verts: verts:
a:1,2,? e:1,5,6,7
e:1,5,6,7 b:3,7,?
c:2,4,? d:3,8,?
f:4,5,6,8 f:4,5,6,8
edges: edges:
1:a,e X,? 3:b,d Y,?
2:a,c X,? 6:e,f Y,W
4:c,f X,? 7:e,b Y,?
5:e,f X,V 8:f,d Y,?
faces: faces:
X:1,2,3,4 Y:3,6,7,8
V:5,... W:6,...
?:... ?:...
我们添加了顶点e和f,边5和6以及面V和W.请注意,边5和6是不同的对象,在不同的面之间共享相同的顶点。
当我们将这两个对象合并在一起时,我们首先简单地合并两个对象图:
verts:
a:1,2,?
b:3,7,?
c:2,4,?
d:3,8,?
e:1,5,6,7
f:4,5,6,8
edges:
1:a,e X,?
2:a,c X,?
3:b,d Y,?
4:c,f X,?
5:e,f X,V
6:e,f Y,W
7:e,b Y,?
8:f,d Y,?
faces:
X:1,2,3,4
Y:3,6,7,8
V:5,...
W:6,...
?:...
我们可以看到,面V和W是由相同的切割平面生成的,并且具有相同的顶点集,因此可以将它们与相关边一起移除。合并与一对重合边相关联的两个未移除的面。
a--1--e-7-b
| |
2 X 3
| |
| |
c--4--f-8-d
verts:
a:1,2,?
b:3,7,?
c:2,4,?
d:3,8,?
e:1,7
f:4,8
edges:
1:a,e X,?
2:a,c X,?
3:b,d X,?
4:c,f X,?
7:e,b X,?
8:f,d X,?
faces:
X:1,2,3,4,7,8
?:...
然后我们可以只删除两个相关边的顶点,然后合并这些边:
verts:
a:1,2,?
b:1,3,?
c:2,4,?
d:3,8,?
edges:
1:a,e X,?
2:a,c X,?
3:b,d Y,?
4:c,d X,?
faces:
X:1,2,3,4
Y:3,6,7,8
?:...
合并这些对象怎么样?
a--1--e
| 5
2 X g-3-b
| 6 |
| 9 Y 7
c--4--f-8-d
verts: verts:
a:1,2,? g:3,5,6,?
e:1,5,? b:3,7,?
c:2,4,? d:7,8,?
f:4,6,8,9,? f:4,6,8,9,?
edges: edges:
1:a,e X,? 3:b,g Y,?
2:a,c X,? 9:f,g Y,W
4:c,f X,? 7:b,d Y,?
5:e,g X,V,? 8:f,d Y,?
6:f,g X,V
faces: faces:
X:1,2,4,5,6 Y:3,7,8,9
V:5,6,... W:9,...
?:... ?:...
我们合并:
verts:
a:1,2,?
b:3,7,?
e:1,5,?
c:2,4,?
d:7,8,?
f:4,6,8,9,?
g:3,5,6,9,?
edges:
1:a,e X,?
2:a,c X,?
3:b,g Y,?
4:c,f X,?
5:e,g X,V,?
6:f,g X,V
7:b,d Y,?
8:f,d Y,?
9:f,g Y,W
faces:
X:1,2,4,5,6
Y:3,6,7,8
V:5,6,...
W:9,...
?:...
并检查面V和W,因为它们是由同一切割平面创建的。这次他们的顶点集是不同的。取下较小的脸。在这两个面中,找到具有相同顶点的边并将其移除:
a--1--e
| 5
2 X g-3-b
| |
| 7
c--4--f-8-d
verts:
a:1,2,?
b:3,7,?
e:1,5,?
c:2,4,?
d:7,8,?
f:4,8
g:3,5,?
edges:
1:a,e X,?
2:a,c X,?
3:b,g X,?
4:c,f X,?
5:e,g X,V,?
7:b,d X,?
8:f,d X,?
faces:
X:1,2,3,4,5,7,8
V:5,...
?:...
现在我们可以删除只有两个入射边的无用顶点:
a--1--e
| 5
2 X g-3-b
| |
| 7
c----4----d
verts:
a:1,2,?
b:3,7,?
e:1,5,?
c:2,4,?
d:4,7,?
g:3,5,?
edges:
1:a,e X,?
2:a,c X,?
3:b,g Y,?
4:c,d X,?
5:e,g X,?
7:b,d X,?
faces:
X:1,2,3,4,5,7
V:5,...
?:...
唷!希望这会有所帮助...