title: Rotating arbitrary plane to be z-axis-aligned
body: <p>Correct me if I'm wrong, but...</p>
  
  <p>Given the normal of an arbitrary source plane, and the normal of the plane after applying a desired rotation:</p>
  
  <pre><code>Vector3F sourceNormal = (x, y, z).normalize()
  Vector3F desiredNormal = (0, 0, 1).normalize()
  </code></pre>
  
  <p>1) We can find the "axis of rotation" through the cross-product of the two normals</p>
  
  <pre><code>Vector3F rotationAxis = Vector3F.cross(sourceNormal, desiredNormal).normalize()
  </code></pre>
  
  <p>2) We can find the "angle of rotation" through the arc-cosine of the dot product of the two normals.</p>
  
  <pre><code>// Thanks nico - it was there in my project source, but it was omitted here.
  float theta = Math.acos(Vector3F.dot(sourceNormal, desiredNormal))
  </code></pre>
  
  <p>3) We can apply the rotation to a set of points in order to orient the source plane to our desired plane.</p>
  
  <pre><code>float[] rotationMatrix = new float[16];
  
  // X component
  rotationMatrix[5] = rotationMatrix[10] = (float)Math.cos(theta);
  rotationMatrix[9] = (float)Math.sin(theta);
  rotationMatrix[6] = -rotationMatrix[9];
  
  // Y component
  rotationMatrix[0] = rotationMatrix[10] = (float)Math.cos(theta);
  rotationMatrix[2] = (float)Math.sin(theta);
  rotationMatrix[8] = -rotationMatrix[2];
  
  // Z component
  rotationMatrix[0] = rotationMatrix[5] = (float)Math.cos(theta);
  rotationMatrix[1] = (float)Math.sin(theta);
  rotationMatrix[4] = -rotationMatrix[1];
  
  for(Point3F point : polygon)
  {
      float x = pt.getX();
      float y = pt.getY();
      float z = pt.getZ();
      float[] xs = new float[3];
      float[] ys = new float[3];
      float[] zs = new float[3];
      for(int j = 0; j &lt; 3; ++j)
      {
      xs[j] = rotationMatrix[j] * x;
      ys[j] = rotationMatrix[j + 4] * y;
      zs[j] = rotationMatrix[j + 8] * z;
      }
      x = 0; y = 0; z = 0;
      for(int j = 0; j &lt; 3; ++j)
      {
      x += xs[j];
      y += ys[j];
      z += zs[j];
      }
      pt.set(x, y, z);
  }
  </code></pre>
  
  <p>My output is incorrect.</p>
  
  <p>In Points:</p>
  
  <pre><code>(-56.00, 72.01, 48.02)
  (-48.00, 72.01, 48.02)
  (-48.00, 86.01, 24.02)
  (-56.00, 86.01, 24.02)
  </code></pre>
  
  <p>Out Points:</p>
  
  <pre><code>(-124.960010, -88.105451, 24.185812)
  (-107.108590, -88.105451, 24.185812)
  (-107.108590, -105.237051, 12.0929052)
  (-124.960010, -105.237051, 12.0929052)
  </code></pre>
  
  <p>If I had to guess, I'd say that I am applying the rotations to the points incorrectly...perhaps I've interpreted the rotation matrix found in this article ( <a href="http://en.wikipedia.org/wiki/Rotation_matrix" rel="nofollow">http://en.wikipedia.org/wiki/Rotation_matrix</a> ) incorrectly?</p>
  
  <p>Thanks for any input.</p>
  
  <p>...assuming that this is the correct way to set up the rotation matrix, the output is still incorrect:</p>
  
  <pre><code>Vector3F axis = Vector3F.cross(sourceNormal, desiredNormal).normalize();
  float angle = (float) Math.acos(p.normal.dot(new Vector3F(0, 0, 1)));
  float s = (float)Math.sin(angle);
  float c = (float)Math.cos(angle);
  float x = axis.getX(), y = axis.getY(), z = axis.getZ();
  float[] matrix = new float[16];
  matrix[0] = x * x * (1 - c) + c;
  matrix[1] = x * y * (1 - c) - (z * s);
  matrix[2] = x * z * (1 - c) + (y * s);
  
  matrix[4] = y * x * (1 - c) + (z * s);
  matrix[5] = y * y * (1 - c) + c;
  matrix[6] = y * z * (1 - c) - (x * s);
  
  matrix[8] = x * z * (1 - c) - (y * s);
  matrix[9] = y * z * (1 - c) + (x * s);
  matrix[10] = z * z * (1 - c) + c;
  
  
  float nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
  float ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
  float nz = x * matrix[8] + y * matrix[9] + z * matrix[10];
  
  In: (-56.00, 56.01, -16.02)
  In: (-48.00, 56.01, -16.02)
  In: (-48.00, 72.01, -8.02)
  In: (-56.00, 72.01, -8.02)
  Out: (-51.270340, 46.887921, -25.5108342)
  Out: (-43.9460070, 46.887921, -25.5108342)
  Out: (-43.9460070, 62.798761, -21.5554182)
  Out: (-51.270340, 62.798761, -21.5554182)
  </code></pre>