实验报告8(用OpenGL生成曲线)

时间:2024.4.20

实验八:用OpenGL生成曲线

实验目的:

一、理解Bézier曲线和B样条曲线的定义、性质及绘制算法。
二、理解OpenGL中窗口坐标与世界坐标的映射关系。
三、掌握OpenGL的Bézier曲线和NURBS曲线的绘制方法。
实验内容:

文件一:StdAfx.cpp

// stdafx.cpp : source file that includes just the standard includes
// OpenGL框架.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

文件二:StdAfx.h

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//


#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers

#include <windows.h>

#include <gl\gl.h>  // OpenGL32库的头文件
#include <gl\glu.h>  // GLu32库的头文件
#include <gl\glaux.h> // GLaux库的头文件
#pragma comment( lib, "winmm.lib")
#pragma comment( lib, "opengl32.lib") // OpenGL32连接库
#pragma comment( lib, "glu32.lib")  // GLu32连接库
#pragma comment( lib, "glaux.lib")  // GLaux连接库

// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)

文件三:bzcurve.cpp

#include "stdafx.h"

void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);

GLfloat ctrlpoints[4][3] = {
   { -4.0, -4.0, 0.0 }, { -2.0, 4.0, 0.0 },
   {2.0,-4.0,0.0},{4.0,4.0,0.0}
};

void myinit(void)
{
 glClearColor(0.0, 0.0, 0.0, 1.0);
 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
 glEnable(GL_MAP1_VERTEX_3);
 glShadeModel(GL_FLAT);
}

void CALLBACK display(void)
{
 int i;

 glClear(GL_COLOR_BUFFER_BIT);
 glColor3f(1.0, 1.0, 1.0);
 glBegin(GL_LINE_STRIP);
 for (i = 0; i <= 30; i++)
  glEvalCoord1f((GLfloat) i/30.0);
 glEnd();

 /* 显示控制点 */
 glPointSize(5.0);
 glColor3f(1.0, 1.0, 0.0);
 glBegin(GL_POINTS);
 for (i = 0; i < 4; i++)
  glVertex3fv(&ctrlpoints[i][0]);
 glEnd();
 glFlush();
}

void CALLBACK myReshape(GLsizei w, GLsizei h)
{
 glViewport(0, 0, w, 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();
}

void main(void)
{
 auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
 auxInitPosition (0, 0, 500, 500);
 auxInitWindow ("Bezier Curves");
 myinit();
 auxReshapeFunc (myReshape);
 auxMainLoop(display);
}

//处理窗口消息-------------------------------------------------------

实验结果:

实验心得:

1、这一次的实验比上一次花了更长的时间。如果算上尝试做MFC框架的时间,整整花了两个星期的时间。而因为有其他的一些事情,每个星期只有大约三天的时间在做这个实验,所以整个实验过程的时间跨度很大,大概持续了三个多星期。
2、原来以为对OpenGL应该算是了解得差不多了,这次实验过后发现,没搞明白的尚且有许多,更不用提还有许多根本不知道的应用方法。而且有许多高级的应用都要跟Windows编程结合起来做,不可能一下子就把所有关于OpenGL的东西都搞通。时间不允许自己再在这上面做功夫,只好先放一边,等以后有机会再慢慢学了。
3、尝试尝试,尝试仍然是实验的主要内容。原来屡思不得其解的问题都在尝试中弄明白了,原来不想去深究的数学原理也在尝试中搞懂了。


第二篇:openGL虚线,点划线,KOCK曲线实验报告


实验四实验报告

1、实验目的和要求

利用OpenGL实现实线,虚线,点划线的绘制,及kock曲线。

2、实验内容

1)用OpenGL程序绘制实现,虚线和点划线

2)用OpenGL程序,分别以直线和正三角形为初始生成员,实现迭代次数在6次以内的kock曲线,要求用键盘交互控制迭代次数。

3、实验步骤

1)相关算法及原理描述

①  直线的绘制

在OpenGL中绘制直线通过指定直线段的端点来实现,用glVertex函数指定直线段端点的坐标位置,用glBegin/glEnd函数对包含一系列的点坐标,并利用符号常量解释这些点构成直线的方式。

②  虚线的绘制

