OpenGL课程设计-三维球体的实现
OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动.

计算机图形学实验报告1、实验目的和要求利用第七章所学的知识,试在OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动,并在撞击地面后能够反弹回来。
并用相应的代码表示出来。
2、实验内容利用glutSolidSphere函数等其它函数,在OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动,并在撞击地面后能够反弹回来3、实验步骤1)相关算法及原理描述我们所使用的glut实用工具中,正好就有一个绘制球体的现成函数: glutSolidSphere,这个函数在“原点”绘制出一个球体。
由于坐标是可以通过glTranslate*和glRotate*两个函数进行随意变换的,所以我们就可以在任意位置绘制球体了。
2)运行结果如下图,程序调试成功,并且能正常显示4、实验总结通过本次试验,进一步认识,感觉OpenGL的功能很强大,各种各样的物理模拟实验他都不在话下!!不得不说,这软件很好很强大!!由于自己不太擅长编程, 所以有些功能还不能完全实现,但我会尽自己最大努力来克服自己的编程不足之处,多加练习。
5、附录带注释的源程序#include "glut.h"#include<stdlib.h>#include<stdio.h>#include<time.h>#include<math.h>#define PI 3.1415926double move=20.0;int i=0;int down=1;int count=1;double timeSpan=0; // 下降到底所需时间double movey=0.0;double duration=0.0; //持续时间double length=0.0;clock_t start,end;void init(void){GLfloat mat_specular[]={220.220,220.0,220.0,220.0};GLfloat mat_shininess[]={100.0};GLfloat light_position[]={0.0, 0.0, 0.0, -2.0}; //r-l u-d f-bGLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };GLfloat diffuseLight[] = { 0.6f, 0.6f, 0.6f, 1.0f };GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};glClearColor(0.2,0.2,1.5,2.0); //bgc glColor3ub(100, 100, 215);glShadeModel(GL_SMOOTH);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);glLightfv(GL_LIGHT0,GL_SPECULAR,specular);glLightfv(GL_LIGHT0,GL_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST);void reshape(int w,int h){ glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w<=h)glOrtho(-12,12,-12*(GLfloat)(h)/(GLfloat)(w),12*(GLfloat)(h)/(GLfloat)(w), -1.0,1.0); }elseglOrtho(-12*(GLfloat)(w)/(GLfloat)(h),12*(GLfloat)(w)/(GLfloat)(h),-12,12,-1.0,1.0) JglMatrixMode(GL_MODELVIEW); glLoadIdentity();}void initDisplay(void){down=1; //向下运动glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0,20.0,0.0);glutSolidSphere(0.4,40,50); glutSwapBuffers();}void display(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity();glTranslatef(0,move,0.0); glutSolidSphere(0.4,40,50);glutSwapBuffers();}void MoveSphereUp(){end=clock();duration = (double)(end - start-16.0) /CLOCKS_PER_SEC;length=5*(timeSpan-duration)*(timeSpan-duration); move=20-length;if(move>19.932) {move=20;down=1;printf("%i",down);start=clock();}display();glLoadIdentity();}void MoveSphereDown(){if(count==1){start=clock();count=0;}end=clock();duration = (double)(end - start) /CLOCKS_PER_SEC;length=5*duration*duration;move=20-length;if(move<-20) {timeSpan=duration; //记下下降所经历的时间move=-20;start=clock();down=0; //向上运动}display();glLoadIdentity();}void TimerFunc2(int value){if(i==0){ //leftGLfloat light_position[]={2.0,0.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==1){ //left-upGLfloat light_position[]={2.0,2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==2){ //upGLfloat light_position[]={0.0,2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==3){ //up-rightGLfloat light_position[]={-2.0,2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==4){ //rightGLfloat light_position[]={-2.0,0.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==5){ //right-downGLfloat light_position[]={-2.0,-2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==6){ //downGLfloat light_position[]={0.0,-2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}if(i==7){ //down-leftGLfloat light_position[]={2.0,-2.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position);}i=(++i)%8; //控制小球旋转的glutTimerFunc(60,TimerFunc2,1);}void TimerFunc1(int value){if(down==1){MoveSphereDown();}if(down==0){MoveSphereUp();}glutTimerFunc(10,TimerFunc1,0);}int main(int argc,char **argv){glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(400,740); glutInitWindowPosition(300,20);glutCreateWindow(argv[0]);init();glutDisplayFunc(initDisplay);glutReshapeFunc(reshape);glutTimerFunc(1400,TimerFunc1,0); //毫秒glutTimerFunc(400,TimerFunc2,1); // 毫秒glutMainLoop();return 0;}。
三维空间球体美术教案设计

