opengl进阶技巧(二)glut绘制贝塞尔曲线

https://my.oschina.net/sweetdark/blog/184313

曲线以及曲面

/*
	MultiBezier.C
	Code by 523066680, 2016-09-27
	[email protected]
*/

#include <GL/glut.h>
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include <chrono>
#include <thread>

//窗口尺寸
#define SIZE_X 500
#define SIZE_Y 500

const double PI = 3.14159265;
const double PI2 = 3.14159265 * 2;

#define LINES    20
#define PARTS    50
#define CP_PARTS 50
#define CP_STEP  1.0/CP_PARTS

// LINES 积累的线的数量,而非细分数量
// PARTS 单条曲线细分的数量
// CP_PARTS 控制点移动轨迹的细分量

typedef struct
{
	float x;
	float y;
}
point;

typedef struct
{
	point cp[4];
	float index;
}
ControlPoint;

point MultiLine[LINES][PARTS];

int winID;

// PointOnCubicBeizer Function, copy from:
// https://zh.wikipedia.org/wiki/貝茲曲線
point PointOnCubicBeizer(point cp[4], float t)
{
	float cx, bx, ax, cy, by, ay;
	float tSquared, tCubed;
	point result;

	cx = 3.0 * (cp[1].x - cp[0].x);
	bx = 3.0 * (cp[2].x - cp[1].x) - cx;
	ax = cp[3].x - cp[0].x - cx - bx;

	cy = 3.0 * (cp[1].y - cp[0].y);
	by = 3.0 * (cp[2].y - cp[1].y) - cy;
	ay = cp[3].y - cp[0].y - cy - by;

	tSquared = t * t;
	tCubed = tSquared * t;

	result.x = ((ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x);
	result.y = ((ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y);
	return result;
}

void display(void)
{
	glBegin(GL_POINTS);
	glColor4f(0.3, 0.5, 0.8, 0.4);

	for (int i = 0; i < LINES; i++)
	{
		for (int j = 0; j < PARTS; j++)
		{
			glVertex3f(MultiLine[i][j].x, MultiLine[i][j].y, 0.0);
		}
	}
	glEnd();

	glutSwapBuffers();
}

//闲时回调函数,主要负责计算、延时
void idle(void)
{
	//临时坐标变量
	point coord;

	//主控制点,通过PointOnCubicBeizer函数和cp[4]数据获取坐标
	point MainCp[4];

	static int MainIdx = 0;

	//ControlPoint 结构包含 控制点、曲线进度信息
	static ControlPoint cp[4] =
	{
		0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
		0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
		0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
		0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
	};

	glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();

	//4个控制点的变化和进度
	for (int i = 0; i < 4; i++)
	{
		cp[i].index += CP_STEP;

		//index超过1.0时重新设定控制点
		if (cp[i].index >= 1.0)
		{
			//上一个终点作为新的起点
			cp[i].cp[0].x = cp[i].cp[3].x;
			cp[i].cp[0].y = cp[i].cp[3].y;

			//使第一控制点与上次曲线对称(减少尖突的情况)
			cp[i].cp[1].x = cp[i].cp[3].x + (cp[i].cp[3].x - cp[i].cp[2].x);
			cp[i].cp[1].y = cp[i].cp[3].y + (cp[i].cp[3].y - cp[i].cp[2].y);

			//后面两个点随机
			for (int ii = 2; ii < 4; ii++)
			{
				cp[i].cp[ii].x = (float)(rand() % 500 - 250);
				cp[i].cp[ii].y = (float)(rand() % 500 - 250);
			}

			//从1单位的CP_STEP开始,而非0.0,避免重合显示
			cp[i].index = CP_STEP;
		}

		coord = PointOnCubicBeizer(cp[i].cp, cp[i].index);

		MainCp[i].x = coord.x;
		MainCp[i].y = coord.y;
	}

	//当前曲线坐标写入数组
	for (int i = 0; i < PARTS; i++)
	{
		coord = PointOnCubicBeizer(MainCp, (float)i / (float)PARTS);
		MultiLine[MainIdx][i].x = coord.x;
		MultiLine[MainIdx][i].y = coord.y;
	}

	//线条序号,达到数组末端时回到 0
	if (MainIdx >= (LINES - 1))
	{
		MainIdx = 0;
	}
	else
	{
		MainIdx++;
	}

    
	Sleep(10);
	glutPostRedisplay();
}

//窗口事件响应函数
void reshape(int Width, int Height)
{
	const float fa = 32.0;
	const float half = 250.0;

	if (Width == Height)
	{
		//视口范围
		glViewport(0, 0, Width, Height);
	}
	else if (Width > Height)
	{
		glViewport(0, 0, Height, Height);
	}
	else
	{
		glViewport(0, 0, Width, Width);
	}

	//投影视图矩阵
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-half, half, -half, half, 0.0, 100.0);

	// 模型视图矩阵
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.0, 0.0, fa, 0.0, 0.0, 0.0, 0.0, 1.0, fa);
	// 观察点,   朝向的坐标, 正上方朝向
}