绘制虚线需要先调用函数过了Enable(GL_LINE_STIPPLE);打开划线模式。然后,函数glLineStipple将建立用于划线的模式

glLineStipple(Glint factor, GLushort pattern);

③  Kock曲线

Kock曲线的初始生成员是一条直线,生成规则是将直线段分为三等分,首尾两段保持不变,中间用两段等长且互成60°角的直线段代替。这样,直线段被分成四段,每段长度都只有原来的1/3。Kock曲线的分形维数为  D=ln4/ln3≈1.26186

假设原直线的首尾点是P0(x0,y0),P1(x1,y1),则新的四段直线段的五个端点坐标分别为

(x0 , y0)      (x0+(x1-x0)/3 , y0+(y1-y0)/3)

((x1+x0)/2±(y0-y1)√3/6 , (y1+y0)/2±(x1-x0)√3/6)

(x0+2(x1-x0)/3 , y0+2(y1-y0)/3)  (x1 , y1)

其中,第三个点坐标公式中的正负号表示中间两条心直线段处于元直线段的哪一侧。根据这一规则迭代六次。

2)程序调试、测试与运行结果分析

①      直线的绘制结果

②      虚线的绘制结果

③       以直线作为初始生成元的Kock曲线

④  以三角形作为初始生成元的Kock曲线

4、      实验总结

     在上一次的实验基础上,利用  GL_LINES画直线,这项实验内容比较容易。然后,利用glEnable(GL_LINE_STIPPLE)函数和glLineStiopple(Glint factor ,GLushort  pattern)进行虚线和点画线的实现。也是比较简单的。

     第二个实验是利用Kock曲线实现迭代生成图形,这个实验很难。用了两节课的时间,最终也没有成功。我自己没有做成功,去请教别人,看别人的才做出来的。看到生成的图像很漂亮

     不管结果怎么样,我在这次的实验中学到了很多知识,对编程也好,对openGL也好,都有了更好更深的理解。

5、附录

1>直线的绘制

#include<gl/glut.h>

int winWidth=400,winHeight=300;

void Initial(void)

{

       glClearColor(1.0f,1.0f,1.0f,1.0f);

}

void ChangeSize(int w,int h)

{

       winWidth=w;

       winHeight=h;

       glViewport(0,0,w,h);

       glMatrixMode(GL_PROJECTION);

       glLoadIdentity();

       gluOrtho2D(0.0,winWidth,0.0,winHeight);

}

void Display(void)

{

       glClear(GL_COLOR_BUFFER_BIT);

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

              glBegin(GL_LINES);

                glVertex2i(100,80);

                glVertex2i(220,250);

              glEnd();

              glutSwapBuffers();

}

int main(int argc,char*argv[])

{

       glutInit(&argc,argv);

       glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

       glutInitWindowSize(400,300);

       glutInitWindowPosition(100,100);

       glutCreateWindow("直线");

       glutDisplayFunc(Display);

       glutReshapeFunc(ChangeSize);

       Initial();

    glutMainLoop();

       return 0;

}

2>虚线及点划线的绘制

#include<gl/glut.h>

int winWidth=400,winHeight=300;

void Initial(void)

{

       glClearColor(1.0f,1.0f,1.0f,1.0f);

}

void ChangeSize(int w,int h)

{

       winWidth=w;

       winHeight=h;

       glViewport(0,0,w,h);

       glMatrixMode(GL_PROJECTION);

       glLoadIdentity();

       gluOrtho2D(0.0,winWidth,0.0,winHeight);

}

void Display(void)

{

       glClear(GL_COLOR_BUFFER_BIT);

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

       

              glBegin(GL_LINES);

                glVertex2i(100,80);

                glVertex2i(220,250);

              glEnd();

              glutSwapBuffers();

}

int main(int argc,char*argv[])

{

       glutInit(&argc,argv);

       glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

      

       glutInitWindowSize(400,300);

       glutInitWindowPosition(100,100);

       glutCreateWindow("虚线");

       glEnable(GL_LINE_STIPPLE);

       glLineStipple(2,0X00FF);

       glutDisplayFunc(Display);

       glutReshapeFunc(ChangeSize);

       Initial();

    glutMainLoop();

       return 0;

}

