计算机图形学报告1

西安电子科技大学

 

计算机图形学 课程实验报告

实验名称 第一次上机实验

计算机 学院 1803012

姓名 曹王欣 学号 18030100167

同作者

实验日期 2020

实验地点 实验批次

 

指导教师评语:

 

 

 

 

 

指导教师:

实验报告内容基本要求及参考格式

一、实验目的

二、实验所用仪器(或实验环境)

三、实验基本原理及步骤(或方案设计及理论计算)

四、实验数据记录(或仿真及软件设计)

五、实验结果分析及回答问题(或测试环境及测试结果)

 

 

 

  1. 简单图元的绘制(借鉴lec3课件)
    1. 在屏幕上绘制几何图元(如下图所示),自定义坐标和颜色。

 

第一次实验主要是熟悉opengl的绘图与使用,用到的基本函数如下:在glbegin和glend()之间写入点,然后glbegin()之中可以设置图元的属性,比如

//画点

    glBegin(GL_POINTS);

//画线段

    glBegin(GL_LINES);

//画开折线

    glBegin(GL_LINE_STRIP);

//画闭折线

    glBegin(GL_LINE_LOOP);

//画填充多边形

    glBegin(GL_POLYGON);

//画四边形

    glBegin(GL_QUADS);

//画连接四边形

    glBegin(GL_QUAD_STRIP);

//画三角形

    glBegin(GL_TRIANGLES);

//画连续三角形

    glBegin(GL_TRIANGLE_STRIP);

//画扇形三角形

    glBegin(GL_TRIANGLE_FAN);

总体的程序如下:

#include <GL/glut.h>

#include <cstdio>

#include <cmath>

 

void myinit()

{

    glClearColor(1, 1.0, 1.0, 1.0);

 

}

 

void ChangeSize(GLsizei w, GLsizei h)

{

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

 

    if (w <= h)

        glOrtho(-20.0, 20.0, -20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, -50.0, 50.0);

    else

        glOrtho(-20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, -20.0, 20.0, -50.0, 50.0);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

void DrawMyObjects()

{

 

    //画点

    glBegin(GL_POINTS);

    glColor3f(1.0, 0.0, 0.0);

    glVertex2f(-10.0, 11.0);

    glColor3f(1.0, 1.0, 0.0);

    glVertex2f(-9.0, 10.0);

    glColor3f(0.0, 1.0, 1.0);

    glVertex2f(-8.0, 12.0);

    glEnd();

    //画线段

    glBegin(GL_LINES);

    glColor3f(1.0, 1.0, 0.0);

 

    glVertex2f(-11.0, 8.0);

    glVertex2f(-8.0, 7.0);

    glColor3f(1.0, 1.0, 1.0);

    glVertex2f(-10.0, 9.0);

    glVertex2f(-7.0, 6.0);

    glEnd();

    //画开折线

    glBegin(GL_LINE_STRIP);

    glColor3f(0.0, 1.0, 0.0);

    //    glPointSize(5);

    glVertex2f(-10.0, 9.0);

    glVertex2f(4.0, 6.0);

    glVertex2f(6.0, 8.0);

    glVertex2f(-5.5, 6.5);

    glEnd();

    //画闭折线

    glBegin(GL_LINE_LOOP);

    glColor3f(0.0, 1.0, 1.0);

    glVertex2f(7.0, 7.0);

    glVertex2f(8.0, 8.0);

    glVertex2f(9.0, 6.5);

    glVertex2f(10.3, 7.5);

    glVertex2f(11.5, 6.0);

    glVertex2f(7.5, 6.0);

    glEnd();

    //画填充多边形

    glBegin(GL_POLYGON);

    glColor3f(0.5, 0.3, 0.7);

    glVertex2f(-9.0, 2.0);

    glVertex2f(-8.0, 3.0);

    glVertex2f(-10.3, 0.5);

    glVertex2f(-7.5, -2.0);

    glVertex2f(-5.0, -3.0);

    glEnd();

    //画四边形

    glBegin(GL_QUADS);

    glColor3f(0.7, 0.5, 0.2);

    glVertex2f(0.0, 2.0);

    glVertex2f(-1.0, 3.0);

    glVertex2f(-3.3, 0.5);

    glVertex2f(-0.5, -1.0);

    glColor3f(0.5, 0.7, 0.2);

    glVertex2f(3.0, 2.0);

    glVertex2f(2.0, 3.0);

    glVertex2f(0.0, 0.5);

    glVertex2f(2.5, -1.0);

    glEnd();

    //画连接四边形

    glBegin(GL_QUAD_STRIP);

    glVertex2f(6.0, -2.0);

    glVertex2f(5.5, 1.0);

    glVertex2f(8.0, -1.0);

    glColor3f(0.8, 0.0, 0.0);

    glVertex2f(9.0, 2.0);

    glVertex2f(11.0, -2.0);

    glColor3f(0.0, 0.0, 0.8);

    glVertex2f(11.0, 2.0);

    glVertex2f(13.0, -1.0);

    glColor3f(0.0, 0.8, 0.0);

    glVertex2f(14.0, 1.0);

    glEnd();

    //画三角形

    glBegin(GL_TRIANGLES);

    glColor3f(0.2, 0.5, 0.7);

    glVertex2f(-10.0, -5.0);

    glVertex2f(-12.3, -7.5);

    glVertex2f(-8.5, -6.0);

    glColor3f(0.2, 0.7, 0.5);

    glVertex2f(-8.0, -7.0);

    glVertex2f(-7.0, -4.5);

    glVertex2f(-5.5, -9.0);

    glEnd();

    //画连续三角形

    glBegin(GL_TRIANGLE_STRIP);

    glVertex2f(-1.0, -8.0);

    glVertex2f(-2.5, -5.0);

    glColor3f(0.8, 0.8, 0.0);

    glVertex2f(1.0, -7.0);

    glColor3f(0.0, 0.8, 0.8);

    glVertex2f(2.0, -4.0);

    glColor3f(0.8, 0.0, 0.8);

    glVertex2f(4.0, -6.0);

    glEnd();

    //画扇形三角形

    glBegin(GL_TRIANGLE_FAN);

    glVertex2f(8.0, -6.0);

    glVertex2f(10.0, -3.0);

    glColor3f(0.8, 0.2, 0.5);

    glVertex2f(12.5, -4.5);

    glColor3f(0.2, 0.5, 0.8);

    glVertex2f(13.0, -7.5);

    glColor3f(0.8, 0.5, 0.2);

    glVertex2f(10.5, -9.0);

    glEnd();

}

void RenderScene()

{

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0, 1.0, 0.0);

    glPointSize(5);

    DrawMyObjects();

    glFlush();

}

