Matrixmultiplication - Own Implementation of glTranslate? Wrong Matrix - opengl-es

Assuming I have the following Projection Matrix (its computed using gluPerspective(40, 1.0, 0.2, 200.0); on the identity matrix):
2.75, 0.00, 0.00, 0.00,
0.00, 2.75, 0.00, 0.00,
0.00, 0.00, -1.00, -1.00,
-0.00, -0.00, -0.40, -0.00
and want to do an glTranslatef(0.0, 0.0, -10.0); command on this matrix. With openGL ES 1.1 function I recieve (that seems correct in my opinion):
2.75, 0.00, 0.00, 0.00,
0.00, 2.75, 0.00, 0.00,
0.00, 0.00, -1.00, -1.00,
0.00, 0.00, 9.62, 10.00
But if I use my own implementation (openGL ES 2.0), I got some strange behavior:
2.75, 0.00, 0.00, 0.00,
0.00, 2.75, 0.00, 0.00,
0.00, 0.00, 9.00, -1.00,
0.00, 0.00, -0.40, 0.00
My code is quite similiar to Apples openGLES1/2 Example and this site http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html:
void Matrix::translate(GLfloat xTranslate, GLfloat yTranslate, GLfloat zTranslate){
GLfloat matrix[16];
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0;
matrix[1] = matrix[2] = matrix[3] = matrix[4] = 0.0;
matrix[6] = matrix[7] = matrix[8] = matrix[9] = 0.0;
matrix[11] = 0.0;
matrix[12] = xTranslate;
matrix[13] = yTranslate;
matrix[14] = zTranslate;
multiMatrix(matrix);
}
void Matrix::multiMatrix(const GLfloat* a){
GLfloat* matrix;
GLfloat b[16];
matrix = currentMatrix(); //gets the ProjectionMatrix as GLfloat*
copyMatrix(matrix, b);
matrix[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
matrix[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
matrix[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
matrix[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
matrix[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
matrix[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
matrix[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
matrix[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
matrix[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
matrix[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
matrix[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
matrix[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
matrix[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
matrix[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
matrix[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
matrix[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
}
void Matrix::copyMatrix(const GLfloat* source, GLfloat* destination){
for(int i=0; i<16; i++){
destination[i] = source[i];
}
}
Im debugging this for 2 days now and have now idea what Im missing... Any ideas?

I always refer to this excellent implementation. The code is easy to follow and it just works.
Their translate method is pasted here:
translate: function (tx, ty, tz) {
this.elements[3*4+0] += this.elements[0*4+0] * tx + this.elements[1*4+0] * ty + this.elements[2*4+0] * tz;
this.elements[3*4+1] += this.elements[0*4+1] * tx + this.elements[1*4+1] * ty + this.elements[2*4+1] * tz;
this.elements[3*4+2] += this.elements[0*4+2] * tx + this.elements[1*4+2] * ty + this.elements[2*4+2] * tz;
this.elements[3*4+3] += this.elements[0*4+3] * tx + this.elements[1*4+3] * ty + this.elements[2*4+3] * tz;
return this;
},

It's a bit hard to tell from your code, but are you intending to use row-order or column-order for your matrices? Row-order would be more common, but you are creating a column-order translation matrix. A translation matrix has the translation 3-vector running down the right-most column from the top-right corner, not along the bottom row.
In a row-ordered matrix, the rows are contiguous blocks so the first four numbers are the top row. In a column-ordered matrix, the columns are contiguous blocks so the first four numbers are the first column.
If I'm reading your code correctly, then it looks like your multiMatrix function is right-multiplying the parameter matrix against the standing class matrix, using row-order. That would be correct for translate if the matrix was row-ordered, so you need to transpose the translation matrix you are creating.

Related

why is my double pendulum programm isn't working in p5js?

var angle1 = 45;
var angle2 = 0;
var L1 = 200;var L2 = 200;
var m1 = 1;
var m2 = 1;
var angleV1 = 0;
var angleV2 = 0;
var g = 1;
var angleA1 =
((-g * (2 * m1 + m2) * sin(angle1) -
m2 * g * sin(angle1 - angle2) -
2 *
sin(angle1 - angle2) *
m2 *
(angleV2 * angleV2 * L2 +
angleV1 * angleV1 * L1 * cos(angle1 - angle2))) /
L1) *
(2 * m1 + m2 - m2 * cos(2 * angle1 - 2 * angle2));
var angleA2 =
((2 *
sin(angle1 - angle2) *
(angleV1 * angleV1 * L1 * (m1 + m2) +
g * (m1 + m2) * cos(angle1) +
angle2 * angle2 * L2 * m2 * cos(angle1 - angle2))) /
L2) *
(2 * m1 + m2 - m2 * cos(2 * angle1 - 2 * angle2));
angleV1 += angleA1;
angle1 += angleV1;
angleV2 += angleA2;
angle2 += angleV2;
var x1 = sin(angle1) * L1;
var y1 = cos(angle1) * L1;
var x2 = x1 + sin(angle2) * L2;
var y2 = y1 + cos(angle2) * L2;
line(0, 0, x1, y1);
line(x1, y1, x2, y2);

How can i simplify this for loop?

I need to fill a 360 element matrix with periods of 90 elements for different phiStart and phiExit values:
flute = 4;
phiStart = 0;
phiExit = 90;
phiDelta = 1;
phiPitch = 360 / flute;
for g = 0:abs(phiExit - phiStart);
for k = 0:abs(phiExit - phiStart);
for j = 0:abs(phiExit - phiStart);
for m = 0:abs(phiExit - phiStart);
for i = 0:abs(phiExit - phiStart);
answerA = phiStart + i * phiDelta;
phi(i+1) = answerA;
end
answerA = phiStart + m * phiDelta;
phi(m + phiPitch) = answerA;
end
answerA = phiStart + j * phiDelta;
phi(j + 2 * phiPitch) = answerA;
end
answerA = phiStart + k * phiDelta;
phi(k + 3 * phiPitch) = answerA;
end
answerA = phiStart + g * phiDelta;
phi(g + 4 * phiPitch) = answerA;
end
b = (phi > 0); % dummy matrix for edge cofficients
h = feedRate * sin(phi / 180 * pi);
Sorry if this makes no sense (just trying to help), I don't even know in what language it is written, but what I read in the original code points to something like
for i = 0:abs(phiExit - phiStart);
answerA = phiStart + i * phiDelta;
for j = 0:abs(flute - 1)
phi(i + j * phiPitch) = answerA;
end
end

what's the math behind cocos's gradient layer

In cocos2d the gradient is implemented using a quad, and the color is interpolated by opengl, but there is an extra parameter which controls the gradient's direction, so how does the algorithm to work.
//_alongVector is the gradient's direction
float h = _alongVector.getLength();
if (h == 0)
return;
// why a sqrt(2.0) ???
float c = sqrtf(2.0f);
Vec2 u(_alongVector.x / h, _alongVector.y / h);
// and what does this mean
if (_compressedInterpolation)
{
float h2 = 1 / ( fabsf(u.x) + fabsf(u.y) );
u = u * (h2 * (float)c);
}
float opacityf = (float)_displayedOpacity / 255.0f;
Color4F S(
_displayedColor.r / 255.0f,
_displayedColor.g / 255.0f,
_displayedColor.b / 255.0f,
_startOpacity * opacityf / 255.0f
);
Color4F E(
_endColor.r / 255.0f,
_endColor.g / 255.0f,
_endColor.b / 255.0f,
_endOpacity * opacityf / 255.0f
);
// what are these magic ??????
// (-1, -1)
_squareColors[0].r = E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c));
_squareColors[0].g = E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c));
_squareColors[0].b = E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c));
_squareColors[0].a = E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c));
// (1, -1)
_squareColors[1].r = E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c));
_squareColors[1].g = E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c));
_squareColors[1].b = E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c));
_squareColors[1].a = E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c));
// (-1, 1)
_squareColors[2].r = E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c));
_squareColors[2].g = E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c));
_squareColors[2].b = E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c));
_squareColors[2].a = E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c));
// (1, 1)
_squareColors[3].r = E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c));
_squareColors[3].g = E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c));
_squareColors[3].b = E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c));
_squareColors[3].a = E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c));
and here is another implementation in cocos2d-objc
// _vector apparently points towards the first color.
float g0 = 0.0f; // (0, 0) dot _vector
float g1 = -_vector.x; // (0, 1) dot _vector
float g2 = -_vector.x - _vector.y; // (1, 1) dot _vector
float g3 = -_vector.y; // (1, 0) dot _vector
float gmin = MIN(MIN(g0, g1), MIN(g2, g3));
float gmax = MAX(MAX(g0, g1), MAX(g2, g3));
GLKVector4 a = GLKVector4Make(_color.r*_color.a*_displayColor.a, _color.g*_color.a*_displayColor.a, _color.b*_color.a*_displayColor.a, _color.a*_displayColor.a);
GLKVector4 b = GLKVector4Make(_endColor.r*_endColor.a*_displayColor.a, _endColor.g*_endColor.a*_displayColor.a, _endColor.b*_endColor.a*_displayColor.a, _endColor.a*_displayColor.a);
_colors[0] = GLKVector4Lerp(a, b, (g0 - gmin)/(gmax - gmin));
_colors[1] = GLKVector4Lerp(a, b, (g1 - gmin)/(gmax - gmin));
_colors[2] = GLKVector4Lerp(a, b, (g2 - gmin)/(gmax - gmin));
_colors[3] = GLKVector4Lerp(a, b, (g3 - gmin)/(gmax - gmin));
are these algorithms the same?
I really want to know the math or algorithm behind those magic operations