3>以直线为生成元的Kock曲线

#include <GL/glut.h> 

       #include <iostream> 

       #include <vector> 

       #include <math.h> 

       #define PI 3.1415926 

       using namespace std; 

             struct Point 

       { 

           float x; 

           float y; 

       };  

       static vector<Point> count; 

       static int m = 0; //迭代次数 

       float line ;      

       void first_state(vector<Point> &count)  //初始情况是只有两个点 

       { 

           Point first = {-1.0f,0.0f},end = {1.0f,0.0f}; 

           line = sqrt( pow(first.x - end.x,2) + pow(first.y - end.y,2) ); 

           count.push_back(first); 

           count.push_back(end); 

       }     

       void Draw_pic(vector<Point> &count) 

       { 

           for (vector<Point>::size_type i = 0; i != (count.size()-1) ; i++) 

           { 

               glBegin(GL_LINES);   

                   glVertex2f(count[i].x, count[i].y); 

                   glVertex2f(count[i+1].x, count[i+1].y); 

               glEnd(); 

           } 

       } 

       void Calculate_point(vector<Point> &count) 

       { 

           vector<Point> new_count; 

           float pline = line /(float) pow((float)3,(int)m) ; 

           vector<Point>::size_type i; 

           for ( i= 0; i != (count.size() - 1); i++ ) 

           { 

               Point p1 , p2 , pmid; 

               p1.x = count[i].x + (count[i+1].x - count[i].x) / 3; 

               p1.y = count[i].y + (count[i+1].y - count[i].y) / 3; 

               p2.x = count[i+1].x - (count[i+1].x - count[i].x) / 3; 

               p2.y = count[i+1].y - (count[i+1].y - count[i].y) / 3; 

               double alpha = 0.0; 

               if (count[i+1].y >= count[i].y) 

               { 

                   alpha = atan((double) (count[i+1].y - count[i].y) / (count[i+1].x - count[i].x) ); 

                   if (count[i+1].x > count[i].x) 

                   {    

                       pmid.x = p1.x + pline * cos(alpha + PI / 3); 

                       pmid.y = p1.y + pline * sin(alpha + PI / 3); 

                   } 

                   else

                   { 

                       pmid.x = p1.x - pline * cos(alpha + PI / 3); 

                       pmid.y = p1.y - pline * sin(alpha + PI / 3); 

                   } 

               } 

               else

               { 

                   alpha = atan((double) (count[i].y - count[i+1].y) / (count[i+1].x - count[i].x) ); 

                   if (count[i+1].x > count[i].x) 

                   { 

                       pmid.x = p2.x - pline * cos(alpha + PI / 3); 

               pmid.y = p2.y + pline * sin(alpha + PI / 3); 

                   } 

                   else

                   { 

                       pmid.x = p2.x + pline * cos(alpha + PI / 3); 

                       pmid.y = p2.y - pline * sin(alpha + PI / 3); 

                   } 

               } 

               new_count.push_back(count[i]); 

               new_count.push_back(p1); 

               new_count.push_back(pmid); 

               new_count.push_back(p2); 

           } 

           new_count.push_back(count[i]); 

           count.clear(); 

           count = new_count; //之前要清空 

       } 

        

       void myDisplay() 

       { 

           glClear(GL_COLOR_BUFFER_BIT); 

           switch (m) 

           { 

               case 0: 

               case 1: 

               case 2: 

               case 3: 

            case 4: 

            case 5: 

               case 6: 

               case 7: 

               case 8: 

               case 9: 

               case 10: 

                   Draw_pic(count); 

                   break; 

               default: 

                   break; 

    } 

           glFlush(); 

       } 

        

       void Keyboard(unsigned char key,int x,int y)    

       { 

           if (key == ' ') 

           { 

               ++m; 

               Calculate_point(count); 

           } 

           glutPostRedisplay(); 

       } 

        

       int main(int argc, char *argv[]) 

       { 

           first_state(count); 

           glutInit(&argc, argv); 

        glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); 

           glutInitWindowPosition(100, 100); 

        glutInitWindowSize(400, 400); 

           glutCreateWindow("直线Kock曲线"); 

           glutDisplayFunc(&myDisplay); 

           glutKeyboardFunc(Keyboard); //键盘响应回调函数 

           glutMainLoop(); 

     return 0; 

       } 

