/***
P R O C E S S I N G . J S - 1.3.6
a port of the Processing visualization language
Processing.js is licensed under the MIT License, see LICENSE.
For a list of copyright holders, please refer to AUTHORS.
http://processingjs.org
***/
(function(window, document, Math, undef) {
var nop = function() {};
var debug = function() {
if ("console" in window) return function(msg) {
window.console.log("Processing.js: " + msg)
};
return nop()
}();
var ajax = function(url) {
var xhr = new XMLHttpRequest;
xhr.open("GET", url, false);
if (xhr.overrideMimeType) xhr.overrideMimeType("text/plain");
xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
xhr.send(null);
if (xhr.status !== 200 && xhr.status !== 0) throw "XMLHttpRequest failed, status code " + xhr.status;
return xhr.responseText
};
var isDOMPresent = "document" in this && !("fake" in this.document);
document.head = document.head || document.getElementsByTagName("head")[0];
function setupTypedArray(name, fallback) {
if (name in window) return window[name];
if (typeof window[fallback] === "function") return window[fallback];
return function(obj) {
if (obj instanceof Array) return obj;
if (typeof obj === "number") {
var arr = [];
arr.length = obj;
return arr
}
}
}
var Float32Array = setupTypedArray("Float32Array", "WebGLFloatArray"),
Int32Array = setupTypedArray("Int32Array", "WebGLIntArray"),
Uint16Array = setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"),
Uint8Array = setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");
var PConstants = {
X: 0,
Y: 1,
Z: 2,
R: 3,
G: 4,
B: 5,
A: 6,
U: 7,
V: 8,
NX: 9,
NY: 10,
NZ: 11,
EDGE: 12,
SR: 13,
SG: 14,
SB: 15,
SA: 16,
SW: 17,
TX: 18,
TY: 19,
TZ: 20,
VX: 21,
VY: 22,
VZ: 23,
VW: 24,
AR: 25,
AG: 26,
AB: 27,
DR: 3,
DG: 4,
DB: 5,
DA: 6,
SPR: 28,
SPG: 29,
SPB: 30,
SHINE: 31,
ER: 32,
EG: 33,
EB: 34,
BEEN_LIT: 35,
VERTEX_FIELD_COUNT: 36,
P2D: 1,
JAVA2D: 1,
WEBGL: 2,
P3D: 2,
OPENGL: 2,
PDF: 0,
DXF: 0,
OTHER: 0,
WINDOWS: 1,
MAXOSX: 2,
LINUX: 3,
EPSILON: 1.0E-4,
MAX_FLOAT: 3.4028235E38,
MIN_FLOAT: -3.4028235E38,
MAX_INT: 2147483647,
MIN_INT: -2147483648,
PI: Math.PI,
TWO_PI: 2 * Math.PI,
HALF_PI: Math.PI / 2,
THIRD_PI: Math.PI / 3,
QUARTER_PI: Math.PI / 4,
DEG_TO_RAD: Math.PI / 180,
RAD_TO_DEG: 180 / Math.PI,
WHITESPACE: " \t\n\r\u000c\u00a0",
RGB: 1,
ARGB: 2,
HSB: 3,
ALPHA: 4,
CMYK: 5,
TIFF: 0,
TARGA: 1,
JPEG: 2,
GIF: 3,
BLUR: 11,
GRAY: 12,
INVERT: 13,
OPAQUE: 14,
POSTERIZE: 15,
THRESHOLD: 16,
ERODE: 17,
DILATE: 18,
REPLACE: 0,
BLEND: 1 << 0,
ADD: 1 << 1,
SUBTRACT: 1 << 2,
LIGHTEST: 1 << 3,
DARKEST: 1 << 4,
DIFFERENCE: 1 << 5,
EXCLUSION: 1 << 6,
MULTIPLY: 1 << 7,
SCREEN: 1 << 8,
OVERLAY: 1 << 9,
HARD_LIGHT: 1 << 10,
SOFT_LIGHT: 1 << 11,
DODGE: 1 << 12,
BURN: 1 << 13,
ALPHA_MASK: 4278190080,
RED_MASK: 16711680,
GREEN_MASK: 65280,
BLUE_MASK: 255,
CUSTOM: 0,
ORTHOGRAPHIC: 2,
PERSPECTIVE: 3,
POINT: 2,
POINTS: 2,
LINE: 4,
LINES: 4,
TRIANGLE: 8,
TRIANGLES: 9,
TRIANGLE_STRIP: 10,
TRIANGLE_FAN: 11,
QUAD: 16,
QUADS: 16,
QUAD_STRIP: 17,
POLYGON: 20,
PATH: 21,
RECT: 30,
ELLIPSE: 31,
ARC: 32,
SPHERE: 40,
BOX: 41,
GROUP: 0,
PRIMITIVE: 1,
GEOMETRY: 3,
VERTEX: 0,
BEZIER_VERTEX: 1,
CURVE_VERTEX: 2,
BREAK: 3,
CLOSESHAPE: 4,
OPEN: 1,
CLOSE: 2,
CORNER: 0,
CORNERS: 1,
RADIUS: 2,
CENTER_RADIUS: 2,
CENTER: 3,
DIAMETER: 3,
CENTER_DIAMETER: 3,
BASELINE: 0,
TOP: 101,
BOTTOM: 102,
NORMAL: 1,
NORMALIZED: 1,
IMAGE: 2,
MODEL: 4,
SHAPE: 5,
SQUARE: "butt",
ROUND: "round",
PROJECT: "square",
MITER: "miter",
BEVEL: "bevel",
AMBIENT: 0,
DIRECTIONAL: 1,
SPOT: 3,
BACKSPACE: 8,
TAB: 9,
ENTER: 10,
RETURN: 13,
ESC: 27,
DELETE: 127,
CODED: 65535,
SHIFT: 16,
CONTROL: 17,
ALT: 18,
CAPSLK: 20,
PGUP: 33,
PGDN: 34,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
F1: 112,
F2: 113,
F3: 114,
F4: 115,
F5: 116,
F6: 117,
F7: 118,
F8: 119,
F9: 120,
F10: 121,
F11: 122,
F12: 123,
NUMLK: 144,
META: 157,
INSERT: 155,
ARROW: "default",
CROSS: "crosshair",
HAND: "pointer",
MOVE: "move",
TEXT: "text",
WAIT: "wait",
NOCURSOR: "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto",
DISABLE_OPENGL_2X_SMOOTH: 1,
ENABLE_OPENGL_2X_SMOOTH: -1,
ENABLE_OPENGL_4X_SMOOTH: 2,
ENABLE_NATIVE_FONTS: 3,
DISABLE_DEPTH_TEST: 4,
ENABLE_DEPTH_TEST: -4,
ENABLE_DEPTH_SORT: 5,
DISABLE_DEPTH_SORT: -5,
DISABLE_OPENGL_ERROR_REPORT: 6,
ENABLE_OPENGL_ERROR_REPORT: -6,
ENABLE_ACCURATE_TEXTURES: 7,
DISABLE_ACCURATE_TEXTURES: -7,
HINT_COUNT: 10,
SINCOS_LENGTH: 720,
PRECISIONB: 15,
PRECISIONF: 1 << 15,
PREC_MAXVAL: (1 << 15) - 1,
PREC_ALPHA_SHIFT: 24 - 15,
PREC_RED_SHIFT: 16 - 15,
NORMAL_MODE_AUTO: 0,
NORMAL_MODE_SHAPE: 1,
NORMAL_MODE_VERTEX: 2,
MAX_LIGHTS: 8
};
function virtHashCode(obj) {
if (typeof obj === "string") {
var hash = 0;
for (var i = 0; i < obj.length; ++i) hash = hash * 31 + obj.charCodeAt(i) & 4294967295;
return hash
}
if (typeof obj !== "object") return obj & 4294967295;
if (obj.hashCode instanceof Function) return obj.hashCode();
if (obj.$id === undef) obj.$id = Math.floor(Math.random() * 65536) - 32768 << 16 | Math.floor(Math.random() * 65536);
return obj.$id
}
function virtEquals(obj, other) {
if (obj === null || other === null) return obj === null && other === null;
if (typeof obj === "string") return obj === other;
if (typeof obj !== "object") return obj === other;
if (obj.equals instanceof Function) return obj.equals(other);
return obj === other
}
var ObjectIterator = function(obj) {
if (obj.iterator instanceof Function) return obj.iterator();
if (obj instanceof Array) {
var index = -1;
this.hasNext = function() {
return ++index < obj.length
};
this.next = function() {
return obj[index]
}
} else throw "Unable to iterate: " + obj;
};
var ArrayList = function() {
function Iterator(array) {
var index = 0;
this.hasNext = function() {
return index < array.length
};
this.next = function() {
return array[index++]
};
this.remove = function() {
array.splice(index, 1)
}
}
function ArrayList() {
var array;
if (arguments.length === 0) array = [];
else if (arguments.length > 0 && typeof arguments[0] !== "number") array = arguments[0].toArray();
else {
array = [];
array.length = 0 | arguments[0]
}
this.get = function(i) {
return array[i]
};
this.contains = function(item) {
return this.indexOf(item) > -1
};
this.indexOf = function(item) {
for (var i = 0, len = array.length; i < len; ++i) if (virtEquals(item, array[i])) return i;
return -1
};
this.add = function() {
if (arguments.length === 1) array.push(arguments[0]);
else if (arguments.length === 2) {
var arg0 = arguments[0];
if (typeof arg0 === "number") if (arg0 >= 0 && arg0 <= array.length) array.splice(arg0, 0, arguments[1]);
else throw arg0 + " is not a valid index";
else throw typeof arg0 + " is not a number";
} else throw "Please use the proper number of parameters.";
};
this.addAll = function(arg1, arg2) {
var it;
if (typeof arg1 === "number") {
if (arg1 < 0 || arg1 > array.length) throw "Index out of bounds for addAll: " + arg1 + " greater or equal than " + array.length;
it = new ObjectIterator(arg2);
while (it.hasNext()) array.splice(arg1++, 0, it.next())
} else {
it = new ObjectIterator(arg1);
while (it.hasNext()) array.push(it.next())
}
};
this.set = function() {
if (arguments.length === 2) {
var arg0 = arguments[0];
if (typeof arg0 === "number") if (arg0 >= 0 && arg0 < array.length) array.splice(arg0, 1, arguments[1]);
else throw arg0 + " is not a valid index.";
else throw typeof arg0 + " is not a number";
} else throw "Please use the proper number of parameters.";
};
this.size = function() {
return array.length
};
this.clear = function() {
array.length = 0
};
this.remove = function(item) {
if (typeof item === "number") return array.splice(item, 1)[0];
item = this.indexOf(item);
if (item > -1) {
array.splice(item, 1);
return true
}
return false
};
this.isEmpty = function() {
return !array.length
};
this.clone = function() {
return new ArrayList(this)
};
this.toArray = function() {
return array.slice(0)
};
this.iterator = function() {
return new Iterator(array)
}
}
return ArrayList
}();
var HashMap = function() {
function HashMap() {
if (arguments.length === 1 && arguments[0] instanceof HashMap) return arguments[0].clone();
var initialCapacity = arguments.length > 0 ? arguments[0] : 16;
var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;
var buckets = [];
buckets.length = initialCapacity;
var count = 0;
var hashMap = this;
function getBucketIndex(key) {
var index = virtHashCode(key) % buckets.length;
return index < 0 ? buckets.length + index : index
}
function ensureLoad() {
if (count <= loadFactor * buckets.length) return;
var allEntries = [];
for (var i = 0; i < buckets.length; ++i) if (buckets[i] !== undef) allEntries = allEntries.concat(buckets[i]);
var newBucketsLength = buckets.length * 2;
buckets = [];
buckets.length = newBucketsLength;
for (var j = 0; j < allEntries.length; ++j) {
var index = getBucketIndex(allEntries[j].key);
var bucket = buckets[index];
if (bucket === undef) buckets[index] = bucket = [];
bucket.push(allEntries[j])
}
}
function Iterator(conversion, removeItem) {
var bucketIndex = 0;
var itemIndex = -1;
var endOfBuckets = false;
function findNext() {
while (!endOfBuckets) {
++itemIndex;
if (bucketIndex >= buckets.length) endOfBuckets = true;
else if (buckets[bucketIndex] === undef || itemIndex >= buckets[bucketIndex].length) {
itemIndex = -1;
++bucketIndex
} else return
}
}
this.hasNext = function() {
return !endOfBuckets
};
this.next = function() {
var result = conversion(buckets[bucketIndex][itemIndex]);
findNext();
return result
};
this.remove = function() {
removeItem(this.next());
--itemIndex
};
findNext()
}
function Set(conversion, isIn, removeItem) {
this.clear = function() {
hashMap.clear()
};
this.contains = function(o) {
return isIn(o)
};
this.containsAll = function(o) {
var it = o.iterator();
while (it.hasNext()) if (!this.contains(it.next())) return false;
return true
};
this.isEmpty = function() {
return hashMap.isEmpty()
};
this.iterator = function() {
return new Iterator(conversion, removeItem)
};
this.remove = function(o) {
if (this.contains(o)) {
removeItem(o);
return true
}
return false
};
this.removeAll = function(c) {
var it = c.iterator();
var changed = false;
while (it.hasNext()) {
var item = it.next();
if (this.contains(item)) {
removeItem(item);
changed = true
}
}
return true
};
this.retainAll = function(c) {
var it = this.iterator();
var toRemove = [];
while (it.hasNext()) {
var entry = it.next();
if (!c.contains(entry)) toRemove.push(entry)
}
for (var i = 0; i < toRemove.length; ++i) removeItem(toRemove[i]);
return toRemove.length > 0
};
this.size = function() {
return hashMap.size()
};
this.toArray = function() {
var result = [];
var it = this.iterator();
while (it.hasNext()) result.push(it.next());
return result
}
}
function Entry(pair) {
this._isIn = function(map) {
return map === hashMap && pair.removed === undef
};
this.equals = function(o) {
return virtEquals(pair.key, o.getKey())
};
this.getKey = function() {
return pair.key
};
this.getValue = function() {
return pair.value
};
this.hashCode = function(o) {
return virtHashCode(pair.key)
};
this.setValue = function(value) {
var old = pair.value;
pair.value = value;
return old
}
}
this.clear = function() {
count = 0;
buckets = [];
buckets.length = initialCapacity
};
this.clone = function() {
var map = new HashMap;
map.putAll(this);
return map
};
this.containsKey = function(key) {
var index = getBucketIndex(key);
var bucket = buckets[index];
if (bucket === undef) return false;
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return true;
return false
};
this.containsValue = function(value) {
for (var i = 0; i < buckets.length; ++i) {
var bucket = buckets[i];
if (bucket === undef) continue;
for (var j = 0; j < bucket.length; ++j) if (virtEquals(bucket[j].value, value)) return true
}
return false
};
this.entrySet = function() {
return new Set(function(pair) {
return new Entry(pair)
},
function(pair) {
return pair instanceof Entry && pair._isIn(hashMap)
},
function(pair) {
return hashMap.remove(pair.getKey())
})
};
this.get = function(key) {
var index = getBucketIndex(key);
var bucket = buckets[index];
if (bucket === undef) return null;
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return bucket[i].value;
return null
};
this.isEmpty = function() {
return count === 0
};
this.keySet = function() {
return new Set(function(pair) {
return pair.key
},
function(key) {
return hashMap.containsKey(key)
},
function(key) {
return hashMap.remove(key)
})
};
this.values = function() {
return new Set(function(pair) {
return pair.value
},
function(value) {
return hashMap.containsValue(value)
},
function(value) {
return hashMap.removeByValue(value)
})
};
this.put = function(key, value) {
var index = getBucketIndex(key);
var bucket = buckets[index];
if (bucket === undef) {
++count;
buckets[index] = [{
key: key,
value: value
}];
ensureLoad();
return null
}
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
var previous = bucket[i].value;
bucket[i].value = value;
return previous
}++count;
bucket.push({
key: key,
value: value
});
ensureLoad();
return null
};
this.putAll = function(m) {
var it = m.entrySet().iterator();
while (it.hasNext()) {
var entry = it.next();
this.put(entry.getKey(), entry.getValue())
}
};
this.remove = function(key) {
var index = getBucketIndex(key);
var bucket = buckets[index];
if (bucket === undef) return null;
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
--count;
var previous = bucket[i].value;
bucket[i].removed = true;
if (bucket.length > 1) bucket.splice(i, 1);
else buckets[index] = undef;
return previous
}
return null
};
this.removeByValue = function(value) {
var bucket, i, ilen, pair;
for (bucket in buckets) if (buckets.hasOwnProperty(bucket)) for (i = 0, ilen = buckets[bucket].length; i < ilen; i++) {
pair = buckets[bucket][i];
if (pair.value === value) {
buckets[bucket].splice(i, 1);
return true
}
}
return false
};
this.size = function() {
return count
}
}
return HashMap
}();
var PVector = function() {
function PVector(x, y, z) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0
}
PVector.dist = function(v1, v2) {
return v1.dist(v2)
};
PVector.dot = function(v1, v2) {
return v1.dot(v2)
};
PVector.cross = function(v1, v2) {
return v1.cross(v2)
};
PVector.angleBetween = function(v1, v2) {
return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()))
};
PVector.prototype = {
set: function(v, y, z) {
if (arguments.length === 1) this.set(v.x || v[0] || 0, v.y || v[1] || 0, v.z || v[2] || 0);
else {
this.x = v;
this.y = y;
this.z = z
}
},
get: function() {
return new PVector(this.x, this.y, this.z)
},
mag: function() {
var x = this.x,
y = this.y,
z = this.z;
return Math.sqrt(x * x + y * y + z * z)
},
add: function(v, y, z) {
if (arguments.length === 1) {
this.x += v.x;
this.y += v.y;
this.z += v.z
} else {
this.x += v;
this.y += y;
this.z += z
}
},
sub: function(v, y, z) {
if (arguments.length === 1) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z
} else {
this.x -= v;
this.y -= y;
this.z -= z
}
},
mult: function(v) {
if (typeof v === "number") {
this.x *= v;
this.y *= v;
this.z *= v
} else {
this.x *= v.x;
this.y *= v.y;
this.z *= v.z
}
},
div: function(v) {
if (typeof v === "number") {
this.x /= v;
this.y /= v;
this.z /= v
} else {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z
}
},
dist: function(v) {
var dx = this.x - v.x,
dy = this.y - v.y,
dz = this.z - v.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz)
},
dot: function(v, y, z) {
if (arguments.length === 1) return this.x * v.x + this.y * v.y + this.z * v.z;
return this.x * v + this.y * y + this.z * z
},
cross: function(v) {
var x = this.x,
y = this.y,
z = this.z;
return new PVector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y)
},
normalize: function() {
var m = this.mag();
if (m > 0) this.div(m)
},
limit: function(high) {
if (this.mag() > high) {
this.normalize();
this.mult(high)
}
},
heading2D: function() {
return -Math.atan2(-this.y, this.x)
},
toString: function() {
return "[" + this.x + ", " + this.y + ", " + this.z + "]"
},
array: function() {
return [this.x, this.y, this.z]
}
};
function createPVectorMethod(method) {
return function(v1, v2) {
var v = v1.get();
v[method](v2);
return v
}
}
for (var method in PVector.prototype) if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) PVector[method] = createPVectorMethod(method);
return PVector
}();
function DefaultScope() {}
DefaultScope.prototype = PConstants;
var defaultScope = new DefaultScope;
defaultScope.ArrayList = ArrayList;
defaultScope.HashMap = HashMap;
defaultScope.PVector = PVector;
defaultScope.ObjectIterator = ObjectIterator;
defaultScope.PConstants = PConstants;
defaultScope.defineProperty = function(obj, name, desc) {
if ("defineProperty" in Object) Object.defineProperty(obj, name, desc);
else {
if (desc.hasOwnProperty("get")) obj.__defineGetter__(name, desc.get);
if (desc.hasOwnProperty("set")) obj.__defineSetter__(name, desc.set)
}
};
function extendClass(subClass, baseClass) {
function extendGetterSetter(propertyName) {
defaultScope.defineProperty(subClass, propertyName, {
get: function() {
return baseClass[propertyName]
},
set: function(v) {
baseClass[propertyName] = v
},
enumerable: true
})
}
var properties = [];
for (var propertyName in baseClass) if (typeof baseClass[propertyName] === "function") {
if (!subClass.hasOwnProperty(propertyName)) subClass[propertyName] = baseClass[propertyName]
} else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName);
while (properties.length > 0) extendGetterSetter(properties.shift())
}
defaultScope.extendClassChain = function(base) {
var path = [base];
for (var self = base.$upcast; self; self = self.$upcast) {
extendClass(self, base);
path.push(self);
base = self
}
while (path.length > 0) path.pop().$self = base
};
defaultScope.extendStaticMembers = function(derived, base) {
extendClass(derived, base)
};
defaultScope.extendInterfaceMembers = function(derived, base) {
extendClass(derived, base)
};
defaultScope.addMethod = function(object, name, fn, superAccessor) {
if (object[name]) {
var args = fn.length,
oldfn = object[name];
object[name] = function() {
if (arguments.length === args) return fn.apply(this, arguments);
return oldfn.apply(this, arguments)
}
} else object[name] = fn
};
defaultScope.createJavaArray = function(type, bounds) {
var result = null;
if (typeof bounds[0] === "number") {
var itemsCount = 0 | bounds[0];
if (bounds.length <= 1) {
result = [];
result.length = itemsCount;
for (var i = 0; i < itemsCount; ++i) result[i] = 0
} else {
result = [];
var newBounds = bounds.slice(1);
for (var j = 0; j < itemsCount; ++j) result.push(defaultScope.createJavaArray(type, newBounds))
}
}
return result
};
var colors = {
aliceblue: "#f0f8ff",
antiquewhite: "#faebd7",
aqua: "#00ffff",
aquamarine: "#7fffd4",
azure: "#f0ffff",
beige: "#f5f5dc",
bisque: "#ffe4c4",
black: "#000000",
blanchedalmond: "#ffebcd",
blue: "#0000ff",
blueviolet: "#8a2be2",
brown: "#a52a2a",
burlywood: "#deb887",
cadetblue: "#5f9ea0",
chartreuse: "#7fff00",
chocolate: "#d2691e",
coral: "#ff7f50",
cornflowerblue: "#6495ed",
cornsilk: "#fff8dc",
crimson: "#dc143c",
cyan: "#00ffff",
darkblue: "#00008b",
darkcyan: "#008b8b",
darkgoldenrod: "#b8860b",
darkgray: "#a9a9a9",
darkgreen: "#006400",
darkkhaki: "#bdb76b",
darkmagenta: "#8b008b",
darkolivegreen: "#556b2f",
darkorange: "#ff8c00",
darkorchid: "#9932cc",
darkred: "#8b0000",
darksalmon: "#e9967a",
darkseagreen: "#8fbc8f",
darkslateblue: "#483d8b",
darkslategray: "#2f4f4f",
darkturquoise: "#00ced1",
darkviolet: "#9400d3",
deeppink: "#ff1493",
deepskyblue: "#00bfff",
dimgray: "#696969",
dodgerblue: "#1e90ff",
firebrick: "#b22222",
floralwhite: "#fffaf0",
forestgreen: "#228b22",
fuchsia: "#ff00ff",
gainsboro: "#dcdcdc",
ghostwhite: "#f8f8ff",
gold: "#ffd700",
goldenrod: "#daa520",
gray: "#808080",
green: "#008000",
greenyellow: "#adff2f",
honeydew: "#f0fff0",
hotpink: "#ff69b4",
indianred: "#cd5c5c",
indigo: "#4b0082",
ivory: "#fffff0",
khaki: "#f0e68c",
lavender: "#e6e6fa",
lavenderblush: "#fff0f5",
lawngreen: "#7cfc00",
lemonchiffon: "#fffacd",
lightblue: "#add8e6",
lightcoral: "#f08080",
lightcyan: "#e0ffff",
lightgoldenrodyellow: "#fafad2",
lightgrey: "#d3d3d3",
lightgreen: "#90ee90",
lightpink: "#ffb6c1",
lightsalmon: "#ffa07a",
lightseagreen: "#20b2aa",
lightskyblue: "#87cefa",
lightslategray: "#778899",
lightsteelblue: "#b0c4de",
lightyellow: "#ffffe0",
lime: "#00ff00",
limegreen: "#32cd32",
linen: "#faf0e6",
magenta: "#ff00ff",
maroon: "#800000",
mediumaquamarine: "#66cdaa",
mediumblue: "#0000cd",
mediumorchid: "#ba55d3",
mediumpurple: "#9370d8",
mediumseagreen: "#3cb371",
mediumslateblue: "#7b68ee",
mediumspringgreen: "#00fa9a",
mediumturquoise: "#48d1cc",
mediumvioletred: "#c71585",
midnightblue: "#191970",
mintcream: "#f5fffa",
mistyrose: "#ffe4e1",
moccasin: "#ffe4b5",
navajowhite: "#ffdead",
navy: "#000080",
oldlace: "#fdf5e6",
olive: "#808000",
olivedrab: "#6b8e23",
orange: "#ffa500",
orangered: "#ff4500",
orchid: "#da70d6",
palegoldenrod: "#eee8aa",
palegreen: "#98fb98",
paleturquoise: "#afeeee",
palevioletred: "#d87093",
papayawhip: "#ffefd5",
peachpuff: "#ffdab9",
peru: "#cd853f",
pink: "#ffc0cb",
plum: "#dda0dd",
powderblue: "#b0e0e6",
purple: "#800080",
red: "#ff0000",
rosybrown: "#bc8f8f",
royalblue: "#4169e1",
saddlebrown: "#8b4513",
salmon: "#fa8072",
sandybrown: "#f4a460",
seagreen: "#2e8b57",
seashell: "#fff5ee",
sienna: "#a0522d",
silver: "#c0c0c0",
skyblue: "#87ceeb",
slateblue: "#6a5acd",
slategray: "#708090",
snow: "#fffafa",
springgreen: "#00ff7f",
steelblue: "#4682b4",
tan: "#d2b48c",
teal: "#008080",
thistle: "#d8bfd8",
tomato: "#ff6347",
turquoise: "#40e0d0",
violet: "#ee82ee",
wheat: "#f5deb3",
white: "#ffffff",
whitesmoke: "#f5f5f5",
yellow: "#ffff00",
yellowgreen: "#9acd32"
};
(function(Processing) {
var unsupportedP5 = ("open() createOutput() createInput() BufferedReader selectFolder() " + "dataPath() createWriter() selectOutput() beginRecord() " + "saveStream() endRecord() selectInput() saveBytes() createReader() " + "beginRaw() endRaw() PrintWriter delay()").split(" "),
count = unsupportedP5.length,
prettyName, p5Name;
function createUnsupportedFunc(n) {
return function() {
throw "Processing.js does not support " + n + ".";
}
}
while (count--) {
prettyName = unsupportedP5[count];
p5Name = prettyName.replace("()", "");
Processing[p5Name] = createUnsupportedFunc(prettyName)
}
})(defaultScope);
defaultScope.defineProperty(defaultScope, "screenWidth", {
get: function() {
return window.innerWidth
}
});
defaultScope.defineProperty(defaultScope, "screenHeight", {
get: function() {
return window.innerHeight
}
});
var processingInstances = [];
var processingInstanceIds = {};
var removeInstance = function(id) {
processingInstances.splice(processingInstanceIds[id], 1);
delete processingInstanceIds[id]
};
var addInstance = function(processing) {
if (processing.externals.canvas.id === undef || !processing.externals.canvas.id.length) processing.externals.canvas.id = "__processing" + processingInstances.length;
processingInstanceIds[processing.externals.canvas.id] = processingInstances.length;
processingInstances.push(processing)
};
function computeFontMetrics(pfont) {
var emQuad = 250,
correctionFactor = pfont.size / emQuad,
canvas = document.createElement("canvas");
canvas.width = 2 * emQuad;
canvas.height = 2 * emQuad;
canvas.style.opacity = 0;
var cfmFont = pfont.getCSSDefinition(emQuad + "px", "normal"),
ctx = canvas.getContext("2d");
ctx.font = cfmFont;
pfont.context2d = ctx;
var protrusions = "dbflkhyjqpg";
canvas.width = ctx.measureText(protrusions).width;
ctx.font = cfmFont;
var leadDiv = document.createElement("div");
leadDiv.style.position = "absolute";
leadDiv.style.opacity = 0;
leadDiv.style.fontFamily = '"' + pfont.name + '"';
leadDiv.style.fontSize = emQuad + "px";
leadDiv.innerHTML = protrusions + "
" + protrusions;
document.body.appendChild(leadDiv);
var w = canvas.width,
h = canvas.height,
baseline = h / 2;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = "black";
ctx.fillText(protrusions, 0, baseline);
var pixelData = ctx.getImageData(0, 0, w, h).data;
var i = 0,
w4 = w * 4,
len = pixelData.length;
while (++i < len && pixelData[i] === 255) nop();
var ascent = Math.round(i / w4);
i = len - 1;
while (--i > 0 && pixelData[i] === 255) nop();
var descent = Math.round(i / w4);
pfont.ascent = correctionFactor * (baseline - ascent);
pfont.descent = correctionFactor * (descent - baseline);
if (document.defaultView.getComputedStyle) {
var leadDivHeight = document.defaultView.getComputedStyle(leadDiv, null).getPropertyValue("height");
leadDivHeight = correctionFactor * leadDivHeight.replace("px", "");
if (leadDivHeight >= pfont.size * 2) pfont.leading = Math.round(leadDivHeight / 2)
}
document.body.removeChild(leadDiv)
}
function PFont(name, size) {
if (name === undef) name = "";
this.name = name;
if (size === undef) size = 0;
this.size = size;
this.glyph = false;
this.ascent = 0;
this.descent = 0;
this.leading = 1.2 * size;
var illegalIndicator = name.indexOf(" Italic Bold");
if (illegalIndicator !== -1) name = name.substring(0, illegalIndicator);
this.style = "normal";
var italicsIndicator = name.indexOf(" Italic");
if (italicsIndicator !== -1) {
name = name.substring(0, italicsIndicator);
this.style = "italic"
}
this.weight = "normal";
var boldIndicator = name.indexOf(" Bold");
if (boldIndicator !== -1) {
name = name.substring(0, boldIndicator);
this.weight = "bold"
}
this.family = "sans-serif";
if (name !== undef) switch (name) {
case "sans-serif":
case "serif":
case "monospace":
case "fantasy":
case "cursive":
this.family = name;
break;
default:
this.family = '"' + name + '", sans-serif';
break
}
this.context2d = null;
computeFontMetrics(this);
this.css = this.getCSSDefinition();
this.context2d.font = this.css
}
PFont.prototype.getCSSDefinition = function(fontSize, lineHeight) {
if (fontSize === undef) fontSize = this.size + "px";
if (lineHeight === undef) lineHeight = this.leading + "px";
var components = [this.style, "normal", this.weight, fontSize + "/" + lineHeight, this.family];
return components.join(" ")
};
PFont.prototype.measureTextWidth = function(string) {
return this.context2d.measureText(string).width
};
PFont.PFontCache = {};
PFont.get = function(fontName, fontSize) {
var cache = PFont.PFontCache;
var idx = fontName + "/" + fontSize;
if (!cache[idx]) cache[idx] = new PFont(fontName, fontSize);
return cache[idx]
};
PFont.list = function() {
return ["sans-serif", "serif", "monospace", "fantasy", "cursive"]
};
PFont.preloading = {
template: {},
initialized: false,
initialize: function() {
var generateTinyFont = function() {
var encoded = "#E3KAI2wAgT1MvMg7Eo3VmNtYX7ABi3CxnbHlm" + "7Abw3kaGVhZ7ACs3OGhoZWE7A53CRobXR47AY3" + "AGbG9jYQ7G03Bm1heH7ABC3CBuYW1l7Ae3AgcG" + "9zd7AI3AE#B3AQ2kgTY18PPPUACwAg3ALSRoo3" + "#yld0xg32QAB77#E777773B#E3C#I#Q77773E#" + "Q7777777772CMAIw7AB77732B#M#Q3wAB#g3B#" + "E#E2BB//82BB////w#B7#gAEg3E77x2B32B#E#" + "Q#MTcBAQ32gAe#M#QQJ#E32M#QQJ#I#g32Q77#";
var expand = function(input) {
return "AAAAAAAA".substr(~~input ? 7 - input : 6)
};
return encoded.replace(/[#237]/g, expand)
};
var fontface = document.createElement("style");
fontface.setAttribute("type", "text/css");
fontface.innerHTML = "@font-face {\n" + ' font-family: "PjsEmptyFont";' + "\n" + " src: url('data:application/x-font-ttf;base64," + generateTinyFont() + "')\n" + " format('truetype');\n" + "}";
document.head.appendChild(fontface);
var element = document.createElement("span");
element.style.cssText = 'position: absolute; top: 0; left: 0; opacity: 0; font-family: "PjsEmptyFont", fantasy;';
element.innerHTML = "AAAAAAAA";
document.body.appendChild(element);
this.template = element;
this.initialized = true
},
getElementWidth: function(element) {
return document.defaultView.getComputedStyle(element, "").getPropertyValue("width")
},
timeAttempted: 0,
pending: function(intervallength) {
if (!this.initialized) this.initialize();
var element, computedWidthFont, computedWidthRef = this.getElementWidth(this.template);
for (var i = 0; i < this.fontList.length; i++) {
element = this.fontList[i];
computedWidthFont = this.getElementWidth(element);
if (this.timeAttempted < 4E3 && computedWidthFont === computedWidthRef) {
this.timeAttempted += intervallength;
return true
} else {
document.body.removeChild(element);
this.fontList.splice(i--, 1);
this.timeAttempted = 0
}
}
if (this.fontList.length === 0) return false;
return true
},
fontList: [],
addedList: {},
add: function(fontSrc) {
if (!this.initialized) this.initialize();
var fontName = typeof fontSrc === "object" ? fontSrc.fontFace : fontSrc,
fontUrl = typeof fontSrc === "object" ? fontSrc.url : fontSrc;
if (this.addedList[fontName]) return;
var style = document.createElement("style");
style.setAttribute("type", "text/css");
style.innerHTML = "@font-face{\n font-family: '" + fontName + "';\n src: url('" + fontUrl + "');\n}\n";
document.head.appendChild(style);
this.addedList[fontName] = true;
var element = document.createElement("span");
element.style.cssText = "position: absolute; top: 0; left: 0; opacity: 0;";
element.style.fontFamily = '"' + fontName + '", "PjsEmptyFont", fantasy';
element.innerHTML = "AAAAAAAA";
document.body.appendChild(element);
this.fontList.push(element)
}
};
defaultScope.PFont = PFont;
var Processing = this.Processing = function(aCanvas, aCode) {
if (! (this instanceof Processing)) throw "called Processing constructor as if it were a function: missing 'new'.";
var curElement, pgraphicsMode = aCanvas === undef && aCode === undef;
if (pgraphicsMode) curElement = document.createElement("canvas");
else curElement = typeof aCanvas === "string" ? document.getElementById(aCanvas) : aCanvas;
if (! (curElement instanceof HTMLCanvasElement)) throw "called Processing constructor without passing canvas element reference or id.";
function unimplemented(s) {
Processing.debug("Unimplemented - " + s)
}
var p = this;
p.externals = {
canvas: curElement,
context: undef,
sketch: undef
};
p.name = "Processing.js Instance";
p.use3DContext = false;
p.focused = false;
p.breakShape = false;
p.glyphTable = {};
p.pmouseX = 0;
p.pmouseY = 0;
p.mouseX = 0;
p.mouseY = 0;
p.mouseButton = 0;
p.mouseScroll = 0;
p.mouseClicked = undef;
p.mouseDragged = undef;
p.mouseMoved = undef;
p.mousePressed = undef;
p.mouseReleased = undef;
p.mouseScrolled = undef;
p.mouseOver = undef;
p.mouseOut = undef;
p.touchStart = undef;
p.touchEnd = undef;
p.touchMove = undef;
p.touchCancel = undef;
p.key = undef;
p.keyCode = undef;
p.keyPressed = nop;
p.keyReleased = nop;
p.keyTyped = nop;
p.draw = undef;
p.setup = undef;
p.__mousePressed = false;
p.__keyPressed = false;
p.__frameRate = 60;
p.frameCount = 0;
p.width = 100;
p.height = 100;
var curContext, curSketch, drawing, online = true,
doFill = true,
fillStyle = [1, 1, 1, 1],
currentFillColor = 4294967295,
isFillDirty = true,
doStroke = true,
strokeStyle = [0, 0, 0, 1],
currentStrokeColor = 4278190080,
isStrokeDirty = true,
lineWidth = 1,
loopStarted = false,
renderSmooth = false,
doLoop = true,
looping = 0,
curRectMode = 0,
curEllipseMode = 3,
normalX = 0,
normalY = 0,
normalZ = 0,
normalMode = 0,
curFrameRate = 60,
curMsPerFrame = 1E3 / curFrameRate,
curCursor = 'default',
oldCursor = curElement.style.cursor,
curShape = 20,
curShapeCount = 0,
curvePoints = [],
curTightness = 0,
curveDet = 20,
curveInited = false,
backgroundObj = -3355444,
bezDetail = 20,
colorModeA = 255,
colorModeX = 255,
colorModeY = 255,
colorModeZ = 255,
pathOpen = false,
mouseDragging = false,
pmouseXLastFrame = 0,
pmouseYLastFrame = 0,
curColorMode = 1,
curTint = null,
curTint3d = null,
getLoaded = false,
start = Date.now(),
timeSinceLastFPS = start,
framesSinceLastFPS = 0,
textcanvas, curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierDrawMatrix, bezierBasisInverse, bezierBasisMatrix, curContextCache = {
attributes: {},
locations: {}
},
programObject3D, programObject2D, programObjectUnlitShape, boxBuffer, boxNormBuffer, boxOutlineBuffer, rectBuffer, rectNormBuffer, sphereBuffer, lineBuffer, fillBuffer, fillColorBuffer, strokeColorBuffer, pointBuffer, shapeTexVBO, canTex, textTex, curTexture = {
width: 0,
height: 0
},
curTextureMode = 2,
usingTexture = false,
textBuffer, textureBuffer, indexBuffer, horizontalTextAlignment = 37,
verticalTextAlignment = 0,
textMode = 4,
curFontName = "Arial",
curTextSize = 12,
curTextAscent = 9,
curTextDescent = 2,
curTextLeading = 14,
curTextFont = PFont.get(curFontName, curTextSize),
originalContext, proxyContext = null,
isContextReplaced = false,
setPixelsCached, maxPixelsCached = 1E3,
pressedKeysMap = [],
lastPressedKeyCode = null,
codedKeys = [16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 144, 155, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 157];
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
if (document.defaultView && document.defaultView.getComputedStyle) {
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingLeft"], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingTop"], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderLeftWidth"], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderTopWidth"], 10) || 0
}
var lightCount = 0;
var sphereDetailV = 0,
sphereDetailU = 0,
sphereX = [],
sphereY = [],
sphereZ = [],
sinLUT = new Float32Array(720),
cosLUT = new Float32Array(720),
sphereVerts, sphereNorms;
var cam, cameraInv, modelView, modelViewInv, userMatrixStack, userReverseMatrixStack, inverseCopy, projection, manipulatingCamera = false,
frustumMode = false,
cameraFOV = 60 * (Math.PI / 180),
cameraX = p.width / 2,
cameraY = p.height / 2,
cameraZ = cameraY / Math.tan(cameraFOV / 2),
cameraNear = cameraZ / 10,
cameraFar = cameraZ * 10,
cameraAspect = p.width / p.height;
var vertArray = [],
curveVertArray = [],
curveVertCount = 0,
isCurve = false,
isBezier = false,
firstVert = true;
var curShapeMode = 0;
var styleArray = [];
var boxVerts = new Float32Array([0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]);
var boxOutlineVerts = new Float32Array([0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
var boxNorms = new Float32Array([0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]);
var rectVerts = new Float32Array([0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]);
var rectNorms = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
var vShaderSrcUnlitShape = "varying vec4 frontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float pointSize;" + "void main(void) {" + " frontColor = aColor;" + " gl_PointSize = pointSize;" + " gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}";
var fShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "void main(void){" + " gl_FragColor = frontColor;" + "}";
var vertexShaderSource2D = "varying vec4 frontColor;" + "attribute vec3 Vertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 color;" + "uniform mat4 model;" + "uniform mat4 view;" + "uniform mat4 projection;" + "uniform float pointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + " gl_PointSize = pointSize;" + " frontColor = color;" + " gl_Position = projection * view * model * vec4(Vertex, 1.0);" + " vTextureCoord = aTextureCoord;" + "}";
var fragmentShaderSource2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int picktype;" + "void main(void){" + " if(picktype == 0){" + " gl_FragColor = frontColor;" + " }" + " else if(picktype == 1){" + " float alpha = texture2D(uSampler, vTextureCoord).a;" + " gl_FragColor = vec4(frontColor.rgb*alpha, alpha);\n" + " }" + "}";
var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent);
var vertexShaderSource3D = "varying vec4 frontColor;" + "attribute vec3 Vertex;" + "attribute vec3 Normal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying vec2 vTexture;" + "uniform vec4 color;" + "uniform bool usingMat;" + "uniform vec3 specular;" + "uniform vec3 mat_emissive;" + "uniform vec3 mat_ambient;" + "uniform vec3 mat_specular;" + "uniform float shininess;" + "uniform mat4 model;" + "uniform mat4 view;" + "uniform mat4 projection;" + "uniform mat4 normalTransform;" + "uniform int lightCount;" + "uniform vec3 falloff;" + "struct Light {" + " int type;" + " vec3 color;" + " vec3 position;" + " vec3 direction;" + " float angle;" + " vec3 halfVector;" + " float concentration;" + "};" + "uniform Light lights0;" + "uniform Light lights1;" + "uniform Light lights2;" + "uniform Light lights3;" + "uniform Light lights4;" + "uniform Light lights5;" + "uniform Light lights6;" + "uniform Light lights7;" + "Light getLight(int index){" + " if(index == 0) return lights0;" + " if(index == 1) return lights1;" + " if(index == 2) return lights2;" + " if(index == 3) return lights3;" + " if(index == 4) return lights4;" + " if(index == 5) return lights5;" + " if(index == 6) return lights6;" + " return lights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + " float d = length( light.position - ecPos );" + " float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ));" + " totalAmbient += light.color * attenuation;" + "}" + "void DirectionalLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float powerfactor = 0.0;" + " float nDotVP = max(0.0, dot( vertNormal, normalize(-light.position) ));" + " float nDotVH = max(0.0, dot( vertNormal, normalize(-light.position-normalize(ecPos) )));" + " if( nDotVP != 0.0 ){" + " powerfactor = pow( nDotVH, shininess );" + " }" + " col += light.color * nDotVP;" + " spec += specular * powerfactor;" + "}" + "void PointLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float powerfactor;" + " vec3 VP = light.position - ecPos;" + " float d = length( VP ); " + " VP = normalize( VP );" + " float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ));" + " float nDotVP = max( 0.0, dot( vertNormal, VP ));" + " vec3 halfVector = normalize( VP - normalize(ecPos) );" + " float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" + " if( nDotVP == 0.0) {" + " powerfactor = 0.0;" + " }" + " else{" + " powerfactor = pow( nDotHV, shininess );" + " }" + " spec += specular * powerfactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void SpotLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float spotAttenuation;" + " float powerfactor;" + " vec3 VP = light.position - ecPos; " + " vec3 ldir = normalize( -light.direction );" + " float d = length( VP );" + " VP = normalize( VP );" + " float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ) );" + " float spotDot = dot( VP, ldir );" + (webglMaxTempsWorkaround ? " spotAttenuation = 1.0; " : " if( spotDot > cos( light.angle ) ) {" + " spotAttenuation = pow( spotDot, light.concentration );" + " }" + " else{" + " spotAttenuation = 0.0;" + " }" + " attenuation *= spotAttenuation;" + "") + " float nDotVP = max( 0.0, dot( vertNormal, VP ));" + " vec3 halfVector = normalize( VP - normalize(ecPos) );" + " float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" + " if( nDotVP == 0.0 ) {" + " powerfactor = 0.0;" + " }" + " else {" + " powerfactor = pow( nDotHV, shininess );" + " }" + " spec += specular * powerfactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void main(void) {" + " vec3 finalAmbient = vec3( 0.0, 0.0, 0.0 );" + " vec3 finalDiffuse = vec3( 0.0, 0.0, 0.0 );" + " vec3 finalSpecular = vec3( 0.0, 0.0, 0.0 );" + " vec4 col = color;" + " if(color[0] == -1.0){" + " col = aColor;" + " }" + " vec3 norm = normalize(vec3( normalTransform * vec4( Normal, 0.0 ) ));" + " vec4 ecPos4 = view * model * vec4(Vertex,1.0);" + " vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + " if( lightCount == 0 ) {" + " frontColor = col + vec4(mat_specular,1.0);" + " }" + " else {" + " for( int i = 0; i < 8; i++ ) {" + " Light l = getLight(i);" + " if( i >= lightCount ){" + " break;" + " }" + " if( l.type == 0 ) {" + " AmbientLight( finalAmbient, ecPos, l );" + " }" + " else if( l.type == 1 ) {" + " DirectionalLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else if( l.type == 2 ) {" + " PointLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else {" + " SpotLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " }" + " if( usingMat == false ) {" + " frontColor = vec4(" + " vec3(col) * finalAmbient +" + " vec3(col) * finalDiffuse +" + " vec3(col) * finalSpecular," + " col[3] );" + " }" + " else{" + " frontColor = vec4( " + " mat_emissive + " + " (vec3(col) * mat_ambient * finalAmbient) + " + " (vec3(col) * finalDiffuse) + " + " (mat_specular * finalSpecular), " + " col[3] );" + " }" + " }" + " vTexture.xy = aTexture.xy;" + " gl_Position = projection * view * model * vec4( Vertex, 1.0 );" + "}";
var fragmentShaderSource3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "uniform sampler2D sampler;" + "uniform bool usingTexture;" + "varying vec2 vTexture;" + "void main(void){" + " if(usingTexture){" + " gl_FragColor = vec4(texture2D(sampler, vTexture.xy)) * frontColor;" + " }" + " else{" + " gl_FragColor = frontColor;" + " }" + "}";
function uniformf(cacheId, programObj, varName, varValue) {
var varLocation = curContextCache.locations[cacheId];
if (varLocation === undef) {
varLocation = curContext.getUniformLocation(programObj, varName);
curContextCache.locations[cacheId] = varLocation
}
if (varLocation !== null) if (varValue.length === 4) curContext.uniform4fv(varLocation, varValue);
else if (varValue.length === 3) curContext.uniform3fv(varLocation, varValue);
else if (varValue.length === 2) curContext.uniform2fv(varLocation, varValue);
else curContext.uniform1f(varLocation, varValue)
}
function uniformi(cacheId, programObj, varName, varValue) {
var varLocation = curContextCache.locations[cacheId];
if (varLocation === undef) {
varLocation = curContext.getUniformLocation(programObj, varName);
curContextCache.locations[cacheId] = varLocation
}
if (varLocation !== null) if (varValue.length === 4) curContext.uniform4iv(varLocation, varValue);
else if (varValue.length === 3) curContext.uniform3iv(varLocation, varValue);
else if (varValue.length === 2) curContext.uniform2iv(varLocation, varValue);
else curContext.uniform1i(varLocation, varValue)
}
function uniformMatrix(cacheId, programObj, varName, transpose, matrix) {
var varLocation = curContextCache.locations[cacheId];
if (varLocation === undef) {
varLocation = curContext.getUniformLocation(programObj, varName);
curContextCache.locations[cacheId] = varLocation
}
if (varLocation !== -1) if (matrix.length === 16) curContext.uniformMatrix4fv(varLocation, transpose, matrix);
else if (matrix.length === 9) curContext.uniformMatrix3fv(varLocation, transpose, matrix);
else curContext.uniformMatrix2fv(varLocation, transpose, matrix)
}
function vertexAttribPointer(cacheId, programObj, varName, size, VBO) {
var varLocation = curContextCache.attributes[cacheId];
if (varLocation === undef) {
varLocation = curContext.getAttribLocation(programObj, varName);
curContextCache.attributes[cacheId] = varLocation
}
if (varLocation !== -1) {
curContext.bindBuffer(curContext.ARRAY_BUFFER, VBO);
curContext.vertexAttribPointer(varLocation, size, curContext.FLOAT, false, 0, 0);
curContext.enableVertexAttribArray(varLocation)
}
}
function disableVertexAttribPointer(cacheId, programObj, varName) {
var varLocation = curContextCache.attributes[cacheId];
if (varLocation === undef) {
varLocation = curContext.getAttribLocation(programObj, varName);
curContextCache.attributes[cacheId] = varLocation
}
if (varLocation !== -1) curContext.disableVertexAttribArray(varLocation)
}
var createProgramObject = function(curContext, vetexShaderSource, fragmentShaderSource) {
var vertexShaderObject = curContext.createShader(curContext.VERTEX_SHADER);
curContext.shaderSource(vertexShaderObject, vetexShaderSource);
curContext.compileShader(vertexShaderObject);
if (!curContext.getShaderParameter(vertexShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(vertexShaderObject);
var fragmentShaderObject = curContext.createShader(curContext.FRAGMENT_SHADER);
curContext.shaderSource(fragmentShaderObject, fragmentShaderSource);
curContext.compileShader(fragmentShaderObject);
if (!curContext.getShaderParameter(fragmentShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(fragmentShaderObject);
var programObject = curContext.createProgram();
curContext.attachShader(programObject, vertexShaderObject);
curContext.attachShader(programObject, fragmentShaderObject);
curContext.linkProgram(programObject);
if (!curContext.getProgramParameter(programObject, curContext.LINK_STATUS)) throw "Error linking shaders.";
return programObject
};
var imageModeCorner = function(x, y, w, h, whAreSizes) {
return {
x: x,
y: y,
w: w,
h: h
}
};
var imageModeConvert = imageModeCorner;
var imageModeCorners = function(x, y, w, h, whAreSizes) {
return {
x: x,
y: y,
w: whAreSizes ? w : w - x,
h: whAreSizes ? h : h - y
}
};
var imageModeCenter = function(x, y, w, h, whAreSizes) {
return {
x: x - w / 2,
y: y - h / 2,
w: w,
h: h
}
};
var DrawingShared = function() {};
var Drawing2D = function() {};
var Drawing3D = function() {};
var DrawingPre = function() {};
Drawing2D.prototype = new DrawingShared;
Drawing2D.prototype.constructor = Drawing2D;
Drawing3D.prototype = new DrawingShared;
Drawing3D.prototype.constructor = Drawing3D;
DrawingPre.prototype = new DrawingShared;
DrawingPre.prototype.constructor = DrawingPre;
DrawingShared.prototype.a3DOnlyFunction = nop;
var charMap = {};
var Char = p.Character = function(chr) {
if (typeof chr === "string" && chr.length === 1) this.code = chr.charCodeAt(0);
else if (typeof chr === "number") this.code = chr;
else if (chr instanceof Char) this.code = chr;
else this.code = NaN;
return charMap[this.code] === undef ? charMap[this.code] = this : charMap[this.code]
};
Char.prototype.toString = function() {
return String.fromCharCode(this.code)
};
Char.prototype.valueOf = function() {
return this.code
};
var PShape = p.PShape = function(family) {
this.family = family || 0;
this.visible = true;
this.style = true;
this.children = [];
this.nameTable = [];
this.params = [];
this.name = "";
this.image = null;
this.matrix = null;
this.kind = null;
this.close = null;
this.width = null;
this.height = null;
this.parent = null
};
PShape.prototype = {
isVisible: function() {
return this.visible
},
setVisible: function(visible) {
this.visible = visible
},
disableStyle: function() {
this.style = false;
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].disableStyle()
},
enableStyle: function() {
this.style = true;
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].enableStyle()
},
getFamily: function() {
return this.family
},
getWidth: function() {
return this.width
},
getHeight: function() {
return this.height
},
setName: function(name) {
this.name = name
},
getName: function() {
return this.name
},
draw: function() {
if (this.visible) {
this.pre();
this.drawImpl();
this.post()
}
},
drawImpl: function() {
if (this.family === 0) this.drawGroup();
else if (this.family === 1) this.drawPrimitive();
else if (this.family === 3) this.drawGeometry();
else if (this.family === 21) this.drawPath()
},
drawPath: function() {
var i, j;
if (this.vertices.length === 0) return;
p.beginShape();
if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i][0], this.vertices[i][1]);
else for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i][0], this.vertices[i][1], this.vertices[i][2]);
else {
var index = 0;
if (this.vertices[0].length === 2) for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
p.vertex(this.vertices[index][0], this.vertices[index][1]);
if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
p.breakShape = false;
index++
} else if (this.vertexCodes[i] === 1) {
p.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 2][0], this.vertices[index + 2][1]);
index += 3
} else if (this.vertexCodes[i] === 2) {
p.curveVertex(this.vertices[index][0], this.vertices[index][1]);
index++
} else {
if (this.vertexCodes[i] === 3) p.breakShape = true
} else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
p.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
p.breakShape = false
} else if (this.vertexCodes[i] === 1) {
p.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 0][2], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 1][2], this.vertices[index + 2][0], this.vertices[index + 2][1], this.vertices[index + 2][2]);
index += 3
} else if (this.vertexCodes[i] === 2) {
p.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
index++
} else if (this.vertexCodes[i] === 3) p.breakShape = true
}
p.endShape(this.close ? 2 : 1)
},
drawGeometry: function() {
var i, j;
p.beginShape(this.kind);
if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i]);
else for (i = 0, j = this.vertices.length; i < j; i++) {
var vert = this.vertices[i];
if (vert[2] === 0) p.vertex(vert[0], vert[1]);
else p.vertex(vert[0], vert[1], vert[2])
}
p.endShape()
},
drawGroup: function() {
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw()
},
drawPrimitive: function() {
if (this.kind === 2) p.point(this.params[0], this.params[1]);
else if (this.kind === 4) if (this.params.length === 4) p.line(this.params[0], this.params[1], this.params[2], this.params[3]);
else p.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
else if (this.kind === 8) p.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
else if (this.kind === 16) p.quad(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5], this.params[6], this.params[7]);
else if (this.kind === 30) if (this.image !== null) {
p.imageMode(0);
p.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3])
} else {
p.rectMode(0);
p.rect(this.params[0], this.params[1], this.params[2], this.params[3])
} else if (this.kind === 31) {
p.ellipseMode(0);
p.ellipse(this.params[0], this.params[1], this.params[2], this.params[3])
} else if (this.kind === 32) {
p.ellipseMode(0);
p.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5])
} else if (this.kind === 41) if (this.params.length === 1) p.box(this.params[0]);
else p.box(this.params[0], this.params[1], this.params[2]);
else if (this.kind === 40) p.sphere(this.params[0])
},
pre: function() {
if (this.matrix) {
p.pushMatrix();
curContext.transform(this.matrix.elements[0], this.matrix.elements[3], this.matrix.elements[1], this.matrix.elements[4], this.matrix.elements[2], this.matrix.elements[5])
}
if (this.style) {
p.pushStyle();
this.styles()
}
},
post: function() {
if (this.matrix) p.popMatrix();
if (this.style) p.popStyle()
},
styles: function() {
if (this.stroke) {
p.stroke(this.strokeColor);
p.strokeWeight(this.strokeWeight);
p.strokeCap(this.strokeCap);
p.strokeJoin(this.strokeJoin)
} else p.noStroke();
if (this.fill) p.fill(this.fillColor);
else p.noFill()
},
getChild: function(child) {
var i, j;
if (typeof child === "number") return this.children[child];
var found;
if (child === "" || this.name === child) return this;
if (this.nameTable.length > 0) {
for (i = 0, j = this.nameTable.length; i < j || found; i++) if (this.nameTable[i].getName === child) {
found = this.nameTable[i];
break
}
if (found) return found
}
for (i = 0, j = this.children.length; i < j; i++) {
found = this.children[i].getChild(child);
if (found) return found
}
return null
},
getChildCount: function() {
return this.children.length
},
addChild: function(child) {
this.children.push(child);
child.parent = this;
if (child.getName() !== null) this.addName(child.getName(), child)
},
addName: function(name, shape) {
if (this.parent !== null) this.parent.addName(name, shape);
else this.nameTable.push([name, shape])
},
translate: function() {
if (arguments.length === 2) {
this.checkMatrix(2);
this.matrix.translate(arguments[0], arguments[1])
} else {
this.checkMatrix(3);
this.matrix.translate(arguments[0], arguments[1], 0)
}
},
checkMatrix: function(dimensions) {
if (this.matrix === null) if (dimensions === 2) this.matrix = new p.PMatrix2D;
else this.matrix = new p.PMatrix3D;
else if (dimensions === 3 && this.matrix instanceof p.PMatrix2D) this.matrix = new p.PMatrix3D
},
rotateX: function(angle) {
this.rotate(angle, 1, 0, 0)
},
rotateY: function(angle) {
this.rotate(angle, 0, 1, 0)
},
rotateZ: function(angle) {
this.rotate(angle, 0, 0, 1)
},
rotate: function() {
if (arguments.length === 1) {
this.checkMatrix(2);
this.matrix.rotate(arguments[0])
} else {
this.checkMatrix(3);
this.matrix.rotate(arguments[0], arguments[1], arguments[2], arguments[3])
}
},
scale: function() {
if (arguments.length === 2) {
this.checkMatrix(2);
this.matrix.scale(arguments[0], arguments[1])
} else if (arguments.length === 3) {
this.checkMatrix(2);
this.matrix.scale(arguments[0], arguments[1], arguments[2])
} else {
this.checkMatrix(2);
this.matrix.scale(arguments[0])
}
},
resetMatrix: function() {
this.checkMatrix(2);
this.matrix.reset()
},
applyMatrix: function(matrix) {
if (arguments.length === 1) this.applyMatrix(matrix.elements[0], matrix.elements[1], 0, matrix.elements[2], matrix.elements[3], matrix.elements[4], 0, matrix.elements[5], 0, 0, 1, 0, 0, 0, 0, 1);
else if (arguments.length === 6) {
this.checkMatrix(2);
this.matrix.apply(arguments[0], arguments[1], arguments[2], 0, arguments[3], arguments[4], arguments[5], 0, 0, 0, 1, 0, 0, 0, 0, 1)
} else if (arguments.length === 16) {
this.checkMatrix(3);
this.matrix.apply(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14], arguments[15])
}
}
};
var PShapeSVG = p.PShapeSVG = function() {
p.PShape.call(this);
if (arguments.length === 1) {
this.element = arguments[0];
this.vertexCodes = [];
this.vertices = [];
this.opacity = 1;
this.stroke = false;
this.strokeColor = 4278190080;
this.strokeWeight = 1;
this.strokeCap = 'butt';
this.strokeJoin = 'miter';
this.strokeGradient = null;
this.strokeGradientPaint = null;
this.strokeName = null;
this.strokeOpacity = 1;
this.fill = true;
this.fillColor = 4278190080;
this.fillGradient = null;
this.fillGradientPaint = null;
this.fillName = null;
this.fillOpacity = 1;
if (this.element.getName() !== "svg") throw "root is not