第6章代码-三维造型

6.3.4编程实例-简单实体构建

本实例参考了著名的Nehe OpenGL示例构建了四棱锥和立方体的实体模型,这两个模型的顶点位置如图6.13所示。可见,四棱锥的四个侧面的顶点序列分别为v0v1v2、v0v2v3、v0v3v4、v0v4v1,底面为v1v2v3v4。传递顶点信息时使用了glVertex3fv函数,以顶点首地址作为参数,比glVertex3f函数直接用顶点坐标作为参数的方式更为方便、直观。在坐标系原点建好的实体可以通过几何变换放置在任意不同的位置。在本示例中,四棱锥被放置在左侧,立方体被放置在右侧。
在这里插入图片描述

#include <gl/glut.h>  
#include<iostream>
using namespace std;
float	rtri;
float	rquad; 
GLfloat points0[5][3] ={{ 0, 1,  0}, {-1, -1, 1}, { 1, -1, 1}, {	1, -1, -1},{-1, -1,-1}};
GLfloat points1[8][3]={ { 1, 1, -1 }, {-1, 1, -1}, {-1, 1, 1}, { 1, 1, 1},
    { 1, -1, 1 }, {-1, -1, 1}, {-1,-1,-1}, { 1, -1, -1}};
GLfloat Colors0[4][3]={{1,0,0},{0,1,0}, {0,0,1},{1,1,0}};	//四棱锥的颜色
//下行是立方体的颜色
GLfloat Colors1[6][3]={{0,1,0},{1,0.5,0},{1,0,0},{1,1,0},{0,0,1},{1,0,1}};
int vertice0[4][3]={{0,1,2},{0,2,3},{0,3,4},{0,4,1}};	//四棱锥的顶点号序列
//下行是立方体的顶点号序列
int vertice1[6][4]={{0,1,2,3},{4,5,6,7},{3,2,5,4},{7,6,1,0},{2,1,6,5}, {0,3,4,7}};
void InitGL ( GLvoid )    
{
    glShadeModel(GL_SMOOTH);					
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);			
    glClearDepth(1.0f);								
    glEnable(GL_DEPTH_TEST);							
    glDepthFunc(GL_LEQUAL);							
    glEnable ( GL_COLOR_MATERIAL );
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glPolygonMode(GL_FRONT, GL_FILL);//控制多边形的正面与背面绘制模式,此处设为正面填充绘制
	glPolygonMode(GL_BACK, GL_LINE);//背面为轮廓线绘制
}
void CreatePyramid()
{
    glBegin(GL_TRIANGLES);
    for(int i=0;i<4;i++)
    {
            glColor3fv(Colors0[i]);
            for(int j=0;j<3;j++)
            {
                int VtxId=vertice0[i][j];
                glVertex3fv(points0[VtxId]);
            }
    }
    glEnd();
    glBegin( GL_QUADS); 	//构建底面
    glColor3f(1.0f, 1.0f, 1.0f );
    for(i=0;i<4;i++)
        glVertex3fv(points0[i]);	
    glEnd();
}
void CreateCube()
{
    glBegin(GL_QUADS);	
    for(int i=0;i<6;i++)
    {
        glColor3fv(Colors1[i]);
        for(int j=0;j<4;j++)
        {
            int VtxId=vertice1[i][j];
            glVertex3fv(points1[VtxId]);
        }
    }
    glEnd();						
}
void display ( void )   
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
    glLoadIdentity();	
    glPushMatrix();
    glTranslatef(-1.5f,0.0f,-6.0f);	//平移至左侧
    glRotatef(rtri,0.0f,1.0f,0.0f);	//旋转一个角度
    CreatePyramid();	//创建三角塔

    glLoadIdentity();	//将矩阵归一化回原样    
    glTranslatef(1.5f,0.0f,-6.0f);	//平移到右侧
    glRotatef(rquad,1.0f,0.0f,0.0f);	//旋转一个角度
    CreateCube(); 	//创建立方体
    glPopMatrix();
    
    rtri+=0.2f;	//修改三角塔旋转角度
    rquad-=0.15f;	//修改立方体的旋转角度
    glutSwapBuffers ( );  
}
void reshape ( int width , int height )  
{
    if (height==0)									
        height=1;										
    glViewport(0,0,width,height);	
    glMatrixMode(GL_PROJECTION);						
    glLoadIdentity();									
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);							
    glLoadIdentity();									
}
void main ( int argc, char** argv )  
{
    glutInit ( &argc, argv ); 
    glutInitDisplayMode ( GLUT_RGBA | GLUT_DOUBLE ); 
    glutInitWindowSize ( 600, 400 ); 
    glutCreateWindow ( "Pyramid and cube" );
    InitGL();
    glutDisplayFunc ( display ); 
    glutReshapeFunc ( reshape );
    glutIdleFunc ( display );
    glutMainLoop ( );
}

