代码之家  ›  专栏  ›  技术社区  ›  Brian Stinar

我有一个OpenGL镶嵌球体,我想在里面切一个圆柱孔

  •  1
  • Brian Stinar  · 技术社区  · 14 年前

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

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

    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. 
    

    这个极为简化的算法有一些我想填补的“漏洞”。例如,我实际上不希望孔有四个边——它应该是一个圆柱体,或者至少是一个圆柱体的镶嵌表示。我也不知道如何制作这些新的多边形来保持我的球体在一个镶嵌的表面上有一个洞。

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

    3 回复  |  直到 7 年前
        1
  •  2
  •   genpfault    14 年前

    听起来像你想要的 constructive solid geometry .

    Carve 可以做你想做的。如果只想运行时渲染 OpenCSG 会工作。

        2
  •  1
  •   Community CDub    7 年前

    今年早些时候,我使用标量字段实现了CSG操作。如果性能不重要,它会很好地工作。也就是说,计算不是实时的。问题是导数并不是到处都定义,所以你可以忘记用这种方法计算便宜的顶点法线。这必须作为一个后期步骤来完成。 关于我使用的论文(第一个答案),以及我所做的一些截图,请参阅此处:

    CSG operations on implicit surfaces with marching cubes

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

        3
  •  1
  •   Spektre    7 年前

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

    1. 使用模具缓冲区创建OpenGL上下文

      我正在使用8位作为模具,但此技术仅使用一位。

    2. 使用 0清除模具,然后关闭深度和颜色遮罩

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

    3. 设置模具with 1 for solid mesh

    4. 清除模具with 0 for hole meshes
    5. 打开深度和颜色遮罩,并渲染实体网格,其中stencil is 1 >

    在代码中,它看起来像这样:

    Glenable(gl_模具测试);
    //整个模具=0
    gl透明模板(0);
    glclear(gl_模具缓冲位);
    //关闭颜色、深度
    GL模板(0xFF);
    glcolormask(gl_假、gl_假、gl_假、gl_假);
    gldepthmask(gl_-false);
    //对于实体网格,模具=1
    glstencifunc(始终为gl_,1,0xff);
    glstencilop(gl_keep,gl_keep,gl_replace);
    glcylinderxz(0.0,y,0.0,r,qh);
    //对于孔网格,模具=0
    glstencifunc(始终为gl_,0,0xff);
    glstencilop(gl_keep,gl_keep,gl_replace);
    对于(b=0.0,j=0;j<12;j++,b+=db)
    {
    x= DeViR**CoS(b);
    Z= DeViR**Sin(B);
    glcylinderxz(x,y-0.1,z,dev_r,qh+0.2);
    }
    //打开颜色、深度
    glcolormask(gl_真、gl_真、gl_真、gl_真);
    gldepthmask(gl_真);
    //渲染实体网格模具测试将创建孔
    glstencifunc(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_模具测试);
    < /代码> 
    
    

    其中,glcylinderxz(x,y,z,r,h)is just function that render cylinder at(x,y,z)with radiusrwithy-axis as its rotation axis.dbis angle step(2*pi/12)。半径是r<-big,dev_r<-hole radius,dev_r<-hole centers andqh<-code>is the thickness of the plate.

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

    这种方法更适合于薄物体。如果切割导致足够厚的边,则需要添加切割边渲染,否则这些零件上的照明可能会出错。

    NCIL缓冲区用于渲染带有孔的球体。例如,我正在渲染圆盘(薄圆柱体),其外缘附近有圆孔(作为机械的底板),周围有固体和透明物体的组合,因此我需要的是真正的孔。因为我懒得对运行时生成的形状进行三角测量,所以我选择了模具。

    1. 使用模具缓冲区创建OpenGL上下文

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

    2. 清除模具0关闭深度和颜色遮罩

      这必须在使用模具渲染网格之前完成。因此,如果您有更多的对象以这种方式呈现,那么您需要在每个对象之前都这样做。

    3. 设置模具1用于实心网格

    4. 清除模具孔网
    5. 启用深度和颜色遮罩,并在模具所在的位置渲染实体网格

    代码如下:

    // [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). 半径是R-大,dev_r孔半径,dev_R-孔中心和qh是板的厚度。

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

    example

    这种方法更适合于薄物体。如果切割导致足够厚的边,则需要添加切割边渲染,否则这些零件上的照明可能会出错。