jjgl's picture

Aspect ratio problem by using Matrix

Project:The Open Toolkit library
Version:1.0.0-rc1
Component:Miscellaneous
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed
Description

I am using OpenTK in my project and have difficulty to use OpenTK.Math.Matrix4.Perspective() dealing with aspect ratio problem. The following Resize function is not working. Could anyone tell me what I have missed here?

private void glControl1_Resize(object sender, EventArgs e)
{
if (!left_glcontrol_loaded)
{
return;
}

GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();

Matrix4 m_prespective = Matrix4.Perspective(45.0f, (float) glControl1.Width/ (float)glControl1.Height, 1.0f, 400.0f);
GL.LoadMatrix(ref m_prespective);

}


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

#1

Status:open» by design

The math library uses radians, not degrees:

Matrix4 m_prespective = Matrix4.Perspective(
    System.Math.Pi / 4,
    (float) glControl1.Width / (float)glControl1.Height, 1.0f, 400.0f);
jjgl's picture

#2

Thank you for quick response. After the angle value is changed from degree to radians, the problem is still not solved. Here is a simple program.

using System;
using System.Drawing;
using System.Windows.Forms;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace openTK_test_01
{
public partial class Form1 : Form
{
private bool loaded1 = false;
private int h;
private int w;

public Form1()
{
InitializeComponent();
}

private void glControl1_Load(object sender, EventArgs e)
{
loaded1 = true;
GL.ClearColor(Color.Black);
w = glControl1.Width;
h = glControl1.Height;
}

private void glControl1_Resize(object sender, EventArgs e)
{
if (!loaded1)
return;

GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();

w = glControl1.Width;
h = glControl1.Height;

Matrix4d m_perspective = Matrix4d.CreatePerspectiveFieldOfView(Math.PI / 4.0, (double)w / (double)h, 1.0, 40.0);
GL.LoadMatrix(ref m_perspective);
GL.Viewport(0, 0, w, h);
glControl1.Refresh();
}

private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded1)
return;

DisplayViewPort();
glControl1.SwapBuffers();
}

private void DisplayViewPort()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LoadIdentity();

GL.MatrixMode(MatrixMode.Modelview);
//
// Draw a triangle
//
GL.Begin(BeginMode.Triangles);
GL.Color3(0.8f, 0.1f, 0.5f);
GL.Vertex3(0.2, 0.0, 0.0);
GL.Color3(0.1f, 0.8f, 0.5f);
GL.Vertex3(0.0, 1.0, 0.0);
GL.Color3(0.1f, 0.5f, 0.8f);
GL.Vertex3(-0.2, 0.0, 0.0);
GL.End();
//
//Switch to the drawing perspective
//
GL.Begin(BeginMode.Lines);
GL.Color3(0.1f, 0.8f, 0.5f);
GL.Vertex3(-0.5 * w, 0.0f, 0.0f);
GL.Vertex3(0.5 * w, 0.0f, 0.0f);

GL.Vertex3(0.0f, -0.5 * h, 0.0f);
GL.Vertex3(0.0f, 0.5 * h, 0.0f);
GL.End();
}
}
}

Run program and resize the window, you will notice that the triangle shape will be changed when ratio of w / h is changed. I am trying to keep object shape unchange even when w / h is changed. Your help is surely appreciated.

jjgl's picture

#3

Can anyone provide a resize function by calling Matrix4d.CreatePerspectiveFieldOfView()? Why A simple thing by calling gluPerspective() dose work in OpenTK?

Hortus Longus's picture

#4

jjgl, please select your sourcecode and click on the "C#"- button to enable syntax highlighting, nobody will read it like in notepad.

Quote:

Can anyone provide a resize function by calling Matrix4d.CreatePerspectiveFieldOfView()?

Sure, that is simple (I am using floats, you see):

    /// <summary> /// Client-window is resized /// </summary>
    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);
 
      GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
      Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4,  Width / (float)Height, 0.1f, 500.0f);
      GL.MatrixMode(MatrixMode.Projection);
      GL.LoadMatrix(ref projection);
    }

Or you can use the search-function, you can find many examples here.

Quote:

Why A simple thing by calling gluPerspective() dose work in OpenTK?

If it is so simple, why do you not write it yourself?

jjgl's picture

