使用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;}。
opengl 球体顶点坐标
opengl 球体顶点坐标在OpenGL中,创建一个球体的最简单方法是使用纬度和经度来生成顶点坐标。
以下是一个例子:```cpp#include <cmath>#include <vector>std::vector<float> createSphereVertices(float radius, int stacks, int slices) {std::vector<float> vertices;for (int i = 0; i <= stacks; ++i) {float latitude = M_PI / stacks * i;float sinLat = sin(latitude);float cosLat = cos(latitude);for (int j = 0; j <= slices; ++j) {float longitude = 2 * M_PI / slices * j;float sinLon = sin(longitude);float cosLon = cos(longitude);float x = radius * sinLat * cosLon;float y = radius * sinLat * sinLon;float z = radius * cosLat;vertices.push_back(x);vertices.push_back(y);vertices.push_back(z);}}return vertices;}int main() {float radius = 1.0f;int stacks = 30;int slices = 30;std::vector<float> sphereVertices = createSphereVertices(radius, stacks, slices);// 使用生成的顶点坐标绘制球体// ...return 0;}```这段代码创建一个球体的顶点坐标,使用纬度(stacks)和经度(slices)作为输入参数,并将其返回为一个`std::vector<float>`类型的容器。
opengl用三角形模拟生成球面[优质文档]
在看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应用程序的最终界面主要由二部分构成,其一是参数控制栏,其二是视图显示窗。
Opengl绘制我们的小屋(一)球体,立方体绘制
Opengl绘制我们的⼩屋(⼀)球体,⽴⽅体绘制这个系列我想⽤来运⽤opengl红⽪书的前⼋章节的内容,来打造⼀个室内⼩屋.这⼀章主要是定义⼏个基本的结构.并给出球体与⽴⽅体的画法,先让我们来定义⼀些基本的结构.⼀个是包含点,法向量,纹理贴图向量,⼆是矩形与圆形的⽗类,包含⼀些基本公有的处理. 1type T2N3V3 =2struct3val mutable TexCoord : Vector24val mutable Normal : Vector35val mutable Position : Vector36new(v,n,p) = {TexCoord = v;Normal = n;Position = p}7end8 [<AbstractClass>]9type Shape() =10let mutable bCreate = false11let mutable vi = 012let mutable ei = 013let mutable count = 014member this.vboID with get() = vi and set value = vi <- value15member this.eboID with get() = ei and set value = ei <- value16member this.TriangelCount with get() = count and set value = count <- value17member this.IsCreate with get() = bCreate and set value = bCreate <- value18abstract Draw : unit -> unit19abstract Init : unit -> unit20member this.InitQ : unit -> unit =fun () -> ()View Code然后是球体的画法,相关具体过程如上篇,先贴上代码,我会对其中⼀些做些说明.1type Sphere(radius:float32,level:int) =2inherit Shape()3let mutable rad,lev = radius,level4let RightLevel =5if lev < 0then lev <- 06 elif lev > 6then lev <-67override this.Draw() =8if this.IsCreate<>true then this.Init()9 GL.BindBuffer(BufferTarget.ArrayBuffer,this.vboID)10 GL.BindBuffer(BufferTarget.ElementArrayBuffer,this.eboID)11 GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f,0,IntPtr.Zero)12 GL.DrawElements(BeginMode.Triangles,this.TriangelCount,DrawElementsType.UnsignedInt,IntPtr.Zero)13override this.Init() =14let alls = Array.create 6 (new T2N3V3())15 alls.[0] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitX, Vector3.UnitX * rad )16 alls.[1] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitY, Vector3.UnitY * rad )17 alls.[2] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitZ, Vector3.UnitZ * rad )18 alls.[3] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitX, -Vector3.UnitX * rad )19 alls.[4] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitY, -Vector3.UnitY * rad )20 alls.[5] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitZ, -Vector3.UnitZ * rad )21let is = [|221;2;0230;2;4240;4;5255;1;0261;3;2274;2;3284;3;5291;5;330 |]31let (vvv:T2N3V3 []),(iv: int[]) = this.Sub (alls,is)32let mutable vID,eID = 0,033//let mutable tv,vv,pv = vvv |> Array.map (fun v -> v.TexCoord,v.Normal,v.Position) |> Array.unzip334 GL.GenBuffers(1,&vID)35 GL.BindBuffer(BufferTarget.ArrayBuffer,vID)36 GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 8 * vvv.Length),vvv,BufferUsageHint.StaticDraw)3738 GL.GenBuffers(1,&eID)39 GL.BindBuffer(BufferTarget.ElementArrayBuffer,eID)40 GL.BufferData(BufferTarget.ElementArrayBuffer,IntPtr (4 * iv.Length),iv,BufferUsageHint.StaticDraw)4142 this.vboID <- vID43 this.eboID <- eID44 this.TriangelCount <- iv.Length45 this.IsCreate <- true46 ()47member v.GetMidValue (first:T2N3V3,second:T2N3V3) =48let midN = Vector3.Lerp(first.Position,second.Position,0.5f) |> Vector3.Normalize49let midP = midN *(float32 rad)50let midT = Vector2.Lerp(first.TexCoord,second.TexCoord,0.5f) |> Vector2.Normalize51let result = new T2N3V3(midT,midN,midP)52 result53member v.Subdivide (v1:T2N3V3,v2:T2N3V3,v3:T2N3V3) =54let vs = Array.create 6 (new T2N3V3())55 vs.[0] <- v156 vs.[1] <- v.GetMidValue(v1,v2)57 vs.[2] <- v.GetMidValue(v3,v1)58 vs.[3] <- v259 vs.[4] <- v.GetMidValue(v2,v3)60 vs.[5] <- v361let is = Array.create 12062 is.[0] <- 063 is.[1] <- 164 is.[2] <- 265 is.[3] <- 266 is.[4] <- 167 is.[5] <- 468 is.[6] <- 469 is.[7] <- 170 is.[8] <- 371 is.[9] <- 272 is.[10] <-473 is.[11] <- 574 (vs,is)75member this.Sub(alls:T2N3V3 [],is:int []) =76//let mutable tv,vv,pv = alls |> Array.map (fun v -> v.TexCoord,v.Normal,v.Position) |> Array.unzip377let mutable allv = alls78let mutable iv = is79let show array = printfn "%A" array80for j in0 .. lev do81let mutable av = Array.create 0 (new T2N3V3())82let mutable ev = Array.create 0083 printfn "%i" allv.Length84 printfn "%i" iv.Length85for i in0 .. 3 .. iv.Length - 1do86let (vvv,iiv) = this.Subdivide(allv.[iv.[i]],allv.[iv.[i+1]],allv.[iv.[i+2]])87let length = av.Length88 av <- Array.append av vvv89let map = iiv |> Array.map (fun p -> p + length)90 ev <- Array.append ev map91 allv <- av92 iv <- ev93 allv |> Array.map (fun p -> p.Position) |> show94 show iv95 allv,ivView Code初始化需要的⼆个参数,分别代表球的⼤⼩(radius),与画的细分程度(level).其中相关如何绘制球体代码在上⽂有讲,相当于有是把⼀个分别位于x,y,z各(+radius,-radius)这六个点,组成的⼀个⼋个三⾓形,索引点的位置如Init⾥GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f,0,IntPtr.Zero)其中的T2fN3fV3f对应于我们的数据结构T2N3V3,这个函数分别相当于指定GL.TexCoordPointer,GL.NormalPointer,GL.VertexPointer(还会打开相应状态),会⾃动给我们处理好,我们也可以只指定顶点,如下GL.VertexPointer(3,VertexPointerType.Float,4*8,IntPtr (4*8-4*5)),这些数据之间的间隔对应与我们前⾯写⼊的GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 8 * vvv.Length),vvv,BufferUsageHint.StaticDraw)其中vvv是T2N3V3的结构.基本的GL.BindBuffer的对应的三个处理就不细说了,在Draw⾥,BindBuffer是指定我们当前格式数据在存储位置,然后分别调⽤InterleavedArrays设定各顶点的状态,然后是调⽤DrawElements对应上⾯的GL.BindBuffer(BufferTarget.ElementArrayBuffer,this.eboID)处理.然后是⽴⽅体的绘制,其中⽴⽅体的绘制⽤的⽅法看起来会容易理解.如下1type Cube(width:float32,height:float32,length:float32,index:int) =2inherit Shape()3let mutable id = index4let xl,yl,zl =width/2.f,height/2.f,length/2.f5let mutable color = Color.White6let v8 = [|7new Vector3(xl,yl,zl)8new Vector3(-xl,yl,zl)9new Vector3(-xl,-yl,zl)10new Vector3(xl,-yl,zl)11new Vector3(xl,yl,-zl)12new Vector3(-xl,yl,-zl)13new Vector3(-xl,-yl,-zl)14new Vector3(xl,-yl,-zl)15 |]16new(x,y,z) =17let rnd = System.Random().Next()18 printfn "%i" rnd19 Cube(x,y,z,-1)20override this.Draw() =21if this.IsCreate<>true then this.Init()22 GL.EnableClientState(ArrayCap.VertexArray)23 GL.EnableClientState(ArrayCap.NormalArray)24 GL.BindBuffer(BufferTarget.ArrayBuffer,this.vboID)25 GL.VertexPointer(3,VertexPointerType.Float,0,IntPtr.Zero)26 GL.PushMatrix()27if id >= 0 && id < 8then28 GL.Translate(v8.[id])29 GL.Color3(this.Color:Color)30 GL.Normal3(Vector3.UnitZ)31 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|0;1;2;0;2;3|])32//GL.Color3(Color.Black)33 GL.Normal3(Vector3.UnitY)34 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|4;5;1;4;1;0|])35//GL.Color3(Color.Red)36 GL.Normal3(Vector3.UnitX)37 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|4;0;3;4;3;7|])38//GL.Color3(Color.Green)39 GL.Normal3(-Vector3.UnitY)40 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|3;2;6;3;6;7|])41//GL.Color3(Color.Blue)42 GL.Normal3(-Vector3.UnitX)43 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|1;5;6;1;6;2|])44//GL.Color3(Color.DodgerBlue)45 GL.Normal3(-Vector3.UnitZ)46 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|5;4;7;5;7;6|])47 GL.PopMatrix()48override this.Init() =49let mutable vID = 050 GL.GenBuffers(1,&vID)51 GL.BindBuffer(BufferTarget.ArrayBuffer,vID)52 GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 3 * v8.Length),v8,BufferUsageHint.StaticDraw)53 this.vboID <- vID54 this.IsCreate <- true55let rnd = System.Random(this.GetHashCode())56 this.Color <- Color.FromArgb(rnd.Next(0,255),rnd.Next(0,255),rnd.Next(0,255))57 ()58member this.Index with get() = id and set value = id <-value59member this.Color with get() = color and set value = color <- valueView Code上图中的V8分别对应其中的0-7个顶点,GL.DrawElements后⾯的0;1;2;0;2;3分别是以三⾓形的画法来画⼀个正⽅形.⽴⽅体的画法主要是确定宽,⾼,长,我们这样定义,我们站在原点上,⾯向Z+轴,我们的⼿展开来表⽰X轴(对应宽度),⽽我们的⾝⾼表⽰Y轴(对应⾼度),和我们⾯向距离的长远来表⽰Z轴,(对应长度).绘制也是8个⾯,和上⾯⼀样,也是在缓存中记录顶点,但是不⼀样的是,顶点索引是在绘制时没有⽤到顶点索引缓存,主要考虑后⾯有法向量的处理,还有现在没有加上的纹理贴图的处理.在这⾥,我们要特别注意,顶点顺序问题,在opengl,默认正⾯是逆时针,⽽我们可以看0;1;2;0;2;3对应图上的顺序.然后⼤家可能会发现,画⽴⽅体的后⾯5;4;7;5;7;6,这个顺序好像不对,是顺时针的.⼤家可以想象下,我们在门外看门的逆时针画法与我们在门内看门外顺时针的画法是⼀样的.所以如果我们要画后⾯4,5,6,7我们以为的是逆时针是不对的,我们要想象我们在那边来看,然后再画,应该是5,4,7,6这个⽅向.其中纹理贴图后⾯会说,和这处理也有类似.在上⾯,我们看到我们都没对顶点的颜⾊来定义,这⾥没必要,因为后⾯我们肯定要⽤到灯光,⽤到灯光的话,设置的颜⾊都没⽤,我们会⽤到灯光颜⾊与材质的颜⾊.纹理贴图也有没对应处理,这⾥在后⾯我会根据讲到再来改写相关处理.下⼀节,主要是讲第⼀⼈称漫游的相关处理.。
一个OPENGL台球实例
//一个OPENGL台球实例――――#include <gl/glut.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <time.h>#include <windows.h>#include <mmsystem.h>#pragma comment(lib, "OPENGL32.LIB")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma comment(lib, "winmm.lib")#define WIDTH 1024#define HEIGHT 768#define BMP_Header_Length 54#define PI 3.1415926#define L0 GL_LIGHT0#define L1 GL_LIGHT1//变量申明GLint font=(int)GLUT_BITMAP_HELVETICA_12,width=1024,height=768; GLuint texGround,texWall,thb,texzb,texqz,thb1,texqg,texgt,texhe;int mx=0,my=0,i=0,j=0,k=0,bcnt=16,jds=0,hqg=0,jiqiu=0;int leftm=0,rightm=0;GLfloat rx,ry,rz,speed=0;static GLfloat kx=0,ky=0,kz=0,zoom=300;static GLfloat anglex=0,angley=90,nowanglex=0,nowangley=0,nowatx=0,nowaty=0; static GLfloat at[6]={0.0,300.0,500.0,0.0,80.0,0.0};static GLfloat M=1,U=0.2,T=0.1,QR=5.715,G=-4;GLfloat m[16];//定义球及位置矢量结构体struct p3{GLfloat x;GLfloat y;GLfloat z;};struct myb{ struct p3 p;struct p3 v;struct p3 a;GLfloat mv;GLfloat ma;int jd;GLuint wl;} B[16];//函数申明int power_of_two(int n);GLuint load_texture(const char* file_name);void mydball(GLfloat mybr,GLuint BALL);void myinitball();void mycolide(int j,int k);void mybianyuan(int j);void myjindai(int j);void mylight(GLint lh,GLfloat lx,GLfloat ly,GLfloat lz,GLfloat lm);void renderoom(void);void renderqz(void);void myinitload();void myIdle(void);void myDisplay(void);static void key(unsigned char key,int x,int y);static void mymouse(int mbutton,int mstate,int x,int y);static void mymotion(int x,int y);void myhqg(GLfloat mspeed);void mystring(float x, float y, void *font, char* c);void myto2d();void myto3d();int main(int argc, char* argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_STENCIL);glutInitWindowPosition(200, 100);glutInitWindowSize(WIDTH, HEIGHT);glutCreateWindow("OpenGL光照演示");glutFullScreen();myinitball();glutDisplayFunc(&myDisplay);glutKeyboardFunc(key); //设置键盘回调函数glutIdleFunc(&myIdle); //设置窗口刷新的回调函数glutMouseFunc(mymouse); //设置鼠标器按键回调函数glutMotionFunc(mymotion); //设置鼠标器移动回调函数mylight(L1,0,390,0,1); //光照模型glutMainLoop();return 0;}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);// 创建透视效果视图glLoadIdentity();gluPerspective(60.0f, 16.0/9, 1, 10000.0f);glTranslatef(kx,ky,kz);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(at[0],at[1],at[2],at[3],at[4],at[5], 0.0, 1.0, 0.0);renderoom();renderqz();for(i=0;i<bcnt;i++){if(B[i].jd==0){for (j=0; j < 15; j++) m[j] = 0.0;m[0] = m[5] = m[10] = 1.0;m[7] = (-1.0)/405;glPushMatrix();glTranslatef(B[i].p.x,B[i].p.y,B[i].p.z);glPushMatrix();glTranslatef(0, 400, 0);glMultMatrixf(m);glTranslatef(0, -400, 0);glDepthMask(GL_FALSE);glEnable (GL_BLEND);glColor4f(0.3,0.3,0.3,0.5);glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);mydball(QR, texhe);glDisable (GL_BLEND);glDepthMask(GL_TRUE);glPopMatrix();glRotatef(B[i].ma, B[i].a.x, B[i].a.y, B[i].a.z);mydball(QR,B[i].wl);glPopMatrix();}else{glPushMatrix();glTranslatef(B[i].p.x,B[i].p.y,B[i].p.z);mydball(QR,B[i].wl);glPopMatrix();}}if(hqg==1) myhqg(speed);glutSwapBuffers();}void myIdle(void){GLfloat vx=0,vz=0;at[0]=zoom*(cos(anglex))+at[3];at[1]=zoom*(sin(angley))+at[4];at[2]=zoom*(sin(anglex))+at[5];for(i=0;i<bcnt;i++){if(B[i].jd==0){for(k=i+1;k<bcnt;k++) mycolide(i,k);//碰撞检测mybianyuan(i);myjindai(i);B[i].mv=pow(B[i].v.x,2)+pow(B[i].v.z,2);if(B[i].mv>0.1){B[i].mv=sqrt(B[i].mv);vx=B[i].v.x/B[i].mv;vz=B[i].v.z/B[i].mv;B[i].mv+=G*T;B[i].v.x=B[i].mv*vx;B[i].v.z=B[i].mv*vz;B[i].p.x+=B[i].v.x*T;B[i].p.z+=B[i].v.z*T;B[i].a.x=(-1)*vz;B[i].a.z=vx;B[i].ma+=-180*B[i].mv*T/(QR*PI);}else B[i].mv=0;}}if(hqg==1){if(speed>200) speed-=200;else speed+=2;}if(jiqiu==1){GLfloat atxy=0;atxy=sqrt(pow(at[3]-at[0],2)+pow(at[5]-at[2],2));B[0].v.x=speed*(at[3]-at[0])/atxy;B[0].v.z=speed*(at[5]-at[2])/atxy;jiqiu=0;speed=0;}if(leftm){B[0].v.x=0;B[0].v.z=0;speed=0;}myDisplay();}void myinitball(){GLfloat hhh;hhh=2*QR*sin(PI/3);B[0].p.x=0; B[0].p.y=80; B[0].p.z=-70;B[1].p.x=0; B[1].p.y=80; B[1].p.z=70;B[2].p.x=-3*QR; B[2].p.y=80; B[2].p.z=70.0+3.0*hhh;B[3].p.x=-1*QR; B[3].p.y=80; B[3].p.z=70+hhh;B[4].p.x=4*QR; B[4].p.y=80; B[4].p.z=70+4.0*hhh;B[5].p.x=2*QR; B[5].p.y=80; B[5].p.z=70+2.0*hhh;B[6].p.x=-2*QR; B[6].p.y=80; B[6].p.z=70+4.0*hhh;B[7].p.x=QR; B[7].p.y=80; B[7].p.z=70+3.0*hhh;B[8].p.x=0; B[8].p.y=80; B[8].p.z=70+2.0*hhh;B[9].p.x=2*QR; B[9].p.y=80; B[9].p.z=70+4.0*hhh;B[10].p.x=QR; B[10].p.y=80; B[10].p.z=70+hhh;B[11].p.x=-1*QR; B[11].p.y=80; B[11].p.z=70+3.0*hhh;B[12].p.x=0; B[12].p.y=80; B[12].p.z=70+4.0*hhh;B[13].p.x=-4*QR; B[13].p.y=80; B[13].p.z=70+4.0*hhh;B[14].p.x=-2*QR; B[14].p.y=80; B[14].p.z=70.0+2.0*hhh;B[15].p.x=3*QR; B[15].p.y=80; B[15].p.z=70+3.0*hhh;for(i=0;i<bcnt;i++){B[i].v.x=0; B[i].v.y=0; B[i].v.z=0;B[i].a.x=0; B[i].a.y=0; B[i].a.z=0;B[i].jd=0;B[i].mv=0;B[i].ma=0;}myinitload();}void mycolide(int j,int k){GLfloat rr,cx,cy,ccx,ccy,v1c,v1cc,v2c,v2cc;rr=sqrt(pow(B[k].p.x-B[j].p.x,2)+pow(B[k].p.z-B[j].p.z,2));if(rr<2*QR-1){PlaySound("audio/hit.wav", NULL, SND_FILENAME | SND_ASYNC);cx=(B[k].p.x-B[j].p.x)/rr;cy=(B[k].p.z-B[j].p.z)/rr;ccx=cy*(-1);ccy=cx;v1c=B[j].v.x*cx+B[j].v.z*cy;v1cc=B[j].v.x*ccx+B[j].v.z*ccy;v2c=B[k].v.x*cx+B[k].v.z*cy;v2cc=B[k].v.x*ccx+B[k].v.z*ccy;B[j].v.x=v1cc*ccx+v2c*cx;B[j].v.z=v1cc*ccy+v2c*cy;B[k].v.x=v1c*cx+v2cc*ccx;B[k].v.z=v1c*cy+v2cc*ccy;B[k].p.x=B[j].p.x+2*QR*cx;B[k].p.z=B[j].p.z+2*QR*cy;}}void mybianyuan(int j){if(abs(B[j].p.x)>72-2*QR ){if(B[j].p.x>0) B[j].p.x=72-2*QR;if(B[j].p.x<0) B[j].p.x=-72+2*QR;B[j].v.x*=(-1);}if(abs(B[j].p.z)>137-2*QR ){if(B[j].p.z>0) B[j].p.z=137-2*QR;if(B[j].p.z<0) B[j].p.z=-137+2*QR;B[j].v.z*=(-1);}}void myjindai(int j){GLfloat hhh;hhh=2*QR*sin(PI/3);if(sqrt(pow(B[j].p.x-(-65),2)+pow(B[j].p.z-(-135),2))<15 ||sqrt(pow(B[j].p.x-65,2)+pow(B[j].p.z-(-135),2))<15 ||sqrt(pow(B[j].p.x-(-65),2)+pow(B[j].p.z-135,2))<15 ||sqrt(pow(B[j].p.x-65,2)+pow(B[j].p.z-135,2))<15 ||sqrt(pow(B[j].p.x-(-70),2)+pow(B[j].p.z,2))<12 ||sqrt(pow(B[j].p.x-70,2)+pow(B[j].p.z,2))<12 ){if(j==0) {B[0].p.x=0; B[0].p.y=80; B[0].p.z=-70;}else if(j==8) {B[8].p.x=0; B[8].p.y=80; B[8].p.z=70+2.0*hhh;}else{B[j].jd=1;jds+=1;B[j].p.z=-100+jds*20;B[j].p.y=80;if(j>8) B[j].p.x=100;else B[j].p.x=-100;}B[j].v.x=0;B[j].v.y=0;B[j].v.z=0;}}static void key(unsigned char key,int x,int y){switch (key){case 27 :exit(0);case 'd' :case 'D' :if(kx>-490) kx-=10;break;case 'a':case 'A':if(kx<490) kx+=10;break;case 'w':case 'W':zoom-=10;if(zoom<10) zoom=10;break;case 's':case 'S':zoom+=10;if(zoom>500) zoom=500;break;}}static void mymouse(int mbutton,int mstate,int x,int y){mx=x;my=y;if(mbutton==GLUT_LEFT_BUTTON && mstate==GLUT_DOWN){ nowatx=kx;nowaty=ky;leftm=1;rightm=0;}else {leftm=0;}if(mbutton==GLUT_MIDDLE_BUTTON && mstate==GLUT_DOWN){at[3]=B[0].p.x; at[4]=B[0].p.y; at[5]=B[0].p.z; }if(mbutton==GLUT_RIGHT_BUTTON && mstate==GLUT_DOWN){nowanglex=anglex;nowangley=angley;leftm=0;rightm=1;hqg=1; }else {rightm=0;hqg=0;}if(mbutton==GLUT_RIGHT_BUTTON && mstate==GLUT_UP) jiqiu=1;else jiqiu=0;}static void mymotion(int x,int y){if(leftm) { kx=nowatx+x-mx; ky=nowaty+y-my; }if(rightm) {anglex=nowanglex+(x-mx)*0.01; angley=nowangley+(y-my)*0.01;} }void myinitload(){B[1].wl=load_texture("tex/B1.bmp");B[2].wl=load_texture("tex/B2.bmp");B[3].wl=load_texture("tex/B3.bmp");B[4].wl=load_texture("tex/B4.bmp");B[5].wl=load_texture("tex/B5.bmp");B[6].wl=load_texture("tex/B6.bmp");B[7].wl=load_texture("tex/B7.bmp");B[8].wl=load_texture("tex/B8.bmp");B[9].wl=load_texture("tex/B9.bmp");B[10].wl=load_texture("tex/B10.bmp");B[11].wl=load_texture("tex/B11.bmp");B[12].wl=load_texture("tex/B12.bmp");B[13].wl=load_texture("tex/B13.bmp");B[14].wl=load_texture("tex/B14.bmp");B[15].wl=load_texture("tex/B15.bmp");B[0].wl=load_texture("tex/B16.bmp");texGround=load_texture("tex/DB.bmp");texWall=load_texture("tex/wood.bmp");thb=load_texture("tex/thb2.bmp");thb1=load_texture("tex/thb1.bmp");texzb=load_texture("tex/zb.bmp");texqz=load_texture("tex/qz.bmp");texqg=load_texture("tex/QG.bmp");texgt=load_texture("tex/GT.bmp");texhe=load_texture("tex/black.bmp");}int power_of_two(int n){if( n <= 0 )return 0;return (n & (n-1)) == 0;}GLuint load_texture(const char* file_name){GLint width, height, total_bytes;GLubyte* pixels = 0;GLuint last_texture_ID, texture_ID = 0;FILE* pFile = fopen(file_name, "rb");if( pFile == 0 )return 0;fseek(pFile, 0x0012, SEEK_SET);fread(&width, 4, 1, pFile);fread(&height, 4, 1, pFile);fseek(pFile, BMP_Header_Length, SEEK_SET);{GLint line_bytes = width * 3;while( line_bytes % 4 != 0 ) ++line_bytes;total_bytes = line_bytes * height;}pixels = (GLubyte*)malloc(total_bytes);if( pixels == 0 ) {fclose(pFile); return 0;}if( fread(pixels, total_bytes, 1, pFile) <= 0 ) { free(pixels); fclose(pFile); return 0; } {GLint max;glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);if( !power_of_two(width) || !power_of_two(height) || width > max || height > max ){const GLint new_width = 256;const GLint new_height = 256; // 规定缩放后新的大小为边长的正方形GLint new_line_bytes, new_total_bytes;GLubyte* new_pixels = 0;new_line_bytes = new_width * 3;while( new_line_bytes % 4 != 0 )++new_line_bytes;new_total_bytes = new_line_bytes * new_height;new_pixels = (GLubyte*)malloc(new_total_bytes);if( new_pixels == 0 ) { free(pixels); fclose(pFile); return 0; }gluScaleImage(GL_RGB,width, height, GL_UNSIGNED_BYTE, pixels,new_width, new_height, GL_UNSIGNED_BYTE, new_pixels);free(pixels);pixels = new_pixels;width = new_width;height = new_height;}}glGenTextures(1, &texture_ID);if( texture_ID == 0 ) { free(pixels); fclose(pFile); return 0; }glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture_ID);glBindTexture(GL_TEXTURE_2D, texture_ID);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEA T);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);glBindTexture(GL_TEXTURE_2D, last_texture_ID);free(pixels);return texture_ID;}void mylight(GLint lh,GLfloat lx,GLfloat ly,GLfloat lz,GLfloat lm){glPushMatrix();{/********* 光照处理**********/GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1 };GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1 };GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_position0[] = { lx, ly, lz ,lm }; //定义光位置得齐次坐标(x,y,z,w),如果w=1.0,为定位光源(也叫点光源),如果w=0,为定向光源(无限光源),定向光源为无穷远点,因而产生光为平行光。
OpenGLES绘制3D图形
OpenGL ES绘制3D图形OpenGL ES是 OpenGL三维图形API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。
Ophone目前支持OpenGL ES 1.0 ,OpenGL ES 1.0 是以OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以OpenGL 1.5 规范为基础的。
本文主要介绍利用OpenGL ES绘制图形方面的基本步骤。
本文内容由三部分构成。
首先通过EGL获得OpenGL ES的编程接口;其次介绍构建3D程序的基本概念;最后是一个应用程序示例。
EGLOpenGL ES 本质上是一个图形渲染管线的状态机,而EGL 则是用于监控这些状态以及维护帧缓冲和其他渲染面的外部层。
图1 是一个典型的EGL 系统布局图。
EGL 视窗设计是基于人们熟悉的用于Microsoft Windows (WGL )和UNIX (GLX )上的OpenGL 的Native 接口,与后者比较接近。
OpenGL ES 图形管线的状态被存储于EGL 管理的一个上下文中。
帧缓冲和其他绘制渲染面通过EGL API 创建、管理和销毁。
EGL 同时也控制和提供了对设备显示和可能的设备渲染配置的访问。
图1OpenGL ES 需要一个渲染上下文和渲染面。
渲染上下文中存储OpenGL ES的状态信息,渲染面用于图元的绘制。
编写OpenGL ES之前需要EGL的操作有:查询设备可以支持的显示句柄,并初始化。
∙创建渲染面,绘制OpenGL ES图形。
∙创建渲染上下文。
EGL需要创建OpenGL ES渲染上下文用于关联到某个渲染面。
Ophone中EGL包括4个类,分别是EGLDisplay:显示句柄、EGLConfig:配置类;EGLContext:渲染上下文;的类和EGLSurface:可渲染的视图类。
EGL可以认为成OpenGL ES和本地窗口系统之间的中间层。
本地窗口系统指GNU/Linux上X窗口系统,或者Mac OX X's Quartz等。
使用open GL在绘制球体的基础上增加光照和材质设置
(计算机图形学)实验报告实验名称使用open GL在绘制球体的基础上增加光照和材质设置实验时间年月日专业班级学号:姓名:成绩教师评语:一、实验目的1、了解并学习open GL的编程;2、掌握在open GL生成图形的基本思想和基本步骤;3、使用open GL具体生成简单的三维立体图形;4、在生成的三维立体的图形上面增加光照和材质的设置。
二、实验原理在上一个实验的基础上,对绘制出来的球体进行光照和材质的设置使其看起来更有立体感,其中对我们有以下几条要求:1、理解环境光,漫反射光和镜面反射光的光照模型2、理解phong光照模型,熟练掌握opengl中设置光照的方法3、掌握材质的设置方式一.材质的指定材质和灯光一样有三种属性:环境属性,漫反射属性和镜面反射属性,这些属性确定了材质反射灯光的多少。
设置材质和设置光照很相似,设置材质的函数是glMaterial*()glMaterial{if}v(face, pname, value)face :指明对物体的哪些面进行材质设置GL_FRONTGL_BACKGL_FRONT_AND_BACKPname:要设置的材质属性GL_AMBIENT 设置材料的环境颜色GL_DIFFUSE 设置材料的漫反射颜色GL_SPECULAR 设置材料的镜面反射颜色GL_AMIBIENT_AND_DIFFUSE 设置材料的环境和漫反射颜色GL_SHININESS 设置镜面指数GL_EMISSION 设置材料的发散颜色GL_COLOR_INDEXES 设置环境,漫反射和镜面反射的颜色索引1.通常,GL_AMBIENT 和GL_DIFFUSE 都取相同的值,可以达到比较真实的效果。
使用GL_AMBIENT_AND_DIFFUSE 可以同时设置 GL_AMBIENT 和 GL_DIFFUSE属性。
2.GL_SHININESS属性。
该属性只有一个值,称为“镜面指数”,取值范围是 0到128。
基于OPENGL的球体碰撞动画模拟
OpenGL(全写 Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口 规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便 的底层图形库。
OpenGL™ 是行业领域中最为广泛接纳的 2D/3D 图形 API, 其自诞生至今已催生了各种 计算机平台及设备上的数千优秀应用程序。OpenGL™ 是独立于视窗操作系统或其它操作系 统的,亦是网络透明的。在包含 CAD、内容创作、能源、娱乐、游戏开发、制造业、制药业 及虚拟现实等行业领域中,OpenGL™ 帮助程序员实现在 PC、工作站、超级计算机等硬件设 备上的高性能、极具冲击力的高视觉表现力图形处理软件的开发。
OpenGL 是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开 发的应用程序可以十分方便地在各种平台间移植;OpenGL 可以与 Visual C++紧密接口,便于 实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;OpenGL 使用简便,效 率高。它具有七大功能:
1.建模:OpenGL 图形库除了提供基本的点、线、多边形的绘制函数外,还提供了复杂 的三维物体(球、锥、多面体、茶壶等)以及复杂曲线和曲面绘制函数。
2.变换:OpenGL 图形库的变换包括基本变换和投影变换。基本变换有平移、旋转、缩 放、镜像四种变换,投影变换有平行投影(又称正射投影)和透视投 影两种变换。其变换 方法有利于减少算法的运行时间,提高三维图形的显示速度。
3.颜色模式设置:OpenGL 颜色模式有两种,即 RGBA 模式和颜色索引(Color Index)。 4.光照和材质设置:OpenGL 光有自发光(Emitted Light)、环境光(Ambient Light)、 漫反射光(Diffuse Light)和高光(Specular Light)。材质是用光反射率来表示。场景(Scene) 中物体最终反映到人眼的颜色是光的红绿蓝分量与材质红绿蓝分量的反射率相乘后形成的 颜色。 5:纹理映射(Texture Mapping)。利用 OpenGL 纹理映射功能可以十分逼真地表达物体
实验一OpenGL直线,圆的绘制
实验一、Ope nGL直线、圆的绘制1、实验目的1)了解OpenGL图形库的功能和结构;2)学习了解OpenGL程序的基本结构,及常用函数;3 )学习使用OpenGL绘制基本图形(线、圆);2、实验内容1 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出直线。
2 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出圆。
3、实验过程1)在系统上配置好OpenGL的环境(头文件,库文件,和链接库文件);2)使用Visual V++6.0新建一个C++文档,并创建相应的工程;3)在文档中引入OpenG啲头文件,编辑代码实现鼠标拖动画直线,画圆。
4、实验结果可单击鼠标左键,然后拖动鼠标画出两条直线,并同时画出圆; 可单击鼠标右键,然后拖动鼠标画出两个圆,并同时画出直线。
结果截图:1.鼠标左键主要控制绘制的直线:石Open诂L直找和园的锭制5、实验代码1. #in elude vgl/glut.h>2. #in elude <math.h>3.3. // GLint pNum = 0;4. GLint px1, py1, px2, py2, ex, cy, r;5. GLint winWidth=600, winHeight=600;-/25.} 26.7. 8. llllllllllllllllll 画直线 llllllllllll 9. void Draw_Brese nham(i nt pStartx,i nt pStarty,i nt 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.27. pEn dx,i nt pEndy) {ll 用Bresenham 算法画直线 int i; if(pStartx==pE ndx) ll 为竖线 if(pStartyv=pE ndy) for(i=pStarty;i<=pE ndy;i++) glVertex2f(pStartx,i); else for(i=pE ndy;i<=pStarty;i++) glVertex2f(pStartx,i); return;-/// 为横线 if(pStarty==pE ndy) { if(pStartx<=pE ndx) { for(i=pStartx;i<=pE ndx;i++) glVertex2f(i,pStarty);} else { for(i=pE ndx;i<=pStartx;i++) glVertex2f(i,pStarty); } return; } // 为斜线 float m=(pE ndy-pStarty)*1.0/(pE ndx-pStartx); 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49.-/ float p;}else-/p=2*m-1; if(m>0 && m<=1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty); if(p>=0) { p+=2*m-2; pStarty++; } else p+=2*m; } { while(pE ndx<=pStartx) {50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71.} else glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=2*m-2; pEndy++; } else p+=2*m; } } return; } p=-2*m-1; if(m<0 && m>=-1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty);72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93.} elseif(p>=0) { p+=-2*m-2; pStarty--; } else p+=-2*m; } } else { while(pE ndx<=pStartx) { glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=-2*m-2; pEn dy--; p+=-2*m;94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115.} else } return; } p=2/m-1; if(m>1) { if(pStartyvpE ndy) { while(pStartyv=pE ndy) { glVertex2f(pStartx,pStarty++); if(p>=0) { p+=2/m-2; pStartx++; p+=2/m; }116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137.-/else {while(pE ndyv=pStarty) {glVertex2f(pE ndx,pE ndy++); if(p>=0) {p+=2/m-2; pEndx++; } else p+=2/m; } }return;} p=-2/m-1; if(pStarty<pE ndy) { while(pStarty<=pE ndy)138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153.154. 155. 156. 157. 158. 159.-/181.{glVertex2f(pStartx,pStarty++);if(p>=0){p+=-2/m-2;pStartx--;}elsep+=-2/m;}}else{while(pE ndyv=pStarty){glVertex2f(pE ndx,pE ndy++);if(p>=0){p+=-2/m-2;pEn dx--;}else160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180.-/203. }182.p+=-2/m; 183. }184. }185. }186.187.////////////////// 画圆//////////// 188. /////////其他象限绘制189. void CirclePoi nts(i nt x,i nt y){190.// 第1象限191.glVertex2f(x,y); 192.glVertex2f(y,x);193.// 第2象限194.glVertex2f(-x,y); 195.glVertex2f(-y,x);196.// 第3象限197.glVertex2f(-y,-x); 198.glVertex2f(-x,-y);199.// 第4象限200.glVertex2f(x,-y); 201.glVertex2f(y,-x);202.-/void DrawCircle(i nt cx,i nt cy,i nt radis){ glPushMatrix(); gITra nslatef(cx,cy,0); glPoi ntSize(1);glColor3f(0.5f, 0.5f, 1.0f); glBegi n( GL_POINTS);int x,y; double p; x=0; y=radis; p=1.25-radis; while(x<=y+1) {CirclePoi nts(x,y); x++; if(p>=0) { y--;p+=2.0*(x-y)+5;204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225.〃////////中点算法画圆-/} else p+=2*x+3; }glE nd(); glPopMatrix(); }////////// 绘制坐标轴 void DrawOx(){ glColor3f(0.95, 0.7, 0.8); glPoi ntSize(1); glBeg in (GL_LINES); glVertex2f(-wi nWidth/2,0); glVertex2f(wi nWidth/2,0); glVertex2f(0,wi nH eight/2); glVertex2f(0,-wi nH eight/2); glE nd(); }226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243.244. 245. 246. 247.////////// 显示函数-/ 248. void Display(){249. 〃//////GL_COLOR_BUFFER_BIT(用背景颜色填充) 250. glClear(GL_COLOR_BUFFER_BIT);251.251. DrawOx();253.252. glColor3f(0.0,0.0,1.0);255.253. glBegi n( GL_POINTS);254. //Brese nhamL in e(px1, py1, px2, py2);255. Draw_Brese nham(px1, py1,px2, py2);256. glE nd();257. glBegi n( GL_POINTS);258. Draw_Brese nham(py1, px1,py2, px2);259. glE nd();260. //glBegi n(GL_LINES);261. 〃glVertex2f(px1,py1);262. 〃glVertex2f(px2,py2);263. 〃glVertex2f(py1,px1);264. 〃glVertex2f(py2,px2);265. //glE nd();269.270. DrawCircle(cx,cy,r);271. DrawCircle(cy,cx,r);272.273. III 交换缓冲区274. glutSwapBuffers();275. 〃glFlush();〃刷新绘图命令276. }277.278.279. II 设置渲染状态(听起来满下人,实际上很简单)280. void SetupRC(void)281. {282. II清除颜色(这里为黑色,为了方便找画的那个点)可以理解成背景颜色283. II和glColor4f(1.0f, O.Of, O.Of , 1.0f) 一样,所有参数都在0.0到1.0之间,后缀f是表示参数是浮点型的284. II最后的那个1.0f是透明度,0.0f表示全透明,1.0f 是完全不透明285. glClearColor(1.0f, 1.0f, 1.0f,1.0f);286. }287.287. II当绘制的窗口大小改变时重新绘制,使绘制的图形同比例变化,288. //几乎所有OpenGL程序中的这个函数都是一样的,所以,放心大胆的拷贝吧290. void Chan geSize(i nt w, i nt h)291. {292. wi nWidth = w;293. wi nH eight = h;294. //设置观察视野为窗口大小(用FLASH里面的话来说应该叫设置摄象机视野)295. glViewport(0,0,w,h);296. //重置坐标系统,指定设置投影参数297. glMatrixMode(GL_PROJECTION);298. /////// 调用单位矩阵,去掉以前的投影参数设置299. glLoadIde ntity();300. ////// 设置投影参数301. gluOrtho2D(-w/2,w/2,-h/2,h/2);302. }303.304. ///////////////// 鼠标点击305. void MousePlot(GLi nt butto n,GL int actio n,GL int xMouse,GLi nt yMouse){306. if(butto n==GLUT_LEFT_BUTTON &&-/324.307. px1 = xMouse - win Width/2; 308. py1 = winH eight/2 - yMouse;309. }310.if(butto n==GLUT_LEFT_BUTTONactio n==GLUT_UP){311. px2 = xMouse - win Width/2; 312. py2 = winH eight/2 - yMouse; 313. glutPostRedisplay();314. }315.if(butto n==GLUT_RIGHT_BUTTONactio n==GLUT_DOWN){316. cx=xMouse-wi nWidth/2; 317. cy=wi nH eight/2-yMouse; 318. }319. }320. //////////////// 鼠标移动321.void MouseMove(GLi nt xMouse,GL int yMouse){ 322. px2 = xMouse - win Width/2; 323. py2 = winH eight/2 - yMouse;actio n==GLUT_DOWN){ &&&&r=sqrt(pow((xMouse-wi nWidth/2-cx),2)+pow((wi nH eig-/ ht/2-yMouse-cy),2));325. glutPostRedisplay();326. }327.327. //主函数328. int main (i nt argc, char* argv[])329. {330. glutI ni t(&argc, argv);331. //设置显示模式332. glutI ni tDisplayMode(GLUT_DOUBLE | GLUT_RGB| GLUT_DEPTH);333. //设置窗口大小像素334. glutI nitWin dowSize(600, 600);335. ////设置窗口出现在屏幕的位置336. glutI nitWin dowPositio n(300,160);337. //建立一个叫OpenGL的窗口338. glutCreateWi ndow("Ope nGL-Li ne");340.339. //调用函数Display进行绘制340. glutDisplayF un c(Display);341. ////// 调用鼠标移动函数-/ 342. //glutPassiveMotio nFun c(PassiveMouseMove);-/ 357. } 345. glutMotio nFun c(MouseMove); 346. ... 调用鼠标点击函数 347. glutMouseFu nc(MousePlot); 348. 349.//如果窗口大小改变则调用函数 绘制 350. glutReshapeF un c(Cha ngeSize); 351. //清屏 352. SetupRC(); 353. //循环绘制 354. glutMai nLoop(); 355. 356.return 0; ChangeSize 重新进行。
opengl实现__太阳、地球和月亮的运动模型及小球的自由落体运动
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void initDisplay(void)
{ printf(" initDisplay()");
down=1;
//向下运动
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int count=1;
double timeSpan=0;
//下降到底所需时间
double movey=0.0;
double duration=0.0;
//持续时间
double length=0.0;
专业资料学习参考
WORD 整理版
clock_t start,end; void init(void) { printf(" init");
专业资料学习参考
glutTimerFunc(50,timer,0); glutPostRedisplay(); }
WORD 整理版
int main(int argc,char **argv) { glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("earth,moon,sun"); glutInitWindowSize(400,400); glutDisplayFunc(display); glutTimerFunc(50,timer,0); glutMainLoop(); return 0; }
z); 缩放矩阵函数 void glScale{df}(TYPE x,TYPE y,TYPE z); 如不需要效果积累可调用重置矩阵函数 void glLoadIdentity(void); 该函数将单位矩阵 置为当前变换矩阵。
使用OpenGL画球体
(计算机图形学)实验报告实验名称使用OpenGL画球体实验时间年月日专业班级学号姓名成绩教师评语:一、实验目的1、了解并学习open GL的编程;2、掌握在open GL生成图形的基本思想和基本步骤;3、使用open GL具体生成简单的三维立体图形;二、实验原理简单的说,该实验就是使用数学函数与OpenGL库中的函数实现图形的生成,比如生成球的函数为x=sin(thetar)*cos(phir);y=cos(thetar)*cos(phir);z=sin(phir);之后在对thetar的值进行定义,使其在某一范围内变化。
然后面的集合就生成了我们所需要的球体,但是该实验没有进行光照和材质的设定,所以看起来并不像一个立体的球体形状。
其间还需要对OpenGL的编程原理和其所包含的库比较了解。
OpenGL核心库:Windows: OpenGL32。
大多数Unix/Linux系统:GL库(libGL.a)OpenGL实用库(Utility Library, GLU):利用OpenGL核心库提供一些功能,从而避免重复编写代码,与窗口系统的连接OpenGL实用工具库(OpenGL Utility ToolkitLibrary, GLUT),提供所有窗口系统的共同功能,打开窗口,从鼠标和键盘获取输入,弹出菜单,事件驱动。
代码可以在平台间移植,但是GLUT缺乏在特定平台上优秀工具包所具有的功能滚动条。
函数的功能glVertex3f(x, y, z),属于GL库参数个数,x, y, z为float。
在glVertex3fv(p)中注意每部分的大小写,p为指向float的指针。
绝大多数常数采用#define在头文件gl.h, glu.h和glut.h中定义。
注意#include <glut.h>会自动包含其它两个头文件。
例如:glBegin(GL_POLYGON);glClear(GL_COLOR_BUFFER_BIT);在头文件中也定义了OpenGL数据类型:GLfloat, GLdouble, …关于最初建立文件的步骤创建一个win32 console application类型的workspace文件,创建一个C/C++文件,包含前面的代码,并把这个文件插入到workspace文件中进入菜单Project Settings…, 选择Link标签,在Object/library modules文本框中加上opengl32.lib, glu32.lib, glut32.lib, 注意用空格分开,然后编写程序。
计算机图形学报告
沈阳航空航天大学计算机图形学实验报告班级:34140102学号:20130 姓名:成绩:指导教师:实验一:OpenGL绘制球体线框图1.实验目的:本实验要求熟悉OpenGL基本图元函数的使用。
通过使用OpenGL及GLUT库在Visual C++环境下编写图形绘制程序掌握图形绘制的一般框架,从而为进一步做综合性的图形绘制实验奠定基础2.实验要求:编写一个程序,在窗口中显示一个旋转的球体线框,利用光标键可启动图形旋转切换视点。
3.实验过程:先配置环境,把相关文件放到相应的文件夹C:\Program Files\Microsoft Visual Studio\VC98\Include\GL C:\WINDOWS\system32 C:\Program Files\Microsoft Visual Studio\VC98\Lib建一个新工程,比照pdf敲代码再通过VC++进行编译4.实验结果:程序运行后,弹出窗口,使用光标键可使球体旋转。
代码:include <windows.h>#include <math.h>#include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>void init();void CALLBACK reshapae(GLsizei w,GLsizei h);void CALLBACK display();GLfloat s, h;//回调函数,绘制窗口时调用void CALLBACK display(){//清空窗口设置背景为白色glClearColor(1, 1, 1, 1);glClear(GL_COLOR_BUFFER_BIT);//取景变换glLoadIdentity();gluLookAt(5, 5, h, s, 0, 0, 0, 1, 0);//glRotatef(30,1,1,0);//设置前景色为黑色glColor3f(0,0,0);//绘图开始,两条水平平行线GLfloat RAD = 3.1415926/180;GLfloat x, y, z, r;int i, j;for(i = 0; i < 180; i+=5){glBegin(GL_LINE_LOOP);r = 2 * sin(i * RAD);z = 2 * cos(i * RAD);for(j = 0; j <= 360; j+=10){x = r * cos(j * RAD);y = r * sin(j * RAD);glVertex3f(x, y, z);}glEnd();}for(j = 0; j < 360; j+=10){glBegin(GL_LINE_LOOP);for(i = 0;i <=180; i+=5){r = 2 * sin(i * RAD);z = 2 * cos(i * RAD);x = r * cos(j * RAD);y = r * sin(j * RAD);glVertex3f(x, y, z);}glEnd();}//清空帧缓存glFlush();}//OpenGL初始化,设置颜色为单一着色模式void init(){glShadeModel(GL_FLAT);s = 0;h = 5;}//回调函数,窗口初始化和大小改变时,调用此函数void CALLBACK reshape(GLsizei w,GLsizei h){//设置当前矩阵为投影变换矩阵glMatrixMode(GL_PROJECTION);//设置投影变换glLoadIdentity();gluPerspective(30, 1, -3, 3);//设置当前矩阵为模式变换矩阵glMatrixMode(GL_MODELVIEW);//设置视区变换glViewport(0, 0, w, h);}void CALLBACK Left(){s+=0.1;}void CALLBACK Right(){s-=0.1;}void CALLBACK Up(){h-=0.1;}void CALLBACK Down(){h+=0.1;}void main(){//设置OpenGL的显示模式:单缓存、RGB模式auxInitDisplayMode(AUX_SINGLE|AUX_RGB);//设置窗口位置、大小和标题auxInitPosition(0, 0, 300, 300);auxInitWindow("OpenGL Demo");init();//设置回调函数auxKeyFunc(AUX_LEFT,Left);auxKeyFunc(AUX_RIGHT,Right);auxKeyFunc(AUX_UP,Up);auxKeyFunc(AUX_DOWN,Down);auxReshapeFunc(reshape);auxMainLoop(display);}5.实验心得:对vc下opengl的配置还是花费了很多时间,通过本次试验,熟悉了OpenGL基本图元函数的使用,通过使用OpenGL及GLUT库在Visual C++环境下编写图形绘制程序掌握图形绘制的一般框架,从而为进一步做综合性的图形绘制实验奠定基础。
openGL画直线、圆、椭圆
drawEllipse(250,250,60,40);
/* and flush that buffer to the screen */
glFlush();
}
int main(int argc, char** argv)
{
/* Standard GLUT initialization */
}
}
void dda_line(int xa,int ya,int xb,int yb)//画直线
{
GLfloat delta_x,delta_y,x,y;
int dx,dy,steps;
dx=xb-xa;
dy=yb-ya;
if(abs(dx)>abs(dy))
steps=abs(dx);
else
steps=abs(dy);
cout<<"************************************************"<<endl;
cout<<"****请选择如下操作: *****"<<endl;
cout<<"**** 1.用DDA画线*****"<<endl;
cout<<"**** 2.用Bresenham算法画圆*****"<<endl;
使用openGl画直线(DDA算法)、画圆、椭圆(Bresenham算法)
#include<stdlib.h>
#include<iostream.h>
opengl鼠标绘制直线及圆图元算法
图框在屏幕的位置 图框大小 图片文件名称
背景颜色的调试
可变数值画椭圆
运行结果
The end
Thanks
注释:可以将#include <iostream> 替换成 #include <iostream.h>
typedef vector<int> list; vector<list> ls, cs; int old_x, old_y, new_x, new_y, cx, cy, cr; int mouse_type; /* breseman画线算法 */ void line(int x1, int y1, int x2, int y2) { glBegin(GL_POINTS); if (x1==x2 && y1==y2) { glVertex2i(x1, y1); return; } if (x1>x2) { swap(x1, x2); swap(y1, y2); } glVertex2d(x1, y1); int dy=abs(y2-y1); int dx=abs(x2-x1); if (dx>=dy) { ……
定义:直线的终点 起点,圆的圆心和 半径。
利用 breseman 算法,进行 画直线的子 文件编辑。
/* 中点圆算法 */ void circle(int cx, int cy, int r) { int x=0, y=r; float p=1.25-r; while (x<=y) { glBegin(GL_POINTS); glVertex2i(cx+x, cy+y); glVertex2i(cx-x, cy+y); glVertex2i(cx-x, cy-y); glVertex2i(cx+x, cy-y); glVertex2i(cx+y, cy+x); glVertex2i(cx-y, cy+x); glVertex2i(cx-y, cy-x); glVertex2i(cx+y, cy-x); glEnd(); if (p<0) { ++x; p+=2*x+1; }else { p+=2*x-2*y+5; ++x; --y; } } ……
c++画圆算法
c++画圆算法在C++中,可以使用数学库中的函数来绘制圆。
以下是一个简单的例子,它使用OpenGL库来绘制一个圆。
cpp复制代码:#include <GL/glut.h>#include <cmath>void drawCircle(float radius, int slices) {float angle;float angleIncrement = 360.0f / slices;glBegin(GL_POLYGON);for(int i = 0; i <= slices; ++i) {angle = angleIncrement * i;glVertex2f(radius * cos(angle), radius * sin(angle));}glEnd();}void display() {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0); // 设置颜色为白色drawCircle(1.0, 100); // 绘制半径为1,分成100份的圆glFlush(); // 强制立即执行所有OpenGL命令}int main(int argc, char **argv) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(500, 500);glutCreateWindow("Draw Circle");glClearColor(0.0, 0.0, 0.0, 1.0); // 设置背景颜色为黑色glColor3f(1.0, 1.0, 1.0); // 设置笔的颜色为白色glutDisplayFunc(display);glutMainLoop();return 0;}这个程序首先定义了一个函数drawCircle,它接受两个参数:圆的半径和圆的切片数。
Android OpenGL ES绘制一个球体
有了 Sphere 类, 创建一个 DrawSphere Activity 来绘制球体,为了能看出 3D 效果,给 场景中添加光源(后面介绍)
[java] view plaincopyprint?
1. public void DrawScene(GL10 gl) { 2. super.DrawScene(gl); 3. initScene(gl); 4. sphere.draw(gl); 5. }
21. r1 = (float)Math.cos(pai * Math.PI / 180.0); 22. r2 = (float)Math.cos((pai + step) * Math.PI / 180.0); 23. h1 = (float)Math.sin(pai * Math.PI / 180.0); 24. h2 = (float)Math.sin((pai + step) * Math.PI / 180.0); 25. 26. for (theta = 0.0f; theta <= 360.0f; theta += step) { 27. co = (float)Math.cos(theta * Math.PI / 180.0); 28. si = -(float)Math.sin(theta * Math.PI / 180.0); 29. 30. v[n][0] = (r2 * co); 31. v[n][1] = (h2); 32. v[n][2] = (r2 * si); 33. v[n + 1][0] = (r1 * co); 34. v[n + 1][1] = (h1); 35. v[n + 1][2] = (r1 * si); 36. 37. vBuf.put(v[n]); 38. vBuf.put(v[n + 1]); 39. 40. n += 2; 41. 42. if(n>31){ 43. vBuf.position(0); 44. 45. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf); 46. gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); 47. gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); 48. 49. n = 0; 50. theta -= step; 51. } 52. 53. } 54. vBuf.position(0); 55. 56. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf); 57. gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); 58. gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); 59. } 60. 61. gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 62. gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); 63. }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(计算机图形学)实验报告
实验名称使用OpenGL画球体
实验时间年月日
专业班级学号姓名
成绩教师评语:
一、实验目的
1、了解并学习open GL的编程;
2、掌握在open GL生成图形的基本思想和基本步骤;
3、使用open GL具体生成简单的三维立体图形;
二、实验原理
简单的说,该实验就是使用数学函数与OpenGL库中的函数实现图形的生成,比如生成球的函数为x=sin(thetar)*cos(phir);
y=cos(thetar)*cos(phir);
z=sin(phir);
之后在对thetar的值进行定义,使其在某一范围内变化。
然后面的集合就生成了我们所需要的球体,但是该实验没有进行光照和材质的设定,所以看起来并不像一个立体的球体形状。
其间还需要对OpenGL的编程原理和其所包含的库比较了解。
OpenGL核心库:Windows: OpenGL32。
大多数Unix/Linux系统:GL库(libGL.a)
OpenGL实用库(Utility Library, GLU):利用OpenGL核心库提供一些功能,从而避免重复编写代码,与窗口系统的连接
OpenGL实用工具库(OpenGL Utility ToolkitLibrary, GLUT),提供所有窗口系统的共同功能,打开窗口,从鼠标和键盘获取输入,弹出菜单,事件驱动。
代码可以在平台间移植,但是GLUT缺乏在特定平台上优秀工具包所具有的功能滚动条。
函数的功能glVertex3f(x, y, z),属于GL库参数个数,x, y, z为float。
在glVertex3fv(p)中注意每部分的大小写,p为指向float的指针。
绝大多数常数采用#define在头文件gl.h, glu.h和glut.h中定义。
注意#include <glut.h>会自动包含其它两个头文件。
例如:glBegin(GL_POLYGON);glClear(GL_COLOR_BUFFER_BIT);在头文件中也定义了OpenGL数据类型:GLfloat, GLdouble, …
关于最初建立文件的步骤
创建一个win32 console application类型的workspace文件,创建一个C/C++
文件,包含前面的代码,并把这个文件插入到workspace文件中进入菜单Project Settings…, 选择Link标签,在Object/library modules文本框中加上opengl32.lib, glu32.lib, glut32.lib, 注意用空格分开,然后编写程序。
三、实验内容
基于OpenGL工作环境绘制一个三维球体。
四、实验步骤
1.点击文件——新建,弹出窗口,选择win32 console application,创建工作站。
2.在想要创建的控制台程序中,选择“一个“Hello,world!”程序”
3.点击完成,完成工作站的创建。
4.在FileView中找到Source File目录下的球.cpp,双击打开。
5.将老师给的程序复制到此cpp文件中。
6.把glut-3.
7.6-bin文件夹下面的glut32.dll文件放到C:\WINDOWS\system32或者是C:\WINDOWS\system路径下,将glut.h文件放到C:\Program Files\Mirosoft Visul studio\VC98\include\GL目录下,将glut32.lib文件放到C:\Program Files\Mirosoft Visul studio\lib目录下。
以上是实验室中的目录途径。
在我自己的电脑上,因为VC++被我安装在F盘,所以将glut.h文件和glut32.lib所放的路径有所改变。
总之,这两个文件是放在VC++的安装目录下的Mirosoft Visul studio\VC98\include\GL目录和Mirosoft Visul studio\lib目录中。
7.在C++页面中,进入工程——属性,出现以下弹框:
8.在连接——对象/库模块的最后输入:glut32.dll,glut32.lib。
9.完成上述步骤之后,编译连接实验程序的代码,看是否有错误。
如有错误,改正;如没有错误,就运行看看。
10.
上图为最后结果运行出来的球,看不出是不是立体的。
四、程序代码:
主代码:
// 画球体.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
#include "stdio.h"
#include "math.h"
#include "gl\glut.h"
void display()
{
double phi,phir,phi20,phir20;
double c,c80,z,x,y,theta,thetar;
double M_PI=3.1415926;
c=M_PI/180.0;//角度转换为弧度,M_PI=3.14159...
for(phi=-180.0;phi<=80.0;phi+=20.0)
{
phir=c*phi;
phi20=c*(phi+20);
glBegin(GL_QUAD_STRIP);
for(theta=-180.0;theta<=180.0;theta+=20.0)
{
thetar=c*theta;
x=sin(thetar)*cos(phir);
y=cos(thetar)*cos(phir);
z=sin(phir);
glVertex3d(x,y,z);
x=sin(thetar)*cos(phir20);
y=cos(thetar)*cos(phir20);
z=sin(phir20);
glVertex3d(x,y,z);
}
glEnd();
}
glBegin(GL_TRIANGLE_FAN);
glVertex3d(0.0,0.0,1.0);
c=M_PI/180.0;
c80=c*80.0;
z=sin(c80);
for(theta=-180.0;theta<=180.0;theta+=20.0)
{
thetar=c*thetar;
x=sin(thetar)*cos(c80);
y=sin(thetar)*cos(c80);
glVertex3d(x,y,z);
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3d(0.0,0.0,-1.0);
z=-sin(c80);
for(theta=-180.0;theta<=180.0;theta+=20.0)
{
thetar=c*thetar;
x=sin(thetar)*cos(c80);
y=sin(thetar)*cos(c80);
glVertex3d(x,y,z);
}
glEnd(); glFlush();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0); // Set the clear color to black
// Specify the boundaries of the viewing window
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // The para are: (left, right, bottom, top)
glMatrixMode(GL_MODELVIEW);
}
int main( int argc, char **argv)
{
glutInit( &argc, argv);
glutInitWindowPosition( 200, 100);
glutCreateWindow("Green Triangle");
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
五、实验结果分析与总结
经过这次实验,使我进一步加深了对OpenGL的使用。
在之前的OpenGL学习中,我知道了应该如何有效的使用OpenGL的库函数。
本次实验的过程中,需要对如下的一些变量进行定义:“double phi,phir,phi20,phir20; double c,c80,z,x,y,theta,thetar; double M_PI=3.1415926;”只有定义了这些,实验中所用到的字符才能够被使用。
同时,在定义头文件的过程中,我们也增加了“#include "stdio.h"”和“#include "math.h"”两个。
只有这样,才能够保证试验程序中的数值计算公式被引用,才能够正常完成程序。
同时OpenGl 的库文件、注册表和需要放在win32之下的文件也必须按要求存放。
经过本次的实验,使我更加了解了OpenGl的工作原理。
虽然这只是一个很简单的实验,但是它让我明白了在使用OpenGL绘制图形时的一般方法和格式。