int main(int argc,char** argv)

 

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowSize(500, 500);

    glutInitWindowPosition(100, 100);

 

    glutCreateWindow("画图");

 

    myinit();

    glutDisplayFunc(RenderScene);

    glutReshapeFunc(ChangeSize);

 

    glutMainLoop();

    return 0;

}

实验截图如下:

  1. 算法模拟题(借鉴lec3课件,可二选一实现)
    1. 采用中点线算法在屏幕上画一条直线。
    2. 采用中点圆算法在屏幕上画一个圆。

 

对于实验1,中点线算法的实验原理如下:

若d0 ->M在直线上方->取E;

此时再下一个象素的中点判别式为

d1=F(xp+2, yp+0.5)

=a(xp+2)+b(yp+0.5)+c

= a(xp +1)+b(yp +0.5)+c +a =d+a;

我的代码中的核心部分如下:

if ((fabs(dx) > fabs(dy)) && dy > 0)

    {

        GLint d1 = 2 * a;

        GLint d2 = 2 * (a + b);

        GLint d = 2 * a + b;

        while (x0 < x1)//斜率0到1

        {

            i++;

            if (d < 0)

            {

                x0++;

                y0++;

                d += d2;

            }

            else

            {

                x0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) > fabs(dy)) && dy < 0)//斜率大于-1小于0

    {

        GLint d1 = 2 * a;

        GLint d2 = 2 * (a - b);

        GLint d = 2 * a - b;

        while (x0 < x1)

        {

            i++;

            if (d > 0)

            {

                x0++;

                y0--;

                d += d2;

            }

            else

            {

                x0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) <= fabs(dy)) && dy > 0)//斜率大于1

    {

        GLint d1 = 2*b;

        GLint d2 = 2*a+2*b;

        GLint d =a +2*b;

        while (y0 < y1)

        {

            i++;

            if (d > 0)

            {

                x0++;

                y0++;

                d += d2;

            }

            else

            {

                y0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) <= fabs(dy)) && dy < 0)//斜率小于-1

    {

        GLint d1 = -2 * b;

        GLint d2 = 2 * a - 2 * b;

        GLint d = a - 2 * b;

        while (y0 > y1)

        {

            i++;

            if (d < 0)

            {

                x0++;

                y0--;

                d += d2;

            }

            else

            {

                y0--;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

可以看到,我对每一个斜率为k的情况都做了分析,分别是k<-1,-1<k<0,0<k<1,k>1这四种情况,全部采用了中点线算法,最后使用drawline(10, 80, 60, 10); // 更改画线范围,

Drawline10806010)的情况表示从(1080)画到(6010)的线段,使用中点线算法结果如下:这里,我调用了四次drawline,分别对应以上的四种情况

请观察我的代码

drawline(10, 80, 60, 10); // 在这里更改你的画线范围

drawline(10, 10, 60, 80);

drawline(10, 50, 40, 20);

drawline(10, 20, 60, 30);

 

截图如下:

 

全部的源程序如下:

#include <GL/glut.h>

#include <cstdlib>

#include <cmath>

 

void ChangeToStandard(GLint& x0, GLint& y0, GLint& x1, GLint y1)

{

    if (x1 < x0)

    {

        GLint tmpx = x1;

        GLint tmpy = y1;

        x1 = x0;

        x0 = tmpx;

        y1 = y0;

        y0 = tmpy;

    }

}

typedef struct {

    GLint x, y;

}Pixel;

void init()

{

    glClearColor(1, 1, 1, 1);

}

int Midpoint(GLint x0, GLint y0, GLint x1, GLint y1,Pixel points[])//可以画四种线段,也就是所有的情况都能画出来,斜率不论正负,不论大于一还是小于1

{

    ChangeToStandard(x0, y0, x1, y1);//保证x0<x1;

    GLint dx = x1 - x0;

    GLint dy = y1 - y0;

    GLint a = y0 - y1, b = x1 - x0, c = x1 * y0 - x0 * y1;

    int i = 0;

    points[i].x = x0;

    points[i].y = y0;

    

    if ((fabs(dx) > fabs(dy)) && dy > 0)

    {

        GLint d1 = 2 * a;

        GLint d2 = 2 * (a + b);

        GLint d = 2 * a + b;

        while (x0 < x1)//斜率0到1

        {

            i++;

            if (d < 0)

            {

                x0++;

                y0++;

                d += d2;

            }

            else

            {

                x0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) > fabs(dy)) && dy < 0)//斜率大于-1小于0

    {

        GLint d1 = 2 * a;

        GLint d2 = 2 * (a - b);

        GLint d = 2 * a - b;

        while (x0 < x1)

        {

            i++;

            if (d > 0)

            {

                x0++;

                y0--;

                d += d2;

            }

            else

            {

                x0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) <= fabs(dy)) && dy > 0)//斜率大于1

    {

        GLint d1 = 2*b;

        GLint d2 = 2*a+2*b;

        GLint d =a +2*b;

        while (y0 < y1)

        {

            i++;

            if (d > 0)

            {

                x0++;

                y0++;

                d += d2;

            }

            else

            {

                y0++;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    if ((fabs(dx) <= fabs(dy)) && dy < 0)//斜率小于-1

    {

        GLint d1 = -2 * b;

        GLint d2 = 2 * a - 2 * b;

        GLint d = a - 2 * b;

        while (y0 > y1)

        {

            i++;

            if (d < 0)

            {

                x0++;

                y0--;

                d += d2;

            }

            else

            {

                y0--;

                d += d1;

            }

            points[i].x = x0;

            points[i].y = y0;

        }

    }

    return i;

}

void drawline(GLint x0, GLint y0, GLint x1, GLint y1)

{

    Pixel points[100];

    int num = Midpoint(x0, y0, x1, y1, points);

    glBegin(GL_POINTS);

    for (int i = 0; i <= num; i++)

    {

        glVertex2i(points[i].x, points[i].y);

    }

    glEnd();

 

 

}

void RenderScene()

{

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0f, 0.0f, 0.f);

    glPointSize(2);

    drawline(10, 80, 60, 10); // 在这里更改你的画线范围

    drawline(10, 10, 60, 80);

    drawline(10, 50, 40, 20);

    drawline(10, 20, 60, 30);

    glFlush();

}

void ChangeSize(GLsizei w, GLsizei h)

{

    GLfloat aspectRatio;

    if (h == 0)

        h = 1;

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

 

    aspectRatio = (GLfloat)w / (GLfloat)h;

    if (w <= h)

        glOrtho(-100.0, 100.0, -100.0 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);

    else

        glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);

 

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

 

int main(int argc,char **argv)

{

    //在drawline之中可以更改画线段的范围;

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

    glutCreateWindow("中点线算法,在drawline里面改线段");

 

    init();

 

    glutDisplayFunc(RenderScene);

    glutReshapeFunc(ChangeSize);

 

    glutMainLoop();

    return 0;

}

 

 

对于实验2,中点圆算法的实现如下:

 

我们可以利用八分圆特性,只要画其中一个八分圆,然后对称就能获得整个圆:

void CirclePoints (float x,float y,int color)

{

    WritePixel (x, y, color);

    WritePixel (y, x, color);

    WritePixel (y, -x, color);

    WritePixel (x, -y, color);

    WritePixel (-x, -y, color);

    WritePixel (-y, -x, color);

    WritePixel (-y, x, color);

    WritePixel (-x, y, color);

}

实验思路的伪代码如下,方法就是判断中点的位置,然后判断是右像素还是右下像素:

MidpointCircle1(int r, int color)

{

int x,y;

float d;

x=0; y=r; d=1.25-r;

WritePixel(x,y,color);

while(x<y)

     {

         if(d<0){ d+ = 2*x+3; x++ }

else{d+ = 2*(x-y) + 5; x++;y--; }

         WritePixel(x,y,color);

}

}

 

我的具体实现中的核心代码就是

void circleMidpoint(GLint xc, GLint yc, GLint redius)

{

    screenPt circlept;

    GLint p = 1 - redius;

    circlept.setCoords(0, redius);

    void circleplotpoints(GLint, GLint, screenPt);

    circleplotpoints(xc,yc,circlept);

    while (circlept.getx() < circlept.gety())

    {

        circlept.incrementx();

        if (p < 0)

        {

            p +=1 + 2 * circlept.getx();

 

        }

        else

        {

            circlept.decrementy();

            p += 2 * (circlept.getx() - circlept.gety()) + 1;

        }

        circleplotpoints(xc, yc, circlept);

    }

}

这里的代码用于画第二个八分圆,然后对称即可

 

具体代码实现如下:

#include <GL/glut.h>

 

class screenPt

{

private:

    GLint x, y;

public:

    screenPt()

    {

        x = y = 0;

    }

    void setCoords(GLint xCoordValue, GLint yCoordValue)

    {

        x = xCoordValue;

        y = yCoordValue;

    }

    GLint getx()

    {

        return x;

    }

    GLint gety()

    {

        return y;

    }

    void incrementx()

    {

        x++;

    }

    void decrementy()

    {

        y--;

    }

};

void setPixel(GLint xcoord, GLint yCoord)

{

    glBegin(GL_POINTS);

    glVertex2i(xcoord, yCoord);

    glEnd();

}

void circleMidpoint(GLint xc, GLint yc, GLint redius)

{

    screenPt circlept;

    GLint p = 1 - redius;

    circlept.setCoords(0, redius);

    void circleplotpoints(GLint, GLint, screenPt);

    circleplotpoints(xc,yc,circlept);

    while (circlept.getx() < circlept.gety())

    {

        circlept.incrementx();

        if (p < 0)

        {

            p +=1 + 2 * circlept.getx();

 

        }

        else

        {

            circlept.decrementy();

            p += 2 * (circlept.getx() - circlept.gety()) + 1;

        }

        circleplotpoints(xc, yc, circlept);

    }

}

void circleplotpoints(GLint xc,GLint yc,screenPt circlePt)

{

    setPixel(xc + circlePt.getx(), yc + circlePt.gety());

    setPixel(xc - circlePt.getx(), yc + circlePt.gety());

    setPixel(xc + circlePt.getx(), yc - circlePt.gety());

    setPixel(xc - circlePt.getx(), yc - circlePt.gety());

    setPixel(xc + circlePt.gety(), yc + circlePt.getx());

    setPixel(xc - circlePt.gety(), yc + circlePt.getx());

    setPixel(xc + circlePt.gety(), yc - circlePt.getx());

    setPixel(xc - circlePt.gety(), yc - circlePt.getx());

 

 

}

 

void init()

{

    glClearColor(1, 1, 1, 1);

}

 

void ChangeSize(GLsizei w, GLsizei h)

{

    GLfloat aspectRatio;

    if (h == 0)

        h = 1;

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

 

    aspectRatio = (GLfloat)w / (GLfloat)h;

    if (w <= h)

        glOrtho(-100.0, 100.0, -100.0 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);

    else

        glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);

 

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

void show()

{

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(0.0f, 0.0f,1.0f);

    glPointSize(5);

    circleMidpoint(0, 0, 50);

    glFlush();

}

int main(int argc,char** argv)

 

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

    glutCreateWindow("中点圆算法");

 

    init();

 

    glutDisplayFunc(show);

    glutReshapeFunc(ChangeSize);

 

    glutMainLoop();

    return 0;

}

 

 

实验截图如下,可以看到我画出了一个完整的圆:

posted @ 2021-01-22 23:30  coolwx  阅读(599)  评论(0编辑  收藏  举报