三维空间球体美术教案设计一、教学内容本次三维空间球体美术教案设计的主要内容为:教授学生如何在三维空间中绘制出球体。
包括球体的基本构造、轮廓线的绘制、阴影的表现以及颜色的运用等方面。
二、教学对象本次教学对象为初学者,适合从事美术创作的学生和从事相关专业的职业人员,对于进一步学习三维空间的其他知识和应用,具有较大的启示作用。
三、教学目标1.了解三维空间中球体的基本构造,能够准确判断球体的大小、位置和比例。
2.掌握球体轮廓线的绘制技巧,能够用准确的线条表现出球体的形态。
3.掌握阴影的表现方法,能够将球体立体感和光影感表现出来。
4.掌握颜色运用的规律,能够将色彩与球体的形态结合,营造出不同的效果。
四、教学重点1.球体的基本构造和比例2.球体轮廓线的绘制技巧3.阴影的表现方法4.颜色运用的规律五、教学难点1.如何在三维空间中准确地表现球体的比例和构造。
2.如何将色彩与球体的形态结合,达到最佳的艺术效果。
六、教学准备1.教学用品:铅笔、炭笔、橡皮、铅笔刀、红、黄、蓝、白、黑等颜料。
2.教学设备:黑板、项目投影仪、电脑。
3.教学环境:教室或绘画室。
七、教学步骤1.介绍三维空间球体的基本构造和比例,通过投影仪展示球体的图像,引导学生从不同角度观察三维空间球体。
2.通过实战演习,教授学生如何用铅笔和纸绘制球体的轮廓线。
重点讲解球体阴影的表现方法,让学生能够掌握球体的立体感和光影感的表现。
3.通过演习和配色练习,讲解颜色运用规律并实际操作,着重讲解球体在不同光照条件下的色彩变化以及如何调配颜料和色调来营造出不同的效果。
4.结合实际情境,让学生进行创意创作,通过教师的点拨和指导,鼓励学生将所掌握的知识应用到实践中去。
八、教学评估1.课堂互动评价:通过学生自由探讨和小组讨论等方式,评估学生对于本课程所掌握的知识的领会和理解。
2.演练表现评估:通过练习和演练的方式,检验学生的实际应用能力和创造力。
九、教学延伸1.讲解球体的相关知识和应用,如球体的切面分析等。
使用opengl程序实现星球环绕

GIS专业实验报告(计算机图形学)实验8 使用opengl程序实现三维星球环绕效果一.实验目的及要求使用opengl程序实现三维星球环绕效果。
二.理论基础三维图形变换:三维图形变换包括三维几何变换和投影变换,通过它可由简单图形得到复杂图形,可以用二维图形表示三维对象。
三.算法设计与分析程序源码如下:#include <gl/gl.h>#include <gl/glu.h>#include <gl/glut.h>static GLfloat angle = 0.0, moon_angle = 0.0;void display(){glClearColor( 1.0, 1.0, 0.0, 0.0 );glShadeModel( GL_SMOOTH );glMatrixMode( GL_PROJECTION );glLoadIdentity();gluPerspective( 80.0, 1.0, 1.0, 50.0 );glMatrixMode( GL_MODELVIEW );glLoadIdentity();gluLookAt(8.0, 5.0, 8.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );//定义太阳的光照//发出白色的光{GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_position[] = { 0.0, 0.0, 0.5, 1.0 };//最后一个参数为正数,表明是位置性光源glEnable( GL_LIGHT0 );glEnable( GL_LIGHTING );glEnable( GL_DEPTH_TEST );//定义太阳的材质//显红色GLfloat mat_ambient[] = { 0.3, 0.0, 0.0, 1.0 };GLfloat mat_emission[] = { 0.3, 0.0, 0.0, 1.0 };//绘制太阳glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );glLightfv( GL_LIGHT0 ,GL_POSITION, light_position );glMaterialfv( GL_FRONT ,GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };glLightModelfv( GL_AMBIENT, ambient );glutSolidSphere( 2.0, 40, 40 );}//定制地球不发光,有材质{GLfloat mat_ambient[] = { 0.0, 0.0, 0.5, 1.0 };GLfloat mat_specular[] = { 0.0, 0.0, 1.0, 1.0 };GLfloat mat_shiness[] = { 30.0 };GLfloat mat_emission[] = { 0.0, 0.0, 0.1, 1.0 };glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );glMaterialfv( GL_FRONT, GL_SHININESS, mat_shiness );glRotatef( angle, 0.0, 1.0, 0.0 );glTranslatef( 6.0, 0.0, 0.0 );glutSolidSphere( 0.5, 40, 40 );}//定制月球{GLfloat mat_ambient[] = { 0.2, 0.2, 0.2, 1.0 };GLfloat mat_specular[] = { 0.8, 0.8, 0.80, 1.0 };GLfloat mat_shiness[] = { 30.0 };GLfloat mat_emission[] = { 0.3, 0.3, 0.3, 1.0 };glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient );glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );glMaterialfv( GL_FRONT, GL_SHININESS, mat_shiness );glRotatef( moon_angle, 0.0, angle, 1.0 );glTranslatef( 1.0, 0.0, 0.0 );glutSolidSphere( 0.3, 30, 30 );}glutSwapBuffers();}void idle(){angle += 0.5;moon_angle += 2.0;if ( angle > 360.0 ){angle = 0.0f;}if ( moon_angle > 360.0 ){moon_angle = 0.0;}glutPostRedisplay();}void menu( int id ){if ( id == 1 ){exit( 0 );}}int main( int argc, char ** argv ){glutInit( &argc, argv );glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); glutInitWindowPosition( 100, 100 );glutInitWindowSize(800, 450 );glutCreateWindow("模拟星球");glutDisplayFunc( display );glutIdleFunc( idle );glutCreateMenu( menu );glutAddMenuEntry( "Out", 1 );glutAttachMenu( GLUT_RIGHT_BUTTON );glutMainLoop();}四.程序调试及运行结果的自我分析与自我评价运行结果见下图1。
基于OpenGL的三维动画效果设计与实现

