matrix inversion help for opengl errors - c++

I am trying to get the inverse of a 4x4 square matrix for opengl, so it is a column major matrix. Also I would like to avoid discussions about making my code into loops, it's quite challenging enough to follow without loops.
I wrote some code that can do most basic matrix operations but matrix inverse was kinda rough, I found this answer: inverting a 4x4 matrix
I implemented it in my code
void mat4inverse(mat4* out, const mat4* in)
{
double inv[16], det;
int i;
inv[0] = in->m[5] * in->m[10] * in->m[15] -
in->m[5] * in->m[11] * in->m[14] -
in->m[9] * in->m[6] * in->m[15] +
in->m[9] * in->m[7] * in->m[14] +
in->m[13] * in->m[6] * in->m[11] -
in->m[13] * in->m[7] * in->m[10];
inv[4] = -in->m[4] * in->m[10] * in->m[15] +
in->m[4] * in->m[11] * in->m[14] +
in->m[8] * in->m[6] * in->m[15] -
in->m[8] * in->m[7] * in->m[14] -
in->m[12] * in->m[6] * in->m[11] +
in->m[12] * in->m[7] * in->m[10];
inv[8] = in->m[4] * in->m[9] * in->m[15] -
in->m[4] * in->m[11] * in->m[13] -
in->m[8] * in->m[5] * in->m[15] +
in->m[8] * in->m[7] * in->m[13] +
in->m[12] * in->m[5] * in->m[11] -
in->m[12] * in->m[7] * in->m[9];
inv[12] = -in->m[4] * in->m[9] * in->m[14] +
in->m[4] * in->m[10] * in->m[13] +
in->m[8] * in->m[5] * in->m[14] -
in->m[8] * in->m[6] * in->m[13] -
in->m[12] * in->m[5] * in->m[10] +
in->m[12] * in->m[6] * in->m[9];
inv[1] = -in->m[1] * in->m[10] * in->m[15] +
in->m[1] * in->m[11] * in->m[14] +
in->m[9] * in->m[2] * in->m[15] -
in->m[9] * in->m[3] * in->m[14] -
in->m[13] * in->m[2] * in->m[11] +
in->m[13] * in->m[3] * in->m[10];
inv[5] = in->m[0] * in->m[10] * in->m[15] -
in->m[0] * in->m[11] * in->m[14] -
in->m[8] * in->m[2] * in->m[15] +
in->m[8] * in->m[3] * in->m[14] +
in->m[12] * in->m[2] * in->m[11] -
in->m[12] * in->m[3] * in->m[10];
inv[9] = -in->m[0] * in->m[9] * in->m[15] +
in->m[0] * in->m[11] * in->m[13] +
in->m[8] * in->m[1] * in->m[15] -
in->m[8] * in->m[3] * in->m[13] -
in->m[12] * in->m[1] * in->m[11] +
in->m[12] * in->m[3] * in->m[9];
inv[13] = in->m[0] * in->m[9] * in->m[14] -
in->m[0] * in->m[10] * in->m[13] -
in->m[8] * in->m[1] * in->m[14] +
in->m[8] * in->m[2] * in->m[13] +
in->m[12] * in->m[1] * in->m[10] -
in->m[12] * in->m[2] * in->m[9];
inv[2] = in->m[1] * in->m[6] * in->m[15] -
in->m[1] * in->m[7] * in->m[14] -
in->m[5] * in->m[2] * in->m[15] +
in->m[5] * in->m[3] * in->m[14] +
in->m[13] * in->m[2] * in->m[7] -
in->m[13] * in->m[3] * in->m[6];
inv[6] = -in->m[0] * in->m[6] * in->m[15] +
in->m[0] * in->m[7] * in->m[14] +
in->m[4] * in->m[2] * in->m[15] -
in->m[4] * in->m[3] * in->m[14] -
in->m[12] * in->m[2] * in->m[7] +
in->m[12] * in->m[3] * in->m[6];
inv[10] = in->m[0] * in->m[5] * in->m[15] -
in->m[0] * in->m[7] * in->m[13] -
in->m[4] * in->m[1] * in->m[15] +
in->m[4] * in->m[3] * in->m[13] +
in->m[12] * in->m[1] * in->m[7] -
in->m[12] * in->m[3] * in->m[5];
inv[14] = -in->m[0] * in->m[5] * in->m[14] +
in->m[0] * in->m[6] * in->m[13] +
in->m[4] * in->m[1] * in->m[14] -
in->m[4] * in->m[2] * in->m[13] -
in->m[12] * in->m[1] * in->m[6] +
in->m[12] * in->m[2] * in->m[5];
inv[3] = -in->m[1] * in->m[6] * in->m[11] +
in->m[1] * in->m[7] * in->m[10] +
in->m[5] * in->m[2] * in->m[11] -
in->m[5] * in->m[3] * in->m[10] -
in->m[9] * in->m[2] * in->m[7] +
in->m[9] * in->m[3] * in->m[6];
inv[7] = in->m[0] * in->m[6] * in->m[11] -
in->m[0] * in->m[7] * in->m[10] -
in->m[4] * in->m[2] * in->m[11] +
in->m[4] * in->m[3] * in->m[10] +
in->m[8] * in->m[2] * in->m[7] -
in->m[8] * in->m[3] * in->m[6];
inv[11] = -in->m[0] * in->m[5] * in->m[11] +
in->m[0] * in->m[7] * in->m[9] +
in->m[4] * in->m[1] * in->m[11] -
in->m[4] * in->m[3] * in->m[9] -
in->m[8] * in->m[1] * in->m[7] +
in->m[8] * in->m[3] * in->m[5];
inv[15] = in->m[0] * in->m[5] * in->m[10] -
in->m[0] * in->m[6] * in->m[9] -
in->m[4] * in->m[1] * in->m[10] +
in->m[4] * in->m[2] * in->m[9] +
in->m[8] * in->m[1] * in->m[6] -
in->m[8] * in->m[2] * in->m[5];
det = in->m[0] * inv[0] + in->m[1] * inv[4] + in->m[2] * inv[8] + in->m[3] * inv[12];
if (det == 0)
printf("oh oh!");
det = 1.0 / det;
//printf("\n\ndeterminant:%f\n\n",det);
for (i = 0; i < 16; i++)
out->m[i] = inv[i] * det;
}
I create a matrix that looks like this:
[ 1.000000 3.000000 4.000000 9.000000 ]
[ 5.000000 6.000000 7.000000 2.000000 ]
[ 8.000000 8.000000 8.000000 9.000000 ]
[ 0.000000 0.000000 0.000000 1.000000 ]
after passing it to my transpose function that I listed above the results are:
[ -1.000000 1.000000 -0.375000 10.375000 ]
[ 2.000000 -3.000000 1.625000 -26.625000 ]
[ -1.000000 2.000000 -1.125000 15.125000 ]
[ 0.000000 0.000000 0.000000 1.000000 ]
I am not sure but that seems a bit wrong to me. This is for opengl rendering and my matrix is a 1D 16 double array.
Am I getting correct results?
additional info
Here is my math over on code review: https://codereview.stackexchange.com/questions/98692/4d-matrix-math-library-for-use-with-opengl