#5

Thanks, Hortus Longus. I appreciated your help.

Hortus Longus's picture

#6

Thread should be moved, not an issue of OpenTK.

jjgl's picture

#7

The problem is still there even with resize function as you suggested. I am still struggling to make it work . Please see attached project files, the object shape, which is a triangle in this example, is changed when window size is changed. I use glControl on top of panel control of .net frameworks. I am not sure if the combination of glcontrol and panel control caused the problem. Thank you for your help.

AttachmentSize
openTK_test_01.zip25.29 KB
migueltk's picture

#8

Hi, ...

True, there is a problem ...

I modified the code as follows:

using System;
using System.Drawing;
using System.Windows.Forms;
 
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
namespace openTK_test_01
{
    public partial class Form1 : Form
    {
        private bool loaded1 = false;
        private int h;
        private int w;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void glControl1_Load(object sender, EventArgs e)
        {
            loaded1 = true;
            GL.ClearColor(Color.Black);
            w = glControl1.Width;
            h = glControl1.Height;
        }
 
        internal void gluPerspective(double fovy, double aspect, double zNear, double zFar)
        {
            double xmin, xmax, ymin, ymax;
 
            ymax = zNear * Math.Tan(fovy * Math.PI / 360.0);
            ymin = -ymax;
 
            xmin = ymin * aspect;
            xmax = ymax * aspect;
 
            GL.Frustum(xmin, xmax, ymin, ymax, zNear, zFar);
        }
 
        private void glControl1_Resize(object sender, EventArgs e)
        {
            //if (!loaded1)
            //    return;
            //base.OnResize(e);
 
            h = glControl1.Height;
            w = glControl1.Width;
            GL.Viewport(0, 0, w, h);
 
            //Matrix4 m_perspective = Matrix4.CreatePerspectiveFieldOfView((float)(Math.PI / 4.0f), w / (float)h, 0.1f, 200.0f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            gluPerspective(45.0, w/(float)h, 0.1, 400.0);
            //GL.LoadMatrix(ref m_perspective);
            //glControl1.Refresh();
        }
 
 
        private void glControl1_Paint(object sender, PaintEventArgs e)
        {
            //if (!loaded1)
            //    return;
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
 
            GL.Enable(EnableCap.DepthTest);
 
            DisplayViewPort();
            glControl1.SwapBuffers();
        }
 
        private void DisplayViewPort()
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            //
            //Switch to the drawing perspective
            //
 
            GL.Translate(0, 0, -10);
            //
            // Draw a triangle
            //
            GL.Begin(BeginMode.Triangles);
            GL.Color3(0.8f, 0.1f, 0.5f);
            GL.Vertex3(0.2, 0.0, 0.0);
            GL.Color3(0.1f, 0.8f, 0.5f);
            GL.Vertex3(0.0, 1.0, 0.0);
            GL.Color3(0.1f, 0.5f, 0.8f);
            GL.Vertex3(-0.2, 0.0, 0.0);
            GL.End();
 
            GL.Begin(BeginMode.Lines);
            GL.Color3(0.1f, 0.8f, 0.5f);
            GL.Vertex3(-0.5 * w, 0.0f, 0.0f);
            GL.Vertex3(0.5 * w, 0.0f, 0.0f);
 
            GL.Vertex3(0.0f, -0.5 * h, 0.0f);
            GL.Vertex3(0.0f, 0.5 * h, 0.0f);
            GL.End();
        }
    }
}

The problem is that when it reduces both the width and height of the control, just call the Resize method () of control, but the paint () method of control is not called.

In another case, when increasing the width or height of the control, everything works fine, first resize () method of control is called and then the paint () method of control is called.

Using OpenTK 1.0 branch ...
Is a Bug ...

Regards, ...

Hortus Longus's picture

#9

Quote:

True, there is a problem ...

Yes, but that is another pair of shoes.
Resize means resizing a window and its contents. So simple as written.
What jjgl is searching for is a resize-and-zoom-in-out-function.

c2woody's picture

#10

Quote:

The problem is that when it reduces both the width and height of the control, just call the Resize method () of control, but the paint () method of control is not called.

Hm got to look that up, but think I've always used .Invalidate() as last call in the resize function since this flags the control contents as now-invalid and calls paint as necessary.