/* Copyright 2009 Pieter Iserbyt This file is part of Pamela. Pamela is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Pamela is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Pamela. If not, see . */ // Class Vector function Vector(x, y, z) { this.x = x; this.y = y; this.z = z; this.w = 1; } Vector.prototype.add = function(v) { this.x += v.x; this.y += v.y; this.z += v.z; }; Vector.prototype.subtract = function(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; }; Vector.prototype.scale = function(s) { this.x *= s; this.y *= s; this.z *= s; }; Vector.prototype.rotateX = function(a) { var c = Math.cos(a); var s = Math.sin(a); this.y = this.y * c + this.z * s; this.z = this.z * c - this.y * s; }; Vector.prototype.rotateY = function(a) { var c = Math.cos(a); var s = Math.sin(a); this.x = this.x * c + this.z * s; this.z = this.z * c - this.x * s; }; Vector.prototype.rotateZ = function(a) { var c = Math.cos(a); var s = Math.sin(a); this.x = this.x * c + this.y * s; this.y = this.y * c - this.x * s; }; Vector.prototype.distance = function(v) { if (typeof v == "undefined") { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); } var xd = this.x - v.x; var yd = this.y - v.y; var zd = this.z - v.z; return Math.sqrt(xd * xd + yd * yd + zd * zd); }; Vector.prototype.clone = function() { return new Vector(this.x, this.y, this.z); }; Vector.prototype.project = function(cam) { var d = this.clone(); d.subtract(cam); if (d.z < 0) return false; var s = (width / 2) / d.distance(); return { x: d.x * s, y: d.y * s, scale: s }; }; // Class Matrix function Matrix(m) { if (typeof m == "undefined") m = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]; this.m = m; } Matrix.prototype.multiplyVector = function(v) { // Initialize the result vector. var result = new Vector(); var m = this.m; // Perform the multiplication result.x = m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3]; result.y = m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3]; result.z = m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3]; result.w = m[3][0]*v.x + m[3][1]*v.y + m[3][2]*v.z + m[3][3]; return result; }; Matrix.prototype.multiplyMatrix = function(m) { this.m = this._mult(m); return this; }; Matrix.prototype.resetMatrix = function() { // identity and translate the axes to the center of the canvas. this.m = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]; }; Matrix.prototype.rotateX = function(angle) { var c = Math.cos(angle); var s = Math.sin(angle); this.m = this._mult([[1, 0, 0, 0],[0, c, -s, 0],[0, s, c, 0],[0, 0, 0, 1]]); return this; }; Matrix.prototype.rotateY = function(angle) { var c = Math.cos(angle); var s = Math.sin(angle); this.m = this._mult([[c, 0, s, 0],[0, 1, 0, 0],[-s, 0, c, 0],[0, 0, 0, 1]]); return this; }; Matrix.prototype.rotateZ = function(angle) { var c = Math.cos(angle); var s = Math.sin(angle); this.m = this._mult([[c, -s, 0, 0],[s, c, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]); return this; }; Matrix.prototype.scale = function(scaleX, scaleY, scaleZ) { this.m = this._mult([[scaleX,0,0,0],[0,scaleY,0,0],[0,0,scaleZ,0],[0,0,0,1]]); return this; }; Matrix.prototype.translate = function(dX, dY, dZ) { this.m = this._mult([[1,0,0,dX],[0,1,0,dY],[0,0,1,dZ],[0,0,0,1]]); return this; }; Matrix.prototype.project = function(v) { var pj = this.multiplyVector(v); pj.x /= pj.z / (width / 2); pj.y /= pj.z / (width / 2); return pj; }; Matrix.prototype._mult = function(m) { var m1 = this.m; var m2 = m; var result = [[],[],[],[]]; for(var i = 0; i < 4; i++){ result[i][0] = m1[i][0] * m2[0][0] + m1[i][1] * m2[1][0] + m1[i][2] * m2[2][0] + m1[i][3] * m2[3][0]; result[i][1] = m1[i][0] * m2[0][1] + m1[i][1] * m2[1][1] + m1[i][2] * m2[2][1] + m1[i][3] * m2[3][1]; result[i][2] = m1[i][0] * m2[0][2] + m1[i][1] * m2[1][2] + m1[i][2] * m2[2][2] + m1[i][3] * m2[3][2]; result[i][3] = m1[i][0] * m2[0][3] + m1[i][1] * m2[1][3] + m1[i][2] * m2[2][3] + m1[i][3] * m2[3][3]; } return result; }; Matrix.prototype.clone = function() { return new Matrix(this.m.slice()); }