Exemple #1
0
        /// <summary>
        /// 把连续16个float值按照列优先的顺序转换为mat4
        /// </summary>
        /// <param name="values"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        public static mat4 ToMat4(this float[] values, int startIndex = 0)
        {
            mat4 result;
            result = new mat4(
                values.ToVec4(startIndex + 0), values.ToVec4(startIndex + 4), values.ToVec4(startIndex + 8), values.ToVec4(startIndex + 12));

            return result;
        }
Exemple #2
0
        void element_BeforeRendering(object sender, Objects.RenderEventArgs e)
        {
            rotation += 3.0f;
            modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0));
            viewMatrix = this.camera.GetViewMat4();
            projectionMatrix = this.camera.GetProjectionMat4();

            mat4 mvp = projectionMatrix * viewMatrix * modelMatrix;

            IMVP element = sender as IMVP;

            element.SetShaderProgram(mvp);
        }
        void pyramidElement_BeforeRendering(object sender, Objects.RenderEventArgs e)
        {
            rotation += 3.0f;
            mat4 modelMatrix = glm.rotate(rotation, new vec3(0, 1, 0));

            const float distance = 0.7f;
            viewMatrix = glm.lookAt(new vec3(-distance, distance, -distance), new vec3(0, 0, 0), new vec3(0, -1, 0));

            int[] viewport = new int[4];
            GL.GetInteger(GetTarget.Viewport, viewport);
            projectionMatrix = glm.perspective(60.0f, (float)viewport[2] / (float)viewport[3], 0.01f, 100.0f);

            mat4 mvp = projectionMatrix * viewMatrix * modelMatrix;

            IMVP element = sender as IMVP;

            element.SetShaderProgram(mvp);
        }
