OpenGL曲面

来源:互联网 发布:access导入sql文件 编辑:程序博客网 时间:2024/04/28 13:32

曲面的构造可以是网格线和填充曲面形式,其实与曲线很类似只是变为二维而已。 1.曲面定义 void glMap2{fd}(GLenum target,TYPE u1,TYPE u2,GLint ustride,GLint uorder,                 TYPE v1,TYPE v2,GLint vstride,GLint vorder,TYPE points); target的定义同上次介绍的曲线中target的定义。 U V是二维曲面坐标 uorder,vorder;ustride,vstride的定义都类似曲线定义。 points是控制点坐标  2.曲面任意一点的计算 void glEvalCoord2{fd}[v](TYPE u,TYPE v); 以曲线坐标U V来计算曲面内任意一点的世界坐标的位置  3.曲面绘制的控制 void glMapGrid2{fd}(GLenum nu,TYPE u1,TYPE u2,GLenum nv,TYPE v1,TYPE v2); 定义曲面参数空间均匀网格,从u1到u2分为等间隔nu步,从v1到v2分为等间隔nv步。  下面给出一个以网格线描绘曲面的例子: //////////////////////////////////////////////////////////// #include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>#pragma comment(lib, "OpenGl32.lib")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma warning(disable : 4244)// MIPS#pragma warning(disable : 4136)// X86#pragma warning(disable : 4051)// ALPHA
void myinit(void); void CALLBACK  display(void); void CALLBACK  reshape(GLsizei w,GLsizei h);  //控制点坐标 GLfloat points[4][4][3]={         {{-1.5,-1.5,2.0},{-0.5,-1.5,2.0},         {0.5,-1.5,-1.0},{1.5,-1.5,2.0}},         {{-1.5,-0.5,1.0},{-0.5,1.5,2.0},         {0.5,0.5,1.0},{1.5,-0.5,-1.0}},         {{-1.5,0.5,2.0},{-0.5,0.5,1.0},         {0.5,0.5,3.0},{1.5,-1.5,1.5}},         {{-1.5,1.5,-2.0},{-0.5,1.5,-2.0},         {0.5,0.5,1.0},{1.5,1.5,-1.0}}};  //为了清楚显示控制点而设置的一组颜色 GLfloat color[4][3]={         {1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,1.0,1.0}};  void myinit(void) {          auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);         auxInitPosition(0,0,500,500);         auxInitWindow("sample1");         glClearColor(0.0,0.0,0.0,0.0);         glClear(GL_COLOR_BUFFER_BIT);  //利用glEnable()来启用曲面模式         glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&points[0][0][0]);         glEnable(GL_MAP2_VERTEX_3);          glMapGrid2f(20,0.0,1.0,20,0.0,1.0);          glEnable(GL_DEPTH_TEST); }  void CALLBACK reshape(GLsizei w,GLsizei h) {  glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity();  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0); else   glOrtho(-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }   void CALLBACK display(void) {   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);   glColor3f(0.0,0.0,1.0);   glPushMatrix();   glRotatef(35.0,1.0,1.0,1.0); //用直线段的连接描绘曲面结构   glBegin(GL_LINE_STRIP);   int i,j; //在U V方向各画出8条网格线,用以构造曲面结构   for(j=0;j<=8;j++)   {          //在U方向用30条直线段描绘一条曲线           glBegin(GL_LINE_STRIP);            for(i=0;i<=30;i++)             glEvalCoord2f((GLfloat)i/30.0,(GLfloat)j/8.0);           glEnd();                   //在V方向用30条直线段描绘一条曲线           glBegin(GL_LINE_STRIP);            for(i=0;i<=30;i++)                    glEvalCoord2f((GLfloat)j/8.0,(GLfloat)i/30.0);           glEnd();  }  //用不同的颜色把控制点显示出来   glPointSize(4.0);   glBegin(GL_POINTS);   for(i=0;i<4;i++)   for(j=0;j<4;j++)   {       glColor3fv(color[i]);       glVertex3fv(&points[i][j][0]);   }   glEnd();    glPopMatrix();   glFlush(); } void main(void) {     myinit();          auxReshapeFunc(reshape);     auxMainLoop(display); } //end of sample ///////////////////////////////////////////////////////  应用中常常不满足曲面的框架结构。下面就介绍填充曲面的绘制方法:  void glEvalMesh2(GLenum mode,GLint p1,GLint p2,GLint q1,GLint q2); 把用glMapGrid2{fd}()设置的网格应用到已经启用的曲面计算上。 mode可以是GL_POINT GL_LINE GL_FILL。顾名思义,GL_FILL就是生成填充曲面  这里给出一个有光照处理的BEZIER曲面的例子(这个曲面除了绘制方法不同,数学 形式和前面的是一样的)。 /////////////////////////////////////////////////////// //sample.cpp #include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>#pragma comment(lib, "OpenGl32.lib")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma warning(disable : 4244)// MIPS#pragma warning(disable : 4136)// X86#pragma warning(disable : 4051)// ALPHA
void myinit(void); void CALLBACK  display(void); void CALLBACK  reshape(GLsizei w,GLsizei h);  GLfloat points[4][4][3]={         {{-1.5,-1.5,2.0},{-0.5,-1.5,2.0},         {0.5,-1.5,-1.0},{1.5,-1.5,2.0}},         {{-1.5,-0.5,1.0},{-0.5,1.5,2.0},         {0.5,0.5,1.0},{1.5,-0.5,-1.0}},         {{-1.5,0.5,2.0},{-0.5,0.5,1.0},         {0.5,0.5,3.0},{1.5,-1.5,1.5}},         {{-1.5,1.5,-2.0},{-0.5,1.5,-2.0},         {0.5,0.5,1.0},{1.5,1.5,-1.0}}}; GLfloat color[4][3]={         {1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,1.0,1.0}};  //初始化光照、材质的过程 void initlights(void) {         GLfloat ambient[]={0.4,0.6,0.2,1.0};         GLfloat position[]={0.0,1.0,3.0,1.0};         GLfloat mat_diffuse[]={0.2,0.4,0.8,1.0};         GLfloat mat_specular[]={1.0,1.0,1.0,1.0};         GLfloat mat_shininess[]={80.0};         glEnable(GL_LIGHTING);         glEnable(GL_LIGHT0);         glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);         glLightfv(GL_LIGHT0,GL_POSITION,position);         glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);         glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);         glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); }  void myinit(void) {          auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);         auxInitPosition(0,0,500,500);         auxInitWindow("sample1");         glClearColor(0.0,0.0,0.0,0.0);         glClear(GL_COLOR_BUFFER_BIT);          glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&points[0][0][0]);         glEnable(GL_MAP2_VERTEX_3);         glEnable(GL_AUTO_NORMAL); //      glEnable(GL_NORMALIZE);         glMapGrid2f(20,0.0,1.0,20,0.0,1.0);          glEnable(GL_DEPTH_TEST); //初始化光照、材质         initlights(); //      glShadeModel(GL_FLAT); }  void CALLBACK reshape(GLsizei w,GLsizei h) {  glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity();  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0); else   glOrtho(-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }   void CALLBACK display(void) {   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);   glColor3f(0.0,0.0,1.0);   glPushMatrix();   glRotatef(35.0,1.0,1.0,1.0);  //将原来网格的绘制部分注释掉,代替以填充曲面的绘制方法   glEvalMesh2(GL_FILL,0,20,0,20);   int i,j; /*  for(j=0;j<=8;j++)   {           glBegin(GL_LINE_STRIP);            for(i=0;i<=30;i++)             glEvalCoord2f((GLfloat)i/30.0,(GLfloat)j/8.0);           glEnd();                      glBegin(GL_LINE_STRIP);            for(i=0;i<=30;i++)                    glEvalCoord2f((GLfloat)j/8.0,(GLfloat)i/30.0);           glEnd();  } */    glPointSize(4.0);   glBegin(GL_POINTS);   for(i=0;i<4;i++)   for(j=0;j<4;j++)   {       glColor3fv(color[i]);           glVertex3fv(&points[i][j][0]);   }   glEnd();   glPopMatrix();   glFlush(); } void main(void) {         myinit();          auxReshapeFunc(reshape);     auxMainLoop(display); } //end of sample //////////////////////////////////////////////////////////////// 一个真正具有实体的曲面就展现出来乐。控制点的不同,可以控制曲面的形状 可以看出OPENGL的强大功能,只用很少的原代码就产生真实的3D效果。 在以此篇结束复杂建模前,给出一个绘制NURBS曲面(非均匀B样条曲面)的例子, 这里用到乐一些OPENGL实用库提供的专门函数。所有的新东东都在程序中做乐注 释,注释给出过程的含义,具体函数的操作可以详细查阅联机手册。 /////////////////////////////////////////////////////////////// //sample.cpp #include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>#pragma comment(lib, "OpenGl32.lib")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma warning(disable : 4244)// MIPS#pragma warning(disable : 4136)// X86#pragma warning(disable : 4051)// ALPHA void myinit(void); void CALLBACK  display(void); void CALLBACK  reshape(GLsizei w,GLsizei h);  //定义一组控制点的存储空间 GLfloat points[4][4][3]; //定义一个指向NURBS曲面对象的指针 GLUnurbsObj *theNurb;  //用来生成控制点的过程,取代被注释掉的原来直接赋值方式生成控制点 void init_surface(void) {         int u,v;         for(u=0;u<4;u++)         {                 for(v=0;v<4;v++)                 {                         points[u][v][0]=2.0*((GLfloat)u-1.5);                         points[u][v][1]=2.0*((GLfloat)v-1.5);                         if((u==1||u==2)&&(v==1||v==2))                                 points[u][v][2]=3.0;                 else                         points[u][v][2]=-3.0;                 }         } } /*                        GLfloat points[4][4][3]={         {{-1.5,-1.5,2.0},{-0.5,-1.5,4.0},         {0.5,-1.5,3.0},{1.5,-1.5,2.0}},         {{-1.5,-0.5,3.0},{-0.5,1.5,4.0},         {0.5,0.5,2.0},{1.5,-0.5,-1.0}},         {{-1.5,0.5,2.0},{-0.5,0.5,4.0},         {0.5,0.5,5.0},{1.5,-1.5,1.5}},         {{-1.5,1.5,-2.0},{-0.5,1.5,3.0},         {0.5,0.5,1.0},{1.5,1.5,-1.0}}}; */ GLfloat color[4][3]={         {1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{1.0,1.0,1.0}};   void initlights(void) {         GLfloat ambient[]={0.4,0.6,0.2,1.0};         GLfloat position[]={0.0,1.0,3.0,1.0};         GLfloat mat_diffuse[]={0.2,0.4,0.8,1.0};         GLfloat mat_specular[]={1.0,1.0,1.0,1.0};         GLfloat mat_shininess[]={80.0};         glEnable(GL_LIGHTING);         glEnable(GL_LIGHT0);         glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);         glLightfv(GL_LIGHT0,GL_POSITION,position);         glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);         glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);         glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); //首先初始化控制点         init_surface(); //创建一个NURBS曲面的对象         theNurb=gluNewNurbsRenderer(); //修改此曲面对象的属性         gluNurbsProperty(theNurb,GLU_SAMPLING_TOLERANCE,25.0);         gluNurbsProperty(theNurb,GLU_DISPLAY_MODE,GLU_FILL); }  void myinit(void) {          auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);         auxInitPosition(0,0,500,500);         auxInitWindow("sample1");         glClearColor(0.0,0.0,0.0,0.0);         glClear(GL_COLOR_BUFFER_BIT);          glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&points[0][0][0]);         glEnable(GL_MAP2_VERTEX_3);         glEnable(GL_AUTO_NORMAL);         glEnable(GL_NORMALIZE);         glMapGrid2f(20,0.0,1.0,20,0.0,1.0);          glEnable(GL_DEPTH_TEST);         initlights(); //      glShadeModel(GL_FLAT); }  void CALLBACK reshape(GLsizei w,GLsizei h) {  glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity();  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0); else   glOrtho(-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }   void CALLBACK display(void) { //B样条曲面(NURBS)的控制向量,可以参阅图形学的相关书籍   GLfloat knots[8]={0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0};    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);   glColor3f(0.0,0.0,1.0);   glPushMatrix();   glRotatef(35.0,1.0,1.0,1.0);   glRotatef(-60.0,1.0,0.0,0.0);   glScalef(0.5,0.5,0.5);  //注释掉原来的曲面绘制函数,代之以新的NURBS曲面绘制函数   //  glEvalMesh2(GL_FILL,0,20,0,20); //定义曲面的数学模型,确定其形状   gluNurbsSurface(theNurb,           8,knots,           8,knots,           4*3,           3,           &points[0][0][0],           4,4,           GL_MAP2_VERTEX_3); //结束曲面的绘制,此结构很类似于标准的glBegin()...glEnd()   gluEndSurface(theNurb);    int i,j;   glPointSize(4.0);   glBegin(GL_POINTS);   for(i=0;i<4;i++)   for(j=0;j<4;j++)   {       glColor3fv(color[i]);           glVertex3fv(&points[i][j][0]);   }   glEnd();   glPopMatrix();   glFlush();   } void main(void) {     myinit();          auxReshapeFunc(reshape);     auxMainLoop(display); } //end of sample ////////////////////////////////////////////////////////////////// 至此,复杂建模告于段落。下次介绍特殊光照