Related

Issue with 3d rotation along the X axis

I'm working on a project that required a 3d cube to be rotated along 3 axes. The cube is made up of 12 triangles, each with an instance of the Triangle class. Each triangle has a p0, p1, and p2 with the type sf::Vector3f. The triangles also have a float* position and a float* rotation. The position and rotation of a triangle is updated using this method.
void Triangle::update() {
position;
p0 = originalP0;
p1 = originalP1;
p2 = originalP2;
sf::Vector3f rotatedP0;
sf::Vector3f rotatedP1;
sf::Vector3f rotatedP2;
// along z
rotatedP0.x = p0.x * cos((*rotation).z * 0.0174533) - p0.y * sin((*rotation).z * 0.0174533);
rotatedP0.y = p0.x * sin((*rotation).z * 0.0174533) + p0.y * cos((*rotation).z * 0.0174533);
rotatedP0.z = p0.z;
rotatedP1.x = p1.x * cos((*rotation).z * 0.0174533) - p1.y * sin((*rotation).z * 0.0174533);
rotatedP1.y = p1.x * sin((*rotation).z * 0.0174533) + p1.y * cos((*rotation).z * 0.0174533);
rotatedP1.z = p1.z;
rotatedP2.x = p2.x * cos((*rotation).z * 0.0174533) - p2.y * sin((*rotation).z * 0.0174533);
rotatedP2.y = p2.x * sin((*rotation).z * 0.0174533) + p2.y * cos((*rotation).z * 0.0174533);
rotatedP2.z = p2.z;
p0 = rotatedP0;
p1 = rotatedP1;
p2 = rotatedP2;
// along y
rotatedP0.x = p0.x * cos((*rotation).y * 0.0174533) + originalP0.z * sin((*rotation).y * 0.0174533);
rotatedP0.y = p0.y;
rotatedP0.z = p0.x * -sin((*rotation).y * 0.0174533) + originalP0.z * cos((*rotation).y * 0.0174533);
rotatedP1.x = p1.x * cos((*rotation).y * 0.0174533) + originalP1.z * sin((*rotation).y * 0.0174533);
rotatedP1.y = p1.y;
rotatedP1.z = p1.x * -sin((*rotation).y * 0.0174533) + originalP1.z * cos((*rotation).y * 0.0174533);
rotatedP2.x = p2.x * cos((*rotation).y * 0.0174533) + originalP2.z * sin((*rotation).y * 0.0174533);
rotatedP2.y = p2.y;
rotatedP2.z = p2.x * -sin((*rotation).y * 0.0174533) + originalP2.z * cos((*rotation).y * 0.0174533);
p0 = rotatedP0;
p1 = rotatedP1;
p2 = rotatedP2;
// along x
rotatedP0.x = p0.x;
rotatedP0.y = p0.y * cos((*rotation).x * 0.0174533) - p0.z * sin((*rotation).x * 0.0174533);
rotatedP0.z = p0.y * sin((*rotation).x * 0.0174533) + p0.z * cos((*rotation).x * 0.0174533);
rotatedP1.x = p1.x;
rotatedP1.y = p1.y * cos((*rotation).x * 0.0174533) - p1.z * sin((*rotation).x * 0.0174533);
rotatedP1.z = p1.y * sin((*rotation).x * 0.0174533) + p1.z * cos((*rotation).x * 0.0174533);
rotatedP2.x = p2.x;
rotatedP2.y = p2.y * cos((*rotation).x * 0.0174533) - p2.z * sin((*rotation).x * 0.0174533);
rotatedP2.z = p2.y * sin((*rotation).x * 0.0174533) + p2.z * cos((*rotation).x * 0.0174533);
p0 = rotatedP0 + *position;
p1 = rotatedP1 + *position;
p2 = rotatedP2 + *position;
}
This method works well for all axes except the X axis. The cube has two red faces intersecting the Z axis, two green faces intersecting the Y axis, and two blue faces intersecting the X axis. Rotating the cube along the Z and Y axes works fine. The cube is rotating around the red and green faces. When rotating along the X axis, the cube is not rotated around the blue faces, but rather the global X axis.
Am I doing something wrong? Is it supposed to be this way? Is there any way to fix it? I searched all over and couldn't find anything helpful.
bro you did it all wrong. use this 3D point rotation algorithm. i know it is javascript but the math still the same

