// krMathLib.mel v0.1 // // // Copyright © 2006 Kiaran Ritchie. All rights reserved // www.kiaran.net // // This is a collection of procedures for // performing various mathematical operations // on vectors and matrices. // // Remember, Maya will automatically convert // vectors -> float[] // and // float[] -> vector // But! Maya will NOT convert between matrix and // float arrays. For this, I have included several // conversion functions. // // Included Procedures: // // vectorXform // vectorCrossProduct // vectorDotProduct // vectorMagnitude // matrixProduct // matrixInverse // matrixMakeIdentity // matrixToFloatArray // floatArrayToMatrix /* ________________________________________ 4x4 Matrix Format with Array Indices COLUMNS 0 1 2 3 R 0 m0 m1 m2 m3 O 1 m4 m5 m6 m7 W 2 m8 m9 m10 m11 S 3 m12 m13 m14 m15 ________________________________________ 1x4 Vector Format with Array Indices COLUMNS 0 1 2 3 ROWS 0 v0 v1 v2 v3 ________________________________________ */ ////////////////////////////////////////////////////////////// // This procedure multiplys two 4x4 matrices passed as float arrays. // It returns the product in the form of a float array. ////////////////////////////////////////////////////////////// global proc float[] matrixProduct( float $m1[], float $m2[]) { matrix $newM[4][4];//The matrix after transformation matrix $A[4][4] = floatArrayToMatrix($m1); //Convert array to matrix type matrix $B[4][4] = floatArrayToMatrix($m2); //Convert array to matrix type float $m[]; float $last; int $row, $col; //If matrix A is multiplied by matrix B and gives matrix C, //the value at r,c in C = dotProduct of column 'c' in matrix A and row 'r' in matrix B. for ($row=0; $row<4; $row++) { for ($col=0; $col<4; $col++) { $newM[$row][$col] = 0; //initialize for ($i=0; $i<4; $i++) { $last = $newM[$row][$col]; $last += $A[$row][$i] * $B[$i][$col]; $newM[$row][$col] = $last; } } } //convert matrix into float array $m = matrixToFloatArray($newM); //return matrix in form of float array. return $m; } ////////////////////////////////////////////////////////////// // This procedure takes a 3d vector and a 4x4 matrix as // float arrays. It post-multiplies the vector and returns // the transformed vector in the form of an array. ////////////////////////////////////////////////////////////// global proc float[] vectorXform( float $p[], float $m[]) { $p[3] = 1;//Turn 3d vector into 4d vector float $newP[];//The point after transformation //If vector A is multiplied by matrix B and gives vector C, //the value at r,c in C = dotProduct of column 'c' in vector A and row 'r' in matrix B. //Compute new vector $newP[0] = $m[0]*$p[0] + $m[4]*$p[1] + $m[8]*$p[2] + $m[12]*$p[3];//0,0 $newP[1] = $m[1]*$p[0] + $m[5]*$p[1] + $m[9]*$p[2] + $m[13]*$p[3];//1,0 $newP[2] = $m[2]*$p[0] + $m[6]*$p[1] + $m[10]*$p[2] + $m[14]*$p[3];//2,0 $newP[3] = $m[3]*$p[0] + $m[7]*$p[1] + $m[11]*$p[2] + $m[15]*$p[3];//3,0 return $newP; } ////////////////////////////////////////////////////////////// // This procedure takes a float array with 16 elements (0-15) // and returns a 4x4 matrix. ////////////////////////////////////////////////////////////// global proc matrix floatArrayToMatrix( float $array[]) { matrix $mat[4][4]; int $i, $row, $col; for ($i=0; $i<16; $i++) { $row = $i/4; $col = $i%4; $mat[$row][$col] = $array[$i]; } return $mat; } ////////////////////////////////////////////////////////////// // This procedure takes a 4x4 matrix and returns a float // array with 16 elements (0-15). ////////////////////////////////////////////////////////////// global proc float[] matrixToFloatArray( matrix $mat) { float $array[]; int $i, $row, $col; for ($i=0; $i<16; $i++) { $row = $i/4; $col = $i%4; $array[$i] = $mat[$row][$col]; } return $array; } ////////////////////////////////////////////////////////////// // This procedure takes two float arrays and returns another // float array containing the dot product (sum of the product // of all cooresponding elements). ////////////////////////////////////////////////////////////// global proc float[] getDotProduct( float $p1[], float $p2[]) { int $size1 = `size($p1)`; int $size2 = `size($p2)`; int $bigger; //Find biggest float array. if ($size1 > $size2) $bigger = $size1; else $bigger = $size2; //Warn if incoming vectors are different sizes. if ($size1 != $size2) warning "Vectors are not the same size. Dot product operation may be inaccurate."; //Store the dot product vector. float $dotProduct[]; //Compute int $i; for ($i=0; $i<$bigger; $i++) $dotProduct[$i] = $p1[$i] * $p2[$i]; return $dotProduct; } /* */ /* float $M[] = { 1,0,7,0, 0,1,0,0, 0,0,1,0, 5,0,0,1 }; float $mat[] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.365261, 1.423754, -0.959577, 1.0}; float $a[] = {4,7,3,1}; float $b[] = {0,0,0,1}; float $c[] = getDotProduct($a,$b); //matrix $mat[4][4]; //$mat = floatArrayToMatrix($c); float $xformedPoint[] = vectorXform($b,$mat); print $xformedPoint[3]; */