基于OpenGL的三维动画效果设计与实现OpenGL是一种跨平台的图形库,广泛应用于计算机图形学、游戏开发和虚拟现实等领域。
在OpenGL的基础上,可以实现各种精美的三维动画效果,如逼真的光影效果、自然的物理模拟和华丽的特效等。
本文将介绍如何基于OpenGL实现三维动画效果。
一、OpenGL简介OpenGL(Open Graphics Library)是一种跨平台的图形库,可以用于开发高性能的3D图形应用程序。
它提供了一套标准的API,程序员可以使用OpenGL库里的函数来绘制各种图形,包括点、线、三角形等。
OpenGL的主要优点是跨平台,程序可以在不同的操作系统和硬件上运行,并且不需要对程序做太多的修改。
二、OpenGL开发环境在开始OpenGL开发之前,需要配置正确的开发环境。
OpenGL的开发环境包括编程语言、OpenGL库、窗口系统和OpenGL的开发工具等。
编程语言:OpenGL支持多种编程语言,如C/C++、Java、Python等。
其中,C/C++是最常用的开发语言,因为它可以直接调用OpenGL的函数库。
OpenGL库:OpenGL库是开发OpenGL程序时必须的工具,它包含了OpenGL 的所有函数和常量。
窗口系统:OpenGL需要一个可视化的窗口系统,用来显示图形界面。
常用的窗口系统有Windows、Linux和MacOS等。
开发工具:开发OpenGL程序需要使用各种IDE和编辑器,如Visual Studio、CodeBlocks和Eclipse等。
三、实现三维动画效果的基础知识1.三维坐标系OpenGL使用右手坐标系表示三维坐标系,其中x轴向右,y轴向上,z轴向外。
2.矩阵变换OpenGL可以通过矩阵变换来实现图形的移动、旋转、缩放等操作。
常用的变换矩阵包括平移矩阵、旋转矩阵和缩放矩阵。
3.光照模型光照模型是OpenGL中重要的概念之一,它用来计算光源对物体的影响。
其中,主要包括光源的位置、光线的颜色和强度等因素。
OpenGL下三维模型的显示和自由旋转