Exemple #4
0
        /// <summary>
        /// Define a picking region.
        /// </summary>
        /// <param name="center">The center.</param>
        /// <param name="delta">The delta.</param>
        /// <param name="viewport">The viewport.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public static mat4 pickMatrix(vec2 center, vec2 delta, vec4 viewport)
        {
            if (delta.x <= 0 || delta.y <= 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var Result = new mat4(1.0f);

            if (!(delta.x > (0f) && delta.y > (0f)))
            {
                return(Result); // Error
            }
            vec3 Temp = new vec3(
                ((viewport[2]) - (2f) * (center.x - (viewport[0]))) / delta.x,
                ((viewport[3]) - (2f) * (center.y - (viewport[1]))) / delta.y,
                (0f));

            // Translate and scale the picked region to the entire window
            Result = translate(Result, Temp);
            return(scale(Result, new vec3((viewport[2]) / delta.x, (viewport[3]) / delta.y, (1))));
        }
Exemple #5
0
        /// <summary>
        /// Builds a perspective projection matrix based on a field of view.
        /// </summary>
        /// <param name="fov">The fov (in radians).</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="zNear">The z near.</param>
        /// <param name="zFar">The z far.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public static mat4 perspectiveFov(float fov, float width, float height, float zNear, float zFar)
        {
            if (width <= 0 || height <= 0 || fov <= 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            var rad = fov;

            var h = glm.cos((0.5f) * rad) / glm.sin((0.5f) * rad);
            var w = h * height / width;

            var result = new mat4(0);

            result[0, 0] = w;
            result[1, 1] = h;
            result[2, 2] = -(zFar + zNear) / (zFar - zNear);
            result[2, 3] = -(1f);
            result[3, 2] = -((2f) * zFar * zNear) / (zFar - zNear);
            return(result);
        }
Exemple #6
0
        /// <summary>
        /// Build a look at view matrix.
        /// </summary>
        /// <param name="eye">The eye.</param>
        /// <param name="center">The center.</param>
        /// <param name="up">Up.</param>
        /// <returns></returns>
        public static mat4 lookAt(vec3 eye, vec3 center, vec3 up)
        {
            vec3 f = normalize(center - eye);
            vec3 s = normalize(cross(f, up));
            vec3 u = cross(s, f);

            mat4 Result = new mat4(1);

            Result[0, 0] = s.x;
            Result[1, 0] = s.y;
            Result[2, 0] = s.z;
            Result[0, 1] = u.x;
            Result[1, 1] = u.y;
            Result[2, 1] = u.z;
            Result[0, 2] = -f.x;
            Result[1, 2] = -f.y;
            Result[2, 2] = -f.z;
            Result[3, 0] = -dot(s, eye);
            Result[3, 1] = -dot(u, eye);
            Result[3, 2] = dot(f, eye);
            return(Result);
        }
Exemple #7
0
 void IMVP.SetShaderProgram(mat4 mvp)
 {
     IMVP element = this.axisElement as IMVP;
     element.SetShaderProgram(mvp);
 }
Exemple #8
0
 void IMVP.SetShaderProgram(mat4 mvp)
 {
     IMVPHelper.DoUpdateMVP(this, mvp);
 }
        //void IRenderable.Render(RenderModes renderMode)
        //{
        //    base.Render(renderMode);
        //}
        void IMVP.SetShaderProgram(mat4 mvp)
        {
            ShaderProgram shaderProgram = this.currentShaderProgram;

            shaderProgram.Bind();
            if (shaderProgram == this.pickingShaderProgram)
            {
                shaderProgram.SetUniform("pickingBaseID", ((IColorCodedPicking)this).PickingBaseID);
                shaderProgram.SetUniformMatrix4(strMVP, mvp.to_array());
            }
            else
            {
                shaderProgram.SetUniformMatrix4(strMVP, mvp.to_array());
            }
        }
        void IMVP.SetShaderProgram(mat4 mvp)
        {
            GL.Enable(GL.GL_VERTEX_PROGRAM_POINT_SIZE);
            GL.Enable(GL.GL_POINT_SPRITE_ARB);
            //GL.TexEnv(GL.GL_POINT_SPRITE_ARB, GL.GL_COORD_REPLACE_ARB, GL.GL_TRUE);//TODO: test TexEnvi()
            GL.TexEnvf(GL.GL_POINT_SPRITE_ARB, GL.GL_COORD_REPLACE_ARB, GL.GL_TRUE);
            GL.Enable(GL.GL_POINT_SMOOTH);
            GL.Hint(GL.GL_POINT_SMOOTH_HINT, GL.GL_NICEST);
            GL.Enable(GL.GL_BLEND);
            GL.BlendEquation(GL.GL_FUNC_ADD_EXT);
            GL.BlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE);

            GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[0]);

            IMVPHelper.DoUpdateMVP(this, mvp);

            //int[] poinSizes = new int[2];
            //GL.GetInteger(GetTarget.PointSizeRange, poinSizes);
            //if (this.textureWidth > poinSizes[1])
            //{
            //    GL.PointParameter(GL.GL_POINT_SIZE_MAX_ARB, this.textureWidth);
            //    GL.GetInteger(GetTarget.PointSizeRange, poinSizes);
            //    Console.WriteLine("asf");
            //}
            shaderProgram.SetUniform(PointSpriteStringElement.strpointSize, this.textureWidth + 0.0f);
            shaderProgram.SetUniform(PointSpriteStringElement.strtex, this.texture[0]);
            shaderProgram.SetUniform(PointSpriteStringElement.strtextColor, this.textColor.x, this.textColor.y, this.textColor.z);
        }
