zoukankan      html  css  js  c++  java
  • 13、事例十三:光源例子:环绕二次曲面球体的光源(二)

    namespace sharpGLTest13
    {
        public partial class Form1 : Form
        {
            private float rotation = 0.0f;
            float m_bReadX, m_bReadY;
            float m_bGreenX, m_bGreenY;
            float m_bBlueX, m_bBlueY;
    
            //3个光源位置
            float[] lightPosR = new float[] { 0f, 0f, 2f, 1f };
            float[] lightPosG = new float[] { 0f, 0f, 2f, 1f };
            float[] lightPosB = new float[] { 0f, 0f, 2f, 1f };
    
            //3个光源漫射光
            float[] diffLightR = { 1f, 0f, 0f, 1f };
            float[] diffLightG = { 0f, 1f, 0f, 1f };
            float[] diffLightB = { 0f, 0f, 1f, 1f };
    
            //定义3个光源我镜面光
            float[] specLightR = { 1f, 0f, 0f, 1f };
            float[] specLightG = { 0f, 1f, 0f, 1f };
            float[] specLightB = { 0f, 0f, 1f, 1f };
    
            //默认的光源, 灰色光源,用于默认照明
            float[] defDiffLight = new float[] { 0.8f, 0.8f, 0.8f, 1f };
            float[] defSpecLight = new float[] { 1f, 1f, 1f, 1f };
            float[] defLightPos = new float[] { 0f, 0f, 10f, 1f };
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
            {
                OpenGL gl = openGLControl.OpenGL;
                setLight(gl);
                //gl.Enable(OpenGL.GL_NORMALIZE);
                gl.ClearColor(0, 0, 0, 0);
            }
            private void setLight(OpenGL gl)
            {
                //0号灯光,默认灯光
                gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, defDiffLight);
                gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, defSpecLight);
                gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, defLightPos);
    
                //1号灯光
                gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, diffLightR);
                gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_SPECULAR, specLightR);
                gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, lightPosR);
    
                //2号灯光
                gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_DIFFUSE, diffLightG);
                gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_SPECULAR, specLightG);
                gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_POSITION, lightPosG);
    
                //3号灯光
                gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_DIFFUSE, diffLightB);
                gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_SPECULAR, specLightB);
                gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_POSITION, lightPosB);
    
                gl.Enable(OpenGL.GL_LIGHTING);
                gl.Enable(OpenGL.GL_LIGHT0);  //启用默认光源
    
            }
    
            private void openGLControl_Resized(object sender, EventArgs e)
            {
                OpenGL gl = openGLControl.OpenGL;
                gl.MatrixMode(OpenGL.GL_PROJECTION);
                gl.LoadIdentity();
                gl.Perspective(70.0f, (double)Width / (double)Height, 0.01, 100.0);
                gl.LookAt(-5, 5, -5, 0, 0, 0, 0, 1, 0);
                gl.MatrixMode(OpenGL.GL_MODELVIEW);
            }
    
            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);
    
                draw(gl);
                rotation += 3.0f;
    
                update(gl);
            }
    
            void update(OpenGL gl)
            {
                gl.Enable(OpenGL.GL_LIGHT1);
                m_bReadX += 16;
                m_bReadY += 12;
                gl.Enable(OpenGL.GL_LIGHT2);
                m_bGreenX += 10;
                m_bGreenY += 6;
                gl.Enable(OpenGL.GL_LIGHT3);
                m_bBlueX += 2;
                m_bBlueY += 4;
            }
    
            void draw(OpenGL gl)
            {
                gl.PushMatrix();
                //旋转红光
                gl.Rotate(m_bReadX, 1f, 0f, 0f);
                gl.Rotate(m_bReadY, 0f, 1f, 0f);
                //设置红光的位置
                gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, lightPosR);
                //绘制光球
                gl.Translate(lightPosR[0], lightPosR[1], lightPosR[2]);
                gl.Color(1f, 0f, 0f);
                gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
                gl.Disable(OpenGL.GL_LIGHTING);
                drawSphere(gl, lightPosR[0], lightPosR[1], lightPosR[2], 0.2f, 10, 10, false);
                gl.Enable(OpenGL.GL_LIGHTING);
                gl.PopAttrib();
                gl.PopMatrix();
    
    
                gl.PushMatrix();
                //旋转绿光
                gl.Rotate(m_bGreenX, 1f, 0f, 0f);
                gl.Rotate(m_bGreenY, 0f, 1f, 0f);
                //设置绿光的位置
                gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_POSITION, lightPosG);
                //绘制光球
                gl.Translate(lightPosG[0], lightPosG[1], lightPosG[2]);
                gl.Color(0f, 1f, 0f);
                gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
                gl.Disable(OpenGL.GL_LIGHTING);
                drawSphere(gl, lightPosG[0], lightPosG[1], lightPosG[2], 0.2f, 10, 10, false);
                gl.Enable(OpenGL.GL_LIGHTING);
                gl.PopAttrib();
                gl.PopMatrix();
    
    
                gl.PushMatrix();
                //旋转蓝光
                gl.Rotate(m_bBlueX, 1f, 0f, 0f);
                gl.Rotate(m_bBlueY, 0f, 1f, 0f);
                //设置蓝光的位置
                gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_POSITION, lightPosB);
                //绘制光球
                gl.Translate(lightPosB[0], lightPosB[1], lightPosB[2]);
                gl.Color(0f, 0f, 1f);
                gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
                gl.Disable(OpenGL.GL_LIGHTING);
                drawSphere(gl, lightPosB[0], lightPosB[1], lightPosB[2], 0.2f, 10, 10, false);
                gl.Enable(OpenGL.GL_LIGHTING);
                gl.PopAttrib();
                gl.PopMatrix();
    
    
                //绘制球体
                gl.PushMatrix();
                gl.Rotate(rotation, 1f, 0f, 0f);
                gl.Rotate(rotation, 0f, 1f, 0f);
                gl.Rotate(rotation, 0f, 0f, 1f);
                drawSphere(gl, 0, 0, 0, 3, 40, 40, false);
    
                gl.PopMatrix();
    
                gl.Flush();
    
            }
            //二次曲面球体
            void drawSphere(OpenGL gl, float x, float y, float z, double radius, int segx, int segy, bool isLines)
            {
                gl.PushMatrix();
                gl.Translate(x, y, z);
                var sphere = gl.NewQuadric();
    
                /*
                 * QuadricDrawStyle(IntPtr quadObject, uint drawStyle);
                 * 第一个参数是二次方程对象状态的指针
                 * 第二个参数的枚举值:GLU_FILL(二次方程对象画成实体)、GLU_LINE(二次方程对象画成线框)
                 *      GLU_POINT(二次方程对象画成一组顶点的集合)、GLU_SILHOUETTE(类似于线框,但相邻的多边形的边不被绘制)
                 * */
                if (isLines)
                    gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);
                else
                    gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);
    
                /*
                 * QuadricNormals(IntPtr quadricObject, uint normals);
                 * 这个函数指定二次方程对象如何生成法线。
                 * 第二个参数可以是:GLU_NONE不生成法线,GLU_FLAT扁平法线,GLU_SMOOTH平滑法线。
                 * 
                 * */
                gl.QuadricNormals(sphere, OpenGL.GLU_NONE);   //GLU_NONE,GLU_FLAT,GLU_SMOOTH
    
                /*
                 * QuadricOrientation(IntPtr quadricObject, int orientation);
                 * 这个函数可以指定法线的朝向,指向外面还是只想里面。
                 * orientation可以是GLU_OUTSIDE或者是GLU_INSIDE这两个值。
                 * OpenGL默认是以GL_CCW逆时针为正方向的
                 * 
                 * */
                gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE);  //GLU_OUTSIDE,GLU_INSIDE
    
                /*
                 * QuadricTexture(IntPtr quadricObject, int textureCoords)
                 * 这个函数可以指定二次方程表面的纹理坐标
                 * textureCoords这个参数可以是GL_TRUE或者GL_FALSE.
                 * 当为球体和圆柱体生成纹理坐标时,纹理是对称地环绕在球体和圆柱体的表面的
                 * 如果应用到圆盘上,那么纹理的中心就是圆盘的中心,然后以线性插值的方式扩展到圆盘的边界
                 * 
                 * */
                gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE);  //GL_TRUE,GLU_FALSE
                gl.Sphere(sphere, radius, segx, segy);
                gl.DeleteQuadric(sphere);
                gl.PopMatrix();
            }
    
            /*
             * 以点画圆
             * 
             * */
            //球心坐标为(x,y,z),球的半径为radius,M,N分别表示球体的横纵向被分成多少份
            void drawSphere1(OpenGL gl, float xx, float yy, float zz, float radius, float M, float N, bool isLines)
            {
                const float PI = 3.1415926f;
                float step_z = (float)Math.PI / M;
                float step_xy = 2 * PI / N;
                float[] x = new float[4] { 0, 0, 0, 0 };
                float[] y = new float[4] { 0, 0, 0, 0 };
                float[] z = new float[4] { 0, 0, 0, 0 };
    
                float angle_z = 0.0f;
                float angle_xy = 0.0f;
                int i = 0, j = 0;
                gl.Begin(OpenGL.GL_QUADS);
                for (i = 0; i < M; i++)
                {
                    angle_z = i * step_z;
                    for (j = 0; j < N; j++)
                    {
                        angle_xy = j * step_xy;
    
                        x[0] = (float)(radius * Math.Sin(angle_z) * Math.Cos(angle_xy));
                        y[0] = (float)(radius * Math.Sin(angle_z) * Math.Sin(angle_xy));
                        z[0] = (float)(radius * Math.Cos(angle_z));
    
                        x[1] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Cos(angle_xy));
                        y[1] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Sin(angle_xy));
                        z[1] = (float)(radius * Math.Cos(angle_z + step_z));
    
                        x[2] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Cos(angle_xy + step_xy));
                        y[2] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Sin(angle_xy + step_xy));
                        z[2] = (float)(radius * Math.Cos(angle_z + step_z));
    
                        x[3] = (float)(radius * Math.Sin(angle_z) * Math.Cos(angle_xy + step_xy));
                        y[3] = (float)(radius * Math.Sin(angle_z) * Math.Sin(angle_xy + step_xy));
                        z[3] = (float)(radius * Math.Cos(angle_z));
    
                        for (int k = 0; k < 4; k++)
                        {
                            gl.Vertex(xx + x[k], yy + y[k], zz + z[k]);
                        }
                    }
                }
                gl.End();
            }
        }
    }
  • 相关阅读:
    14.会场安排问题(L4)
    图形化调试工具DDD
    sking
    全排列
    DNS
    一种排序
    多边形重心问题
    街区最短路径问题
    Fibonacci数
    python url解析
  • 原文地址:https://www.cnblogs.com/lotuses/p/11360292.html
Copyright © 2011-2022 走看看