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);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/lotuses/p/11360272.html