6、事例六:裁剪变换(ClipPlane)
namespace sharpGLTest06 { public partial class SharpGLForm : Form { public SharpGLForm() { InitializeComponent(); } private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); gl.LoadIdentity(); double[] eqn = new double[4] { 1f, 0f, 1f, 0f }; //白色 gl.Color(1.0, 1.0, 1.0); //建立模型堆栈,将当前位置保存起来(入栈) /* 详解 * 当你做一些移动或旋转等变换后,使用glPushMatrix(),OpenGL会把这个变换后的位置和角度保存起来; * 然后你再随便坐第二次移动或旋转变换,再用glPopMatrix(),OpenGL就会把刚刚保存的那个位置和角度恢复; * 消除上一次变换对本次变换的影响 * */ gl.PushMatrix(); { gl.Translate(2, -2, -3); gl.Rotate(-90.0, 1.0, 0.0, 0.0); drawSphere(gl); } // 将保存的位置放出(出栈) gl.PopMatrix(); gl.PushMatrix(); { // 定义一个裁剪平面 /* * ClipPlane(OpenGL.GL_CLIP_PLANE0, double[] equation); * equation 是一个拥有4个系数的数组,它定义一个裁剪平面。equation参数指向平面方程 Ax+By+Cz+D=0 的4个系数 * equation=(0,-1,0,0),前三个参数(0,-1,0)可以理解为法线向下,只有向下的,即Y<0的才能显示,最后一个参数0表示从 * z=0平面开始。这样就是裁剪掉上半平面。 * 相应的 * equation=(0,1,0,0)表示裁剪掉下半平面 * equation=(1,0,0,0)表示裁剪掉左半平面 * equation=(-1,0,0,0)表示裁剪掉右半平面 * equation=(0,0,-1,0)表示裁剪掉前半平面 * equation=(0,0,1,0)表示裁剪掉后半平面 * */ gl.ClipPlane(OpenGL.GL_CLIP_PLANE0, eqn); gl.Enable(OpenGL.GL_CLIP_PLANE0); drawGrid(gl); } gl.PopMatrix(); gl.Flush(); } //曲面绘制 void drawSphere(OpenGL gl) { //画二次曲面球体绘制过程 gl.PushMatrix(); gl.Translate(2f, 1f, 2f); //绘制二次曲面 var sphere = gl.NewQuadric(); //设置二次却面绘制风格。gluQuadricDrawStyle。一般都是选用GLU_FILL风格,采用多边形来模拟 gl.QuadricDrawStyle(sphere, OpenGL.GLU_LINE); //设置法线风格。gluQuadricNormals。一般都是使用GLU_SMOOTH风格,对每个顶点都计算法线向量,是默认方式 gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH); //设置二次曲面的绘制方向。gluQuadricOrientation。一般使用GLU_OUTSIDE, 按照所有的法线都指向外面的方式绘制。是默认方式 gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE); //设置纹理。gluQuadricTexture。设置是否自动计算纹理。默认是GLU_FALSE。当需要使用纹理时应修改为GLU_TRUE. gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE); gl.Sphere(sphere, 3f, 20, 10); gl.DeleteQuadric(sphere); gl.PopMatrix(); } void drawGrid(OpenGL gl) { //绘制栅格线过程 gl.PushAttrib(OpenGL.GL_CURRENT_BIT); //保存当前属性 gl.PushMatrix(); //压入堆栈 gl.Translate(0f, 0f, 0f); gl.Color(0f, 0f, 1f); //在X,Z平面上绘制网格 for (float i = -50; i <= 50; i += 1) { //绘制线 gl.Begin(OpenGL.GL_LINES); //X轴方向 gl.Vertex(-50f, 0f, i); gl.Vertex(50f, 0f, i); //Z轴方向 gl.Vertex(i, 0f, -50f); gl.Vertex(i, 0f, 50f); gl.End(); } gl.PopMatrix(); gl.PopAttrib(); } private void openGLControl_OpenGLInitialized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.ClearColor(0, 0, 0, 0); } private void openGLControl_Resized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.MatrixMode(OpenGL.GL_PROJECTION); gl.LoadIdentity(); gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0); gl.LookAt(0, 5, 10, 0, 0, 0, 0, 1, 0); gl.MatrixMode(OpenGL.GL_MODELVIEW); } } }
我驰骋天下,守你盛世繁华