Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
/* | |
* 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) { | |
; | |
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) { | |
; | |
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<r; i+=2) { k = i0+i; Fv = F(F(Fv,x[k],k),x[k+1],k+1); } | |
for (i=r; i<l; 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); } | |
} | |
return Fv; | |
} | |
,each: function each(x, F, i0, i1, reverse) { | |
if (null == x || !x.length) return x; | |
var len = x.length; | |
if (arguments.length < 4) i1 = len-1; | |
if (0 > 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<r; i+=2) | |
{ | |
k = i0+i; | |
F(x[k ]); | |
F(x[k+1]); | |
} | |
for (i=r; i<l; 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]); | |
} | |
} | |
return x; | |
} | |
}; | |
/** | |
* MOD3 MeshProxy Super Class | |
**/ | |
function dispose(o) | |
{ | |
o.dispose(); | |
} | |
function reset(o) | |
{ | |
o.reset(); | |
} | |
function collapse(o) | |
{ | |
o.collapse(); | |
} | |
MOD3.FaceProxy = MOD3.Class(null, { | |
constructor: function FaceProxy() { | |
this.vertices = []; | |
}, | |
name: "FaceProxy", | |
vertices: null, | |
dispose: function() { | |
var self = this; | |
self.vertices = null; | |
return self; | |
}, | |
addVertex: function(v) { | |
this.vertices.push(v); | |
}, | |
getVertices: function() { | |
return this.vertices; | |
} | |
}); | |
MOD3.VertexProxy = MOD3.Class(null, { | |
constructor: function VertexProxy(vertex, mesh) { | |
var self = this; | |
self.mesh = mesh || null; | |
// use internal typed-arrays for speed | |
self.original = new MOD3.VecArray([0,0,0]); | |
self.ratio = new MOD3.VecArray([0,0,0]); | |
// vertex can be zero | |
if (null != vertex) self.setVertex(vertex); | |
}, | |
name: "VertexProxy", | |
mesh: null, | |
vertex: null, | |
original: null, | |
ratio: null, | |
dispose: function() { | |
var self = this; | |
self.mesh = null; | |
self.vertex = null; | |
self.original = null; | |
self.ratio = null; | |
return self; | |
}, | |
setVertex: function(vt) { | |
// override | |
var self = this; | |
self.vertex = vt; | |
return self; | |
}, | |
getRatioVector: function() { | |
var r = this.ratio, rv = new MOD3.VecArray(3); | |
rv[0] = r[0]; rv[1] = r[1]; rv[2] = r[2]; | |
return rv; | |
}, | |
getRatio: function(axis) { | |
return this.ratio[MOD3.XYZi[axis]] || 0; | |
}, | |
setRatios: function(rx, ry, rz) { | |
var r = this.ratio; | |
r[0] = rx || 0; | |
r[1] = ry || 0; | |
r[2] = rz || 0; | |
return this; | |
}, | |
getOriginalValue: function(axis) { | |
return this.original[MOD3.XYZi[axis]] || 0; | |
}, | |
setOriginalPosition: function(ox, oy, oz) { | |
var o = this.original; | |
o[0] = ox || 0; | |
o[1] = oy || 0; | |
o[2] = oz || 0; | |
return this; | |
}, | |
getXYZ: function() { | |
// override | |
return new MOD3.VecArray([0,0,0]); | |
}, | |
getX: function() { | |
// override | |
return 0; | |
}, | |
getY: function() { | |
// override | |
return 0; | |
}, | |
getZ: function() { | |
// override | |
return 0; | |
}, | |
getValue: function(axis) { | |
var self = this; | |
// override | |
return MOD3.ModConstant.X === axis | |
? self.getX() | |
: (MOD3.ModConstant.Y === axis | |
? self.getY() | |
: (MOD3.ModConstant.Z === axis | |
? self.getZ() | |
: 0)) | |
; | |
}, | |
setXYZ: function(xyz) { | |
// override | |
return this; | |
}, | |
setX: function(vo) { | |
// override | |
return this; | |
}, | |
setY: function(vo) { | |
// override | |
return this; | |
}, | |
setZ: function(vo) { | |
// override | |
return this; | |
}, | |
setValue: function(axis, vo) { | |
var self = this; | |
// override | |
if (MOD3.ModConstant.X === axis) self.setX(vo); | |
else if (MOD3.ModConstant.Y === axis) self.setY(vo); | |
else if (MOD3.ModConstant.Z === axis) self.setZ(vo); | |
return self; | |
}, | |
reset: function() { | |
// override | |
var self = this; | |
self.setXYZ(self.original); | |
return self; | |
}, | |
collapse: function() { | |
// override | |
var self = this, xyz = self.getXYZ(), o = self.original; | |
o[0] = xyz[0]; o[1] = xyz[1]; o[2] = xyz[2]; | |
return self; | |
} | |
}); | |
MOD3.MeshProxy = MOD3.Class(null, { | |
constructor: function MeshProxy(mesh) { | |
var self = this; | |
self.maxX = 0; | |
self.maxY = 0; | |
self.maxZ = 0; | |
self.minX = 0; | |
self.minY = 0; | |
self.minZ = 0; | |
self.maxAxis = 0; | |
self.midAxis = 0; | |
self.minAxis = 0; | |
self.width = 0; | |
self.height = 0; | |
self.depth = 0; | |
self.vertices = null; | |
self.faces = null; | |
self.mesh = null; | |
if (null != mesh) self.setMesh(mesh); | |
}, | |
name: "MeshProxy", | |
maxX: 0, | |
maxY: 0, | |
maxZ: 0, | |
minX: 0, | |
minY: 0, | |
minZ: 0, | |
maxAxis: 0, | |
midAxis: 0, | |
minAxis: 0, | |
width: 0, | |
height: 0, | |
depth: 0, | |
vertices : null, | |
faces : null, | |
mesh : null, | |
v: null, | |
dispose: function() { | |
var self = this; | |
self.maxX = null; | |
self.maxY = null; | |
self.maxZ = null; | |
self.minX = null; | |
self.minY = null; | |
self.minZ = null; | |
self.maxAxis = null; | |
self.midAxis = null; | |
self.minAxis = null; | |
self.width = null; | |
self.height = null; | |
self.depth = null; | |
self.disposeFaces(); | |
self.disposeVertices(); | |
self.mesh = null; | |
self.v = null; | |
return self; | |
}, | |
disposeVertices: function() { | |
var self = this; | |
if (self.vertices) MOD3.List.each(self.vertices, dispose); | |
self.vertices = null; | |
return self; | |
}, | |
disposeFaces: function() { | |
var self = this; | |
if (self.faces) MOD3.List.each(self.faces, dispose); | |
self.faces = null; | |
return self; | |
}, | |
init: function(mesh) { | |
var self = this; | |
self.mesh = mesh; | |
//self.vertices = []; | |
// not used | |
//self.faces = []; | |
return self; | |
}, | |
setMesh: function(mesh) { | |
var self = this; | |
self.init(mesh); | |
self.preApply(); | |
self.analyzeGeometry() | |
self.postApply(); | |
return self; | |
}, | |
getVertices: function() { | |
return this.vertices; | |
}, | |
getFaces: function() { | |
return this.faces; | |
}, | |
applyModifiers: function(modStack) { | |
var self = this, sl, i; | |
for (i=0,sl=modStack.length; i<sl; ++i) | |
{ | |
modStack[i].enabled && modStack[i].apply(self); | |
} | |
return self; | |
}, | |
analyzeGeometry: function() { | |
var self = this, | |
vertices = self.vertices, | |
minX = 0, minY = 0, minZ = 0, | |
maxX = 0, maxY = 0, maxZ = 0, | |
width = 0, height = 0, depth = 0, | |
maxe, mine, w | |
; | |
if (!vertices || !vertices.length) return self; | |
w = vertices[0].getXYZ(); | |
minX = w[0]; | |
minY = w[1]; | |
minZ = w[2]; | |
maxX = w[0]; | |
maxY = w[1]; | |
maxZ = w[2]; | |
MOD3.List.each(vertices, function(v) { | |
var xyz = v.getXYZ(), x = xyz[0], y = xyz[1], z = xyz[2]; | |
minX = stdMath.min(minX, x); | |
minY = stdMath.min(minY, y); | |
minZ = stdMath.min(minZ, z); | |
maxX = stdMath.max(maxX, x); | |
maxY = stdMath.max(maxY, y); | |
maxZ = stdMath.max(maxZ, z); | |
v.setOriginalPosition(x, y, z); | |
}); | |
width = maxX - minX; | |
height = maxY - minY; | |
depth = maxZ - minZ; | |
self.width = width; | |
self.height = height; | |
self.depth = depth; | |
self.minX = minX; | |
self.maxX = maxX; | |
self.minY = minY; | |
self.maxY = maxY; | |
self.minZ = minZ; | |
self.maxZ = maxZ; | |
maxe = stdMath.max(width, height, depth); | |
mine = stdMath.min(width, height, depth); | |
if ((maxe === width) && (mine === height)) | |
{ | |
self.minAxis = MOD3.ModConstant.Y; | |
self.midAxis = MOD3.ModConstant.Z; | |
self.maxAxis = MOD3.ModConstant.X; | |
} | |
else if ((maxe === width) && (mine === depth)) | |
{ | |
self.minAxis = MOD3.ModConstant.Z; | |
self.midAxis = MOD3.ModConstant.Y; | |
self.maxAxis = MOD3.ModConstant.X; | |
} | |
else if ((maxe === height) && (mine === width)) | |
{ | |
self.minAxis = MOD3.ModConstant.X; | |
self.midAxis = MOD3.ModConstant.Z; | |
self.maxAxis = MOD3.ModConstant.Y; | |
} | |
else if ((maxe === height) && (mine === depth)) | |
{ | |
self.minAxis = MOD3.ModConstant.Z; | |
self.midAxis = MOD3.ModConstant.X; | |
self.maxAxis = MOD3.ModConstant.Y; | |
} | |
else if ((maxe === depth) && (mine === width)) | |
{ | |
self.minAxis = MOD3.ModConstant.X; | |
self.midAxis = MOD3.ModConstant.Y; | |
self.maxAxis = MOD3.ModConstant.Z; | |
} | |
else if ((maxe === depth) && (mine === height)) | |
{ | |
self.minAxis = MOD3.ModConstant.Y; | |
self.midAxis = MOD3.ModConstant.X; | |
self.maxAxis = MOD3.ModConstant.Z; | |
} | |
MOD3.List.each(vertices, function(v) { | |
var xyz = v.getXYZ(); | |
v.setRatios(width > 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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) { | |
; | |
/** | |
* 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<size; ++index,++i) | |
{ | |
if (i >= 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<size; ++index,++i) | |
{ | |
if (i >= 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; | |
}); | |