Exemple #11
0
        /// <summary>
        /// 如果此矩阵是glm.perspective()的结果,那么返回glm.perspective()的各个参数值。
        /// </summary>
        /// <param name="matrix"></param>
        /// <param name="fovy"></param>
        /// <param name="aspectRatio"></param>
        /// <param name="zNear"></param>
        /// <param name="zFar"></param>
        /// <returns></returns>
        public static bool TryParse(this mat4 matrix,
                                    out float fovy, out float aspectRatio, out float zNear, out float zFar)
        {
            /*
             * var result = mat4.identity();
             * float tangent = (float)Math.Tan(fovy / 2.0f);
             * float height = zNear * tangent;
             * float width = height * aspect;
             * float l = -width, r = width, b = -height, t = height, n = zNear, f = zFar;
             * result[0, 0] = 2 * n / (r - l);// = 2 * zNear / (2 * zNear * tangent * aspect)
             * result[1, 1] = 2 * n / (t - b);// = 2 * zNear / (2 * zNear * tangent)
             * result[2, 0] = (r + l) / (r - l);// = 0
             * result[2, 1] = (t + b) / (t - b);// = 0
             * result[2, 2] = -(f + n) / (f - n);
             * result[2, 3] = -1;
             * result[3, 2] = -(2 * f * n) / (f - n);
             * result[3, 3] = 0;
             */
            float tanHalfFovy = 1.0f / matrix[1, 1];

            fovy = 2 * (float)(Math.Atan(tanHalfFovy));
            if (fovy < 0)
            {
                fovy = -fovy;
            }
            //aspectRatio = 1.0f / matrix[0, 0] / tanHalfFovy;
            aspectRatio = matrix[1, 1] / matrix[0, 0];
            if (matrix[2, 2] == 1.0f)
            {
                zFar  = 0.0f;
                zNear = 0.0f;
            }
            else if (matrix[2, 2] == -1.0f)
            {
                zNear = 0.0f;
                zFar  = float.PositiveInfinity;
            }
            else
            {
                zNear = matrix[3, 2] / (matrix[2, 2] - 1);
                zFar  = matrix[3, 2] / (matrix[2, 2] + 1);
            }

            if (matrix[0, 0] == 0.0f || matrix[1, 1] == 0.0f || matrix[2, 2] == 0.0f)
            {
                return(false);
            }

            if (matrix[1, 0] != 0.0f || matrix[3, 0] != 0.0f ||
                matrix[0, 1] != 0.0f || matrix[3, 1] != 0.0f ||
                matrix[0, 2] != 0.0f || matrix[1, 2] != 0.0f ||
                matrix[0, 3] != 0.0f || matrix[1, 3] != 0.0f || matrix[3, 3] != 0.0f)
            {
                return(false);
            }

            if (matrix[2, 3] != -1.0f)
            {
                return(false);
            }

            return(true);
        }
        public static void TypicalScene()
        {
            const int count = 1000000;

            long startTick = 0;
            long interval, interval2;

            // 测试float类型
            {
                var floatArray = new UnmanagedArray<float>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    floatArray[i] = i;
                }
                for (int i = 0; i < count; i++)
                {
                    var item = floatArray[i];
                    if (item != i)
                    { throw new Exception(); }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    float* header = (float*)floatArray.FirstElement();
                    float* last = (float*)floatArray.LastElement();
                    float* tailAddress = (float*)floatArray.TailAddress();
                    int value = 0;
                    for (float* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = value++;
                    }
                    int i = 0;
                    for (float* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        if (item != i)
                        { throw new Exception(); }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);
            }

            // 测试decimal类型
            {
                var decimalArray = new UnmanagedArray<decimal>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    decimalArray[i] = i;
                }
                for (int i = 0; i < count; i++)
                {
                    var item = decimalArray[i];
                    if (item != i)
                    { throw new Exception(); }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    decimal* header = (decimal*)decimalArray.FirstElement();
                    decimal* last = (decimal*)decimalArray.LastElement();
                    decimal* tailAddress = (decimal*)decimalArray.TailAddress();
                    int value = 0;
                    for (decimal* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = value++;
                    }
                    int i = 0;
                    for (decimal* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        if (item != i)
                        { throw new Exception(); }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);
            }

            // 测试int类型
            {
                var intArray = new UnmanagedArray<int>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    intArray[i] = i;
                }
                for (int i = 0; i < count; i++)
                {
                    var item = intArray[i];
                    if (item != i)
                    { throw new Exception(); }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    int* header = (int*)intArray.FirstElement();
                    int* last = (int*)intArray.LastElement();
                    int* tailAddress = (int*)intArray.TailAddress();
                    int value = 0;
                    for (int* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = value++;
                    }
                    int i = 0;
                    for (int* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        if (item != i)
                        { throw new Exception(); }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);
            }

            // 测试bool类型
            {
                var boolArray = new UnmanagedArray<bool>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    boolArray[i] = i % 2 == 0;
                }
                for (int i = 0; i < count; i++)
                {
                    var item = boolArray[i];
                    if (item != (i % 2 == 0))
                    { throw new Exception(); }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    bool* header = (bool*)boolArray.FirstElement();
                    bool* last = (bool*)boolArray.LastElement();
                    bool* tailAddress = (bool*)boolArray.TailAddress();
                    int value = 0;
                    for (bool* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = (value % 2 == 0);
                        value++;
                    }
                    int i = 0;
                    for (bool* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        if (item != (i % 2 == 0))
                        { throw new Exception(); }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);
            }

            // 测试vec3类型
            {
                var vec3Array = new UnmanagedArray<vec3>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    vec3Array[i] = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2);
                }
                for (int i = 0; i < count; i++)
                {
                    var item = vec3Array[i];
                    var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2);
                    if (item.x != old.x || item.y != old.y || item.z != old.z)
                    { throw new Exception(); }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    vec3* header = (vec3*)vec3Array.FirstElement();
                    vec3* last = (vec3*)vec3Array.LastElement();
                    vec3* tailAddress = (vec3*)vec3Array.TailAddress();
                    int i = 0;
                    for (vec3* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2);
                        i++;
                    }
                    i = 0;
                    for (vec3* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2);
                        if (item.x != old.x || item.y != old.y || item.z != old.z)
                        { throw new Exception(); }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);

            }

            // 测试mat4类型
            {
                var vec3Array = new UnmanagedArray<mat4>(count);
                startTick = DateTime.Now.Ticks;
                for (int i = 0; i < count; i++)
                {
                    vec3Array[i] = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3));
                }
                for (int i = 0; i < count; i++)
                {
                    var item = vec3Array[i];
                    var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3));
                    for (int col = 0; col < 4; col++)
                    {
                        for (int row = 0; row < 4; row++)
                        {
                            if (item[col][row] != old[col][row])
                            { throw new Exception(); }
                        }
                    }
                }
                interval = DateTime.Now.Ticks - startTick;

                unsafe
                {
                    startTick = DateTime.Now.Ticks;
                    mat4* header = (mat4*)vec3Array.FirstElement();
                    mat4* last = (mat4*)vec3Array.LastElement();
                    mat4* tailAddress = (mat4*)vec3Array.TailAddress();
                    int i = 0;
                    for (mat4* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++)
                    {
                        *ptr = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3));
                        i++;
                    }
                    i = 0;
                    for (mat4* ptr = header; ptr <= last/*or: ptr < tailAddress*/; ptr++, i++)
                    {
                        var item = *ptr;
                        var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3));
                        for (int col = 0; col < 4; col++)
                        {
                            for (int row = 0; row < 4; row++)
                            {
                                if (item[col][row] != old[col][row])
                                { throw new Exception(); }
                            }
                        }
                    }
                    interval2 = DateTime.Now.Ticks - startTick;
                }
                Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2);

            }

            // 立即释放所有非托管数组占用的内存,任何之前创建的UnmanagedBase数组都不再可用了。
            UnmanagedArray<int>.FreeAll();
        }
