Skip to content

Commit

Permalink
Redid Quaternion implementation.
Browse files Browse the repository at this point in the history
Added Quaternion test cases.
  • Loading branch information
OneGeek committed Feb 11, 2010
1 parent 7d28eb2 commit 262d7e3
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 1 deletion.
110 changes: 110 additions & 0 deletions src/webglu.js
Expand Up @@ -48,6 +48,12 @@ $W = {
/** The raw WebGL object for low level work. */
GL : null,

/** Simulated world */
world: {
/** Physical objects */
objects: []
},

/** Renderable objects */
objects : [],

Expand Down Expand Up @@ -905,6 +911,9 @@ $W = {

/** @namespace Utility functions. */
util:{
integrateEuler:function(fun, t, dt) {
return fun(t + dt);
},

/** XXX Not yet implemented. */
getPickRay : function(x, y) {
Expand Down Expand Up @@ -1431,7 +1440,31 @@ $W = {
}
}
}
},

/** @class A physical simulation.
*/
Simulation:function() {
$W.anim.ProceduralAnimation.call(this); // subclass of ProceduralAnimation

/** Bounding sphere radius */
this.radius = 1;
/** Object mass */
this.mass = 1;
/** Object velocity */
this.velocity = Vector.Zero(3);
/** Angular velocity */
this.omega = Vector.Zero(3);

this.update = function(dt) {
// calculate forces
// integrate position/rotation
// update momentum
// calculate velocities
}

}

},


Expand Down Expand Up @@ -1504,8 +1537,84 @@ $W = {
},

// Classes
/** @class Quaternion implementation.
* based on reference implementation at
* http://3dengine.org/Quaternions
*/
Quaternion:function() {
// Called as Quaternion(x, y, z, theta)
if (arguments.length == 4) {
var angle = (arguments[3] / 180.0) * Math.PI;
var result = Math.sin(angle / 2);
this.w = Math.cos(angle / 2);
this.x = arguments[0] * result;
this.y = arguments[1] * result;
this.z = arguments[2] * result;

// Called as Quaternion([w, x, y, z])
}else if (arguments[0] != undefined && arguments[0].length == 4) {
this.w = arguments[0][0];
this.x = arguments[0][1];
this.y = arguments[0][2];
this.z = arguments[0][3];

// Called as Quaternion()
}else {
this.w = 1;
this.x = 0;
this.y = 0;
this.z = 0;
}

this.matrix = function() {
var w = this.w;
var x = this.x;
var y = this.y;
var z = this.z;
var xx = x * x;
var yy = y * y;
var zz = z * z;
var xy = x * y;
var xz = x * z;
var xw = x * w;
var yz = y * z;
var yw = y * w;
var zw = z * w;

var m = [[],[],[],[]];

m[0][0] = 1 - 2 * (yy + zz);
m[0][1] = 2 * (xy + zw);
m[0][2] = 2 * (xz - yw);
m[0][3] = 0;
m[1][0] = 2 * (xy - zw);
m[1][1] = 1 - 2 * (xx + zz);
m[1][2] = 2 * (yz + xw);
m[1][3] = 0;
m[2][0] = 2 * (xz + yw);
m[2][1] = 2 * (yz - xw);
m[2][2] = 1 - 2 * (xx + yy);
m[2][3] = 0;
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = 0;
m[3][3] = 1;

return $M(m);
}

this.multiply = function(q) {
var result = new $W.Quaternion();
result.w = this.w * q.w - this.x * q.x - this.y * q.y - this.z * q.z;
result.x = this.w * q.x + this.x * q.w + this.y * q.z - this.z * q.y;
result.y = this.w * q.y + this.y * q.w + this.z * q.x - this.x * q.z;
result.z = this.w * q.z + this.z * q.w + this.x * q.y - this.y * q.x;
return result;
}
},

/** @class Quaternion implementation XXX broken */
/*
Quaternion:function(m) {
this.vec = Vector.Zero(4);
Expand Down Expand Up @@ -1535,6 +1644,7 @@ $W = {
return result;
}
},
*/

