/* * Real3D FlipBook [https://real3dflipbook.com] * @author creativeinteractivemedia [https://codecanyon.net/user/creativeinteractivemedia/portfolio] * @version 4.10 * @date 2025-05-15 */ /** * MOD3 3D Modifier Library for JavaScript * port of AS3DMod ActionScript3 library (http://code.google.com/p/as3dmod/) * * @version 1.0.0 (2023-01-03 16:08:34) * https://github.com/foo123/MOD3 * **//** * MOD3 3D Modifier Library for JavaScript * port of AS3DMod ActionScript3 library (http://code.google.com/p/as3dmod/) * * @version 1.0.0 (2023-01-03 16:08:34) * https://github.com/foo123/MOD3 * **/ !function(root, name, factory) { "use strict"; if (('object' === typeof module) && module.exports) /* CommonJS */ (module.$deps = module.$deps||{}) && (module.exports = module.$deps[name] = factory.call(root)); else if (('function' === typeof define) && define.amd && ('function' === typeof require) && ('function' === typeof require.specified) && require.specified(name) /*&& !require.defined(name)*/) /* AMD */ define(name, ['module'], function(module) {factory.moduleUri = module.uri; return factory.call(root);}); else if (!(name in root)) /* Browser/WebWorker/.. */ (root[name] = factory.call(root)||1) && ('function' === typeof(define)) && define.amd && define(function() {return root[name];}); }( /* current root */ 'undefined' !== typeof self ? self : this, /* module name */ "MOD3", /* module factory */ function ModuleFactory__MOD3(undef) { "use strict"; var HAS = Object.prototype.hasOwnProperty, toString = Object.prototype.toString, def = Object.defineProperty, stdMath = Math, PI = stdMath.PI, TWO_PI = 2*PI, HALF_PI = PI/2, INV_PI = 1/PI, EMPTY_ARR = [], EMPTY_OBJ = {}, NOP = function() {}, isNode = ("undefined" !== typeof global) && ("[object global]" === toString.call(global)), isBrowser = ("undefined" !== typeof window) && ("[object Window]" === toString.call(window)) ; // basic backwards-compatible "class" construction function makeSuper(superklass) { var called = {}; return function $super(method, args) { var self = this, m = ':'+method, ret; if (1 === called[m]) return (superklass.prototype.$super || NOP).call(self, method, args); called[m] = 1; ret = ('constructor' === method ? superklass : (superklass.prototype[method] || NOP)).apply(self, args || []); called[m] = 0; return ret; }; } function makeClass(superklass, klass, statik) { if (arguments.length < 2) { klass = superklass; superklass = null; } var C = HAS.call(klass, 'constructor') ? klass.constructor : function() {}, p; if (superklass) { C.prototype = Object.create(superklass.prototype); C.prototype.$super = makeSuper(superklass); } else { C.prototype.$super = NOP; } C.prototype.constructor = C; for (p in klass) { if (HAS.call(klass, p) && ('constructor' !== p)) { C.prototype[p] = klass[p]; } } if (statik) { for (p in statik) { if (HAS.call(statik, p)) { C[p] = statik[p]; } } } return C; } var MOD3 = { VERSION: "1.0.0", Class: makeClass }; /** * MOD3 Constants and Auxilliary methods **/ MOD3.Constants = { // cache math constants for reference and optimization PI: PI, invPI: INV_PI, halfPI: HALF_PI, doublePI: TWO_PI, toRad: PI/180, toDeg: 180/PI }; MOD3.ModConstant = { NONE: 0, LEFT: -1, RIGHT: 1, X: 1, Y: 2, Z: 4, Xi: 0, Yi: 1, Zi: 2 }; MOD3.XYZi = [ null, 0, 1, null, 2 ]; MOD3.iXYZ = [ 1, 2, 4 ]; MOD3.xyz = [ "x", "y", "z" ]; MOD3.XYZ = [ "X", "Y", "Z" ]; // Typed Arrays Substitutes MOD3.Array32F = typeof Float32Array !== "undefined" ? Float32Array : Array; MOD3.Array64F = typeof Float64Array !== "undefined" ? Float64Array : Array; MOD3.Array8I = typeof Int8Array !== "undefined" ? Int8Array : Array; MOD3.Array16I = typeof Int16Array !== "undefined" ? Int16Array : Array; MOD3.Array32I = typeof Int32Array !== "undefined" ? Int32Array : Array; MOD3.Array8U = typeof Uint8Array !== "undefined" ? Uint8Array : Array; MOD3.Array16U = typeof Uint16Array !== "undefined" ? Uint16Array : Array; MOD3.Array32U = typeof Uint32Array !== "undefined" ? Uint32Array : Array; // vector typed-array MOD3.VecArray = MOD3.Array32F; /** * MOD3 Math Utilities Class **/ MOD3.XMath = { normalize: function(start, end, val) { var range = end - start; return 0 === range ? 1 : MOD3.XMath.trim(0, 1, (val - start)/end); }, toRange: function(start, end, normalized) { var range = end - start; return 0 === range ? 0 : (start + range*normalized); }, inRange: function(start, end, value, excluding) { return false !== excluding ? (value >= start && value <= end) : (value > start && value < end); }, sign: function(val, ifZero) { return 0 === val ? (ifZero || 0) : (val > 0 ? 1 : -1); }, trim: function(start, end, value) { return value < start ? start : (value > end ? end : value); }, wrap: function(start, end, value) { var r = end - start; return value < start ? (value + r) : (value >= end ? value - r : value); }, degToRad: function(deg) { return deg/180*PI; }, radToDeg: function(rad) { return rad/PI*180; }, presicion: function(number, precision) { var r = stdMath.pow(10, precision); return stdMath.round(number*r)/r; }, uceil: function(val) { return val < 0 ? stdMath.floor(val) : stdMath.ceil(val); } }; // alias MOD3.XMath.clamp = MOD3.XMath.trim; /** * MOD3 Range Auxilliary Class **/ MOD3.Range = MOD3.Class({ constructor: function Range(s, e) { var self = this; if (!(self instanceof Range)) return new Range(s, e); self.start = null != s ? s : 0; self.end = null != e ? e : 1; }, name: "Range", start: 0, end: 1, dispose: function() { var self = this; self.start = null; self.end = null; return self; }, getSize: function() { return this.end - this.start; }, move: function(amount) { this.start += amount; this.end += amount; }, isIn: function(n) { return (n >= this.start && n <= this.end); }, normalize: function(n) { return MOD3.XMath.normalize(this.start, this.end, n); }, toRange: function(n) { return MOD3.XMath.toRange(this.start, this.end, n); }, trim: function(n) { return MOD3.XMath.trim(this.start, this.end, n); }, interpolate: function(n, r) { return MOD3.XMath.toRange(this.start, this.end, r.normalize(n)); }, toString: function() { return "[" + this.start + " - " + this.end + "]"; } }); /** * MOD3 Phase Auxilliary Class **/ MOD3.Phase = MOD3.Class({ constructor: function Phase(v) { var self = this; if (!(self instanceof Phase)) return new Phase(v); self.value = v || 0; }, name: "Phase", value: 0, dispose: function() { this.value = null; return this; }, getPhasedValue: function() { return stdMath.sin(this.value); }, getAbsPhasedValue: function() { return stdMath.abs(stdMath.sin(this.value)); }, getNormValue: function() { return (stdMath.sin(this.value) + 1)*0.5; } }); /** * MOD3 2D Point Class **/ MOD3.Point = MOD3.Class({ constructor: function Point(x, y) { var self = this; if (!(self instanceof Point)) return new Point(x, y); self.x = x || 0; self.y = y || 0; }, name: "Point", x: 0, y: 0, dispose: function() { var self = this; self.x = null; self.y = null; return self; }, clone: function() { return new MOD3.Point(this.x, this.y); } }); /** * MOD3 2D Transform Matrix Class **/ MOD3.Matrix = MOD3.Class(null, { constructor: function Matrix(m11, m12, m21, m22) { var self = this; if (!(self instanceof Matrix)) return new Matrix(m11, m12, m21, m22); self.m = new MOD3.VecArray([ m11 == null ? 1 : m11, m12 == null ? 0 : m12, m21 == null ? 0 : m21, m22 == null ? 1 : m22 ]); }, name: "Matrix", m: null, dispose: function() { this.m = null; return this; }, reset: function() { var m = this.m; m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; return this; }, rotate: function(angle) { var m = this.m, c = stdMath.cos(angle), s = stdMath.sin(angle); m[0] = c; m[1] = -s; m[2] = s; m[3] = c; return this; }, scale: function(sx, sy) { var m = this.m; m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; if (sx != null) { m[0] = sx; m[3] = sx; } if (sy != null) { m[3] = sy; } return this; }, multiply: function(b) { return MOD3.Matrix.mult(this, b); }, transformPoint: function(p) { var xy = MOD3.Matrix.transform(this, [p.x, p.y]); return new MOD3.Point(xy[0], xy[1]); }, transformPointSelf: function(p) { var xy = MOD3.Matrix.transform(this, [p.x, p.y]); p.x = xy[0]; p.y = xy[1]; return p; }, clone: function() { var m = this.m; return new MOD3.Matrix(m[0], m[1], m[2], m[3]); } }, { transform: function(m2, xy) { var m = m2.m, x = xy[0], y = xy[1]; xy[0] = m[0]*x + m[1]*y; xy[1] = m[2]*x + m[3]*y; return xy; }, mult: function(m1, m2) { var a = m1.m, b = m2.m, a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; a[0] = a0*b[0] + a1*b[2]; a[1] = a0*b[1] + a1*b[3]; a[2] = a2*b[0] + a3*b[2]; a[3] = a2*b[1] + a3*b[3]; return m1; } }); /** * MOD3 Vector3 Class **/ MOD3.Vector3 = MOD3.Class(null, { constructor: function Vector3(x, y, z) { var self = this; if (!(self instanceof Vector3)) return new Vector3(x, y, z); // use an internal typed-array for speed var v = new MOD3.VecArray(3); if (x && (3 === x.length)) { // array passed v[0] = x[0] || 0; v[1] = x[1] || 0; v[2] = x[2] || 0; } else { // numbers passed v[0] = x || 0; v[1] = y || 0; v[2] = z || 0; } self.xyz = v; }, name: "Vector3", xyz: null, dispose: function() { this.xyz = null; return this; }, getXYZ: function() { // copy it return new MOD3.VecArray(this.xyz); }, getXYZRef: function() { return this.xyz; }, setXYZ: function(w) { var v = this.xyz; v[0] = w[0]; v[1] = w[1]; v[2] = w[2]; return this; }, setXYZRef: function(xyz) { this.xyz = xyz; return this; }, clone: function() { return new MOD3.Vector3(this.xyz); }, equalsSelf: function(b) { var v = this.xyz, w = b.xyz; return (v[0] === w[0]) && (v[1] === w[1]) && (v[2] === w[2]); }, zeroSelf: function() { var v = this.xyz; v[0] = 0; v[1] = 0; v[2] = 0; return this; }, negate: function() { var v = this.xyz; return new MOD3.Vector3(-v[0], -v[1], -v[2]); }, negateSelf: function() { var v = this.xyz; v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; return this; }, add: function(b) { var v = this.xyz, w = b.xyz; return new MOD3.Vector3(v[0] + w[0], v[1] + w[1], v[2] + w[2]); }, addSelf: function(b) { var v = this.xyz, w = b.xyz; v[0] += w[0]; v[1] += w[1]; v[2] += w[2]; return this; }, subtract: function(b) { var v = this.xyz, w = b.xyz; return new MOD3.Vector3(v[0] - w[0], v[1] - w[1], v[2] - w[2]); }, subtractSelf: function(b) { var v = this.xyz, w = b.xyz; v[0] -= w[0]; v[1] -= w[1]; v[2] -= w[2]; return this; }, multiplyScalar: function(s) { var v = this.xyz; return new MOD3.Vector3(v[0]*s, v[1]*s, v[2]*s); }, multiplyScalarSelf: function(s) { var v = this.xyz; v[0] *= s; v[1] *= s; v[2] *= s; return this; }, multiply: function(b) { var v = this.xyz, w = b.xyz; return new MOD3.Vector3(v[0] * w[0], v[1] * w[1], v[2] * w[2]); }, multiplySelf: function(b) { var v = this.xyz, w = b.xyz; v[0] *= w[0]; v[1] *= w[1]; v[2] *= w[2]; return this; }, divide: function(s) { var v = this.xyz; return new MOD3.Vector3(v[0] / s, v[1] / s, v[2] / s); }, divideSelf: function(s) { var v = this.xyz; v[0] /= s; v[1] /= s; v[2] /= s; return this; }, normalize: function() { var v = this.xyz, x = v[0], y = v[1], z = v[2], m = x * x + y * y + z * z, n; if (0 < m) { n = stdMath.sqrt(m); x /= n; y /= n; z /= n; } return new MOD3.Vector3(x, y, z); }, normalizeSelf: function() { var v = this.xyz, x = v[0], y = v[1], z = v[2], m = x * x + y * y + z * z, n; if (0 < m) { n = stdMath.sqrt(m); x /= n; y /= n; z /= n; } v[0] = x; v[1] = y; v[2] = z; return this; }, getMagnitude: function() { var v = this.xyz, x = v[0], y = v[1], z = v[2]; return stdMath.sqrt(x*x + y*y + z*z); }, setMagnitude: function(m) { this.normalizeSelf(); var v = this.xyz; v[0] *= m; v[1] *= m; v[2] *= m; return this; }, dot: function(b) { var v = this.xyz, w = b.xyz; return v[0]*w[0] + v[1]*w[1] + v[2]*w[2]; }, cross: function(b) { var v = this.xyz, w = b.xyz, x1 = v[0], y1 = v[1], z1 = v[2], x2 = w[0], y2 = w[1], z2 = w[2]; return new MOD3.Vector3(y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2); }, crossSelf: function(v) { var v = this.xyz, w = b.xyz, x1 = v[0], y1 = v[1], z1 = v[2], x2 = w[0], y2 = w[1], z2 = w[2]; v[0] = y1 * z2 - z1 * y2; v[1] = z1 * x2 - x1 * z2; v[2] = x1 * y2 - y1 * x2; return this; }, distance: function(b) { var v = this.xyz, w = b.xyz, dx = v[0] - w[0], dy = v[1] - w[1], dz = v[2] - w[2]; return stdMath.sqrt(dx*dx + dy*dy + dz*dz); }, toString: function() { var v = this.xyz; return "[" + v[0] + " , " + v[1] + " , " + v[2] + "]"; } }, { ZERO: function() { return new MOD3.Vector3(0, 0, 0); }, X: function(direct_or_complement) { return false === direct_or_complement ? new MOD3.Vector3(0, 1, 1) : new MOD3.Vector3(1, 0, 0); }, Y: function(direct_or_complement) { return false === direct_or_complement ? new MOD3.Vector3(1, 0, 1) : new MOD3.Vector3(0, 1, 0); }, Z: function(direct_or_complement) { return false === direct_or_complement ? new MOD3.Vector3(1, 1, 0) : new MOD3.Vector3(0, 0, 1); }, dot: function(v, w) { return v[0]*w[0] + v[1]*w[1] + v[2]*w[2]; }, equals: function(v, w) { return (v[0] === w[0]) && (v[1] === w[1]) && (v[2] === w[2]); }, cross: function(v, w) { var vw = new MOD3.VecArray(3); vw[0] = v[1] * w[2] - v[2] * w[1]; vw[1] = v[2] * w[0] - v[0] * w[2]; vw[2] = v[0] * w[1] - v[1] * w[0]; return vw; }, mod: function(v) { var x = v[0], y = v[1], z = v[2]; return stdMath.sqrt(x*x + y*y + z*z); }, dist: function(v, w) { var dx = v[0] - w[0], dy = v[1] - w[1], dz = v[2] - w[2]; return stdMath.sqrt(dx*dx + dy*dy + dz*dz); }, add: function(v, w) { v[0] += w[0]; v[1] += w[1]; v[2] += w[2]; return v; }, sub: function(v, w) { v[0] -= w[0]; v[1] -= w[1]; v[2] -= w[2]; return v; }, mul: function(v, w) { v[0] *= w[0]; v[1] *= w[1]; v[2] *= w[2]; return v; }, muls: function(v, m) { v[0] *= m; v[1] *= m; v[2] *= m; return v; }, norm: function(v) { var x = v[0], y = v[1], z = v[2], m = x*x + y*y + z*z, n; if (0 < m) { n = stdMath.sqrt(m); x /= n; y /= n; z /= n; } v[0] = x; v[1] = y; v[2] = z; return v; } }); // alaises MOD3.Vector3.modulo = MOD3.Vector3.mod; MOD3.Vector3.distance = MOD3.Vector3.dist; MOD3.Vector3.prototype.dotSelf = MOD3.Vector3.prototype.dot; MOD3.Vector3.prototype.distanceSelf = MOD3.Vector3.prototype.distance; /** * MOD3 3D Transform Matrix Class **/ MOD3.Matrix4 = MOD3.Class(null, { constructor: function Matrix4(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { var self = this; if (!(self instanceof Matrix4)) return new Matrix4(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44); self.m = new MOD3.VecArray([ n11 == null ? 1 : n11, n12 == null ? 0 : n12, n13 == null ? 0 : n13, n14 == null ? 0 : n14, n21 == null ? 0 : n21, n22 == null ? 1 : n22, n23 == null ? 0 : n23, n24 == null ? 0 : n24, n31 == null ? 0 : n31, n32 == null ? 0 : n32, n33 == null ? 1 : n33, n34 == null ? 0 : n34, n41 == null ? 0 : n41, n42 == null ? 0 : n42, n43 == null ? 0 : n43, n44 == null ? 1 : n44 ]); }, name: "Matrix4", m: null, dispose: function() { this.m = null; return this; }, reset: function() { var m = this.m; m[0 ] = 1; m[1 ] = 0; m[2 ] = 0; m[3 ] = 0; m[4 ] = 0; m[5 ] = 1; m[6 ] = 0; m[7 ] = 0; m[8 ] = 0; m[9 ] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; return this; }, translate: function(tx, ty, tz, reset) { var m = this.m; if (true === reset) this.reset(); m[3 ] = tx; m[7 ] = ty; m[11] = tz; return this; }, scale: function(sx, sy, sz, reset) { var m = this.m; if (true === reset) this.reset(); m[0 ] = sx; m[5 ] = sy; m[10] = sz; return this; }, rotate: function(rx, ry, rz, theta, reset) { var m = this.m, nCos = stdMath.cos(theta), nSin = stdMath.sin(theta), scos = 1 - nCos, sxy = rx*ry*scos, syz = ry*rz*scos, sxz = rx*rz*scos, sz = nSin*rz, sy = nSin*ry, sx = nSin*rx ; if (true === reset) this.reset(); m[0 ] = nCos + rx*rx*scos; m[1 ] = -sz + sxy; m[2 ] = sy + sxz; m[3 ] = 0; m[4 ] = sz + sxy; m[5 ] = nCos + ry*ry*scos; m[6 ] = -sx + syz; m[7 ] = 0; m[8 ] = -sy + sxz; m[9 ] = sx + syz; m[10] = nCos + rz*rz*scos; m[11] = 0; return this; }, translateFromVector: function(v, reset) { return this.translate(v.xyz[0], v.xyz[1], v.xyz[2], reset); }, scaleFromVector: function(v, reset) { return this.scale(v.xyz[0], v.xyz[1], v.xyz[2], reset); }, rotateFromVector: function(v, theta, reset) { return this.rotate(v.xyz[0], v.xyz[1], v.xyz[2], theta, reset); }, multiply: function(b) { return MOD3.Matrix4.mult(this, b); }, multiplyVector: function(v) { MOD3.Matrix4.multXYZ(this, v.xyz); return v; } }, { multXYZ: function(m4, v) { var m = m4.m, x = v[0], y = v[1], z = v[2]; v[0] = x*m[0 ] + y*m[1 ] + z*m[2 ] + m[3 ]; v[1] = x*m[4 ] + y*m[5 ] + z*m[6 ] + m[7 ]; v[2] = x*m[8 ] + y*m[9 ] + z*m[10] + m[11]; return v; }, mult: function(m1, m2) { var a = m1.m, b = m2.m, a11 = a[0 ], b11 = b[0 ], a21 = a[4 ], b21 = b[4 ], a31 = a[8 ], b31 = b[8 ], a12 = a[1 ], b12 = b[1 ], a22 = a[5 ], b22 = b[5 ], a32 = a[9 ], b32 = b[9 ], a13 = a[2 ], b13 = b[2 ], a23 = a[6 ], b23 = b[6 ], a33 = a[10], b33 = b[10], a14 = a[3 ], b14 = b[3 ], a24 = a[7 ], b24 = b[7 ], a34 = a[11], b34 = b[11]; a[0 ] = a11*b11 + a12*b21 + a13*b31; a[1 ] = a11*b12 + a12*b22 + a13*b32; a[2 ] = a11*b13 + a12*b23 + a13*b33; a[3 ] = a11*b14 + a12*b24 + a13*b34 + a14; a[4 ] = a21*b11 + a22*b21 + a23*b31; a[5 ] = a21*b12 + a22*b22 + a23*b32; a[6 ] = a21*b13 + a22*b23 + a23*b33; a[7 ] = a21*b14 + a22*b24 + a23*b34 + a24; a[8 ] = a31*b11 + a32*b21 + a33*b31; a[9 ] = a31*b12 + a32*b22 + a33*b32; a[10] = a31*b13 + a32*b23 + a33*b33; a[11] = a31*b14 + a32*b24 + a33*b34 + a34; return m1; } }); // aliases MOD3.Matrix4.prototype.translationMatrix = MOD3.Matrix4.prototype.translate; MOD3.Matrix4.prototype.scaleMatrix = MOD3.Matrix4.prototype.scale; MOD3.Matrix4.prototype.rotationMatrix = MOD3.Matrix4.prototype.rotate; MOD3.Matrix4.prototype.translationMatrixFromVector = MOD3.Matrix4.prototype.translateFromVector; MOD3.Matrix4.prototype.scaleMatrixFromVector = MOD3.Matrix4.prototype.scaleFromVector; MOD3.Matrix4.prototype.rotationMatrixFromVector = MOD3.Matrix4.prototype.rotateFromVector; // fast list utilities MOD3.List = { operate: function operate(x, F, F0, i0, i1, reverse) { var len = x.length; if (arguments.length < 5) i1 = len-1; if (0 > i1) i1 += len; if (arguments.length < 4) i0 = 0; if (i0 > i1) return F0; if (true === reverse) { var i, k, l=i1-i0+1, l1=l-1, r=l&15, q=r&1, lr=l1-r, Fv=q?F(F0,x[i1],i1):F0; for (i=l1-q; i>lr; i-=2) { k = i0+i; Fv = F(F(Fv,x[k],k),x[k-1],k-1); } for (i=lr; i>=0; i-=16) { k = i0+i; Fv = F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(Fv,x[k],k),x[k-1],k-1),x[k-2],k-2),x[k-3],k-3),x[k-4],k-4),x[k-5],k-5),x[k-6],k-6),x[k-7],k-7),x[k-8],k-8),x[k-9],k-9),x[k-10],k-10),x[k-11],k-11),x[k-12],k-12),x[k-13],k-13),x[k-14],k-14),x[k-15],k-15); } } else { var i, k, l=i1-i0+1, r=l&15, q=r&1, Fv=q?F(F0,x[i0],i0):F0; for (i=q; i i1) i1 += len; if (arguments.length < 3) i0 = 0; if (i0 > i1) return x; var i, k, l=i1-i0+1, l1, lr, r, q; if (true === reverse) { l1=l-1; r=l&15; q=r&1; lr=l1-r; if (q) F(x[i1]); for (i=l1-q; i>lr; i-=2) { k = i0+i; F(x[k ]); F(x[k-1]); } for (i=lr; i>=0; i-=16) { k = i0+i; F(x[k ] ); F(x[k-1] ); F(x[k-2] ); F(x[k-3] ); F(x[k-4] ); F(x[k-5] ); F(x[k-6] ); F(x[k-7] ); F(x[k-8] ); F(x[k-9] ); F(x[k-10]); F(x[k-11]); F(x[k-12]); F(x[k-13]); F(x[k-14]); F(x[k-15]); } } else { r=l&15; q=r&1; if (q) F(x[i0]); for (i=q; i 0 ? (xyz[0] - minX) / width : 0, height > 0 ? (xyz[1] - minY) / height : 0, depth > 0 ? (xyz[2] - minZ) / depth : 0); }); return self; }, resetGeometry: function() { var self = this; MOD3.List.each(self.vertices, reset); return self; }, collapseGeometry: function() { var self = this; MOD3.List.each(self.vertices, collapse); self.analyzeGeometry(); return self; }, getMin: function(axis) { var self = this; return MOD3.ModConstant.X === axis ? self.minX : (MOD3.ModConstant.Y === axis ? self.minY : (MOD3.ModConstant.Z === axis ? self.minZ : -1)) ; }, getMax: function(axis) { var self = this; return MOD3.ModConstant.X === axis ? self.maxX : (MOD3.ModConstant.Y === axis ? self.maxY : (MOD3.ModConstant.Z === axis ? self.maxZ : -1)) ; }, getSize: function(axis) { var self = this; return MOD3.ModConstant.X === axis ? self.width : (MOD3.ModConstant.Y === axis ? self.height : (MOD3.ModConstant.Z === axis ? self.depth : -1)) ; }, update: function() { // do nothing return this; }, preApply: function() { // do nothing return this; }, postApply: function() { // do nothing return this; }, updateMeshPosition: function(p) { // do nothing return this; } }); MOD3.Library3d = { id : "Library3d", Mesh : MOD3.MeshProxy, Vertex : MOD3.VertexProxy }; MOD3.Factory = { getLibrary: function(json) { if (json && json.library && MOD3[json.library]) return MOD3[json.library]; // dummy, default return MOD3.Library3d; } ,getMeshProxy: function(lib3D) { if (arguments.length) return lib3D.Mesh ? new lib3D.Mesh() : null; return null; } ,getModifier: function(json) { if (json && json.modifier && MOD3[json.modifier]) return new MOD3[json.modifier](); return null; } /* ,getMesh: function(json) { if (json && json.mesh && MOD3[json.mesh] ) return new MOD3.MeshProxy().unserialize(json); // dummy, default return new MOD3.MeshProxy(); } ,getVertex: function(json) { if (json && json.vertex && MOD3[json.vertex]) return new MOD3.VertexProxy().unserialize(json); // dummy, default return new MOD3.VertexProxy(); }*/ }; /** * MOD3 Modifier & ModifierStack Classes **/ var _modCount = 0; MOD3.Modifier = MOD3.Class({ constructor: function Modifier() { var self = this; self.id = ++_modCount; self.name = 'Modifier'; self.axes = MOD3.ModConstant.NONE; self.constraint = MOD3.ModConstant.NONE; self.enabled = true; }, id: null, name: 'Modifier', axes: null, constraint: null, enabled: true, dispose: function() { var self = this; self.name = null; self.axes = null; self.constraint = null; return self; }, enable: function(enabled) { if (arguments.length) { this.enabled = !!enabled; return this; } return this.enabled; }, constraintAxes: function(axes) { this.axes = axes || MOD3.ModConstant.NONE; return this; }, setConstraint: function(c) { this.constraint = c || MOD3.ModConstant.NONE; return this; }, // override apply: function(modifiable) { return this; }, toString: function() { return '[Modifier '+this.name+']'; } }); MOD3.ModifierStack = MOD3.Class({ constructor: function ModifierStack(lib3d, mesh) { var self = this; if (!(self instanceof ModifierStack)) return new ModifierStack(lib3d, mesh); self.stack = []; self.setModifiable(MOD3.Factory.getMeshProxy(lib3d), mesh); }, name: "ModifierStack", modifiable: null, stack: null, dispose: function(withModifiers) { var self = this; if (withModifiers && self.stack) while (self.stack.length) self.stack.pop().dispose(); if (self.modifiable) self.modifiable.dispose(); self.stack = null; self.modifiable = null; return self; }, getModifiable: function() { return this.modifiable; }, setModifiable: function(modifiable, mesh) { var self = this; self.modifiable = modifiable; if (mesh) self.modifiable.setMesh(mesh); return self; }, add: function(modifier) { var self = this; if (modifier) self.stack.push(modifier); return self; }, apply: function() { var self = this, modifiable = self.modifiable, stack = self.stack; if (modifiable && stack && stack.length) modifiable .preApply() .resetGeometry() .applyModifiers(stack) .postApply() .update() ; return self; }, collapse: function() { var self = this, modifiable = self.modifiable, stack = self.stack; if (modifiable && stack && stack.length) { modifiable .preApply() .resetGeometry() .applyModifiers(stack) .collapseGeometry() .postApply() .update() ; stack.length = 0; } return self; }, clear: function() { var self = this; if (self.stack) self.stack.length = 0; return self; } }); // aliases MOD3.ModifierStack.prototype.getMeshInfo = MOD3.ModifierStack.prototype.getModifiable; MOD3.ModifierStack.prototype.addModifier = MOD3.ModifierStack.prototype.add; !function(MOD3) { "use strict"; /** * MOD3 Pivot Modifier **/ /**[DOC_MD] * ### Pivot modifier * * Allows to move the pivot point of a 3D mesh. * * @author Bartek Drozdz * [/DOC_MD]**/ MOD3.Pivot = MOD3.Class(MOD3.Modifier, { constructor: function Pivot(x, y, z) { var self = this; if (!(self instanceof Pivot)) return new Pivot(x, y, z); self.$super('constructor'); self.name = 'Pivot'; self.vector = new MOD3.Vector3(x||0, y||0, z||0); }, vector: null, dispose: function() { var self = this; self.vector.dispose(); self.vector = null; self.$super('dispose'); return self; }, setMeshCenter: function(modifiable) { var self = this; self.vector = new MOD3.Vector3( -(modifiable.minX + 0.5*modifiable.width), -(modifiable.minY + 0.5*modifiable.height), -(modifiable.minZ + 0.5*modifiable.depth) ); return self; }, apply: function(modifiable) { var self = this, pivot = self.vector, pv = pivot.xyz; MOD3.List.each(modifiable.vertices, function(v) { v.setXYZ(MOD3.Vector3.add(v.getXYZ(), pv)); }); modifiable.updateMeshPosition(pivot.negate()); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Bend Modifier **/ /**[DOC_MD] * ### Bend modifier * * Bends an object along an axis. * * @author Bartek Drozdz * [/DOC_MD]**/ var stdMath = Math, PI = stdMath.PI, TWO_PI = 2*PI, HALF_PI = PI/2; MOD3.Bend = MOD3.Class(MOD3.Modifier, { constructor: function Bend(force, offset, angle) { var self = this; if (!(self instanceof Bend)) return new Bend(force, offset, angle); self.$super('constructor'); self.name = 'Bend'; self.constraint = MOD3.ModConstant.NONE; self.switchAxes = false; self.force = force || 0; self.offset = offset || 0; self.angle = angle || 0; }, force: 0, offset: 0, angle: 0, switchAxes: false, dispose: function() { var self = this; self.force = null; self.offset = null; self.angle = null; self.switchAxes = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this; if (0 === self.force) return self; var constraint = self.constraint, switchAxes = self.switchAxes, force = self.force, offset = stdMath.min(1, stdMath.max(0, self.offset)), a = self.angle, max = switchAxes ? modifiable.midAxis : modifiable.maxAxis, min = modifiable.minAxis, mid = switchAxes ? modifiable.maxAxis : modifiable.midAxis, width = modifiable.getSize(max), height = modifiable.getSize(mid), origin = modifiable.getMin(max), //diagAngle = stdMath.atan2(height, width), m1 = new MOD3.Matrix().rotate(a), m2 = new MOD3.Matrix().rotate(-a), distance = origin + width * offset, radius = width / PI / force, bendAngle = TWO_PI * (width / (radius * TWO_PI)) ; MOD3.List.each(modifiable.vertices, function(v) { var xyz = v.getXYZ(), vmax = xyz[MOD3.XYZi[max]], vmid = xyz[MOD3.XYZi[mid]], vmin = xyz[MOD3.XYZi[min]], np = MOD3.Matrix.transform(m1, [vmax, vmid]), p, fa, op, ow, np2 ; vmax = np[0]; vmid = np[1]; p = (vmax - origin) / width; if ( ((MOD3.ModConstant.LEFT === constraint) && (p <= offset)) || ((MOD3.ModConstant.RIGHT === constraint) && (p >= offset)) ) { /* do nothing */ } else { fa = (HALF_PI - bendAngle * offset) + (bendAngle * p); op = stdMath.sin(fa) * (radius + vmin); ow = stdMath.cos(fa) * (radius + vmin); vmin = op - radius; vmax = distance - ow; } np2 = MOD3.Matrix.transform(m2, [vmax, vmid]); vmax = np2[0]; vmid = np2[1]; xyz[MOD3.XYZi[max]] = vmax; xyz[MOD3.XYZi[mid]] = vmid; xyz[MOD3.XYZi[min]] = vmin; v.setXYZ(xyz); }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Bloat Modifier **/ /**[DOC_MD] * ### Bloat modifier * * Bloats a mesh by forcing vertices out of specified sphere * * @author makc * [/DOC_MD]**/ var stdMath = Math; MOD3.Bloat = MOD3.Class(MOD3.Modifier, { constructor: function Bloat(radius, a, center) { var self = this; if (!(self instanceof Bloat)) return new Bloat(radius, a, center); self.$super('constructor'); self.name = 'Bloat'; self.radius = radius || 0; self.a = null == a ? 0.01 : a; self.center = center || MOD3.Vector3.ZERO(); //self.u = MOD3.Vector3.ZERO(); }, radius: 0, a: 0.01, center: null, //u: null, dispose: function() { var self = this; self.center.dispose(); self.center = null; self.radius = null; self.a = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, center = self.center.xyz, radius = stdMath.max(0, self.radius), a = stdMath.max(0, self.a); MOD3.List.each(modifiable.vertices, function(v) { // get a vector towards vertex // change norm to norm + r * exp (-a * norm) var uu = MOD3.Vector3.sub(v.getXYZ(), center), magn = MOD3.Vector3.mod(uu); MOD3.Vector3.muls(MOD3.Vector3.norm(uu), magn + radius * stdMath.exp(- magn * a)); // move vertex accordingly v.setXYZ(MOD3.Vector3.add(uu, center)); // ?? needed?? //self.u=uu; }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Twist Modifier **/ /**[DOC_MD] * ### Twist modifier * * Twist mesh along an axis * Adapted from the Twist modifier for PV3D * [/DOC_MD]**/ MOD3.Twist = MOD3.Class(MOD3.Modifier, { constructor: function Twist(angle, vector, center) { var self = this; if (!(self instanceof Twist)) return new Twist(angle, vector, center); self.$super('constructor'); self.name = 'Twist'; self.angle = angle || 0; self.vector = vector || MOD3.Vector3.Y(); self.center = center || MOD3.Vector3.ZERO(); }, angle: 0, vector: null, center: null, dispose: function() { var self = this; self.vector.dispose(); self.vector = null; self.angle = null; self.center.dispose(); self.center = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, tvec = self.vector.normalizeSelf().xyz, angle = self.angle, center = self.center.xyz, modulo = MOD3.Vector3.mod([0.5*modifiable.maxX, 0.5*modifiable.maxY, 0.5*modifiable.maxZ]), d = -MOD3.Vector3.dot(tvec, center), m1 = new MOD3.Matrix4(), m2 = new MOD3.Matrix4() ; MOD3.List.each(modifiable.vertices, function(v) { var xyz = v.getXYZ(), a = (MOD3.Vector3.dot(xyz, tvec) + d) * angle / modulo, m = MOD3.Matrix4.mult( m2.rotate(tvec[0], tvec[1], tvec[2], a, true), m1.translate(xyz[0], xyz[1], xyz[2], true) ) ; v.setXYZ([m.m[3], m.m[7], m.m[11]]); }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Skew Modifier **/ /**[DOC_MD] * ### Skew modifier * * Skew mesh along an axis * * @author Bartek Drozdz * [/DOC_MD]**/ var stdMath = Math; MOD3.Skew = MOD3.Class(MOD3.Modifier, { constructor: function Skew(force, offset, power, falloff) { var self = this; if (!(self instanceof Skew)) return new Skew(force, offset, power, falloff); self.$super('constructor'); self.name = 'Skew'; self.constraint = MOD3.ModConstant.NONE; self.force = force != null ? force : 0; self.offset = offset != null ? offset : 0.5; self.power = power != null ? power : 1; self.falloff = falloff != null ? falloff : 1; self.inverseFalloff = false; self.oneSide = false; self.swapAxes = false; self.skewAxis = 0; }, force: 0, skewAxis: 0, offset: 0.5, power: 1, falloff: 1, inverseFalloff: false, oneSide: false, swapAxes: false, dispose: function() { var self = this; self.force = null; self.skewAxis = null; self.offset = null; self.power = null; self.falloff = null; self.inverseFalloff = null; self.oneSide = null; self.swapAxes = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, constraint = self.constraint, skewAxis = self.skewAxis || modifiable.maxAxis, swapAxes = self.swapAxes, offset = stdMath.min(1, stdMath.max(0, self.offset)), oneSide = self.oneSide, inverseFalloff = !!self.inverseFalloff, falloff = stdMath.min(1, stdMath.max(0, self.falloff)), mirrorfalloff = 1-falloff, power = self.power, force = self.force, displaceAxis = MOD3.ModConstant.X === skewAxis ? (swapAxes ? MOD3.ModConstant.Z : MOD3.ModConstant.Y) : (MOD3.ModConstant.Y === skewAxis ? (swapAxes ? MOD3.ModConstant.Z : MOD3.ModConstant.X) : (MOD3.ModConstant.Z === skewAxis ? (swapAxes ? MOD3.ModConstant.Y : MOD3.ModConstant.X) : 0)) ; MOD3.List.each(modifiable.vertices, function(v) { var r, dr, f, p, vRatio; vRatio = v.getRatio(skewAxis); if ((MOD3.ModConstant.LEFT === constraint) && (vRatio <= offset)) return; if ((MOD3.ModConstant.RIGHT === constraint) && (vRatio > offset)) return; r = vRatio - offset; if (oneSide && (0 > r)) r = -r; dr = v.getRatio(displaceAxis); if (inverseFalloff) dr = 1 - dr; f = falloff + dr * mirrorfalloff; p = (0 > r ? -1 : 1) * stdMath.pow(stdMath.abs(r), power); v.setValue(displaceAxis, v.getValue(displaceAxis) + force * p * f); }); return self; }, }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Taper Modifier **/ /**[DOC_MD] * ### Taper modifier * * The taper modifier displaces the vertices on two axes proportionally to their position on the third axis. * * @author Bartek Drozdz * [/DOC_MD]**/ var stdMath = Math; MOD3.Taper = MOD3.Class(MOD3.Modifier, { constructor: function Taper(force, power, v1, v2) { var self = this; if (!(self instanceof Taper)) return new Taper(force, power, v1, v2); self.$super('constructor'); self.name = 'Taper'; /*self.start = 0; self.end = 1;*/ self.force = force != null ? force : 0; self.power = power != null ? power : 1; self.vector = v1 || MOD3.Vector3.Y(false); self.vector2 = v2 || MOD3.Vector3.Y(); }, force: 0, power: 1, /*start: 0, end: 1,*/ vector: null, vector2: null, /*setFalloff : function(start, end) { this.start = (start!==undef) ? start : 0; this.end = (end!==undef) ? end : 1; return this; },*/ dispose: function() { var self = this; self.vector.dispose(); self.vector2.dispose(); self.vector = null; self.vector2 = null; self.force = null; self.power = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, vec = self.vector.xyz, vec2 = self.vector2.xyz, force = self.force, power = self.power, m = new MOD3.Matrix4(); MOD3.List.each(modifiable.vertices, 1 !== power ? function(v) { var ar = MOD3.Vector3.mod(MOD3.Vector3.mul(v.getRatioVector(), vec2)), sc = force * stdMath.pow(ar, power); v.setXYZ(MOD3.Matrix4.multXYZ(m.scale(1 + sc * vec[0], 1 + sc * vec[1], 1 + sc * vec[2]), v.getXYZ())); } : function(v) { var ar = MOD3.Vector3.mod(MOD3.Vector3.mul(v.getRatioVector(), vec2)), sc = force * ar; v.setXYZ(MOD3.Matrix4.multXYZ(m.scale(1 + sc * vec[0], 1 + sc * vec[1], 1 + sc * vec[2]), v.getXYZ())); } ); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Wheel Modifier **/ /**[DOC_MD] * ### Wheel modifier * * Use it with vehicle models for wheels. * * The usual problem with a 3d wheel in a vahicle is that it is * supposed to turn (steer) and roll in the same time. * So, this code: * * ```javascript * wheel.rotationY = 10; // Steer 10deg to the left * wheel.rotationZ += 5; // Roll with a speed of 5 * ``` * This will make the wheel roll incorectly. * * A usual way to solve this problem is to put the wheel in another DisplayObject3D/Mesh, * turn the parent and roll the child, like that: * ```javascript * steer.rotationY = 10; // Steer 10deg to the left * steer.wheel.rotationZ += 5; // Roll with a speed of 5 * ``` * That will make the wheel behave correctly. But it can be uncomfortanble to apply, especially * to imported complex Collada models. * * The Wheel modifier elegantly solves this problem by doind the proper math in order to steer and roll * a single mesh at the same time. The only thing you need to do is to specify a steer vector and * roll vector - usually it will be 2 of the cardinal axes. The default value is: * * * steer - along the Y axis / new Vector3(0, 1, 0) * * roll - along the Z axis / new Vector3(0, 0, 1) * * * It should work with most car models imported from 3D editors as this is the natural position of a wheel. * * *Please note, that Papervision primitive cylinder, which may also be used as wheel, will require different axes * (Y for roll and Z or X for steer).* * * @author Bartek Drozdz * [/DOC_MD]**/ MOD3.Wheel = MOD3.Class(MOD3.Modifier, { constructor: function Wheel(speed, turn, roll, steerVector, rollVector) { var self = this; if (!(self instanceof Wheel)) return new Wheel(speed, turn, roll, steerVector, rollVector); self.$super('constructor'); self.name = 'Wheel'; self.speed = speed || 0; self.turn = turn || 0; self.roll = roll || 0; self.steerVector = steerVector || MOD3.Vector3.Y(); self.rollVector = rollVector || MOD3.Vector3.Z(); }, speed: 0, turn: 0, roll: 0, steerVector: null, rollVector: null, dispose: function() { var self = this; self.speed = null; self.turn = null; self.roll = null; self.steerVector.dispose(); self.rollVector.dispose(); self.steerVector = null; self.rollVector = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, steerVector = self.steerVector.normalizeSelf(), rollVector = self.rollVector.normalizeSelf(), turn = self.turn, roll = self.roll, //radius = 0.5*modifiable.width, //step = radius * self.speed / PI, //perimeter = radius * TWO_PI, ms = null, mt = null ; self.roll += self.speed; if (turn) { mt = new MOD3.Matrix4().rotateFromVector(steerVector, turn); ms = new MOD3.Matrix4().rotateFromVector(mt.multiplyVector(rollVector.clone()), roll); } else { ms = new MOD3.Matrix4().rotateFromVector(rollVector, roll); } MOD3.List.each(modifiable.vertices, mt ? function(v) { v.setXYZ(MOD3.Matrix4.multXYZ(ms, MOD3.Matrix4.multXYZ(mt, v.getXYZ()))); } : function(v) { v.setXYZ(MOD3.Matrix4.multXYZ(ms, v.getXYZ())); } ); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Break Modifier **/ /**[DOC_MD] * ### Break modifier * * Allow to break a mesh * * @author Bartek Drozdz * [/DOC_MD]**/ var stdMath = Math; MOD3.Break = MOD3.Class(MOD3.Modifier, { constructor: function Break(offset, angle, vector) { var self = this; if (!(self instanceof Break)) return new Break(offset, angle, vector); self.$super('constructor'); self.name = 'Break'; self.offset = offset || 0; self.angle = angle || 0; self.vector = vector || MOD3.Vector3.Y(); self.range = new MOD3.Range(0, 1); }, offset: 0, angle: 0, vector: null, range: null, dispose: function() { var self = this; self.vector.dispose(); self.range.dispose(); self.vector = null; self.range = null; self.offset = null; self.angle = null; self.$super('dispose'); return self; }, apply: function(modifiable) { var self = this, offset = stdMath.min(1, stdMath.max(0, self.offset)), range = self.range, angle = self.angle, bv = self.vector.normalizeSelf().xyz, pv, rm; pv = modifiable.minZ + modifiable.depth*offset; rm = new MOD3.Matrix4().rotate(bv[0], bv[1], bv[2], angle); MOD3.List.each(modifiable.vertices, function(v) { var c = v.getXYZ(); c[2] -= pv; if ((0 <= c[2]) && range.isIn(v.ratio[1])) MOD3.Matrix4.multXYZ(rm, c); c[2] += pv; v.setXYZ(c); }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Noise Modifier **/ /**[DOC_MD] * ### Noise modifier * * Randomly displaces each vertex in all 3 axes * * [/DOC_MD]**/ var stdMath = Math; MOD3.Noise = MOD3.Class(MOD3.Modifier, { constructor: function Noise(force) { var self = this; if (!(self instanceof Noise)) return new Noise(force); self.$super('constructor'); self.name = 'Noise'; self.force = force || 0; self.start = 0; self.end = 1; self.axes = MOD3.ModConstant.X | MOD3.ModConstant.Y | MOD3.ModConstant.Z; }, force: 0, start: 0, end: 1, dispose: function() { var self = this; self.force = null; self.start = null; self.end = null; self.$super('dispose'); return self; }, setFalloff: function(start, end) { var self = this; self.start = start != null ? start : 0; self.end = end != null ? end : 1; return self; }, apply: function(modifiable) { var self = this, axes = self.axes, start = self.start, end = self.end, force = self.force, halfforce = 0.5*force, maxAxis = modifiable.maxAxis; if ((0 == axes) || (0 == force)) return self; MOD3.List.each(modifiable.vertices, function(v) { var r = stdMath.random() * force - halfforce, p = v.getRatio(maxAxis), rp, xyz; if (start < end) { if (p < start) p = 0; else if (p > end) p = 1; } else if (start > end) { p = 1 - p; if (p > start) p = 0; else if (p < end) p = 1; } else { p = 1; } rp = r * p; xyz = v.getXYZ(); v.setXYZ([ xyz[0] + (axes & MOD3.ModConstant.X ? rp : 0), xyz[1] + (axes & MOD3.ModConstant.Y ? rp : 0), xyz[2] + (axes & MOD3.ModConstant.Z ? rp : 0) ]); }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 DisplaceMap (BitmapDisplacement) Modifier **/ /**[DOC_MD] * ### DisplaceMap (BitmapDisplacement) Modifier * * Displaces vertices based on RGB values of bitmapData pixels. * * BitmapDisplacement is inspired by both the AS3 built-in DisplacementMapFilter. It allows * to use color values for each channels of a bitmap to modify the position of vertices in a mesh. * * The displacement takes place along the cardinal axes, and each axis is mapped to a * channel in the bitmap: X for Red, Y for Green and Z for Blue. * * @author Bartek Drozdz * [/DOC_MD]**/ MOD3.DisplaceMap = MOD3.Class(MOD3.Modifier, { constructor: function DisplaceMap(bmp, force, offset) { var self = this; if (!(self instanceof DisplaceMap)) return new DisplaceMap(bmp, force, offset); self.$super('constructor'); self.name = 'DisplaceMap'; if (+bmp === bmp) // number { self.force = bmp || 1; self.offset = null == force ? 127 : force;// 0x7F; } else { self.setBitmap(bmp); self.force = force || 1; self.offset = null == offset ? 127 : offset;// 0x7F; } self.axes = MOD3.ModConstant.X | MOD3.ModConstant.Y | MOD3.ModConstant.Z; }, width: null, height: null, bmpData: null, force: 1, offset: 127, dispose: function() { var self = this; self.bmpData = null; self.width = null; self.height = null; self.force = null; self.offset = null; self.$super('dispose'); return self; }, setBitmap: function(bmpData) { var self = this; self.bmpData = bmpData ? bmpData.data : null; self.width = bmpData ? bmpData.width : 0; self.height = bmpData ? bmpData.height : 0; return self; }, apply: function(modifiable) { var self = this, axes = self.axes, w = self.width, h = self.height, bmp = self.bmpData, force = self.force, offset = self.offset; if (!axes || !bmp) return self; MOD3.List.each(modifiable.vertices, function(v) { var uv, uu, vv, xyz = v.getXYZ(); uu = ~~((w - 1) * v.ratio[0]/* X */); vv = ~~((h - 1) * v.ratio[2]/* Z */); uv = (vv * w + uu) << 2; v.setXYZ([ xyz[0] + (axes & MOD3.ModConstant.X ? ((bmp[uv] & 0xff) - offset) * force : 0), xyz[1] + (axes & MOD3.ModConstant.Y ? ((bmp[uv+1] & 0xff) - offset) * force : 0), xyz[2] + (axes & MOD3.ModConstant.Z ? ((bmp[uv+2] & 0xff) - offset) * force : 0) ]); }); return self; } }); }(MOD3);!function(MOD3) { "use strict"; /** * MOD3 Perlin/Simplex Noise Modifier **/ /**[DOC_MD] * ### Perlin modifier * * Displaces vertices based on a perlin/simplex noise source. * * Accepts a perlin/simplex noise data (with width and height information) and displaces vertices * based on the value of each point of the noise map. * * @author Bartek Drozdz * * @uses: https://github.com/josephg/noisejs for JavaScript * [/DOC_MD]**/ function cyclic_shift(a, w, h, dX, dY) { var size = w*h, b = new MOD3.VecArray(size), i, j, i2, j2, index; if (dX < 0) dX += w; if (dY < 0) dY += h; dX = ~~dX; dY = ~~dY; for (i=0,j=0,index=0; index= w) {i = 0; ++j;} i2 = (i + dX) % w; j2 = (j + dY) % h; b[index] = a[i2 + j2 * w]; } return b; } /*function generate2d(perlinNoise2d, w, h) { var size = w*h, a = new MOD3.VecArray(size), i, j, index; for (i=0,j=0,index=0; index= w) {i = 0; ++j;} a[index] = perlinNoise2d(i/w, j/h); } return a; }*/ MOD3.Perlin = MOD3.Class(MOD3.Modifier, { constructor: function Perlin(force, noise, autoRun) { var self = this; if (!(self instanceof Perlin)) return new Perlin(force, noise, autoRun); self.$super('constructor'); self.name = 'Perlin'; self.force = null != force ? force : 1; self.perlin = noise; self.autoRun = null != autoRun ? !!autoRun : true; self.axes = MOD3.ModConstant.X | MOD3.ModConstant.Y | MOD3.ModConstant.Z; }, speedX: 1, speedY: 1, perlin: null, force: 1, offset: 0, autoRun: true, dispose: function() { var self = this; self.perlin = null; self.speedX = null; self.speedY = null; self.force = null; self.offset = null; self.autoRun = null; self.$super('dispose'); return self; }, setSpeed: function(dX, dY) { var self = this; self.speedX = dX; self.speedY = dY; return self; }, apply: function(modifiable) { var self = this, axes = self.axes, force = self.force, offset = self.offset, pn = self.perlin, w, h; if (!axes || !pn) return self; w = pn.width; h = pn.height; if (self.autoRun) { pn = self.perlin = cyclic_shift(pn, w, h, self.speedX, self.speedY); pn.width = w; pn.height = h; } MOD3.List.each(modifiable.vertices, function(v) { var xyz = v.getXYZ(), uu = ~~((w - 1) * v.ratio[0]/* u */), vv = ~~((h - 1) * v.ratio[2]/* v */), uv = uu + vv * w; v.setXYZ([ xyz[0] + (axes & MOD3.ModConstant.X ? (pn[uv] - offset) * force : 0), xyz[1] + (axes & MOD3.ModConstant.Y ? (pn[uv/*+1*/] - offset) * force : 0), xyz[2] + (axes & MOD3.ModConstant.Z ? (pn[uv/*+2*/] - offset) * force : 0) ]); }); return self; } }); }(MOD3);// export it return MOD3; });