title: How do I compose a rotation matrix with human readable angles from scratch?
body: <p>The one thing that has always hindered me from doing 3D programming is failing to understand how math works. I can go along with math fine in programming flow using methods and functions, then its all clear and logical to me, but in mathematical notation, I just can't make heads or tails from it.</p>
  
  <p>I have been reading websites, a watching videos of institutes trying to explain this, but they all use mathematical notation and I simply get lost in it, my mind won't translate it to something understandable. I might have a defect there.</p>
  
  <p>Also, Just using someone's code isn't my interest, I want to understand the mechanics behind it, the logic. I'd be happy to use someone else's code, but I really want to understand how it works.</p>
  
  <p><strong>The question</strong></p>
  
  <p>Can you explain to me in simple terms <strong>without</strong> mathematical notation, just programming notation/functions/psuedocode, how to implement a matrix transform along all 3 axes?</p>
  
  <p>Ideally what I want is the material/understanding to write a method/object where I can define the angles of 3 axes similar to glRotate to rotate the collection of quads/triangles I have. (I am trying to program a 3D rotation of a cube shapes without having access to OpenGL functions to do it for me because this is done in one draw call every time something changes in the display list.)</p>
  
  <p><strong>What have I done?</strong></p>
  
  <p>I have attempted at making a 90 degrees transform function to get the hang of the math but failed utterly in making a proper matrix which in theory should have been the simplest to do. You can see my failed attempt in all its glory on <a href="http://jsfiddle.net/bLfg0tj8/5/" rel="noreferrer">http://jsfiddle.net/bLfg0tj8/5/</a></p>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>Vec3 = function(x,y,z) {
      this.x = x;
      this.y = y;
      this.z = z;
  }
  Matrix = function Matrix() {
      this.matrixPoints = new Array();    
      this.rotationPoint = new Vec3(0,0,0);
      this.rotationAngle = 90;
  }
  Matrix.prototype.addVector = function(vector) {
      this.matrixPoints.push(vector);
  }
  Matrix.prototype.setRotationPoint = function(vector) {
      this.rotationPoint = vector; 
  }
  Matrix.prototype.setRotationAngle = function(angle) {
      this.rotationAngle = angle;
  }
  Matrix.prototype.populate = function() {
      translateToOrigin =     [[1,0,0-this.rotationPoint.x],
                                    [0,1,0-this.rotationPoint.y],
                                    [0,0,0-this.rotationPoint.z]];
      rotationMatrix =         [[0,-1,0],
                                    [0,1,0],
                                    [0,0,1]];
      translateEnd =         [[1,0,this.rotationPoint.x],
                                    [0,1,this.rotationPoint.y],
                                    [0,0,this.rotationPoint.z]];
      currentColumn = 0;
      currentRow = 0;
      this.combomatrix = this.mergeMatrices(this.mergeMatrices(translateEnd,rotationMatrix),
                                            translateToOrigin);
  }
  Matrix.prototype.transform = function() {
      newmatrix = new Array();
      for(c = 0;c&lt;this.matrixPoints.length;c++) {
          newmatrix.push(this.applyToVertex(this.matrixPoints[c]));
      }
      return newmatrix;
  }
  Matrix.prototype.applyToVertex = function(vertex) {
      ret = new Vec3(vertex.x,vertex.y,vertex.z);
      ret.x = ret.x + this.combomatrix[0][0] * vertex.x +
              this.combomatrix[0][1] * vertex.y +
              this.combomatrix[0][2] * vertex.z;
      
      ret.y = ret.y + this.combomatrix[1][0] * vertex.x +
              this.combomatrix[1][1] * vertex.y +
              this.combomatrix[1][2] * vertex.z;
      
      ret.z = ret.z + this.combomatrix[2][0] * vertex.x +
              this.combomatrix[2][1] * vertex.y +
              this.combomatrix[2][2] * vertex.z;
      return ret;
  }
  Matrix.prototype.mergeMatrices = function(lastStep, oneInFront) {
      step1 = [[0,0,0],[0,0,0],[0,0,0]];
      step1[0][0] =   lastStep[0][0] * oneInFront[0][0] + 
                      lastStep[0][1] * oneInFront[1][0] + 
                      lastStep[0][2] * oneInFront[2][0];
      
      step1[0][1] =   lastStep[0][0] * oneInFront[0][1] + 
                      lastStep[0][1] * oneInFront[1][1] + 
                      lastStep[0][2] * oneInFront[2][1];
      
      step1[0][2] =   lastStep[0][0] * oneInFront[0][2] + 
                      lastStep[0][1] * oneInFront[1][2] + 
                      lastStep[0][2] * oneInFront[2][2];
      //============================================================
      step1[1][0] =   lastStep[1][0] * oneInFront[0][0] + 
                      lastStep[1][1] * oneInFront[1][0] + 
                      lastStep[1][2] * oneInFront[2][0];
      
      step1[1][1] =   lastStep[1][0] * oneInFront[0][1] + 
                      lastStep[1][1] * oneInFront[1][1] + 
                      lastStep[1][2] * oneInFront[2][1];
      
      step1[1][2] =   lastStep[1][0] * oneInFront[0][2] + 
                      lastStep[1][1] * oneInFront[1][2] + 
                      lastStep[1][2] * oneInFront[2][2];
      //============================================================
      step1[2][0] =   lastStep[2][0] * oneInFront[0][0] + 
                      lastStep[2][1] * oneInFront[1][0] + 
                      lastStep[2][2] * oneInFront[2][0];
      
      step1[2][1] =   lastStep[2][0] * oneInFront[0][1] + 
                      lastStep[2][1] * oneInFront[1][1] + 
                      lastStep[2][2] * oneInFront[2][1];
      
      step1[2][2] =   lastStep[2][0] * oneInFront[0][2] + 
                      lastStep[2][1] * oneInFront[1][2] + 
                      lastStep[2][2] * oneInFront[2][2];
      return step1;
  }
  Matrix.prototype.getCurrentMatrix = function() {
      return this.matrixPoints;
  }
  myvectors = [new Vec3(50,50,0), new Vec3(20,80,0), new Vec3(80, 80, 0)];
  
  function drawVectors(vectors,color) {
      for(c=0;c&lt;vectors.length;c++) {
          document.getElementById("whoa").innerHTML += '&lt;div style="color:'+color+';position:absolute;left:'+vectors[c].x+'px; top:'+vectors[c].y+'px;z-index:'+vectors[c].z+';"&gt;('+c+').&lt;/div&gt;';
      }
  }
  matrix = new Matrix();
  for(c=0;c&lt;myvectors.length;c++) {
      matrix.addVector(myvectors[c]);
  }
  matrix.setRotationPoint(new Vec3(50,70,0));
  matrix.populate();
  somematrix = matrix.transform();
  drawVectors(matrix.getCurrentMatrix(),"lime"); // draw current matrix that was hand coded
  drawVectors([matrix.rotationPoint],'white'); // draw rotation point
  drawVectors(somematrix,"red"); // transformed matrix... somehow two points merge</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div id="whoa" style="position:relative;top:50px;left:150px;background-color:green;color:red;width:400px;height:300px;"&gt;
      &amp;nbsp;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>The green text is the original triangle, the white point the center point, the red points the failed transformation(I think, because it isn't aligned around the center point). The tutorial I was in thought me how to combine matrices into a combined matrix, but I guess I screwed up somewhere.</p>
  
  <p>As I said, it's really really hard for me to understand mathematical notation and speak. And not helping is that most teachers skip parts of the explanation. Took me 2 hours alone to understand when multiplying matrices you need to add each step together instead of just keep on multiplying. Yay for explanations.</p>
  
  <p><strong>A practical example what I work with/want to work with</strong></p>
  
  <p>For example I have a cube, loaded from a wavefront obj file located in the world at </p>
  
  <pre><code>x = 50
  y = 100
  z = 200
  </code></pre>
  
  <p>The cube is drawn using quads and some uv mapping. No problems here. It renders beautifully with all the textures showing correctly.</p>
  
  <p>These are the location coordinates for each "face" of the cube which is drawn using a quad.</p>
  
  <pre><code>// Front face
  -1.0, -1.0,  1.0,
   1.0, -1.0,  1.0,
   1.0,  1.0,  1.0,
  -1.0,  1.0,  1.0,
  
  // Back face
  -1.0, -1.0, -1.0,
  -1.0,  1.0, -1.0,
   1.0,  1.0, -1.0,
   1.0, -1.0, -1.0,
  
  // Top face
  -1.0,  1.0, -1.0,
  -1.0,  1.0,  1.0,
   1.0,  1.0,  1.0,
   1.0,  1.0, -1.0,
  
  // Bottom face
  -1.0, -1.0, -1.0,
   1.0, -1.0, -1.0,
   1.0, -1.0,  1.0,
  -1.0, -1.0,  1.0,
  
  // Right face
   1.0, -1.0, -1.0,
   1.0,  1.0, -1.0,
   1.0,  1.0,  1.0,
   1.0, -1.0,  1.0,
  
  // Left face
  -1.0, -1.0, -1.0,
  -1.0, -1.0,  1.0,
  -1.0,  1.0,  1.0,
  -1.0,  1.0, -1.0
  </code></pre>
  
  <p>So this works all great. But what if I want this cube rotated 90 degrees along the x axis and 45 degrees around the z axis? I cannot use glRotate because at the moment I pass the data to the tesselator object I cannot do any matrix transforms to it via the opengl functions because it's just taking in the data, not actually rendering it per se.</p>
  
  <p>The way the data is stored is as following:</p>
  
  <pre><code>WaveFrontObject()
     |
     |-&gt; Groups(String groupname)
          |
          |-&gt; Faces()
                |
                |-&gt; Vertex(float x, float y, float z)[] 
                |-&gt; Float UVmap[] corresponding to each vertex
                |-&gt; drawFace() // Draws the face as a quad or triangle
  </code></pre>
  
  <p>So each of the above coordinates I gave is stored as a face of the wavefront object in the group "cube".</p>
  
  <p>When the cube is added to the tesselator it is translated to the right coordinates in the world and it renders normal.</p>
  
  <p>It always renders the same however. If I would want it to render at an angle I would have to make a seperate wavefront object at this moment to be able to do that. In my opnion that is madness to do when it can be solved with some math.</p>
  
  <p><strong>Needed in the answer</strong></p>
  
  <ol>
  <li>Explanation step by step how to build a translation matrix and an attempt to explain the math to me.</li>
  <li><p>Explanation how to apply the translation matrix to the quads/triangles in the faces whist they keep oriented around the center of their location </p>
  
  <p>x = 50.5
  y = 100.5
  z = 200.5</p></li>
  <li><p>Some example/pseudo code to go along with the explanation.</p></li>
  </ol>
  
  <p>The used programming language used to explain isn't really relevant as long as its in the C family</p>
  
  <p>Please try to stay away from mathematical notation/speak. I don't know what alpha beta, thetha is, I do know what x axis, y axis and z axis is. I do know what angles are, but I do not know the names mathematicians find for it.</p>
  
  <p>If you wish to use math names, please explain to me what they are in the 3D world/code and how they are formed/calculated.</p>
  
  <p>I simply want to make a method/object along the lines of</p>
  
  <pre><code>Matrix.transformVertices(vertices[], 90deg x, 45 deg y, 0 deg z);
  </code></pre>