我有一个OpenGL Tessellated Sphere,我想在其中切出一个圆柱孔

时间:2010-10-18 22:33:26

标签: algorithm opengl graphics tesselation

我正在开发一个软件,它生成一个多边形网格来表示一个球体,我想在球体上切一个洞。此多边形网格仅是球体表面的叠加。我很清楚如何确定哪些多边形将与我的洞相交,我可以从我的集合中删除它们,但在那之后我有点困惑。我想知道是否有人可以帮助我处理高级概念?

基本上,我设想了三种情况:

1.) The cylindrical hole does not intersect my sphere.
2.) The cylindrical hole partially goes through my sphere.
3.) The cylindrical hole goes all the way through my sphere. 

对于#1,我可以测试这个(没有多边形被移除)并相应地采取行动(什么都不做)。对于#2和#3,我不知道如何重新镶嵌我的球体以解释漏洞。对于#3,我有点想法基本上沿着以下几行:

a.) Find your entry point (a circle)
b.) Find your exit point (a circle) 
c.) Remove the necessary polygons
d.) Make new polygons along the 4* 'sides' of the hole to keep my 
    sphere a manifold. 

这个极其简化的算法有一些我想填写的“漏洞”。例如,我实际上并不想让我的洞有4个边 - 它应该是一个圆柱体,或者至少是一个曲面细分的表示圆筒。我也不确定如何制作这些新的多边形以保持我的球体在镶嵌表面上有一个洞。

我不知道如何处理方案#2。

3 个答案:

答案 0 :(得分:2)

听起来像你想要constructive solid geometry

Carve可能会做你想要的。如果您只是想要运行时渲染,OpenCSG将起作用。

答案 1 :(得分:1)

我在今年早些时候使用标量字段实施了CSG操作。如果性能不重要,它的效果很好。也就是说,计算不是实时的。问题在于衍生物并未在任何地方定义,因此您可以忘记以这种方式计算廉价的顶点法线。它必须作为后续步骤完成。 在这里查看我使用的论文(在第一个答案中),以及我制作的一些截图:

CSG operations on implicit surfaces with marching cubes

此外,CSG这种方式要求使用隐式曲面表示初始网格。虽然任何几何网格都可以分割成平面,但它不会产生良好的效果。因此,球体必须由半径和原点表示,圆柱体将由半径,原点和基部高度表示。

答案 2 :(得分:1)

好吧,如果你想渲染它(可视化)那么你可能根本不需要改变生成的网格物体。而是使用Stencil缓冲区来渲染带有孔的球体。例如,我正在渲染圆盘(薄圆柱体),在其外边缘附近有圆形孔(作为机械的底板),周围有实心和透明物体的组合,所以我需要的是真正的孔洞。由于我懒得对运行时生成的形状进行三角测量,因此我选择了模板。

  1. 使用模板缓冲区

    创建OpenGL上下文

    我使用8位用于模板,但这种技术只使用一位。

  2. 使用0清除模具并关闭深度和颜色蒙版

    必须在使用模板渲染网格之前完成此操作。因此,如果您有更多以这种方式呈现的对象,则需要在每个对象之前执行此操作。

  3. 使用1为实体网格设置模具

  4. 清除模具,0用于打孔网格
  5. 启用深度和颜色蒙版并渲染实心网格,其中模板为1
  6. 在代码中它看起来像这样:

    // [stencil]
    glEnable(GL_STENCIL_TEST);
    // whole stencil=0
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);
    // turn off color,depth
    glStencilMask(0xFF);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glDepthMask(GL_FALSE);
    // stencil=1 for solid mesh
    glStencilFunc(GL_ALWAYS,1,0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glCylinderxz(0.0,y,0.0,r,qh);
    // stencil=0 for hole meshes
    glStencilFunc(GL_ALWAYS,0,0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    for(b=0.0,j=0;j<12;j++,b+=db)
        {
        x=dev_R*cos(b);
        z=dev_R*sin(b);
        glCylinderxz(x,y-0.1,z,dev_r,qh+0.2);
        }
    // turn on color,depth
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glDepthMask(GL_TRUE);
    // render solid mesh the holes will be created by the stencil test
    glStencilFunc(GL_NOTEQUAL,0,0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    glColor3f(0.1,0.3,0.4);
    glCylinderxz(0.0,y,0.0,r,qh);
    glDisable(GL_STENCIL_TEST);
    

    其中glCylinderxz(x,y,z,r,h)只是在(x,y,z)处呈现圆柱体的函数,其半径为r,其中y - 轴为其旋转轴。 db是角度步(2*Pi/12)。 Radiuses是r - 大,dev_r - 孔半径,dev_R - 孔中心和qh是板的厚度。

    结果如下所示(2个板中的每一个都用这个渲染):

    example

    这种方法更适合瘦对象。如果您的切割导致侧面足够厚,那么您需要添加切割面,否则这些部件上的照明可能会出错。