20 世纪 70 年代后期 ,计算机图形工作站的出现推动了基于矢量的 3D 计算机图形学 ( 3D Computer Grap hics) 的迅速发展 . 目前 3D 计算机图形学已经广泛地应用于各个行业和领域 , 如 :3D Max ,Poser 等三维设计软件可以生成复杂的三维模型 . 考虑到软件的通用性 , 本文选 取了图形数据工业标准 — — — DXF 格式的三维模型数据文件作为源文件 , 不仅可以对任意软件 生成的 DXF 格式的三维模型文件进行处理 ,同时还可以处理三维模型和二维模型 . 在三维软件的开发方面 ,目前主要存在 2 种 API : 一个是微软的 Direct 3D ,一个是开放标 准 Open GL . Direct 3D 大量应用于民用产品 ,如游戏领域 ,而 Open GL 作为应用最为广泛的高 性能工业图形标准 ,是开发高质量的二维或三维交互式图形应用程序的首选环境 [ 1 ] . Open GL 提供的应用程序 API 包含了许多现代图形学中的基本功能 , 如 : 图元的绘制 、 颜色指定 、 纹理 映射 、 光照处理 、 双缓存动画和特效等 ; 另外 , 其跨平台的特性也备受用户推崇 ; Open GL 简化 了图形软件的开发过程 ,缩短了产品进入市场的周期 : 因此 ,我们选用 Open GL 作为开发工具 . 在对三维模型的研究中 ,需要对其进行自由旋转 ,以方便从任意角度细致地进行观察 . 本 文提供了一种通过操纵虚拟球实现对模型自由旋转的方法 ,使用户仅通过鼠标的拖动就能从 任何角度观看模型 .
v= b +c , cosβ= c/ v , sinβ= b/ v ;
2 2
1
Rx =
0 0 0
0 β cos sinβ - sinβ cosβ 0 0
opengl用三角形模拟生成球面[优质文档]
![opengl用三角形模拟生成球面[优质文档]](https://img.taocdn.com/s3/m/edae9f16bfd5b9f3f90f76c66137ee06eff94e9b.png)
在看OpenGL红皮书,看到生成球体这节,讲了很多,总感觉不如自己动手写一些代码来的实在,用OpenGL中三角形模拟球形生成.主要要点,模型视图变换,多边形表面环绕一致性,矩阵堆栈.先贴上代码.虽然是用F#写的,但是处理全是过程式的,很好理解.01 #r "F:\3D\1.0\Binaries\OpenTK\Debug\OpenTK.dll"02 #r "F:\3D\1.0\Binaries\OpenTK\Debug\OpenTK.GLControl.dll"0304open System05open System.Collections.Generic06open System.Windows.Forms07open System.Threading08open System.Drawing09open System.Drawing.Imaging010open OpenTK011open OpenTK.Graphics012open OpenTK.Graphics.OpenGL013014type loopForm() as form=015inherit Form()016let mutable x = 5.f017let mutable y = 5.f018let mutable z = 5.f019let offest = 1.f020let glControl = new OpenTK.GLControl()021let textX= new TextBox()022let textY= new TextBox()023let textZ= new TextBox()024let textLR = new TextBox()025let textUD= new TextBox()026let textInfo = new TextBox()027let labelX= new Label()028let labelY= new Label()029let labelZ= new Label()030let labelLR = new Label()031let labelUD= new Label()032let mutable first = 0033let mutable buffer = 0034let list = 0035let scale = 3.f036do037form.SuspendLayout()038glControl.Location <- new Point(10,40)039glControl.Size <- new Size(400,300)040glControl.BackColor <- Color.Red041glControl.Resize.Add(form.resize)042glControl.Paint.Add(form.paint)043form.MouseWheel.Add(form.MouseDown)044form.ClientSize <- new Size(600,400)045form.Text <- "opengl"046form.StartPosition <- FormStartPosition.Manual0 47form.Location <- new Point(1200,600)048form.Controls.Add(glControl)049form.ResumeLayout(false)050labelX.Location <- new Point(420,40)051labelY.Location <- new Point(420,70)052labelZ.Location <- new Point(420,100)053labelLR.Location <- new Point(420,130)054labelUD.Location <- new Point(420,160)055labelX.Text <- "X:" 056labelY.Text <- "Y:"057labelZ.Text <- "Z:"058labelLR.Text <- "水平:"059labelUD.Text <-"上下:"060textX.Location <- new Point(460,40)061textY.Location <- new Point(460,70)062textZ.Location <- new Point(460,100)063textLR.Location <- new Point(460,130)064textUD.Location <- new Point(460,160)065textInfo.Location <- new Point(420,190)066textInfo.Width <- 140067form.Controls.Add(textX)068form.Controls.Add(textY)069form.Controls.Add(textZ)070form.Controls.Add(textLR)071form.Controls.Add(textUD)072form.Controls.Add(labelX)073form.Controls.Add(labelY)074form.Controls.Add(labelZ)075form.Controls.Add(labelLR)076form.Controls.Add(labelUD)077form.Controls.Add(textInfo)078//#endregion 079override v.OnLoad e =080base.OnLoad e081GL.ClearColor Color.MidnightBlue082Application.Idle.Add(v.AIdle)083v.ShowUI 084textX.TextChanged.Add(form.TextChange)085textY.TextChanged.Add(form.TextChange)086textZ.TextChanged.Add(form.TextChange)087textLR.TextChanged.Add(form.TextChange)088textUD.TextChanged.Add(form.TextChange)089//踢除正反面090//GL.Enable EnableCap.CullFace091//GL.CullFace CullFaceMode.Back092//指定正反面093GL.FrontFace w094//设置材料面填充模式095GL.PolygonMode(MaterialFace.Front,PolygonMode.Fill)096GL.PolygonMode(MaterialFace.Back,PolygonMode.Line) 097//启用数组功能.098GL.EnableClientState(ArrayCap.VertexArray)099//GL.EnableClientState(ArrayCap.ColorArray)0100GL.EnableClientState(ArrayCap.IndexArray)0101//#region ""0102member v.resize (e:EventArgs) =0103GL.Viewport(0,0,glControl.ClientSize.Width,glControl.ClientSize.Height) 0104let aspect = float32 glControl.ClientSize.Width /float32glControl.ClientSize.Height0105let mutable projection =Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4,aspect,0.1f,64.f) 0106GL.MatrixMode MatrixMode.Projection0107GL.LoadMatrix(&projection)0108member v.paint (e:PaintEventArgs) =0109v.Render()0110member v.AIdle (e:EventArgs) =0111while (glControl.IsIdle) do0112v.Render()0113member v.TextChange (e:EventArgs) =0114x <- v.UIValue(textX)0115y <- v.UIValue(textY)0116z <- v.UIValue(textZ)0117member v.MouseDown(e:MouseEventArgs) =0118match v.ActiveControl with0119| :? TextBox as t1 -> 0120let mutable t = v.UIValue(t1)0121t <- t + float32 e.Delta * offest * 0.01f0122t1.Text <- t.ToString()0123| _ -> 0124v.Text <- v.ActiveControl.Text0125let state =float32 e.Delta * offest * 0.01f0126x<- x+state0127y<- y + state0128z <- z + state0129v.ShowUI0130member x.UIValue0131with get (text:TextBox) = 0132let mutable value = 0.f0133if System.Single.TryParse(text.Text,&value) then0 134value <- value0135value0136and set (text:TextBox) (value:float32) = text.Text<- value.ToString() 0137member v.ShowUI =0138textX.Text <- x.ToString()0139textY.Text <- y.ToString()0140textZ.Text <- z.ToString()0141textLR.Text <- v.UIValue(textLR).ToString()0142textUD.Text <- v.UIValue(textUD).ToString()0143member v.Normal (c:Vector3) =0144 c.Normalize() 0145 c * scale0146member v.Subdivide (v1:Vector3,v2:Vector3,v3:Vector3) =0 147let vs = Array.create 6 Vector3.Zero0148vs.[0] <- v10149vs.[1] <- v.Normal( Vector3.Lerp(v1,v2,0.5f))0150vs.[2] <- v.Normal( Vector3.Lerp(v3,v1,0.5f))0151vs.[3] <- v20152vs.[4] <- v.Normal( Vector3.Lerp(v2,v3,0.5f))0153vs.[5] <- v30154let is = Array.create 1200155is.[0] <- 00156is.[1] <- 10157is.[2] <- 20158is.[3] <- 20159is.[4] <- 10160is.[5] <- 40161is.[6] <- 40162is.[7] <- 10163is.[8] <- 30164is.[9] <- 20165is.[10] <-40166is.[11] <- 50167(vs,is)0168//#endregion 0169member v.CreatePane (angle:float32,x,y,z) =0170GL.PushMatrix()0171GL.Color3(Color.Green)0172GL.Rotate(angle,x,y,z)0173let mutable vv =[|Vector3.UnitY*scale;Vector3.UnitZ*scale;Vector3.UnitX*scale|]0174let mutable iv = [|0;1;2|]0175//let show array = printfn "%A" array0176let mutable t =int (v.UIValue(textInfo))0177if t > 6then0178t <- 60179elif t < 0then0180t <- 00181for j in0 .. t do0182let mutable av = Array.create 0 Vector3.Zero0183let mutable ev = Array.create 000184for i in0 .. 3 .. iv.Length - 1do0185let (vvv,iiv) =v.Subdivide(vv.[iv.[i]],vv.[iv.[i+1]],vv.[iv.[i+2]])0186let length = av.Length0187av <- Array.append av vvv0188let map = iiv |> Array.map (fun p -> p + length)0 189ev <- Array.append ev map0190vv <- av0191iv <- ev 0192//show vv0193//show iv0194GL.VertexPointer(3,VertexPointerType.Float,0,vv) 0195GL.DrawElements(BeginMode.Triangles,iv.Length,DrawElementsType.UnsignedInt, iv)0196GL.PopMatrix() 0197member v.Render =0198let mutable lookat = Matrix4.LookAt(newVector3(x,y,z),Vector3.Zero,Vector3.UnitY)0199GL.MatrixMode(MatrixMode.Modelview)0200GL.LoadMatrix(&lookat) 0201GL.Rotate(v.UIValue(textLR),0.f,1.f,0.f)0202GL.Rotate(v.UIValue(textUD),1.f,0.f,0.f)0203GL.Clear(ClearBufferMask.ColorBufferBit |||ClearBufferMask.DepthBufferBit)0204GL.Color3(Color.Green)0205v.CreatePane(0.f,0.f,1.f,0.f)0206v.CreatePane(90.f,0.f,1.f,0.f)0207//v.CreatePane(180.f,0.f,1.f,0.f)0208glControl.SwapBuffers()0209ignore0210let t = new loopForm()0211 t.Show() 0首先我们设定逆时针方向为正方向,分别设定正面为画布填充,反面为线填充,这样我们就能很容易知道我们生成的三角形倒底是不是正确生成的我们要的面向.0然后分别取用顶点数组和顶点数组索引功能.毕竟后面的点多,一个一个去组装没这个脑力,还没性能.0如何用三角开来模拟生成球面,方法肯定很多种,这里我们可以想象下,在坐标轴的原点就是球的原点,半径为1,被X,Y,Z轴分成八个部分,我们找到正右上的那边,与X,Y,Z轴的交点分别为x1(1,0,0),y1(0,1,0),z1(0,0,1).0然后我们把x1,y1,z1连起来画一个三角形.注意这里就有顺序了,想像一下,三个点的位置,要画正面是用逆时针方向,一算,x1,y1,z1这个方向就是,但是通常为了形象些,我们从y1上开始画,然后是前z1,然后是右x1.如代码是这样0let m utable vv = [|Vector3.UnitY*scale;Vector3.UnitZ*scale;Vector3.UnitX*scale|] let m utable iv = [|0;1;2|]0然后就是细分这三角形,过程就是这样,一个三角形分成四个.在for j in 0 .. t 这里,t越多,分的就越多,t是0,分一次成四个,t是1,四个再分别分成四个,就是16个.最后总的三角形就是4的t+1次方.0细分算法,大致如下,已知球面上二点,a1,a2,求在这球二点中间点ax.0已知球心在中间,得知,三个向量有如下关系,向量ax = (向量a2-向量a1)*0.5 + 向量a1.这样可以算到向量a1,那点ax就是向量a1*半径.0当一个三角形分成几个三角形,也就是三个顶点变成六个顶点,那么生成生成三角形的索引也要重新更新.具体过程用图来说明.0分的越细,球面越光滑,这样只生成了八分之一的球面,后面的如何画了,前面讲了矩阵堆栈的用法,刚好可以用在这样能在我方便生成另外几个面,v.CreatePane(90.f,0.f,1.f,0.f)这个是我们绕Y轴90度后,生成另外的一个面,为了不破坏全局坐标,我们可以在转之前调用PushMatrix记住当前矩阵,画完后再用PopMatrix回到当前矩阵.0看一下程序运行后的效果图.界面上的X,Y,Z指向人眼的位置,左右与上下指旋转方向.最下面指细分的程度,值越大,细分的越厉害.0大家可以把顶点索引变下顺序,然后再来看下效果,也可以把余下的六面全部补起.。
OpenGL课程设计-三维球体的实现

游戏软件设计课程报告(三维球体的实现)院系:专业:学号:姓名:指导教师:2010年10月10日目录目录一、应用程序的最终界面----------------------------------------------------------------1二、三维球体的绘制---------------------------------------------------------------------21、球体绘制方法研究 ----------------------------------------------------------------22、面分解法的实现----------------------------------------------------------------32.1面分解函数 ----------------------------------------------------------------32.2初值的选取 ----------------------------------------------------------------32.3 球体的实现----------------------------------------------------------------43、三角形绘制函数----------------------------------------------------------------44、三角面法向量函数 ----------------------------------------------------------------55、点的模长扩展函数 ----------------------------------------------------------------56、南北极法的实现----------------------------------------------------------------57、动画的实现-------------------------------------------------------------------10三、二种绘制方法的比较---------------------------------------------------------------12一、应用程序的最终界面一、应用程序的最终界面本OpenGL应用程序的最终界面主要由二部分构成,其一是参数控制栏,其二是视图显示窗。
计算机图形学课程设计完本

1中文摘要本次课程设计采用OpenGL来完成。
OpenGL是个定义了一个跨编程语言、跨平台的编程接口的规格,它用于三维图象(二维的亦可)。
OpenGL是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库。
本次课程设计是在win7系统下VC++6.0中的win32环境中,通过使用OpenGL所提供的标准库函数,综合图形学里的坐标转换,投影变换,光照以及纹理等知识,实现一个简单的太阳系的运行状况。
该系统仅做演示使用,将只包括太阳,地球与月亮,并且不保证相关数据的设定准确性。
目录一、课程设计任务及要求 (1)二、需求分析 (1)三、系统设计 (1)四、详细设计 (3)4.1 初始化的设定 (3)4.2 光源的位置与观察位置的设定 (4)4.3 纹理映射的设置 (5)4.4 各星球球体的绘制 (7)4.5 星球公转轨道 (9)4.6 人机交互式的实现 (10)五、运行调试与分析讨论 (12)5.1 程序运行截图 (12)5.2 结果分析 (13)六、设计体会与小结 (14)七、参考文献 (16)一、课程设计任务及要求1.利用OpenGL创建太阳,地球,月亮三个球体。
2. 实现“月亮绕着地球转,地球绕着太阳转”。
3. 为太阳,地球,月亮附上不同的纹理。
4. 具有较好的动画效果,消除闪烁现象。
5. 其他功能的添加。
二、需求分析本次课程设计使用的编译软件为Visual C++ 6.0。
设计中通过调用OpenGL函数库以来完成太阳,月亮,地球的球体绘制与纹理的加载,通过矩阵的变换以实现星球的运动效果。
从而模拟出太阳系的运行效果动画。
在之后,加入星球的轨道轨迹,使得模拟系统3D效果更加明显。
并加入人机交互操作。
通过“q,w,e,s,a,d”键来调整观察视角,可以实现全方位对此系统进行观察,使系统具有一定的可操作性。
三、系统设计本次课题为:实现太阳系运行动画。
系统设计步骤为:1.太阳,地球,月亮三个球体的创建。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
游戏软件设计课程报告(三维球体的实现)院系:专业:学号:姓名:指导教师:2010年10月10日目录目录一、应用程序的最终界面----------------------------------------------------------------1二、三维球体的绘制---------------------------------------------------------------------21、球体绘制方法研究 ----------------------------------------------------------------22、面分解法的实现----------------------------------------------------------------32.1面分解函数 ----------------------------------------------------------------32.2初值的选取 ----------------------------------------------------------------32.3 球体的实现----------------------------------------------------------------43、三角形绘制函数----------------------------------------------------------------44、三角面法向量函数 ----------------------------------------------------------------55、点的模长扩展函数 ----------------------------------------------------------------56、南北极法的实现----------------------------------------------------------------57、动画的实现-------------------------------------------------------------------10三、二种绘制方法的比较---------------------------------------------------------------12一、应用程序的最终界面一、应用程序的最终界面本OpenGL应用程序的最终界面主要由二部分构成,其一是参数控制栏,其二是视图显示窗。
如下图如示。
当通过左边的控制面板来修改球体参数时,右边的视图窗口即会显示出用户操作所产生的效果。
球体参数控制面板动态球体效果显示二、三维球体的绘制1、球体绘制方法研究OpenGL 绘制几何图形,本人认为关键的一步在于建立物体的几何模型。
我们通过不同的规则来对同一个物体建模,将会得到很不相同的结果。
把物体的模型建设好,即能用数学表达式来表达或说构建出一个物体,那么用OpenGL 将其画出来或说表达出来,将不会是一件很困难的事情。
如何建立球体模型呢?由于我们实际的生活经验不难发现,地球可以抽象为一个理想的球体,而地球的定位一般是通过经度纬度值。
也就是说只要有二个参数就基本上可以确定一个球体上的点的几何位置。
基于此,首先可用经纬特征来构建一个球体模型。
假想好球体也分为南北二极,再选取一个点为经度的零点,这样便可以把球体想成是由很多的水平圆和竖直圆来包围着的。
而这些圆与圆的交点就构造出了很多的小平面,我们画球的目的就是要将这些小平面一个个画出来。
每个小平面再分为二个三角面,这样使每个经纬相交的点对应着二个小三角面。
4个顶点由经纬度是容易确定的,从而2个小三角面也就易于在OpenGL 中勾画出来。
如下图所示:当然,像球这样规则的几何体还有一个更普通的建模方法,在此简称为面分解法:即是先想像出构造出该物体的最小单元,由此画出逼近物体最粗糙或说最失真的图形。
再由该最失真图形一步步细化,从而慢慢逼近最真实的图形。
球体可以想像是由很多的小三角面构成,球体最粗糙的图形可以认为是一个正4面体,它的面分解法原理是将每个三角面分再分为更小的三角面,其过程表述如下:取初始三角形三边上的中点,将该三点模长扩展为球体半径长度,再将原始三点与现在三点结合,构成了4个小三角形。
其图形表示如下:纬线1纬线2经线1经线2图:每个交点对应二个小三角面V PP1 P2 P3 P4P1P2P3 P12 P312、面分解法的实现2.1面分解函数参数v1,v2,v3为初始三角面的三个顶点向量,count记录当前要分解的级数,也就是当前该面要进行等分的次数。
若count = 0,则不需要等分,而直接以初始三个顶点画三角面。
若count = 1,则要等分一次,若count = 2,则要进行二次等分,最终该原始三角面将被分为1*4*4 = 16个。
依次类推。
程序实现代码如下:void CVRworkView::SubDivide(float *v1, float *v2, float *v3, int count){//count为等分级数if(0 >= count) //count=0,则画由三点构成的三角形{DrawTriangle(v1,v2,v3);}else{GLfloat v12[3],v23[3],v31[3];GLint i;for(i = 0; i < 3; i++){v12[i] = (v1[i]+v2[i])/2; //求取等分的中点坐标v23[i] = (v2[i]+v3[i])/2;v31[i] = (v3[i]+v1[i])/2;}Normalize(v12,(float)m_nRadius); //将所得中点进行模长扩展Normalize(v23,(float)m_nRadius);Normalize(v31,(float)m_nRadius);SubDivide(v1,v12,v31,count-1); //对所产生的4个新的三角面再进行等分SubDivide(v2,v23,v12,count-1);SubDivide(v3,v31,v23,count-1);SubDivide(v12,v23,v31,count-1);}}2.2初值的选取2.1介绍的是针对一个普通面的分解办法,进行其操作的前提是要已知经初始的三个顶点。
实际中初始面(初始图形)的设计是有一定艺术水平的。
初始图形构造的好,不仅图形的空间位置易于确定,而且也容易构造出更逼真的图形。
在一般的参考书上,球体的初始图形是一个正20面体,当然,这是一个很好的办法。
但在本次设计中,球体的初始图形设置为由6个点构成的8面体,之所以这样做,是因为这样更有利于理解球体图形的生成,而且这样也方便确定各点的空间坐标。
所构成的图形如下图所示述:初始的六个点都取自于坐标轴,关于原点对称地在各坐标轴上取二点,从而易写出一个适合坐球体初始图形的各点的坐标如下:P1(r, 0, 0),P2(-r, 0, 0)P3(0, 0, r),P4(0, 0, -r)P5(0, r, 0),P6(0, -r, 0)2.3 球体的实现void CVRworkView::DrawGeometry(){GLfloat r = (GLfloat)m_nRadius;GLfloat vdata[6][3] = { //初始点坐标{r,0.0,0.0},{-r,0.0,0.0},{0.0,r,0.0},{0.0,-r,0.0},{0.0,0.0,r},{0.0,0.0,-r}};GLuint tindices[8][3] = { //初始面的构造{2,4,0},{2,0,5},{2,5,1},{2,1,4},{3,0,4},{3,5,0},{3,1,5},{3,4,1}};for(int i = 0; i < 8; i++){ //绘制球体SubDivide(&vdata[tindices[i][0]][0],&vdata[tindices[i][1]][0],&vdata[tindices[i][2]][0],m_nCount);}}3、三角形绘制函数void CVRworkView::DrawTriangle(float *v1, float *v2, float *v3) {//以三点为顶点画三角形GLfloat normal[3] = {0,0,0};NormalTriangle(v1,v2,v3,normal); //求取面法向量glBegin(m_nPattern);glNormal3fv(normal);glVertex3fv(v1);glVertex3fv(v2);glVertex3fv(v3);glEnd();} X4、三角面法向量函数经验认为,画图时面法向量的方向判定是很关键的。
有时,所画出的图形经常看到黑白相间,使不当显示的地方却能够被人眼所看到,那么这类问题一般都是因为法向量的方向计算有误。
void CVRworkView::NormalTriangle(float *v1, float *v2, float *v3, float *vout){//求三点构成的三角形面的法向量GLfloat v12[3],v23[3];for(int i = 0; i < 3; i++){v12[i] = v2[i] - v1[i];v23[i] = v3[i] - v2[i];}vout[0] = v12[1]*v23[2] - v12[2]*v23[1];vout[1] = -(v12[0]*v23[2] - v12[2]*v23[0]);vout[2] = v12[0]*v23[1] - v12[1]*v23[0];Normalize(vout,1);}5、点的模长扩展函数当细分三角面的时候,求取中点之后还需要将该中点的模长扩展为球半径的长度,这样才会使新增的点属于球体面上的点,从而画的图形才不会失真,不会有突高突低的形状。
扩展模长的方法很简单,即是使点的失量方向不改变,只增大其模长。
代码如下述:void CVRworkView::Normalize(float *v, float radius){//向量的标准化,以模长为radius进行标准化GLfloat d = (GLfloat)sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);if(d == 0.0){return ;}v[0] /= d; v[1] /= d; v[2] /= d;v[0] *= radius; v[1] *= radius; v[2] *= radius;}6、经纬度法的实现按一定的角度分解出单位纬度,然后再按一定的角度分解出单位经度,由此可得画小三角面的循环次数以及各点上的经纬值,从而可画出图形。