topical media & game development

talk show tell print

mobile-query-three-plugins-cannonjs-vendor-cannon.js-src-math-Mat3.js / js



  /*global CANNON:true */
  
  
@class CANNON.Mat3 @brief A 3x3 matrix.
parameter: array elements Array of nine elements. Optional.
author: schteppe / github.com/schteppe

  
  CANNON.Mat3 = function(elements){
      
@property Float32Array elements @memberof CANNON.Mat3 @brief A vector of length 9, containing all matrix elements The values in the array are stored in the following order: | 0 1 2 | | 3 4 5 | | 6 7 8 |

  
      if(elements){
          this.elements = new Float32Array(elements);
      } else {
          this.elements = new Float32Array(9);
      }
  };
  
  
@method identity @memberof CANNON.Mat3 @brief Sets the matrix to identity @todo Should perhaps be renamed to setIdentity() to be more clear. @todo Create another function that immediately creates an identity matrix eg. eye()

  
  CANNON.Mat3.prototype.identity = function(){
      this.elements[0] = 1;
      this.elements[1] = 0;
      this.elements[2] = 0;
  
      this.elements[3] = 0;
      this.elements[4] = 1;
      this.elements[5] = 0;
  
      this.elements[6] = 0;
      this.elements[7] = 0;
      this.elements[8] = 1;
  };
  
  
@method vmult @memberof CANNON.Mat3 @brief Matrix-Vector multiplication
parameter: CANNON.Vec3 v The vector to multiply with
parameter: CANNON.Vec3 target Optional, target to save the result in.

  
  CANNON.Mat3.prototype.vmult = function(v,target){
      target = target || new CANNON.Vec3();
  
      var vec = [v.x, v.y, v.z];
      var targetvec = [0, 0, 0];
      for(var i=0; i<3; i++){
          for(var j=0; j<3; j++){
            targetvec[j] += this.elements[i+3*j]*vec[i]; // instead of  
          //targetvec[i] += this.elements[i+3*j]*vec[i]
          }
      }
  
      target.x = targetvec[0];
      target.y = targetvec[1];
      target.z = targetvec[2];
      return target;
  };
  
  
@method smult @memberof CANNON.Mat3 @brief Matrix-scalar multiplication
parameter: float s

  
  CANNON.Mat3.prototype.smult = function(s){
      for(var i=0; i<this.elements.length; i++){
          this.elements[i] *= s;
      }
  };
  
  
@method mmult @memberof CANNON.Mat3 @brief Matrix multiplication
parameter: CANNON.Mat3 m Matrix to multiply with from left side.
returns: CANNON.Mat3 The result.

  
  CANNON.Mat3.prototype.mmult = function(m){
      var r = new CANNON.Mat3();
      for(var i=0; i<3; i++){
          for(var j=0; j<3; j++){
              var sum = 0.0;
              for(var k=0; k<3; k++){
                  sum += m.elements[i+k*3] * this.elements[k+j*3];
              }
              r.elements[i+j*3] = sum;
          }
      }
      return r;
  };
  
  
@method solve @memberof CANNON.Mat3 @brief Solve Ax=b
parameter: CANNON.Vec3 b The right hand side
parameter: CANNON.Vec3 target Optional. Target vector to save in.
returns: CANNON.Vec3 The solution x

  
  CANNON.Mat3.prototype.solve = function(b,target){
  
      target = target || new CANNON.Vec3();
  
      // Construct equations
      var nr = 3; // num rows
      var nc = 4; // num cols
      var eqns = new Float32Array(nr*nc);
      var i,j;
      for(i=0; i<3; i++){
          for(j=0; j<3; j++){
              eqns[i+nc*j] = this.elements[i+3*j];
          }
      }
      eqns[3+4*0] = b.x;
      eqns[3+4*1] = b.y;
      eqns[3+4*2] = b.z;
  
      // Compute right upper triangular version of the matrix - Gauss elimination
      var n = 3, k = n, np;
      var kp = 4; // num rows
      var p, els;
  do {
      i = k - n;
      if (eqns[i+nc*i] === 0) {
          // the pivot is null, swap lines
        for (j = i + 1; j < k; j++) {
          if (eqns[i+nc*j] !== 0) {
            np = kp;
            do {  // do ligne( i ) = ligne( i ) + ligne( k )
              p = kp - np;
              eqns[p+nc*i] += eqns[p+nc*j]; 
            } while (--np);
            break;
          }
        }
      }
      if (eqns[i+nc*i] !== 0) {
        for (j = i + 1; j < k; j++) {
          var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
          np = kp;
          do {  // do ligne( k ) = ligne( k ) - multiplier * ligne( i )
            p = kp - np;
            eqns[p+nc*j] = p <= i ? 0 : eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
          } while (--np);
        }
      }
    } while (--n);
  
      // Get the solution
      target.z = eqns[2*nc+3] / eqns[2*nc+2];
      target.y = (eqns[1*nc+3] - eqns[1*nc+2]*target.z) / eqns[1*nc+1];
      target.x = (eqns[0*nc+3] - eqns[0*nc+2]*target.z - eqns[0*nc+1]*target.y) / eqns[0*nc+0];
  
      if(isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || target.x===Infinity || target.y===Infinity || target.z===Infinity){
          throw "Could not solve equation! Got x=["+target.toString()+"], b=["+b.toString()+"], A=["+this.toString()+"]";
      }
  
      return target;
  };
  
  
