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
Related
I've been following this tutorial to implement my variance shadow mapping feature for point light in deferred rendering.
I'm using GLSL 3.3, left-handed coordinate system. Here is what I've been doing:
I render the scene to dual-paraboloid maps, storing depth and depth * depth.
Result:
Above image contains front and back maps. The point light is at the center of scene, you can see where it glows yellow the most.
Then I set up a full-screen shader pass.
I do this by transforming the tutorial code from FX to GLSL.
Author's .fx code:
float4 TexturePS(float3 normalW : TEXCOORD0, float2 tex0 : TEXCOORD1, float3 pos : TEXCOORD2) : COLOR
{
float4 texColor = tex2D(TexS, tex0 * TexScale);
pos = mul(float4(pos, 1.0f), LightView);
float L = length(pos);
float3 P0 = pos / L;
float alpha = .5f + pos.z / LightAttenuation;
P0.z = P0.z + 1;
P0.x = P0.x / P0.z;
P0.y = P0.y / P0.z;
P0.z = L / LightAttenuation;
P0.x = .5f * P0.x + .5f;
P0.y = -.5f * P0.y + .5f;
float3 P1 = pos / L;
P1.z = 1 - P1.z;
P1.x = P1.x / P1.z;
P1.y = P1.y / P1.z;
P1.z = L / LightAttenuation;
P1.x = .5f * P1.x + .5f;
P1.y = -.5f * P1.y + .5f;
float depth;
float mydepth;
float2 moments;
if(alpha >= 0.5f)
{
moments = tex2D(ShadowFrontS, P0.xy).xy;
depth = moments.x;
mydepth = P0.z;
}
else
{
moments = tex2D(ShadowBackS, P1.xy).xy;
depth = moments.x;
mydepth = P1.z;
}
float lit_factor = (mydepth <= moments[0]);
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = min(max(E_x2 - Ex_2, 0.0) + SHADOW_EPSILON, 1.0);
float m_d = (moments.x - mydepth);
float p = variance / (variance + m_d * m_d); //Chebychev's inequality
texColor.xyz *= max(lit_factor, p + .2f);
return texColor;
}
My translated GLSL code:
void main() {
vec3 in_vertex = texture(scenePosTexture, texCoord).xyz; // get 3D vertex from 2D screen coordinate
vec4 vert = lightViewMat * vec4(in_vertex, 1); // project vertex to point light space (view from light position, look target is -Z)
float L = length(vert.xyz);
float distance = length(lightPos - in_vertex);
float denom = distance / lightRad + 1;
float attenuation = 1.0 / (denom * denom);
// to determine which paraboloid map to use
float alpha = vert.z / attenuation + 0.5f;
vec3 P0 = vert.xyz / L;
P0.z = P0.z + 1;
P0.x = P0.x / P0.z;
P0.y = P0.y / P0.z;
P0.z = L / attenuation;
P0.x = .5f * P0.x + .5f;
P0.y = -.5f * P0.y + .5f;
vec3 P1 = vert.xyz / L;
P1.z = 1 - P1.z;
P1.x = P1.x / P1.z;
P1.y = P1.y / P1.z;
P1.z = L / attenuation;
P1.x = .5f * P1.x + .5f;
P1.y = -.5f * P1.y + .5f;
// Variance shadow mapping
float depth;
float mydepth;
vec2 moments;
if(alpha >= 0.5f)
{
moments = texture(shadowMapFrontTexture, P0.xy).xy;
depth = moments.x;
mydepth = P0.z;
}
else
{
moments = texture(shadowMapBackTexture, P1.xy).xy;
depth = moments.x;
mydepth = P1.z;
}
// Original .fx code is: float lit_factor = (mydepth <= moments[0]);
// I'm not sure my translated code belew is correct
float lit_factor = 0;
if (mydepth <= moments.x)
lit_factor = mydepth;
else
lit_factor = moments.x;
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = min(max(E_x2 - Ex_2, 0.0) + SHADOW_EPSILON, 1.0);
float m_d = (moments.x - mydepth);
float p = variance / (variance + m_d * m_d); //Chebychev's inequality
fragColor = texture(sceneTexture, texCoord).rgb; // sample original color
fragColor.rgb *= max(lit_factor, p + .2f);
}
Render result
Right now I'm clueless about where I'm gonna touch to render the shadow correctly. Could someone point it out for me?
Some friend of mine pointed out that the Y component is flipped, that's why shadow looked like up-side down. After adding minus to P0 and P1's Y, it starts to show quite reasonable shadow:
But another problem is the location of shadow is wrong.
Why do you duplicate the paraboloid projection computation ?
You compute it on 'vert', then 'P0' and 'P1', shouldn't you do it only on 'P0' and 'P1' ? (The original code doesn't do this thing on 'pos').
EDIT:
Your lit_factor is wrong, it should be either 0.0 or 1.0.
You could use the step() GLSL intrinsic, in this way :
float lit_factor = step(mydepth, moments[0]);
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
I'm drawing a quad using Geometry Shader, but can't figure out how to rotate it with angle.
void main(void)
{
float scaleX = 2.0f / u_resolution.x;
float scaleY = 2.0f / u_resolution.y;
float nx = (u_position.x * scaleX) - 1.0f;
float ny = -(u_position.y * scaleY) + 1.0f;
float nw = u_size.x * scaleX;
float nh = u_size.y * scaleY;
gl_Position = vec4( nx+nw, ny, 0.0, 1.0 );
texcoord = vec2( 1.0, 0.0 );
EmitVertex();
gl_Position = vec4(nx, ny, 0.0, 1.0 );
texcoord = vec2( 0.0, 0.0 );
EmitVertex();
gl_Position = vec4( nx+nw, ny-nh, 0.0, 1.0 );
texcoord = vec2( 1.0, 1.0 );
EmitVertex();
gl_Position = vec4(nx, ny-nh, 0.0, 1.0 );
texcoord = vec2( 0.0, 1.0 );
EmitVertex();
EndPrimitive();
}
Should I use a rotation matrix or sin and cos? I'm not too great at math.
You don't have to use matrices, but you need to use those sine functions. Here is a way to rotate a 3D position about some arbitrary axis by some angle specified in degrees:
// This is the 3D position that we want to rotate:
vec3 p = position.xyz;
// Specify the axis to rotate about:
float x = 0.0;
float y = 0.0;
float z = 1.0;
// Specify the angle in radians:
float angle = 90.0 * 3.14 / 180.0; // 90 degrees, CCW
vec3 q;
q.x = p.x * (x*x * (1.0 - cos(angle)) + cos(angle))
+ p.y * (x*y * (1.0 - cos(angle)) + z * sin(angle))
+ p.z * (x*z * (1.0 - cos(angle)) - y * sin(angle));
q.y = p.x * (y*x * (1.0 - cos(angle)) - z * sin(angle))
+ p.y * (y*y * (1.0 - cos(angle)) + cos(angle))
+ p.z * (y*z * (1.0 - cos(angle)) + x * sin(angle));
q.z = p.x * (z*x * (1.0 - cos(angle)) + y * sin(angle))
+ p.y * (z*y * (1.0 - cos(angle)) - x * sin(angle))
+ p.z * (z*z * (1.0 - cos(angle)) + cos(angle));
gl_Position = vec4(q, 1.0);
If you know that you are rotating about some standard x-, y-, or z-axis, you can simplify the "algorithm" a lot by defining it explicitly for that standard axis.
Notice how we rotate about the z-axis in the above code. For example, rotation about the x-axis would be (x,y,z) = (1,0,0). You could set the variables to anything, but the values should result in the axis being a unit vector (if that even matters.)
Then again, you might as well use matrices:
vec3 n = vec3(0.0, 0.0, 1.0); // the axis to rotate about
// Specify the rotation transformation matrix:
mat3 m = mat3(
n.x*n.x * (1.0f - cos(angle)) + cos(angle), // column 1 of row 1
n.x*n.y * (1.0f - cos(angle)) + n.z * sin(angle), // column 2 of row 1
n.x*n.z * (1.0f - cos(angle)) - n.y * sin(angle), // column 3 of row 1
n.y*n.x * (1.0f - cos(angle)) - n.z * sin(angle), // column 1 of row 2
n.y*n.y * (1.0f - cos(angle)) + cos(angle), // ...
n.y*n.z * (1.0f - cos(angle)) + n.x * sin(angle), // ...
n.z*n.x * (1.0f - cos(angle)) + n.y * sin(angle), // column 1 of row 3
n.z*n.y * (1.0f - cos(angle)) - n.x * sin(angle), // ...
n.z*n.z * (1.0f - cos(angle)) + cos(angle) // ...
);
// Apply the rotation to our 3D position:
vec3 q = m * p;
gl_Position = vec4(q, 1.0);
Notice how the elements of the matrix are laid out such that we first complete the first column, and then the second, and so on; the matrix is in column-major order. This matters when you try to transfer a matrix written in mathematical notation into a data type in your code. You basically need to transpose it (to flip the elements diagonally) in order to use it in your code. Also, we are essentially multiplying a matrix on left with a column vector on right.
If you need a 4-by-4 homogeneous matrix, then you would simply add an extra column and a row into the above matrix, such that both the new rightmost column and bottommost row would consist of [0 0 0 1]:
vec4 p = position.xyzw; // new dimension
vec3 n = ...; // same
mat4 m = mat4( // new dimension
...
0.0,
...
0.0,
...
0.0,
0.0,
0.0,
0.0,
1.0
);
vec4 q = m * p;
gl_Position = q;
Again, notice the order of the multiplication when applying the rotation, it is important because it affects the end result. What happens in the multiplication is basically that a new vector is formed by calculating the dot-product of the position vector and each column in the matrix; each coordinate in the resulting vector is the dot-product of the original vector and a single column in the matrix (see the first code example.)
The
q.x = p.x * (x*x * (1.0 - cos(angle)) + cos(angle))
+ p.y * (x*y * (1.0 - cos(angle)) + z * sin(angle))
+ p.z * (x*z * (1.0 - cos(angle)) - y * sin(angle));
Is same as:
q.x = dot(p, m[0]);
One could even compose the matrix with itself: m = m*m; which would result in a 180-degree counterclockwise rotation matrix, depending on the angle used.
I use a quaternion to rotate the normal vector of a mesh into the direction the normal map vector. I thought I could use the Quaternion. So I create a quaternion with the angle between the normal of the mesh and (0,0,1). Shortened the methods in libgdx, creation of the Quaternion looks like this
vec4 createQuaternion(vec3 normal) {
float l_ang = acos(clamp(normal.z, -CONST_ONE, CONST_ONE))/CONST_TWO;
float l_sin = sin(l_ang);
return normalize(vec4(-normal.y * l_sin, normal.x * l_sin, CONST_ZERO, cos(l_ang)));
}
with this Quaternion I can rotate the normal of the mesh in the direction of the normal map. Therefore I use a method I've seen in the libgdx Quaternion (while v is the normal from the normalmap and m is the quaternion):
vec3 rotateNormal(vec3 v, vec4 m) {
vec4 tmp1 = vec4(v,CONST_ZERO);
vec4 tmp2 = vec4(m);
// conjugate
tmp2.x = -tmp2.x;
tmp2.y = -tmp2.y;
tmp2.z = -tmp2.z;
tmp2 = mulLeft(tmp1, tmp2);
tmp1 = mulLeft(m, tmp2);
v.x = tmp1.x;
v.y = tmp1.y;
v.z = tmp1.z;
return v;
}
The method mulLeft looks like that:
vec4 mulLeft(vec4 q, vec4 a) {
float newX = q.w * a.x + q.x * a.w + q.y * a.z - q.z * a.y;
float newY = q.w * a.y + q.y * a.w + q.z * a.x - q.x * a.z;
float newZ = q.w * a.z + q.z * a.w + q.x * a.y - q.y * a.x;
float newW = q.w * a.w - q.x * a.x - q.y * a.y - q.z * a.z;
a.x = newX;
a.y = newY;
a.z = newZ;
a.w = newW;
return a;
}
For the use in the shader I just call:
normal = rotateNormal(normalMap, createQuaternion(normalMesh));
and it works as expected.
The only thing I am considered about is that I can imagine that there is a shorter way to write that. Especially the mulLeft Method. Is there?
What do you think about the whole method, turning the vector by quaternion instead of using NTB?
ntb looks a bit like too much calculation while animating the mesh.
Edit:
This is the a test with my sourcecode
This is a Test with Tenfour's suggestion
Edit2:
I shortened the whole thing to:
vec3 rotateNormal(vec3 normalMap, vec3 normal) {
// create quaternion from cross(normal, vec3(0,0,1))
float l_ang = acos(clamp(normal.z, -CONST_ONE, CONST_ONE))/CONST_TWO;
float l_sin = sin(l_ang);
vec4 quat = normalize(vec4(-normal.y * l_sin, normal.x * l_sin, CONST_ZERO, cos(l_ang)));
// shortened function to double mulQuat the normalMap on the quaternion
return vec3(
quat.x*quat.x*normalMap.x - quat.y*quat.y*normalMap.x - quat.z*quat.z*normalMap.x + quat.w*quat.w*normalMap.x - CONST_TWO*quat.z*quat.w*normalMap.y + CONST_TWO*quat.y*quat.w*normalMap.z + CONST_TWO*quat.x *(quat.y*normalMap.y + quat.z*normalMap.z),
-(quat.x*quat.x*normalMap.y) - quat.z*quat.z* normalMap.y + (quat.y*quat.y + quat.w*quat.w ) * normalMap.y + CONST_TWO*quat.z *(quat.w*normalMap.x + quat.y*normalMap.z) + CONST_TWO*quat.x* (quat.y*normalMap.x - quat.w*normalMap.z),
quat.y*(-CONST_TWO*quat.w*normalMap.x + CONST_TWO*quat.z*normalMap.y) + CONST_TWO*quat.x*(quat.z*normalMap.x + quat.w*normalMap.y) - quat.x*quat.x*normalMap.z - quat.y*quat.y*normalMap.z + (quat.z*quat.z + quat.w*quat.w )* normalMap.z
);
}
Input is the normal from the normal map and the normal of the mesh.
I am sure there's something better than that. what could that be?
I found this
vec3 rotate_vector( vec4 quat, vec3 vec )
{
return vec + 2.0 * cross( cross( vec, quat.xyz ) + quat.w * vec, quat.xyz );
}
here. Does that work? Not sure how much less underlying math there is, but built-in GLSL functions can often take advantage of GPU optimizations.
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.