多边形的孔

时间:2008-12-12 05:25:56

标签: algorithm graphics 3d geometry

我需要创建一个立方体的3D模型,在一个面的中心打孔的圆形孔完全穿过立方体到达另一侧。我能够为面孔和孔生成顶点。

可以将四个面(不受孔影响)建模为单个三角形条。孔的内部也可以建模为单个三角形条。

如何为有孔的面生成索引缓冲区?是否有标准算法来执行此操作?

我正在使用Direct3D,但欢迎来自其他地方的想法。

6 个答案:

答案 0 :(得分:6)

要生成所需的索引缓冲区,您可以这样做。在2D中将所讨论的面思考为具有顶点(±1,±1)的正方形,并将孔作为圆形在中间。

  1. 沿着圆圈的边缘行走,将其分成若干段。
  2. 对于每个顶点,使用(x/M,y/M)将其投影到周围的正方形上,其中Mmax(abs(x),abs(y))M是最大坐标的绝对值,因此会缩放(x,y),以便最大坐标为±1。
  3. 这一行你也分成若干段。
  4. 您成对连接的两个后续行的片段作为面。
  5. 这是一个例子,将圆圈细分为64个段,每个射线划分为8个段。您可以选择符合要求的数字。

    alt text http://pici.se/pictures/AVhcssRRz.gif

    以下是一些演示此内容的Python代码:

    from math import sin, cos, pi
    from itertools import izip
    
    def pairs(iterable):
        """Yields the previous and the current item on each iteration.
        """
        last = None
        for item in iterable:
            if last is not None:
                yield last, item
            last = item
    
    def circle(radius, subdiv):
        """Yields coordinates of a circle.
        """
        for angle in xrange(0,subdiv+1):
            x = radius * cos(angle * 2 * pi / subdiv)
            y = radius * sin(angle * 2 * pi / subdiv)
            yield x, y
    
    def line(x0,y0,x1,y1,subdiv):
        """Yields coordinates of a line.
        """
        for t in xrange(subdiv+1):
            x = (subdiv - t)*x0 + t*x1
            y = (subdiv - t)*y0 + t*y1
            yield x/subdiv, y/subdiv
    
    def tesselate_square_with_hole((x,y),(w,h), radius=0.5, subdiv_circle=64, subdiv_ray=8):
        """Yields quads of a tesselated square with a circluar hole.
        """
        for (x0,y0),(x1,y1) in pairs(circle(radius,subdiv_circle)):
            M0 = max(abs(x0),abs(y0))
            xM0, yM0 = x0/M0, y0/M0
    
            M1 = max(abs(x1),abs(y1))
            xM1, yM1 = x1/M1, y1/M1
    
            L1 = line(x0,y0,xM0,yM0,subdiv_ray)
            L2 = line(x1,y1,xM1,yM1,subdiv_ray)
            for ((xa,ya),(xb,yb)),((xc,yc),(xd,yd)) in pairs(izip(L1,L2)):
                yield ((x+xa*w/2,y+ya*h/2),
                       (x+xb*w/2,y+yb*h/2),
                       (x+xc*w/2,y+yc*h/2),
                       (x+xd*w/2,y+yd*h/2))
    
    
    import pygame
    def main():
        """Simple pygame program that displays the tesselated figure.
        """
        print('Calculating faces...')
        faces = list(tesselate_square_with_hole((150,150),(200,200),0.5,64,8))
        print('done')
    
        pygame.init()
        pygame.display.set_mode((300,300))
        surf = pygame.display.get_surface()
        running = True
    
        while running:
            need_repaint = False
            for event in pygame.event.get() or [pygame.event.wait()]:
                if event.type == pygame.QUIT:
                    running = False
                elif event.type in (pygame.VIDEOEXPOSE, pygame.VIDEORESIZE):
                    need_repaint = True
            if need_repaint:
                print('Repaint')
                surf.fill((255,255,255))
                for pa,pb,pc,pd in faces:
                    # draw a single quad with corners (pa,pb,pd,pc)
                    pygame.draw.aalines(surf,(0,0,0),True,(pa,pb,pd,pc),1)
                pygame.display.flip()
    
    try:
        main()
    finally:
        pygame.quit()
    

答案 1 :(得分:4)

你想查找Tessellation,这是处理MizardX正在展示的数学领域.3D Graphcs中的问题必须始终处理这个问题,并且有各种各样的曲面细分算法可以带来一个带孔的面孔并计算渲染它所需的三角形。

答案 2 :(得分:3)

现代硬件通常无法正确渲染凹多边形 具体来说,通常甚至没有办法定义带孔的多边形 你需要以某种方式在洞周围找到飞机的三角剖分。最好的方法可能是从孔的顶点到矩形面的最近顶点创建三角形。这可能会创建一些非常薄的三角形。如果这不是问题,那么你就完成了。如果它是那么你需要一些网格整流/优化算法来创建漂亮的三角形。

答案 3 :(得分:3)

Alpha混合是不可能的?如果没有,只需使用在中间具有透明度的纹理对带有孔的边进行纹理化。你必须做更多的多边形渲染,因为你不能利用前后绘制和忽略覆盖的面,但它可能比有很多小三角形更快。

答案 4 :(得分:2)

我想象着来自广场四角的4个三角扇。

答案 5 :(得分:1)

只是一个想法 -

如果你正在作弊(在游戏中多次这样做),你总是可以构建一个普通的立方体,但是你想要一个洞(alpha = 0)的两个面的纹理,然后你可以剪辑它在着色器中,或混合它(在这种情况下,您需要使用Z排序进行渲染)。 你可以通过构造一个面向内并且没有盖子的内圆柱来获得内孔。

当然,只有在几何图形不重要的情况下,这才有效。