splitting trapezoid in given proportion

I need to split trapezoid in 2 part of given size with line, parallel basement. I need to get new h1 of new trapezoid.
For example I have trapezoid of area S and I want to split it in 2 trapezoids of areas S1 and S2.
S1 = aS; S2 = (1-a)S;
S1 = (a+z)*(h1)/2;
S2 = (b+z)*(1-h1)/2;
S1/S2 = KS;
To get new h1 I compare a and b, if a != b, I solve square equation and if a == b I work like with square. But sometimes I get mistakes because of rounding (for example when I solve this analytically I get a = b and program thinks a > b). How can I handle this? Or maybe there is another better way to split trapezoid?
Here is simplifyed code:
if (base > base_prev) {
b_t = base; // base of trapezoid
h = H; //height of trapezoid
a_t = base_prev; //another base of trapezoid
KS = S1 / S2;
a_x = (a_t - b_t) * (1 + KS) / h;
b_x = 2 * KS * b_t + 2 * b_t;
c_x = -(a_t * h + b_t * h);
h_tmp = (-b_x + sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
if (h_tmp > h || h_tmp < 0)
h_tmp = (-b_x - sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
} else if (base < base_prev) {
b_t = base_prev;
a_t = base;
KS = S1 / S2;
a_x = (a_t - b_t) * (1 + KS) / h;
b_x = 2 * KS * b_t + 2 * b_t;
c_x = -(a_t * h + b_t * h);
h_tmp = (-b_x + sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
if (h_tmp > h || h_tmp < 0)
h_tmp = (-b_x - sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
}
else {
KS = S1 / S2;
h_tmp = h * KS;
}
If you're dealing with catastrophic cancellation, one approach, dating back to a classic article by Forsythe, is to use the alternative solution form x = 2c/(-b -+ sqrt(b^2 - 4ac)) for the quadratic equation ax^2 + bx + c = 0. One way to write the two roots, good for b < 0, is
x = (-b + sqrt(b^2 - 4ac))/(2a)
x = 2c/(-b + sqrt(b^2 - 4ac)),
and another, good for b >= 0, is
x = 2c/(-b - sqrt(b^2 - 4ac))
x = (-b - sqrt(b^2 - 4ac))/(2a).
Alternatively, you could use the bisection method to obtain a reasonably good guess and polish it with Newton's method.

Can someone explain the mat4.translate function from glMatrix?

Does anyone know why glmatrix ( 1.x ) defines mat4.translate like this:
/**
* Translates a matrix by the given vector
*
* #param {mat4} mat mat4 to translate
* #param {vec3} vec vec3 specifying the translation
* #param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
*
* #returns {mat4} dest if specified, mat otherwise
*/
mat4.translate = function (mat, vec, dest) {
var x = vec[0], y = vec[1], z = vec[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (!dest || mat === dest) {
mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
return mat;
}
a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03;
dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13;
dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23;
dest[12] = a00 * x + a10 * y + a20 * z + mat[12];
dest[13] = a01 * x + a11 * y + a21 * z + mat[13];
dest[14] = a02 * x + a12 * y + a22 * z + mat[14];
dest[15] = a03 * x + a13 * y + a23 * z + mat[15];
return dest;
};
It looks like the vector values are multiplied (scaled) by the directional vectors ( dir, left, up ) of the matrix. But I don't understand why. Also why is mat[15] assigned. I thought it should always be 1...
I am using this most of the time and I am quite happy:
mat4.translate_alt = function (mat, vec, factor) {
factor = factor || 1;
mat[12] += vec[0]*factor;
mat[13] += vec[1]*factor;
mat[14] += vec[2]*factor;
}
When should I use mat4.translate and when is my mat4.translate_alt enough ?
mat4.translate translates a matrix with a given vector (vec3), which is the same as multiplying with a translation matrix.
Another way to look at it is to say mat4.translate = mat4.multiply(someMatrix, mat4.create_translate_matrix(someVec3)) (pseudo-code).

Resources