@method e @memberof CANNON.Mat3 @brief Get an element in the matrix by index. Index starts at 0, not 1!!!
parameter: int row
parameter: int column
parameter: float value Optional. If provided, the matrix element will be set to this value.
returns: float

  
  CANNON.Mat3.prototype.e = function( row , column ,value){
      if(value===undefined){
          return this.elements[column+3*row];
      } else {
      // Set value
          this.elements[column+3*row] = value;
      }
  };
  
  
@method copy @memberof CANNON.Mat3 @brief Copy the matrix
parameter: CANNON.Mat3 target Optional. Target to save the copy in.
returns: CANNON.Mat3

  
  CANNON.Mat3.prototype.copy = function(target){
      target = target || new CANNON.Mat3();
      for(var i=0; i<this.elements.length; i++){
          target.elements[i] = this.elements[i];
      }
      return target;
  };
  
  
@method toString @memberof CANNON.Mat3 @brief Returns a string representation of the matrix.
returns: string

  
  CANNON.Mat3.prototype.toString = function(){
      var r = "";
      var sep = ",";
      for(var i=0; i<9; i++){
          r += this.elements[i] + sep;
      }
      return r;
  };
  
  
@method reverse @memberof CANNON.Mat3 @brief reverse the matrix
parameter: CANNON.Mat3 target Optional. Target matrix to save in.
returns: CANNON.Mat3 The solution x

  
  CANNON.Mat3.prototype.reverse = function(target){
  
      target = target || new CANNON.Mat3();
  
    // Construct equations
      var nr = 3; // num rows
      var nc = 6; // num cols
      var eqns = new Float32Array(nr*nc);
      var i,j;
      for(i=0; i<3; i++){
          for(j=0; j<3; j++){
              eqns[i+nc*j] = this.elements[i+3*j];
          }
      }
      eqns[3+6*0] = 1;
      eqns[3+6*1] = 0;
      eqns[3+6*2] = 0;
      eqns[4+6*0] = 0;
      eqns[4+6*1] = 1;
      eqns[4+6*2] = 0;
      eqns[5+6*0] = 0;
      eqns[5+6*1] = 0;
      eqns[5+6*2] = 1;
    
    // Compute right upper triangular version of the matrix - Gauss elimination
      var n = 3, k = n, np;
      var kp = nc; // num rows
      var p;
      do {
          i = k - n;
          if (eqns[i+nc*i] === 0) {
              // the pivot is null, swap lines
              for (j = i + 1; j < k; j++) {
                  if (eqns[i+nc*j] !== 0) {
                      np = kp;
                      do { // do line( i ) = line( i ) + line( k )
                          p = kp - np;
                          eqns[p+nc*i] += eqns[p+nc*j];
                      } while (--np);
                      break;
                  }
              }
          }
          if (eqns[i+nc*i] !== 0) {
              for (j = i + 1; j < k; j++) {
                  var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
                  np = kp;
                  do { // do line( k ) = line( k ) - multiplier * line( i )
                      p = kp - np;
                      eqns[p+nc*j] = p <= i ? 0 : eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
                  } while (--np);
              }
          }
      } while (--n);
    
    // eliminate the upper left triangle of the matrix
    i = 2
      do {
          j = i-1;
          do {
              var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
              np = nc;
              do { 
                  p = nc - np;
                  eqns[p+nc*j] =  eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
              } while (--np);
          } while (j--);
      } while (--i);
    
    // operations on the diagonal
      i = 2;
      do {
          var multiplier = 1 / eqns[i+nc*i];
          np = nc;
          do { 
              p = nc - np;
              eqns[p+nc*i] = eqns[p+nc*i] * multiplier ;
          } while (--np);
      } while (i--);
    
    
      i = 2;
      do {
          j = 2;
          do {
              p = eqns[nr+j+nc*i];
              if( isNaN( p ) || p ===Infinity )
                  throw "Could not reverse! A=["+this.toString()+"]";
              target.e( i , j , p );
          } while (j--);
      } while (i--);
      
      return target;
  };


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.