OpenGL学习——glut/ 球体绘制原理,brensenham算法/ 代码&注释/ From芃

  • 球体绘制底层代码实现
    这个看懂有点难度额,我自己都没仔细研究呢哈哈。
    反正学了没坏处奥。
    在这里插入图片描述
#include <gl/glut.h>
#include<math.h>
#define PI 3.14159265358979323846
#define PI2 6.28318530717958647692

GLsizei width = 600,height = 600;          //球的大小

int uStepsNum = 50,vStepNum = 50;          //线的条数,从一个极点到另外一个极点的条数

class Point                                //点的数据结构
{
public:
    Point(){};
    Point(double a,double b,double c):x(a),y(b),z(c){};
public:
    double x;
    double y;
    double z;                             //xyz三个座标
};
Point getPoint(double u,double v)        //参数座标(u,v)转换成时机座标(x,y,z)函数
{
    double x = sin(PI*v)*cos(PI2*u);
    double y = sin(PI*v)*sin(PI2*u);
    double z = cos(PI*v);
    return Point(x,y,z);               //球面参数座标的转换公式
}
void drawWire()                         //绘制球面
{
    double ustep = 1/(double)uStepsNum, vstep = 1/(double)vStepNum; //离散化处理,设置增量大小
    double u = 0,v = 0;   //初始化位置,v是球面点与原点的连线与z轴正向的夹角,u表示连线在xy平面的投影与x轴正向的夹角
    //绘制下端三角形组
    for(int i = 0;i<uStepsNum;i++)
    {
        glBegin(GL_LINE_LOOP);              //GL_LINE_LOOP绘制的
        Point a = getPoint(0,0);
        glVertex3d(a.x,a.y,a.z);             //绘制三维空间座标点
        Point b = getPoint(u,vstep);
        glVertex3d(b.x,b.y,b.z);
        Point c = getPoint(u+ustep,vstep);
        glVertex3d(c.x,c.y,c.z);
        u += ustep;
        glEnd();
    }                                        //下端三角形组主要是绘制极点附近的图形
    //绘制中间四边形组
    u = 0, v = vstep;
    for(int i=0;i<vStepNum-1;i++)
    {
        for(int j=0;j<uStepsNum;j++)
        {
            glBegin(GL_LINE_LOOP);
            Point a = getPoint(u,v);
            Point b = getPoint(u+ustep,v);
            Point c = getPoint(u+ustep,v+vstep);
            Point d = getPoint(u,v+vstep);
            glVertex3d(a.x,a.y,a.z);
            glVertex3d(b.x,b.y,b.z);
            glVertex3d(c.x,c.y,c.z);
            glVertex3d(d.x,d.y,d.z);
            u += ustep;
            glEnd();
        }
        v += vstep;
    }
    //绘制下端三角形组
    u = 0;
    for(int i=0;i<uStepsNum;i++)
    {
        glBegin(GL_LINE_LOOP);
        Point a = getPoint(0,1);
        Point b = getPoint(u,1-vstep);
        Point c = getPoint(u+ustep,1-vstep);
        glVertex3d(a.x,a.y,a.z);
        glVertex3d(b.x,b.y,b.z);
        glVertex3d(c.x,c.y,c.z);
        glEnd();
    }
}
void init()
{
    glClearColor(0,0,1,1);//使用指定颜色清除颜色缓冲区
    glClearDepth(0.0);//指定深度缓冲区的清除值
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//要清除颜色缓冲以及深度缓冲
    glClearColor(0,1,1,1);
    glClearDepth(1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    GLfloat light_position [ ] = { 1.0f, 1.0f, 1.0f, 0.0f }; //光源位置
    GLfloat light_ambient  [ ] = { 0.2f, 0.2f, 0.2f, 0.2f }; //环境光
    GLfloat light_diffuse  [ ] = { 0.5f, 0.5f, 0.5f, 0.2f };//漫反射光
    GLfloat light_specular [ ] = { 0.5f, 0.5f, 0.5f, 0.2f };//镜面反射光
    glLightfv(GL_LIGHT0, GL_POSITION,  light_position); //创建指定的光源,light可以是GL_LIGHT0、GL_LIGHT1,pname定义的是光源的属性,它指定了一个命名参数。params表示表示pname属性将要被设置的值
    glLightfv(GL_LIGHT0, GL_AMBIENT,   light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE,   light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR,  light_specular);

    glEnable (GL_COLOR_MATERIAL); //开启材质颜料设置功能
    glEnable(GL_LIGHTING);        //启动光源
    glEnable(GL_LIGHT0);          //光源的颜色为白色
    glEnable(GL_AUTO_NORMAL);     //执行后,图形能把光反射到各个方向
    glEnable (GL_NORMALIZE);        //根据函数glNormal的设置条件,启用法向量
    glEnable(GL_DEPTH_TEST);        //启用深度测试。根据座标的远近自动隐藏被遮住的图形(材料)
    glDepthFunc (GL_LESS);        //深度小的时候才渲染
}
void displayFunc()
{
    glMatrixMode(GL_MODELVIEW);  //对模型视景矩阵操作
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0,0.0,0.0);
    glPointSize(1.0);//指定栅格化点的直径
    glRotated(30,1,0,0);//相乘旋转矩阵的当前的矩阵
    glRotated(60,0,1,0);
    glRotated(90,0,0,1);
    drawWire();
    glutSwapBuffers();//交换两个缓冲区指针
}
int main(int argc,char* argv[])
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(width,height);
    glutCreateWindow("傻逼球体");

    init();
    glutDisplayFunc(displayFunc);
    glutMainLoop();
}

  • Brensenham算法实现
    这个是实验要求的题目,老师上课也有讲过,我反正觉得这个还蛮重要的,看懂代码就等于看懂这个划线方法的思路了,考试还真有可能考这玩意。
    在这里插入图片描述
