AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

基于VC++的OpenGL编程讲座之曲线和曲面

51自学网 2015-08-30 http://www.wanshiok.com

  二、曲面构造

  曲面的绘制方法基本上与曲线的绘制方法是相同的,所不同的是曲面使用二维求值器,并且控制点连接起来形成一个网格。

  对于曲面,求值器除了使用二个参数U、V之外,其余与一维求值器基本相同。顶点坐标 、颜色、法线矢量和纹理坐标都对应于曲面而不是曲线。在OpenGL中定义二维求值器的函数是:

void glMap2{fd}(GLenum target,TYPE u1,TYPE u2,GLint ustride,GLint uorder,TYPE v1,TYPE v2,
GLint vstride,GLint vorder,TYPE points);

  参数target可以是表一中任意值,不过需将MAP1改为MAP2。同样,启动曲面的函数仍是glEnable(),关闭是glDisable()。u1、u2为u的最大值和最小值;v1、v2为v的最大值和最小值。参数ustride和vstride指出在控制点数组中u和v向相邻点的跨度,即可从一个非常大的数组中选择一块控制点长方形。例如,若数据定义成如下形式:

GLfloat ctlpoints[100][100][3];

  并且,要用从ctlpoints[20][30]开始的4x4子集,选择ustride为100*3,vstride为3,初始点设置为ctlpoints[20][30][0]。最后的参数都是阶数,uorder和vorder,二者可以不同。

  曲面坐标计算函数为:

void glEvalCoord2{fd}[v](TYPE u,TYPE v);

  该函数产生曲面坐标并绘制。参数u和v是定义域内的值。下面看一个绘制Bezier曲面的例子:

/* 控制点的坐标 */
  GLfloat ctrlpoints[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}}
};
void myinit(void)
{
    glClearColor (0.0, 0.0, 0.0, 1.0);
    glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&ctrlpoints[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 display(void)
  {
    int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(0.3, 0.6, 0.9);
    glPushMatrix ();
    glRotatef(35.0, 1.0, 1.0, 1.0);
    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();
    }
    glPopMatrix ();
    glFlush();
  }

  OpenGL中定义均匀间隔的曲面坐标值的函数与曲线的类似,其函数形式为:

void glMapGrid2{fd}(GLenum nu,TYPE u1,TYPE u2,GLenum nv,TYPE v1,TYPE v2);
void glEvalMesh2(GLenum mode,GLint p1,GLint p2,GLint q1,GLint q2);

  第一个函数定义参数空间的均匀网格,从u1到u2分为等间隔的nu步,从v1到v2分为等间隔的nv步,然后glEvalMesh2()把这个网格应用到已经启动的曲面计算上。第二个函数参数mode除了可以是GL_POINT和GL_LINE外,还可以是GL_FILL,即生成填充空间曲面。

  下面举出一个用网格绘制一个经过光照和明暗处理的Bezier曲面的例程:

#include "glos.h"
#include
#include
#include
void myinit(void);
void initlights(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
/* 控制点坐标 */
GLfloat ctrlpoints[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}}
};
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 CALLBACK display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glPushMatrix();
 glRotatef(35.0, 1.0, 1.0, 1.0);
 glEvalMesh2(GL_FILL, 0, 20, 0, 20);
 glPopMatrix();
 glFlush();
}
void myinit(void)
{
    glClearColor (0.0, 0.0, 0.0, 1.0);
  glEnable (GL_DEPTH_TEST);
 glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12,
4, &ctrlpoints[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);
initlights();
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if (w <= h)
glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
else
  glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void main(void)
{
  auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
 auxInitPosition (0, 0, 500, 500);
 auxInitWindow ("Lighted and Filled Bezier Surface");
 myinit();
 auxReshapeFunc (myReshape);
 auxMainLoop(display);
}

 

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:VC与Matlab接口编程之Matcom安装配置  下一篇:VC++实现单文档程序的全屏显示及恢复