用OpenGL绘制裁剪曲面时,发现裁剪后的曲面方向不对,很急!! 40C

我将Nurbs曲面数据点读入后,画曲面没有问题,但在增加裁剪过程的时候发现被裁剪曲面的方向不对,如图所示:
图片说明
原本应该是上面的平面和下面的环拼接在一起的,但是画出来以后就错位,检查后发现数据点没问题,所以应该是裁剪中的错误,很急,恳请会的大神帮助一下,谢谢了!!

下面是我的绘制程序:
void COpenGLDC::DrawNurbsSurface(const CVector3D* pts,int uSize,int vSize,int uOrder,int vOrder,float* Weight,CNurbsCurve* OuterTrimCurve,vectorInerTrimCurve,float* uKnots , float* vKnots ,bool Trim ) //参数pts:曲面组),uSize:u向节点矢量个数,vSize:v向节点矢量个数
//uOrder:u向阶数,vOrder:v向阶数, Weight:曲面的权因子(一维数组)
//OuterTrimCurv:外圈裁剪曲线,InerTrimCurve:内圈裁剪曲线,uKnots:u向节点矢量
//vKnots:v向节点矢量

{
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
//glCullFace( GL_BACK );
glEnable(GL_AUTO_NORMAL);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);

int iner_size = InerTrimCurve.size();
int size = uSize*vSize;
GLfloat* ctrlPts = new GLfloat[size*3];

for(int i=0; i<size; i++)   {
    ctrlPts[i*3]   = pts[i].dx;
    ctrlPts[i*3+1] = pts[i].dy;
    ctrlPts[i*3+2] = pts[i].dz;
}

int a=sizeof(ctrlPts);

GLUnurbsObj *pNurbsObj = gluNewNurbsRenderer();

gluNurbsProperty(pNurbsObj,GLU_SAMPLING_TOLERANCE,100);
gluNurbsProperty(pNurbsObj,GLU_DISPLAY_MODE,(GLfloat) GLU_FILL);

gluBeginSurface(pNurbsObj);
    gluNurbsSurface(pNurbsObj,                               //绘制曲面
        vSize+vOrder, vKnots,
        uSize+uOrder, uKnots,
        uSize*3,
        3,
        ctrlPts,
        vOrder,
        uOrder,
        GL_MAP2_VERTEX_3);
    if(Trim == TRUE)                                                 //如果曲面被裁剪,绘制裁剪曲面
    {
        int Trim_size = OuterTrimCurve->m_Size;
        GLfloat* Trim_ctrlPts = new GLfloat[Trim_size*3];
        for(int i=0; i<Trim_size; i++)  {
            Trim_ctrlPts[i*3]   = OuterTrimCurve->m_ctrlPts[i].dx;
            Trim_ctrlPts[i*3+1] = OuterTrimCurve->m_ctrlPts[i].dy;
            Trim_ctrlPts[i*3+2] = OuterTrimCurve->m_ctrlPts[i].dz;
        }
        gluBeginTrim(pNurbsObj);
                    gluNurbsCurve(pNurbsObj,                       //外圈裁剪曲线
                    OuterTrimCurve->m_Size+OuterTrimCurve->m_Order,
                    OuterTrimCurve->m_Knots,
                    3,
                    (float*) Trim_ctrlPts,
                    OuterTrimCurve->m_Order,
                    GLU_MAP1_TRIM_2);
        gluEndTrim(pNurbsObj);
        delete [] Trim_ctrlPts;

            /*for(int j=0;j<iner_size;j++)
            {
                int Trim1_size = InerTrimCurve[j]->m_Size;
                GLfloat* Trim1_ctrlPts = new GLfloat[Trim1_size*3];
                for(int i=0; i<Trim1_size; i++) {
                    Trim1_ctrlPts[i*3]   = InerTrimCurve[j]->m_ctrlPts[i].dx;
                    Trim1_ctrlPts[i*3+1] = InerTrimCurve[j]->m_ctrlPts[i].dy;
                    Trim1_ctrlPts[i*3+2] = InerTrimCurve[j]->m_ctrlPts[i].dz;
                }
                gluBeginTrim(pNurbsObj);
                            //gluNurbsProperty(pNurbsObj,GLU_SAMPLING_TOLERANCE,25.0);
                            gluBeginCurve(pNurbsObj);
                                gluNurbsCurve(pNurbsObj,
                                InerTrimCurve[j]->m_Size+InerTrimCurve[j]->m_Order,
                                InerTrimCurve[j]->m_Knots,
                                3,
                                (float*) Trim1_ctrlPts,
                                InerTrimCurve[j]->m_Order,
                                GL_MAP1_VERTEX_3);
                            gluEndCurve(pNurbsObj);
                gluEndTrim(pNurbsObj);
                delete [] Trim1_ctrlPts;
            }*/
}

gluEndSurface(pNurbsObj);

if(pNurbsObj)
    gluDeleteNurbsRenderer(pNurbsObj);

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE); 
glCullFace(GL_BACK|GL_FRONT);
glEnable(GL_CULL_FACE);
glFlush();
delete [] ctrlPts;

}

1个回答

要画出一个曲面,首先要有曲面的表达方式。对于OpenGL渲染而言,个人觉得曲面可以分“参数曲面”跟“非参数曲面”两种。  参数曲面的通常由一组控制点(称为Patch,可以理解为一个很粗糙的曲面)定义,用一个正方形或者单位等边三角形作为参数空间(称为Domain),在Domain上通过一定精细度采样多个参数点,最后把这些Domain上的采样点映射到Patch所在空间上的三维点坐标,构成比Patch更加精细的曲面。
非参数化的曲面不像参数曲面那样直接算出曲面点,它是通过某种细分算法逐步把Patch细分的,例如Catmull-Clark【1】曲面是通过递归细分得到的,这种方法没办法通过GPU硬件直接支持,但可以通过参数曲面近似模拟之【2】。  
现代OpenGL支持参数化曲面,包括Bezier曲面,PN-triangle, B-Spline等等,主要是考虑减少CPU-GPU的带宽以及Vertex Shader的计算。理论上应用可以在pipeline外边用software自行根据细分规则,通过参数也好,通过递归也好,生成光滑精细的Mesh,然后把曲面上的三角形逐个送入GPU去rendering,但这种方法明显性能不好。  新的OpenGL引入Tessellation Shader来渲染曲面,包含三大块:Control Shader, Primitive Generator,Evaluation Shader。Tessellation Shader的输入仅仅是Control point而非Mesh。
(1)Control Shader是可编程的,负责对patch做变换,比如我们旋转patch,那么后面生成的整个精细曲面会被旋转,作用:便于更轻量地实现动画
在Control Shader可以改变控制点的数量,做任意自由的变换。如有必要,它还可以计算一些整个Patch共享的常量(Patch Constant)给Evaluation Shader使用,这个就不展开了。
(2)Primitive Generator是个不可编程但可配置的模块,负责在一个Domain上按应用指定的精细程度采样Domain点,在Domain空间上实现了细分,最终要Evaluate Shader将Domain坐标变成三维坐标。
(3)Evaluation Shader也是可编程模块,Control Shader会把转化后的新Patch送给Evaluation Shader,Primitive Generator所有采样点送给Evaluation Shader,然后Evaluation Shader根据应用写的Shader(evalute公式)把每个采样点转化为三维曲面三维坐标点,众多的曲面点就能构成了更精细的曲面了。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!