11、事例十一:光源创建综合例子;光源参数、视角可调节测试场景;(坐标不知道可采用此测试例子里的功能,利用键盘进行调节)
namespace sharpGLTest11 { public partial class Form1 : Form { private float rotation = 0.0f; private bool isRotate = false; private bool isLines = false; private bool isFrontView = false; private bool isLeftView = false; private bool isTopView = false; private bool isPerspective = true; private float[] lightPos = new float[] { -1, -3, 1, 1 }; private float[] lightSphereColor = new float[] { 1f, 1f, 1f }; private IList<float[]> lightColor = new List<float[]>(); //光源 private double[] lookatValue = { 1, 1, 2, 0, 0, 0, 0, 1, 0 }; private IList<double[]> viewDefaultPos = new List<double[]>(); //视图 public Form1() { InitializeComponent(); } /* * 初始化 * * */ private void openGLControl_OpenGLInitialized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; //四个视图的缺省位置 viewDefaultPos.Add(new double[] { 1, 1, 2, 0, 0, 0, 0, 1, 0 }); //透视 viewDefaultPos.Add(new double[] { 0, 0, 2, 0, 0, 0, 0, 1, 0 }); //前视 viewDefaultPos.Add(new double[] { 5, 0, 0, 0, 0, 0, 0, 1, 0 }); //左视 viewDefaultPos.Add(new double[] { 0, 13, 0, -1, 0, 0, 0, 1, 0 }); //顶视 lookatValue = (double[])viewDefaultPos[0].Clone(); //灯 lightColor.Add(new float[] { 1f, 1f, 1f, 1f }); //环境光(ambient light) lightColor.Add(new float[] { 1f, 1f, 1f, 1f }); //漫射光(diffuse light) lightColor.Add(new float[] { 1f, 1f, 1f, 1f }); //镜面反射光(specular light) setLightColor(gl); gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos); //设定灯光的位置 gl.Enable(OpenGL.GL_LIGHTING); //这两行是让灯光开,有效 gl.Enable(OpenGL.GL_LIGHT0); // //光 gl.ClearColor(0, 0, 0, 0); } //灯光 private void setLightColor(OpenGL gl) { gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, lightColor[0]); //环境光 gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, lightColor[1]); //漫射光 gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, lightColor[2]); //镜面反射 } /* * 画图 * * */ private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); gl.LoadIdentity(); gl.Rotate(rotation, 0.0f, 1.0f, 0.0f); drawGrid(gl); //网格线 DrawCube(ref gl, 1.5f, -1f, -2f, isLines); drawOneSphere(ref gl, -3, -2, -4, isLines); //球体 if (isRotate) rotation += 3.0f; } void drawGrid(OpenGL gl) { //绘制过程 gl.PushAttrib(OpenGL.GL_CURRENT_BIT); //保存当前属性 gl.PushMatrix(); //压入堆栈 gl.Translate(0f, -2f, 0f); gl.Color(0f, 0f, 1f); //在X,Z平面上绘制网格 for (float i = -50; i <= 50; i += 1) { //绘制线 gl.Begin(OpenGL.GL_LINES); { if (i == 0) gl.Color(0f, 1f, 0f); else gl.Color(0f, 0f, 1f); //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(); } internal void DrawCube(ref OpenGL Gl, float xPos, float yPos, float zPos, bool isLine) { Gl.PushMatrix(); Gl.Translate(xPos, yPos, zPos); if (isLine) Gl.Begin(OpenGL.GL_LINE_STRIP); else Gl.Begin(OpenGL.GL_POLYGON); /** 顶面 */ Gl.Vertex(0.0f, 0.0f, 0.0f); Gl.Vertex(0.0f, 0.0f, -1.0f); Gl.Vertex(-1.0f, 0.0f, -1.0f); Gl.Vertex(-1.0f, 0.0f, 0.0f); /** 前面 */ Gl.Vertex(0.0f, 0.0f, 0.0f); Gl.Vertex(-1.0f, 0.0f, 0.0f); Gl.Vertex(-1.0f, -1.0f, 0.0f); Gl.Vertex(0.0f, -1.0f, 0.0f); /** 右面 */ Gl.Vertex(0.0f, 0.0f, 0.0f); Gl.Vertex(0.0f, -1.0f, 0.0f); Gl.Vertex(0.0f, -1.0f, -1.0f); Gl.Vertex(0.0f, 0.0f, -1.0f); /** 左面*/ Gl.Vertex(-1.0f, 0.0f, 0.0f); Gl.Vertex(-1.0f, 0.0f, -1.0f); Gl.Vertex(-1.0f, -1.0f, -1.0f); Gl.Vertex(-1.0f, -1.0f, 0.0f); /** 底面 */ Gl.Vertex(0.0f, 0.0f, 0.0f); Gl.Vertex(0.0f, -1.0f, -1.0f); Gl.Vertex(-1.0f, -1.0f, -1.0f); Gl.Vertex(-1.0f, -1.0f, 0.0f); /** 后面 */ Gl.Vertex(0.0f, 0.0f, 0.0f); Gl.Vertex(-1.0f, 0.0f, -1.0f); Gl.Vertex(-1.0f, -1.0f, -1.0f); Gl.Vertex(0.0f, -1.0f, -1.0f); Gl.End(); Gl.PopMatrix(); } private void drawOneSphere(ref OpenGL gl, float xPos, float yPos, float zPos, bool isLine) { gl.PushMatrix(); { gl.Translate(xPos, yPos, zPos); gl.Color(lightSphereColor); drawSphere(gl, 1, 20, 10, isLine); } gl.PopMatrix(); } void drawSphere(OpenGL gl, double radius, int segx, int segy, bool isLines) { gl.PushMatrix(); gl.Translate(2f, 1f, 2f); var sphere = gl.NewQuadric(); if (isLines) gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES); else gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS); gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH); gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE); gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE); gl.Sphere(sphere, radius, segx, segy); gl.DeleteQuadric(sphere); gl.PopMatrix(); } /* * 调整视角 * * */ private void openGLControl_Resized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.MatrixMode(OpenGL.GL_PROJECTION); gl.LoadIdentity(); gl.Perspective(40.0f, (double)Width / (double)Height, 0.01, 100.0); gl.LookAt(lookatValue[0], lookatValue[1], lookatValue[2], lookatValue[3], lookatValue[4], lookatValue[5], lookatValue[6], lookatValue[7], lookatValue[8]); gl.MatrixMode(OpenGL.GL_MODELVIEW); updateLabInfo(); } /* * 将灯光位置、LookAt视角坐标显示 * */ private void updateLabInfo() { tbLightPos.Text = string.Format("{0},{1},{2},{3}", lightPos[0], lightPos[1], lightPos[2], lightPos[3]); tbLookAt.Text = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}", lookatValue[0], lookatValue[1], lookatValue[2], lookatValue[3], lookatValue[4], lookatValue[5], lookatValue[6], lookatValue[7], lookatValue[8]); } /* * 视口切换 * */ private void rbPerspective_CheckedChanged(object sender, EventArgs e) { switch (((RadioButton)sender).Name) { case "rbPerspective": isPerspective = !isPerspective; isFrontView = false; isTopView = false; isLeftView = false; break; case "rbLeft": isLeftView = !isLeftView; isFrontView = false; isPerspective = false; isTopView = false; break; case "rbFront": isFrontView = !isFrontView; isTopView = false; isPerspective = false; isLeftView = false; break; case "rbTop": isTopView = !isTopView; isPerspective = false; isLeftView = false; isFrontView = false; break; default: return; } setViewDefaultValue(); openGLControl_Resized(null, null); } private void setViewDefaultValue() { if (isPerspective) { lookatValue = (double[])viewDefaultPos[0].Clone(); } else if (isFrontView) { lookatValue = (double[])viewDefaultPos[1].Clone(); } else if (isLeftView) { lookatValue = (double[])viewDefaultPos[2].Clone(); } else if (isTopView) { lookatValue = (double[])viewDefaultPos[3].Clone(); } } /* * 光源的颜色 * */ private void rbWhite_CheckedChanged(object sender, EventArgs e) { var rad = ((RadioButton)sender); var lightType = this.cbxLightType.SelectedIndex; if (rad.Checked) { switch (rad.Name) { case "rbWhite": lightColor[lightType][0] = 1f; lightColor[lightType][1] = 1f; lightColor[lightType][2] = 1f; lightColor[lightType][3] = 1f; break; case "rbRed": lightColor[lightType][0] = 1f; lightColor[lightType][1] = 0f; lightColor[lightType][2] = 0f; lightColor[lightType][3] = 1f; break; case "rbGreen": lightColor[lightType][0] = 0f; lightColor[lightType][1] = 1f; lightColor[lightType][2] = 0f; lightColor[lightType][3] = 1f; break; case "rbBlue": lightColor[lightType][0] = 0f; lightColor[lightType][1] = 0f; lightColor[lightType][2] = 1f; lightColor[lightType][3] = 1f; break; } setLightColor(openGLControl.OpenGL); } } //下拉框 private void cbxLightType_SelectedIndexChanged(object sender, EventArgs e) { var lightType = this.cbxLightType.SelectedIndex; if (lightType >= 0) judgeColor(lightColor[lightType]); } private void judgeColor(float[] color) { if (color[0] == 1f && color[1] == 1f && color[2] == 1f && color[3] == 1f) rbWhite.Checked = true; else if (color[0] == 1f && color[1] == 0f && color[2] == 0f && color[3] == 1f) rbRed.Checked = true; else if (color[0] == 0f && color[1] == 1f && color[2] == 0f && color[3] == 1f) rbGreen.Checked = true; else if (color[0] == 0f && color[1] == 0f && color[2] == 1f && color[3] == 1f) rbBlue.Checked = true; } //Form1事件,将下拉框选项改为默认选第一个 private void SharpGLForm_Load(object sender, EventArgs e) { this.cbxLightType.SelectedIndex = 0; updateLabInfo(); } /* * 视图旋转、线框显示、灯光关闭 * */ private void cbxRotate_CheckedChanged(object sender, EventArgs e) { var cbx = ((CheckBox)sender); switch (cbx.Name) { case "cbxRotate": isRotate = cbx.Checked; break; case "cbxLines": isLines = cbx.Checked; break; case "cbxLightOff": if (!cbx.Checked) this.openGLControl.OpenGL.Enable(OpenGL.GL_LIGHT0); else this.openGLControl.OpenGL.Disable(OpenGL.GL_LIGHT0); break; } } /* * 修改灯光位置、LookAt视角的确定按钮 * */ private void btnSetPos_Click(object sender, EventArgs e) { if (radioButton1.Checked) { double[] ary = tbLookAt.Text.Split(',').Select(s => Convert.ToDouble(s)).ToArray(); lookatValue = ary; openGLControl_Resized(null, null); } else { float[] ary = tbLightPos.Text.Split(',').Select(s => Convert.ToSingle(s)).ToArray(); lightPos = ary; openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, ary); } } /* * 缺省位置 * */ private void btnDefaultPOS_Click(object sender, EventArgs e) { if (radioButton1.Checked) { setViewDefaultValue(); } else { lightPos = new float[] { -1, -3, 1, 1 }; openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos); } openGLControl_Resized(null, null); } /* * 单点位置变换——视图、光源 * */ private void btnQ_Click(object sender, EventArgs e) { moveObject(radioButton1.Checked ? 0 : 1, ((Button)sender).Name); openGLControl_Resized(null, null); openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos); } private void moveObject(int obj, string keyName) { //obj==0移动视图 switch (keyName) { case "btnQ": if (obj == 0) ++lookatValue[1]; //y else ++lightPos[1]; break; case "btnE": if (obj == 0) --lookatValue[1]; else --lightPos[1]; break; case "btnW": if (obj == 0) --lookatValue[2]; //z else --lightPos[2]; break; case "btnS": if (obj == 0) ++lookatValue[2]; else ++lightPos[2]; break; case "btnA": if (obj == 0) --lookatValue[0]; //X else --lightPos[0]; break; case "btnD": if (obj == 0) ++lookatValue[0]; else ++lightPos[0]; break; } } /* * 添加键盘事件 * * */ private void openGLControl_KeyDown(object sender, KeyEventArgs e) { Console.WriteLine("点击键盘!"); string name = string.Empty; switch (e.KeyCode) { case Keys.W: name = "btnW"; break; case Keys.A: name = "btnA"; break; case Keys.S: name = "btnS"; break; case Keys.D: name = "btnD"; break; case Keys.Q: name = "btnQ"; break; case Keys.E: name = "btnE"; break; } moveObject(radioButton1.Checked ? 0 : 1, name); openGLControl_Resized(null, null); } } }
我驰骋天下,守你盛世繁华