4>以三角形为初始生成元的Kock曲线

#include <GL/glut.h>  

#include <iostream>  

#include <vector>  

#include <math.h>  

#define PI 3.1415926  

 using namespace std;  

struct Point  

{  

    float x;  

    float y;  

};  

static vector<Point> count1,count2,count3;  

const Point first = {-0.5f,0.1f},end = {0.5f,0.1f},second = {0.0f,-0.766f};  

static int m = 0; //迭代次数  

float line ;   

void first_state(vector<Point> &count1,vector<Point> &count2,vector<Point> &count3) //初始情况是只有两个点  

{  

    line = sqrt( pow(first.x - end.x,2) + pow(first.y - end.y,2) );  

    count1.push_back(first);  

    count1.push_back(end);  

       count2.push_back(end);  

       count2.push_back(second);  

       count3.push_back(second);  

       count3.push_back(first);  

}   

void Draw_pic(vector<Point> &count1)  

{   

    for (vector<Point>::size_type i = 0; i != (count1.size()-1) ; i++)  

         {  

        glBegin(GL_LINES);    

        glVertex2f(count1[i].x, count1[i].y);  

        glVertex2f(count1[i+1].x, count1[i+1].y);  

           glEnd();  

    }  

    for (vector<Point>::size_type j = 0; j != (count2.size()-1) ; j++)  

        {  

          glBegin(GL_LINES);    

          glVertex2f(count2[j].x, count2[j].y);  

          glVertex2f(count2[j+1].x, count2[j+1].y);  

        glEnd();  

    }  

    for (vector<Point>::size_type k = 0; k != (count3.size()-1) ; k++)  

    {  

        glBegin(GL_LINES);    

        glVertex2f(count3[k].x, count3[k].y);  

        glVertex2f(count3[k+1].x, count3[k+1].y);  

        glEnd();  

    }  

}   

void Calculate_point(vector<Point> &count1)  

{  

    vector<Point> new_count;  

    float pline = line /(float) pow((float)3,(int)m) ;  

    vector<Point>::size_type i;  

    for ( i= 0; i != (count1.size() - 1); i++ )  

    {  

        Point p1 , p2 , pmid;  

        p1.x = count1[i].x + (count1[i+1].x - count1[i].x) / 3;  

        p1.y = count1[i].y + (count1[i+1].y - count1[i].y) / 3;  

        p2.x = count1[i+1].x - (count1[i+1].x - count1[i].x) / 3;  

        p2.y = count1[i+1].y - (count1[i+1].y - count1[i].y) / 3;  

        //mark  count[i+1].x < count[i].x情况下不成立  

        double alpha = 0.0;  

        if (count1[i+1].y >= count1[i].y)  

        {  

            alpha = atan((double) (count1[i+1].y - count1[i].y) / (count1[i+1].x - count1[i].x) );  

            if (count1[i+1].x > count1[i].x)  

            {     

                pmid.x = p1.x + pline * cos(alpha + PI / 3);  

                pmid.y = p1.y + pline * sin(alpha + PI / 3);  

            }  

            else 

            {  

                pmid.x = p1.x - pline * cos(alpha + PI / 3);  

                pmid.y = p1.y - pline * sin(alpha + PI / 3);  

            }  

        }  

        else 

        {  

            alpha = atan((double) (count1[i].y - count1[i+1].y) / (count1[i+1].x - count1[i].x) );  

            if (count1[i+1].x > count1[i].x)  

            {  

                pmid.x = p2.x - pline * cos(alpha + PI / 3);  

                pmid.y = p2.y + pline * sin(alpha + PI / 3);  

            }  

            else 

            {  

                pmid.x = p2.x + pline * cos(alpha + PI / 3);  

                pmid.y = p2.y - pline * sin(alpha + PI / 3);  

            }  

        }  

        new_count.push_back(count1[i]);  

        new_count.push_back(p1);  

        new_count.push_back(pmid);  

        new_count.push_back(p2);  

    }  

    new_count.push_back(count1[i]);  

        count1.clear();  

    count1 = new_count; //之前要清空  

}  

void myDisplay()  