Exemple #13
0
        /// <summary>
        /// Multiplies the <paramref name="lhs"/> matrix by the <paramref name="rhs"/> matrix.
        /// </summary>
        /// <param name="lhs">The LHS matrix.</param>
        /// <param name="rhs">The RHS matrix.</param>
        /// <returns>The product of <paramref name="lhs"/> and <paramref name="rhs"/>.</returns>
        public static mat4 operator *(mat4 lhs, mat4 rhs)
        {
            mat4 result = new mat4(
                new vec4(
                    lhs[0][0] * rhs[0][0] + lhs[1][0] * rhs[0][1] + lhs[2][0] * rhs[0][2] + lhs[3][0] * rhs[0][3],
                    lhs[0][1] * rhs[0][0] + lhs[1][1] * rhs[0][1] + lhs[2][1] * rhs[0][2] + lhs[3][1] * rhs[0][3],
                    lhs[0][2] * rhs[0][0] + lhs[1][2] * rhs[0][1] + lhs[2][2] * rhs[0][2] + lhs[3][2] * rhs[0][3],
                    lhs[0][3] * rhs[0][0] + lhs[1][3] * rhs[0][1] + lhs[2][3] * rhs[0][2] + lhs[3][3] * rhs[0][3]
                    ),
                new vec4(
                    lhs[0][0] * rhs[1][0] + lhs[1][0] * rhs[1][1] + lhs[2][0] * rhs[1][2] + lhs[3][0] * rhs[1][3],
                    lhs[0][1] * rhs[1][0] + lhs[1][1] * rhs[1][1] + lhs[2][1] * rhs[1][2] + lhs[3][1] * rhs[1][3],
                    lhs[0][2] * rhs[1][0] + lhs[1][2] * rhs[1][1] + lhs[2][2] * rhs[1][2] + lhs[3][2] * rhs[1][3],
                    lhs[0][3] * rhs[1][0] + lhs[1][3] * rhs[1][1] + lhs[2][3] * rhs[1][2] + lhs[3][3] * rhs[1][3]
                    ),
                new vec4(
                    lhs[0][0] * rhs[2][0] + lhs[1][0] * rhs[2][1] + lhs[2][0] * rhs[2][2] + lhs[3][0] * rhs[2][3],
                    lhs[0][1] * rhs[2][0] + lhs[1][1] * rhs[2][1] + lhs[2][1] * rhs[2][2] + lhs[3][1] * rhs[2][3],
                    lhs[0][2] * rhs[2][0] + lhs[1][2] * rhs[2][1] + lhs[2][2] * rhs[2][2] + lhs[3][2] * rhs[2][3],
                    lhs[0][3] * rhs[2][0] + lhs[1][3] * rhs[2][1] + lhs[2][3] * rhs[2][2] + lhs[3][3] * rhs[2][3]
                    ),
                new vec4(
                    lhs[0][0] * rhs[3][0] + lhs[1][0] * rhs[3][1] + lhs[2][0] * rhs[3][2] + lhs[3][0] * rhs[3][3],
                    lhs[0][1] * rhs[3][0] + lhs[1][1] * rhs[3][1] + lhs[2][1] * rhs[3][2] + lhs[3][1] * rhs[3][3],
                    lhs[0][2] * rhs[3][0] + lhs[1][2] * rhs[3][1] + lhs[2][2] * rhs[3][2] + lhs[3][2] * rhs[3][3],
                    lhs[0][3] * rhs[3][0] + lhs[1][3] * rhs[3][1] + lhs[2][3] * rhs[3][2] + lhs[3][3] * rhs[3][3]
                    )
                    );

            return result;
        }
