stackgl / shader-school

:mortar_board: A workshopper for GLSL shaders and graphics programming
Other
4.28k stars 252 forks source link

intro-6 (matrices): visually correct solution fails for n > 6 #102

Closed dy-dx closed 9 years ago

dy-dx commented 9 years ago

My solution looks correct but it fails when n > 6.

float determinant2x2(mat2 m) {
  return m[0][0]*m[1][1] - m[1][0]*m[0][1];
}

mat2 inverse2x2(mat2 m) {
  return 1.0/determinant2x2(m) * mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
}

mat2 eigenvectors2x2(mat2 m, float L1, float L2) {
  vec2 v1 = vec2(1.0, 0.0);
  vec2 v2 = vec2(0.0, 1.0);

  if (m[0][1] != 0.0) {
    v1 = vec2(L1 - m[1][1], m[0][1]);
    v2 = vec2(L2 - m[1][1], m[0][1]);
  } else if (m[1][0] != 0.0) {
    v1 = vec2(m[1][0], L1 - m[0][0]);
    v2 = vec2(m[1][0], L2 - m[0][0]);
  }
  return mat2(v1, v2);
}

mat2 matrixPower(highp mat2 m, int n) {
  float power = float(n);
  float trace = m[0][0] + m[1][1];
  float det = determinant2x2(m);

  // Eigenvalues
  float L1 = (trace + sqrt( pow(trace,2.0) - 4.0*det )) / 2.0;
  float L2 = (trace - sqrt( pow(trace,2.0) - 4.0*det )) / 2.0;

  // Diagonalization
  mat2 eigenvectors = eigenvectors2x2(m, L1, L2);
  mat2 diagonal = mat2(pow(L1, power), 0.0, 0.0, pow(L2, power));

  return eigenvectors * diagonal * inverse2x2(eigenvectors);
}

Comparing this to the expected solution, I guess you could argue that I failed this exercise spectacularly... and I wouldn't disagree with you. But I still think this solution should pass! :stuck_out_tongue_closed_eyes:

mikolalysenko commented 9 years ago

Fixed