6.4.3 Bezier曲线曲面

1. 调和函数方式绘制Bezier曲线

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

struct Point {
	int x, y;
};

int ctrlPtNum = 0;
Point ctrlPt[4];
int bzSegNum = 20;
Point *bzPt = new Point[bzSegNum];

float white[3] = { 1.0f, 1.0f, 1.0f };
float red[3] = { 1.0f, 0.0f, 0.0f };

void CalcBZPtByBaseFunc()
{
	double B0, B1, B2, B3;	//调和函数
	double u;
	double t = 0.0;
	double dt = 1.0 / bzSegNum;
	for (int i = 0; i < bzSegNum + 1; i++)
	{
		u = 1.0 - t;
		B0 = u * u * u;
		B1 = 3 * t * u * u;
		B2 = 3 * t * t * u;
		B3 = t * t * t;
		bzPt[i].x = ctrlPt[0].x * B0 + ctrlPt[1].x * B1 + ctrlPt[2].x * B2 + ctrlPt[3].x * B3;
		bzPt[i].y = ctrlPt[0].y * B0 + ctrlPt[1].y * B1 + ctrlPt[2].y * B2 + ctrlPt[3].y * B3;
		t += dt;
	}
}

void DisplayCtrlPt(Point *pt)
{
	glPointSize(4);
	for (int i = 0; i < ctrlPtNum; i++)
	{
		glBegin(GL_POINTS);
		glColor3fv(red);
		glVertex2i(pt[i].x, pt[i].y);
		glEnd();
	}
}

void DrawLineStrip(Point *pt, int num, float *clr)
{
	glBegin(GL_LINE_STRIP);
	for (int i = 0; i < num; i++)
	{
		glColor3fv(clr);
		glVertex2i(pt[i].x, pt[i].y);
	}
	glEnd();
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	DisplayCtrlPt(ctrlPt);

	if (ctrlPtNum == 4)
	{
		DrawLineStrip(ctrlPt, ctrlPtNum, red);
		DrawLineStrip(bzPt, bzSegNum + 1, white);
	}

	glFlush();
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);

	printf("Please Click left button of mouse to input control point of Bezier Curve!\n");
}

void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}

void mouse(int button, int state, int x, int y)
{
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
		{
			if (ctrlPtNum == 4)
				ctrlPtNum = 0;

			ctrlPtNum++;
			ctrlPt[ctrlPtNum - 1].x = x;
			ctrlPt[ctrlPtNum - 1].y = 480 - y;

			if (ctrlPtNum == 4)
				CalcBZPtByBaseFunc();
		}

		glutPostRedisplay();
		break;

	default:
		break;
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Hello World!");

	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutMouseFunc(mouse);
	glutMainLoop();
	return 0;
}

2. 离散方式绘制Bezier曲线

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

struct Point {
	int x, y;
};

int ctrlPtNum = 0;
Point ctrlPt[4];
int bzSegNum = 20;
Point *bzPt = new Point[bzSegNum];

float white[3] = { 1.0f, 1.0f, 1.0f };
float red[3] = { 1.0f, 0.0f, 0.0f };

void CalcBZPtByCasteljau()
{
	double t = 0.0;
	double dt = 1.0 / bzSegNum;
	Point p01, p11, p21, p02, p12;
	for (int i = 0; i < bzSegNum + 1; i++)
	{
		p01.x = (1 - t)*ctrlPt[0].x + t * ctrlPt[1].x;
		p01.y = (1 - t)*ctrlPt[0].y + t * ctrlPt[1].y;

		p11.x = (1 - t)*ctrlPt[1].x + t * ctrlPt[2].x;
		p11.y = (1 - t)*ctrlPt[1].y + t * ctrlPt[2].y;

		p21.x = (1 - t)*ctrlPt[2].x + t * ctrlPt[3].x;
		p21.y = (1 - t)*ctrlPt[2].y + t * ctrlPt[3].y;

		p02.x = (1 - t)*p01.x + t * p11.x;
		p02.y = (1 - t)*p01.y + t * p11.y;

		p12.x = (1 - t)*p11.x + t * p21.x;
		p12.y = (1 - t)*p11.y + t * p21.y;

		bzPt[i].x = (1 - t)*p02.x + t * p12.x;
		bzPt[i].y = (1 - t)*p02.y + t * p12.y;

		t += dt;
	}
}

