topical media & game development
mobile-query-three-plugins-flamethrower-tmp-vendor-tquery-tquery-bundle.js / js
// tquery.js - github.com/jeromeetienne/tquery - MIT License
// vim: ts=4 sts=4 sw=4 expandtab
// -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
// -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License
// -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License
// -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License
// -- kossnocorp Sasha Koss XXX TODO License or CLA
// -- bryanforbes Bryan Forbes XXX TODO License or CLA
// -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence
// -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License
// -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License
// -- bbqsrc Brendan Molloy (C) 2011 Creative Commons Zero (public domain)
// -- iwyg XXX TODO License or CLA
// -- DomenicDenicola Domenic Denicola Copyright (C) 2011 MIT License
// -- xavierm02 Montillet Xavier Copyright (C) 2011 MIT License
// -- Raynos Jake Verbaten Copyright (C) 2011 MIT Licence
// -- samsonjs Sami Samhuri Copyright (C) 2010 MIT License
// -- rwldrn Rick Waldron Copyright (C) 2011 MIT License
// -- lexer Alexey Zakharov XXX TODO License or CLA
/*!
Copyright (c) 2009, 280 North Inc. http://280north.com/
MIT License. http://github.com/280north/narwhal/blob/master/README.md
*/
// Module systems magic dance
(function (definition) {
// RequireJS
if (typeof define == "function") {
define(definition);
// CommonJS and <script>
} else {
definition();
}
})(function () {
Brings an environment as close to ECMAScript 5 compliance
as is possible with the facilities of erstwhile engines.
Annotated ES5: http://es5.github.com/ (specific links below)
ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
//
// Function
// ========
//
// ES-5 15.3.4.5
// http://es5.github.com/#x15.3.4.5
if (!Function.prototype.bind) {
Function.prototype.bind = function bind(that) { // .length is 1
// 1. Let Target be the this value.
var target = this;
// 2. If IsCallable(Target) is false, throw a TypeError exception.
if (typeof target != "function") {
throw new TypeError("Function.prototype.bind called on incompatible " + target);
}
// 3. Let A be a new (possibly empty) internal list of all of the
// argument values provided after thisArg (arg1, arg2 etc), in order.
// XXX slicedArgs will stand in for "A" if used
var args = slice.call(arguments, 1); // for normal call
// 4. Let F be a new native ECMAScript object.
// 11. Set the [[Prototype]] internal property of F to the standard
// built-in Function prototype object as specified in 15.3.3.1.
// 12. Set the [[Call]] internal property of F as described in
// 15.3.4.5.1.
// 13. Set the [[Construct]] internal property of F as described in
// 15.3.4.5.2.
// 14. Set the [[HasInstance]] internal property of F as described in
// 15.3.4.5.3.
var bound = function () {
if (this instanceof bound) {
// 15.3.4.5.2 [[Construct]]
// When the [[Construct]] internal method of a function object,
// F that was created using the bind function is called with a
// list of arguments ExtraArgs, the following steps are taken:
// 1. Let target be the value of F's [[TargetFunction]]
// internal property.
// 2. If target has no [[Construct]] internal method, a
// TypeError exception is thrown.
// 3. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Construct]] internal
// method of target providing args as the arguments.
var F = function(){};
F.prototype = target.prototype;
var self = new F;
var result = target.apply(
self,
args.concat(slice.call(arguments))
);
if (Object(result) === result) {
return result;
}
return self;
} else {
// 15.3.4.5.1 [[Call]]
// When the [[Call]] internal method of a function object, F,
// which was created using the bind function is called with a
// this value and a list of arguments ExtraArgs, the following
// steps are taken:
// 1. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 2. Let boundThis be the value of F's [[BoundThis]] internal
// property.
// 3. Let target be the value of F's [[TargetFunction]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Call]] internal method
// of target providing boundThis as the this value and
// providing args as the arguments.
// equiv: target.call(this, ...boundArgs, ...args)
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
// XXX bound.length is never writable, so don't even try
//
// 15. If the [[Class]] internal property of Target is "Function", then
// a. Let L be the length property of Target minus the length of A.
// b. Set the length own property of F to either 0 or L, whichever is
// larger.
// 16. Else set the length own property of F to 0.
// 17. Set the attributes of the length own property of F to the values
// specified in 15.3.5.1.
// TODO
// 18. Set the [[Extensible]] internal property of F to true.
// TODO
// 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
// 20. Call the [[DefineOwnProperty]] internal method of F with
// arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
// thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
// false.
// 21. Call the [[DefineOwnProperty]] internal method of F with
// arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
// [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
// and false.
// TODO
// NOTE Function objects created using Function.prototype.bind do not
// have a prototype property or the [[Code]], [[FormalParameters]], and
// [[Scope]] internal properties.
// XXX can't delete prototype in pure-js.
// 22. Return F.
return bound;
};
}
// Shortcut to an often accessed properties, in order to avoid multiple
// dereference that costs universally.
// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
// us it in defining shortcuts.
var call = Function.prototype.call;
var prototypeOfArray = Array.prototype;
var prototypeOfObject = Object.prototype;
var slice = prototypeOfArray.slice;
// Having a toString local variable name breaks in Opera so use _toString.
var _toString = call.bind(prototypeOfObject.toString);
var owns = call.bind(prototypeOfObject.hasOwnProperty);
// If JS engine supports accessors creating shortcuts.
var defineGetter;
var defineSetter;
var lookupGetter;
var lookupSetter;
var supportsAccessors;
if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
defineGetter = call.bind(prototypeOfObject.__defineGetter__);
defineSetter = call.bind(prototypeOfObject.__defineSetter__);
lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
}
//
// Array
// =====
//
// ES5 15.4.3.2
// http://es5.github.com/#x15.4.3.2
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray) {
Array.isArray = function isArray(obj) {
return _toString(obj) == "[object Array]";
};
}
// The IsCallable() check in the Array functions
// has been replaced with a strict check on the
// internal class of the object to trap cases where
// the provided function was actually a regular
// expression literal, which in V8 and
// JavaScriptCore is a typeof "function". Only in
// V8 are regular expression literals permitted as
// reduce parameters, so it is desirable in the
// general case for the shim to match the more
// strict and common behavior of rejecting regular
// expressions.
// ES5 15.4.4.18
// http://es5.github.com/#x15.4.4.18
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
if (!Array.prototype.forEach) {
Array.prototype.forEach = function forEach(fun /*, thisp*/) {
var self = toObject(this),
thisp = arguments[1],
i = -1,
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(); // TODO message
}
while (++i < length) {
if (i in self) {
// Invoke the callback function with call, passing arguments:
// context, property value, property key, thisArg object context
fun.call(thisp, self[i], i, self);
}
}
};
}
// ES5 15.4.4.19
// http://es5.github.com/#x15.4.4.19
// developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map) {
Array.prototype.map = function map(fun /*, thisp*/) {
var self = toObject(this),
length = self.length >>> 0,
result = Array(length),
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self)
result[i] = fun.call(thisp, self[i], i, self);
}
return result;
};
}
// ES5 15.4.4.20
// http://es5.github.com/#x15.4.4.20
// developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
if (!Array.prototype.filter) {
Array.prototype.filter = function filter(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
result = [],
value,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self) {
value = self[i];
if (fun.call(thisp, value, i, self)) {
result.push(value);
}
}
}
return result;
};
}
// ES5 15.4.4.16
// http://es5.github.com/#x15.4.4.16
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
if (!Array.prototype.every) {
Array.prototype.every = function every(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self && !fun.call(thisp, self[i], i, self)) {
return false;
}
}
return true;
};
}
// ES5 15.4.4.17
// http://es5.github.com/#x15.4.4.17
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
if (!Array.prototype.some) {
Array.prototype.some = function some(fun /*, thisp */) {
var self = toObject(this),
length = self.length >>> 0,
thisp = arguments[1];
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
for (var i = 0; i < length; i++) {
if (i in self && fun.call(thisp, self[i], i, self)) {
return true;
}
}
return false;
};
}
// ES5 15.4.4.21
// http://es5.github.com/#x15.4.4.21
// developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(fun /*, initial*/) {
var self = toObject(this),
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
// no value to return if no initial value and an empty array
if (!length && arguments.length == 1) {
throw new TypeError('reduce of empty array with no initial value');
}
var i = 0;
var result;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i++];
break;
}
// if array contains no values, no initial value to return
if (++i >= length) {
throw new TypeError('reduce of empty array with no initial value');
}
} while (true);
}
for (; i < length; i++) {
if (i in self) {
result = fun.call(void 0, result, self[i], i, self);
}
}
return result;
};
}
// ES5 15.4.4.22
// http://es5.github.com/#x15.4.4.22
// developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
if (!Array.prototype.reduceRight) {
Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
var self = toObject(this),
length = self.length >>> 0;
// If no callback function or if callback is not a callable function
if (_toString(fun) != "[object Function]") {
throw new TypeError(fun + " is not a function");
}
// no value to return if no initial value, empty array
if (!length && arguments.length == 1) {
throw new TypeError('reduceRight of empty array with no initial value');
}
var result, i = length - 1;
if (arguments.length >= 2) {
result = arguments[1];
} else {
do {
if (i in self) {
result = self[i--];
break;
}
// if array contains no values, no initial value to return
if (--i < 0) {
throw new TypeError('reduceRight of empty array with no initial value');
}
} while (true);
}
do {
if (i in this) {
result = fun.call(void 0, result, self[i], i, self);
}
} while (i--);
return result;
};
}
// ES5 15.4.4.14
// http://es5.github.com/#x15.4.4.14
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
var self = toObject(this),
length = self.length >>> 0;
if (!length) {
return -1;
}
var i = 0;
if (arguments.length > 1) {
i = toInteger(arguments[1]);
}
// handle negative indices
i = i >= 0 ? i : Math.max(0, length + i);
for (; i < length; i++) {
if (i in self && self[i] === sought) {
return i;
}
}
return -1;
};
}
// ES5 15.4.4.15
// http://es5.github.com/#x15.4.4.15
// developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
if (!Array.prototype.lastIndexOf) {
Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
var self = toObject(this),
length = self.length >>> 0;
if (!length) {
return -1;
}
var i = length - 1;
if (arguments.length > 1) {
i = Math.min(i, toInteger(arguments[1]));
}
// handle negative indices
i = i >= 0 ? i : length - Math.abs(i);
for (; i >= 0; i--) {
if (i in self && sought === self[i]) {
return i;
}
}
return -1;
};
}
//
// Object
// ======
//
// ES5 15.2.3.2
// http://es5.github.com/#x15.2.3.2
if (!Object.getPrototypeOf) {
// github.com/kriskowal/es5-shim/issues#issue/2
// http://ejohn.org/blog/objectgetprototypeof/
// recommended by fschaefer on github
Object.getPrototypeOf = function getPrototypeOf(object) {
return object.__proto__ || (
object.constructor
? object.constructor.prototype
: prototypeOfObject
);
};
}
// ES5 15.2.3.3
// http://es5.github.com/#x15.2.3.3
if (!Object.getOwnPropertyDescriptor) {
var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a non-object: ";
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError(ERR_NON_OBJECT + object);
}
// If object does not owns property return undefined immediately.
if (!owns(object, property)) {
return;
}
// If object has a property then it's for sure both `enumerable` and
// `configurable`.
var descriptor = { enumerable: true, configurable: true };
// If JS engine supports accessor properties then property may be a
// getter or setter.
if (supportsAccessors) {
// Unfortunately `__lookupGetter__` will return a getter even
// if object has own non getter property along with a same named
// inherited getter. To avoid misbehavior we temporary remove
// `__proto__` so that `__lookupGetter__` will return getter only
// if it's owned by an object.
var prototype = object.__proto__;
object.__proto__ = prototypeOfObject;
var getter = lookupGetter(object, property);
var setter = lookupSetter(object, property);
// Once we have getter and setter we can put values back.
object.__proto__ = prototype;
if (getter || setter) {
if (getter) {
descriptor.get = getter;
}
if (setter) {
descriptor.set = setter;
}
// If it was accessor property we're done and return here
// in order to avoid adding `value` to the descriptor.
return descriptor;
}
}
// If we got this far we know that object has an own property that is
// not an accessor so we set it as a value and return descriptor.
descriptor.value = object[property];
return descriptor;
};
}
// ES5 15.2.3.4
// http://es5.github.com/#x15.2.3.4
if (!Object.getOwnPropertyNames) {
Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
return Object.keys(object);
};
}
// ES5 15.2.3.5
// http://es5.github.com/#x15.2.3.5
if (!Object.create) {
Object.create = function create(prototype, properties) {
var object;
if (prototype === null) {
object = { "__proto__": null };
} else {
if (typeof prototype != "object") {
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
// IE has no built-in implementation of `Object.getPrototypeOf`
// neither `__proto__`, but this manually setting `__proto__` will
// guarantee that `Object.getPrototypeOf` will work as expected with
// objects created using `Object.create`
object.__proto__ = prototype;
}
if (properties !== void 0) {
Object.defineProperties(object, properties);
}
return object;
};
}
// ES5 15.2.3.6
// http://es5.github.com/#x15.2.3.6
// Patch for WebKit and IE8 standard mode
// Designed by hax <hax.github.com>
// related issue: github.com/kriskowal/es5-shim/issues#issue/5
// IE8 Reference:
// http://msdn.microsoft.com/en-us/library/dd282900.aspx
// http://msdn.microsoft.com/en-us/library/dd229916.aspx
// WebKit Bugs:
// bugs.webkit.org/show_bug.cgi?id=36423
function doesDefinePropertyWork(object) {
try {
Object.defineProperty(object, "sentinel", {});
return "sentinel" in object;
} catch (exception) {
// returns falsy
}
}
// check whether defineProperty works if it's given. Otherwise,
// shim partially.
if (Object.defineProperty) {
var definePropertyWorksOnObject = doesDefinePropertyWork({});
var definePropertyWorksOnDom = typeof document == "undefined" ||
doesDefinePropertyWork(document.createElement("div"));
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
var definePropertyFallback = Object.defineProperty;
}
}
if (!Object.defineProperty || definePropertyFallback) {
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
"on this javascript engine";
Object.defineProperty = function defineProperty(object, property, descriptor) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
}
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) {
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
}
// make a valiant attempt to use the real defineProperty
// for I8's DOM elements.
if (definePropertyFallback) {
try {
return definePropertyFallback.call(Object, object, property, descriptor);
} catch (exception) {
// try the shim if the real one doesn't work
}
}
// If it's a data property.
if (owns(descriptor, "value")) {
// fail silently if "writable", "enumerable", or "configurable"
// are requested but not supported
/*
// alternate approach:
if ( // can't implement these features; allow false but not true
!(owns(descriptor, "writable") ? descriptor.writable : true) ||
!(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
!(owns(descriptor, "configurable") ? descriptor.configurable : true)
)
throw new RangeError(
"This implementation of Object.defineProperty does not " +
"support configurable, enumerable, or writable."
);
*/
if (supportsAccessors && (lookupGetter(object, property) ||
lookupSetter(object, property)))
{
// As accessors are supported only on engines implementing
// `__proto__` we can safely override `__proto__` while defining
// a property to make sure that we don't hit an inherited
// accessor.
var prototype = object.__proto__;
object.__proto__ = prototypeOfObject;
// Deleting a property anyway since getter / setter may be
// defined on object itself.
delete object[property];
object[property] = descriptor.value;
// Setting original `__proto__` back now.
object.__proto__ = prototype;
} else {
object[property] = descriptor.value;
}
} else {
if (!supportsAccessors) {
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
}
// If we got that far then getters and setters can be defined !!
if (owns(descriptor, "get")) {
defineGetter(object, property, descriptor.get);
}
if (owns(descriptor, "set")) {
defineSetter(object, property, descriptor.set);
}
}
return object;
};
}
// ES5 15.2.3.7
// http://es5.github.com/#x15.2.3.7
if (!Object.defineProperties) {
Object.defineProperties = function defineProperties(object, properties) {
for (var property in properties) {
if (owns(properties, property) && property != "__proto__") {
Object.defineProperty(object, property, properties[property]);
}
}
return object;
};
}
// ES5 15.2.3.8
// http://es5.github.com/#x15.2.3.8
if (!Object.seal) {
Object.seal = function seal(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// ES5 15.2.3.9
// http://es5.github.com/#x15.2.3.9
if (!Object.freeze) {
Object.freeze = function freeze(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// detect a Rhino bug and patch it
try {
Object.freeze(function () {});
} catch (exception) {
Object.freeze = (function freeze(freezeObject) {
return function freeze(object) {
if (typeof object == "function") {
return object;
} else {
return freezeObject(object);
}
};
})(Object.freeze);
}
// ES5 15.2.3.10
// http://es5.github.com/#x15.2.3.10
if (!Object.preventExtensions) {
Object.preventExtensions = function preventExtensions(object) {
// this is misleading and breaks feature-detection, but
// allows "securable" code to "gracefully" degrade to working
// but insecure code.
return object;
};
}
// ES5 15.2.3.11
// http://es5.github.com/#x15.2.3.11
if (!Object.isSealed) {
Object.isSealed = function isSealed(object) {
return false;
};
}
// ES5 15.2.3.12
// http://es5.github.com/#x15.2.3.12
if (!Object.isFrozen) {
Object.isFrozen = function isFrozen(object) {
return false;
};
}
// ES5 15.2.3.13
// http://es5.github.com/#x15.2.3.13
if (!Object.isExtensible) {
Object.isExtensible = function isExtensible(object) {
// 1. If Type(O) is not Object throw a TypeError exception.
if (Object(object) !== object) {
throw new TypeError(); // TODO message
}
// 2. Return the Boolean value of the [[Extensible]] internal property of O.
var name = '';
while (owns(object, name)) {
name += '?';
}
object[name] = true;
var returnValue = owns(object, name);
delete object[name];
return returnValue;
};
}
// ES5 15.2.3.14
// http://es5.github.com/#x15.2.3.14
if (!Object.keys) {
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
var hasDontEnumBug = true,
dontEnums = [
"toString",
"toLocaleString",
"valueOf",
"hasOwnProperty",
"isPrototypeOf",
"propertyIsEnumerable",
"constructor"
],
dontEnumsLength = dontEnums.length;
for (var key in {"toString": null}) {
hasDontEnumBug = false;
}
Object.keys = function keys(object) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError("Object.keys called on a non-object");
}
var keys = [];
for (var name in object) {
if (owns(object, name)) {
keys.push(name);
}
}
if (hasDontEnumBug) {
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
var dontEnum = dontEnums[i];
if (owns(object, dontEnum)) {
keys.push(dontEnum);
}
}
}
return keys;
};
}
//
// Date
// ====
//
// ES5 15.9.5.43
// http://es5.github.com/#x15.9.5.43
// This function returns a String value represent the instance in time
// represented by this Date object. The format of the String is the Date Time
// string format defined in 15.9.1.15. All fields are present in the String.
// The time zone is always UTC, denoted by the suffix Z. If the time value of
// this object is not a finite Number a RangeError exception is thrown.
if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {
Date.prototype.toISOString = function toISOString() {
var result, length, value, year;
if (!isFinite(this)) {
throw new RangeError("Date.prototype.toISOString called on non-finite value.");
}
// the date time string format is specified in 15.9.1.15.
result = [this.getUTCMonth() + 1, this.getUTCDate(),
this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
year = this.getUTCFullYear();
year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6);
length = result.length;
while (length--) {
value = result[length];
// pad months, days, hours, minutes, and seconds to have two digits.
if (value < 10) {
result[length] = "0" + value;
}
}
// pad milliseconds to have three digits.
return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." +
("000" + this.getUTCMilliseconds()).slice(-3) + "Z";
}
}
// ES5 15.9.4.4
// http://es5.github.com/#x15.9.4.4
if (!Date.now) {
Date.now = function now() {
return new Date().getTime();
};
}
// ES5 15.9.5.44
// http://es5.github.com/#x15.9.5.44
// This function provides a String representation of a Date object for use by
// JSON.stringify (15.12.3).
if (!Date.prototype.toJSON) {
Date.prototype.toJSON = function toJSON(key) {
// When the toJSON method is called with argument key, the following
// steps are taken:
// 1. Let O be the result of calling ToObject, giving it the this
// value as its argument.
// 2. Let tv be ToPrimitive(O, hint Number).
// 3. If tv is a Number and is not finite, return null.
// XXX
// 4. Let toISO be the result of calling the [[Get]] internal method of
// O with argument "toISOString".
// 5. If IsCallable(toISO) is false, throw a TypeError exception.
if (typeof this.toISOString != "function") {
throw new TypeError('toISOString property is not callable');
}
// 6. Return the result of calling the [[Call]] internal method of
// toISO with O as the this value and an empty argument list.
return this.toISOString();
// NOTE 1 The argument is ignored.
// NOTE 2 The toJSON function is intentionally generic; it does not
// require that its this value be a Date object. Therefore, it can be
// transferred to other kinds of objects for use as a method. However,
// it does require that any such object have a toISOString method. An
// object is free to use the argument key to filter its
// stringification.
};
}
// ES5 15.9.4.2
// http://es5.github.com/#x15.9.4.2
// based on work shared by Daniel Friesen (dantman)
// http://gist.github.com/303249
if (!Date.parse || Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) {
// XXX global assignment won't work in embeddings that use
// an alternate object for the context.
Date = (function(NativeDate) {
// Date.length === 7
var Date = function Date(Y, M, D, h, m, s, ms) {
var length = arguments.length;
if (this instanceof NativeDate) {
var date = length == 1 && String(Y) === Y ? // isString(Y)
// We explicitly pass it through parse:
new NativeDate(Date.parse(Y)) :
// We have to manually make calls depending on argument
// length here
length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
length >= 5 ? new NativeDate(Y, M, D, h, m) :
length >= 4 ? new NativeDate(Y, M, D, h) :
length >= 3 ? new NativeDate(Y, M, D) :
length >= 2 ? new NativeDate(Y, M) :
length >= 1 ? new NativeDate(Y) :
new NativeDate();
// Prevent mixups with unfixed Date object
date.constructor = Date;
return date;
}
return NativeDate.apply(this, arguments);
};
// 15.9.1.15 Date Time String Format.
var isoDateExpression = new RegExp("^" +
"(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year
"(?:-(\\d{2})" + // optional month capture
"(?:-(\\d{2})" + // optional day capture
"(?:" + // capture hours:minutes:seconds.milliseconds
"T(\\d{2})" + // hours capture
":(\\d{2})" + // minutes capture
"(?:" + // optional :seconds.milliseconds
":(\\d{2})" + // seconds capture
"(?:\\.(\\d{3}))?" + // milliseconds capture
")?" +
"(?:" + // capture UTC offset component
"Z|" + // UTC capture
"(?:" + // offset specifier +/-hours:minutes
"([-+])" + // sign capture
"(\\d{2})" + // hours offset capture
":(\\d{2})" + // minutes offset capture
")" +
")?)?)?)?" +
"");
String.prototype.trim = function trim() {
if (this === undefined || this === null) {
throw new TypeError("can't convert "+this+" to object");
}
return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
};
}
//
// Util
// ======
//
// ES5 9.4
// http://es5.github.com/#x9.4
// http://jsperf.com/to-integer
var toInteger = function (n) {
n = +n;
if (n !== n) { // isNaN
n = 0;
} else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
return n;
};
var prepareString = "a"[0] != "a";
// ES5 9.9
// http://es5.github.com/#x9.9
var toObject = function (o) {
if (o == null) { // this matches both null and undefined
throw new TypeError("can't convert "+o+" to object");
}
// If the implementation doesn't support by-index access of
// string characters (ex. IE < 9), split the string
if (prepareString && typeof o == "string" && o) {
return o.split("");
}
return Object(o);
};
});
// Three.js - http://github.com/mrdoob/three.js
'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array);
(function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c<b.length&&!window.requestAnimationFrame;++c){window.requestAnimationFrame=window[b[c]+"RequestAnimationFrame"];window.cancelAnimationFrame=window[b[c]+"CancelAnimationFrame"]||window[b[c]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame)window.requestAnimationFrame=function(b){var c=Date.now(),f=Math.max(0,16-(c-a)),g=window.setTimeout(function(){b(c+f)},f);a=c+f;return g};if(!window.cancelAnimationFrame)window.cancelAnimationFrame=
function(a){clearTimeout(a)}})();THREE.Clock=function(a){this.autoStart=a!==void 0?a:true;this.elapsedTime=this.oldTime=this.startTime=0;this.running=false};THREE.Clock.prototype.start=function(){this.oldTime=this.startTime=Date.now();this.running=true};THREE.Clock.prototype.stop=function(){this.getElapsedTime();this.running=false};THREE.Clock.prototype.getElapsedTime=function(){return this.elapsedTime=this.elapsedTime+this.getDelta()};
THREE.Clock.prototype.getDelta=function(){var a=0;this.autoStart&&!this.running&&this.start();if(this.running){var b=Date.now(),a=0.001*(b-this.oldTime);this.oldTime=b;this.elapsedTime=this.elapsedTime+a}return a};THREE.Color=function(a){a!==void 0&&this.setHex(a);return this};
THREE.Color.prototype={constructor:THREE.Color,r:1,g:1,b:1,copy:function(a){this.r=a.r;this.g=a.g;this.b=a.b;return this},copyGammaToLinear:function(a){this.r=a.r*a.r;this.g=a.g*a.g;this.b=a.b*a.b;return this},copyLinearToGamma:function(a){this.r=Math.sqrt(a.r);this.g=Math.sqrt(a.g);this.b=Math.sqrt(a.b);return this},convertGammaToLinear:function(){var a=this.r,b=this.g,c=this.b;this.r=a*a;this.g=b*b;this.b=c*c;return this},convertLinearToGamma:function(){this.r=Math.sqrt(this.r);this.g=Math.sqrt(this.g);
this.b=Math.sqrt(this.b);return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSV:function(a,b,c){var d,e,f;if(c===0)this.r=this.g=this.b=0;else{d=Math.floor(a*6);e=a*6-d;a=c*(1-b);f=c*(1-b*e);b=c*(1-b*(1-e));switch(d){case 1:this.r=f;this.g=c;this.b=a;break;case 2:this.r=a;this.g=c;this.b=b;break;case 3:this.r=a;this.g=f;this.b=c;break;case 4:this.r=b;this.g=a;this.b=c;break;case 5:this.r=c;this.g=a;this.b=f;break;case 6:case 0:this.r=c;this.g=b;this.b=a}}return this},setHex:function(a){a=
Math.floor(a);this.r=(a>>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}};
THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0};
THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x=
this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)},
lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0};
THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+
a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y=
this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},
setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this,
a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b=
this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1};
THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x=
this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())},
normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]};
THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}};
THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3;
THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3,
l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(),
a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q<r;q++){b=t.faces[q];l.copy(this.origin);k.copy(this.direction);C=a.matrixWorld;p=C.multiplyVector3(p.copy(b.centroid)).subSelf(l);m=a.matrixRotationWorld.multiplyVector3(m.copy(b.normal));s=k.dot(m);if(!(Math.abs(s)<e)){i=m.dot(p)/s;if(!(i<0)&&(a.doubleSided||(a.flipSided?
s>0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(),
face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;c<d;c++)Array.prototype.push.apply(b,this.intersectObject(a[c]));b.sort(function(a,b){return a.distance-b.distance});return b};var q=new THREE.Vector3,n=new THREE.Vector3,r=new THREE.Vector3,u,t,y,s,w,H,E,z,v,A,J};
THREE.Rectangle=function(){function a(){f=d-b;g=e-c}var b,c,d,e,f,g,h=true;this.getX=function(){return b};this.getY=function(){return c};this.getWidth=function(){return f};this.getHeight=function(){return g};this.getLeft=function(){return b};this.getTop=function(){return c};this.getRight=function(){return d};this.getBottom=function(){return e};this.set=function(f,g,k,p){h=false;b=f;c=g;d=k;e=p;a()};this.addPoint=function(f,g){if(h){h=false;b=f;c=g;d=f;e=g}else{b=b<f?b:f;c=c<g?c:g;d=d>f?d:f;e=e>g?
e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=f<k?f<m?f:m:k<m?k:m;c=g<p?g<o?g:o:p<o?p:o;d=f>k?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=f<k?f<m?f<b?f:b:m<b?m:b:k<m?k<b?k:b:m<b?m:b;c=g<p?g<o?g<c?g:c:o<c?o:c:p<o?p<c?p:c:o<c?o:c;d=f>k?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=b<f.getLeft()?b:f.getLeft();c=c<f.getTop()?c:f.getTop();
d=d>f.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=d<f.getRight()?d:f.getRight();e=e<f.getBottom()?e:f.getBottom();a()};this.intersects=function(a){return d<a.getLeft()||b>a.getRight()||e<a.getTop()||c>a.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}};
THREE.Math={clamp:function(a,b,c){return a<b?b:a>c?c:a},clampBottom:function(a,b){return a<b?b:a},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},random16:function(){return(65280*Math.random()+255*Math.random())/65535},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(0.5-Math.random())},sign:function(a){return a<0?-1:a>0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)};
THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this},
transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)};
THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements,
e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4],
H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this,
a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]=
b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x,
d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7],
n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2];
a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13],
a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q=
c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p-
e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g*
j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j;
c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements,
e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3;
c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements;
b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]*
d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]=
k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x,
e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]=
o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this},
makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h-
d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a,
b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4;
THREE.Matrix4.__m2=new THREE.Matrix4;
THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=
true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3};
THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,
this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b=
this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c<d;c++){e=this.children[c];if(e.name===a)return e;if(b){e=e.getChildByName(a,b);if(e!==void 0)return e}}},updateMatrix:function(){this.matrix.setPosition(this.position);this.useQuaternion?this.matrix.setRotationFromQuaternion(this.quaternion):this.matrix.setRotationFromEuler(this.rotation,
this.eulerOrder);if(this.scale.x!==1||this.scale.y!==1||this.scale.z!==1){this.matrix.scale(this.scale);this.boundRadiusScale=Math.max(this.scale.x,Math.max(this.scale.y,this.scale.z))}this.matrixWorldNeedsUpdate=true},updateMatrixWorld:function(a){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||a){this.parent?this.matrixWorld.multiply(this.parent.matrixWorld,this.matrix):this.matrixWorld.copy(this.matrix);this.matrixWorldNeedsUpdate=false;a=true}for(var b=0,c=this.children.length;b<
c;b++)this.children[b].updateMatrixWorld(a)}};THREE.Object3DCount=0;
THREE.Projector=function(){function a(){var a=g[f]=g[f]||new THREE.RenderableObject;f++;return a}function b(){var a=l[j]=l[j]||new THREE.RenderableVertex;j++;return a}function c(a,b){return b.z-a.z}function d(a,b){var c=0,d=1,e=a.z+a.w,f=b.z+b.w,g=-a.z+a.w,h=-b.z+b.w;if(e>=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(d<c)return false;a.lerpSelf(b,c);b.lerpSelf(a,1-
d);return true}var e,f,g=[],h,j,l=[],k,p,m=[],o,q=[],n,r,u=[],t,y,s=[],w={objects:[],sprites:[],lights:[],elements:[]},H=new THREE.Vector3,E=new THREE.Vector4,z=new THREE.Matrix4,v=new THREE.Matrix4,A=new THREE.Frustum,J=new THREE.Vector4,K=new THREE.Vector4;this.projectVector=function(a,b){b.matrixWorldInverse.getInverse(b.matrixWorld);z.multiply(b.projectionMatrix,b.matrixWorldInverse);z.multiplyVector3(a);return a};this.unprojectVector=function(a,b){b.projectionMatrixInverse.getInverse(b.projectionMatrix);
z.multiply(b.matrixWorld,b.projectionMatrixInverse);z.multiplyVector3(a);return a};this.pickingRay=function(a,b){var c;a.z=-1;c=new THREE.Vector3(a.x,a.y,1);this.unprojectVector(a,b);this.unprojectVector(c,b);c.subSelf(a).normalize();return new THREE.Ray(a,c)};this.projectGraph=function(b,d){f=0;w.objects.length=0;w.sprites.length=0;w.lights.length=0;var g=function(b){if(b.visible!==false){if((b instanceof THREE.Mesh||b instanceof THREE.Line)&&(b.frustumCulled===false||A.contains(b))){H.copy(b.matrixWorld.getPosition());
z.multiplyVector3(H);e=a();e.object=b;e.z=H.z;w.objects.push(e)}else if(b instanceof THREE.Sprite||b instanceof THREE.Particle){H.copy(b.matrixWorld.getPosition());z.multiplyVector3(H);e=a();e.object=b;e.z=H.z;w.sprites.push(e)}else b instanceof THREE.Light&&w.lights.push(b);for(var c=0,d=b.children.length;c<d;c++)g(b.children[c])}};g(b);d&&w.objects.sort(c);return w};this.projectScene=function(a,e,f){var g=e.near,G=e.far,i=false,H,U,C,Y,F,ea,fa,ia,O,Q,Z,=O.geometry.materials;Y=Z.vertices;ha=Z.faces;Ma=Z.faceVertexUvs;Z=O.matrixRotationWorld.extractRotation(Q);U=0;for(C=
Y.length;U<C;U++){h=b();h.positionWorld.copy(Y[U]);Q.multiplyVector3(h.positionWorld);h.positionScreen.copy(h.positionWorld);z.multiplyVector4(h.positionScreen);h.positionScreen.x=h.positionScreen.x/h.positionScreen.w;h.positionScreen.y=h.positionScreen.y/h.positionScreen.w;h.visible=h.positionScreen.z>g&&h.positionScreen.z<G}Y=0;for(U=ha.length;Y<U;Y++){C=ha[Y];if(C instanceof THREE.Face3){F=l[C.a];ea=l[C.b];fa=l[C.c];if(F.visible&&ea.visible&&fa.visible){i=(fa.positionScreen.x-F.positionScreen.x)*
(ea.positionScreen.y-F.positionScreen.y)-(fa.positionScreen.y-F.positionScreen.y)*(ea.positionScreen.x-F.positionScreen.x)<0;if(O.doubleSided||i!=O.flipSided){ia=m[p]=m[p]||new THREE.RenderableFace3;p++;k=ia;k.v1.copy(F);k.v2.copy(ea);k.v3.copy(fa)}else continue}else continue}else if(C instanceof THREE.Face4){F=l[C.a];ea=l[C.b];fa=l[C.c];ia=l[C.d];if(F.visible&&ea.visible&&fa.visible&&ia.visible){i=(ia.positionScreen.x-F.positionScreen.x)*(ea.positionScreen.y-F.positionScreen.y)-(ia.positionScreen.y-
F.positionScreen.y)*(ea.positionScreen.x-F.positionScreen.x)<0||(ea.positionScreen.x-fa.positionScreen.x)*(ia.positionScreen.y-fa.positionScreen.y)-(ea.positionScreen.y-fa.positionScreen.y)*(ia.positionScreen.x-fa.positionScreen.x)<0;if(O.doubleSided||i!=O.flipSided){Ka=q[o]=q[o]||new THREE.RenderableFace4;o++;k=Ka;k.v1.copy(F);k.v2.copy(ea);k.v3.copy(fa);k.v4.copy(ia)}else continue}else continue}k.normalWorld.copy(C.normal);!i&&(O.flipSided||O.doubleSided)&&k.normalWorld.negate();Z.multiplyVector3(k.normalWorld);
k.centroidWorld.copy(C.centroid);Q.multiplyVector3(k.centroidWorld);k.centroidScreen.copy(k.centroidWorld);z.multiplyVector3(k.centroidScreen);fa=C.vertexNormals;F=0;for(ea=fa.length;F<ea;F++){ia=k.vertexNormalsWorld[F];ia.copy(fa[F]);!i&&(O.flipSided||O.doubleSided)&&ia.negate();Z.multiplyVector3(ia)}F=0;for(ea=Ma.length;F<ea;F++)if(Ka=Ma[F][Y]){fa=0;for(ia=Ka.length;fa<ia;fa++)k.uvs[F][fa]=Ka[fa]}k.material=O.material;k.faceMaterial=C.materialIndex!==null?=u[r]=u[r]||new THREE.RenderableLine;r++;n==new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=.g=aa.g;Q.b=Z.b=);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));.r,1));.g,1));.b,1));ha.r=(Z.r+.g)*0.5;ha.b=(Z.b+,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g=
aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,
Ra,La);.g=.r)*0.5;ha.g=(Z.g+.b)*0.5;Sa=Cc(Q,Z,a)if(!m.wireframe&&
m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=.g=ha.g=aa.g;Q.b=Z.b=);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g=
Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));.r,1));.g,1));.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,.r=.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc<bd;Dc++){Ha=h[Dc];eb=Ha.material;eb=eb instanceof THREE.MeshFaceMaterial?Ha.faceMaterial:eb;if(!(eb===void 0||eb.visible===false)){xa.empty();if(Ha instanceof THREE.RenderableParticle){v=Ha;v.x=v.x*o;v.y=v.y*q;r(v,Ha,eb,a)}else if(Ha instanceof THREE.RenderableLine){v=Ha.v1;A=Ha.v2;v.positionScreen.x=v.positionScreen.x*o;v.positionScreen.y=v.positionScreen.y*q;A.positionScreen.x=A.positionScreen.x*
o;A.positionScreen.y=A.positionScreen.y*q;xa.addPoint(v.positionScreen.x,v.positionScreen.y);xa.addPoint(A.positionScreen.x,A.positionScreen.y);Wa.intersects(xa)&&s(v,A,Ha,eb,a)}else if(Ha instanceof THREE.RenderableFace3){v=Ha.v1;A=Ha.v2;J=Ha.v3;v.positionScreen.x=v.positionScreen.x*o;v.positionScreen.y=v.positionScreen.y*q;A.positionScreen.x=A.positionScreen.x*o;A.positionScreen.y=A.positionScreen.y*q;J.positionScreen.x=J.positionScreen.x*o;J.positionScreen.y=J.positionScreen.y*q;if(eb.overdraw){Nb(v.positionScreen,
A.positionScreen);Nb(A.positionScreen,J.positionScreen);Nb(J.positionScreen,v.positionScreen)}xa.add3Points(v.positionScreen.x,v.positionScreen.y,A.positionScreen.x,A.positionScreen.y,J.positionScreen.x,J.positionScreen.y);Wa.intersects(xa)&&t(v,A,J,0,1,2,Ha,eb,a)}else if(Ha instanceof THREE.RenderableFace4){v=Ha.v1;A=Ha.v2;J=Ha.v3;K=Ha.v4;v.positionScreen.x=v.positionScreen.x*o;v.positionScreen.y=v.positionScreen.y*q;A.positionScreen.x=A.positionScreen.x*o;A.positionScreen.y=A.positionScreen.y*q;
J.positionScreen.x=J.positionScreen.x*o;J.positionScreen.y=J.positionScreen.y*q;K.positionScreen.x=K.positionScreen.x*o;K.positionScreen.y=K.positionScreen.y*q;R.positionScreen.copy(A.positionScreen);P.positionScreen.copy(K.positionScreen);if(eb.overdraw){Nb(v.positionScreen,A.positionScreen);Nb(A.positionScreen,K.positionScreen);Nb(K.positionScreen,v.positionScreen);Nb(J.positionScreen,R.positionScreen);Nb(J.positionScreen,P.positionScreen)}xa.addPoint(v.positionScreen.x,v.positionScreen.y);xa.addPoint(A.positionScreen.x,
A.positionScreen.y);xa.addPoint(J.positionScreen.x,J.positionScreen.y);xa.addPoint(K.positionScreen.x,K.positionScreen.y);Wa.intersects(xa)&&u(v,A,J,K,R,P,Ha,eb,a)}Ba.addRectangle(xa)}}n.setTransform(1,0,0,1,0,0)}};
THREE.SVGRenderer=function(){function a(a,b,c,d){var e,f,g,h,j,k;e=0;for(f=a.length;e<f;e++){g=a[e];h=g.color;if(g instanceof THREE.DirectionalLight){j=g.matrixWorld.getPosition();k=c.dot(j);if(!(k<=0)){k=k*g.intensity;d.r=d.r+h.r*k;d.g=d.g+h.g*k;d.b=d.b+h.b*k}}else if(g instanceof THREE.PointLight){j=g.matrixWorld.getPosition();k=c.dot(v.sub(j,b).normalize());if(!(k<=0)){k=k*(g.distance==0?1:1-Math.min(b.distanceTo(j)/g.distance,1));if(k!=0){k=k*g.intensity;d.r=d.r+h.r*k;d.g=d.g+h.g*k;d.b=d.b+h.b*
k}}}}}function b(a){if(A[a]==null){A[a]=document.createElementNS("http://www.w3.org/2000/svg","path");D==0&&A[a].setAttribute("shape-rendering","crispEdges")}return A[a]}function c(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color,
z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k,
l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i<v;i++){C=g[i];A=C.color;if(C instanceof THREE.AmbientLight){w.r=w.r+A.r;w.g=w.g+A.g;w.b=w.b+A.b}else if(C instanceof THREE.DirectionalLight){H.r=H.r+A.r;H.g=H.g+A.g;H.b=H.b+A.b}else if(C instanceof THREE.PointLight){E.r=E.r+A.r;E.g=E.g+A.g;E.b=E.b+A.b}}}i=
0;for(v=f.length;i<v;i++){A=f[i];C=A.material;C=C instanceof THREE.MeshFaceMaterial?A.faceMaterial:C;if(!(C===void 0||C.visible===false)){t.empty();if(A instanceof THREE.RenderableParticle){o=A;o.x=o.x*p;o.y=o.y*-m}else if(A instanceof THREE.RenderableLine){o=A.v1;q=A.v2;o.positionScreen.x=o.positionScreen.x*p;o.positionScreen.y=o.positionScreen.y*-m;q.positionScreen.x=q.positionScreen.x*p;q.positionScreen.y=q.positionScreen.y*-m;t.addPoint(o.positionScreen.x,o.positionScreen.y);t.addPoint(q.positionScreen.x,
q.positionScreen.y);if(u.intersects(t)){A=o;var Y=q,F=P++;if(J[F]==null){J[F]=document.createElementNS("http://www.w3.org/2000/svg","line");D==0&&J[F].setAttribute("shape-rendering","crispEdges")}K=J[F];K.setAttribute("x1",A.positionScreen.x);K.setAttribute("y1",A.positionScreen.y);K.setAttribute("x2",Y.positionScreen.x);K.setAttribute("y2",Y.positionScreen.y);if(C instanceof THREE.LineBasicMaterial){K.setAttribute("style","fill: none; stroke: "+C.color.getContextStyle()+"; stroke-width: "+C.linewidth+
"; stroke-opacity: "+C.opacity+"; stroke-linecap: "+C.linecap+"; stroke-linejoin: "+C.linejoin);j.appendChild(K)}}}else if(A instanceof THREE.RenderableFace3){o=A.v1;q=A.v2;n=A.v3;o.positionScreen.x=o.positionScreen.x*p;o.positionScreen.y=o.positionScreen.y*-m;q.positionScreen.x=q.positionScreen.x*p;q.positionScreen.y=q.positionScreen.y*-m;n.positionScreen.x=n.positionScreen.x*p;n.positionScreen.y=n.positionScreen.y*-m;t.addPoint(o.positionScreen.x,o.positionScreen.y);t.addPoint(q.positionScreen.x,
q.positionScreen.y);t.addPoint(n.positionScreen.x,n.positionScreen.y);if(u.intersects(t)){var Y=o,F=q,ea=n;d.info.render.vertices=d.info.render.vertices+3;d.info.render.faces++;K=b(R++);K.setAttribute("d","M "+Y.positionScreen.x+" "+Y.positionScreen.y+" L "+F.positionScreen.x+" "+F.positionScreen.y+" L "+ea.positionScreen.x+","+ea.positionScreen.y+"z");if(C instanceof THREE.MeshBasicMaterial)s.copy(C.color);else if(C instanceof THREE.MeshLambertMaterial)if(y){s.r=w.r;s.g=w.g;s.b=w.b;a(g,A.centroidWorld,
A.normalWorld,s);s.r=Math.max(0,Math.min(C.color.r*s.r,1));s.g=Math.max(0,Math.min(C.color.g*s.g,1));s.b=Math.max(0,Math.min(C.color.b*s.b,1))}else s.copy(C.color);else if(C instanceof THREE.MeshDepthMaterial){z=1-C.__2near/(C.__farPlusNear-A.z*C.__farMinusNear);s.setRGB(z,z,z)}else C instanceof THREE.MeshNormalMaterial&&s.setRGB(c(A.normalWorld.x),c(A.normalWorld.y),c(A.normalWorld.z));C.wireframe?K.setAttribute("style","fill: none; stroke: "+s.getContextStyle()+"; stroke-width: "+C.wireframeLinewidth+
"; stroke-opacity: "+C.opacity+"; stroke-linecap: "+C.wireframeLinecap+"; stroke-linejoin: "+C.wireframeLinejoin):K.setAttribute("style","fill: "+s.getContextStyle()+"; fill-opacity: "+C.opacity);j.appendChild(K)}}else if(A instanceof THREE.RenderableFace4){o=A.v1;q=A.v2;n=A.v3;r=A.v4;o.positionScreen.x=o.positionScreen.x*p;o.positionScreen.y=o.positionScreen.y*-m;q.positionScreen.x=q.positionScreen.x*p;q.positionScreen.y=q.positionScreen.y*-m;n.positionScreen.x=n.positionScreen.x*p;n.positionScreen.y=
n.positionScreen.y*-m;r.positionScreen.x=r.positionScreen.x*p;r.positionScreen.y=r.positionScreen.y*-m;t.addPoint(o.positionScreen.x,o.positionScreen.y);t.addPoint(q.positionScreen.x,q.positionScreen.y);t.addPoint(n.positionScreen.x,n.positionScreen.y);t.addPoint(r.positionScreen.x,r.positionScreen.y);if(u.intersects(t)){var Y=o,F=q,ea=n,fa=r;d.info.render.vertices=d.info.render.vertices+4;d.info.render.faces++;K=b(R++);K.setAttribute("d","M "+Y.positionScreen.x+" "+Y.positionScreen.y+" L "+F.positionScreen.x+
" "+F.positionScreen.y+" L "+ea.positionScreen.x+","+ea.positionScreen.y+" L "+fa.positionScreen.x+","+fa.positionScreen.y+"z");if(C instanceof THREE.MeshBasicMaterial)s.copy(C.color);else if(C instanceof THREE.MeshLambertMaterial)if(y){s.r=w.r;s.g=w.g;s.b=w.b;a(g,A.centroidWorld,A.normalWorld,s);s.r=Math.max(0,Math.min(C.color.r*s.r,1));s.g=Math.max(0,Math.min(C.color.g*s.g,1));s.b=Math.max(0,Math.min(C.color.b*s.b,1))}else s.copy(C.color);else if(C instanceof THREE.MeshDepthMaterial){z=1-C.__2near/
(C.__farPlusNear-A.z*C.__farMinusNear);s.setRGB(z,z,z)}else C instanceof THREE.MeshNormalMaterial&&s.setRGB(c(A.normalWorld.x),c(A.normalWorld.y),c(A.normalWorld.z));C.wireframe?K.setAttribute("style","fill: none; stroke: "+s.getContextStyle()+"; stroke-width: "+C.wireframeLinewidth+"; stroke-opacity: "+C.opacity+"; stroke-linecap: "+C.wireframeLinecap+"; stroke-linejoin: "+C.wireframeLinejoin):K.setAttribute("style","fill: "+s.getContextStyle()+"; fill-opacity: "+C.opacity);j.appendChild(K)}}}}}};
THREE.ShaderChunk={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n#endif",
envmap_pars_fragment:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float reflectivity;\nuniform samplerCube envMap;\nuniform float flipEnvMap;\nuniform int combine;\n#endif",envmap_fragment:"#ifdef USE_ENVMAP\n#ifdef DOUBLE_SIDED\nfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\nvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * vReflect.x, vReflect.yz ) );\n#else\nvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * vReflect.x, vReflect.yz ) );\n#endif\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\nif ( combine == 1 ) {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, reflectivity );\n} else {\ngl_FragColor.xyz = gl_FragColor.xyz * cubeColor.xyz;\n}\n#endif",
envmap_pars_vertex:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float refractionRatio;\nuniform bool useRefract;\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvec3 nWorld = mat3( objectMatrix[ 0 ].xyz, objectMatrix[ 1 ].xyz, objectMatrix[ 2 ].xyz ) * normal;\nif ( useRefract ) {\nvReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refractionRatio );\n} else {\nvReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );\n}\n#endif",
map_particle_pars_fragment:"#ifdef USE_MAP\nuniform sampler2D map;\n#endif",map_particle_fragment:"#ifdef USE_MAP\ngl_FragColor = gl_FragColor * texture2D( map, gl_PointCoord );\n#endif",map_pars_vertex:"#ifdef USE_MAP\nvarying vec2 vUv;\nuniform vec4 offsetRepeat;\n#endif",map_pars_fragment:"#ifdef USE_MAP\nvarying vec2 vUv;\nuniform sampler2D map;\n#endif",map_vertex:"#ifdef USE_MAP\nvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif",map_fragment:"#ifdef USE_MAP\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( map, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( map, vUv );\n#endif\n#endif",
lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\nuniform sampler2D lightMap;\n#endif",lightmap_pars_vertex:"#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\n#endif",lightmap_fragment:"#ifdef USE_LIGHTMAP\ngl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );\n#endif",lightmap_vertex:"#ifdef USE_LIGHTMAP\nvUv2 = uv2;\n#endif",lights_lambert_pars_vertex:"uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif",
lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif",
lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif",
lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",
lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif",
color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif",
morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif",
default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif",
shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif",
shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif",
linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"};
THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b<a.length;b++){d=this.clone(a[b]);for(c in d)e[c]=d[c]}return e},clone:function(a){var b,c,d,e={};for(b in a){e[b]={};for(c in a[b]){d=a[b][c];e[b][c]=d instanceof THREE.Color||d instanceof THREE.Vector2||d instanceof THREE.Vector3||d instanceof THREE.Vector4||d instanceof THREE.Matrix4||d instanceof THREE.Texture?d.clone():d instanceof Array?d.slice():d}}return e}};
THREE.UniformsLib={common:{diffuse:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},map:{type:"t",value:0,texture:null},offsetRepeat:{type:"v4",value:new THREE.Vector4(0,0,1,1)},lightMap:{type:"t",value:2,texture:null},envMap:{type:"t",value:1,texture:null},flipEnvMap:{type:"f",value:-1},useRefract:{type:"i",value:0},reflectivity:{type:"f",value:1},refractionRatio:{type:"f",value:0.98},combine:{type:"i",value:0},morphTargetInfluences:{type:"f",value:0}},fog:{fogDensity:{type:"f",
value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},lights:{ambientLightColor:{type:"fv",value:[]},directionalLightDirection:{type:"fv",value:[]},directionalLightColor:{type:"fv",value:[]},pointLightColor:{type:"fv",value:[]},pointLightPosition:{type:"fv",value:[]},pointLightDistance:{type:"fv1",value:[]},spotLightColor:{type:"fv",value:[]},spotLightPosition:{type:"fv",value:[]},spotLightDirection:{type:"fv",value:[]},spotLightDistance:{type:"fv1",
value:[]},spotLightAngle:{type:"fv1",value:[]},spotLightExponent:{type:"fv1",value:[]}},particle:{psColor:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},size:{type:"f",value:1},scale:{type:"f",value:1},map:{type:"t",value:0,texture:null},fogDensity:{type:"f",value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},shadowmap:{shadowMap:{type:"tv",value:6,texture:[]},shadowMapSize:{type:"v2v",value:[]},shadowBias:{type:"fv1",
value:[]},shadowDarkness:{type:"fv1",value:[]},shadowMatrix:{type:"m4v",value:[]}}};
THREE.ShaderLib={depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3},opacity:{type:"f",value:1}},vertexShader:"void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform float mNear;\nuniform float mFar;\nuniform float opacity;\nvoid main() {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat color = 1.0 - smoothstep( mNear, mFar, depth );\ngl_FragColor = vec4( vec3( color ), opacity );\n}"},normal:{uniforms:{opacity:{type:"f",
value:1}},vertexShader:"varying vec3 vNormal;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalMatrix * normal;\ngl_Position = projectionMatrix * mvPosition;\n}",fragmentShader:"uniform float opacity;\nvarying vec3 vNormal;\nvoid main() {\ngl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );\n}"},basic:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,THREE.UniformsLib.shadowmap]),vertexShader:[THREE.ShaderChunk.map_pars_vertex,
THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.color_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.morphtarget_vertex,
THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;",THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,"void main() {\ngl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,
THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},lambert:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{ambient:{type:"c",value:new THREE.Color(16777215)},emissive:{type:"c",value:new THREE.Color(0)},wrapRGB:{type:"v3",value:new THREE.Vector3(1,
1,1)}}]),vertexShader:["varying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif",THREE.ShaderChunk.map_pars_vertex,THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.lights_lambert_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.ShaderChunk.map_vertex,
THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.color_vertex,THREE.ShaderChunk.morphnormal_vertex,"#ifndef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\n#endif",THREE.ShaderChunk.lights_lambert_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif",
THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );",THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,"#ifdef DOUBLE_SIDED\nif ( gl_FrontFacing )\ngl_FragColor.xyz *= vLightFront;\nelse\ngl_FragColor.xyz *= vLightBack;\n#else\ngl_FragColor.xyz *= vLightFront;\n#endif",
THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},phong:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{ambient:{type:"c",value:new THREE.Color(16777215)},emissive:{type:"c",value:new THREE.Color(0)},specular:{type:"c",value:new THREE.Color(1118481)},
shininess:{type:"f",value:30},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),vertexShader:["varying vec3 vViewPosition;\nvarying vec3 vNormal;",THREE.ShaderChunk.map_pars_vertex,THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.lights_phong_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.color_vertex,"#ifndef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\n#endif\nvViewPosition = -mvPosition.xyz;",THREE.ShaderChunk.morphnormal_vertex,"vNormal = transformedNormal;",THREE.ShaderChunk.lights_phong_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),
fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;\nuniform vec3 ambient;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;",THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment,THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.lights_phong_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.lights_phong_fragment,THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},particle_basic:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.particle,THREE.UniformsLib.shadowmap]),vertexShader:["uniform float size;\nuniform float scale;",
THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.color_vertex,"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n#ifdef USE_SIZEATTENUATION\ngl_PointSize = size * ( scale / length( mvPosition.xyz ) );\n#else\ngl_PointSize = size;\n#endif\ngl_Position = projectionMatrix * mvPosition;",THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 psColor;\nuniform float opacity;",THREE.ShaderChunk.color_pars_fragment,
THREE.ShaderChunk.map_particle_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,"void main() {\ngl_FragColor = vec4( psColor, opacity );",THREE.ShaderChunk.map_particle_fragment,THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,"}"].join("\n"),fragmentShader:"vec4 pack_depth( const in float depth ) {\nconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\nconst vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\nvec4 res = fract( depth * bit_shift );\nres -= res.xxyz * bit_mask;\nreturn res;\n}\nvoid main() {\ngl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n}"}};
THREE.WebGLRenderer=function(a){function b(a,b){var c=a.vertices.length,d=b.material;if(d.attributes){if(a.__webglCustomAttributesList===void 0)a.__webglCustomAttributesList=[];for(var e in d.attributes){var f=d.attributes[e];if(!f.__webglInitialized||f.createUniqueBuffers){f.__webglInitialized=true;var g=1;f.type==="v2"?g=2:f.type==="v3"?g=3:f.type==="v4"?g=4:f.type==="c"&&(g=3);f.size=g;f.array=new Float32Array(c*g);f.buffer=i.createBuffer();f.buffer.belongsToAttribute=e;f.needsUpdate=true}a.__webglCustomAttributesList.push(f)}}}
function c(a,b){if(a.material&&!(a.material instanceof THREE.MeshFaceMaterial))return a.material;if(b.materialIndex>=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length;
var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d<g;d++){e=h[d];a);n[d]=[=-1,ha=-1,Ma=-1,Ka=-1,Ra=null,La=null,Sa=null,Na=null,Kb=0,lb=0,gb=0,Lb=0,hb=0,Cb=0,Wa=new THREE.Frustum,
Ba=new THREE.Matrix4,xa=new THREE.Matrix4,a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3(a.z}}}this.sortObjects&&
m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d<e;d++){f=m[d];k=f.object;if(k.visible){r(k,b);k=f.object.material;if(k.transparent){f.transparent=k;f.opaque=null}else{f.opaque=k;f.transparent=null}}}if(a.overrideMaterial){d=a.overrideMaterial;this.setBlending(d.blending,d.blendEquation,d.blendSrc,d.blendDst);this.setDepthTest(d.depthTest);this.setDepthWrite(d.depthWrite);u(d.polygonOffset,d.polygonOffsetFactor,d.polygonOffsetUnits);j(a.__webglObjects,false,"",b,n,p,true,d);l(a.__webglObjectsImmediate,
"",b,n,p,false,d)}else{this.setBlending(THREE.NormalBlending);j(a.__webglObjects,true,"opaque",b,n,p,false);l(a.__webglObjectsImmediate,"opaque",b,n,p,false);j(a.__webglObjects,false,"transparent",b,n,p,true);l(a.__webglObjectsImmediate,"transparent",b,n,p,true)}h(this.renderPluginsPost,a,b);if(c&&c.generateMipmaps&&c.minFilter!==THREE.NearestFilter&&c.minFilter!==THREE.LinearFilter)if(c instanceof THREE.WebGLRenderTargetCube){i.bindTexture(i.TEXTURE_CUBE_MAP,c.__webglTexture);i.generateMipmap(i.TEXTURE_CUBE_MAP);
i.bindTexture(i.TEXTURE_CUBE_MAP,null)}else{i.bindTexture(i.TEXTURE_2D,c.__webglTexture);i.generateMipmap(i.TEXTURE_2D);i.bindTexture(i.TEXTURE_2D,null)}this.setDepthTest(true);this.setDepthWrite(true)};this.renderImmediateObject=function(a,b,c,d,e){var f=n(a,b,c,d,e);F=-1;G.setObjectFaces(e);e.immediateRenderCallback?e.immediateRenderCallback(f,i,Wa):e.render(function(a){G.renderBufferImmediate(a,f,d.shading)})};this.initWebGLObjects=function(a){if(!a.__webglObjects){a.__webglObjects=[];a.__webglObjectsImmediate=
[];a.__webglSprites=[];a.__webglFlares=[]}for(;a.__objectsAdded.length;){var g=a.__objectsAdded[0],h=a,j=void 0,l=void 0,n=void 0;if(!g.__webglInit){g.__webglInit=true;g._modelViewMatrix=new THREE.Matrix4;g._normalMatrix=new THREE.Matrix3;if(g instanceof THREE.Mesh){l=g.geometry;if(l instanceof THREE.Geometry){if(l.geometryGroups===void 0){var r=l,s=void 0,t=void 0,u=void 0,v=void 0,w=void 0,z=void 0,y=void 0,A={},C=r.morphTargets.length,D=r.morphNormals.length;r.geometryGroups={};s=0;for(t=r.faces.length;s<
t;s++){u=r.faces[s];v=u.materialIndex;z=v!==void 0?v:-1;A[z]===void 0&&(A[z]={hash:z,counter:0});y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C,numMorphNormals:D});w=u instanceof THREE.Face3?3:4;if(r.geometryGroups[y].vertices+w>65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C,
numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer();
F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H<K;H++)F.__webglMorphTargetsBuffers.push(i.createBuffer())}if(F.numMorphNormals){F.__webglMorphNormalsBuffers=
[];H=0;for(K=F.numMorphNormals;H<K;H++)F.__webglMorphNormalsBuffers.push(i.createBuffer())}G.info.memory.geometries++;var Q=n,J=g,O=J.geometry,M=Q.faces3,.length*4,Z=M.length*1+.length*4,R=c(J,Q),T=e(R),ea=d(R),ia=R.vertexColors?R.vertexColors:false;Q.__vertexArray=new Float32Array(P*3);if(ea)Q.__normalArray=new Float32Array(P*3);if(O.hasTangents)Q.__tangentArray=new Float32Array(P*4);if(ia)Q.__colorArray=new Float32Array(P*3);if(T){if(O.faceUvs.length>
0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays=
[];U=0;for(ha=Q.numMorphTargets;U<ha;U++)Q.__morphTargetsArrays.push(new Float32Array(P*3))}if(Q.numMorphNormals){Q.__morphNormalsArrays=[];U=0;for(ha=Q.numMorphNormals;U<ha;U++)Q.__morphNormalsArrays.push(new Float32Array(P*3))}Q.__webglFaceCount=Z*3;Q.__webglLineCount=Y*2;if(R.attributes){if(Q.__webglCustomAttributesList===void 0)Q.__webglCustomAttributesList=[];var Ra=void 0;for(Ra in R.attributes){var Ma=R.attributes[Ra],aa={},Ka;for(Ka in Ma)aa[Ka]=Ma[Ka];if(!aa.__webglInitialized||aa.createUniqueBuffers){aa.__webglInitialized=
true;var La=1;aa.type==="v2"?La=2:aa.type==="v3"?La=3:aa.type==="v4"?La=4:aa.type==="c"&&(La=3);aa.size=La;aa.array=new Float32Array(P*La);aa.buffer=i.createBuffer();aa.buffer.belongsToAttribute=Ra;Ma.needsUpdate=true;aa.__original=Ma}Q.__webglCustomAttributesList.push(aa)}}Q.__inittedArrays=true;l.verticesNeedUpdate=true;l.morphTargetsNeedUpdate=true;l.elementsNeedUpdate=true;l.uvsNeedUpdate=true;l.normalsNeedUpdate=true;l.tangetsNeedUpdate=true;l.colorsNeedUpdate=true}}}}else if(g instanceof THREE.Ribbon){l=
g.geometry;if(!l.__webglVertexBuffer){var Sa=l;Sa.__webglVertexBuffer=i.createBuffer();Sa.__webglColorBuffer=i.createBuffer();G.info.memory.geometries++;var oa=l,xa=oa.vertices.length;oa.__vertexArray=new Float32Array(xa*3);oa.__colorArray=new Float32Array(xa*3);oa.__webglVertexCount=xa;l.verticesNeedUpdate=true;l.colorsNeedUpdate=true}}else if(g instanceof THREE.Line){l=g.geometry;if(!l.__webglVertexBuffer){var Ba=l;Ba.__webglVertexBuffer=i.createBuffer();Ba.__webglColorBuffer=i.createBuffer();G.info.memory.geometries++;
var Na=l,Ta=g,Wa=Na.vertices.length;Na.__vertexArray=new Float32Array(Wa*3);Na.__colorArray=new Float32Array(Wa*3);Na.__webglLineCount=Wa;b(Na,Ta);l.verticesNeedUpdate=true;l.colorsNeedUpdate=true}}else if(g instanceof THREE.ParticleSystem){l=g.geometry;if(!l.__webglVertexBuffer){var a.__webglVertexBuffer=i.createBuffer();b=void 0,Kc=void 0,id=Zb.vertices,jd=Zb.colors,vd=id.length,wd=jd.length,Lc=Zb.__vertexArray,Mc=Zb.__colorArray,xd=Zb.colorsNeedUpdate;if(Zb.verticesNeedUpdate){for(xc=0;xc<
vd;xc++){Jc=id[xc];b]=Jc.x;Lc[b+2]=Jc.z}i.bindBuffer(i.ARRAY_BUFFER,Zb.__webglVertexBuffer);i.bufferData(i.ARRAY_BUFFER,Lc,hd)}if(xd){for(yc=0;yc<wd;yc++){Kc=jd[yc];b]=Kc.r;Mc[b+2]=Kc.b}i.bindBuffer(i.ARRAY_BUFFER,Zb.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Mc,hd)}}ga.verticesNeedUpdate=false;ga.colorsNeedUpdate=false}else if(jb instanceof THREE.Line){Ua=c(jb,hb);ic=Ua.attributes&&p(Ua);if(ga.verticesNeedUpdate||ga.colorsNeedUpdate||ic){var Jb=
ga,Zc=i.DYNAMIC_DRAW,zc=void 0,Ac=void 0,Nc=void 0,va=void 0,Oc=void 0,kd=Jb.vertices,ld=Jb.colors,yd=kd.length,zd=ld.length,Pc=Jb.__vertexArray,Qc=Jb.__colorArray,Ad=Jb.colorsNeedUpdate,c){Rc=0;for(md=c[Rc];if(pa.needsUpdate&&(pa.boundTo===void 0||pa.boundTo==="vertices")){va=0;oc=pa.value.length;if(pa.size===1)for(Ia=0;Ia<oc;Ia++)pa.array[Ia]=pa.value[Ia];else if(pa.size===2)for(Ia=0;Ia<oc;Ia++){Va=pa.value[Ia];pa.array[va]=Va.x;pa.array[va+1]=Va.y;va=va+2}else if(pa.size===3)if(pa.type==="c")for(Ia=0;Ia<oc;Ia++){Va=
pa.value[Ia];pa.array[va]=Va.r;pa.array[va+1]=Va.g;pa.array[va+2]=Va.b;va=va+3}else for(Ia=0;Ia<oc;Ia++){Va=pa.value[Ia];pa.array[va]=Va.x;pa.array[va+1]=Va.y;pa.array[va+2]=Va.z;va=va+3}else if(pa.size===4)for(Ia=0;Ia<oc;Ia++){Va=pa.value[Ia];pa.array[va]=Va.x;pa.array[va+1]=Va.y;pa.array[va+2]=Va.z;pa.array[va+3]=Va.w;va=va+4}i.bindBuffer(i.ARRAY_BUFFER,pa.buffer);i.bufferData(i.ARRAY_BUFFER,pa.array,Zc)}}}}ga.verticesNeedUpdate=false;ga.colorsNeedUpdate=false;Ua.attributes&&m(Ua)}else if(jb instanceof
THREE.ParticleSystem){Ua=c(jb,hb);ic=Ua.attributes&&p(Ua);(ga.verticesNeedUpdate||ga.colorsNeedUpdate||jb.sortParticles||ic)&&f(ga,i.DYNAMIC_DRAW,jb);ga.verticesNeedUpdate=false;ga.colorsNeedUpdate=false;Ua.attributes&&m(Ua)}}};this.initMaterial=function(a,b,c,d){var e,f,g;a instanceof THREE.MeshDepthMaterial?g="depth":a instanceof THREE.MeshNormalMaterial?g="normal":a instanceof THREE.MeshBasicMaterial?g="basic":a instanceof THREE.MeshLambertMaterial?g="lambert":a instanceof THREE.MeshPhongMaterial?
g="phong":a instanceof THREE.LineBasicMaterial?g="basic":a instanceof THREE.ParticleBasicMaterial&&(g="particle_basic");if(g){var h=THREE.ShaderLib[g];a.uniforms=THREE.UniformsUtils.clone(h.uniforms);a.vertexShader=h.vertexShader;a.fragmentShader=h.fragmentShader}var j,k,l,m,n;j=m=n=h=0;for(k=b.length;j<k;j++){l=b[j];if(!l.onlyShadow){l instanceof THREE.DirectionalLight&&m++;l instanceof THREE.PointLight&&n++;l instanceof THREE.SpotLight&&h++}}if(n+h+m<=M){k=m;l=n;m=h}else{k=Math.ceil(M*m/(n+m));
m=l=M-k}var p=0,h=0;for(n=b.length;h<n;h++){j=b[h];if(j.castShadow){j instanceof THREE.SpotLight&&p++;j instanceof THREE.DirectionalLight&&!j.shadowCascade&&p++}}var o=50;if(d!==void 0&&d instanceof THREE.SkinnedMesh)o=d.bones.length;var q;a:{n=a.fragmentShader;j=a.vertexShader;var h=a.uniforms,b=a.attributes,c={map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:o,morphTargets:a.morphTargets,
morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:k,maxPointLights:l,maxSpotLights:m,maxShadows:p,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapSoft:this.shadowMapSoft,shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:d&&d.doubleSided},r,d=[];if(g)d.push(g);else{d.push(n);d.push(j)}for(r in c){d.push(r);
d.push(c[r])}g=d.join();r=0;for(d=T.length;r<d;r++)if(T[r].code===g){q=T[r].program;break a}r=i.createProgram();d=["precision "+z+" float;",oa>0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+
c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":
"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP":
"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");
i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d<h;d++){n=
s[d];r.uniforms[n]=i.getUniformLocation(r,n)}d=["position","normal","uv","uv2","tangent","color","skinVertexA","skinVertexB","skinIndex","skinWeight"];for(s=0;s<c.maxMorphTargets;s++)d.push("morphTarget"+s);for(s=0;s<c.maxMorphNormals;s++)d.push("morphNormal"+s);for(q in b)d.push(q);q=d;s=0;for(b=q.length;s<b;s++){c=q[s];r.attributes[c]=i.getAttribLocation(r,c)}r.id=T.length;T.push({program:r,code:g});G.info.memory.programs=T.length;q=r}a.program=q;q=a.program.attributes;q.position>=0&&i.enableVertexAttribArray(q.position);
q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets=
0;r="morphTarget";for(f=0;f<this.maxMorphTargets;f++){s=r+f;if(q[s]>=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f<this.maxMorphNormals;f++){s=r+f;if(q[s]>=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK):
a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending=
function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND);
i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!===c;ha=d}}else ha=
@fileOverview This file is the core of tQuery library.
Create a tQuery element
@class root class
parameter: {} object
parameter: {THREE.Object3D} rootnode
returns: {tQuery.*} the tQuery object created
var tQuery = function(object, root)
{
// support for tQuery(geometry, material)
if( arguments.length === 2 &&
(arguments[0] instanceof THREE.Geometry || arguments[0] instanceof tQuery.Geometry)
&&
(arguments[1] instanceof THREE.Material || arguments[1] instanceof tQuery.Material)
){
var tGeometry = arguments[0] instanceof tQuery.Geometry ? arguments[0].get(0) : arguments[0];
var tMaterial = arguments[1] instanceof tQuery.Material ? arguments[1].get(0) : arguments[1];
var tMesh = new THREE.Mesh(tGeometry, tMaterial);
return tQuery( tMesh );
}
// TODO make tthat cleaner
// - there is a list of functions registered by each plugins
// - handle() object instanceof THREE.Mesh
// - create() return new tQuery(object)
// - this list is processed in order here
// if the object is an array, compare only the first element
// - up to the subconstructor to check if the whole array has proper type
var instance = Array.isArray(object) ? object[0] : object;
if( instance instanceof THREE.Mesh && tQuery.Mesh){
return new tQuery.Mesh(object);
}else if( instance instanceof THREE.DirectionalLight && tQuery.DirectionalLight){
return new tQuery.DirectionalLight(object);
}else if( instance instanceof THREE.AmbientLight && tQuery.AmbientLight){
return new tQuery.AmbientLight(object);
}else if( instance instanceof THREE.Light && tQuery.Light){
return new tQuery.Light(object);
}else if( instance instanceof THREE.Object3D && tQuery.Object3D){
return new tQuery.Object3D(object);
}else if( instance instanceof THREE.Geometry && tQuery.Geometry){
return new tQuery.Geometry(object);
}else if( instance instanceof THREE.Material && tQuery.Material){
return new tQuery.Material(object);
}else if( typeof instance === "string" && tQuery.Object3D){
return new tQuery.Object3D(object, root);
}else{
console.assert(false, "unsupported type")
}
return undefined;
};
The version of tQuery
tQuery.VERSION = "r49.1";
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
generic getter/setter
parameter: {Object} object the object in which store the data
parameter: {String} key the key/name of the data to get/set
parameter: {*} value the value to set (optional)
parameter: {Boolean} mustNotExist if true, ensure that the key doesnt already exist, optional default to false
returns: {*} return the value stored in this object for this key
tQuery.data = function(object, key, value, mustNotExist)
{
// sanity check
console.assert( object, 'invalid parameters' );
console.assert( typeof key === 'string', 'invalid parameters');
// init _tqData
object['_tqData'] = object['_tqData'] || {};
// honor mustNotExist
if( mustNotExist ){
console.assert(object['_tqData'][key] === undefined, "This key already exists "+key);
}
// set the value if any
if( value ){
object['_tqData'][key] = value;
}
// return the value
return object['_tqData'][key];
};
Same as jQuery.removeData()
parameter: {Boolean} mustExist if true, ensure the key does exist, default to false
tQuery.removeData = function(object, key, mustExist)
{
// handle the 'key as Array' case
if( key instanceof Array ){
key.forEach(function(key){
tQuery.removeData(object, key);
})
return;
}
// sanity check
console.assert( typeof key === "string");
// honor mustNotExist
if( mustExist ){
console.assert(object['_tqData'][key] !== undefined, "This key doesnt already exists "+key);
}
// do delete the key
delete object['_tqData'][key];
// TOTO remove object [tqData] if empty now
}
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
loop over a Array.
parameter: {Array} arr the array to traverse.
parameter: {Function} callback the function to notify. function(element){ }.
loop interrupted if it returns false
returns: {Boolean} return true if completed, false if interrupted
tQuery.each = function(arr, callback){
for(var i = 0; i < arr.length; i++){
var keepLooping = callback(arr[i])
if( keepLooping === false ) return false;
}
return true;
};
Make a child Class inherit from the parent class.
parameter: {Object} childClass the child class which gonna inherit
parameter: {Object} parentClass the class which gonna be inherited
tQuery.inherit = function(childClass, parentClass){
// trick to avoid calling parentClass constructor
var tempFn = function() {};
tempFn.prototype = parentClass.prototype;
childClass.prototype = new tempFn();
childClass.parent = parentClass.prototype;
childClass.prototype.constructor= childClass;
};
extend function. mainly aimed at handling default values - jme: im not sure at all it is the proper one.
http://jsapi.info/_/extend
similar to jquery one but much smaller
tQuery.extend = function(obj, base){
var result = {};
base && Object.keys(base).forEach(function(key){
result[key] = base[key];
})
obj && Object.keys(obj).forEach(function(key){
result[key] = obj[key];
})
return result;
};
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
Make an object pluginable
parameter: {Object} object the object on which you mixin function
parameter: {Object} dest the object in which to register the plugin
parameter: {string} suffix the suffix to add to the function name
tQuery._pluginsOn = function(object, dest, fnNameSuffix){
dest = dest || object.prototype || object;
fnNameSuffix = fnNameSuffix || '';
object['register'+fnNameSuffix] = function(name, funct) {
if( dest[name] ){
throw new Error('Conflict! Already method called: ' + name);
}
dest[name] = funct;
};
object['unregister'+fnNameSuffix] = function(name){
if( dest.hasOwnProperty(name) === false ){
throw new Error('Plugin not found: ' + name);
}
delete dest[name];
};
object['registered'+fnNameSuffix] = function(name){
return dest.hasOwnProperty(name) === true;
}
};
tQuery.pluginsInstanceOn= function(klass){ return tQuery._pluginsOn(klass); };
tQuery.pluginsStaticOn = function(klass){ return tQuery._pluginsOn(klass, klass, 'Static'); };
for backward compatibility only
tQuery.pluginsOn = function(object, dest){
console.warn("tQuery.pluginsOn is obsolete. prefere .pluginsInstanceOn, .pluginsStaticOn");
console.trace();
return tQuery._pluginsOn(object, dest)
}
// make it pluginable
tQuery.pluginsOn(tQuery, tQuery);
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
tQuery.mixinAttributes = function(dstObject, properties){
// mixin the new property
// FIXME the inheritance should work now... not sure
dstObject.prototype._attrProps = tQuery.extend(dstObject.prototype._attrProps, properties);
dstObject.prototype.attr = function(name, value){
// handle parameters
if( name instanceof Object && value === undefined ){
Object.keys(name).forEach(function(key){
this.attr(key, name[key]);
}.bind(this));
}else if( typeof(name) === 'string' ){
console.assert( Object.keys(this._attrProps).indexOf(name) !== -1, 'invalid property name:'+name);
}else console.assert(false, 'invalid parameter');
// handle setter
if( value !== undefined ){
var convertFn = this._attrProps[name];
value = convertFn(value);
this.each(function(element){
element[name] = value;
})
return this;
}
// handle getter
if( this.length === 0 ) return undefined
var element = this.get(0);
return element[name];
};
// add shortcuts
Object.keys(properties).forEach(function(name){
dstObject.prototype[name] = function(value){
return this.attr(name, value);
};
}.bind(this));
};
////////////////////////////////////////////////////////////////////////////
// put some helpers //
////////////////////////////////////////////////////////////////////////////
Flow control - from github.com/jeromeetienne/gowiththeflow.js
tQuery.Flow = function(){
var self, stack = [], timerId = setTimeout(function(){ timerId = null; self._next(); }, 0);
return self = {
destroy : function(){ timerId && clearTimeout(timerId); },
par : function(callback, isSeq){
if(isSeq || !(stack[stack.length-1] instanceof Array)) stack.push([]);
stack[stack.length-1].push(callback);
return self;
},seq : function(callback){ return self.par(callback, true); },
_next : function(err, result){
var errors = [], results = [], callbacks = stack.shift() || [], nbReturn = callbacks.length, isSeq = nbReturn == 1;
callbacks && callbacks.forEach(function(fct, index){
fct(function(error, result){
errors[index] = error;
results[index] = result;
if(--nbReturn == 0) self._next(isSeq?errors[0]:errors, isSeq?results[0]:results)
}, err, result)
})
}
}
};
microevents.js - github.com/jeromeetienne/microevent.js
tQuery.MicroeventMixin = function(destObj){
var bind = function(event, fct){
if(this._events === undefined) this._events = {};
this._events[event] = this._events[event] || [];
this._events[event].push(fct);
return fct;
};
var unbind = function(event, fct){
if(this._events === undefined) this._events = {};
if( event in this._events === false ) return;
this._events[event].splice(this._events[event].indexOf(fct), 1);
};
var trigger = function(event /* , args... */){
if(this._events === undefined) this._events = {};
if( this._events[event] === undefined ) return;
var tmpArray = this._events[event].slice();
for(var i = 0; i < tmpArray.length; i++){
tmpArray[i].apply(this, Array.prototype.slice.call(arguments, 1))
}
};
// backward compatibility
destObj.bind = bind;
destObj.unbind = unbind;
destObj.trigger = trigger;
destObj.addEventListener = function(event, fct){
destObj.bind(event, fct)
return this; // for chained API
}
destObj.removeEventListener = function(event, fct){
destObj.unbind(event, fct)
return this; // for chained API
}
destObj.dispatchEvent = function(event){
destObj.trigger(event)
return this;
}
};
tQuery.convert = {};
Convert the value into a THREE.Color object
returns: {THREE.Color} the resulting color
tQuery.convert.toThreeColor = function(value){
if( arguments.length === 1 && typeof(value) === 'number'){
return new THREE.Color(value);
}else if( arguments.length === 1 && value instanceof THREE.Color ){
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.toNumber = function(value){
if( arguments.length === 1 && typeof(value) === 'number'){
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.toNumberZeroToOne = function(value){
if( arguments.length === 1 && typeof(value) === 'number'){
value = Math.min(value, 1.0);
value = Math.max(value, 0);
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.toInteger = function(value){
if( arguments.length === 1 && typeof(value) === 'number'){
value = Math.floor(value);
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.identity = function(value){
return value;
};
tQuery.convert.toBool = function(value){
if( arguments.length === 1 && typeof(value) === 'boolean'){
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.toString = function(value){
if( arguments.length === 1 && typeof(value) === 'string'){
return value;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
tQuery.convert.toTexture = function(value){
if( arguments.length === 1 && value instanceof THREE.Texture ){
return value;
}else if( arguments.length === 1 && typeof(value) === 'string' ){
return THREE.ImageUtils.loadTexture(value);
}else if( arguments.length === 1 && (value instanceof Image || value instanceof HTMLCanvasElement) ){
var texture = new THREE.Texture( value );
texture.needsUpdate = true;
return texture;
}else{
console.assert(false, "invalid parameter");
}
return undefined; // never reached - just to workaround linter complaint
};
implementation of the tQuery.Node
@class base class for tQuery objects
parameter: {Object} object an instance or an array of instance
tQuery.Node = function(object)
{
// handle parameters
if( object instanceof Array ) this._lists = object;
else if( !object ) this._lists = [];
else this._lists = [object];
this.length = this._lists.length;
};
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
Retrieve the elements matched by the tQuery object
parameter: {Function} callback the function to notify. function(element){ }.
loop interrupted if it returns false
returns: {Boolean} return true if completed, false if interrupted
tQuery.Node.prototype.get = function(idx)
{
if( idx === undefined ) return this._lists;
// sanity check - it MUST be defined
console.assert(this._lists[idx], "element not defined");
return this._lists[idx];
};
loop over element
parameter: {Function} callback the function to notify. function(element){ }.
loop interrupted if it returns false
returns: {Boolean} return true if completed, false if interrupted
tQuery.Node.prototype.each = function(callback)
{
return tQuery.each(this._lists, callback)
};
getter/setter of the back pointer
parameter: {Object} back the value to return when .back() is called. optional
tQuery.Node.prototype.back = function(value)
{
if( value === undefined ) return this._back;
this._back = value;
return this;
};
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
same as .data() in jquery
tQuery.Node.prototype.data = function(key, value)
{
// handle the setter case
if( value ){
this.each(function(element){
tQuery.data(element, key, value);
});
return this; // for chained API
}
// return the value of the first element
if( this.length > 0 ) return tQuery.data(this.get(0), key)
// return undegined if the list is empty
console.assert(this.length === 0);
return undefined
}
same as .data() in jquery
tQuery.Node.prototype.removeData = function(key)
{
this.each(function(element){
tQuery.removeData(element, key);
});
return this; // for chained API
}
Handle object3D
@class include THREE.Object3D
parameter: {} object
parameter: {THREE.Object3D} rootnode
returns: {tQuery.*} the tQuery object created
tQuery.Object3D = function(object, root)
{
// handle the case of selector
if( typeof object === "string" ){
object = tQuery.Object3D._select(object, root);
}
// call parent ctor
tQuery.Object3D.parent.constructor.call(this, object)
// sanity check - all items MUST be THREE.Object3D
this._lists.forEach(function(item){ console.assert(item instanceof THREE.Object3D); });
};
inherit from tQuery.Node
tQuery.inherit(tQuery.Object3D, tQuery.Node);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.Object3D);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.Object3D, {
eulerOrder : tQuery.convert.toString,
doubleSided : tQuery.convert.toBool,
flipSided : tQuery.convert.toBool,
rotationAutoUpdate : tQuery.convert.toBool,
matrixAutoUpdate : tQuery.convert.toBool,
matrixWorldNeedsUpdate : tQuery.convert.toBool,
useQuaternion : tQuery.convert.toBool,
visible : tQuery.convert.toBool,
receiveShadow : tQuery.convert.toBool,
castShadow : tQuery.convert.toBool
});
Traverse the hierarchy of Object3D.
returns: {tQuery.Object3D} return the tQuery.Object3D itself
tQuery.Object3D.prototype.traverseHierarchy = function(callback){
this.each(function(object3d){
THREE.SceneUtils.traverseHierarchy(object3d, function(object3d){
callback(object3d);
});
});
return this; // for chained API
};
////////////////////////////////////////////////////////////////////////////
// geometry and material //
////////////////////////////////////////////////////////////////////////////
get geometry.
TODO this should be move in tQuery.Mesh
returns: {tQuery.Geometry} return the geometries from the tQuery.Object3D
tQuery.Object3D.prototype.geometry = function(value){
var geometries = [];
this.each(function(object3d){
geometries.push(object3d.geometry)
});
return new tQuery.Geometry(geometries).back(this);
};
get material.
TODO this should be move in tQuery.Mesh
returns: {tQuery.Material} return the materials from the tQuery.Object3D
tQuery.Object3D.prototype.material = function(){
var materials = [];
this.each(function(object3d){
materials.push(object3d.material)
});
return new tQuery.Material(materials);
};
Clone a Object3D
tQuery.Object3D.prototype.clone = function(){
var clones = [];
this._lists.forEach(function(object3d){
var clone = THREE.SceneUtils.cloneObject(object3d)
clones.push(clone);
})
return tQuery(clones)
}
////////////////////////////////////////////////////////////////////////////
// addTo/removeFrom tQuery.World/tQuery.Object3d //
////////////////////////////////////////////////////////////////////////////
add all matched elements to a world
parameter: {tQuery.World or tQuery.Object3D} target object to which add it
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.addTo = function(target)
{
console.assert( target instanceof tQuery.World || target instanceof tQuery.Object3D || target instanceof THREE.Object3D )
this.each(function(object3d){
target.add(object3d)
}.bind(this));
return this;
}
remove all matched elements from a world
parameter: {tQuery.World or tQuery.Object3D} target object to which add it
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.removeFrom = function(target)
{
console.assert( target instanceof tQuery.World || target instanceof tQuery.Object3D )
this.each(function(object3d){
target.remove(object3d)
}.bind(this));
return this;
}
////////////////////////////////////////////////////////////////////////////
// addTo/removeFrom tQuery.World/tQuery.Object3d //
////////////////////////////////////////////////////////////////////////////
add all matched elements to a world
parameter: {tQuery.Object3D} target object to which add it
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.add = function(object3d)
{
if( object3d instanceof tQuery.Object3D ){
this.each(function(object1){
object3d.each(function(object2){
object1.add(object2);
})
}.bind(this));
}else if( object3d instanceof THREE.Object3D ){
this.each(function(object1){
object1.add(object3d);
});
}else console.assert(false, "invalid parameter");
return this;
}
remove all matched elements from a world
parameter: {tQuery.Object3D} object3d the object to add in this object
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.remove = function(tqObject3d)
{
console.assert( tqObject3d instanceof tQuery.Object3D )
this.each(function(object1){
tqObject3d.each(function(object2){
object1.remove(object2);
})
}.bind(this));
return this;
}
////////////////////////////////////////////////////////////////////////////
// Handle dom attribute //
////////////////////////////////////////////////////////////////////////////
Getter/Setter for the id of the matched elements
tQuery.Object3D.prototype.id = function(value)
{
// sanity check
console.assert(this.length <= 1, "tQuery.Object3D.id used on multi-elements" );
if( value !== undefined ){
if( this.length > 0 ){
var object3d = this.get(0);
object3d._tqId = value;
}
return this;
}else{
if( this.length > 0 ){
var object3d = this.get(0);
return object3d._tqId;
}
return undefined;
}
};
add a class to all matched elements
parameter: {string} className the name of the class to add
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.addClass = function(className){
this.each(function(tObject3d){
// init ._tqClasses if needed
tObject3d._tqClasses = tObject3d._tqClasses || '';
if( tQuery.Object3D._hasClassOne(tObject3d, className) ) return;
tObject3d._tqClasses += ' '+className;
}.bind(this));
return this;
};
remove a class to all matched elements
parameter: {string} className the name of the class to remove
returns: {tQuery.Object3D} chained API
tQuery.Object3D.prototype.removeClass = function(className){
this.each(function(tObject3d){
tQuery.Object3D._removeClassOne(tObject3d, className);
}.bind(this));
return this; // for chained api
};
return true if any of the matched elements has this class
parameter: {string} className the name of the class
returns: {tQuery.Object3D} true if any of the matched elements has this class, false overwise
tQuery.Object3D.prototype.hasClass = function(className){
var completed = this.each(function(object3d){
// init ._tqClasses if needed
object3d._tqClasses = object3d._tqClasses || '';
var hasClass = tQuery.Object3D._hasClassOne(object3d, className);
return hasClass ? false : true;
}.bind(this));
return completed ? false : true;
};
tQuery.Object3D._hasClassOne = function(object3d, className){
if( object3d._tqClasses === undefined ) return false;
var classes = object3d._tqClasses;
var re = new RegExp('(^| |\t)+('+className+')(| |\t)+');
return classes.match(re) ? true : false;
};
tQuery.Object3D._removeClassOne = function(object3d, className){
if( object3d._tqClasses === undefined ) return;
var re = new RegExp('(^| |\t)('+className+')(/);}).map(function(value){ return value.replace(/Geometry/);}).map(function(value){ return value.replace(/Light
Handle geometry. It inherit from tQuery.Node
@class handle THREE.Geometry. It inherit from {gray tQuery.Node}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.Geometry} object an instance or an array of instance
tQuery.Geometry = function(object)
{
// call parent
tQuery.Geometry.parent.constructor.call(this, object)
// sanity check - all items MUST be THREE.Geometry
this._lists.forEach(function(item){ console.assert(item instanceof THREE.Geometry); });
};
inherit from tQuery.Node
tQuery.inherit(tQuery.Geometry, tQuery.Node);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.Geometry);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.Geometry, {
hasTangents : tQuery.convert.toBool,
dynamic : tQuery.convert.toBool
});
Handle material
@class include THREE.Material. It inherit from {gray tQuery.Node}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.Material} object an instance or array of instance
tQuery.Material = function(object)
{
// call parent
tQuery.Material.parent.constructor.call(this, object)
// sanity check - all items MUST be THREE.Material
this._lists.forEach(function(item){ console.assert(item instanceof THREE.Material); });
};
inherit from tQuery.Node
tQuery.inherit(tQuery.Material, tQuery.Node);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.Material);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.Material, {
opacity : tQuery.convert.toNumber,
transparent : tQuery.convert.toBool
});
Handle light
@class include THREE.Light. It inherit from {gray tQuery.Node}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.Light} object an instance or array of instance
tQuery.Light = function(elements)
{
// call parent ctor
tQuery.Light.parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Light
this._lists.forEach(function(item){ console.assert(item instanceof THREE.Light); });
};
inherit from tQuery.Node
- TODO this should inherit from tQuery.Object3D but but in inheritance
tQuery.inherit(tQuery.Light, tQuery.Object3D);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.Light);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.Light, {
color : tQuery.convert.toThreeColor
});
Handle mesh
@class include THREE.Mesh. It inherit from {gray tQuery.Node}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.Mesh} object an instance or array of instance
tQuery.Mesh = function(elements)
{
// call parent ctor
var parent = tQuery.Mesh.parent;
parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Mesh
this._lists.forEach(function(item){ console.assert(item instanceof THREE.Mesh); });
};
inherit from tQuery.Object3D
tQuery.inherit(tQuery.Mesh, tQuery.Object3D);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.Mesh);
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
TODO to remove. this function is crap
tQuery.Mesh.prototype.material = function(value){
var parent = tQuery.Mesh.parent;
// handle the getter case
if( value == undefined ) return parent.material.call(this);
// handle the setter case
this.each(function(tMesh){
tMesh.material = value;
});
return this; // for the chained API
}
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
Handle world (aka scene+camera+renderer)
@class youpla
parameter: {THREE.Material} object an instance or an array of instance
tQuery.World = function(opts)
{
// handle parameters
opts = opts || {};
opts = tQuery.extend(opts, {
renderW : window.innerWidth,
renderH : window.innerHeight,
webGLNeeded : true,
autoRendering : true,
scene : null,
camera : null,
renderer : null
});
this._opts = opts;
// update default world.
// - TODO no sanity check ?
// - not clear what to do with this...
// - tQuery.world is the user world. like the camera controls
console.assert( !tQuery.word );
tQuery.world = this;
this._autoRendering = true;
// create a scene
this._scene = opts.scene ||(new THREE.Scene());
// create a camera in the scene
if( !opts.camera ){
this._camera = new THREE.PerspectiveCamera(35, opts.renderW / opts.renderH, 0.01, 10000 );
this._camera.position.set(0, 0, 3);
this._scene.add(this._camera);
}else{
this._camera = opts.camera;
}
// create the loop
this._loop = new tQuery.Loop();
// hook the render function in this._loop
this._loop.hookOnRender(this._loopCb = function(){
this.render();
}.bind(this));
// create a renderer
if( opts.renderer ){
this._renderer = opts.renderer;
}else if( tQuery.World.hasWebGL() ){
this._renderer = new THREE.WebGLRenderer({
antialias : true, // to get smoother output
preserveDrawingBuffer : true // to allow screenshot
});
}else if( !opts.webGLNeeded ){
this._renderer = new THREE.CanvasRenderer();
}else{
this._addGetWebGLMessage();
throw new Error("WebGL required and not available")
}
this._renderer.setClearColorHex( 0xBBBBBB, 1 );
this._renderer.setSize( opts.renderW, opts.renderH );
};
// make it pluginable
tQuery.pluginsInstanceOn(tQuery.World);
// make it eventable
tQuery.MicroeventMixin(tQuery.World.prototype)
tQuery.World.prototype.destroy = function(){
// microevent.js notification
this.trigger('destroy');
// unhook the render function in this._loop
this._loop.unhookOnRender(this._
true if webgl is available, false otherwise
tQuery.World._hasWebGL = (function(){
// test from Detector.js
try{
return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' );
} catch( e ){
return false;
}
})();
returns: {Boolean} true if webgl is available, false otherwise
tQuery.World.hasWebGL = function(){
return tQuery.World._hasWebGL;
};
tQuery.World.prototype._addGetWebGLMessage = function(parent)
{
parent = parent || document.body;
// message directly taken from Detector.js
var domElement = document.createElement( 'div' );
domElement.style.fontFamily = 'monospace';
domElement.style.fontSize = '13px';
domElement.style.textAlign = 'center';
domElement.style.background = '#eee';
domElement.style.color = '#000';
domElement.style.padding = '1em';
domElement.style.width = '475px';
domElement.style.margin = '5em auto 0';
domElement.innerHTML = window.WebGLRenderingContext ? [
'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>.<br />',
'Find out how to get it <a href="http://get.webgl.org/">here</a>.'
].join( '\n' ) : [
'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>.<br/>',
'Find out how to get it <a href="http://get.webgl.org/">here</a>.'
].join( '\n' );
parent.appendChild(domElement);
}
////////////////////////////////////////////////////////////////////////////
// add/remove object3D //
////////////////////////////////////////////////////////////////////////////
tQuery.World.prototype.setCameraControls = function(control){
if( this.hasCameraControls() ) this.removeCameraControls();
this._cameraControls = control;
return this; // for chained API
};
tQuery.World.prototype.removeCameraControls = function(){
if( this.hasCameraControls() === false ) return this;
this._cameraControls = undefined;
return this; // for chained API
};
tQuery.World.prototype.getCameraControls = function(){
return this._cameraControls;
};
tQuery.World.prototype.hasCameraControls = function(){
return this._cameraControls !== undefined ? true : false;
};
////////////////////////////////////////////////////////////////////////////
// add/remove object3D //
////////////////////////////////////////////////////////////////////////////
add an object to the scene
parameter: {tQuery.Object3D} object3D to add to the scene (THREE.Object3D is accepted)
tQuery.World.prototype.add = function(object3d)
{
if( object3d instanceof tQuery.Object3D ){
object3d.each(function(object3d){
this._scene.add(object3d)
}.bind(this));
}else if( object3d instanceof THREE.Object3D ){
this._scene.add(object3d)
}else console.assert(false, "invalid type");
// for chained API
return this;
}
remove an object to the scene
parameter: {tQuery.Object3D} object3D to add to the scene (THREE.Object3D is accepted)
tQuery.World.prototype.remove = function(object3d)
{
if( object3d instanceof tQuery.Object3D ){
object3d.each(function(object3d){
this._scene.remove(object3d)
}.bind(this));
}else if( object3d instanceof THREE.Object3D ){
this._scene.remove(object3d)
}else console.assert(false, "invalid type");
// for chained API
return this;
}
tQuery.World.prototype.appendTo = function(domElement)
{
domElement.appendChild(this._renderer.domElement)
// for chained API
return this;
}
Start the loop
tQuery.World.prototype.start = function(){
this._loop.start();
return this; // for chained API
}
Stop the loop
tQuery.World.prototype.stop = function(){
this._loop.stop();
return this; // for chained API
}
tQuery.World.prototype.loop = function(){ return this._loop; }
tQuery.World.prototype.tRenderer= function(){ return this._renderer; }
tQuery.World.prototype.tCamera = function(){ return this._camera; }
tQuery.World.prototype.tScene = function(){ return this._scene; }
// backward compatible functions to remove
tQuery.World.prototype.renderer = function(){ console.trace();console.warn("world.renderer() is ovbslete, use .tRenderer() instead");
return this._renderer; }
tQuery.World.prototype.camera = function(){ console.trace();console.warn("world.camera() is obsolete, use .tCamerar() instead");
return this._camera; }
tQuery.World.prototype.scene = function(){ console.trace();console.warn("world.scene() is obsolete, use .tScene() instead");
return this._scene; }
tQuery.World.prototype.get = function(){ return this._scene; }
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
tQuery.World.prototype.autoRendering = function(value){
if(value === undefined) return this._autoRendering;
this._autoRendering = value;
return this;
}
tQuery.World.prototype.render = function()
{
// update the cameraControl
if( this.hasCameraControls() ) this._cameraControls.update();
// render the scene
if( this._autoRendering ) this._renderer.render( this._scene, this._camera );
}
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
Handle the rendering loop
@class This class handle the rendering loop
parameter: {THREE.World} world the world to display (optional)
tQuery.Loop = function()
{
// internally if world present do that
this._hooks = [];
this._lastTime = null;
};
// make it pluginable
tQuery.pluginsInstanceOn(tQuery.Loop);
destructor
tQuery.Loop.prototype.destroy = function()
{
this.stop();
}
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
start looping
returns: {tQuery.Loop} chained API
tQuery.Loop.prototype.start = function()
{
if( this._timerId ) this.stop();
this._timerId = requestAnimationFrame( this._onAnimationFrame.bind(this) );
// for chained API
return this;
}
stop looping
returns: {tQuery.Loop} chained API
tQuery.Loop.prototype.stop = function()
{
cancelAnimationFrame(this._timerId);
this._timerId = null;
// for chained API
return this;
}
tQuery.Loop.prototype._onAnimationFrame = function(time)
{
// loop on request animation loop
// - it has to be at the begining of the function
// - see details at http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
this._timerId = requestAnimationFrame( this._onAnimationFrame.bind(this) );
// update time values
var now = time/1000;
if( !this._lastTime ) this._lastTime = now - 1/60;
var delta = now - this._lastTime;
this._lastTime = now;
// run all the hooks - from lower priority to higher - in order of registration
for(var priority = 0; priority <= this._hooks.length; priority++){
if( this._hooks[priority] === undefined ) continue;
var callbacks = this._hooks[priority].slice(0)
for(var i = 0; i < callbacks.length; i++){
callbacks[i](delta, now);
}
}
}
////////////////////////////////////////////////////////////////////////////
// Handle the hooks //
////////////////////////////////////////////////////////////////////////////
tQuery.Loop.prototype.PRE_RENDER = 20;
tQuery.Loop.prototype.ON_RENDER = 50;
tQuery.Loop.prototype.POST_RENDER = 80;
hook a callback at a given priority
parameter: {Number} priority for this callback
parameter: {Function} callback the function which will be called function(time){}
returns: {Function} the callback function. usefull for this._callback = loop.hook(this._callback.bind(this))
and later loop.unhook(this._
tQuery.Loop.prototype.hook = function(priority, callback)
{
// handle parameters
if( typeof priority === 'function' ){
callback = priority;
priority = this.PRE_RENDER;
}
this._hooks[priority] = this._hooks[priority] || [];
console.assert(this._hooks[priority].indexOf(callback) === -1)
this._hooks[priority].push(callback);
return callback;
}
unhook a callback at a given priority
parameter: {Number} priority for this callback
parameter: {Function} callback the function which will be called function(time){}
returns: {tQuery.Loop} chained API
tQuery.Loop.prototype.unhook = function(priority, callback)
{
// handle parameters
if( typeof priority === 'function' ){
callback = priority;
priority = this.PRE_RENDER;
}
var index = this._hooks[priority].indexOf(callback);
console.assert(index !== -1);
this._hooks[priority].splice(index, 1);
this._hooks[priority].length === 0 && delete this._hooks[priority]
// for chained API
return this;
}
// bunch of shortcut
// - TODO should it be in a plugin ?
tQuery.Loop.prototype.hookPreRender = function(callback){ return this.hook(this.PRE_RENDER, callback); };
tQuery.Loop.prototype.hookOnRender = function(callback){ return this.hook(this.ON_RENDER, callback); };
tQuery.Loop.prototype.hookPostRender = function(callback){ return this.hook(this.POST_RENDER, callback); };
tQuery.Loop.prototype.unhookPreRender = function(callback){ return this.unhook(this.PRE_RENDER, callback); };
tQuery.Loop.prototype.unhookOnRender = function(callback){ return this.unhook(this.ON_RENDER, callback); };
tQuery.Loop.prototype.unhookPostRender = function(callback){ return this.unhook(this.POST_RENDER, callback); };
@fileOverview plugins for tQuery.core to help creation of object
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
Create tQuery.World
tQuery.register('createWorld', function(opts){
return new tQuery.World(opts);
});
Create tQuery.World
tQuery.register('createObject3D', function(){
var object3d = new THREE.Object3D();
return tQuery(object3d);
});
Create tQuery.loop
parameter: {tQuery.World} world the world to display (optional)
@function
tQuery.register('createLoop', function(world){
return new tQuery.Loop(world);
});
tQuery.register('createDirectionalLight', function(){
var tLight = new THREE.DirectionalLight();
return new tQuery.DirectionalLight([tLight]);
});
tQuery.register('createSpotLight', function(){
var tLight = new THREE.SpotLight();
return new tQuery.SpotLight([tLight]);
});
tQuery.register('createPointLight', function(){
var tLight = new THREE.PointLight();
return new tQuery.PointLight([tLight]);
});
tQuery.register('createAmbientLight', function(){
var tLight = new THREE.AmbientLight();
return new tQuery.AmbientLight([tLight]);
});
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
contains the default material to use when create tQuery.Object3D
@fieldOf tQuery
@name defaultObject3DMaterial
tQuery.register('defaultObject3DMaterial', new THREE.MeshNormalMaterial());
tQuery.Geometry.prototype.toMesh = function(material){
var meshes = [];
this.each(function(tGeometry){
// handle paramters
material = material || tQuery.defaultObject3DMaterial;
// create the THREE.Mesh
var mesh = new THREE.Mesh(tGeometry, material)
// return it
meshes.push(mesh);
});
return new tQuery.Mesh(meshes);
};
Create a cube
returns: {tQuery.Object3D} a tQuery.Object3D containing it
tQuery.register('createCube', function(){
var ctor = THREE.CubeGeometry;
var dflGeometry = [1, 1, 1];
return this._createMesh(ctor, dflGeometry, arguments)
});
tQuery.register('createTorus', function(){
var ctor = THREE.TorusGeometry;
var dflGeometry = [0.5-0.15, 0.15];
return this._createMesh(ctor, dflGeometry, arguments)
});
tQuery.register('createVector3', function(){
return new THREE.Vector3();
});
tQuery.register('createSphere', function(){
var ctor = THREE.SphereGeometry;
var dflGeometry = [0.5, 32, 16];
return this._createMesh(ctor, dflGeometry, arguments)
});
tQuery.register('createPlane', function(){
var ctor = THREE.PlaneGeometry;
var dflGeometry = [1, 1, 16, 16];
return this._createMesh(ctor, dflGeometry, arguments)
});
tQuery.register('createCylinder', function(){
var ctor = THREE.CylinderGeometry;
var dflGeometry = [0.5, 0.5, 1, 16, 4];
return this._createMesh(ctor, dflGeometry, arguments)
});
tQuery.register('_createMesh', function(ctor, dflGeometry, args)
{
// convert args to array if it is instanceof Arguments
// FIXME if( args instanceof Arguments )
args = Array.prototype.slice.call( args );
// init the material
var material = tQuery.defaultObject3DMaterial;
// if the last arguments is a material, use it
if( args.length && args[args.length-1] instanceof THREE.Material ){
material = args.pop();
}
// ugly trick to get .apply() to work
var createFn = function(ctor, a0, a1, a2, a3, a4, a5, a6, a7){
console.assert(arguments.length <= 9);
//console.log("createFn", arguments)
return new ctor(a0,a1,a2,a3,a4,a5,a6,a7);
}
if( args.length === 0 ) args = dflGeometry.slice();
args.unshift(ctor);
var geometry = createFn.apply(this, args);
// set the geometry.dynamic by default
geometry.dynamic= true;
// create the THREE.Mesh
var mesh = new THREE.Mesh(geometry, material)
// return it
return tQuery(mesh);
});
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
tQuery.register('createAxis', function(){
var axis = new THREE.AxisHelper();
axis.scale.multiplyScalar(1/100);
return tQuery(axis);
});
Handle ambient light
@class include THREE.AmbientLight. It inherit from {gray tQuery.Light}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.AmbientLight} element an instance or array of instance
tQuery.AmbientLight = function(elements)
{
// call parent ctor
tQuery.AmbientLight.parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Light
this._lists.forEach(function(item){ console.assert(item instanceof THREE.AmbientLight); });
};
inherit from tQuery.Node
tQuery.inherit(tQuery.AmbientLight, tQuery.Light);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.AmbientLight);
Handle directional light
@class include THREE.DirectionalLight. It inherit from {gray tQuery.Light}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.DirectionalLight} element an instance or array of instance
tQuery.DirectionalLight = function(elements)
{
// call parent ctor
tQuery.DirectionalLight.parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Light
this._lists.forEach(function(item){ console.assert(item instanceof THREE.DirectionalLight); });
};
inherit from tQuery.Light
tQuery.inherit(tQuery.DirectionalLight, tQuery.Light);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.DirectionalLight);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.DirectionalLight, {
intensity : tQuery.convert.toNumber,
distance : tQuery.convert.toNumber,
shadowDarkness : tQuery.convert.toNumberZeroToOne,
shadowBias : tQuery.convert.toNumber,
shadowMapWidth : tQuery.convert.toInteger,
shadowMapHeight : tQuery.convert.toInteger,
shadowCameraRight : tQuery.convert.toNumber,
shadowCameraLeft : tQuery.convert.toNumber,
shadowCameraTop : tQuery.convert.toNumber,
shadowCameraBottom : tQuery.convert.toNumber,
shadowCameraVisible : tQuery.convert.toBool,
shadowCameraNear : tQuery.convert.toNumber,
shadowCameraFar : tQuery.convert.toNumber
});
Handle directional light
@class include THREE.PointLight. It inherit from {gray tQuery.Light}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.PointLight} element an instance or array of instance
tQuery.PointLight = function(elements)
{
// call parent ctor
tQuery.PointLight.parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Light
this._lists.forEach(function(item){ console.assert(item instanceof THREE.PointLight); });
};
inherit from tQuery.Light
tQuery.inherit(tQuery.PointLight, tQuery.Light);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.PointLight);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.PointLight, {
intensity : tQuery.convert.toNumber,
distance : tQuery.convert.toNumber
});
Handle directional light
@class include THREE.SpotLight. It inherit from {gray tQuery.Light}
@borrows tQuery.Node#get as this.get
@borrows tQuery.Node#each as this.each
@borrows tQuery.Node#back as this.back
parameter: {THREE.SpotLight} element an instance or array of instance
tQuery.SpotLight = function(elements)
{
// call parent ctor
tQuery.SpotLight.parent.constructor.call(this, elements)
// sanity check - all items MUST be THREE.Light
this._lists.forEach(function(item){ console.assert(item instanceof THREE.SpotLight); });
};
inherit from tQuery.Light
tQuery.inherit(tQuery.SpotLight, tQuery.Light);
Make it pluginable
tQuery.pluginsInstanceOn(tQuery.SpotLight);
define all acceptable attributes for this class
tQuery.mixinAttributes(tQuery.SpotLight, {
intensity : tQuery.convert.toNumber,
distance : tQuery.convert.toNumber,
shadowDarkness : tQuery.convert.toNumberZeroToOne,
shadowBias : tQuery.convert.toNumber,
shadowMapWidth : tQuery.convert.toInteger,
shadowMapHeight : tQuery.convert.toInteger,
shadowCameraRight : tQuery.convert.toNumber,
shadowCameraLeft : tQuery.convert.toNumber,
shadowCameraTop : tQuery.convert.toNumber,
shadowCameraBottom : tQuery.convert.toNumber,
shadowCameraVisible : tQuery.convert.toBool
});
@fileOverview Plugins for tQuery.Geometry: tool box to play with geometry
(function(){ // TODO why is there a closure here ?
////////////////////////////////////////////////////////////////////////////
// Size functions //
////////////////////////////////////////////////////////////////////////////
tQuery.Geometry.register('computeAll', function(){
this.each(function(tGeometry){
tGeometry.computeBoundingBox();
tGeometry.computeCentroids();
tGeometry.computeFaceNormals();
tGeometry.computeVertexNormals();
//tGeometry.computeTangents();
});
// return this, to get chained API
return this;
});
zoom a geometry
@name zoom
@methodOf tQuery.Geometry
tQuery.Geometry.register('scaleBy', function(vector3){
// handle parameters
if( typeof vector3 === "number" && arguments.length === 1 ){
vector3 = new THREE.Vector3(vector3, vector3, vector3);
}else if( typeof vector3 === "number" && arguments.length === 3 ){
vector3 = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(vector3 instanceof THREE.Vector3, "Geometry.vector3 parameter error");
// change all geometry.vertices
this.each(function(geometry){
for(var i = 0; i < geometry.vertices.length; i++) {
var vertex = geometry.vertices[i];
vertex.multiplySelf(vector3);
}
// mark the vertices as dirty
geometry.verticesNeedUpdate = true;
geometry.computeBoundingBox();
})
// return this, to get chained API
return this;
});
tQuery.Geometry.register('size', function(){
// only on zero-or-one element
console.assert(this.length <= 1)
// if no element, return undefined
if( this.length === 0 ) return undefined
// else measure the size of the element
var geometry = this.get(0);
// compute middle
var size= new THREE.Vector3()
size.x = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
size.y = geometry.boundingBox.max.y - geometry.boundingBox.min.y;
size.z = geometry.boundingBox.max.z - geometry.boundingBox.min.z;
// return the just computed middle
return size;
});
tQuery.Geometry.register('normalize', function(){
// change all geometry.vertices
this.each(function(geometry){
var node = tQuery(geometry);
var size = node.size();
if( size.x >= size.y && size.x >= size.z ){
node.zoom(1/size.x);
}else if( size.y >= size.x && size.y >= size.z ){
node.zoom(1/size.y);
}else{
node.zoom(1/size.z);
}
});
// return this, to get chained API
return this;
});
////////////////////////////////////////////////////////////////////////////
// //
////////////////////////////////////////////////////////////////////////////
tQuery.Geometry.register('middlePoint', function(){
// only on zero-or-one element
console.assert(this.length <= 1)
// if no element, return undegined
if( this.length === 0 ) return undefined
// else measure the size of the element
var geometry = this.get(0);
// compute middle
var middle = new THREE.Vector3()
middle.x = ( geometry.boundingBox.max.x + geometry.boundingBox.min.x ) / 2;
middle.y = ( geometry.boundingBox.max.y + geometry.boundingBox.min.y ) / 2;
middle.z = ( geometry.boundingBox.max.z + geometry.boundingBox.min.z ) / 2;
// return the just computed middle
return middle;
});
////////////////////////////////////////////////////////////////////////////
// move functions //
////////////////////////////////////////////////////////////////////////////
tQuery.Geometry.register('translate', function(delta){
// handle parameters
if( typeof delta === "number" && arguments.length === 3 ){
delta = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(delta instanceof THREE.Vector3, "Geometry.translate parameter error");
// change all geometry.vertices
this.each(function(geometry){
// change all geometry.vertices
for(var i = 0; i < geometry.vertices.length; i++) {
var vertex = geometry.vertices[i];
vertex.addSelf(delta);
}
// mark the vertices as dirty
geometry.verticesNeedUpdate = true;
geometry.computeBoundingBox();
})
// return this, to get chained API
return this;
});
tQuery.Geometry.register('rotate', function(angles, order){
// handle parameters
if( typeof angles === "number" && arguments.length === 3 ){
angles = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(angles instanceof THREE.Vector3, "Geometry.rotate parameter error");
// set default rotation order if needed
order = order || 'XYZ';
// compute transformation matrix
var matrix = new THREE.Matrix4();
matrix.setRotationFromEuler(angles, order);
// change all geometry.vertices
this.each(function(geometry){
// apply the matrix
geometry.applyMatrix( matrix );
// mark the vertices as dirty
geometry.verticesNeedUpdate = true;
geometry.computeBoundingBox();
});
// return this, to get chained API
return this;
});
tQuery.Geometry.register('center', function(noX, noY, noZ){
// change all geometry.vertices
this.each(function(tGeometry){
var geometry = tQuery(tGeometry);
// compute delta
var delta = geometry.middlePoint().negate();
if( noX ) delta.x = 0;
if( noY ) delta.y = 0;
if( noZ ) delta.z = 0;
return geometry.translate(delta)
});
// return this, to get chained API
return this;
});
Smooth the geometry using catmull-clark
parameter: {Number} subdivision the number of subdivision to do
tQuery.Geometry.register('smooth', function(subdivision){
// init the modifier
var modifier = new THREE.SubdivisionModifier( subdivision );
// apply it to each geometry
this.each(function(geometry){
// apply it
modifier.modify( geometry )
// mark the vertices as dirty
geometry.verticesNeedUpdate = true;
geometry.computeBoundingBox();
});
// return this, to get chained API
return this;
});
// some shortcuts
tQuery.Geometry.register('translateX' , function(delta){ return this.translate(delta, 0, 0); });
tQuery.Geometry.register('translateY' , function(delta){ return this.translate(0, delta, 0); });
tQuery.Geometry.register('translateZ' , function(delta){ return this.translate(0, 0, delta); });
tQuery.Geometry.register('rotateX' , function(angle){ return this.rotate(angle, 0, 0); });
tQuery.Geometry.register('rotateY' , function(angle){ return this.rotate(0, angle, 0); });
tQuery.Geometry.register('rotateZ' , function(angle){ return this.rotate(0, 0, angle); });
tQuery.Geometry.register('scaleXBy' , function(ratio){ return this.scaleBy(ratio, 1, 1); });
tQuery.Geometry.register('scaleYBy' , function(ratio){ return this.scaleBy(1, ratio, 1); });
tQuery.Geometry.register('scaleZBy' , function(ratio){ return this.scaleBy(1, 1, ratio); });
// backward compatibility
tQuery.Geometry.register('zoom' , function(value){return this.scaleBy(value); });
tQuery.Geometry.register('zoomX' , function(ratio){ return this.zoom(ratio, 1, 1); });
tQuery.Geometry.register('zoomY' , function(ratio){ return this.zoom(1, ratio, 1); });
tQuery.Geometry.register('zoomZ' , function(ratio){ return this.zoom(1, 1, ratio); });
})(); // closure function end
@fileOverview Plugins for tQuery.Object3D to play with .position/.rotation/.scale
(function(){ // TODO why is there a closure here ?
////////////////////////////////////////////////////////////////////////////
// set function //
////////////////////////////////////////////////////////////////////////////
tQuery.Object3D.register('scale', function(scale){
// handle parameters
if( typeof scale === "number" && arguments.length === 1 ){
scale = new THREE.Vector3(scale, scale, scale);
}else if( typeof scale === "number" && arguments.length === 3 ){
scale = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(scale instanceof THREE.Vector3, "Geometry.scale parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.scale.copy(scale);
});
// return this, to get chained API
return this;
});
tQuery.Object3D.register('position', function(vector3){
// handle parameters
if( typeof vector3 === "number" && arguments.length === 3 ){
vector3 = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(vector3 instanceof THREE.Vector3, "Object3D.position parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.position.copy(vector3);
})
// return this, to get chained API
return this;
});
tQuery.Object3D.register('rotation', function(vector3){
// handle parameters
if( typeof vector3 === "number" && arguments.length === 3 ){
vector3 = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(vector3 instanceof THREE.Vector3, "Object3D.rotation parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.rotation.copy(vector3);
})
// return this, to get chained API
return this;
});
////////////////////////////////////////////////////////////////////////////
// add function //
////////////////////////////////////////////////////////////////////////////
tQuery.Object3D.register('translate', function(delta){
// handle parameters
if( typeof delta === "number" && arguments.length === 3 ){
delta = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(delta instanceof THREE.Vector3, "Object3D.translate parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.position.addSelf(delta);
})
// return this, to get chained API
return this;
});
tQuery.Object3D.register('rotate', function(angles){
// handle parameters
if( typeof angles === "number" && arguments.length === 3 ){
angles = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(angles instanceof THREE.Vector3, "Object3D.rotate parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.rotation.addSelf(angles);
})
// return this, to get chained API
return this;
});
tQuery.Object3D.register('scaleBy', function(ratio){
// handle parameters
if( typeof ratio === "number" && arguments.length === 1 ){
ratio = new THREE.Vector3(ratio, ratio, ratio);
}else if( typeof ratio === "number" && arguments.length === 3 ){
ratio = new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
}
console.assert(ratio instanceof THREE.Vector3, "Object3D.rotate parameter error");
// do the operation on each node
this.each(function(object3d){
object3d.scale.multiplySelf(ratio);
})
// return this, to get chained API
return this;
});
// some shortcuts
tQuery.Object3D.register('translateX' , function(delta){ return this.translate(delta, 0, 0); });
tQuery.Object3D.register('translateY' , function(delta){ return this.translate(0, delta, 0); });
tQuery.Object3D.register('translateZ' , function(delta){ return this.translate(0, 0, delta); });
tQuery.Object3D.register('rotateX' , function(angle){ return this.rotate(angle, 0, 0); });
tQuery.Object3D.register('rotateY' , function(angle){ return this.rotate(0, angle, 0); });
tQuery.Object3D.register('rotateZ' , function(angle){ return this.rotate(0, 0, angle); });
tQuery.Object3D.register('scaleXBy' , function(ratio){ return this.scaleBy(ratio, 1, 1); });
tQuery.Object3D.register('scaleYBy' , function(ratio){ return this.scaleBy(1, ratio, 1); });
tQuery.Object3D.register('scaleZBy' , function(ratio){ return this.scaleBy(1, 1, ratio); });
// backward compatibility
tQuery.Object3D.register('zoom' , function(value){ return this.scaleBy(value); });
tQuery.Object3D.register('zoomX' , function(ratio){ return this.zoom(ratio, 1, 1); });
tQuery.Object3D.register('zoomY' , function(ratio){ return this.zoom(1, ratio, 1); });
tQuery.Object3D.register('zoomZ' , function(ratio){ return this.zoom(1, 1, ratio); });
})(); // closure function end
// backward compatibility only
tQuery.World.register('fullpage', function(){
console.log("world.fullpage() is obsolete. use world.boilerplate() instead.");
return this.boilerplate();
});
tQuery.World.register('boilerplate', function(opts){
// put renderer fullpage
var domElement = document.body;
domElement.style.margin = "0";
domElement.style.padding = "0";
domElement.style.overflow = 'hidden';
this.appendTo(domElement);
this._renderer.setSize( domElement.offsetWidth, domElement.offsetHeight );
// add the boilerplate
this.addBoilerplate(opts);
// for chained API
return this;
});
Define a page title
tQuery.World.register('pageTitle', function(element){
// handle parameters polymorphism
if( typeof(element) === 'string' ){
var element = document.querySelector(element);
}
// sanity check
console.assert( element instanceof HTMLElement);
// set element.style
element.style.position = "absolute";
element.style.width = "100%";
element.style.textAlign = "center";
element.style.fontWeight= "bolder";
element.style.fontColor = "white";
element.style.paddingTop= "0.5em";
element.style.fontFamily= "arial";
// for chained API
return this;
});
tQuery.World.register('addBoilerplate', function(opts){
var _this = this;
// sanity check - no boilerplate is already installed
console.assert( this.hasBoilerplate() !== true );
// handle parameters
opts = tQuery.extend(opts, {
stats : true,
cameraControls : true,
windowResize : true,
screenshot : true,
fullscreen : true
});
// get the context
var ctx = {};
// make tRenderer.domElement style "display: block" - by default it is inline-block
// - so it is affected by line-height and create a white line at the bottom
this.tRenderer().domElement.style.display = "block"
// create the context
tQuery.data(this, '_boilerplateCtx', ctx);
// get some variables
var tCamera = this.tCamera();
var tRenderer = this.tRenderer();
// add Stats.js - github.com/mrdoob/stats.js
if( opts.stats ){
ctx.stats = new Stats();
ctx.stats.domElement.style.position = 'absolute';
ctx.stats.domElement.style.bottom = '0px';
tRenderer.domElement.parentNode && tRenderer.domElement.parentNode.appendChild( ctx.stats.domElement );
ctx.loopStats = function(){
ctx.stats.update();
};
this.loop().hook(ctx.loopStats);
}
// create a camera contol
if( opts.cameraControls ){
ctx.cameraControls = new THREEx.DragPanControls(tCamera);
this.setCameraControls(ctx.cameraControls);
}
// transparently support window resize
if( opts.windowResize ){
ctx.windowResize = THREEx.WindowResize.bind(tRenderer, tCamera);
}
// allow 'p' to make screenshot
if( opts.screenshot ){
ctx.screenshot = THREEx.Screenshot.bindKey(tRenderer);
}
// allow 'f' to go fullscreen where this feature is supported
if( opts.fullscreen && THREEx.FullScreen.available() ){
ctx.fullscreen = THREEx.FullScreen.bindKey();
}
// bind 'destroy' event on tQuery.world
ctx._onDestroy = this.bind('destroy', function(){
if( this.hasBoilerplate() === false ) return;
this.removeBoilerplate();
});
// for chained API
return this;
});
tQuery.World.register('hasBoilerplate', function(){
// get the context
var ctx = tQuery.data(this, "_boilerplateCtx")
// return true if ctx if defined, false otherwise
return ctx === undefined ? false : true;
});
tQuery.World.register('removeBoilerplate', function(){
// get context
var ctx = tQuery.data(this, '_boilerplateCtx');
// if not present, return now
if( ctx === undefined ) return this;
// remove the context from this
tQuery.removeData(this, '_boilerplateCtx');
// unbind 'destroy' for tQuery.World
this.unbind('destroy', this._
@namespace
var THREEx = THREEx || {};
Update renderer and camera when the window is resized
parameter: {Object} renderer the renderer to update
parameter: {Object} Camera the camera to update
THREEx.WindowResize = function(renderer, camera){
var callback = function(){
// notify the renderer of the size change
renderer.setSize( window.innerWidth, window.innerHeight );
// update the camera
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
// bind the resize event
window.addEventListener('resize', callback, false);
// return .stop() the function to stop watching window resize
return {
Stop watching window resize
stop : function(){
window.removeEventListener('resize', callback);
}
};
}
THREEx.WindowResize.bind = function(renderer, camera){
return THREEx.WindowResize(renderer, camera);
}
@namespace
var THREEx = THREEx || {};
// TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri
// able to upload your screenshot without running servers
// forced closure
(function(){
Take a screenshot of a renderer
- require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
- TODO is it possible to check if this variable is set ? if so check it
and make advice in the console.log
- maybe with direct access to the gl context...
parameter: {Object} renderer to use
parameter: {String} mimetype of the output image. default to "image/png"
parameter: {String} dataUrl of the image
var toDataURL = function(renderer, mimetype)
{
mimetype = mimetype || "image/png";
var dataUrl = renderer.domElement.toDataURL(mimetype);
return dataUrl;
}
resize an image to another resolution while preserving aspect
parameter: {String} srcUrl the url of the image to resize
parameter: {Number} dstWidth the destination width of the image
parameter: {Number} dstHeight the destination height of the image
parameter: {Number} callback the callback to notify once completed with callback(newImageUrl)
var _aspectResize = function(srcUrl, dstW, dstH, callback){
// to compute the width/height while keeping aspect
var cpuScaleAspect = function(maxW, maxH, curW, curH){
var ratio = curH / curW;
if( curW >= maxW && ratio <= 1 ){
curW = maxW;
curH = maxW * ratio;
}else if(curH >= maxH){
curH = maxH;
curW = maxH / ratio;
}
return { width: curW, height: curH };
}
// callback once the image is loaded
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
var onLoad = __bind(function(){
// init the canvas
var canvas = document.createElement('canvas');
canvas.width = dstW; canvas.height = dstH;
var ctx = canvas.getContext('2d');
// TODO is this needed
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// scale the image while preserving the aspect
var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);
// actually draw the image on canvas
var offsetX = (canvas.width - scaled.width )/2;
var offsetY = (canvas.height - scaled.height)/2;
ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);
// dump the canvas to an URL
var mimetype = "image/png";
var newDataUrl = canvas.toDataURL(mimetype);
// notify the url to the caller
callback && callback(newDataUrl)
}, this);
// Create new Image object
var image = new Image();
image.onload = onLoad;
image.src = srcUrl;
}
// Super cooked function: THREEx.Screenshot.bindKey(renderer)
// and you are done to get screenshot on your demo
Bind a key to renderer screenshot
var bindKey = function(renderer, opts){
// handle parameters
opts = opts || {};
var charCode = opts.charCode || 'p'.charCodeAt(0);
var width = opts.width;
var height = opts.height;
var callback = opts.callback || function(url){
window.open(url, "name-"+Math.random());
};
// callback to handle keypress
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
var onKeyPress = __bind(function(event){
// return now if the KeyPress isnt for the proper charCode
if( event.which !== charCode ) return;
// get the renderer output
var dataUrl = this.toDataURL(renderer);
if( width === undefined && height === undefined ){
callback( dataUrl )
}else{
// resize it and notify the callback
// * resize == async so if callback is a window open, it triggers the pop blocker
_aspectResize(dataUrl, width, height, callback);
}
}, this);
// listen to keypress
// NOTE: for firefox it seems mandatory to listen to document directly
document.addEventListener('keypress', onKeyPress, false);
return {
unbind : function(){
document.removeEventListener('keypress', onKeyPress, false);
}
};
}
// export it
THREEx.Screenshot = {
toDataURL : toDataURL,
bindKey : bindKey
};
})();
// This THREEx helper makes it easy to handle the fullscreen API
// * it hides the prefix for each browser
// * it hides the little discrepencies of the various vendor API
// * at the time of this writing (nov 2011) it is available in
// [firefox nightly](http://blog.pearce.org.nz/2011/11/firefoxs-html-full-screen-api-enabled.html),
// [webkit nightly](http://peter.sh/2011/01/javascript-full-screen-api-navigation-timing-and-repeating-css-gradients/) and
// [chrome stable](http://updates.html5rocks.com/2011/10/Let-Your-Content-Do-the-Talking-Fullscreen-API).
//
// # Code
//
@namespace
var THREEx = THREEx || {};
THREEx.FullScreen = THREEx.FullScreen || {};
test if it is possible to have fullscreen
returns: {Boolean} true if fullscreen API is available, false otherwise
THREEx.FullScreen.available = function()
{
return this._hasWebkitFullScreen || this._hasMozFullScreen;
}
test if fullscreen is currently activated
returns: {Boolean} true if fullscreen is currently activated, false otherwise
THREEx.FullScreen.activated = function()
{
if( this._hasWebkitFullScreen ){
return document.webkitIsFullScreen;
}else if( this._hasMozFullScreen ){
return document.mozFullScreen;
}else{
console.assert(false);
}
}
Request fullscreen on a given element
parameter: {DomElement} element to make fullscreen. optional. default to document.body
THREEx.FullScreen.request = function(element)
{
element = element || document.body;
if( this._hasWebkitFullScreen ){
element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}else if( this._hasMozFullScreen ){
element.mozRequestFullScreen();
}else{
console.assert(false);
}
}
Cancel fullscreen
THREEx.FullScreen.cancel = function()
{
if( this._hasWebkitFullScreen ){
document.webkitCancelFullScreen();
}else if( this._hasMozFullScreen ){
document.mozCancelFullScreen();
}else{
console.assert(false);
}
}
// internal functions to know which fullscreen API implementation is available
THREEx.FullScreen._hasWebkitFullScreen = 'webkitCancelFullScreen' in document ? true : false;
THREEx.FullScreen._hasMozFullScreen = 'mozCancelFullScreen' in document ? true : false;
Bind a key to renderer screenshot
THREEx.FullScreen.bindKey = function(opts){
opts = opts || {};
var charCode = opts.charCode || 'f'.charCodeAt(0);
var dblclick = opts.dblclick !== undefined ? opts.dblclick : false;
var element = opts.element
var toggle = function(){
if( THREEx.FullScreen.activated() ){
THREEx.FullScreen.cancel();
}else{
THREEx.FullScreen.request(element);
}
}
// callback to handle keypress
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
var onKeyPress = __bind(function(event){
// return now if the KeyPress isnt for the proper charCode
if( event.which !== charCode ) return;
// toggle fullscreen
toggle();
}, this);
// listen to keypress
// NOTE: for firefox it seems mandatory to listen to document directly
document.addEventListener('keypress', onKeyPress, false);
// listen to dblclick
dblclick && document.addEventListener('dblclick', toggle, false);
return {
unbind : function(){
document.removeEventListener('keypress', onKeyPress, false);
dblclick && document.removeEventListener('dblclick', toggle, false);
}
};
}
@namespace
var THREEx = THREEx || {};
THREEx.DragPanControls = function(object, domElement)
{
this._object = object;
this._domElement= domElement || document;
// parameters that you can change after initialisation
this.target = new THREE.Vector3(0, 0, 0);
this.speedX = 0.03;
this.speedY = 0.03;
this.rangeX = -40;
this.rangeY = +40;
// private variables
this._mouseX = 0;
this._mouseY = 0;
var _this = this;
this._onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); };
this._onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); };
this._domElement.addEventListener( 'mousemove', this._onTouchStart,false );
this._domElement.addEventListener( 'touchmove', this._onMouseMove, false );
this._domElement.removeEventListener( 'touchstart', this._onTouchMove, false );
}
THREEx.DragPanControls.prototype.update = function(event)
{
this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX;
this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY;
this._object.lookAt( this.target );
}
THREEx.DragPanControls.prototype._onMouseMove = function(event)
{
this._mouseX = ( event.clientX / window.innerWidth ) - 0.5;
this._mouseY = ( event.clientY / window.innerHeight) - 0.5;
}
THREEx.DragPanControls.prototype._onTouchStart = function(event)
{
if( event.touches.length != 1 ) return;
// no preventDefault to get click event on ios
this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5;
this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5;
}
THREEx.DragPanControls.prototype._onTouchMove = function(event)
{
if( event.touches.length != 1 ) return;
event.preventDefault();
this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5;
this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5;
}
// stats.js r8 - http://github.com/mrdoob/stats.js
var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign=
"left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height=
"30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding=
"0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"),
a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/
100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}};
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.