opengl - LookAt有近和远

时间:2013-09-06 04:25:32

标签: c# opengl

我对opengl和matrices很新,但是我的相机课程以第一人称模式工作,但事情正在消失,我想知道是否有任何方法可以设置近距离和远距离剪辑我只使用模型视图和视图矩阵时的平面

我此刻只有这个,

        Matrix4 view = Matrix4.LookAt
        (
            cam_pos[0],
            cam_pos[1],
            cam_pos[2],
            cam_pos[0] + cam_view[0],
            cam_pos[1] + cam_view[1],
            cam_pos[2] + cam_view[2],
            0.0f, 1.0f, 0.0f
       );

        GL.MatrixMode(MatrixMode.Modelview);
        GL.LoadMatrix(ref view);

这是我的全班:

namespace opengl.Cameras
{
    using opengl.Components;
    using OpenTK;
    using OpenTK.Graphics.OpenGL;
    using System.Windows.Forms;
    using System;

    public class BasicCamera : CameraComponent, IComponent
    {
        const float sensitivity = 0.002f;
        const float walk_speed = 100.5f;

        float[] cam_pos = {75.5f, 30.0f, -110};
        float[] cam_view = {-0.0f, 0.0f, 0.7f};

        static int old_x, old_y;

        void normalize(float[] v)
        {
            float magnitude = (float)Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);           
            v[0] /= magnitude;
            v[1] /= magnitude;
            v[2] /= magnitude;
        }

        void rotate_view(float[] view, float angle, float x, float y, float z)
        {
            float new_x;
            float new_y;
            float new_z;

            float c = (float)Math.Cos(angle);
            float s = (float)Math.Sin(angle);

            new_x = (x * x * (1 - c) + c) * view[0];
            new_x += (x * y * (1 - c) - z * s) * view[1];
            new_x += (x * z * (1 - c) + y * s) * view[2];

            new_y = (y * x * (1 - c) + z * s) * view[0];
            new_y += (y * y * (1 - c) + c) * view[1];
            new_y += (y * z * (1 - c) - x * s) * view[2];

            new_z = (x * z * (1 - c) - y * s) * view[0];
            new_z += (y * z * (1 - c) + x * s) * view[1];
            new_z += (z * z * (1 - c) + c) * view[2];

            view[0] = new_x;
            view[1] = new_y;
            view[2] = new_z;

            normalize(view);
        }

        void motion(int x, int y)
        {
            float rot_x, rot_y;
            float[] rot_axis = new float[3];

            x -= Viewport.Width / 2;
            y -= Viewport.Height / 2;

            rot_x = -(float)(x - old_x) * sensitivity;
            rot_y = -(float)(y - old_y) * sensitivity;

            old_x = x;
            old_y = y;

            rotate_view(cam_view, rot_x, 0.0f, 1.0f, 0.0f);

            rot_axis[0] = -cam_view[2];
            rot_axis[1] = 0.0f;
            rot_axis[2] = cam_view[0];

            normalize(rot_axis);

            rotate_view(cam_view, rot_y, rot_axis[0], rot_axis[1], rot_axis[2]);
        }

        public BasicCamera() :  base()
        {
            // Enable depth testing
            GL.Enable(EnableCap.DepthTest);
            GL.ClearDepth(1.0f);
        }

        public void Load(CameraComponent Camera)
        {
        }

        public void UpdateFrame(double elapsed)
        {
            if (this[Keys.W])
            {
                cam_pos[0] += cam_view[0] * walk_speed;
                cam_pos[1] += cam_view[1] * walk_speed;
                cam_pos[2] += cam_view[2] * walk_speed;
            }
            if (this[Keys.S])
            {
                cam_pos[0] -= cam_view[0] * walk_speed;
                cam_pos[1] -= cam_view[1] * walk_speed;
                cam_pos[2] -= cam_view[2] * walk_speed;
            }
            if (this[Keys.A])
            {
                cam_pos[0] += cam_view[2] * walk_speed;
                cam_pos[2] -= cam_view[0] * walk_speed;
            }
            if (this[Keys.D])
            {
                cam_pos[0] -= cam_view[2] * walk_speed;
                cam_pos[2] += cam_view[0] * walk_speed;
            }

            if (this[Keys.Space])
                cam_pos[1] += walk_speed;
        }

        public void Render(double elapsed)
        {
            Matrix4 view = Matrix4.LookAt
            (
                cam_pos[0],
                cam_pos[1],
                cam_pos[2],
                cam_pos[0] + cam_view[0],
                cam_pos[1] + cam_view[1],
                cam_pos[2] + cam_view[2],
                0.0f, 1.0f, 0.0f
           );

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref view);
        }

        public void OnMouseMove(MouseEventArgs e)
        {

        }

        public void OnMouseDown(MouseEventArgs e)
        {
            old_x = (int)e.X - Viewport.Width / 2;
            old_y = (int)e.Y - Viewport.Height / 2;
        }

        public void OnMouseMotion(Vector2 MousePosition, Vector2 PrevMousePosition)
        {           
            motion((int)MousePosition.X, (int)MousePosition.Y);
        }

        public void Destroy()
        {
        }

        public void Load()
        {

        }
    }
}

2 个答案:

答案 0 :(得分:2)

最佳解决方案是将投影矩阵合并到您的班级中。我假设你现在有一个正交类型输出,因为OpenGL通常默认使用单位多维数据集。

以下列方式构建矩阵将允许您更改近平面和远平面,至少对于正交投影。

wiki

from Wikipedia

右/左/上/下/远/近是立方体的面。然后,您需要调用glMatrixMode(GL_PROJECTION)并加载此新投影矩阵。我使用立即模式已经有一段时间了,所以这一步可能不正确。

Here is another good reference

答案 1 :(得分:1)

最简单的答案是否。虽然可以使用glClipPlain()设置剪裁平台,但使用此函数不会覆盖投影矩阵设置的默认剪裁平面(默认情况下为(1.0近和-1.0远) ,我认为)正交)作为结果,走出这些剪裁平台的物体将消失,除非您设置自己的投影矩阵非常容易: glMatrixMode(GL_PROJECTION); glFrustum(-left_side,right_side,-bottom,top,near,-far) *注意这些功能实际上已被弃用 您可以使用glFloatv(GL_PROJECTION_MATRIX,modview)检索顶点着色器中的矩阵设置; glUniformMatrix4fv(vert_shader,1,false,modview); *在这种情况下,modview将是您的16个浮点元素数组,用于保存矩阵值 * vert_shader你的着色器我

有关这些着色器功能的详细信息,您可以自己了解或者在线阅读任何高度丰富的教程。我自己也是一个noobie,我希望以某种方式帮助过你;)