/** @class Common state representation (position, rotation, scale).
* A position, rotation, and scale.
Expand Down
104 changes: 103 additions & 1 deletion tests/test.html
Expand Up @@ -12,7 +12,7 @@
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/yuitest/yuitest-min.js"></script>

<!-- WebGLU -->
<script type="text/javascript" src="../Sylvester.src.js"></script>
<script type="text/javascript" src="../external/Sylvester.src.js"></script>
<script type="text/javascript" src="../src/webglu.js"></script>
<script type="text/javascript" src="../src/gameglu.js"></script>

Expand Down Expand Up @@ -73,6 +73,13 @@
WebGLUTestSuite.add(
new YT.TestCase({
name:'Shader Tests',
setUp : function() {
$W.initialize();
},

tearDown : function() {
$W.reset();
},

test_newProgram : function() {

Expand All @@ -84,6 +91,13 @@
WebGLUTestSuite.add(
new YT.TestCase({
name:'Object Tests',
setUp : function() {
$W.initialize();
},

tearDown : function() {
$W.reset();
},

test_newObject : function() {

Expand All @@ -94,6 +108,94 @@
})
);

WebGLUTestSuite.add(
new YT.TestCase({
name:'Math Tests',
setUp : function() {
$W.initialize();
},

tearDown : function() {
$W.reset();
},

test_newQuaternion : function() {
var q;

var error1 = "Quaternion(x, y, z, theta) failed";
var x1 = 1;
var y1 = 0;
var z1 = 0;
var theta = 90;
var expected_q1x = 0.7071;
var expected_q1y = 0;
var expected_q1z = 0;
var expected_q1w = 0.7071;

var error2 = "Quaternion([w, x, y, z]) failed";
var w2 = 0.1;
var x2 = 0.3;
var y2 = 0.3;
var z2 = 0.5;

var error3 = "Quaternion() failed";

// Test Quaternion(x, y, z, theta)
q = new $W.Quaternion(x1, y1, z1, theta);
assert.areEqual(expected_q1x, q.x.toPrecision(4), error1);
assert.areEqual(expected_q1y, q.y.toPrecision(4), error1);
assert.areEqual(expected_q1z, q.z.toPrecision(4), error1);
assert.areEqual(expected_q1w, q.w.toPrecision(4), error1);

// Test Quaternion([w, x, y, z])
q = new $W.Quaternion([w2, x2, y2, z2]);
assert.areEqual(w2, q.w, error2);
assert.areEqual(x2, q.x, error2);
assert.areEqual(y2, q.y, error2);
assert.areEqual(z2, q.z, error2);

// Test Quaternion()
q = new $W.Quaternion();
assert.areEqual(1, q.w, error3);
assert.areEqual(0, q.x, error3);
assert.areEqual(0, q.y, error3);
assert.areEqual(0, q.z, error3);
},

test_multQuaternions : function() {
var roll = 30;
var pitch = 45;
var heading = 30;
var expected_glMatrix =
[0.57322332027622536, 0.73919890801437749,
-0.3535533898605015, 0.0, -0.3535533898605015,
0.61237244705783134, 0.70710677171312086, 0.0,
0.73919890801437749, -0.28033009198934633,
0.61237244705783134, 0.0, 0, 0, 0, 1.0]

var q1 = new $W.Quaternion(0, 0, 1, roll);
var q2 = new $W.Quaternion(1, 0, 0, pitch);
var q3 = new $W.Quaternion(0, 1, 0, heading);

var qr = (q1.multiply(q2)).multiply(q3);

var result_glMatrix = qr.matrix().elements.flatten();

console.log(expected_glMatrix);
console.log(result_glMatrix);

for (var i = 0; i < expected_glMatrix.length; i++) {
// 7 digit precision because reference values were
// calculated with Pi accurate to just 7 digits.
assert.areEqual(
expected_glMatrix[i].toPrecision(7),
result_glMatrix[i].toPrecision(7),
"Quaternion multiplation failure");
}
}
})
);

logger = new YAHOO.tool.TestLogger();
with(YAHOO.tool.TestRunner) {
//subscribe(TEST_FAIL_EVENT, handleTestResult);
Expand Down

0 comments on commit 262d7e3

Please sign in to comment.