//按键响应
void keypress(unsigned char key, int mousex, int mousey)
{
	switch (key)
	{
	case 'q':
		glutDestroyWindow(winID);
		exit(0);
		break;
	case 'Q':
		glutDestroyWindow(winID);
		exit(0);
		break;
	}
}

void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glLineWidth(2.0);
	glPointSize(6.0);
	//glEnable(GL_DEPTH_TEST);    //开启深度缓冲
	glEnable(GL_BLEND);           //开启颜色混合
	glEnable(GL_POINT_SMOOTH);    //点平滑
	glEnable(GL_LINE_SMOOTH);     //线平滑

	srand(time(NULL));

	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			MultiLine[i][j].x = 0.0;
			MultiLine[i][j].y = 0.0;
		}
	}

}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	//显示模式   双缓冲         RGBA        深度缓冲
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(SIZE_X, SIZE_Y);       //窗口大小
	glutInitWindowPosition(200, 200);         //位置
	winID = glutCreateWindow("MultiBezier");  //窗口句柄
	init();
	glutDisplayFunc(display);          //显示
	glutKeyboardFunc(keypress);        //按键事件响应
	glutReshapeFunc(reshape);          //窗口事件响应
	glutIdleFunc(idle);                //闲时回调函数
	glutMainLoop();                    //开始主循环
}

 


#include <GL/glut.h>
#include <math.h>

GLfloat ctrlpoints[4][4][3] = {
	{{ -1.5, -1.5, 4.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, -0.5, 3.0},
		{0.5, -0.5, 0.0}, {1.5, -0.5, -1.0}},
	{{ -1.5, 0.5, 4.0}, { -0.5, 0.5, 0.0},
		{0.5, 0.5, 3.0}, {1.5, 0.5, 4.0}},
	{{ -1.5, 1.5, -2.0}, { -0.5, 1.5, -2.0},
		{0.5, 1.5, 0.0}, {1.5, 1.5, -1.0}}
};

GLfloat texpts[2][2][2] = { {{0.0, 0.0}, {0.0, 1.0}},
	{{1.0, 0.0}, {1.0, 1.0}} };

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	glEvalMesh2(GL_FILL, 0, 20, 0, 20);//glMapGrid2f()均匀产生坐标值,这里执行绘制
	glFlush();
}

#define imageWidth 64
#define imageHeight 64
GLubyte image[3 * imageWidth*imageHeight];
//纹理数据
void makeImage(void)
{
	int i, j;
	float ti, tj;

	for (i = 0; i < imageWidth; i++) {
		ti = 2.0*3.14159265*i / imageWidth;
		for (j = 0; j < imageHeight; j++) {
			tj = 2.0*3.14159265*j / imageHeight;

			image[3 * (imageHeight*i + j)] = (GLubyte)127 * (1.0 + sin(ti));
			image[3 * (imageHeight*i + j) + 1] = (GLubyte)127 * (1.0 + cos(2 * tj));
			image[3 * (imageHeight*i + j) + 2] = (GLubyte)127 * (1.0 + cos(ti + tj));
		}
	}
}

void init(void)
{
	//定义了两个求值器程序
	glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
		0, 1, 12, 4, &ctrlpoints[0][0][0]);
	glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2,
		0, 1, 4, 2, &texpts[0][0][0]);
	glEnable(GL_MAP2_TEXTURE_COORD_2);
	glEnable(GL_MAP2_VERTEX_3);
	glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);//均匀产生坐标

	//纹理属性设置
	makeImage();
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_FLAT);
}

void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)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();
	glRotatef(85.0, 1.0, 1.0, 1.0);
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key) {
	case 27:
		break;
	}
}

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);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;

}
发布了194 篇原创文章 · 获赞 8 · 访问量 9860

猜你喜欢

转载自blog.csdn.net/qq_43439240/article/details/104231861