{  

    glClear(GL_COLOR_BUFFER_BIT);  

    switch (m)  

    {  

        case 0:  

        case 1:  

        case 2:  

        case 3:  

        case 4:  

        case 5:  

        case 6:  

        case 7:  

        case 8:  

        case 9:  

        case 10:  

     Draw_pic(count1);  

            Draw_pic(count2);  

            Draw_pic(count3);  

            break;  

        default:

            break;  

    }  

    glFlush();  

}   

void Keyboard(unsigned char key,int x,int y)     

{  

    if (key == ' ')  

    {  

        ++m;  

        Calculate_point(count1);  

        Calculate_point(count2);  

        Calculate_point(count3);  

    }  

    glutPostRedisplay();  

}   

int main(int argc, char *argv[])  

{  

    first_state(count1,count2,count3);  

    glutInit(&argc, argv);  

    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);  

    glutInitWindowPosition(100, 100);  

    glutInitWindowSize(400, 400);  

    glutCreateWindow("三角形Kock曲线");  

    glutDisplayFunc(&myDisplay);  

    glutKeyboardFunc(Keyboard); //键盘响应回调函数  

    glutMainLoop();  

    return 0;  

}  

更多相关推荐:
用友ERP-U8实验报告

上海立信会计学院市场营销专业ERP企业经营综合模拟实验用友ERPU8实验报告实验目的21世纪后随着信息技术的飞速发展和市场竞争的日趋激烈企业面临着更多挑战应变速度成为企业生存和发展最关键的竞争性要素信息化浪潮席...

用友ERP实验报告

用友ERPU8.72实验报告用友ERPU8.72是企业应用套件在全面总结、分析、提炼中国中小企业业务运作与管理特性的基础上,针对中小企业不同管理层次、不同管理与信息化成熟度、不同应用与行业特性的信息化需求而设计…

用友ERP-U8实验报告

xxxxxxxxxxxxxxxxxx实验报告册学期20xx年20xx年上学期课程名称会计信息系统班级学号xxxxxxxxxxxxxxxxx姓名xxxxxxxxxxxxxxx20xx年12月16日注1实验报告册各...

用友ERP实验分析报告

用友ERP实验分析报告一实验内容概述一本课程内容介绍ERP企业资源计划系统融先进管理思想最佳企业业务实践为一体受到企业界的广泛关注ERP系统是当今世界企业经营与管理技术进步的代表对企业来说应用ERP的价值就在于...

用友ERP-U8实验报告

上海企通软件CRM事业部用友ERPU8客户关系管理系统实验报告一实验目的1掌握用友ERPU8管理系统中有关客户关系管理系统和基础设置的相关内容2理解系统管理在整个系统中的作用及基础设置的重要性3掌握系统中用户账...

用友ERP-U8软件实验报告

用友ERP-U8软件实验报告,内容附图。

用友ERP生产管理系统实验报告

用友ERP生产管理系统实验报告本课程共分14单以用友ERPU872为实验平台以一个企业的生产经营业务贯穿始终分别介绍了ERP生产管理系统中物料清单主生产计划产能管理需求规划生产订单车间管理工程变更设备管理的生产...

用友ERP会计电算化——实验报告

会计电算化实验报告班级会计1208班姓名尹杰学号20xx年6月

用友ERP实验报告三-

实验报告三

用友实验报告

实验报告项目名称用友财务链与供应链实训一实验目的及要求实训目的通过本课程的学习使同学们在掌握会计电算化和财务会计的理论知识基础上理解用友财务软件的设计理念熟练应用友软件的财务链和供应链的各模块借助于用友财务软件...

用友ERP供应链实验报告

用友ERP供应链实验报告学院会计学院姓名专业学号班级组别3组员成绩无实验地点计算机实验室二实验日期20xx12指导教师签名项目名称用友供应链ERP综合实训一实验目的及要求实训目的通过本课程的学习使同学们在掌握会...

用友ERP生产管理实验报告

ERP原理与应用课程名称用友ERP生产管理系统实验教程实验序号1实验项目1实验地点综B303实验学时实验类型指导教师实验员专业电子商务班级学号姓名实验报告要求1作成电子文档并每人打印输出一份电子文档由学委统一打...

用友erp实验报告(20篇)