#include<GL/GLUT.H>
#include<stdio.h>
#include<math.h>
int xs,ys,xe,ye;
void BresenhamLine(int x0,int y0,int x1,int y1)   //参数为两个点,四个座标
{
	if((x0!=x1)&&(y0!=y1))                        //如果不是一条横线或竖线
	{
		int x,y,dx,dy,e,i;
		dx=x1-x0;                                 //增量思想,dx,dy都是增量
		dy=y1-y0;
		e=-dx;
		x=x0;
		y=y0;
		for(i=0;i<=dx;i++)                       //在增量的范围之内
		{
			glVertex2i(x,y);                     //绘制二维座标点
			x=x+1;
			e=e+dy+dy;                           //判断中点运算后和0的大小比较
			if(e>=0)                             //如果e大于0 ,则取上面的点,反之y=y
			{
				y=y+1;
				e=e-dx-dx;
			}
		}
	}
	else                                        //如果两点在相同的x或y上
	{
		int min,d;
		if(x0==x1)                             // 如果是竖线
		{
			int x=x0,y;
			y=(y0<=y1)?y0:y1;                  //初始点的位置
			d=fabs((double)(y0-y1));           //求绝对值
			while(d>=0)
			{
				glVertex2i(x,y+d);             //绘制点
				d--;                           //绘制连续的点,直到两点重合。
			}
		}
		if(y0==y1)                             //同上
		{
			int x,y=y0;
			x=(x0<=x1)?x0:x1;
			d=fabs((double)(x0-x1));
			while(d>=0)
			{
				glVertex2i(x+d,y);
				d--;
			}
		}
	}
}
void lineSegment()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.0,0.0,0.0);
	glBegin(GL_POINTS);
	BresenhamLine(xs,ys,xe,ye);              //调用划线算法
	glEnd();
	glFlush();
}

int main(int argc,char * argv[])
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	printf("输入起始座标和终点座标(范围为0-500  0-500)");
	scanf("%d,%d,%d,%d",&xs,&ys,&xe,&ye);
	glutInitWindowPosition(50,100);
	glutInitWindowSize(500,500);
	glutCreateWindow("Bresenham画线算法");
	glClearColor(1.0,1.0,1.0,0.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0,500.0,0.0,500.0);
	glutDisplayFunc(lineSegment);
	glutMainLoop();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章