Rotation around axis other than X makes 3D object flat

In my program I'm loading a cube from a GLTF file and display it using my own implementation of math objects like vectors, matrices, and quaternions.
That's what my program draws when I try to rotate the cube:
The X rotation:
and the Y rotation:
as you can see the Y rotation looks like if my cube was flat.
I tried to find the culprit but for now it eludes me. But I'm 100% sure that:
it is not the GLTF loader fault as my tests shows me the data for the cube is loaded right
it is not my math module fault as my tests again tell me the calculations are done right
it only happens when I try to rotate around Y and Z axis. The X axis rotation somehow doesn't have got this problem
The only thing that I'm not sure are shaders. But my shader code is the simplest possible:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
uniform mat4 projection;
uniform mat4 view;
out vec3 fragNormal;
out float distance;
void main()
{
gl_Position = projection * view * vec4(position, 1.0);
vec4 tmp = view * vec4(position, 1.0);
distance = tmp.z + 10.0;
fragNormal = normal;
}
#version 330 core
in vec3 fragNormal;
in float distance;
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f) * distance;
}
I really don't know where else could I look. Also, I wish to give you my code for the rest of my program, but at this point it would be plain impossible to put it in this post as my program has many lines of code.
So, how this error might happen?
EDIT:
My projection matrix is standard perspective with fov=45°, near=0.1, far=100.0 :
|1.29996 0 0 0 |
|0 2.41421 0 0 |
|0 0 -1.002 -0.2002 |
|0 0 -1 0 |
The view matrix changes: it is a translation matrix (x=0,y=0,z=-10) multiplied (from the right) with a rotation matrix (in the below listing around Y axis by some degree)
| 0.5 0 0 0 |
| 0 1 0 0 |
| -0.866026 0 0.5 -10 |
| 0 0 0 1 |
Rotation is taken from a quaternion, but it can also be calculated from a rotation matrix directly. The error happens no mater how I calculate the rotation matrix.
I've found where lies the error: in the multiplication method of the matrix class. Somehow this code:
mat4 operator* (const mat4& other) const {
T _c11 = c11 * other.c11 + c12 * other.c21 + c13 * other.c31 + c14 * other.c41;
T _c12 = c11 * other.c12 + c12 * other.c22 + c13 * other.c32 + c14 * other.c42;
T _c13 = c11 * other.c13 + c12 * other.c23 + c13 * other.c33 + c14 * other.c43;
T _c14 = c11 * other.c14 + c12 * other.c24 + c13 * other.c34 + c14 * other.c44;
T _c21 = c21 * other.c11 + c22 * other.c21 + c23 * other.c31 + c24 * other.c41;
T _c22 = c21 * other.c12 + c22 * other.c22 + c23 * other.c32 + c24 * other.c42;
T _c23 = c21 * other.c13 + c22 * other.c23 + c23 * other.c33 + c24 * other.c43;
T _c24 = c21 * other.c14 + c22 * other.c24 + c23 * other.c34 + c24 * other.c44;
T _c31 = c31 * other.c11 + c32 * other.c21 + c33 * other.c31 + c34 * other.c41;
T _c32 = c31 * other.c12 + c32 * other.c22 + c33 * other.c32 + c34 * other.c42;
T _c33 = c31 * other.c13 + c32 * other.c23 + c33 * other.c33 + c34 * other.c43;
T _c34 = c31 * other.c14 + c32 * other.c24 + c33 * other.c34 + c34 * other.c44;
T _c41 = c41 * other.c11 + c42 * other.c21 + c43 * other.c31 + c44 * other.c41;
T _c42 = c41 * other.c12 + c42 * other.c22 + c43 * other.c32 + c44 * other.c42;
T _c43 = c41 * other.c13 + c42 * other.c23 + c43 * other.c33 + c44 * other.c43;
T _c44 = c41 * other.c14 + c42 * other.c24 + c43 * other.c34 + c44 * other.c44;
return mat4{_c11, c12, c13, _c14,
_c21, _c22, _c23, _c24,
_c31, _c32, _c33, _c34,
_c41, _c42, _c43, _c44};
}
wasn't working like this code:
mat4 operator* (const mat4& other) const {
mat4<T> result;
result.c11 = c11 * other.c11 + c12 * other.c21 + c13 * other.c31 + c14 * other.c41;
result.c12 = c11 * other.c12 + c12 * other.c22 + c13 * other.c32 + c14 * other.c42;
result.c13 = c11 * other.c13 + c12 * other.c23 + c13 * other.c33 + c14 * other.c43;
result.c14 = c11 * other.c14 + c12 * other.c24 + c13 * other.c34 + c14 * other.c44;
result.c21 = c21 * other.c11 + c22 * other.c21 + c23 * other.c31 + c24 * other.c41;
result.c22 = c21 * other.c12 + c22 * other.c22 + c23 * other.c32 + c24 * other.c42;
result.c23 = c21 * other.c13 + c22 * other.c23 + c23 * other.c33 + c24 * other.c43;
result.c24 = c21 * other.c14 + c22 * other.c24 + c23 * other.c34 + c24 * other.c44;
result.c31 = c31 * other.c11 + c32 * other.c21 + c33 * other.c31 + c34 * other.c41;
result.c32 = c31 * other.c12 + c32 * other.c22 + c33 * other.c32 + c34 * other.c42;
result.c33 = c31 * other.c13 + c32 * other.c23 + c33 * other.c33 + c34 * other.c43;
result.c34 = c31 * other.c14 + c32 * other.c24 + c33 * other.c34 + c34 * other.c44;
result.c41 = c41 * other.c11 + c42 * other.c21 + c43 * other.c31 + c44 * other.c41;
result.c42 = c41 * other.c12 + c42 * other.c22 + c43 * other.c32 + c44 * other.c42;
result.c43 = c41 * other.c13 + c42 * other.c23 + c43 * other.c33 + c44 * other.c43;
result.c44 = c41 * other.c14 + c42 * other.c24 + c43 * other.c34 + c44 * other.c44;
return result;
}
Probably I hit some compilator implementation detail.

