3
votes

At the moment, I convert the vec3 to vec4, multiply it with the matrix, and then cast it back to vec3

Code:

glm::vec3 transformed = glm::vec3(matrix * glm::vec4(point, 0.0))

It works, but I think it is not the good way to calculate it. Is it possible to apply a mat4 on a vec3, without casting it to vec4 and back?

2

2 Answers

5
votes

When working with OpenGL it is very wise to stick with homogeneous coordinates. For 3D space these are 4D vectors where normally the fourth element equals 1. When you do this all your calculations are in 4 dimensional space, so no conversions needed anywhere.

Also note that in your example, you will actually lose any translation that may have been recorded in the transformation matrix. If you want to keep this you'll need to use 1 for the 4th element, not 0.

Appendix F of the Red Book describes how and why homogeneous coordinates are used within OpenGL.

1
votes

mat4 is a 4 by 4 matrix, so you need a 4 dimension vector to multiply it.

That 4th dimension is really useful for 3D math, to distinguish between 3D space points (1) and 3D vectors (0)

Here I missing lots of operator, but I hope that you get the idea.

class point3
{
public:
    vec4 p;

public:
    point3();
    point3(const point3& rhs);
    point3(const point3& rhs);
    point3(float x, float y, float z);
    point3& operator=(const point3&rhs);
    vector3 operator-(const point3&rhs);
    point3 operator+(const vector3&rhs);
    point3& operator+=(const vector3&rhs);
};

point3::point3():p.x(0), p.y(0), p.z(0), p.w(1)
{

}
point3::point3(const point3& rhs):p(rhs.p)
{

}
point3::point3(const point3& rhs):p(rhs.p)
{

}
point3::point3(float x, float y, float z):p.x(x), p.y(y), p.z(z), p.w(1)
{

}
point3& point3::operator=(const point3&rhs)
{
    return (p=rhs.p);
}
vector3 point3::operator-(const point3&rhs)
{
    vector3 result;
    result.p=(p-rhs.p);
    return result;
}
point3 point3::operator+(const vector3&rhs)
{
    point3 result;
    result.p=(p+rhs.p);
    return result;
}
point3& point3::operator+=(const vector3&rhs)
{
    p=(p+rhs.p);
    return p;
}

class vector3
{
public:
    vec4 p;

public:
    vector3();
    vector3(const vector3& rhs);
    vector3(const vector3& rhs);
    vector3(float x, float y, float z);
    vector3& operator=(const vector3&rhs);
    vector3 operator-(const vector3&rhs);
    point3 operator-(const point3&rhs);
    point3 operator+(const point3&rhs);
    vector3 operator+(const vector3&rhs);
    vector3& operator+=(const vector3&rhs);
};
vector3::vector3():p.x(0), p.y(0), p.z(0), p.w(0)
{
}
vector3::vector3(const vector3& rhs):p(rhs.p)
{
}
vector3::vector3(const vector3& rhs):p(rhs.p)
{
}
vector3::vector3(float x, float y, float z):p.x(x), p.y(y), p.z(z), p.w(0)
{
}
vector3& vector3::operator=(const vector3&rhs)
{
    p=rhs.p;
    return p;
}
vector3 vector3::operator-(const vector3&rhs)
{
    vector3 result;
    result.p=(p-rhs.p);
    return result;
}
point3 vector3::operator-(const point3&rhs)
{
    point3 result;
    result.p=(p-rhs.p);
    return result;
}
point3 vector3::operator+(const point3&rhs)
{
    point3 result;
    result.p=(p+rhs.p);
    return result;
}
vector3 vector3::operator+(const vector3&rhs)
{
    vector3 result;
    result.p=(p+rhs.p);
    return result;
}
vector3& vector3::operator+=(const vector3&rhs)
{
    p=(p+rhs.p);
    return p;
}