void DisplayCtrlPt(Point *pt)
{
	glPointSize(4);
	for (int i = 0; i < ctrlPtNum; i++)
	{
		glBegin(GL_POINTS);
		glColor3fv(red);
		glVertex2i(pt[i].x, pt[i].y);
		glEnd();
	}
}

void DrawLineStrip(Point *pt, int num, float *clr)
{
	glBegin(GL_LINE_STRIP);
	for (int i = 0; i < num; i++)
	{
		glColor3fv(clr);
		glVertex2i(pt[i].x, pt[i].y);
	}
	glEnd();
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	DisplayCtrlPt(ctrlPt);

	if (ctrlPtNum == 4)
	{
		DrawLineStrip(ctrlPt, ctrlPtNum, red);
		DrawLineStrip(bzPt, bzSegNum + 1, white);
	}

	glFlush();
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);

	printf("Please Click left button of mouse to input control point of Bezier Curve!\n");
}

void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}

void mouse(int button, int state, int x, int y)
{
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
		{
			if (ctrlPtNum == 4)
				ctrlPtNum = 0;

			ctrlPtNum++;
			ctrlPt[ctrlPtNum - 1].x = x;
			ctrlPt[ctrlPtNum - 1].y = 480 - y;

			if (ctrlPtNum == 4)
				CalcBZPtByCasteljau();
		}

		glutPostRedisplay();
		break;

	default:
		break;
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Hello World!");

	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutMouseFunc(mouse);
	glutMainLoop();
	return 0;
}

6.4.6 编程实例-OpenGL曲线曲面生成

在这里插入图片描述

1.绘制Bezier曲线

#include <GL/glut.h>
GLfloat ctrlpoints[4][3] = 
{{ -4.0, -4.0, 0.0}, { -2.0, 3.0, 0.0},
{2.0, 4.5, 0.0}, {3.0, -3.0, 0.0}};
void init(void)
{
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glShadeModel(GL_FLAT);
    //下行用于定义曲线函数
    glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]); 
    glEnable(GL_MAP1_VERTEX_3);	//将当前曲线函数激活
}
void display(void)
{
    int i;
    glClear(GL_COLOR_BUFFER_BIT);
    //下面用求值器按20等分计算Bezier曲线上的点
    glColor3f(0.0, 0.0, 0.0);
    glLineWidth(2);
    glBegin(GL_LINE_STRIP);
    for (i = 0; i <= 20; i++)
        glEvalCoord1f((GLfloat) i/20.0);	//相当于调用了glVertex*()
    glEnd();
    //下面绘制控制多边形
    glLineWidth(1);
    glColor3f(0.0, 0.0, 1.0);	
    glBegin(GL_LINE_STRIP);
    for (i = 0; i < 4; i++)
        glVertex3fv(&ctrlpoints[i][0]);
    glEnd();
    glFlush();
}
void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei) w, (GLsizei) 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)w/(GLfloat)h, 5.0*(GLfloat)w/(GLfloat)h,
          -5.0, 5.0, -5.0, 5.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (argv[0]);
    init ();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

2.绘制Bezier曲面

#include <GL/glut.h>
GLfloat ctrlpoints[4][4][3] = {
{{-3, 0, 4.0}, {-2, 0, 2.0}, {-1, 0, 0.0}, {0, 0, 2.0}},
{{-3, 1, 1.0}, {-2, 1, 3.0}, {-1, 1, 6.0}, {0, 1, -1.0}},
{{-3, 2, 4.0}, {-2, 2, 0.0}, {-1, 2, 3.0}, {0, 2, 4.0}},
{{-3, 3, 0.0}, {-2, 3, 0.0}, {-1, 3, 0.0}, {0, 3, 0.0}}
};
void display(void)
{
    int i, j;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(0.0, 0.0, 0.0);
    glPushMatrix ();
    glRotatef(85.0, 1.0, 1.0, 1.0);
    for (j = 0; j <= 20; j++)
    {
        glBegin(GL_LINE_STRIP);
        for (i = 0; i <= 20; i++)
            glEvalCoord2f((GLfloat)i/20.0, (GLfloat)j/20.0);	//调用求值器
        glEnd();
        glBegin(GL_LINE_STRIP);
        for (i = 0; i <= 20; i++)
            glEvalCoord2f((GLfloat)j/20.0, (GLfloat)i/20.0);	//调用求值器
        glEnd();
    }
    glPopMatrix ();
    glFlush();
}
void init(void)
{
    glClearColor (1.0, 1.0, 1.0, 0.0);
    //下行的代码用控制点定义Bezier曲面函数
    glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
    glEnable(GL_MAP2_VERTEX_3);  	//激活该曲面函数
    glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0); 	//构造平行投影矩阵
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图形空间

文章不错,赞赏鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值