0

I have created a simple program that creates a cube and makes its rear plane move in a circle.

When i use GL.Ortho() to view it it works fine, I can see the cube but to my belief GL.Ortho() is for 2D projections and i want to make a 3D game, so I've moved on to attempting projection matrices. Heres my code so far:

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shifted
{
    class Program
    {
        public static double Offset = 0;
        public static Vector3 m_eye;
        public static Vector3 m_target;
        static void Main(string[] args)
        {
            using (GameWindow window = new GameWindow())
            {
                window.Load += (sender, e) =>
                {
                    //Vertical Sync on or off
                    window.VSync = VSyncMode.On;
                    //Set window title
                    window.Title = "Test";
                    //set the "clear color", the colour displayed when nothing is drawn and were looking to infinity
                    GL.ClearColor(Color4.Black);
                    //Set the viewport to match the screen width/height
                    GL.Viewport(0, 0, window.Width, window.Height);

                    m_eye = new Vector3(0, 0, 1f);
                    m_target = new Vector3(0, 0, 0);
                };

                window.Resize += (sender, e) =>
                {
                    //on window resize, resize the viewport. (the "window" were looking into the OpenGL "world" with)
                    GL.Viewport(0, 0, window.Width, window.Height);
                };

                //heres where all game logic should be stored
                window.UpdateFrame += (sender, e) =>
                {
                    Offset += e.Time;
                    KeyboardState keyState = Keyboard.GetState();
                    if (keyState.IsKeyDown(Key.W))
                    {
                        m_eye = m_eye + new Vector3(0f, 0f, .1f);
                        m_target = m_target + new Vector3(0f, 0f, .1f);
                    }
                    if (keyState.IsKeyDown(Key.S))
                    {
                        m_eye = m_eye - new Vector3(0f, 0f, .1f);
                        m_target = m_target - new Vector3(0f, 0f, .1f);
                    }
                    Console.WriteLine(m_eye);
                };

                //heres where everything that draws should go
                window.RenderFrame += (sender, e) =>
                {
                    //Clear the buffer to draw a fresh image
                    GL.Enable(EnableCap.DepthTest);
                    GL.DepthFunc(DepthFunction.Less);
                    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                    //Set draw mode to lines (wiremesh)
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);

                    //GL.LoadIdentity();
                    //GL.Ortho(0.0f, window.Width, 0.0f, window.Height, 0.0f, 1000.0f);
                    GL.MatrixMode(MatrixMode.Projection);
                    GL.LoadIdentity();
                    Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)window.Width / (float)window.Height, 0.1f, 100f);
                    GL.LoadMatrix(ref perspective);
                    GL.MatrixMode(MatrixMode.Modelview);
                    GL.LoadIdentity();
                    Matrix4 lookat = Matrix4.LookAt(m_eye,m_target,Vector3.UnitY);
                    GL.LoadMatrix(ref lookat);
                    GL.LoadIdentity();
                    //Set what colour to draw in
                    GL.Translate(-m_eye);
                    GL.Color3(1.0f, 1.0f, 1.0f);
                    //8 Vertices for a cube
                    double[] vertices = new double[]{100,100,0,
                                                     100,200,0,
                                                     200,200,0,
                                                     200,100,0,
                                                     200+(Math.Sin(Offset)*10),100+(Math.Cos(Offset)*10),-100,
                                                     200+(Math.Sin(Offset)*10),200+(Math.Cos(Offset)*10),-100,
                                                     100+(Math.Sin(Offset)*10),200+(Math.Cos(Offset)*10),-100,
                                                     100+(Math.Sin(Offset)*10),100+(Math.Cos(Offset)*10),-100};
                    //Indice order to draw the cube in, shouldnt have to call this every frame but whatever for now
                    byte[] indices = new byte[] { 0, 1, 2, 2, 3, 0, 2, 3, 4, 4, 5, 2, 2, 1, 6, 6, 5, 2, 0, 1, 7, 7, 6, 1, 7, 6, 5, 5, 4, 7 };
                    //Enable the use of vertex arrays
                    GL.EnableClientState(ArrayCap.VertexArray);
                    //Tell it where to find the vertices
                    GL.Translate(m_eye.X * -1, m_eye.Y * -1, m_eye.Z * -1);
                    GL.VertexPointer(3, VertexPointerType.Double, 0, vertices);
                    //Draw them
                    GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedByte, indices);
                    //Flush it to the buffer
                    GL.Flush();
                    //swap the back buffer we're drawing to to be the front buffer thats displayed
                    window.SwapBuffers();
                };
                //Run at X frames per second. Null = 60 FPS, 200 = no cap, anything in between = that cap.
                window.Run(200);
            }
        }
    }
}

When i remove

GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)window.Width / (float)window.Height, 0.1f, 100f);
GL.LoadMatrix(ref perspective);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
Matrix4 lookat = Matrix4.LookAt(m_eye,m_target,Vector3.UnitY);
GL.LoadMatrix(ref lookat);
GL.LoadIdentity();

and replace it with

GL.Ortho(0.0f, window.Width, 0.0f, window.Height, 0.0f, 1000.0f);

it renders fine, but if i try and use the matrices I just get a black window.

What is it i am doing wrong?

genpfault
  • 51,148
  • 11
  • 85
  • 139
James T
  • 1,155
  • 4
  • 17
  • 39
  • Orthographic projection suit well for 2d but it's also used in 3d. The difference is that all points are projected parallel to the view vector, while in perspective, the field of view parameter mimic real world lens behavior, making the points converge thought the focal points before reaching observer eye, making the points projected from a single point, giving a decreasing size to objects while getting further from the camera... – j-p Mar 03 '15 at 08:13

1 Answers1

2

The problem is that you are not setting up the matrices correctly.

First declare these variables somewhere:

private Matrix4 projectionMatrix;
private Matrix4 modelViewMatrix;
private Vector3 cameraPosition;
private Vector3 cameraTarget;
private Vector3 cameraUp = Vector3.UnitY; // which way is up for the camera

And then use these functions to control your basic camera:

private void SetPerspectiveProjection (int width, int height, float FOV)
{
    projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI * (FOV/180f), width / (float)height, 0.2f, 256.0f);
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadMatrix(ref projectionMatrix); // this replaces the old matrix, no need for GL.LoadIdentity()
}

private void SetOrthographicProjection ()
{
    projectionMatrix = Matrix4.Identity;
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadIdentity(); // reset matrix
    GL.Ortho (-1f, 1f, -1f, 1f, 1000f, -1000f);
}

private void SetLookAtCamera(Vector3 position, Vector3 target, Vector3 up)
{
    modelViewMatrix = Matrix4.LookAt(position, target, up);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadMatrix(ref modelViewMatrix);
}

Finally, before drawing anything:

SetPerspectiveProjection(viewWidth, viewHeight, 45); // 45 is in degrees
SetLookAtCamera(cameraPosition, cameraTarget, cameraUp);

// draw 3D models here

SetOrthographicProjection();

// draw user interface elements here
Daniklad
  • 945
  • 8
  • 10
  • 1
    Explanation of how LookAt matrix is created http://stackoverflow.com/questions/349050/calculating-a-lookat-matrix – Daniklad Mar 26 '15 at 21:47