OpenGL Matrix Multiplication C++

So I am trying to multiply rotation and translation matrices together and I can't quite figure out what is going wrong.
If, in the program I multiply a translation matrix by a rotation matrix then send that matrix as a uniform to my shader program I end up with the object becoming 2D then 3D again as it spins [ https://a.pomf.se/xvvrsg.mp4 ] (object on the right).
shader.setUniformMat4("model_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f)) * Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f)));
(vertex shader)
#version 330 core
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec4 in_normal;
uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);
uniform mat4 model_matrix = mat4(1.0);
out vec4 pos;
out vec4 normal;
void main()
{
pos = pr_matrix * vw_matrix * model_matrix * in_position;
normal = in_normal;
gl_Position = pos;
}
However if I send my individual translation and rotation matrices as separate uniforms and then multiply them in the shader to create my model matrix it works as intended [ https://a.pomf.se/jyxpnb.mp4 ] (object on the right).
shader.setUniformMat4("translation_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f)));
shader.setUniformMat4("rotation_matrix", Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f)));
shader.setUniformMat4("scale_matrix", Matrix4::identity());
(vertex shader)
#version 330 core
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec4 in_normal;
uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);
uniform mat4 translation_matrix = mat4(1.0);
uniform mat4 rotation_matrix = mat4(1.0);
uniform mat4 scale_matrix = mat4(1.0);
out vec4 pos;
out vec4 normal;
void main()
{
mat4 model_matrix = translation_matrix * rotation_matrix * scale_matrix;
pos = pr_matrix * vw_matrix * model_matrix * in_position;
normal = in_normal;
gl_Position = pos;
}
This leads me to believe that there must be an error in my multiplication of matrices, this is how I am currently doing it:
Matrix4 &Matrix4::multiply(const Matrix4 &other)
{
elements[0] = elements[0] * other.elements[0] + elements[4] * other.elements[1] + elements[8] * other.elements[2] + elements[12] * other.elements[3];
elements[1] = elements[1] * other.elements[0] + elements[5] * other.elements[1] + elements[9] * other.elements[2] + elements[13] * other.elements[3];
elements[2] = elements[2] * other.elements[0] + elements[6] * other.elements[1] + elements[10] * other.elements[2] + elements[14] * other.elements[3];
elements[3] = elements[3] * other.elements[0] + elements[7] * other.elements[1] + elements[11] * other.elements[2] + elements[15] * other.elements[3];
elements[4] = elements[0] * other.elements[4] + elements[4] * other.elements[5] + elements[8] * other.elements[6] + elements[12] * other.elements[7];
elements[5] = elements[1] * other.elements[4] + elements[5] * other.elements[5] + elements[9] * other.elements[6] + elements[13] * other.elements[7];
elements[6] = elements[2] * other.elements[4] + elements[6] * other.elements[5] + elements[10] * other.elements[6] + elements[14] * other.elements[7];
elements[7] = elements[3] * other.elements[4] + elements[7] * other.elements[5] + elements[11] * other.elements[6] + elements[15] * other.elements[7];
elements[8] = elements[0] * other.elements[8] + elements[4] * other.elements[9] + elements[8] * other.elements[10] + elements[12] * other.elements[11];
elements[9] = elements[1] * other.elements[8] + elements[5] * other.elements[9] + elements[9] * other.elements[10] + elements[13] * other.elements[11];
elements[10] = elements[2] * other.elements[8] + elements[6] * other.elements[9] + elements[10] * other.elements[10] + elements[14] * other.elements[11];
elements[11] = elements[3] * other.elements[8] + elements[7] * other.elements[9] + elements[11] * other.elements[10] + elements[15] * other.elements[11];
elements[12] = elements[0] * other.elements[12] + elements[4] * other.elements[13] + elements[8] * other.elements[14] + elements[12] * other.elements[15];
elements[13] = elements[1] * other.elements[12] + elements[5] * other.elements[13] + elements[9] * other.elements[14] + elements[13] * other.elements[15];
elements[14] = elements[2] * other.elements[12] + elements[6] * other.elements[13] + elements[10] * other.elements[14] + elements[14] * other.elements[15];
elements[15] = elements[3] * other.elements[12] + elements[7] * other.elements[13] + elements[11] * other.elements[14] + elements[15] * other.elements[15];
return *this;
}
I did have a nested loop to do this but I ended up writing it all out while trying to find out an answer to this problem. Bear in mind the matrices are in column major and do not get transposed by OpenGL
The rotation and translation matrices are as follows but I don't believe there is any problem with them:
Matrix4 Matrix4::translation(const Vector3 &translation)
{
Matrix4 result(1.0f);
result.elements[0 + 3 * 4] = translation.x;
result.elements[1 + 3 * 4] = translation.y;
result.elements[2 + 3 * 4] = translation.z;
return result;
}
Matrix4 Matrix4::rotation(float angle, const Vector3 &axis)
{
Matrix4 result(1.0f);
float r = toRadians(angle);
float c = (float)cos(r);
float s = (float)sin(r);
float cFlip = 1.0f - c;
result.elements[0 + 0 * 4] = axis.x * cFlip + c;
result.elements[1 + 0 * 4] = axis.y * axis.x * cFlip + axis.z * s;
result.elements[2 + 0 * 4] = axis.x * axis.z * cFlip - axis.y * s;
result.elements[0 + 1 * 4] = axis.x * axis.y * cFlip - axis.z * s;
result.elements[1 + 1 * 4] = axis.y * cFlip + c;
result.elements[2 + 1 * 4] = axis.y * axis.z * cFlip + axis.x * s;
result.elements[0 + 2 * 4] = axis.x * axis.y * cFlip + axis.y * s;
result.elements[1 + 2 * 4] = axis.y * axis.z * cFlip - axis.x * s;
result.elements[2 + 2 * 4] = axis.z * cFlip + c;
return result;
}
Any ideas on what the problem here could be or how to fix it would be greatly appreciated :^)
At your multiply function, you wrote:
elements[0] = elements[0] * other.elements[0] ...
...
Notice that element[0] got its contents actualized now and then you do:
elements[8] = elements[0] * other.elements[8] ...
which use the new value and not the original one. I guess, you want to make a copy of your original matrix before doing this multiplication
opssss !! i just saw !!!
in your multiply, your output matrice is the first input matrix, so the latest operations are calculated with coefficient of the multiplied matrix !! :
elements[0] = elements[0] * .....
....
elements[4] = elements[0] * ..... /* here element[ 0 ] is the top left
element of the multiplied matix */
moreover, operator* shouldn't modfify (nor return) one of his operand, operator*= is here for that