Exemple #14
0
        /// <summary>
        /// 获取此UI元素的投影矩阵、视图矩阵和模型矩阵
        /// </summary>
        /// <param name="uiElement"></param>
        /// <param name="projectionMatrix"></param>
        /// <param name="viewMatrix"></param>
        /// <param name="modelMatrix"></param>
        /// <param name="camera">如果为null,会以glm.lookAt(new vec3(0, 0, 1), new vec3(0, 0, 0), new vec3(0, 1, 0))计算默认值。</param>
        /// <param name="maxDepth">UI元素的外接球半径的倍数。</param>
        public static void GetMatrix(this IUILayout uiElement,
            out mat4 projectionMatrix, out mat4 viewMatrix, out mat4 modelMatrix,
            IViewCamera camera = null, float maxDepth = 2.0f)
        {
            IUILayoutArgs args = uiElement.GetArgs();
            float max = (float)Math.Max(args.UIWidth, args.UIHeight);

            {
                //projectionMatrix = glm.ortho((float)args.left, (float)args.right, (float)args.bottom, (float)args.top,
                // TODO: / 2后与legacy opengl的UI元素显示就完全一致了。为什么???
                projectionMatrix = glm.ortho((float)args.left / 2, (float)args.right / 2, (float)args.bottom / 2, (float)args.top / 2,
                    uiElement.Param.zNear, uiElement.Param.zFar);
                // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。
                //{
                //    float[] matrix = new float[16];

                //    GL.MatrixMode(GL.GL_PROJECTION);
                //    GL.PushMatrix();
                //    GL.GetFloat(GetTarget.ProjectionMatrix, matrix);

                //    GL.LoadIdentity();
                //    GL.GetFloat(GetTarget.ProjectionMatrix, matrix);

                //    GL.Ortho(args.left / 2, args.right / 2, args.bottom / 2, args.top / 2, uiElement.Param.zNear, uiElement.Param.zFar);
                //    GL.GetFloat(GetTarget.ProjectionMatrix, matrix);// this equals projectionMatrix

                //    GL.PopMatrix();
                //}
                // 把UI元素移到ortho长方体的最靠近camera的地方,这样就可以把UI元素放到OpenGL最前方。
                projectionMatrix = glm.translate(projectionMatrix, new vec3(0, 0, uiElement.Param.zFar - max / 2 * maxDepth));
            }
            {
                // UI元素不在三维场景中,所以其Camera可以是null。
                if (camera == null)
                {
                    //viewMatrix = glm.lookAt(new vec3(0, 0, 1), new vec3(0, 0, 0), new vec3(0, 1, 0));
                    viewMatrix = glm.lookAt(
                        ScientificCamera.defaultPosition,
                        ScientificCamera.defaultTarget,
                        ScientificCamera.defaultUpVector);
                }
                else
                {
                    vec3 position = camera.Position - camera.Target;
                    position.Normalize();
                    viewMatrix = glm.lookAt(position, new vec3(0, 0, 0), camera.UpVector);
                }
                // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。
                //{
                //    float[] matrix = new float[16];

                //    GL.MatrixMode(GL.GL_MODELVIEW);
                //    GL.PushMatrix();
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);

                //    GL.LoadIdentity();
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);

                //    if(camera==null)
                //    {
                //        GL.gluLookAt(0, 0, 1, 0, 0, 0, 0, 1, 0);
                //    }
                //    else
                //    {
                //        vec3 position = camera.Position - camera.Target;
                //        position.Normalize();
                //        GL.gluLookAt(position.x, position.y, position.z, 0, 0, 0, camera.UpVector.x, camera.UpVector.y, camera.UpVector.z);
                //    }
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);// this equals viewMatrix

                //    GL.PopMatrix();
                //}
            }
            {
                modelMatrix = glm.scale(mat4.identity(), new vec3(args.UIWidth / 2, args.UIHeight / 2, max / 2));
                // 下面注释掉的代码是用来测试legacy OpenGL的matrix与GLM库计算的matrix是否相同用的。已经证明了两者完全相同,此处仅作留念+以防万一。
                //{
                //    float[] matrix = new float[16];

                //    GL.MatrixMode(GL.GL_MODELVIEW);
                //    GL.PushMatrix();
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);

                //    GL.LoadIdentity();
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);

                //    GL.Scale(args.UIWidth / 2, args.UIHeight / 2, max / 2);
                //    GL.GetFloat(GetTarget.ModelviewMatix, matrix);// this equals modelMatrix

                //    GL.PopMatrix();
                //}
            }
        }