2

I am very new to OpenGL and am using the latest version of OpenTK with C#.

My camera class currently does the following,

public Matrix4 GetProjectionMatrix()
{
    return Matrix4.CreatePerspectiveFieldOfView(_fov, AspectRatio, 0.01f, 100f);
}

public Matrix4 GetViewMatrix()
{
    Vector3 lookAt = new Vector3(myObject.Pos.X, myObject.Pos.Y, myObject.Pos.Z);
    return Matrix4.LookAt(Position, lookAt, _up);
}

I have a slightly weird use case, where my game window will be long, something like a 4:12 ratio, and it will present a long object. From my reading, online the best way to present this the way I want is to do a lense shift (Oblique Frustum).

I've seen articles online on how to do this, namely: http://www.terathon.com/code/oblique.html https://docs.unity3d.com/Manual/ObliqueFrustum.html

But I am having trouble translating this to OpenTk.

Was wondering if anyone on here has done something similar to this in OpenTK.

EDIT: This kind of worked, but not quite what I was looking for :(

private float sgn(float a)
{
    if (a > 0.0F) return (1.0F);
    if (a < 0.0F) return (-1.0F);
    return (0.0F);
}

public Matrix4 CreatePerspectiveFieldOfView(Matrix4 projectionMatrix)
{
    Vector4 clipPlane = new Vector4(0.0f, 0.7f, 1.0f , 1.0f);
    Vector4 q = new Vector4
    {
        X = (sgn(clipPlane.X) + projectionMatrix.M13) / projectionMatrix.M11,
        Y = (sgn(clipPlane.Y) + projectionMatrix.M23) / projectionMatrix.M22,
        Z = -1.0f,
        W = (1.0F + projectionMatrix.M33) / projectionMatrix.M34
    };

    Vector4 c = clipPlane * (2.0F / Vector4.Dot(clipPlane, q));
    projectionMatrix.M31 = c.X;
    projectionMatrix.M32 = c.Y;
    projectionMatrix.M33 = c.Z + 1.0f;
    projectionMatrix.M34 = c.W;

    return projectionMatrix;
}

EDIT 2:

Basically what I am looking to do, is bring the look at point closer to the edge of the frustum like so: enter image description here

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Khal
  • 23
  • 1
  • 4

1 Answers1

1

There are some obvious issues. OpenGL matrices are column major order. Hence, i is the column and j is the row for the Mij properties of Matrix4:

In the following columns are from the top to the bottom and rows are form the left to the right, because that is the representation of the fields of the matrix in memory and how a matrix "looks" in the debuger:

         row1 row2 row3 row4             indices
column1 (M11, M12, M13, M14)             ( 0,  1,  2,  3) 
column2 (M21, M22, M23, M24)             ( 4,  5,  6,  7) 
column3 (M31, M32, M33, M34)             ( 8,  9, 10, 11) 
column4 (M41, M42, M43, M44)             (12, 13, 14, 15)  

Thus

q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];

has to be translated to:

Vector4 q = new Vector4
{
    X = (sgn(clipPlane.X) + projectionMatrix.M31) / projectionMatrix.M11,
    Y = (sgn(clipPlane.Y) + projectionMatrix.M32) / projectionMatrix.M22,
    Z = -1.0f,
    W = (1.0f + projectionMatrix.M33) / projectionMatrix.M43
};

and 

```cpp
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;

has to be

projectionMatrix.M13 = c.X;
projectionMatrix.M23 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M43 = c.W;

If you want an asymmetric perspective projection, then consider to to create the perojection matrix by Matrix4.CreatePerspectiveOffCenter.

public Matrix4 GetProjectionMatrix()
{
    var offset_x  = -0.0f; 
    var offset_y  = -0.005f; // just for instance
    var tan_fov_2 = Math.Tan(_fov / 2.0);

    var near   = 0.01f;
    var far    = 100.0f; 
    var left   = -near * AspectRatio * tan_fov_2 + offset_x;
    var right  =  near * AspectRatio * tan_fov_2 + offset_x;
    var bottom = -near * tan_fov_2 + offset_y;
    var top    =  near * tan_fov_2 + offset_y;

    return Matrix4.CreatePerspectiveOffCenter(left, right, bottom, top, near, far);
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Hey, thanks for the reply! this indeed fixes the algorithm but isn't doing what I thought it was supposed to do, I'm just looking to do a lense shift as described here: https://docs.unity3d.com/Manual/PhysicalCameras.html – Khal May 09 '20 at 16:26
  • I appreciate the effort @Rabbid76 :) – Khal May 09 '20 at 16:34
  • @Khal Consider to use [`Matrix4.CreatePerspectiveOffCenter`](https://opentk.net/api/OpenTK.Matrix4.html#OpenTK_Matrix4_CreatePerspectiveOffCenter_System_Single_System_Single_System_Single_System_Single_System_Single_System_Single_). I've add an suggestion to the answer. – Rabbid76 May 09 '20 at 16:48
  • Yup! that's exactly what I was looking for! Thanks a Million!!!!! – Khal May 09 '20 at 16:52