UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

289 lines (245 loc) 13.4 kB
var $builtinmodule = function(name) { var mod = {}; // todo; should probably put this in a math package mod.Mat44 = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func(function(self) { Sk.misceval.callsim($loc.loadIdentity, self); self.stack = []; }); $loc.push = new Sk.builtin.func(function(self) { self.stack.push(self.elements.slice(0)); }); $loc.pop = new Sk.builtin.func(function(self) { self.elements = self.stack.pop(); }); $loc.loadIdentity = new Sk.builtin.func(function(self) { self.elements = [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.0, 0.0, 0.0, 1.0]; }); $loc.transform3 = new Sk.builtin.func(function(self, v) { var e = self.elements; return Sk.misceval.callsim(mod.Vec3, e[0] * v.x + e[4] * v.y + e[8] * v.z, e[1] * v.x + e[5] * v.y + e[9] * v.z, e[2] * v.x + e[6] * v.y + e[10] * v.z); }); $loc.scale = new Sk.builtin.func(function(self, sx, sy, sz) { self.elements[0*4+0] *= sx; self.elements[0*4+1] *= sx; self.elements[0*4+2] *= sx; self.elements[0*4+3] *= sx; self.elements[1*4+0] *= sy; self.elements[1*4+1] *= sy; self.elements[1*4+2] *= sy; self.elements[1*4+3] *= sy; self.elements[2*4+0] *= sz; self.elements[2*4+1] *= sz; self.elements[2*4+2] *= sz; self.elements[2*4+3] *= sz; return self; }); $loc.translate = new Sk.builtin.func(function(self, tx, ty, tz) { self.elements[3*4+0] += self.elements[0*4+0] * tx + self.elements[1*4+0] * ty + self.elements[2*4+0] * tz; self.elements[3*4+1] += self.elements[0*4+1] * tx + self.elements[1*4+1] * ty + self.elements[2*4+1] * tz; self.elements[3*4+2] += self.elements[0*4+2] * tx + self.elements[1*4+2] * ty + self.elements[2*4+2] * tz; self.elements[3*4+3] += self.elements[0*4+3] * tx + self.elements[1*4+3] * ty + self.elements[2*4+3] * tz; return self; }); $loc.rotate = new Sk.builtin.func(function(self, angle, x, y, z) { var mag = Math.sqrt(x*x + y*y + z*z); var sinAngle = Math.sin(angle * Math.PI / 180.0); var cosAngle = Math.cos(angle * Math.PI / 180.0); if (mag > 0) { var xx, yy, zz, xy, yz, zx, xs, ys, zs; var oneMinusCos; var rotMat; x /= mag; y /= mag; z /= mag; xx = x * x; yy = y * y; zz = z * z; xy = x * y; yz = y * z; zx = z * x; xs = x * sinAngle; ys = y * sinAngle; zs = z * sinAngle; oneMinusCos = 1.0 - cosAngle; rotMat = Sk.misceval.callsim(mod.Mat44); rotMat.elements[0*4+0] = (oneMinusCos * xx) + cosAngle; rotMat.elements[0*4+1] = (oneMinusCos * xy) - zs; rotMat.elements[0*4+2] = (oneMinusCos * zx) + ys; rotMat.elements[0*4+3] = 0.0; rotMat.elements[1*4+0] = (oneMinusCos * xy) + zs; rotMat.elements[1*4+1] = (oneMinusCos * yy) + cosAngle; rotMat.elements[1*4+2] = (oneMinusCos * yz) - xs; rotMat.elements[1*4+3] = 0.0; rotMat.elements[2*4+0] = (oneMinusCos * zx) - ys; rotMat.elements[2*4+1] = (oneMinusCos * yz) + xs; rotMat.elements[2*4+2] = (oneMinusCos * zz) + cosAngle; rotMat.elements[2*4+3] = 0.0; rotMat.elements[3*4+0] = 0.0; rotMat.elements[3*4+1] = 0.0; rotMat.elements[3*4+2] = 0.0; rotMat.elements[3*4+3] = 1.0; rotMat = rotMat.multiply(self); self.elements = rotMat.elements; } return self; }); $loc.multiply = new Sk.builtin.func(function(self, right) { var tmp = Sk.misceval.callsim(mod.Mat44); for (var i = 0; i < 4; i++) { tmp.elements[i*4+0] = (self.elements[i*4+0] * right.elements[0*4+0]) + (self.elements[i*4+1] * right.elements[1*4+0]) + (self.elements[i*4+2] * right.elements[2*4+0]) + (self.elements[i*4+3] * right.elements[3*4+0]) ; tmp.elements[i*4+1] = (self.elements[i*4+0] * right.elements[0*4+1]) + (self.elements[i*4+1] * right.elements[1*4+1]) + (self.elements[i*4+2] * right.elements[2*4+1]) + (self.elements[i*4+3] * right.elements[3*4+1]) ; tmp.elements[i*4+2] = (self.elements[i*4+0] * right.elements[0*4+2]) + (self.elements[i*4+1] * right.elements[1*4+2]) + (self.elements[i*4+2] * right.elements[2*4+2]) + (self.elements[i*4+3] * right.elements[3*4+2]) ; tmp.elements[i*4+3] = (self.elements[i*4+0] * right.elements[0*4+3]) + (self.elements[i*4+1] * right.elements[1*4+3]) + (self.elements[i*4+2] * right.elements[2*4+3]) + (self.elements[i*4+3] * right.elements[3*4+3]) ; } self.elements = tmp.elements; return self; }); /* Following gluLookAt implementation is adapted from * the Mesa 3D Graphics library. http://www.mesa3d.org */ // todo; rewrite this with proper vec/mat ops $loc.lookAt = new Sk.builtin.func(function(self, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) { /* Z vector */ var z = [ eyeX - centerX, eyeY - centerY, eyeZ - centerZ ]; var mag = Math.sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]); if (mag) { z[0] /= mag; z[1] /= mag; z[2] /= mag; } /* Y vector */ var y = [ upX, upY, upZ ]; /* X vector = Y cross Z */ var x = []; x[0] = y[1] * z[2] - y[2] * z[1]; x[1] = -y[0] * z[2] + y[2] * z[0]; x[2] = y[0] * z[1] - y[1] * z[0]; /* Recompute Y = Z cross X */ y[0] = z[1] * x[2] - z[2] * x[1]; y[1] = -z[0] * x[2] + z[2] * x[0]; y[2] = z[0] * x[1] - z[1] * x[0]; /* mpichler, 19950515 */ /* cross product gives area of parallelogram, which is < 1.0 for * non-perpendicular unit-length vectors; so normalize x, y here */ mag = Math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); if (mag) { x[0] /= mag; x[1] /= mag; x[2] /= mag; } mag = Math.sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]); if (mag) { y[0] /= mag; y[1] /= mag; y[2] /= mag; } var lookAt = Sk.misceval.callsim(mod.Mat44); lookAt.elements[0 * 4 + 0] = x[0]; lookAt.elements[1 * 4 + 0] = x[1]; lookAt.elements[2 * 4 + 0] = x[2]; lookAt.elements[3 * 4 + 0] = 0.; lookAt.elements[0 * 4 + 1] = y[0]; lookAt.elements[1 * 4 + 1] = y[1]; lookAt.elements[2 * 4 + 1] = y[2]; lookAt.elements[3 * 4 + 1] = 0.; lookAt.elements[0 * 4 + 2] = z[0]; lookAt.elements[1 * 4 + 2] = z[1]; lookAt.elements[2 * 4 + 2] = z[2]; lookAt.elements[3 * 4 + 2] = 0.; lookAt.elements[0 * 4 + 3] = 0.; lookAt.elements[1 * 4 + 3] = 0.; lookAt.elements[2 * 4 + 3] = 0.; lookAt.elements[3 * 4 + 3] = 1.; // log(lookAt.elements); lookAt = lookAt.multiply(self); self.elements = lookAt.elements; self.translate(-eyeX, -eyeY, -eyeZ); // log(this.elements); return self; }); }, 'Mat44', []); // todo; should probably put this in a math package mod.Mat33 = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func(function(self) { Sk.misceval.callsim($loc.loadIdentity, self); }); $loc.loadIdentity = new Sk.builtin.func(function(self) { self.elements = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]; }); }, 'Mat33', []); mod.Vec3 = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func(function(self, x, y, z) { self.x = x; self.y = y; self.z = z; }); $loc.__sub__ = new Sk.builtin.func(function(self, other) { return Sk.misceval.callsim(mod.Vec3, self.x - other.x, self.y - other.y, self.z - other.z); }); }, 'Vec3', []); mod.cross = new Sk.builtin.func(function(v1, v2) { goog.asserts.assert(v1 instanceof mod.Vec3 && v2 instanceof mod.Vec3); return Sk.misceval.callsim(mod.Vec3, v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); }); return mod; };