How Calculate NORMAL in triangle strip - opengl

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.

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

How to add vertical Gaussian blur

This is my Fragment shader code where i am applying gaussian blur to a Texture2D image.
vec3 incrementalGaussian;
incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * BlurValue );
incrementalGaussian.y = exp(-0.5f / (BlurValue * BlurValue ));
incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
float coefficientSum = 0.0f;
// Take the central sample first...
avgValue += texture2D(text, TexCoords.st) * incrementalGaussian.x;
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
//Go through the remaining 8 vertical samples (4 on each side of the center)
for (float i = 1.0f; i <= numBlurPixelsPerSide ; i++) {
avgValue += texture2D(text, TexCoords.st - i * 0.01f *
blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2D(text, TexCoords.st + i * 0.01f *
blurMultiplyVec) * incrementalGaussian.x;
coefficientSum += 2 * incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
avgValue.g = avgValue.r;
avgValue.b = avgValue.r;
color = avgValue * vec4(textColor, 1.0) / coefficientSum ;
}
this only applies a horizontal blur , How can i also add vertical Gaussian blur.
In general for the gaussian blur are used 2 passes. For the vertical blur, you've to add a 2nd pass. First do the horizontal blur, then apply the vertical blur to the result.
For the horizontal blur the u-component of the texture coordinate is displaced:
for (float i = 1.0f; i <= numBlurPixelsPerSide ; i++) {
float offset = i * 0.01f * blurMultiplyVec;
avgValue += texture2D(text, TexCoords.st - vec2(offset, 0.0) * incrementalGaussian.x;
avgValue += texture2D(text, TexCoords.st + vec2(offset, 0.0) * incrementalGaussian.x;
// ...
}
And for the vertical blur the v-component of the texture coordinate is displaced:
for (float i = 1.0f; i <= numBlurPixelsPerSide ; i++) {
float offset = i * 0.01f * blurMultiplyVec;
avgValue += texture2D(text, TexCoords.st - vec2(0.0, offset) * incrementalGaussian.x;
avgValue += texture2D(text, TexCoords.st + vec2(0.0, offset) * incrementalGaussian.x;
// ...
}
A related question is What kind of blurs can be implemented in pixel shaders?
There are a lot of good tutorials all over the web, e.g. LearnOpenGL.com - Gaussian blur

Most accurate way to calculate view frustum corners in world space

I'm trying to calculate the view frustum corners in world space. I've implemented it by using the FOV and using the width/height of the planes and some vector math
However, a lot of examples simply state that you can multiply a NDC corner like (1,1,1) by the inverse viewProjection matrix. But when I do this I get somewhat different results. This is the code I'm using right now to test things:
float nearHeight = 2 * tan(mFOV / 2) * mNear;
float nearWidth = mNear * mRatio;
float farHeight = 2 * tan(mFOV / 2) * mFar;
float farWidth = mFar * mRatio;
glm::vec3 fc = mPos + mFront * mFar;
glm::vec3 nc = mPos + mFront * mNear;
mFrustum.frustumCorners[0] = fc + (mUp * farHeight / 2.0f) - (mRight * farWidth / 2.0f);
mFrustum.frustumCorners[1] = fc + (mUp * farHeight / 2.0f) + (mRight * farWidth / 2.0f);
mFrustum.frustumCorners[2] = fc - (mUp * farHeight / 2.0f) - (mRight * farWidth / 2.0f);
mFrustum.frustumCorners[3] = fc - (mUp * farHeight / 2.0f) + (mRight * farWidth / 2.0f);
mFrustum.frustumCorners[4] = nc + (mUp * nearHeight / 2.0f) - (mRight * nearWidth / 2.0f);
mFrustum.frustumCorners[5] = nc + (mUp * nearHeight / 2.0f) + (mRight * nearWidth / 2.0f);
mFrustum.frustumCorners[6] = nc - (mUp * nearHeight / 2.0f) - (mRight * nearWidth / 2.0f);
mFrustum.frustumCorners[7] = nc - (mUp * nearHeight / 2.0f) + (mRight * nearWidth / 2.0f);
glm::vec4 test(1.0f, 1.0f, 1.0f,1.0f);
glm::vec4 test2(-1.0f, -1.0f, -1.0f, 1.0f);
glm::mat4 testingMatrix = glm::inverse(mProjectionMatrix * getViewMatrix());
test = testingMatrix*test;
test2 = testingMatrix*test2;
test2.x /= test2.w;
test2.y /= test2.w;
test2.z /= test2.w;
test.x /= test.w;
test.y /= test.w;
test.z /= test.w;
Now both of these results give an accurate z value for [near,far] = [1, 10000] but the x values are off by quite a bit while the y values are pretty much the same. I was just wonder which way is the most accurate one?
Inverse viewProjection
Regular calculation

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.