4

So, I tried to use matrices in OpenTK, my "Transform" class has a Rotation (a quaternion) and a Vector3 for the position. It offers the folling fields:

    public virtual Vector3 Right
    {
        get
        {
            
            return Vector3.Transform(Vector3.UnitX, Rotation);
        }
    }
    public virtual Vector3 Forward
    {
        get 
        {
            return Vector3.Transform(-Vector3.UnitZ, Rotation);
        }
    }
    public virtual Vector3 Up
    {
        get
        {
            return Vector3.Transform(Vector3.UnitY, Rotation);
        }
    }

This is how the view and model matrices are creates:

    public virtual Matrix4 GetMatrix()
    {
        Matrix4 translation = Matrix4.CreateTranslation(Position);
        Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
        return translation * rotation;
    }

Projection:

    private void SetupProjection()
    {
        if(GameObject != null)
        {
            AspectRatio = GameObject.App.Window.Width / (float)GameObject.App.Window.Height;
            projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)((Math.PI * Fov) / 180), AspectRatio, ZNear, ZFar);
            
        }
    }

Matrix multiplication:

    public Matrix4 GetModelViewProjectionMatrix(Transform model)
    {
        return  model.GetMatrix()* Transform.GetMatrix() * projectionMatrix;
    }

Shader:

[Shader vertex]
#version 150 core

in vec3 pos;
in vec4 color;
uniform float _time;
uniform mat4 _modelViewProjection;

out vec4 vColor;

void main() {
    gl_Position = _modelViewProjection * vec4(pos, 1);
    vColor = color;
}

OpenTK matrices are transposed, thus the multiplication order.

The problem with this setup is, that all axis and the direction vectors as well object position are mixed up, mirrored and turned upside down.

Now after a lot of fiddling, I managed to get a useful transformation and ended up with the following:

I had to invert the quaternion for the directions:

    public virtual Vector3 Right
    {
        get
        {
            
            return Vector3.Transform(Vector3.UnitX, Rotation.Inverted());
        }
    }
    public virtual Vector3 Forward
    {
        get
        {
            return Vector3.Transform(-Vector3.UnitZ, Rotation.Inverted());
        }
    }
    public virtual Vector3 Up
    {
        get
        {
            return Vector3.Transform(Vector3.UnitY, Rotation.Inverted());
        }
    }

And I had to modify the view matrix construction like this:

    public virtual Matrix4 GetMatrixView()
    {
        Matrix4 translation = Matrix4.CreateTranslation(Position*2).Inverted();
        Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
        return translation * rotation;
    }

As you can see, I had to invert the translation matrix and multiply the position by two, to make the camera space match the worldspace. What the F ?

Edit: look at this. With the default/intuitional setup I get this:

[LOG]: (0; 0; 10) ->

[LOG]: FW(0; 0; -1)

[LOG]: R(-1; 0; 0)

[LOG]: UP(0; 1; 0)

Okay, I'm at Z 10, looking at 0,0,0. Forward is x -1, as expected. Up is Y 1, also okay. But the horizontal axis goes to the LEFT ? What kind of coordinate system is this ?

Community
  • 1
  • 1
pixartist
  • 1,137
  • 2
  • 18
  • 40
  • What are the values of your Position, Rotation, ZNear and ZFar? – vesan Jul 07 '14 at 22:58
  • znear is 1, zfar is 120. Position and Rotation are variable. But at startup position and rotation are identity and zero respectively. – pixartist Jul 07 '14 at 23:03
  • Zero rotation, so it's `Quaternion.Identity`? Otherwise it is strange, with identities for the MV matrix, your model should just be rendered wherever it is. Btw, you're doing `translation * rotation`, are you sure you want to translate first and then rotate? – vesan Jul 07 '14 at 23:11
  • Well, I want to translate the object by its position and then rotate by its rotation ?! Otherwise I would rotate the translation. PS: yes rotation is identity – pixartist Jul 07 '14 at 23:13
  • My point is, if you for example start at (0,0,0), translate by (-10,0,0), the rotate by 90 degrees around the Z axis, your object will be at (0,0,10). If you rotate then translate, your object will be rotated around its center and then translated to (-10,0,0). So, it will end up in a different place depending on the order of the transforms. – vesan Jul 07 '14 at 23:18
  • In OpenTK Matrices are transposed, see http://stackoverflow.com/questions/11452241/opentk-matrix-transformations edit: or do I have it wrong? When I switch them, the camera will rotate around the center (0,0,0), which seems to be exactly what I don't want – pixartist Jul 08 '14 at 00:49
  • Transform.GetMatrix()... GetMatrix() is a static method of your transform class? is that intentional? – David Carpenter Jul 15 '14 at 19:53

1 Answers1

2

You mention that the matrices are transposed, hence why the multiplication order is reversed. For example your MVP calc is:

model.GetMatrix()* Transform.GetMatrix() * projectionMatrix;

But your translation * rotation concatenation is in wrong order:

Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return translation * rotation;

With non-transposed matrices the correct multiplcation order is:

translation * rotation * scale

So with your transposed matrices, it should be reversed to:

scale * rotation * translation

So your code should be:

Matrix4 translation = Matrix4.CreateTranslation(Position);
Matrix4 rotation = Matrix4.CreateFromQuaternion(Rotation);
return rotation * translation;
kbirk
  • 3,906
  • 7
  • 48
  • 72
  • That causes the camera to turn around the 0,0 coordinate – pixartist Jul 16 '14 at 22:11
  • is GetMatrixView() supposed to return a view matrix? – kbirk Jul 16 '14 at 22:24
  • yes. But shouldnt the view matrix be calculated just like the model matrix for a mesh ? – pixartist Jul 16 '14 at 23:31
  • No the view matrix is assembled differently, here is a good link to look at: http://3dgep.com/understanding-the-view-matrix/ – kbirk Jul 17 '14 at 00:38
  • Okay, even though that tutorial uses row major matrices it helped. But now when I try to rotate the camera matrix (no view) around a local axis, the rotation is all messed up! I do the following to pitch the view: `LocalRotation *= Quaternion.FromAxisAngle(axis, angle);` using the axis `Vector3.Transform(Vector3.UnitX, Rotation)`. Should that be the local right vector ? – pixartist Jul 17 '14 at 21:40