Need documentation that describes the output of OpenGL's rotate method

I have created a custom cube whose sides can be removed. I would eventually like to print the cube to a paper printer. I would like to do my own rotation by using the output from the OpenGL rotate method.
My question: Does documentation exist that describes the Identity Matrix after a rotation? Or is the source available for the OpenGL rotate method?
glRotate creates a rotation matrix and multiplies that in place on the matrix on top of the current matrix stack. Rotation matrices are a well known thing in linear algebra.
You can read about Matrix calculations and Matrix Transformations all over the internet, here is a few links.
Matrix Mathematics
Transformation Matrix
OpenGL Programming/3D/Matrices
Though here is something I've created for calculating exactly what you're trying to calculate. There isn't much so explain because it is basically just a bunch of math formulas.
public class Matrix4
{
public float m00, m01, m02, m03;
public float m10, m11, m12, m13;
public float m20, m21, m22, m23;
public float m30, m31, m32, m33;
public Matrix4()
{
this.set(
1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
0f, 0f, 0f, 1f);
}
public void rotate(float angle, float x, float y, float z)
{
float sin = (float) Math.sin(angle);
float cos = (float) Math.cos(angle);
if ((x * x + y * y + z * z) != 1f)
{
float length = (float) Math.sqrt(x * x + y * y + z * z);
if (length > 0f)
{
length = 1f / length;
x *= length;
y *= length;
z *= length;
}
}
this.mul(
x * x * (1f - cos) + cos, x * y * (1f - cos) - z * sin, x * z * (1f - cos) + y * sin, 0f,
y * x * (1f - cos) + z * sin, y * y * (1f - cos) + cos, y * z * (1f - cos) - x * sin, 0f,
x * z * (1f - cos) - y * sin, y * z * (1f - cos) + x * sin, z * z * (1f - cos) + cos, 0f,
0f, 0f, 0f, 1f);
}
public void mul(
float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
float mm00 = this.m00 * m00 + this.m01 * m10 + this.m02 * m20 + this.m03 * m30;
float mm01 = this.m00 * m01 + this.m01 * m11 + this.m02 * m21 + this.m03 * m31;
float mm02 = this.m00 * m02 + this.m01 * m12 + this.m02 * m22 + this.m03 * m32;
float mm03 = this.m00 * m03 + this.m01 * m13 + this.m02 * m23 + this.m03 * m33;
float mm10 = this.m10 * m00 + this.m11 * m10 + this.m12 * m20 + this.m13 * m30;
float mm11 = this.m10 * m01 + this.m11 * m11 + this.m12 * m21 + this.m13 * m31;
float mm12 = this.m10 * m02 + this.m11 * m12 + this.m12 * m22 + this.m13 * m32;
float mm13 = this.m10 * m03 + this.m11 * m13 + this.m12 * m23 + this.m13 * m33;
float mm20 = this.m20 * m00 + this.m21 * m10 + this.m22 * m20 + this.m23 * m30;
float mm21 = this.m20 * m01 + this.m21 * m11 + this.m22 * m21 + this.m23 * m31;
float mm22 = this.m20 * m02 + this.m21 * m12 + this.m22 * m22 + this.m23 * m32;
float mm23 = this.m20 * m03 + this.m21 * m13 + this.m22 * m23 + this.m23 * m33;
float mm30 = this.m30 * m00 + this.m31 * m10 + this.m32 * m20 + this.m33 * m30;
float mm31 = this.m30 * m01 + this.m31 * m11 + this.m32 * m21 + this.m33 * m31;
float mm32 = this.m30 * m02 + this.m31 * m12 + this.m32 * m22 + this.m33 * m32;
float mm33 = this.m30 * m03 + this.m31 * m13 + this.m32 * m23 + this.m33 * m33;
this.m00 = mm00; this.m01 = mm01; this.m02 = mm02; this.m03 = mm03;
this.m10 = mm10; this.m11 = mm11; this.m12 = mm12; this.m13 = mm13;
this.m20 = mm20; this.m21 = mm21; this.m22 = mm22; this.m23 = mm23;
this.m30 = mm30; this.m31 = mm31; this.m32 = mm32; this.m33 = mm33;
}
public void set(
float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m03 = m03;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m20 = m20;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m30 = m30;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
}
}
The following will create an Identity Matrix Matrix4 m = new Matrix4();
Important do notice that the angle given in the rotate() function in Matrix4 is in radians where in OpenGL the glRotate() functions requires the angle to be in degrees.
Also if the Matrix is "opposite", when you are using it then simply before you use the Matrix for anything else calculate the Transpose of the matrix, and then you can use it.

