1

我一般是opengl和矩阵的新手,但我的相机类可以在第一人称模式下工作,但是事情正在消失,我想知道当我有什么方法可以设置近处和远处的剪裁平面'我只使用模型视图和视图矩阵

我现在只有这个

        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()
        {

        }
    }
}
4

2 回答 2

2

最好的解决方案是将投影矩阵合并到您的课程中。我假设你现在有一个正交类型的输出,因为 OpenGL 通常默认使用一个单位立方体。

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

维基

来自维基百科

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

这是另一个很好的参考

于 2013-09-06T15:17:59.790 回答
1

最简单的答案是否定的。虽然可以使用 glClipPlain() 设置剪切平面,但使用此函数不会覆盖投影矩阵设置的默认剪切平面(默认情况下是(1.0 近和 -1.0 远,我认为) orthographic) 结果,超出这些剪切平原的对象将消失,除非您设置自己的投影矩阵,这很容易: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 你的着色器我会

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

于 2013-09-06T05:47:33.567 回答