How Calculate NORMAL in triangle strip

i have a problem with the lighting of my OPENGL projects.
I program on c++ using ECLIPSE.
I have a terrein construited by triangle strip. the code of my render is the follow:
HeightMap::~HeightMap(void) {
}
float HeightMap::getScaledGrayColor(double height) {
float fColor = NULL;
if (height == this->NODATA_value) {
return 0.0f;
}
fColor = ((255.00f / max) * height) / 255.00f;
return fColor;
}
double* HeightMap::getHeights(int rowNumber) {
rowNumber = rowNumber + 6;
ifstream fin(this->filename);
string s;
long length;
fin.seekg(0, ios::beg); // go to the first line
for (int i = 0; i < rowNumber; i++) { // loop 'till the desired line
getline(fin, s);
}
string nextToken;
getline(fin, nextToken);
StringUtils stringUtils;
vector<string> tempVec = stringUtils.split(nextToken, " ");
double* heights = new double[this->ncols];
for (int i = 0; i < tempVec.size() - 1; i++) {
heights[i] = strtod(tempVec[i].c_str(), NULL);
}
return heights;
}
void HeightMap::Render(void)
{
int x = 0;
int i = 0;
for (int i = 0, j = 0; j < nrows; i--, j++) {
//cout<<"valore di i è: "<<i<<endl;
//cout<<"valore di j è: "<<j<<endl;
double * rowHeights = this->getHeights(j);//
for (int x = 0; x < ncols; x++) {
float color = getScaledGrayColor(rowHeights[x]);
double * Quote = this->getHeights(x);
glBegin(GL_TRIANGLE_STRIP);
glColor3f(color, color, color);
//triangolo ABC
//glNormal3f((x * cellsize), (i * cellsize), 0);
glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base
//glNormal3f((x * cellsize), ((i * cellsize) + cellsize), 0);
glVertex3f((x * cellsize), ((i * cellsize) + cellsize),
0);//vertice base
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+
(cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)
+ (cellsize / 2)), *Quote);//vertice altezza
//triangolo DEF
//glNormal3f((x * cellsize), (i * cellsize) + cellsize, 0);
glVertex3f((x * cellsize), (i * cellsize) + cellsize, 0);
//vertice base
//glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize,
0);//vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize,
0);//vertice base
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+
(cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)
+ (cellsize / 2)),
*Quote);//vertice altezza
//triangolo GHI
//glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize,
0); //vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize,
0); //vertice base
//glNormal3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice
base
glVertex3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice
base
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+
(cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)
+ (cellsize / 2)),
*Quote);//vertice altezza
//triangolo LMN
//glNormal3f((x * cellsize), (i * cellsize), 0); //vertice base
glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base
//glNormal3f((x * cellsize) + cellsize, (i * cellsize),
0);//vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice
base
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+
(cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)
+ (cellsize / 2)),
*Quote);//vertice altezza
glEnd();
}
//}
}
}
i try to use a normal for vertex but i don't know how calculate the argument of glnormal function.
Then i must use a normal for face.
Can you help me with this problem?
yes, i need normal by face and after i must do normal by vertex:
for normal by face i do this
void HeightMap::Render(void)
{
int x = 0;
int i = 0;
glPushMatrix();
glRotatef(angle, xrot, yrot, zrot);//rotate the object
cout<<"valore di nrows è: "<getHeights(j);
float vectorba[3]={0.0,0.0,0.0};
float vectorcb[3]={0.0,0.0,0.0};
float xnormal = 0.0;
float ynormal = 0.0;
float znormal = 0.0;
float len=0.0;
for (int x = 0; x < ncols; x++) {
//if (rowHeights[x] != this->NODATA_value) {
float color = getScaledGrayColor(rowHeights[x]);
double * Quote = this->getHeights(x);
glBegin(GL_TRIANGLE_STRIP);
glColor3f(color, color, color);
//triangolo ABC
//inizio normal
vectorba[0]={(x * cellsize)-(x * cellsize)};
vectorba[1]={((i * cellsize) + cellsize)-(i * cellsize)};
vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize)};
vectorcb[1]={((i * cellsize) + (cellsize / 2))-((i * cellsize) +cellsize)};
vectorcb[2]=*Quote;
// calculate the cross product and place the resulting vector
// into the variable xnormal,ynormal e znormal
xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]);
ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]);
znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]);
//fine normal
//inizio normalize
// calculate the length of the vector
len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal)));
// avoid division by 0
if (len == 0.0f)
len = 1.0f;
// reduce to unit size
xnormal /= len;
ynormal /= len;
znormal /= len;
//fine normalize
//glNormal3f((x * cellsize), (i * cellsize), 0); //normal per vertex. controllare la formula
glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base A
//glNormal3f((x * cellsize), ((i * cellsize) + cellsize), 0);
glVertex3f((x * cellsize), ((i * cellsize) + cellsize), 0);//vertice base B
glNormal3f(xnormal, ynormal, znormal); //normal per face
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)
+ (cellsize / 2)), *Quote);//vertice altezza C
//triangolo DEF
//inizio normal
vectorba[0]={(x * cellsize) + cellsize-(x * cellsize)};
vectorba[1]={((i * cellsize) + cellsize)-((i * cellsize) + cellsize)};
vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize};
vectorcb[1]={((i * cellsize)+ (cellsize / 2))-((i * cellsize) + cellsize)};
vectorcb[2]=*Quote;
// calculate the cross product and place the resulting vector
// into the variable xnormal,ynormal e znormal
xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]);
ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]);
znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]);
//fine normal
//inizio normalize
// calculate the length of the vector
len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal)));
// avoid division by 0
if (len == 0.0f)
len = 1.0f;
// reduce to unit size
xnormal /= len;
ynormal /= len;
znormal /= len;
//fine normalize
//glNormal3f((x * cellsize), (i * cellsize) + cellsize, 0);
glVertex3f((x * cellsize), (i * cellsize) + cellsize, 0); //vertice base D
//glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base E
glNormal3f(xnormal, ynormal, znormal); //normal per face
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza F
//triangolo GHI
//inizio normal
vectorba[0]={(x * cellsize) + cellsize-(x * cellsize) + cellsize};
vectorba[1]={i * cellsize-(i * cellsize) + cellsize};
vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize};
vectorcb[1]={((i * cellsize)+ (cellsize / 2))-(i * cellsize)};
vectorcb[2]=*Quote;
// calculate the cross product and place the resulting vector
// into the variable xnormal,ynormal e znormal
xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]);
ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]);
znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]);
//fine normal
//inizio normalize
// calculate the length of the vector
len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal)));
// avoid division by 0
if (len == 0.0f)
len = 1.0f;
// reduce to unit size
xnormal /= len;
ynormal /= len;
znormal /= len;
//fine normalize
//glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base G
//glNormal3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base
glVertex3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base H
glNormal3f(xnormal, ynormal, znormal); //normal per face
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza I
//triangolo LMN
//inizio normal
vectorba[0]={(x * cellsize) + cellsize-(x * cellsize)};
vectorba[1]={(i * cellsize)-(i * cellsize)};
vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize};
vectorcb[1]={((i * cellsize)+ (cellsize / 2))-(i * cellsize)};
vectorcb[2]=*Quote;
// calculate the cross product and place the resulting vector
// into the variable xnormal,ynormal e znormal
xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]);
ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]);
znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]);
//fine normal
//inizio normalize
// calculate the length of the vector
len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal)));
// avoid division by 0
if (len == 0.0f)
len = 1.0f;
// reduce to unit size
xnormal /= len;
ynormal /= len;
znormal /= len;
//fine normalize
//glNormal3f((x * cellsize), (i * cellsize), 0); //vertice base
glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base L
//glNormal3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base
glVertex3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base M
glNormal3f(xnormal, ynormal, znormal); //normal per face
//glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza
glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza N
glEnd();
}
//}
}
glPopMatrix();
}
the formulation is right?
how can i transform the Render using the function for normal and normalize?
If I understood, you want the normal by face?
If you have the triangle points you can calculate the normal for each face.
Take a look at this:
http://www.opengl.org/wiki/Calculating_a_Surface_Normal
The normal by vertex could be calculated taking the avg normals between faces.