Skip to content

Instantly share code, notes, and snippets.

@njcray
Created January 23, 2018 00:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save njcray/60000735c813d617c94197e96749246b to your computer and use it in GitHub Desktop.
Save njcray/60000735c813d617c94197e96749246b to your computer and use it in GitHub Desktop.
QVM 3D Contingency Table Visualisation
<html><head>
<TITLE>QVM Contingency Table</TITLE>
</head>
<body onload="rgl.start();">
<div align="center">
<script>/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Copyright (2016) Duncan Murdoch - fixed CanvasMatrix4.ortho,
* cleaned up.
*/
/*
CanvasMatrix4 class
This class implements a 4x4 matrix. It has functions which
duplicate the functionality of the OpenGL matrix stack and
glut functions.
IDL:
[
Constructor(in CanvasMatrix4 matrix), // copy passed matrix into new CanvasMatrix4
Constructor(in sequence<float> array) // create new CanvasMatrix4 with 16 floats (row major)
Constructor() // create new CanvasMatrix4 with identity matrix
]
interface CanvasMatrix4 {
attribute float m11;
attribute float m12;
attribute float m13;
attribute float m14;
attribute float m21;
attribute float m22;
attribute float m23;
attribute float m24;
attribute float m31;
attribute float m32;
attribute float m33;
attribute float m34;
attribute float m41;
attribute float m42;
attribute float m43;
attribute float m44;
void load(in CanvasMatrix4 matrix); // copy the values from the passed matrix
void load(in sequence<float> array); // copy 16 floats into the matrix
sequence<float> getAsArray(); // return the matrix as an array of 16 floats
WebGLFloatArray getAsCanvasFloatArray(); // return the matrix as a WebGLFloatArray with 16 values
void makeIdentity(); // replace the matrix with identity
void transpose(); // replace the matrix with its transpose
void invert(); // replace the matrix with its inverse
void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
void scale(in float x, in float y, in float z); // multiply the matrix by passed scale values on the right
void rotate(in float angle, // multiply the matrix by passed rotation values on the right
in float x, in float y, in float z); // (angle is in degrees)
void multRight(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the right
void multLeft(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the left
void ortho(in float left, in float right, // multiply the matrix by the passed ortho values on the right
in float bottom, in float top,
in float near, in float far);
void frustum(in float left, in float right, // multiply the matrix by the passed frustum values on the right
in float bottom, in float top,
in float near, in float far);
void perspective(in float fovy, in float aspect, // multiply the matrix by the passed perspective values on the right
in float zNear, in float zFar);
void lookat(in float eyex, in float eyey, in float eyez, // multiply the matrix by the passed lookat
in float ctrx, in float ctry, in float ctrz, // values on the right
in float upx, in float upy, in float upz);
}
*/
CanvasMatrix4 = function(m)
{
if (typeof m == 'object') {
if ("length" in m && m.length >= 16) {
this.load(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
return;
}
else if (m instanceof CanvasMatrix4) {
this.load(m);
return;
}
}
this.makeIdentity();
};
CanvasMatrix4.prototype.load = function()
{
if (arguments.length == 1 && typeof arguments[0] == 'object') {
var matrix = arguments[0];
if ("length" in matrix && matrix.length == 16) {
this.m11 = matrix[0];
this.m12 = matrix[1];
this.m13 = matrix[2];
this.m14 = matrix[3];
this.m21 = matrix[4];
this.m22 = matrix[5];
this.m23 = matrix[6];
this.m24 = matrix[7];
this.m31 = matrix[8];
this.m32 = matrix[9];
this.m33 = matrix[10];
this.m34 = matrix[11];
this.m41 = matrix[12];
this.m42 = matrix[13];
this.m43 = matrix[14];
this.m44 = matrix[15];
return;
}
if (arguments[0] instanceof CanvasMatrix4) {
this.m11 = matrix.m11;
this.m12 = matrix.m12;
this.m13 = matrix.m13;
this.m14 = matrix.m14;
this.m21 = matrix.m21;
this.m22 = matrix.m22;
this.m23 = matrix.m23;
this.m24 = matrix.m24;
this.m31 = matrix.m31;
this.m32 = matrix.m32;
this.m33 = matrix.m33;
this.m34 = matrix.m34;
this.m41 = matrix.m41;
this.m42 = matrix.m42;
this.m43 = matrix.m43;
this.m44 = matrix.m44;
return;
}
}
this.makeIdentity();
};
CanvasMatrix4.prototype.getAsArray = function()
{
return [
this.m11, this.m12, this.m13, this.m14,
this.m21, this.m22, this.m23, this.m24,
this.m31, this.m32, this.m33, this.m34,
this.m41, this.m42, this.m43, this.m44
];
};
CanvasMatrix4.prototype.getAsWebGLFloatArray = function()
{
return new WebGLFloatArray(this.getAsArray());
};
CanvasMatrix4.prototype.makeIdentity = function()
{
this.m11 = 1;
this.m12 = 0;
this.m13 = 0;
this.m14 = 0;
this.m21 = 0;
this.m22 = 1;
this.m23 = 0;
this.m24 = 0;
this.m31 = 0;
this.m32 = 0;
this.m33 = 1;
this.m34 = 0;
this.m41 = 0;
this.m42 = 0;
this.m43 = 0;
this.m44 = 1;
};
CanvasMatrix4.prototype.transpose = function()
{
var tmp = this.m12;
this.m12 = this.m21;
this.m21 = tmp;
tmp = this.m13;
this.m13 = this.m31;
this.m31 = tmp;
tmp = this.m14;
this.m14 = this.m41;
this.m41 = tmp;
tmp = this.m23;
this.m23 = this.m32;
this.m32 = tmp;
tmp = this.m24;
this.m24 = this.m42;
this.m42 = tmp;
tmp = this.m34;
this.m34 = this.m43;
this.m43 = tmp;
};
CanvasMatrix4.prototype.invert = function()
{
// Calculate the 4x4 determinant
// If the determinant is zero,
// then the inverse matrix is not unique.
var det = this._determinant4x4();
if (Math.abs(det) < 1e-8)
return null;
this._makeAdjoint();
// Scale the adjoint matrix to get the inverse
this.m11 /= det;
this.m12 /= det;
this.m13 /= det;
this.m14 /= det;
this.m21 /= det;
this.m22 /= det;
this.m23 /= det;
this.m24 /= det;
this.m31 /= det;
this.m32 /= det;
this.m33 /= det;
this.m34 /= det;
this.m41 /= det;
this.m42 /= det;
this.m43 /= det;
this.m44 /= det;
};
CanvasMatrix4.prototype.translate = function(x,y,z)
{
if (x === undefined)
x = 0;
if (y === undefined)
y = 0;
if (z === undefined)
z = 0;
var matrix = new CanvasMatrix4();
matrix.m41 = x;
matrix.m42 = y;
matrix.m43 = z;
this.multRight(matrix);
};
CanvasMatrix4.prototype.scale = function(x,y,z)
{
if (x === undefined)
x = 1;
if (z === undefined) {
if (y === undefined) {
y = x;
z = x;
}
else
z = 1;
}
else if (y === undefined)
y = x;
var matrix = new CanvasMatrix4();
matrix.m11 = x;
matrix.m22 = y;
matrix.m33 = z;
this.multRight(matrix);
};
CanvasMatrix4.prototype.rotate = function(angle,x,y,z)
{
// angles are in degrees. Switch to radians
angle = angle / 180 * Math.PI;
angle /= 2;
var sinA = Math.sin(angle);
var cosA = Math.cos(angle);
var sinA2 = sinA * sinA;
// normalize
var length = Math.sqrt(x * x + y * y + z * z);
if (length === 0) {
// bad vector, just use something reasonable
x = 0;
y = 0;
z = 1;
} else if (length != 1) {
x /= length;
y /= length;
z /= length;
}
var mat = new CanvasMatrix4();
// optimize case where axis is along major axis
if (x == 1 && y === 0 && z === 0) {
mat.m11 = 1;
mat.m12 = 0;
mat.m13 = 0;
mat.m21 = 0;
mat.m22 = 1 - 2 * sinA2;
mat.m23 = 2 * sinA * cosA;
mat.m31 = 0;
mat.m32 = -2 * sinA * cosA;
mat.m33 = 1 - 2 * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else if (x === 0 && y == 1 && z === 0) {
mat.m11 = 1 - 2 * sinA2;
mat.m12 = 0;
mat.m13 = -2 * sinA * cosA;
mat.m21 = 0;
mat.m22 = 1;
mat.m23 = 0;
mat.m31 = 2 * sinA * cosA;
mat.m32 = 0;
mat.m33 = 1 - 2 * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else if (x === 0 && y === 0 && z == 1) {
mat.m11 = 1 - 2 * sinA2;
mat.m12 = 2 * sinA * cosA;
mat.m13 = 0;
mat.m21 = -2 * sinA * cosA;
mat.m22 = 1 - 2 * sinA2;
mat.m23 = 0;
mat.m31 = 0;
mat.m32 = 0;
mat.m33 = 1;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else {
var x2 = x*x;
var y2 = y*y;
var z2 = z*z;
mat.m11 = 1 - 2 * (y2 + z2) * sinA2;
mat.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
mat.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
mat.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
mat.m22 = 1 - 2 * (z2 + x2) * sinA2;
mat.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
mat.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
mat.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
mat.m33 = 1 - 2 * (x2 + y2) * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
}
this.multRight(mat);
};
CanvasMatrix4.prototype.multRight = function(mat)
{
var m11 = (this.m11 * mat.m11 + this.m12 * mat.m21 +
this.m13 * mat.m31 + this.m14 * mat.m41);
var m12 = (this.m11 * mat.m12 + this.m12 * mat.m22 +
this.m13 * mat.m32 + this.m14 * mat.m42);
var m13 = (this.m11 * mat.m13 + this.m12 * mat.m23 +
this.m13 * mat.m33 + this.m14 * mat.m43);
var m14 = (this.m11 * mat.m14 + this.m12 * mat.m24 +
this.m13 * mat.m34 + this.m14 * mat.m44);
var m21 = (this.m21 * mat.m11 + this.m22 * mat.m21 +
this.m23 * mat.m31 + this.m24 * mat.m41);
var m22 = (this.m21 * mat.m12 + this.m22 * mat.m22 +
this.m23 * mat.m32 + this.m24 * mat.m42);
var m23 = (this.m21 * mat.m13 + this.m22 * mat.m23 +
this.m23 * mat.m33 + this.m24 * mat.m43);
var m24 = (this.m21 * mat.m14 + this.m22 * mat.m24 +
this.m23 * mat.m34 + this.m24 * mat.m44);
var m31 = (this.m31 * mat.m11 + this.m32 * mat.m21 +
this.m33 * mat.m31 + this.m34 * mat.m41);
var m32 = (this.m31 * mat.m12 + this.m32 * mat.m22 +
this.m33 * mat.m32 + this.m34 * mat.m42);
var m33 = (this.m31 * mat.m13 + this.m32 * mat.m23 +
this.m33 * mat.m33 + this.m34 * mat.m43);
var m34 = (this.m31 * mat.m14 + this.m32 * mat.m24 +
this.m33 * mat.m34 + this.m34 * mat.m44);
var m41 = (this.m41 * mat.m11 + this.m42 * mat.m21 +
this.m43 * mat.m31 + this.m44 * mat.m41);
var m42 = (this.m41 * mat.m12 + this.m42 * mat.m22 +
this.m43 * mat.m32 + this.m44 * mat.m42);
var m43 = (this.m41 * mat.m13 + this.m42 * mat.m23 +
this.m43 * mat.m33 + this.m44 * mat.m43);
var m44 = (this.m41 * mat.m14 + this.m42 * mat.m24 +
this.m43 * mat.m34 + this.m44 * mat.m44);
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m14 = m14;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m24 = m24;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
this.m34 = m34;
this.m41 = m41;
this.m42 = m42;
this.m43 = m43;
this.m44 = m44;
};
CanvasMatrix4.prototype.multLeft = function(mat)
{
var m11 = (mat.m11 * this.m11 + mat.m12 * this.m21 +
mat.m13 * this.m31 + mat.m14 * this.m41);
var m12 = (mat.m11 * this.m12 + mat.m12 * this.m22 +
mat.m13 * this.m32 + mat.m14 * this.m42);
var m13 = (mat.m11 * this.m13 + mat.m12 * this.m23 +
mat.m13 * this.m33 + mat.m14 * this.m43);
var m14 = (mat.m11 * this.m14 + mat.m12 * this.m24 +
mat.m13 * this.m34 + mat.m14 * this.m44);
var m21 = (mat.m21 * this.m11 + mat.m22 * this.m21 +
mat.m23 * this.m31 + mat.m24 * this.m41);
var m22 = (mat.m21 * this.m12 + mat.m22 * this.m22 +
mat.m23 * this.m32 + mat.m24 * this.m42);
var m23 = (mat.m21 * this.m13 + mat.m22 * this.m23 +
mat.m23 * this.m33 + mat.m24 * this.m43);
var m24 = (mat.m21 * this.m14 + mat.m22 * this.m24 +
mat.m23 * this.m34 + mat.m24 * this.m44);
var m31 = (mat.m31 * this.m11 + mat.m32 * this.m21 +
mat.m33 * this.m31 + mat.m34 * this.m41);
var m32 = (mat.m31 * this.m12 + mat.m32 * this.m22 +
mat.m33 * this.m32 + mat.m34 * this.m42);
var m33 = (mat.m31 * this.m13 + mat.m32 * this.m23 +
mat.m33 * this.m33 + mat.m34 * this.m43);
var m34 = (mat.m31 * this.m14 + mat.m32 * this.m24 +
mat.m33 * this.m34 + mat.m34 * this.m44);
var m41 = (mat.m41 * this.m11 + mat.m42 * this.m21 +
mat.m43 * this.m31 + mat.m44 * this.m41);
var m42 = (mat.m41 * this.m12 + mat.m42 * this.m22 +
mat.m43 * this.m32 + mat.m44 * this.m42);
var m43 = (mat.m41 * this.m13 + mat.m42 * this.m23 +
mat.m43 * this.m33 + mat.m44 * this.m43);
var m44 = (mat.m41 * this.m14 + mat.m42 * this.m24 +
mat.m43 * this.m34 + mat.m44 * this.m44);
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m14 = m14;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m24 = m24;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
this.m34 = m34;
this.m41 = m41;
this.m42 = m42;
this.m43 = m43;
this.m44 = m44;
};
CanvasMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
{
var tx = (left + right) / (left - right);
var ty = (top + bottom) / (bottom - top);
var tz = (far + near) / (near - far);
var matrix = new CanvasMatrix4();
matrix.m11 = 2 / (right - left);
matrix.m12 = 0;
matrix.m13 = 0;
matrix.m14 = 0;
matrix.m21 = 0;
matrix.m22 = 2 / (top - bottom);
matrix.m23 = 0;
matrix.m24 = 0;
matrix.m31 = 0;
matrix.m32 = 0;
matrix.m33 = -2 / (far - near);
matrix.m34 = 0;
matrix.m41 = tx;
matrix.m42 = ty;
matrix.m43 = tz;
matrix.m44 = 1;
this.multRight(matrix);
};
CanvasMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
{
var matrix = new CanvasMatrix4();
var A = (right + left) / (right - left);
var B = (top + bottom) / (top - bottom);
var C = -(far + near) / (far - near);
var D = -(2 * far * near) / (far - near);
matrix.m11 = (2 * near) / (right - left);
matrix.m12 = 0;
matrix.m13 = 0;
matrix.m14 = 0;
matrix.m21 = 0;
matrix.m22 = 2 * near / (top - bottom);
matrix.m23 = 0;
matrix.m24 = 0;
matrix.m31 = A;
matrix.m32 = B;
matrix.m33 = C;
matrix.m34 = -1;
matrix.m41 = 0;
matrix.m42 = 0;
matrix.m43 = D;
matrix.m44 = 0;
this.multRight(matrix);
};
CanvasMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
{
var top = Math.tan(fovy * Math.PI / 360) * zNear;
var bottom = -top;
var left = aspect * bottom;
var right = aspect * top;
this.frustum(left, right, bottom, top, zNear, zFar);
};
CanvasMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
{
var matrix = new CanvasMatrix4();
// Make rotation matrix
// Z vector
var zx = eyex - centerx;
var zy = eyey - centery;
var zz = eyez - centerz;
var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
if (mag) {
zx /= mag;
zy /= mag;
zz /= mag;
}
// Y vector
var yx = upx;
var yy = upy;
var yz = upz;
// X vector = Y cross Z
xx = yy * zz - yz * zy;
xy = -yx * zz + yz * zx;
xz = yx * zy - yy * zx;
// Recompute Y = Z cross X
yx = zy * xz - zz * xy;
yy = -zx * xz + zz * xx;
yx = zx * xy - zy * xx;
// cross product gives area of parallelogram, which is < 1.0 for
// non-perpendicular unit-length vectors; so normalize x, y here
mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
if (mag) {
xx /= mag;
xy /= mag;
xz /= mag;
}
mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
if (mag) {
yx /= mag;
yy /= mag;
yz /= mag;
}
matrix.m11 = xx;
matrix.m12 = xy;
matrix.m13 = xz;
matrix.m14 = 0;
matrix.m21 = yx;
matrix.m22 = yy;
matrix.m23 = yz;
matrix.m24 = 0;
matrix.m31 = zx;
matrix.m32 = zy;
matrix.m33 = zz;
matrix.m34 = 0;
matrix.m41 = 0;
matrix.m42 = 0;
matrix.m43 = 0;
matrix.m44 = 1;
matrix.translate(-eyex, -eyey, -eyez);
this.multRight(matrix);
};
// Support functions
CanvasMatrix4.prototype._determinant2x2 = function(a, b, c, d)
{
return a * d - b * c;
};
CanvasMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
{
return a1 * this._determinant2x2(b2, b3, c2, c3) -
b1 * this._determinant2x2(a2, a3, c2, c3) +
c1 * this._determinant2x2(a2, a3, b2, b3);
};
CanvasMatrix4.prototype._determinant4x4 = function()
{
var a1 = this.m11;
var b1 = this.m12;
var c1 = this.m13;
var d1 = this.m14;
var a2 = this.m21;
var b2 = this.m22;
var c2 = this.m23;
var d2 = this.m24;
var a3 = this.m31;
var b3 = this.m32;
var c3 = this.m33;
var d3 = this.m34;
var a4 = this.m41;
var b4 = this.m42;
var c4 = this.m43;
var d4 = this.m44;
return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
};
CanvasMatrix4.prototype._makeAdjoint = function()
{
var a1 = this.m11;
var b1 = this.m12;
var c1 = this.m13;
var d1 = this.m14;
var a2 = this.m21;
var b2 = this.m22;
var c2 = this.m23;
var d2 = this.m24;
var a3 = this.m31;
var b3 = this.m32;
var c3 = this.m33;
var d3 = this.m34;
var a4 = this.m41;
var b4 = this.m42;
var c4 = this.m43;
var d4 = this.m44;
// Row column labeling reversed since we transpose rows & columns
this.m11 = this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
this.m21 = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
this.m31 = this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
this.m41 = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
this.m12 = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
this.m22 = this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
this.m32 = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
this.m42 = this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
this.m13 = this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
this.m23 = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
this.m33 = this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
this.m43 = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
this.m14 = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
this.m24 = this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
this.m34 = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
this.m44 = this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
};</script>
<script>
rglwidgetClass = function() {
this.canvas = null;
this.userMatrix = new CanvasMatrix4();
this.types = [];
this.prMatrix = new CanvasMatrix4();
this.mvMatrix = new CanvasMatrix4();
this.vp = null;
this.prmvMatrix = null;
this.origs = null;
this.gl = null;
this.scene = null;
};
(function() {
this.multMV = function(M, v) {
return [ M.m11 * v[0] + M.m12 * v[1] + M.m13 * v[2] + M.m14 * v[3],
M.m21 * v[0] + M.m22 * v[1] + M.m23 * v[2] + M.m24 * v[3],
M.m31 * v[0] + M.m32 * v[1] + M.m33 * v[2] + M.m34 * v[3],
M.m41 * v[0] + M.m42 * v[1] + M.m43 * v[2] + M.m44 * v[3]
];
};
this.vlen = function(v) {
return Math.sqrt(this.dotprod(v, v));
};
this.dotprod = function(a, b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
};
this.xprod = function(a, b) {
return [a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]];
};
this.cbind = function(a, b) {
if (b.length < a.length)
b = this.repeatToLen(b, a.length);
else if (a.length < b.length)
a = this.repeatToLen(a, b.length);
return a.map(function(currentValue, index, array) {
return currentValue.concat(b[index]);
});
};
this.swap = function(a, i, j) {
var temp = a[i];
a[i] = a[j];
a[j] = temp;
};
this.flatten = function(a) {
return [].concat.apply([], a);
};
/* set element of 1d or 2d array as if it was flattened. Column major, zero based! */
this.setElement = function(a, i, value) {
if (Array.isArray(a[0])) {
var dim = a.length,
col = Math.floor(i/dim),
row = i % dim;
a[row][col] = value;
} else {
a[i] = value;
}
};
this.transpose = function(a) {
var newArray = [],
n = a.length,
m = a[0].length,
i;
for(i = 0; i < m; i++){
newArray.push([]);
}
for(i = 0; i < n; i++){
for(var j = 0; j < m; j++){
newArray[j].push(a[i][j]);
}
}
return newArray;
};
this.sumsq = function(x) {
var result = 0, i;
for (i=0; i < x.length; i++)
result += x[i]*x[i];
return result;
};
this.toCanvasMatrix4 = function(mat) {
if (mat instanceof CanvasMatrix4)
return mat;
var result = new CanvasMatrix4();
mat = this.flatten(this.transpose(mat));
result.load(mat);
return result;
};
this.stringToRgb = function(s) {
s = s.replace("#", "");
var bigint = parseInt(s, 16);
return [((bigint >> 16) & 255)/255,
((bigint >> 8) & 255)/255,
(bigint & 255)/255];
};
this.componentProduct = function(x, y) {
if (typeof y === "undefined") {
this.alertOnce("Bad arg to componentProduct");
}
var result = new Float32Array(3), i;
for (i = 0; i<3; i++)
result[i] = x[i]*y[i];
return result;
};
this.getPowerOfTwo = function(value) {
var pow = 1;
while(pow<value) {
pow *= 2;
}
return pow;
};
this.unique = function(arr) {
arr = [].concat(arr);
return arr.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
};
this.repeatToLen = function(arr, len) {
arr = [].concat(arr);
while (arr.length < len/2)
arr = arr.concat(arr);
return arr.concat(arr.slice(0, len - arr.length));
};
this.alertOnce = function(msg) {
if (typeof this.alerted !== "undefined")
return;
this.alerted = true;
alert(msg);
};
this.f_is_lit = 1;
this.f_is_smooth = 2;
this.f_has_texture = 4;
this.f_is_indexed = 8;
this.f_depth_sort = 16;
this.f_fixed_quads = 32;
this.f_is_transparent = 64;
this.f_is_lines = 128;
this.f_sprites_3d = 256;
this.f_sprite_3d = 512;
this.f_is_subscene = 1024;
this.f_is_clipplanes = 2048;
this.f_fixed_size = 4096;
this.f_is_points = 8192;
this.f_is_twosided = 16384;
this.whichList = function(id) {
var obj = this.getObj(id),
flags = obj.flags;
if (obj.type === "light")
return "lights";
if (flags & this.f_is_subscene)
return "subscenes";
if (flags & this.f_is_clipplanes)
return "clipplanes";
if (flags & this.f_is_transparent)
return "transparent";
return "opaque";
};
this.getObj = function(id) {
if (typeof id !== "number") {
this.alertOnce("getObj id is "+typeof id);
}
return this.scene.objects[id];
};
this.getIdsByType = function(type, subscene) {
var
result = [], i, self = this;
if (typeof subscene === "undefined") {
Object.keys(this.scene.objects).forEach(
function(key) {
key = parseInt(key, 10);
if (self.getObj(key).type === type)
result.push(key);
});
} else {
ids = this.getObj(subscene).objects;
for (i=0; i < ids.length; i++) {
if (this.getObj(ids[i]).type === type) {
result.push(ids[i]);
}
}
}
return result;
};
this.getMaterial = function(id, property) {
var obj = this.getObj(id),
mat = obj.material[property];
if (typeof mat === "undefined")
mat = this.scene.material[property];
return mat;
};
this.inSubscene = function(id, subscene) {
return this.getObj(subscene).objects.indexOf(id) > -1;
};
this.addToSubscene = function(id, subscene) {
var thelist,
thesub = this.getObj(subscene),
ids = [id],
obj = this.getObj(id), i;
if (typeof obj.newIds !== "undefined") {
ids = ids.concat(obj.newIds);
}
for (i = 0; i < ids.length; i++) {
id = ids[i];
if (thesub.objects.indexOf(id) == -1) {
thelist = this.whichList(id);
thesub.objects.push(id);
thesub[thelist].push(id);
}
}
};
this.delFromSubscene = function(id, subscene) {
var thelist,
thesub = this.getObj(subscene),
obj = this.getObj(id),
ids = [id], i;
if (typeof obj.newIds !== "undefined")
ids = ids.concat(obj.newIds);
for (j=0; j<ids.length;j++) {
id = ids[j];
i = thesub.objects.indexOf(id);
if (i > -1) {
thesub.objects.splice(i, 1);
thelist = this.whichList(id);
i = thesub[thelist].indexOf(id);
thesub[thelist].splice(i, 1);
}
}
};
this.setSubsceneEntries = function(ids, subsceneid) {
var sub = this.getObj(subsceneid);
sub.objects = ids;
this.initSubscene(subsceneid);
};
this.getSubsceneEntries = function(subscene) {
return this.getObj(subscene).objects;
};
this.getChildSubscenes = function(subscene) {
return this.getObj(subscene).subscenes;
};
this.startDrawing = function() {
var value = this.drawing;
this.drawing = true;
return value;
};
this.stopDrawing = function(saved) {
this.drawing = saved;
if (!saved && this.gl && this.gl.isContextLost())
this.restartCanvas();
};
this.getVertexShader = function(id) {
var obj = this.getObj(id),
userShader = obj.userVertexShader,
flags = obj.flags,
type = obj.type,
is_lit = flags & this.f_is_lit,
has_texture = flags & this.f_has_texture,
fixed_quads = flags & this.f_fixed_quads,
sprites_3d = flags & this.f_sprites_3d,
sprite_3d = flags & this.f_sprite_3d,
nclipplanes = this.countClipplanes(),
fixed_size = flags & this.f_fixed_size,
is_points = flags & this.f_is_points,
is_twosided = flags & this.f_is_twosided,
result;
if (type === "clipplanes" || sprites_3d) return;
if (typeof userShader !== "undefined") return userShader;
result = " /* ****** "+type+" object "+id+" vertex shader ****** */\n"+
" attribute vec3 aPos;\n"+
" attribute vec4 aCol;\n"+
" uniform mat4 mvMatrix;\n"+
" uniform mat4 prMatrix;\n"+
" varying vec4 vCol;\n"+
" varying vec4 vPosition;\n";
if ((is_lit && !fixed_quads) || sprite_3d)
result = result + " attribute vec3 aNorm;\n"+
" uniform mat4 normMatrix;\n"+
" varying vec3 vNormal;\n";
if (has_texture || type === "text")
result = result + " attribute vec2 aTexcoord;\n"+
" varying vec2 vTexcoord;\n";
if (fixed_size)
result = result + " uniform vec2 textScale;\n";
if (fixed_quads)
result = result + " attribute vec2 aOfs;\n";
else if (sprite_3d)
result = result + " uniform vec3 uOrig;\n"+
" uniform float uSize;\n"+
" uniform mat4 usermat;\n";
if (is_twosided)
result = result + " attribute vec3 aPos1;\n"+
" attribute vec3 aPos2;\n"+
" varying float normz;\n";
result = result + " void main(void) {\n";
if (nclipplanes || (!fixed_quads && !sprite_3d))
result = result + " vPosition = mvMatrix * vec4(aPos, 1.);\n";
if (!fixed_quads && !sprite_3d)
result = result + " gl_Position = prMatrix * vPosition;\n";
if (is_points) {
var size = this.getMaterial(id, "size");
result = result + " gl_PointSize = "+size.toFixed(1)+";\n";
}
result = result + " vCol = aCol;\n";
if (is_lit && !fixed_quads && !sprite_3d)
result = result + " vNormal = normalize((normMatrix * vec4(aNorm, 1.)).xyz);\n";
if (has_texture || type == "text")
result = result + " vTexcoord = aTexcoord;\n";
if (fixed_size)
result = result + " vec4 pos = prMatrix * mvMatrix * vec4(aPos, 1.);\n"+
" pos = pos/pos.w;\n"+
" gl_Position = pos + vec4(aOfs*textScale, 0.,0.);\n";
if (type == "sprites" && !fixed_size)
result = result + " vec4 pos = mvMatrix * vec4(aPos, 1.);\n"+
" pos = pos/pos.w + vec4(aOfs, 0., 0.);\n"+
" gl_Position = prMatrix*pos;\n";
if (sprite_3d)
result = result + " vNormal = normalize((normMatrix * vec4(aNorm, 1.)).xyz);\n"+
" vec4 pos = mvMatrix * vec4(uOrig, 1.);\n"+
" vPosition = pos/pos.w + vec4(uSize*(vec4(aPos, 1.)*usermat).xyz,0.);\n"+
" gl_Position = prMatrix * vPosition;\n";
if (is_twosided)
result = result + " vec4 pos1 = prMatrix*(mvMatrix*vec4(aPos1, 1.));\n"+
" pos1 = pos1/pos1.w - gl_Position/gl_Position.w;\n"+
" vec4 pos2 = prMatrix*(mvMatrix*vec4(aPos2, 1.));\n"+
" pos2 = pos2/pos2.w - gl_Position/gl_Position.w;\n"+
" normz = pos1.x*pos2.y - pos1.y*pos2.x;\n";
result = result + " }\n";
// console.log(result);
return result;
};
this.getFragmentShader = function(id) {
var obj = this.getObj(id),
userShader = obj.userFragmentShader,
flags = obj.flags,
type = obj.type,
is_lit = flags & this.f_is_lit,
has_texture = flags & this.f_has_texture,
fixed_quads = flags & this.f_fixed_quads,
sprites_3d = flags & this.f_sprites_3d,
is_twosided = (flags & this.f_is_twosided) > 0,
nclipplanes = this.countClipplanes(), i,
texture_format, nlights,
result;
if (type === "clipplanes" || sprites_3d) return;
if (typeof userShader !== "undefined") return userShader;
if (has_texture)
texture_format = this.getMaterial(id, "textype");
result = "/* ****** "+type+" object "+id+" fragment shader ****** */\n"+
"#ifdef GL_ES\n"+
" precision highp float;\n"+
"#endif\n"+
" varying vec4 vCol; // carries alpha\n"+
" varying vec4 vPosition;\n";
if (has_texture || type === "text")
result = result + " varying vec2 vTexcoord;\n"+
" uniform sampler2D uSampler;\n";
if (is_lit && !fixed_quads)
result = result + " varying vec3 vNormal;\n";
for (i = 0; i < nclipplanes; i++)
result = result + " uniform vec4 vClipplane"+i+";\n";
if (is_lit) {
nlights = this.countLights();
if (nlights)
result = result + " uniform mat4 mvMatrix;\n";
else
is_lit = false;
}
if (is_lit) {
result = result + " uniform vec3 emission;\n"+
" uniform float shininess;\n";
for (i=0; i < nlights; i++) {
result = result + " uniform vec3 ambient" + i + ";\n"+
" uniform vec3 specular" + i +"; // light*material\n"+
" uniform vec3 diffuse" + i + ";\n"+
" uniform vec3 lightDir" + i + ";\n"+
" uniform bool viewpoint" + i + ";\n"+
" uniform bool finite" + i + ";\n";
}
}
if (is_twosided)
result = result + " uniform bool front;\n"+
" varying float normz;\n";
result = result + " void main(void) {\n";
for (i=0; i < nclipplanes;i++)
result = result + " if (dot(vPosition, vClipplane"+i+") < 0.0) discard;\n";
if (fixed_quads) {
result = result + " vec3 n = vec3(0., 0., 1.);\n";
} else if (is_lit) {
result = result + " vec3 n = normalize(vNormal);\n";
}
if (is_twosided) {
result = result + " if ((normz <= 0.) != front) discard;";
}
if (is_lit) {
result = result + " vec3 eye = normalize(-vPosition.xyz);\n"+
" vec3 lightdir;\n"+
" vec4 colDiff;\n"+
" vec3 halfVec;\n"+
" vec4 lighteffect = vec4(emission, 0.);\n"+
" vec3 col;\n"+
" float nDotL;\n";
if (!fixed_quads) {
result = result + " n = -faceforward(n, n, eye);\n";
}
for (i=0; i < nlights; i++) {
result = result + " colDiff = vec4(vCol.rgb * diffuse" + i + ", vCol.a);\n"+
" lightdir = lightDir" + i + ";\n"+
" if (!viewpoint" + i +")\n"+
" lightdir = (mvMatrix * vec4(lightdir, 1.)).xyz;\n"+
" if (!finite" + i + ") {\n"+
" halfVec = normalize(lightdir + eye);\n"+
" } else {\n"+
" lightdir = normalize(lightdir - vPosition.xyz);\n"+
" halfVec = normalize(lightdir + eye);\n"+
" }\n"+
" col = ambient" + i + ";\n"+
" nDotL = dot(n, lightdir);\n"+
" col = col + max(nDotL, 0.) * colDiff.rgb;\n"+
" col = col + pow(max(dot(halfVec, n), 0.), shininess) * specular" + i + ";\n"+
" lighteffect = lighteffect + vec4(col, colDiff.a);\n";
}
} else {
result = result + " vec4 colDiff = vCol;\n"+
" vec4 lighteffect = colDiff;\n";
}
if (type === "text")
result = result + " vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n";
if (has_texture) {
result = result + {
rgb: " vec4 textureColor = lighteffect*vec4(texture2D(uSampler, vTexcoord).rgb, 1.);\n",
rgba: " vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n",
alpha: " vec4 textureColor = texture2D(uSampler, vTexcoord);\n"+
" float luminance = dot(vec3(1.,1.,1.), textureColor.rgb)/3.;\n"+
" textureColor = vec4(lighteffect.rgb, lighteffect.a*luminance);\n",
luminance: " vec4 textureColor = vec4(lighteffect.rgb*dot(texture2D(uSampler, vTexcoord).rgb, vec3(1.,1.,1.))/3., lighteffect.a);\n",
"luminance.alpha":" vec4 textureColor = texture2D(uSampler, vTexcoord);\n"+
" float luminance = dot(vec3(1.,1.,1.),textureColor.rgb)/3.;\n"+
" textureColor = vec4(lighteffect.rgb*luminance, lighteffect.a*textureColor.a);\n"
}[texture_format]+
" gl_FragColor = textureColor;\n";
} else if (type === "text") {
result = result + " if (textureColor.a < 0.1)\n"+
" discard;\n"+
" else\n"+
" gl_FragColor = textureColor;\n";
} else
result = result + " gl_FragColor = lighteffect;\n";
result = result + " }\n";
// console.log(result);
return result;
};
this.getShader = function(shaderType, code) {
var gl = this.gl, shader;
shader = gl.createShader(shaderType);
gl.shaderSource(shader, code);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) && !gl.isContextLost())
alert(gl.getShaderInfoLog(shader));
return shader;
};
this.handleLoadedTexture = function(texture, textureCanvas) {
var gl = this.gl || this.initGL();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvas);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);
};
this.loadImageToTexture = function(uri, texture) {
var canvas = this.textureCanvas,
ctx = canvas.getContext("2d"),
image = new Image(),
self = this;
image.onload = function() {
var w = image.width,
h = image.height,
canvasX = self.getPowerOfTwo(w),
canvasY = self.getPowerOfTwo(h),
gl = self.gl || self.initGL(),
maxTexSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
if (maxTexSize > 4096) maxTexSize = 4096;
while (canvasX > 1 && canvasY > 1 && (canvasX > maxTexSize || canvasY > maxTexSize)) {
canvasX /= 2;
canvasY /= 2;
}
canvas.width = canvasX;
canvas.height = canvasY;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(image, 0, 0, canvasX, canvasY);
self.handleLoadedTexture(texture, canvas);
self.drawScene();
};
image.src = uri;
};
this.drawTextToCanvas = function(text, cex, family, font) {
var canvasX, canvasY,
textY,
scaling = 20,
textColour = "white",
backgroundColour = "rgba(0,0,0,0)",
canvas = this.textureCanvas,
ctx = canvas.getContext("2d"),
i, textHeights = [], widths = [], offset = 0, offsets = [],
fontStrings = [],
getFontString = function(i) {
textHeights[i] = scaling*cex[i];
var fontString = textHeights[i] + "px",
family0 = family[i],
font0 = font[i];
if (family0 === "sans")
family0 = "sans-serif";
else if (family0 === "mono")
family0 = "monospace";
fontString = fontString + " " + family0;
if (font0 === 2 || font0 === 4)
fontString = "bold " + fontString;
if (font0 === 3 || font0 === 4)
fontString = "italic " + fontString;
return fontString;
};
cex = this.repeatToLen(cex, text.length);
family = this.repeatToLen(family, text.length);
font = this.repeatToLen(font, text.length);
canvasX = 1;
for (i = 0; i < text.length; i++) {
ctx.font = fontStrings[i] = getFontString(i);
widths[i] = ctx.measureText(text[i]).width;
offset = offsets[i] = offset + 2*textHeights[i];
canvasX = (widths[i] > canvasX) ? widths[i] : canvasX;
}
canvasX = this.getPowerOfTwo(canvasX);
canvasY = this.getPowerOfTwo(offset);
canvas.width = canvasX;
canvas.height = canvasY;
ctx.fillStyle = backgroundColour;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.textBaseline = "alphabetic";
for(i = 0; i < text.length; i++) {
textY = offsets[i];
ctx.font = fontStrings[i];
ctx.fillStyle = textColour;
ctx.textAlign = "left";
ctx.fillText(text[i], 0, textY);
}
return {canvasX:canvasX, canvasY:canvasY,
widths:widths, textHeights:textHeights,
offsets:offsets};
};
this.setViewport = function(id) {
var gl = this.gl || this.initGL(),
vp = this.getObj(id).par3d.viewport,
x = vp.x*this.canvas.width,
y = vp.y*this.canvas.height,
width = vp.width*this.canvas.width,
height = vp.height*this.canvas.height;
this.vp = {x:x, y:y, width:width, height:height};
gl.viewport(x, y, width, height);
gl.scissor(x, y, width, height);
gl.enable(gl.SCISSOR_TEST);
};
this.setprMatrix = function(id) {
var subscene = this.getObj(id),
embedding = subscene.embeddings.projection;
if (embedding === "replace")
this.prMatrix.makeIdentity();
else
this.setprMatrix(subscene.parent);
if (embedding === "inherit")
return;
// This is based on the Frustum::enclose code from geom.cpp
var bbox = subscene.par3d.bbox,
scale = subscene.par3d.scale,
ranges = [(bbox[1]-bbox[0])*scale[0]/2,
(bbox[3]-bbox[2])*scale[1]/2,
(bbox[5]-bbox[4])*scale[2]/2],
radius = Math.sqrt(this.sumsq(ranges))*1.1; // A bit bigger to handle labels
if (radius <= 0) radius = 1;
var observer = subscene.par3d.observer,
distance = observer[2],
FOV = subscene.par3d.FOV, ortho = FOV === 0,
t = ortho ? 1 : Math.tan(FOV*Math.PI/360),
near = distance - radius,
far = distance + radius,
hlen,
aspect = this.vp.width/this.vp.height,
z = subscene.par3d.zoom;
if (far < 0.)
far = 1.;
if (near < far/100.)
near = far/100.;
hlen = t*near;
if (ortho) {
if (aspect > 1)
this.prMatrix.ortho(-hlen*aspect*z, hlen*aspect*z,
-hlen*z, hlen*z, near, far);
else
this.prMatrix.ortho(-hlen*z, hlen*z,
-hlen*z/aspect, hlen*z/aspect,
near, far);
} else {
if (aspect > 1)
this.prMatrix.frustum(-hlen*aspect*z, hlen*aspect*z,
-hlen*z, hlen*z, near, far);
else
this.prMatrix.frustum(-hlen*z, hlen*z,
-hlen*z/aspect, hlen*z/aspect,
near, far);
}
};
this.setmvMatrix = function(id) {
var observer = this.getObj(id).par3d.observer;
this.mvMatrix.makeIdentity();
this.setmodelMatrix(id);
this.mvMatrix.translate(-observer[0], -observer[1], -observer[2]);
};
this.setmodelMatrix = function(id) {
var subscene = this.getObj(id),
embedding = subscene.embeddings.model;
if (embedding !== "inherit") {
var scale = subscene.par3d.scale,
bbox = subscene.par3d.bbox,
center = [(bbox[0]+bbox[1])/2,
(bbox[2]+bbox[3])/2,
(bbox[4]+bbox[5])/2];
this.mvMatrix.translate(-center[0], -center[1], -center[2]);
this.mvMatrix.scale(scale[0], scale[1], scale[2]);
this.mvMatrix.multRight( subscene.par3d.userMatrix );
}
if (embedding !== "replace")
this.setmodelMatrix(subscene.parent);
};
this.setnormMatrix = function(subsceneid) {
var self = this,
recurse = function(id) {
var sub = self.getObj(id),
embedding = sub.embeddings.model;
if (embedding !== "inherit") {
var scale = sub.par3d.scale;
self.normMatrix.scale(1/scale[0], 1/scale[1], 1/scale[2]);
self.normMatrix.multRight(sub.par3d.userMatrix);
}
if (embedding !== "replace")
recurse(sub.parent);
};
self.normMatrix.makeIdentity();
recurse(subsceneid);
};
this.setprmvMatrix = function() {
this.prmvMatrix = new CanvasMatrix4( this.mvMatrix );
this.prmvMatrix.multRight( this.prMatrix );
};
this.countClipplanes = function() {
return this.countObjs("clipplanes");
};
this.countLights = function() {
return this.countObjs("light");
};
this.countObjs = function(type) {
var self = this,
bound = 0;
Object.keys(this.scene.objects).forEach(
function(key) {
if (self.getObj(parseInt(key, 10)).type === type)
bound = bound + 1;
});
return bound;
};
this.initSubscene = function(id) {
var sub = this.getObj(id),
i, obj;
if (sub.type !== "subscene")
return;
sub.par3d.userMatrix = this.toCanvasMatrix4(sub.par3d.userMatrix);
sub.par3d.listeners = [].concat(sub.par3d.listeners);
sub.backgroundId = undefined;
sub.subscenes = [];
sub.clipplanes = [];
sub.transparent = [];
sub.opaque = [];
sub.lights = [];
for (i=0; i < sub.objects.length; i++) {
obj = this.getObj(sub.objects[i]);
if (typeof obj === "undefined") {
sub.objects.splice(i, 1);
i--;
} else if (obj.type === "background")
sub.backgroundId = obj.id;
else
sub[this.whichList(obj.id)].push(obj.id);
}
};
this.copyObj = function(id, reuse) {
var obj = this.getObj(id),
prev = document.getElementById(reuse);
if (prev !== null) {
prev = prev.rglinstance;
var
prevobj = prev.getObj(id),
fields = ["flags", "type",
"colors", "vertices", "centers",
"normals", "offsets",
"texts", "cex", "family", "font", "adj",
"material",
"radii",
"texcoords",
"userMatrix", "ids",
"dim",
"par3d", "userMatrix",
"viewpoint", "finite"],
i;
for (i = 0; i < fields.length; i++) {
if (typeof prevobj[fields[i]] !== "undefined")
obj[fields[i]] = prevobj[fields[i]];
}
} else
console.warn("copyObj failed");
};
this.planeUpdateTriangles = function(id, bbox) {
var perms = [[0,0,1], [1,2,2], [2,1,0]],
x, xrow, elem, A, d, nhits, i, j, k, u, v, w, intersect, which, v0, v2, vx, reverse,
face1 = [], face2 = [], normals = [],
obj = this.getObj(id),
nPlanes = obj.normals.length;
obj.bbox = bbox;
obj.vertices = [];
obj.initialized = false;
for (elem = 0; elem < nPlanes; elem++) {
// Vertex Av = normal.getRecycled(elem);
x = [];
A = obj.normals[elem];
d = obj.offsets[elem][0];
nhits = 0;
for (i=0; i<3; i++)
for (j=0; j<2; j++)
for (k=0; k<2; k++) {
u = perms[0][i];
v = perms[1][i];
w = perms[2][i];
if (A[w] !== 0.0) {
intersect = -(d + A[u]*bbox[j+2*u] + A[v]*bbox[k+2*v])/A[w];
if (bbox[2*w] < intersect && intersect < bbox[1+2*w]) {
xrow = [];
xrow[u] = bbox[j+2*u];
xrow[v] = bbox[k+2*v];
xrow[w] = intersect;
x.push(xrow);
face1[nhits] = j + 2*u;
face2[nhits] = k + 2*v;
nhits++;
}
}
}
if (nhits > 3) {
/* Re-order the intersections so the triangles work */
for (i=0; i<nhits-2; i++) {
which = 0; /* initialize to suppress warning */
for (j=i+1; j<nhits; j++) {
if (face1[i] == face1[j] || face1[i] == face2[j] ||
face2[i] == face1[j] || face2[i] == face2[j] ) {
which = j;
break;
}
}
if (which > i+1) {
this.swap(x, i+1, which);
this.swap(face1, i+1, which);
this.swap(face2, i+1, which);
}
}
}
if (nhits >= 3) {
/* Put in order so that the normal points out the FRONT of the faces */
v0 = [x[0][0] - x[1][0] , x[0][1] - x[1][1], x[0][2] - x[1][2]];
v2 = [x[2][0] - x[1][0] , x[2][1] - x[1][1], x[2][2] - x[1][2]];
/* cross-product */
vx = this.xprod(v0, v2);
reverse = this.dotprod(vx, A) > 0;
for (i=0; i<nhits-2; i++) {
obj.vertices.push(x[0]);
normals.push(A);
for (j=1; j<3; j++) {
obj.vertices.push(x[i + (reverse ? 3-j : j)]);
normals.push(A);
}
}
}
}
obj.pnormals = normals;
};
this.initObj = function(id) {
var obj = this.getObj(id),
flags = obj.flags,
type = obj.type,
is_indexed = flags & this.f_is_indexed,
is_lit = flags & this.f_is_lit,
has_texture = flags & this.f_has_texture,
fixed_quads = flags & this.f_fixed_quads,
depth_sort = flags & this.f_depth_sort,
sprites_3d = flags & this.f_sprites_3d,
sprite_3d = flags & this.f_sprite_3d,
fixed_size = flags & this.f_fixed_size,
is_twosided = (flags & this.f_is_twosided) > 0,
gl = this.gl || this.initGL(),
texinfo, drawtype, nclipplanes, f, nrows,
i,j,v,v1,v2, mat, uri, matobj, pass, pmode,
dim, nx, nz, attr;
if (typeof id !== "number") {
this.alertOnce("initObj id is "+typeof id);
}
obj.initialized = true;
if (type === "bboxdeco" || type === "subscene")
return;
if (type === "light") {
obj.ambient = new Float32Array(obj.colors[0].slice(0,3));
obj.diffuse = new Float32Array(obj.colors[1].slice(0,3));
obj.specular = new Float32Array(obj.colors[2].slice(0,3));
obj.lightDir = new Float32Array(obj.vertices[0]);
return;
}
if (type === "clipplanes") {
obj.vClipplane = this.flatten(this.cbind(obj.normals, obj.offsets));
return;
}
if (type == "background" && typeof obj.ids !== "undefined") {
obj.quad = this.flatten([].concat(obj.ids));
return;
}
if (typeof obj.vertices === "undefined")
obj.vertices = [];
v = obj.vertices;
obj.vertexCount = v.length;
if (!obj.vertexCount) return;
if (is_twosided) {
if (typeof obj.userAttributes === "undefined")
obj.userAttributes = {};
v1 = Array(v.length);
v2 = Array(v.length);
if (obj.type == "triangles" || obj.type == "quads") {
if (obj.type == "triangles")
nrow = 3;
else
nrow = 4;
for (i=0; i<Math.floor(v.length/nrow); i++)
for (j=0; j<nrow; j++) {
v1[nrow*i + j] = v[nrow*i + ((j+1) % nrow)];
v2[nrow*i + j] = v[nrow*i + ((j+2) % nrow)];
}
} else if (obj.type == "surface") {
dim = obj.dim[0];
nx = dim[0];
nz = dim[1];
for (j=0; j<nx; j++) {
for (i=0; i<nz; i++) {
if (i+1 < nz && j+1 < nx) {
v2[j + nx*i] = v[j + nx*(i+1)];
v1[j + nx*i] = v[j+1 + nx*(i+1)];
} else if (i+1 < nz) {
v2[j + nx*i] = v[j-1 + nx*i];
v1[j + nx*i] = v[j + nx*(i+1)];
} else {
v2[j + nx*i] = v[j + nx*(i-1)];
v1[j + nx*i] = v[j-1 + nx*(i-1)];
}
}
}
}
obj.userAttributes.aPos1 = v1;
obj.userAttributes.aPos2 = v2;
}
if (!sprites_3d) {
if (gl.isContextLost()) return;
obj.prog = gl.createProgram();
gl.attachShader(obj.prog, this.getShader( gl.VERTEX_SHADER,
this.getVertexShader(id) ));
gl.attachShader(obj.prog, this.getShader( gl.FRAGMENT_SHADER,
this.getFragmentShader(id) ));
// Force aPos to location 0, aCol to location 1
gl.bindAttribLocation(obj.prog, 0, "aPos");
gl.bindAttribLocation(obj.prog, 1, "aCol");
gl.linkProgram(obj.prog);
var linked = gl.getProgramParameter(obj.prog, gl.LINK_STATUS);
if (!linked) {
// An error occurred while linking
var lastError = gl.getProgramInfoLog(obj.prog);
console.warn("Error in program linking:" + lastError);
gl.deleteProgram(obj.prog);
return;
}
}
if (type === "text") {
texinfo = this.drawTextToCanvas(obj.texts,
this.flatten(obj.cex),
this.flatten(obj.family),
this.flatten(obj.family));
}
if (fixed_quads && !sprites_3d) {
obj.ofsLoc = gl.getAttribLocation(obj.prog, "aOfs");
}
if (sprite_3d) {
obj.origLoc = gl.getUniformLocation(obj.prog, "uOrig");
obj.sizeLoc = gl.getUniformLocation(obj.prog, "uSize");
obj.usermatLoc = gl.getUniformLocation(obj.prog, "usermat");
}
if (has_texture || type == "text") {
obj.texture = gl.createTexture();
obj.texLoc = gl.getAttribLocation(obj.prog, "aTexcoord");
obj.sampler = gl.getUniformLocation(obj.prog, "uSampler");
}
if (has_texture) {
mat = obj.material;
if (typeof mat.uri !== "undefined")
uri = mat.uri;
else if (typeof mat.uriElementId === "undefined") {
matobj = this.getObj(mat.uriId);
if (typeof matobj !== "undefined") {
uri = matobj.material.uri;
} else {
uri = "";
}
} else
uri = document.getElementById(mat.uriElementId).rglinstance.getObj(mat.uriId).material.uri;
this.loadImageToTexture(uri, obj.texture);
}
if (type === "text") {
this.handleLoadedTexture(obj.texture, this.textureCanvas);
}
var stride = 3, nc, cofs, nofs, radofs, oofs, tofs, vnew;
nc = obj.colorCount = obj.colors.length;
if (nc > 1) {
cofs = stride;
stride = stride + 4;
v = this.cbind(v, obj.colors);
} else {
cofs = -1;
obj.onecolor = this.flatten(obj.colors);
}
if (typeof obj.normals !== "undefined") {
nofs = stride;
stride = stride + 3;
v = this.cbind(v, typeof obj.pnormals !== "undefined" ? obj.pnormals : obj.normals);
} else
nofs = -1;
if (typeof obj.radii !== "undefined") {
radofs = stride;
stride = stride + 1;
// FIXME: always concat the radii?
if (obj.radii.length === v.length) {
v = this.cbind(v, obj.radii);
} else if (obj.radii.length === 1) {
v = v.map(function(row, i, arr) { return row.concat(obj.radii[0]);});
}
} else
radofs = -1;
if (type == "sprites" && !sprites_3d) {
tofs = stride;
stride += 2;
oofs = stride;
stride += 2;
vnew = new Array(4*v.length);
var rescale = fixed_size ? 72 : 1,
size = obj.radii, s = rescale*size[0]/2;
for (i=0; i < v.length; i++) {
if (size.length > 1)
s = rescale*size[i]/2;
vnew[4*i] = v[i].concat([0,0,-s,-s]);
vnew[4*i+1]= v[i].concat([1,0, s,-s]);
vnew[4*i+2]= v[i].concat([1,1, s, s]);
vnew[4*i+3]= v[i].concat([0,1,-s, s]);
}
v = vnew;
obj.vertexCount = v.length;
} else if (type === "text") {
tofs = stride;
stride += 2;
oofs = stride;
stride += 2;
vnew = new Array(4*v.length);
for (i=0; i < v.length; i++) {
vnew[4*i] = v[i].concat([0,-0.5]).concat(obj.adj[0]);
vnew[4*i+1]= v[i].concat([1,-0.5]).concat(obj.adj[0]);
vnew[4*i+2]= v[i].concat([1, 1.5]).concat(obj.adj[0]);
vnew[4*i+3]= v[i].concat([0, 1.5]).concat(obj.adj[0]);
for (j=0; j < 4; j++) {
v1 = vnew[4*i+j];
v1[tofs+2] = 2*(v1[tofs]-v1[tofs+2])*texinfo.widths[i];
v1[tofs+3] = 2*(v1[tofs+1]-v1[tofs+3])*texinfo.textHeights[i];
v1[tofs] *= texinfo.widths[i]/texinfo.canvasX;
v1[tofs+1] = 1.0-(texinfo.offsets[i] -
v1[tofs+1]*texinfo.textHeights[i])/texinfo.canvasY;
vnew[4*i+j] = v1;
}
}
v = vnew;
obj.vertexCount = v.length;
} else if (typeof obj.texcoords !== "undefined") {
tofs = stride;
stride += 2;
oofs = -1;
v = this.cbind(v, obj.texcoords);
} else {
tofs = -1;
oofs = -1;
}
if (typeof obj.userAttributes !== "undefined") {
obj.userAttribOffsets = {};
obj.userAttribLocations = {};
obj.userAttribSizes = {};
for (attr in obj.userAttributes) {
obj.userAttribLocations[attr] = gl.getAttribLocation(obj.prog, attr);
if (obj.userAttribLocations[attr] >= 0) { // Attribute may not have been used
obj.userAttribOffsets[attr] = stride;
v = this.cbind(v, obj.userAttributes[attr]);
stride = v[0].length;
obj.userAttribSizes[attr] = stride - obj.userAttribOffsets[attr];
}
}
}
if (typeof obj.userUniforms !== "undefined") {
obj.userUniformLocations = {};
for (attr in obj.userUniforms)
obj.userUniformLocations[attr] = gl.getUniformLocation(obj.prog, attr);
}
if (stride !== v[0].length) {
this.alertOnce("problem in stride calculation");
}
obj.vOffsets = {vofs:0, cofs:cofs, nofs:nofs, radofs:radofs, oofs:oofs, tofs:tofs, stride:stride};
obj.values = new Float32Array(this.flatten(v));
if (sprites_3d) {
obj.userMatrix = new CanvasMatrix4(obj.userMatrix);
obj.objects = this.flatten([].concat(obj.ids));
is_lit = false;
}
if (is_lit && !fixed_quads) {
obj.normLoc = gl.getAttribLocation(obj.prog, "aNorm");
}
nclipplanes = this.countClipplanes();
if (nclipplanes && !sprites_3d) {
obj.clipLoc = [];
for (i=0; i < nclipplanes; i++)
obj.clipLoc[i] = gl.getUniformLocation(obj.prog,"vClipplane" + i);
}
if (is_lit) {
obj.emissionLoc = gl.getUniformLocation(obj.prog, "emission");
obj.emission = new Float32Array(this.stringToRgb(this.getMaterial(id, "emission")));
obj.shininessLoc = gl.getUniformLocation(obj.prog, "shininess");
obj.shininess = this.getMaterial(id, "shininess");
obj.nlights = this.countLights();
obj.ambientLoc = [];
obj.ambient = new Float32Array(this.stringToRgb(this.getMaterial(id, "ambient")));
obj.specularLoc = [];
obj.specular = new Float32Array(this.stringToRgb(this.getMaterial(id, "specular")));
obj.diffuseLoc = [];
obj.lightDirLoc = [];
obj.viewpointLoc = [];
obj.finiteLoc = [];
for (i=0; i < obj.nlights; i++) {
obj.ambientLoc[i] = gl.getUniformLocation(obj.prog, "ambient" + i);
obj.specularLoc[i] = gl.getUniformLocation(obj.prog, "specular" + i);
obj.diffuseLoc[i] = gl.getUniformLocation(obj.prog, "diffuse" + i);
obj.lightDirLoc[i] = gl.getUniformLocation(obj.prog, "lightDir" + i);
obj.viewpointLoc[i] = gl.getUniformLocation(obj.prog, "viewpoint" + i);
obj.finiteLoc[i] = gl.getUniformLocation(obj.prog, "finite" + i);
}
}
if (is_indexed) {
obj.f = Array(2);
for (pass = 0; pass < is_twosided + 1; pass++) {
if (type === "triangles" || type === "quads" || type === "surface")
pmode = this.getMaterial(id, (pass === 0) ? "front" : "back");
else pmode = "filled";
if (pmode === "culled")
continue;
if (pmode === "points") {
nrows = obj.vertexCount;
f = Array(nrows);
for (i=0; i < nrows; i++)
f[i] = i;
} else if ((type === "quads" || type === "text" ||
type === "sprites") && !sprites_3d) {
nrows = Math.floor(obj.vertexCount/4);
if (pmode === "filled") {
f = Array(6*nrows);
for (i=0; i < nrows; i++) {
f[6*i] = 4*i;
f[6*i+1] = 4*i + 1;
f[6*i+2] = 4*i + 2;
f[6*i+3] = 4*i;
f[6*i+4] = 4*i + 2;
f[6*i+5] = 4*i + 3;
}
} else {
f = Array(8*nrows);
for (i=0; i < nrows; i++) {
f[8*i] = 4*i;
f[8*i+1] = 4*i + 1;
f[8*i+2] = 4*i + 1;
f[8*i+3] = 4*i + 2;
f[8*i+4] = 4*i + 2;
f[8*i+5] = 4*i + 3;
f[8*i+6] = 4*i + 3;
f[8*i+7] = 4*i;
}
}
} else if (type === "triangles") {
nrows = Math.floor(obj.vertexCount/3);
if (pmode === "filled") {
f = Array(3*nrows);
for (i=0; i < f.length; i++) {
f[i] = i;
}
} else if (pmode === "lines") {
f = Array(6*nrows);
for (i=0; i < nrows; i++) {
f[6*i] = 3*i;
f[6*i + 1] = 3*i + 1;
f[6*i + 2] = 3*i + 1;
f[6*i + 3] = 3*i + 2;
f[6*i + 4] = 3*i + 2;
f[6*i + 5] = 3*i;
}
}
} else if (type === "spheres") {
nrows = obj.vertexCount;
f = Array(nrows);
for (i=0; i < f.length; i++) {
f[i] = i;
}
} else if (type === "surface") {
dim = obj.dim[0];
nx = dim[0];
nz = dim[1];
if (pmode === "filled") {
f = [];
for (j=0; j<nx-1; j++) {
for (i=0; i<nz-1; i++) {
f.push(j + nx*i,
j + nx*(i+1),
j + 1 + nx*(i+1),
j + nx*i,
j + 1 + nx*(i+1),
j + 1 + nx*i);
}
}
} else if (pmode === "lines") {
f = [];
for (j=0; j<nx; j++) {
for (i=0; i<nz; i++) {
if (i+1 < nz)
f.push(j + nx*i,
j + nx*(i+1));
if (j+1 < nx)
f.push(j + nx*i,
j+1 + nx*i);
}
}
}
}
obj.f[pass] = new Uint16Array(f);
if (depth_sort) {
drawtype = "DYNAMIC_DRAW";
} else {
drawtype = "STATIC_DRAW";
}
}
}
if (type !== "spheres" && !sprites_3d) {
obj.buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW); //
}
if (is_indexed && type !== "spheres" && !sprites_3d) {
obj.ibuf = Array(is_twosided + 1);
obj.ibuf[0] = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[0]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, obj.f[0], gl[drawtype]);
if (is_twosided) {
obj.ibuf[1] = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[1]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, obj.f[1], gl[drawtype]);
}
}
if (!sprites_3d) {
obj.mvMatLoc = gl.getUniformLocation(obj.prog, "mvMatrix");
obj.prMatLoc = gl.getUniformLocation(obj.prog, "prMatrix");
}
if (fixed_size) {
obj.textScaleLoc = gl.getUniformLocation(obj.prog, "textScale");
}
if (is_lit && !sprites_3d) {
obj.normMatLoc = gl.getUniformLocation(obj.prog, "normMatrix");
}
if (is_twosided) {
obj.frontLoc = gl.getUniformLocation(obj.prog, "front");
}
};
this.setDepthTest = function(id) {
var gl = this.gl || this.initGL(),
tests = {never: gl.NEVER,
less: gl.LESS,
equal: gl.EQUAL,
lequal:gl.LEQUAL,
greater: gl.GREATER,
notequal: gl.NOTEQUAL,
gequal: gl.GEQUAL,
always: gl.ALWAYS},
test = tests[this.getMaterial(id, "depth_test")];
gl.depthFunc(test);
};
this.mode4type = {points : "POINTS",
linestrip : "LINE_STRIP",
abclines : "LINES",
lines : "LINES",
sprites : "TRIANGLES",
planes : "TRIANGLES",
text : "TRIANGLES",
quads : "TRIANGLES",
surface : "TRIANGLES",
triangles : "TRIANGLES"};
this.drawObj = function(id, subsceneid) {
var obj = this.getObj(id),
subscene = this.getObj(subsceneid),
flags = obj.flags,
type = obj.type,
is_indexed = flags & this.f_is_indexed,
is_lit = flags & this.f_is_lit,
has_texture = flags & this.f_has_texture,
fixed_quads = flags & this.f_fixed_quads,
depth_sort = flags & this.f_depth_sort,
sprites_3d = flags & this.f_sprites_3d,
sprite_3d = flags & this.f_sprite_3d,
is_lines = flags & this.f_is_lines,
is_points = flags & this.f_is_points,
fixed_size = flags & this.f_fixed_size,
is_twosided = (flags & this.f_is_twosided) > 0,
gl = this.gl || this.initGL(),
mat,
sphereMV, baseofs, ofs, sscale, i, count, light,
faces, pass, mode, pmode, attr,
depthsort = function(i,j) { return depths[j] - depths[i]; };
if (typeof id !== "number") {
this.alertOnce("drawObj id is "+typeof id);
}
if (type === "planes") {
if (obj.bbox !== subscene.par3d.bbox || !obj.initialized) {
this.planeUpdateTriangles(id, subscene.par3d.bbox);
}
}
if (!obj.initialized)
this.initObj(id);
if (type === "clipplanes") {
count = obj.offsets.length;
var IMVClip = [];
for (i=0; i < count; i++) {
IMVClip[i] = this.multMV(this.invMatrix, obj.vClipplane.slice(4*i, 4*(i+1)));
}
obj.IMVClip = IMVClip;
return;
}
if (type === "light" || type === "bboxdeco" || !obj.vertexCount)
return;
this.setDepthTest(id);
if (sprites_3d) {
var norigs = obj.vertices.length,
savenorm = new CanvasMatrix4(this.normMatrix);
this.origs = obj.vertices;
this.usermat = new Float32Array(obj.userMatrix.getAsArray());
this.radii = obj.radii;
this.normMatrix = subscene.spriteNormmat;
for (this.iOrig=0; this.iOrig < norigs; this.iOrig++) {
for (i=0; i < obj.objects.length; i++) {
this.drawObj(obj.objects[i], subsceneid);
}
}
this.normMatrix = savenorm;
return;
} else {
gl.useProgram(obj.prog);
}
if (sprite_3d) {
gl.uniform3fv(obj.origLoc, new Float32Array(this.origs[this.iOrig]));
if (this.radii.length > 1) {
gl.uniform1f(obj.sizeLoc, this.radii[this.iOrig][0]);
} else {
gl.uniform1f(obj.sizeLoc, this.radii[0][0]);
}
gl.uniformMatrix4fv(obj.usermatLoc, false, this.usermat);
}
if (type === "spheres") {
gl.bindBuffer(gl.ARRAY_BUFFER, this.sphere.buf);
} else {
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
}
gl.uniformMatrix4fv( obj.prMatLoc, false, new Float32Array(this.prMatrix.getAsArray()) );
gl.uniformMatrix4fv( obj.mvMatLoc, false, new Float32Array(this.mvMatrix.getAsArray()) );
var clipcheck = 0,
clipplaneids = subscene.clipplanes,
clip, j;
for (i=0; i < clipplaneids.length; i++) {
clip = this.getObj(clipplaneids[i]);
for (j=0; j < clip.offsets.length; j++) {
gl.uniform4fv(obj.clipLoc[clipcheck + j], clip.IMVClip[j]);
}
clipcheck += clip.offsets.length;
}
if (typeof obj.clipLoc !== "undefined")
for (i=clipcheck; i < obj.clipLoc.length; i++)
gl.uniform4f(obj.clipLoc[i], 0,0,0,0);
if (is_lit) {
gl.uniformMatrix4fv( obj.normMatLoc, false, new Float32Array(this.normMatrix.getAsArray()) );
gl.uniform3fv( obj.emissionLoc, obj.emission);
gl.uniform1f( obj.shininessLoc, obj.shininess);
for (i=0; i < subscene.lights.length; i++) {
light = this.getObj(subscene.lights[i]);
gl.uniform3fv( obj.ambientLoc[i], this.componentProduct(light.ambient, obj.ambient));
gl.uniform3fv( obj.specularLoc[i], this.componentProduct(light.specular, obj.specular));
gl.uniform3fv( obj.diffuseLoc[i], light.diffuse);
gl.uniform3fv( obj.lightDirLoc[i], light.lightDir);
gl.uniform1i( obj.viewpointLoc[i], light.viewpoint);
gl.uniform1i( obj.finiteLoc[i], light.finite);
}
for (i=subscene.lights.length; i < obj.nlights; i++) {
gl.uniform3f( obj.ambientLoc[i], 0,0,0);
gl.uniform3f( obj.specularLoc[i], 0,0,0);
gl.uniform3f( obj.diffuseLoc[i], 0,0,0);
}
}
if (fixed_size) {
gl.uniform2f( obj.textScaleLoc, 0.75/this.vp.width, 0.75/this.vp.height);
}
gl.enableVertexAttribArray( this.posLoc );
var nc = obj.colorCount;
count = obj.vertexCount;
if (type === "spheres") {
subscene = this.getObj(subsceneid);
var scale = subscene.par3d.scale,
scount = count;
gl.vertexAttribPointer(this.posLoc, 3, gl.FLOAT, false, 4*this.sphere.vOffsets.stride, 0);
gl.enableVertexAttribArray(obj.normLoc );
gl.vertexAttribPointer(obj.normLoc, 3, gl.FLOAT, false, 4*this.sphere.vOffsets.stride, 0);
gl.disableVertexAttribArray( this.colLoc );
var sphereNorm = new CanvasMatrix4();
sphereNorm.scale(scale[0], scale[1], scale[2]);
sphereNorm.multRight(this.normMatrix);
gl.uniformMatrix4fv( obj.normMatLoc, false, new Float32Array(sphereNorm.getAsArray()) );
if (nc == 1) {
gl.vertexAttrib4fv( this.colLoc, new Float32Array(obj.onecolor));
}
if (has_texture) {
gl.enableVertexAttribArray( obj.texLoc );
gl.vertexAttribPointer(obj.texLoc, 2, gl.FLOAT, false, 4*this.sphere.vOffsets.stride,
4*this.sphere.vOffsets.tofs);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, obj.texture);
gl.uniform1i( obj.sampler, 0);
}
for (i = 0; i < scount; i++) {
sphereMV = new CanvasMatrix4();
if (depth_sort) {
baseofs = faces[i]*obj.vOffsets.stride;
} else {
baseofs = i*obj.vOffsets.stride;
}
ofs = baseofs + obj.vOffsets.radofs;
sscale = obj.values[ofs];
sphereMV.scale(sscale/scale[0], sscale/scale[1], sscale/scale[2]);
sphereMV.translate(obj.values[baseofs],
obj.values[baseofs+1],
obj.values[baseofs+2]);
sphereMV.multRight(this.mvMatrix);
gl.uniformMatrix4fv( obj.mvMatLoc, false, new Float32Array(sphereMV.getAsArray()) );
if (nc > 1) {
ofs = baseofs + obj.vOffsets.cofs;
gl.vertexAttrib4f( this.colLoc, obj.values[ofs],
obj.values[ofs+1],
obj.values[ofs+2],
obj.values[ofs+3] );
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.sphere.ibuf);
gl.drawElements(gl.TRIANGLES, this.sphere.sphereCount, gl.UNSIGNED_SHORT, 0);
}
return;
} else {
if (obj.colorCount === 1) {
gl.disableVertexAttribArray( this.colLoc );
gl.vertexAttrib4fv( this.colLoc, new Float32Array(obj.onecolor));
} else {
gl.enableVertexAttribArray( this.colLoc );
gl.vertexAttribPointer(this.colLoc, 4, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.cofs);
}
}
if (is_lit && obj.vOffsets.nofs > 0) {
gl.enableVertexAttribArray( obj.normLoc );
gl.vertexAttribPointer(obj.normLoc, 3, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.nofs);
}
if (has_texture || type === "text") {
gl.enableVertexAttribArray( obj.texLoc );
gl.vertexAttribPointer(obj.texLoc, 2, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.tofs);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, obj.texture);
gl.uniform1i( obj.sampler, 0);
}
if (fixed_quads) {
gl.enableVertexAttribArray( obj.ofsLoc );
gl.vertexAttribPointer(obj.ofsLoc, 2, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.oofs);
}
if (typeof obj.userAttributes !== "undefined") {
for (attr in obj.userAttribSizes) { // Not all attributes may have been used
gl.enableVertexAttribArray( obj.userAttribLocations[attr] );
gl.vertexAttribPointer( obj.userAttribLocations[attr], obj.userAttribSizes[attr],
gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.userAttribOffsets[attr]);
}
}
if (typeof obj.userUniforms !== "undefined") {
for (attr in obj.userUniformLocations) {
var loc = obj.userUniformLocations[attr];
if (loc !== null) {
var uniform = obj.userUniforms[attr];
if (typeof uniform.length === "undefined")
gl.uniform1f(loc, uniform);
else if (typeof uniform[0].length === "undefined") {
uniform = new Float32Array(uniform);
switch(uniform.length) {
case 2: gl.uniform2fv(loc, uniform); break;
case 3: gl.uniform3fv(loc, uniform); break;
case 4: gl.uniform4fv(loc, uniform); break;
default: console.warn("bad uniform length");
}
} else if (uniform.length == 4 && uniform[0].length == 4)
gl.uniformMatrix4fv(loc, false, new Float32Array(uniform.getAsArray()));
else
console.warn("unsupported uniform matrix");
}
}
}
for (pass = 0; pass < is_twosided + 1; pass++) {
if (type === "triangles" || type === "quads" || type === "surface")
pmode = this.getMaterial(id, (pass === 0) ? "front" : "back");
else pmode = "filled";
if (pmode === "culled")
continue;
mode = this.mode4type[type];
if (depth_sort && pmode == "filled") {// Don't try depthsorting on wireframe or points
var nfaces = obj.centers.length,
z, w, frowsize;
frowsize = Math.floor(obj.f[pass].length/nfaces);
var depths = new Float32Array(nfaces);
faces = new Array(nfaces);
for(i=0; i<nfaces; i++) {
z = this.prmvMatrix.m13*obj.centers[3*i] +
this.prmvMatrix.m23*obj.centers[3*i+1] +
this.prmvMatrix.m33*obj.centers[3*i+2] +
this.prmvMatrix.m43;
w = this.prmvMatrix.m14*obj.centers[3*i] +
this.prmvMatrix.m24*obj.centers[3*i+1] +
this.prmvMatrix.m34*obj.centers[3*i+2] +
this.prmvMatrix.m44;
depths[i] = z/w;
faces[i] = i;
}
faces.sort(depthsort);
if (type !== "spheres") {
var f = new Uint16Array(obj.f[pass].length);
for (i=0; i<nfaces; i++) {
for (j=0; j<frowsize; j++) {
f[frowsize*i + j] = obj.f[pass][frowsize*faces[i] + j];
}
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[pass]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, f, gl.DYNAMIC_DRAW);
}
}
if (is_twosided)
gl.uniform1i(obj.frontLoc, pass !== 0);
if (is_indexed && type !== "spheres") {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[pass]);
} else if (type === "spheres") {
// FIX ME!
}
if (type === "sprites" || type === "text" || type === "quads") {
count = count * 6/4;
} else if (type === "surface") {
count = obj.f[pass].length;
}
if (is_indexed) {
count = obj.f[pass].length;
if (pmode === "lines") {
mode = "LINES";
is_lines = true;
} else if (pmode === "points") {
mode = "POINTS";
}
}
if (is_lines) {
gl.lineWidth( this.getMaterial(id, "lwd") );
}
gl.vertexAttribPointer(this.posLoc, 3, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.vofs);
if (is_indexed) {
gl.drawElements(gl[mode], count, gl.UNSIGNED_SHORT, 0);
} else {
gl.drawArrays(gl[mode], 0, count);
}
}
};
this.drawBackground = function(id, subsceneid) {
var gl = this.gl || this.initGL(),
obj = this.getObj(id),
bg, i;
if (!obj.initialized)
this.initObj(id);
if (obj.colors.length) {
bg = obj.colors[0];
gl.clearColor(bg[0], bg[1], bg[2], bg[3]);
gl.depthMask(true);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
if (typeof obj.quad !== "undefined") {
this.prMatrix.makeIdentity();
this.mvMatrix.makeIdentity();
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.depthMask(false);
for (i=0; i < obj.quad.length; i++)
this.drawObj(obj.quad[i], subsceneid);
}
};
this.drawSubscene = function(subsceneid) {
var gl = this.gl || this.initGL(),
obj = this.getObj(subsceneid),
objects = this.scene.objects,
subids = obj.objects,
subscene_has_faces = false,
subscene_needs_sorting = false,
flags, i;
if (obj.par3d.skipRedraw)
return;
for (i=0; i < subids.length; i++) {
flags = objects[subids[i]].flags;
if (typeof flags !== "undefined") {
subscene_has_faces |= (flags & this.f_is_lit)
& !(flags & this.f_fixed_quads);
subscene_needs_sorting |= (flags & this.f_depth_sort);
}
}
this.setViewport(subsceneid);
if (typeof obj.backgroundId !== "undefined")
this.drawBackground(obj.backgroundId, subsceneid);
if (subids.length) {
this.setprMatrix(subsceneid);
this.setmvMatrix(subsceneid);
if (subscene_has_faces) {
this.setnormMatrix(subsceneid);
if ((obj.flags & this.f_sprites_3d) &&
typeof obj.spriteNormmat === "undefined") {
obj.spriteNormmat = new CanvasMatrix4(this.normMatrix);
}
}
if (subscene_needs_sorting)
this.setprmvMatrix();
gl.enable(gl.DEPTH_TEST);
gl.depthMask(true);
gl.disable(gl.BLEND);
var clipids = obj.clipplanes;
if (typeof clipids === "undefined") {
console.warn("bad clipids");
}
if (clipids.length > 0) {
this.invMatrix = new CanvasMatrix4(this.mvMatrix);
this.invMatrix.invert();
for (i = 0; i < clipids.length; i++)
this.drawObj(clipids[i], subsceneid);
}
subids = obj.opaque;
if (subids.length > 0) {
for (i = 0; i < subids.length; i++) {
this.drawObj(subids[i], subsceneid);
}
}
subids = obj.transparent;
if (subids.length > 0) {
gl.depthMask(false);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
gl.ONE, gl.ONE);
gl.enable(gl.BLEND);
for (i = 0; i < subids.length; i++) {
this.drawObj(subids[i], subsceneid);
}
}
subids = obj.subscenes;
for (i = 0; i < subids.length; i++) {
this.drawSubscene(subids[i]);
}
}
};
this.relMouseCoords = function(event) {
var totalOffsetX = 0,
totalOffsetY = 0,
currentElement = this.canvas;
do {
totalOffsetX += currentElement.offsetLeft;
totalOffsetY += currentElement.offsetTop;
currentElement = currentElement.offsetParent;
}
while(currentElement);
var canvasX = event.pageX - totalOffsetX,
canvasY = event.pageY - totalOffsetY;
return {x:canvasX, y:canvasY};
};
this.setMouseHandlers = function() {
var self = this, activeSubscene, handler,
handlers = {}, drag = 0;
handlers.rotBase = 0;
this.screenToVector = function(x, y) {
var viewport = this.getObj(activeSubscene).par3d.viewport,
width = viewport.width*this.canvas.width,
height = viewport.height*this.canvas.height,
radius = Math.max(width, height)/2.0,
cx = width/2.0,
cy = height/2.0,
px = (x-cx)/radius,
py = (y-cy)/radius,
plen = Math.sqrt(px*px+py*py);
if (plen > 1.e-6) {
px = px/plen;
py = py/plen;
}
var angle = (Math.SQRT2 - plen)/Math.SQRT2*Math.PI/2,
z = Math.sin(angle),
zlen = Math.sqrt(1.0 - z*z);
px = px * zlen;
py = py * zlen;
return [px, py, z];
};
handlers.trackballdown = function(x,y) {
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, "model")),
i, l = activeModel.par3d.listeners;
handlers.rotBase = this.screenToVector(x, y);
this.saveMat = [];
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.saveMat = new CanvasMatrix4(activeSub.par3d.userMatrix);
}
};
handlers.trackballmove = function(x,y) {
var rotCurrent = this.screenToVector(x,y),
rotBase = handlers.rotBase,
dot = rotBase[0]*rotCurrent[0] +
rotBase[1]*rotCurrent[1] +
rotBase[2]*rotCurrent[2],
angle = Math.acos( dot/this.vlen(rotBase)/this.vlen(rotCurrent) )*180.0/Math.PI,
axis = this.xprod(rotBase, rotCurrent),
objects = this.scene.objects,
activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, "model")),
l = activeModel.par3d.listeners,
i;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.userMatrix.load(objects[l[i]].saveMat);
activeSub.par3d.userMatrix.rotate(angle, axis[0], axis[1], axis[2]);
}
this.drawScene();
};
handlers.trackballend = 0;
handlers.axisdown = function(x,y) {
handlers.rotBase = this.screenToVector(x, this.canvas.height/2);
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, "model")),
i, l = activeModel.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.saveMat = new CanvasMatrix4(activeSub.par3d.userMatrix);
}
};
handlers.axismove = function(x,y) {
var rotCurrent = this.screenToVector(x, this.canvas.height/2),
rotBase = handlers.rotBase,
angle = (rotCurrent[0] - rotBase[0])*180/Math.PI,
rotMat = new CanvasMatrix4();
rotMat.rotate(angle, handlers.axis[0], handlers.axis[1], handlers.axis[2]);
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, "model")),
i, l = activeModel.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.userMatrix.load(activeSub.saveMat);
activeSub.par3d.userMatrix.multLeft(rotMat);
}
this.drawScene();
};
handlers.axisend = 0;
handlers.y0zoom = 0;
handlers.zoom0 = 0;
handlers.zoomdown = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, "projection")),
i, l = activeProjection.par3d.listeners;
handlers.y0zoom = y;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.zoom0 = Math.log(activeSub.par3d.zoom);
}
};
handlers.zoommove = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, "projection")),
i, l = activeProjection.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.zoom = Math.exp(activeSub.zoom0 + (y-handlers.y0zoom)/this.canvas.height);
}
this.drawScene();
};
handlers.zoomend = 0;
handlers.y0fov = 0;
handlers.fovdown = function(x, y) {
handlers.y0fov = y;
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, "projection")),
i, l = activeProjection.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.fov0 = activeSub.par3d.FOV;
}
};
handlers.fovmove = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, "projection")),
i, l = activeProjection.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.FOV = Math.max(1, Math.min(179, activeSub.fov0 +
180*(y-handlers.y0fov)/this.canvas.height));
}
this.drawScene();
};
handlers.fovend = 0;
this.canvas.onmousedown = function ( ev ){
if (!ev.which) // Use w3c defns in preference to MS
switch (ev.button) {
case 0: ev.which = 1; break;
case 1:
case 4: ev.which = 2; break;
case 2: ev.which = 3;
}
drag = ["left", "middle", "right"][ev.which-1];
var coords = self.relMouseCoords(ev);
coords.y = self.canvas.height-coords.y;
activeSubscene = self.whichSubscene(coords);
var sub = self.getObj(activeSubscene), f;
handler = sub.par3d.mouseMode[drag];
switch (handler) {
case "xAxis":
handler = "axis";
handlers.axis = [1.0, 0.0, 0.0];
break;
case "yAxis":
handler = "axis";
handlers.axis = [0.0, 1.0, 0.0];
break;
case "zAxis":
handler = "axis";
handlers.axis = [0.0, 0.0, 1.0];
break;
}
f = handlers[handler + "down"];
if (f) {
coords = self.translateCoords(activeSubscene, coords);
f.call(self, coords.x, coords.y);
ev.preventDefault();
}
};
this.canvas.onmouseup = function ( ev ){
if ( drag === 0 ) return;
var f = handlers[handler + "up"];
if (f)
f();
drag = 0;
};
this.canvas.onmouseout = this.canvas.onmouseup;
this.canvas.onmousemove = function ( ev ) {
if ( drag === 0 ) return;
var f = handlers[handler + "move"];
if (f) {
var coords = self.relMouseCoords(ev);
coords.y = self.canvas.height - coords.y;
coords = self.translateCoords(activeSubscene, coords);
f.call(self, coords.x, coords.y);
}
};
handlers.wheelHandler = function(ev) {
var del = 1.02, i;
if (ev.shiftKey) del = 1.002;
var ds = ((ev.detail || ev.wheelDelta) > 0) ? del : (1 / del);
if (typeof activeSubscene === "undefined")
activeSubscene = self.scene.rootSubscene;
var activeSub = self.getObj(activeSubscene),
activeProjection = self.getObj(self.useid(activeSub.id, "projection")),
l = activeProjection.par3d.listeners;
for (i = 0; i < l.length; i++) {
activeSub = self.getObj(l[i]);
activeSub.par3d.zoom *= ds;
}
self.drawScene();
ev.preventDefault();
};
this.canvas.addEventListener("DOMMouseScroll", handlers.wheelHandler, false);
this.canvas.addEventListener("mousewheel", handlers.wheelHandler, false);
};
this.useid = function(subsceneid, type) {
var sub = this.getObj(subsceneid);
if (sub.embeddings[type] === "inherit")
return(this.useid(sub.parent, type));
else
return subsceneid;
};
this.inViewport = function(coords, subsceneid) {
var viewport = this.getObj(subsceneid).par3d.viewport,
x0 = coords.x - viewport.x*this.canvas.width,
y0 = coords.y - viewport.y*this.canvas.height;
return 0 <= x0 && x0 <= viewport.width*this.canvas.width &&
0 <= y0 && y0 <= viewport.height*this.canvas.height;
};
this.whichSubscene = function(coords) {
var self = this,
recurse = function(subsceneid) {
var subscenes = self.getChildSubscenes(subsceneid), i, id;
for (i=0; i < subscenes.length; i++) {
id = recurse(subscenes[i]);
if (typeof(id) !== "undefined")
return(id);
}
if (self.inViewport(coords, subsceneid))
return(subsceneid);
else
return undefined;
},
rootid = this.scene.rootSubscene,
result = recurse(rootid);
if (typeof(result) === "undefined")
result = rootid;
return result;
};
this.translateCoords = function(subsceneid, coords) {
var viewport = this.getObj(subsceneid).par3d.viewport;
return {x: coords.x - viewport.x*this.canvas.width,
y: coords.y - viewport.y*this.canvas.height};
};
this.initSphere = function() {
var verts = this.scene.sphereVerts,
reuse = verts.reuse, result;
if (typeof reuse !== "undefined") {
var prev = document.getElementById(reuse).rglinstance.sphere;
result = {values: prev.values, vOffsets: prev.vOffsets, it: prev.it};
} else
result = {values: new Float32Array(this.flatten(this.cbind(this.transpose(verts.vb),
this.transpose(verts.texcoords)))),
it: new Uint16Array(this.flatten(this.transpose(verts.it))),
vOffsets: {vofs:0, cofs:-1, nofs:-1, radofs:-1, oofs:-1,
tofs:3, stride:5}};
result.sphereCount = result.it.length;
this.sphere = result;
};
this.initSphereGL = function() {
var gl = this.gl || this.initGL(), sphere = this.sphere;
if (gl.isContextLost()) return;
sphere.buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, sphere.buf);
gl.bufferData(gl.ARRAY_BUFFER, sphere.values, gl.STATIC_DRAW);
sphere.ibuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sphere.ibuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sphere.it, gl.STATIC_DRAW);
return;
};
this.initialize = function(el, x) {
this.textureCanvas = document.createElement("canvas");
this.textureCanvas.style.display = "block";
this.scene = x;
this.normMatrix = new CanvasMatrix4();
this.saveMat = {};
this.distance = null;
this.posLoc = 0;
this.colLoc = 1;
if (el) {
el.rglinstance = this;
this.el = el;
this.webGLoptions = el.rglinstance.scene.webGLoptions;
this.initCanvas();
}
};
this.restartCanvas = function() {
var newcanvas = document.createElement("canvas");
newcanvas.width = this.el.width;
newcanvas.height = this.el.height;
newcanvas.addEventListener("webglcontextrestored",
this.onContextRestored, false);
newcanvas.addEventListener("webglcontextlost",
this.onContextLost, false);
while (this.el.firstChild) {
this.el.removeChild(this.el.firstChild);
}
this.el.appendChild(newcanvas);
this.canvas = newcanvas;
this.gl = null;
};
this.initCanvas = function() {
this.restartCanvas();
var objs = this.scene.objects,
self = this;
Object.keys(objs).forEach(function(key){
var id = parseInt(key, 10),
obj = self.getObj(id);
if (typeof obj.reuse !== "undefined")
self.copyObj(id, obj.reuse);
});
Object.keys(objs).forEach(function(key){
self.initSubscene(parseInt(key, 10));
});
this.setMouseHandlers();
this.initSphere();
this.onContextRestored = function(event) {
self.initGL();
self.drawScene();
// console.log("restored context for "+self.scene.rootSubscene);
};
this.onContextLost = function(event) {
if (!self.drawing)
self.restartCanvas();
event.preventDefault();
};
this.initGL0();
lazyLoadScene = function() {
if (self.isInBrowserViewport()) {
if (!self.gl) {
self.initGL();
}
self.drawScene();
}
};
window.addEventListener("DOMContentLoaded", lazyLoadScene, false);
window.addEventListener("load", lazyLoadScene, false);
window.addEventListener("resize", lazyLoadScene, false);
window.addEventListener("scroll", lazyLoadScene, false);
};
/* this is only used by writeWebGL; rglwidget has
no debug element and does the drawing in rglwidget.js */
this.start = function() {
if (typeof this.prefix !== "undefined") {
this.debugelement = document.getElementById(this.prefix + "debug");
this.debug("");
}
this.drag = 0;
this.drawScene();
};
this.debug = function(msg, img) {
if (typeof this.debugelement !== "undefined" && this.debugelement !== null) {
this.debugelement.innerHTML = msg;
if (typeof img !== "undefined") {
this.debugelement.insertBefore(img, this.debugelement.firstChild);
}
} else if (msg !== "")
alert(msg);
};
this.getSnapshot = function() {
var img;
if (typeof this.scene.snapshot !== "undefined") {
img = document.createElement("img");
img.src = this.scene.snapshot;
img.alt = "Snapshot";
}
return img;
};
this.initGL0 = function() {
if (!window.WebGLRenderingContext){
alert("Your browser does not support WebGL. See http://get.webgl.org");
return;
}
};
this.isInBrowserViewport = function() {
var rect = this.canvas.getBoundingClientRect(),
windHeight = (window.innerHeight || document.documentElement.clientHeight),
windWidth = (window.innerWidth || document.documentElement.clientWidth);
return (
rect.top >= -windHeight &&
rect.left >= -windWidth &&
rect.bottom <= 2*windHeight &&
rect.right <= 2*windWidth);
};
this.initGL = function() {
var self = this;
if (this.gl) {
if (!this.drawing && this.gl.isContextLost())
this.restartCanvas();
else
return this.gl;
}
// if (!this.isInBrowserViewport()) return; Return what??? At this point we know this.gl is null.
this.canvas.addEventListener("webglcontextrestored",
this.onContextRestored, false);
this.canvas.addEventListener("webglcontextlost",
this.onContextLost, false);
this.gl = this.canvas.getContext("webgl", this.webGLoptions) ||
this.canvas.getContext("experimental-webgl", this.webGLoptions);
var save = this.startDrawing();
this.initSphereGL();
Object.keys(this.scene.objects).forEach(function(key){
self.initObj(parseInt(key, 10));
});
this.stopDrawing(save);
return this.gl;
};
this.resize = function(el) {
this.canvas.width = el.width;
this.canvas.height = el.height;
};
this.drawScene = function() {
var gl = this.gl || this.initGL(),
save = this.startDrawing();
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearDepth(1.0);
gl.clearColor(1,1,1,1);
gl.depthMask(true); // Must be true before clearing depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
this.drawSubscene(this.scene.rootSubscene);
this.stopDrawing(save);
};
this.subsetSetter = function(el, control) {
if (typeof control.subscenes === "undefined" ||
control.subscenes === null)
control.subscenes = this.scene.rootSubscene;
var value = Math.round(control.value),
subscenes = [].concat(control.subscenes),
fullset = [].concat(control.fullset),
i, j, entries, subsceneid,
adds = [], deletes = [],
ismissing = function(x) {
return fullset.indexOf(x) < 0;
},
tointeger = function(x) {
return parseInt(x, 10);
};
if (control.accumulate)
for (i=0; i <= value; i++)
adds = adds.concat(control.subsets[i]);
else
adds = adds.concat(control.subsets[value]);
deletes = fullset.filter(function(x) { return adds.indexOf(x) < 0 });
for (i = 0; i < subscenes.length; i++) {
subsceneid = subscenes[i];
if (typeof this.getObj(subsceneid) === "undefined")
this.alertOnce("typeof object is undefined");
for (j = 0; j < adds.length; j++)
this.addToSubscene(adds[j], subsceneid);
for (j = 0; j < deletes.length; j++)
this.delFromSubscene(deletes[j], subsceneid);
}
};
this.propertySetter = function(el, control) {
var value = control.value,
values = [].concat(control.values),
svals = [].concat(control.param),
direct = values[0] === null,
entries = [].concat(control.entries),
ncol = entries.length,
nrow = values.length/ncol,
properties = this.repeatToLen(control.properties, ncol),
objids = this.repeatToLen(control.objids, ncol),
property, objid = objids[0],
obj = this.getObj(objid),
propvals, i, v1, v2, p, entry, gl, needsBinding,
newprop, newid,
getPropvals = function() {
if (property === "userMatrix")
return obj.par3d.userMatrix.getAsArray();
else if (property === "scale" || property === "FOV" || property === "zoom")
return [].concat(obj.par3d[property]);
else
return [].concat(obj[property]);
};
putPropvals = function(newvals) {
if (newvals.length == 1)
newvals = newvals[0];
if (property === "userMatrix")
obj.par3d.userMatrix.load(newvals);
else if (property === "scale" || property === "FOV" || property === "zoom")
obj.par3d[property] = newvals;
else
obj[property] = newvals;
}
if (direct && typeof value === "undefined")
return;
if (control.interp) {
values = values.slice(0, ncol).concat(values).
concat(values.slice(ncol*(nrow-1), ncol*nrow));
svals = [-Infinity].concat(svals).concat(Infinity);
for (i = 1; i < svals.length; i++) {
if (value <= svals[i]) {
if (svals[i] === Infinity)
p = 1;
else
p = (svals[i] - value)/(svals[i] - svals[i-1]);
break;
}
}
} else if (!direct) {
value = Math.round(value);
}
for (j=0; j<entries.length; j++) {
entry = entries[j];
newprop = properties[j];
newid = objids[j];
if (newprop !== property || newid != objid) {
if (typeof property !== "undefined")
putPropvals(propvals);
property = newprop;
objid = newid;
obj = this.getObj(objid);
propvals = getPropvals();
}
if (control.interp) {
v1 = values[ncol*(i-1) + j];
v2 = values[ncol*i + j];
this.setElement(propvals, entry, p*v1 + (1-p)*v2);
} else if (!direct) {
this.setElement(propvals, entry, values[ncol*value + j]);
} else {
this.setElement(propvals, entry, value[j]);
}
}
putPropvals(propvals);
needsBinding = [];
for (j=0; j < entries.length; j++) {
if (properties[j] === "values" &&
needsBinding.indexOf(objids[j]) === -1) {
needsBinding.push(objids[j]);
}
}
for (j=0; j < needsBinding.length; j++) {
gl = this.gl || this.initGL();
obj = this.getObj(needsBinding[j]);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW);
}
};
this.vertexSetter = function(el, control) {
var svals = [].concat(control.param),
j, k, p, propvals, stride, ofs, obj,
attrib,
ofss = {x:"vofs", y:"vofs", z:"vofs",
red:"cofs", green:"cofs", blue:"cofs",
alpha:"cofs", radii:"radofs",
nx:"nofs", ny:"nofs", nz:"nofs",
ox:"oofs", oy:"oofs", oz:"oofs",
ts:"tofs", tt:"tofs"},
pos = {x:0, y:1, z:2,
red:0, green:1, blue:2,
alpha:3,radii:0,
nx:0, ny:1, nz:2,
ox:0, oy:1, oz:2,
ts:0, tt:1},
values = control.values,
direct = values === null,
ncol,
interp = control.interp,
vertices = [].concat(control.vertices),
attributes = [].concat(control.attributes),
value = control.value;
ncol = Math.max(vertices.length, attributes.length);
if (!ncol)
return;
vertices = this.repeatToLen(vertices, ncol);
attributes = this.repeatToLen(attributes, ncol);
if (direct)
interp = false;
/* JSON doesn't pass Infinity */
svals[0] = -Infinity;
svals[svals.length - 1] = Infinity;
for (j = 1; j < svals.length; j++) {
if (value <= svals[j]) {
if (interp) {
if (svals[j] === Infinity)
p = 1;
else
p = (svals[j] - value)/(svals[j] - svals[j-1]);
} else {
if (svals[j] - value > value - svals[j-1])
j = j - 1;
}
break;
}
}
obj = this.getObj(control.objid);
propvals = obj.values;
for (k=0; k<ncol; k++) {
attrib = attributes[k];
vertex = vertices[k];
ofs = obj.vOffsets[ofss[attrib]];
if (ofs < 0)
this.alertOnce("Attribute '"+attrib+"' not found in object "+control.objid);
else {
stride = obj.vOffsets.stride;
ofs = vertex*stride + ofs + pos[attrib];
if (direct) {
propvals[ofs] = value;
} else if (interp) {
propvals[ofs] = p*values[j-1][k] + (1-p)*values[j][k];
} else {
propvals[ofs] = values[j][k];
}
}
}
if (typeof obj.buf !== "undefined") {
var gl = this.gl || this.initGL();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, propvals, gl.STATIC_DRAW);
}
};
this.ageSetter = function(el, control) {
var objids = [].concat(control.objids),
nobjs = objids.length,
time = control.value,
births = [].concat(control.births),
ages = [].concat(control.ages),
steps = births.length,
j = Array(steps),
p = Array(steps),
i, k, age, j0, propvals, stride, ofs, objid, obj,
attrib, dim,
attribs = ["colors", "alpha", "radii", "vertices",
"normals", "origins", "texcoords",
"x", "y", "z",
"red", "green", "blue"],
ofss = ["cofs", "cofs", "radofs", "vofs",
"nofs", "oofs", "tofs",
"vofs", "vofs", "vofs",
"cofs", "cofs", "cofs"],
dims = [3,1,1,3,
3,2,2,
1,1,1,
1,1,1],
pos = [0,3,0,0,
0,0,0,
0,1,2,
0,1,2];
/* Infinity doesn't make it through JSON */
ages[0] = -Infinity;
ages[ages.length-1] = Infinity;
for (i = 0; i < steps; i++) {
if (births[i] !== null) { // NA in R becomes null
age = time - births[i];
for (j0 = 1; age > ages[j0]; j0++);
if (ages[j0] == Infinity)
p[i] = 1;
else if (ages[j0] > ages[j0-1])
p[i] = (ages[j0] - age)/(ages[j0] - ages[j0-1]);
else
p[i] = 0;
j[i] = j0;
}
}
for (l = 0; l < nobjs; l++) {
objid = objids[l];
obj = this.getObj(objid);
if (typeof obj.vOffsets === "undefined")
continue;
propvals = obj.values;
stride = obj.vOffsets.stride;
for (k = 0; k < attribs.length; k++) {
attrib = control[attribs[k]];
if (typeof attrib !== "undefined") {
ofs = obj.vOffsets[ofss[k]];
if (ofs >= 0) {
dim = dims[k];
ofs = ofs + pos[k];
for (i = 0; i < steps; i++) {
if (births[i] !== null) {
for (d=0; d < dim; d++) {
propvals[i*stride + ofs + d] = p[i]*attrib[dim*(j[i]-1) + d] + (1-p[i])*attrib[dim*j[i] + d];
}
}
}
} else
this.alertOnce("\'"+attribs[k]+"\' property not found in object "+objid);
}
}
obj.values = propvals;
if (typeof obj.buf !== "undefined") {
gl = this.gl || this.initGL();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW);
}
}
};
this.oldBridge = function(el, control) {
var attrname, global = window[control.prefix + "rgl"];
if (typeof global !== "undefined")
for (attrname in global)
this[attrname] = global[attrname];
window[control.prefix + "rgl"] = this;
};
this.Player = function(el, control) {
var
self = this,
components = [].concat(control.components),
buttonLabels = [].concat(control.buttonLabels),
Tick = function() { /* "this" will be a timer */
var i,
nominal = this.value,
slider = this.Slider,
labels = this.outputLabels,
output = this.Output,
step;
if (typeof slider !== "undefined" && nominal != slider.value)
slider.value = nominal;
if (typeof output !== "undefined") {
step = Math.round((nominal - output.sliderMin)/output.sliderStep);
if (labels !== null) {
output.innerHTML = labels[step];
} else {
step = step*output.sliderStep + output.sliderMin;
output.innerHTML = step.toPrecision(output.outputPrecision);
}
}
for (i=0; i < this.actions.length; i++) {
this.actions[i].value = nominal;
}
self.applyControls(el, this.actions, false);
self.drawScene();
},
OnSliderInput = function() { /* "this" will be the slider */
this.rgltimer.value = Number(this.value);
this.rgltimer.Tick();
},
addSlider = function(min, max, step, value) {
var slider = document.createElement("input");
slider.type = "range";
slider.min = min;
slider.max = max;
slider.step = step;
slider.value = value;
slider.oninput = OnSliderInput;
slider.sliderActions = control.actions;
slider.sliderScene = this;
slider.className = "rgl-slider";
slider.id = el.id + "-slider";
el.rgltimer.Slider = slider;
slider.rgltimer = el.rgltimer;
el.appendChild(slider);
},
addLabel = function(labels, min, step, precision) {
var output = document.createElement("output");
output.sliderMin = min;
output.sliderStep = step;
output.outputPrecision = precision;
output.className = "rgl-label";
output.id = el.id + "-label";
el.rgltimer.Output = output;
el.rgltimer.outputLabels = labels;
el.appendChild(output);
},
addButton = function(which, label, active) {
var button = document.createElement("input"),
onclicks = {Reverse: function() { this.rgltimer.reverse();},
Play: function() { this.rgltimer.play();
this.value = this.rgltimer.enabled ? this.inactiveValue : this.activeValue; },
Slower: function() { this.rgltimer.slower(); },
Faster: function() { this.rgltimer.faster(); },
Reset: function() { this.rgltimer.reset(); },
Step: function() { this.rgltimer.step(); }
};
button.rgltimer = el.rgltimer;
button.type = "button";
button.value = label;
button.activeValue = label;
button.inactiveValue = active;
if (which === "Play")
button.rgltimer.PlayButton = button;
button.onclick = onclicks[which];
button.className = "rgl-button";
button.id = el.id + "-" + which;
el.appendChild(button);
};
if (typeof control.reinit !== "undefined" && control.reinit !== null) {
control.actions.reinit = control.reinit;
}
el.rgltimer = new rgltimerClass(Tick, control.start, control.interval, control.stop,
control.step, control.value, control.rate, control.loop, control.actions);
for (var i=0; i < components.length; i++) {
switch(components[i]) {
case "Slider": addSlider(control.start, control.stop,
control.step, control.value);
break;
case "Label": addLabel(control.labels, control.start,
control.step, control.precision);
break;
default:
addButton(components[i], buttonLabels[i], control.pause);
}
}
el.rgltimer.Tick();
};
this.applyControls = function(el, x, draw) {
var self = this, reinit = x.reinit, i, control, type;
for (i = 0; i < x.length; i++) {
control = x[i];
type = control.type;
self[type](el, control);
}
if (typeof reinit !== "undefined" && reinit !== null) {
reinit = [].concat(reinit);
for (i = 0; i < reinit.length; i++)
self.getObj(reinit[i]).initialized = false;
}
if (typeof draw === "undefined" || draw)
self.drawScene();
};
this.sceneChangeHandler = function(message) {
var self = document.getElementById(message.elementId).rglinstance,
objs = message.objects, mat = message.material,
root = message.rootSubscene,
initSubs = message.initSubscenes,
redraw = message.redrawScene,
skipRedraw = message.skipRedraw,
deletes, subs, allsubs = [], i,j;
if (typeof message.delete !== "undefined") {
deletes = [].concat(message.delete);
if (typeof message.delfromSubscenes !== "undefined")
subs = [].concat(message.delfromSubscenes);
else
subs = [];
for (i = 0; i < deletes.length; i++) {
for (j = 0; j < subs.length; j++) {
self.delFromSubscene(deletes[i], subs[j]);
}
delete self.scene.objects[deletes[i]];
}
}
if (typeof objs !== "undefined") {
Object.keys(objs).forEach(function(key){
key = parseInt(key, 10);
self.scene.objects[key] = objs[key];
self.initObj(key);
var obj = self.getObj(key),
subs = [].concat(obj.inSubscenes), k;
allsubs = allsubs.concat(subs);
for (k = 0; k < subs.length; k++)
self.addToSubscene(key, subs[k]);
});
}
if (typeof mat !== "undefined") {
self.scene.material = mat;
}
if (typeof root !== "undefined") {
self.scene.rootSubscene = root;
}
if (typeof initSubs !== "undefined")
allsubs = allsubs.concat(initSubs);
allsubs = self.unique(allsubs);
for (i = 0; i < allsubs.length; i++) {
self.initSubscene(allsubs[i]);
}
if (typeof skipRedraw !== "undefined") {
root = self.getObj(self.scene.rootSubscene);
root.par3d.skipRedraw = skipRedraw;
}
if (redraw)
self.drawScene();
};
}).call(rglwidgetClass.prototype);
rgltimerClass = function(Tick, startTime, interval, stopTime, stepSize, value, rate, loop, actions) {
this.enabled = false;
this.timerId = 0;
this.startTime = startTime; /* nominal start time in seconds */
this.value = value; /* current nominal time */
this.interval = interval; /* seconds between updates */
this.stopTime = stopTime; /* nominal stop time */
this.stepSize = stepSize; /* nominal step size */
this.rate = rate; /* nominal units per second */
this.loop = loop; /* "none", "cycle", or "oscillate" */
this.realStart = undefined; /* real world start time */
this.multiplier = 1; /* multiplier for fast-forward
or reverse */
this.actions = actions;
this.Tick = Tick;
};
(function() {
this.play = function() {
if (this.enabled) {
this.enabled = false;
window.clearInterval(this.timerId);
this.timerId = 0;
return;
}
var tick = function(self) {
var now = new Date();
self.value = self.multiplier*self.rate*(now - self.realStart)/1000 + self.startTime;
self.forceToRange();
if (typeof self.Tick !== "undefined") {
self.Tick(self.value);
}
};
this.realStart = new Date() - 1000*(this.value - this.startTime)/this.rate/this.multiplier;
this.timerId = window.setInterval(tick, 1000*this.interval, this);
this.enabled = true;
};
this.forceToRange = function() {
if (this.value > this.stopTime + this.stepSize/2 || this.value < this.startTime - this.stepSize/2) {
if (!this.loop) {
this.reset();
} else {
var cycle = this.stopTime - this.startTime + this.stepSize,
newval = (this.value - this.startTime) % cycle + this.startTime;
if (newval < this.startTime) {
newval += cycle;
}
this.realStart += (this.value - newval)*1000/this.multiplier/this.rate;
this.value = newval;
}
}
}
this.reset = function() {
this.value = this.startTime;
this.newmultiplier(1);
if (typeof this.Tick !== "undefined") {
this.Tick(this.value);
}
if (this.enabled)
this.play(); /* really pause... */
if (typeof this.PlayButton !== "undefined")
this.PlayButton.value = "Play";
};
this.faster = function() {
this.newmultiplier(Math.SQRT2*this.multiplier);
};
this.slower = function() {
this.newmultiplier(this.multiplier/Math.SQRT2);
};
this.reverse = function() {
this.newmultiplier(-this.multiplier);
};
this.newmultiplier = function(newmult) {
if (newmult != this.multiplier) {
this.realStart += 1000*(this.value - this.startTime)/this.rate*(1/this.multiplier - 1/newmult);
this.multiplier = newmult;
}
};
this.step = function() {
this.value += this.rate*this.multiplier;
this.forceToRange();
if (typeof this.Tick !== "undefined")
this.Tick(this.value);
}
}).call(rgltimerClass.prototype);</script>
<div id="div" class="rglWebGL"></div>
<script type="text/javascript">
var div = document.getElementById("div"),
rgl = new rglwidgetClass();
div.width = 1000;
div.height = 1000;
rgl.initialize(div,
{"material":{"color":"#000000","alpha":1,"lit":true,"ambient":"#000000","specular":"#FFFFFF","emission":"#000000","shininess":50,"smooth":true,"front":"filled","back":"filled","size":3,"lwd":1,"fog":false,"point_antialias":false,"line_antialias":false,"texture":null,"textype":"rgb","texmipmap":false,"texminfilter":"linear","texmagfilter":"linear","texenvmap":false,"depth_mask":true,"depth_test":"less","isTransparent":false},"rootSubscene":66,"objects":{"72":{"id":72,"type":"spheres","material":{},"vertices":[[1,1,1],[1,8,2],[2,7,4],[1,1,10],[8,9,11],[8,10,11]],"colors":[[1,0,0,1]],"radii":[[0.006859576]],"centers":[[1,1,1],[1,8,2],[2,7,4],[1,1,10],[8,9,11],[8,10,11]],"ignoreExtent":false,"flags":3},"73":{"id":73,"type":"spheres","material":{},"vertices":[[1,8,1],[4,11,7],[7,9,10],[7,10,11]],"colors":[[1,0.1215686,0,1]],"radii":[[0.01575917]],"centers":[[1,8,1],[4,11,7],[7,9,10],[7,10,11]],"ignoreExtent":false,"flags":3},"74":{"id":74,"type":"spheres","material":{},"vertices":[[2,1,1],[4,6,1],[3,1,2],[5,1,2],[3,2,2],[1,7,2],[1,2,3],[2,7,3],[2,6,4],[4,11,5],[4,11,6],[8,9,10],[7,9,11],[9,9,11],[9,10,11]],"colors":[[1,0.2431373,0,1]],"radii":[[0.02563556]],"centers":[[2,1,1],[4,6,1],[3,1,2],[5,1,2],[3,2,2],[1,7,2],[1,2,3],[2,7,3],[2,6,4],[4,11,5],[4,11,6],[8,9,10],[7,9,11],[9,9,11],[9,10,11]],"ignoreExtent":false,"flags":3},"75":{"id":75,"type":"spheres","material":{},"vertices":[[3,1,1],[1,2,1],[3,2,1],[5,2,1],[1,7,1],[1,9,1],[1,1,2],[5,2,2],[5,1,3],[3,2,3],[8,3,3],[1,4,3],[1,7,3],[1,8,3],[2,8,4],[4,11,4],[5,11,4],[6,11,4],[2,6,5],[2,7,5],[3,9,5],[4,9,5],[3,9,6],[3,9,7],[4,10,7],[5,11,7],[1,1,9],[7,8,10],[7,10,10],[6,10,11]],"colors":[[1,0.3686275,0,1]],"radii":[[0.03620506]],"centers":[[3,1,1],[1,2,1],[3,2,1],[5,2,1],[1,7,1],[1,9,1],[1,1,2],[5,2,2],[5,1,3],[3,2,3],[8,3,3],[1,4,3],[1,7,3],[1,8,3],[2,8,4],[4,11,4],[5,11,4],[6,11,4],[2,6,5],[2,7,5],[3,9,5],[4,9,5],[3,9,6],[3,9,7],[4,10,7],[5,11,7],[1,1,9],[7,8,10],[7,10,10],[6,10,11]],"ignoreExtent":false,"flags":3},"76":{"id":76,"type":"spheres","material":{},"vertices":[[7,3,1],[3,4,1],[4,5,1],[4,7,1],[2,1,2],[4,1,2],[1,2,2],[3,3,2],[4,5,2],[1,6,2],[4,6,2],[1,9,2],[3,1,3],[2,2,3],[1,3,3],[7,3,3],[1,6,3],[2,6,3],[4,6,3],[6,11,3],[1,1,4],[2,1,4],[4,1,4],[1,2,4],[1,6,4],[1,7,4],[4,9,4],[3,8,5],[4,10,5],[5,11,5],[4,9,6],[4,10,6],[5,11,6],[3,11,7],[1,1,8],[3,9,8],[8,10,10],[8,8,11]],"colors":[[1,0.4901961,0,1]],"radii":[[0.0473218]],"centers":[[7,3,1],[3,4,1],[4,5,1],[4,7,1],[2,1,2],[4,1,2],[1,2,2],[3,3,2],[4,5,2],[1,6,2],[4,6,2],[1,9,2],[3,1,3],[2,2,3],[1,3,3],[7,3,3],[1,6,3],[2,6,3],[4,6,3],[6,11,3],[1,1,4],[2,1,4],[4,1,4],[1,2,4],[1,6,4],[1,7,4],[4,9,4],[3,8,5],[4,10,5],[5,11,5],[4,9,6],[4,10,6],[5,11,6],[3,11,7],[1,1,8],[3,9,8],[8,10,10],[8,8,11]],"ignoreExtent":false,"flags":3},"77":{"id":77,"type":"spheres","material":{},"vertices":[[6,2,1],[1,3,1],[3,3,1],[5,3,1],[1,4,2],[3,4,2],[1,1,3],[2,1,3],[2,3,3],[3,3,3],[3,4,3],[2,8,3],[5,11,3],[2,2,4],[8,3,4],[1,4,4],[1,5,4],[2,5,4],[1,8,4],[3,9,4],[4,10,4],[4,1,5],[3,7,5],[4,7,5],[2,8,5],[4,8,5],[6,11,5],[6,11,6],[6,4,7],[8,11,7],[6,3,8],[4,11,8],[5,11,8],[8,8,10],[6,10,10],[1,1,11],[9,8,11],[8,11,11]],"colors":[[1,0.6117647,0,1]],"radii":[[0.05889504]],"centers":[[6,2,1],[1,3,1],[3,3,1],[5,3,1],[1,4,2],[3,4,2],[1,1,3],[2,1,3],[2,3,3],[3,3,3],[3,4,3],[2,8,3],[5,11,3],[2,2,4],[8,3,4],[1,4,4],[1,5,4],[2,5,4],[1,8,4],[3,9,4],[4,10,4],[4,1,5],[3,7,5],[4,7,5],[2,8,5],[4,8,5],[6,11,5],[6,11,6],[6,4,7],[8,11,7],[6,3,8],[4,11,8],[5,11,8],[8,8,10],[6,10,10],[1,1,11],[9,8,11],[8,11,11]],"ignoreExtent":false,"flags":3},"78":{"id":78,"type":"spheres","material":{},"vertices":[[5,1,1],[7,2,1],[2,3,1],[6,3,1],[1,4,1],[2,5,1],[1,6,1],[10,10,1],[2,2,2],[4,2,2],[2,3,2],[1,5,2],[4,1,3],[2,4,3],[1,5,3],[2,5,3],[4,11,3],[3,1,4],[3,2,4],[1,3,4],[3,7,4],[5,10,4],[2,5,5],[3,11,5],[2,6,6],[2,7,6],[3,7,6],[4,9,7],[3,10,7],[5,10,7],[6,11,7],[6,4,8],[8,9,8],[9,9,8],[4,10,8],[8,9,9],[9,9,9],[9,9,10],[7,8,11],[6,11,11]],"colors":[[1,0.7333333,0,1]],"radii":[[0.07086225]],"centers":[[5,1,1],[7,2,1],[2,3,1],[6,3,1],[1,4,1],[2,5,1],[1,6,1],[10,10,1],[2,2,2],[4,2,2],[2,3,2],[1,5,2],[4,1,3],[2,4,3],[1,5,3],[2,5,3],[4,11,3],[3,1,4],[3,2,4],[1,3,4],[3,7,4],[5,10,4],[2,5,5],[3,11,5],[2,6,6],[2,7,6],[3,7,6],[4,9,7],[3,10,7],[5,10,7],[6,11,7],[6,4,8],[8,9,8],[9,9,8],[4,10,8],[8,9,9],[9,9,9],[9,9,10],[7,8,11],[6,11,11]],"ignoreExtent":false,"flags":3},"79":{"id":79,"type":"spheres","material":{},"vertices":[[2,4,1],[4,4,1],[1,5,1],[3,5,1],[9,10,1],[6,1,2],[2,4,2],[4,4,2],[3,5,2],[2,6,2],[2,7,2],[5,10,2],[6,1,3],[5,2,3],[7,2,3],[3,5,3],[4,5,3],[4,7,3],[3,9,3],[4,9,3],[4,10,3],[5,10,3],[7,11,3],[7,3,4],[2,4,4],[3,6,4],[4,7,4],[3,8,4],[6,10,4],[1,1,5],[2,1,5],[3,1,5],[1,2,5],[3,2,5],[8,3,5],[1,5,5],[3,6,5],[5,10,5],[6,10,5],[1,1,6],[2,1,6],[3,2,6],[3,8,6],[5,9,6],[5,10,6],[6,10,6],[3,11,6],[8,11,6],[6,3,7],[9,9,7],[2,11,7],[3,7,8],[6,11,8],[6,3,9],[7,9,9],[7,10,9],[1,5,10],[9,10,10],[7,11,11],[9,11,11]],"colors":[[1,0.8588235,0,1]],"radii":[[0.08317738]],"centers":[[2,4,1],[4,4,1],[1,5,1],[3,5,1],[9,10,1],[6,1,2],[2,4,2],[4,4,2],[3,5,2],[2,6,2],[2,7,2],[5,10,2],[6,1,3],[5,2,3],[7,2,3],[3,5,3],[4,5,3],[4,7,3],[3,9,3],[4,9,3],[4,10,3],[5,10,3],[7,11,3],[7,3,4],[2,4,4],[3,6,4],[4,7,4],[3,8,4],[6,10,4],[1,1,5],[2,1,5],[3,1,5],[1,2,5],[3,2,5],[8,3,5],[1,5,5],[3,6,5],[5,10,5],[6,10,5],[1,1,6],[2,1,6],[3,2,6],[3,8,6],[5,9,6],[5,10,6],[6,10,6],[3,11,6],[8,11,6],[6,3,7],[9,9,7],[2,11,7],[3,7,8],[6,11,8],[6,3,9],[7,9,9],[7,10,9],[1,5,10],[9,10,10],[7,11,11],[9,11,11]],"ignoreExtent":false,"flags":3},"80":{"id":80,"type":"spheres","material":{},"vertices":[[4,1,1],[6,1,1],[2,2,1],[4,2,1],[2,6,1],[1,10,1],[6,2,2],[1,3,2],[7,3,2],[8,3,2],[8,4,2],[2,5,2],[4,7,2],[2,8,2],[5,11,2],[8,11,2],[6,2,3],[8,2,3],[6,3,3],[8,4,3],[8,11,3],[5,1,4],[6,1,4],[6,2,4],[2,3,4],[3,3,4],[6,3,4],[3,4,4],[3,5,4],[4,8,4],[8,2,5],[3,3,5],[1,4,5],[1,6,5],[5,9,5],[3,10,5],[7,11,5],[3,3,6],[3,6,6],[4,7,6],[2,8,6],[4,8,6],[11,9,6],[3,10,6],[3,2,7],[3,3,7],[5,3,7],[5,4,7],[3,7,7],[5,9,7],[1,11,7],[7,11,7],[2,7,8],[4,9,8],[5,10,8],[8,10,8],[1,11,8],[3,11,8],[1,6,10],[9,8,10],[6,9,10],[6,11,10],[6,9,11],[1,10,11]],"colors":[[1,0.9803922,0,1]],"radii":[[0.09580502]],"centers":[[4,1,1],[6,1,1],[2,2,1],[4,2,1],[2,6,1],[1,10,1],[6,2,2],[1,3,2],[7,3,2],[8,3,2],[8,4,2],[2,5,2],[4,7,2],[2,8,2],[5,11,2],[8,11,2],[6,2,3],[8,2,3],[6,3,3],[8,4,3],[8,11,3],[5,1,4],[6,1,4],[6,2,4],[2,3,4],[3,3,4],[6,3,4],[3,4,4],[3,5,4],[4,8,4],[8,2,5],[3,3,5],[1,4,5],[1,6,5],[5,9,5],[3,10,5],[7,11,5],[3,3,6],[3,6,6],[4,7,6],[2,8,6],[4,8,6],[11,9,6],[3,10,6],[3,2,7],[3,3,7],[5,3,7],[5,4,7],[3,7,7],[5,9,7],[1,11,7],[7,11,7],[2,7,8],[4,9,8],[5,10,8],[8,10,8],[1,11,8],[3,11,8],[1,6,10],[9,8,10],[6,9,10],[6,11,10],[6,9,11],[1,10,11]],"ignoreExtent":false,"flags":3},"81":{"id":81,"type":"spheres","material":{},"vertices":[[4,3,1],[5,7,1],[4,8,1],[8,10,1],[8,11,1],[7,2,2],[5,3,2],[4,9,2],[5,9,2],[4,10,2],[6,11,2],[7,1,3],[9,1,3],[3,6,3],[3,7,3],[1,9,3],[8,2,4],[4,6,4],[3,10,4],[3,11,4],[7,11,4],[2,2,5],[1,3,5],[6,3,5],[7,3,5],[3,4,5],[1,7,5],[3,1,6],[8,2,6],[6,3,6],[6,4,6],[1,5,6],[1,6,6],[7,10,6],[7,11,6],[1,1,7],[4,5,7],[3,6,7],[2,7,7],[3,8,7],[11,9,7],[6,10,7],[2,1,8],[5,3,8],[4,5,8],[1,7,8],[3,8,8],[7,9,8],[3,10,8],[6,10,8],[7,10,8],[7,3,9],[3,9,9],[2,1,10],[6,8,10],[1,11,11],[10,11,11]],"colors":[[0.8980392,1,0,1]],"radii":[[0.1087169]],"centers":[[4,3,1],[5,7,1],[4,8,1],[8,10,1],[8,11,1],[7,2,2],[5,3,2],[4,9,2],[5,9,2],[4,10,2],[6,11,2],[7,1,3],[9,1,3],[3,6,3],[3,7,3],[1,9,3],[8,2,4],[4,6,4],[3,10,4],[3,11,4],[7,11,4],[2,2,5],[1,3,5],[6,3,5],[7,3,5],[3,4,5],[1,7,5],[3,1,6],[8,2,6],[6,3,6],[6,4,6],[1,5,6],[1,6,6],[7,10,6],[7,11,6],[1,1,7],[4,5,7],[3,6,7],[2,7,7],[3,8,7],[11,9,7],[6,10,7],[2,1,8],[5,3,8],[4,5,8],[1,7,8],[3,8,8],[7,9,8],[3,10,8],[6,10,8],[7,10,8],[7,3,9],[3,9,9],[2,1,10],[6,8,10],[1,11,11],[10,11,11]],"ignoreExtent":false,"flags":3},"82":{"id":82,"type":"spheres","material":{},"vertices":[[5,4,1],[2,7,1],[2,8,1],[3,9,1],[7,1,2],[4,3,2],[2,9,2],[3,9,2],[4,11,2],[7,11,2],[3,8,3],[2,9,3],[7,4,4],[8,4,4],[2,3,5],[2,4,5],[3,5,5],[4,6,5],[8,11,5],[4,1,6],[1,2,6],[2,2,6],[5,3,6],[1,4,6],[2,5,6],[3,5,6],[1,7,6],[9,9,6],[1,3,7],[1,4,7],[4,4,7],[5,5,7],[10,9,7],[8,10,7],[7,3,8],[5,4,8],[2,6,8],[3,6,8],[1,9,8],[5,9,8],[2,11,8],[8,11,8],[6,10,9],[9,10,9],[1,11,9],[5,8,10],[2,10,11],[10,10,11]],"colors":[[0.7764706,1,0,1]],"radii":[[0.1218901]],"centers":[[5,4,1],[2,7,1],[2,8,1],[3,9,1],[7,1,2],[4,3,2],[2,9,2],[3,9,2],[4,11,2],[7,11,2],[3,8,3],[2,9,3],[7,4,4],[8,4,4],[2,3,5],[2,4,5],[3,5,5],[4,6,5],[8,11,5],[4,1,6],[1,2,6],[2,2,6],[5,3,6],[1,4,6],[2,5,6],[3,5,6],[1,7,6],[9,9,6],[1,3,7],[1,4,7],[4,4,7],[5,5,7],[10,9,7],[8,10,7],[7,3,8],[5,4,8],[2,6,8],[3,6,8],[1,9,8],[5,9,8],[2,11,8],[8,11,8],[6,10,9],[9,10,9],[1,11,9],[5,8,10],[2,10,11],[10,10,11]],"ignoreExtent":false,"flags":3},"83":{"id":83,"type":"spheres","material":{},"vertices":[[8,4,1],[3,6,1],[3,8,1],[5,8,1],[2,9,1],[4,9,1],[9,9,1],[9,11,1],[6,3,2],[1,10,2],[8,1,3],[4,2,3],[9,3,3],[4,4,3],[7,4,3],[4,8,3],[5,9,3],[3,10,3],[6,10,3],[7,1,4],[8,1,4],[4,2,4],[5,2,4],[2,9,4],[5,1,5],[7,4,5],[2,9,5],[11,9,5],[7,10,5],[4,2,6],[1,3,6],[2,4,6],[3,4,6],[5,4,6],[2,9,6],[8,10,6],[2,1,7],[3,1,7],[1,2,7],[8,2,7],[2,3,7],[4,3,7],[6,5,7],[2,6,7],[2,9,7],[8,9,7],[9,10,7],[8,3,8],[4,4,8],[2,5,8],[5,5,8],[11,9,8],[9,10,8],[7,11,8],[5,3,9],[7,8,9],[9,8,9],[4,10,9],[5,10,9],[8,10,9],[5,11,9],[6,11,9],[6,3,10],[1,7,10],[5,9,10],[5,10,10],[8,11,10],[10,11,10],[6,8,11],[10,8,11],[10,9,11],[4,10,11]],"colors":[[0.654902,1,0,1]],"radii":[[0.1353053]],"centers":[[8,4,1],[3,6,1],[3,8,1],[5,8,1],[2,9,1],[4,9,1],[9,9,1],[9,11,1],[6,3,2],[1,10,2],[8,1,3],[4,2,3],[9,3,3],[4,4,3],[7,4,3],[4,8,3],[5,9,3],[3,10,3],[6,10,3],[7,1,4],[8,1,4],[4,2,4],[5,2,4],[2,9,4],[5,1,5],[7,4,5],[2,9,5],[11,9,5],[7,10,5],[4,2,6],[1,3,6],[2,4,6],[3,4,6],[5,4,6],[2,9,6],[8,10,6],[2,1,7],[3,1,7],[1,2,7],[8,2,7],[2,3,7],[4,3,7],[6,5,7],[2,6,7],[2,9,7],[8,9,7],[9,10,7],[8,3,8],[4,4,8],[2,5,8],[5,5,8],[11,9,8],[9,10,8],[7,11,8],[5,3,9],[7,8,9],[9,8,9],[4,10,9],[5,10,9],[8,10,9],[5,11,9],[6,11,9],[6,3,10],[1,7,10],[5,9,10],[5,10,10],[8,11,10],[10,11,10],[6,8,11],[10,8,11],[10,9,11],[4,10,11]],"ignoreExtent":false,"flags":3},"84":{"id":84,"type":"spheres","material":{},"vertices":[[5,5,1],[3,10,1],[8,2,2],[3,6,2],[8,10,2],[9,1,4],[7,2,4],[5,9,4],[8,11,4],[6,2,5],[8,4,5],[1,8,5],[2,3,6],[4,3,6],[8,3,6],[7,4,6],[4,5,6],[5,5,6],[4,6,6],[2,11,6],[2,2,7],[3,4,7],[3,5,7],[4,6,7],[1,9,7],[2,10,7],[7,10,7],[9,11,7],[1,2,8],[8,2,8],[7,4,8],[6,5,8],[1,6,8],[2,9,8],[10,9,8],[2,1,9],[8,3,9],[6,4,9],[1,9,9],[4,9,9],[5,9,9],[11,9,9],[2,11,9],[4,11,9],[7,3,10],[4,10,10],[1,11,10],[5,10,11],[5,11,11]],"colors":[[0.5294118,1,0,1]],"radii":[[0.1489462]],"centers":[[5,5,1],[3,10,1],[8,2,2],[3,6,2],[8,10,2],[9,1,4],[7,2,4],[5,9,4],[8,11,4],[6,2,5],[8,4,5],[1,8,5],[2,3,6],[4,3,6],[8,3,6],[7,4,6],[4,5,6],[5,5,6],[4,6,6],[2,11,6],[2,2,7],[3,4,7],[3,5,7],[4,6,7],[1,9,7],[2,10,7],[7,10,7],[9,11,7],[1,2,8],[8,2,8],[7,4,8],[6,5,8],[1,6,8],[2,9,8],[10,9,8],[2,1,9],[8,3,9],[6,4,9],[1,9,9],[4,9,9],[5,9,9],[11,9,9],[2,11,9],[4,11,9],[7,3,10],[4,10,10],[1,11,10],[5,10,11],[5,11,11]],"ignoreExtent":false,"flags":3},"85":{"id":85,"type":"spheres","material":{},"vertices":[[8,3,1],[5,6,1],[9,8,1],[5,9,1],[1,11,1],[7,11,1],[10,11,1],[9,1,2],[5,7,2],[3,10,2],[9,10,2],[9,2,3],[5,3,3],[8,10,3],[3,11,3],[1,9,4],[7,10,4],[8,10,4],[6,1,5],[8,1,5],[4,2,5],[5,3,5],[6,4,5],[9,9,5],[2,11,5],[5,2,6],[4,4,6],[8,4,6],[6,5,6],[11,8,6],[7,9,6],[8,9,6],[9,10,6],[4,2,7],[2,4,7],[1,5,7],[2,5,7],[1,6,7],[4,7,7],[4,8,7],[7,9,7],[9,2,8],[1,3,8],[4,3,8],[1,5,8],[3,5,8],[9,8,8],[11,8,8],[1,10,8],[1,2,9],[9,2,9],[1,5,9],[3,7,9],[5,8,9],[8,8,9],[6,9,9],[10,9,9],[3,11,9],[10,11,9],[10,10,10],[7,11,10],[9,11,10]],"colors":[[0.4078431,1,0,1]],"radii":[[0.1627987]],"centers":[[8,3,1],[5,6,1],[9,8,1],[5,9,1],[1,11,1],[7,11,1],[10,11,1],[9,1,2],[5,7,2],[3,10,2],[9,10,2],[9,2,3],[5,3,3],[8,10,3],[3,11,3],[1,9,4],[7,10,4],[8,10,4],[6,1,5],[8,1,5],[4,2,5],[5,3,5],[6,4,5],[9,9,5],[2,11,5],[5,2,6],[4,4,6],[8,4,6],[6,5,6],[11,8,6],[7,9,6],[8,9,6],[9,10,6],[4,2,7],[2,4,7],[1,5,7],[2,5,7],[1,6,7],[4,7,7],[4,8,7],[7,9,7],[9,2,8],[1,3,8],[4,3,8],[1,5,8],[3,5,8],[9,8,8],[11,8,8],[1,10,8],[1,2,9],[9,2,9],[1,5,9],[3,7,9],[5,8,9],[8,8,9],[6,9,9],[10,9,9],[3,11,9],[10,11,9],[10,10,10],[7,11,10],[9,11,10]],"ignoreExtent":false,"flags":3},"86":{"id":86,"type":"spheres","material":{},"vertices":[[7,4,1],[3,7,1],[5,10,1],[9,2,2],[5,4,2],[7,4,2],[5,5,2],[8,5,2],[4,8,2],[5,8,2],[6,10,2],[10,1,3],[5,3,4],[6,4,4],[4,5,4],[7,5,4],[8,7,4],[10,1,5],[5,2,5],[5,4,5],[4,5,5],[7,5,5],[6,9,5],[8,10,5],[6,2,6],[6,9,6],[10,9,6],[2,10,6],[1,11,6],[9,11,6],[5,2,7],[8,3,7],[1,7,7],[2,8,7],[11,8,7],[1,10,7],[2,2,8],[3,2,8],[3,3,8],[4,6,8],[6,9,8],[8,2,9],[5,4,9],[2,5,9],[1,6,9],[3,8,9],[11,8,9],[2,9,9],[3,10,9],[7,11,9],[1,4,10],[2,5,10],[1,9,10],[4,9,10],[10,9,10],[1,10,10],[5,11,10],[1,5,11],[1,9,11]],"colors":[[0.2862745,1,0,1]],"radii":[[0.1768507]],"centers":[[7,4,1],[3,7,1],[5,10,1],[9,2,2],[5,4,2],[7,4,2],[5,5,2],[8,5,2],[4,8,2],[5,8,2],[6,10,2],[10,1,3],[5,3,4],[6,4,4],[4,5,4],[7,5,4],[8,7,4],[10,1,5],[5,2,5],[5,4,5],[4,5,5],[7,5,5],[6,9,5],[8,10,5],[6,2,6],[6,9,6],[10,9,6],[2,10,6],[1,11,6],[9,11,6],[5,2,7],[8,3,7],[1,7,7],[2,8,7],[11,8,7],[1,10,7],[2,2,8],[3,2,8],[3,3,8],[4,6,8],[6,9,8],[8,2,9],[5,4,9],[2,5,9],[1,6,9],[3,8,9],[11,8,9],[2,9,9],[3,10,9],[7,11,9],[1,4,10],[2,5,10],[1,9,10],[4,9,10],[10,9,10],[1,10,10],[5,11,10],[1,5,11],[1,9,11]],"ignoreExtent":false,"flags":3},"87":{"id":87,"type":"spheres","material":{},"vertices":[[4,10,1],[5,11,1],[3,7,2],[9,7,2],[9,8,2],[1,11,2],[9,11,2],[4,3,3],[6,4,3],[6,7,3],[1,10,3],[10,1,4],[4,3,4],[9,3,4],[9,7,4],[8,8,4],[9,8,4],[6,9,4],[1,10,4],[9,1,5],[7,2,5],[6,5,5],[5,8,5],[7,9,5],[2,10,5],[9,10,5],[9,11,5],[7,3,6],[7,5,6],[5,7,6],[5,8,6],[9,8,6],[1,9,6],[4,1,7],[9,2,7],[7,3,7],[6,9,7],[10,10,7],[3,1,8],[9,1,8],[2,3,8],[1,4,8],[2,4,8],[4,7,8],[4,8,8],[7,8,8],[8,8,8],[2,10,8],[1,4,9],[4,5,9],[5,5,9],[1,7,9],[1,10,9],[8,11,9],[9,11,9],[1,2,10],[1,8,10],[10,8,10],[11,8,10],[3,9,10],[2,1,11],[1,6,11],[4,9,11],[5,9,11],[3,10,11]],"colors":[[0.1647059,1,0,1]],"radii":[[0.1910914]],"centers":[[4,10,1],[5,11,1],[3,7,2],[9,7,2],[9,8,2],[1,11,2],[9,11,2],[4,3,3],[6,4,3],[6,7,3],[1,10,3],[10,1,4],[4,3,4],[9,3,4],[9,7,4],[8,8,4],[9,8,4],[6,9,4],[1,10,4],[9,1,5],[7,2,5],[6,5,5],[5,8,5],[7,9,5],[2,10,5],[9,10,5],[9,11,5],[7,3,6],[7,5,6],[5,7,6],[5,8,6],[9,8,6],[1,9,6],[4,1,7],[9,2,7],[7,3,7],[6,9,7],[10,10,7],[3,1,8],[9,1,8],[2,3,8],[1,4,8],[2,4,8],[4,7,8],[4,8,8],[7,8,8],[8,8,8],[2,10,8],[1,4,9],[4,5,9],[5,5,9],[1,7,9],[1,10,9],[8,11,9],[9,11,9],[1,2,10],[1,8,10],[10,8,10],[11,8,10],[3,9,10],[2,1,11],[1,6,11],[4,9,11],[5,9,11],[3,10,11]],"ignoreExtent":false,"flags":3},"88":{"id":88,"type":"spheres","material":{},"vertices":[[6,7,1],[8,9,1],[9,3,2],[5,6,2],[6,7,2],[3,8,2],[3,11,2],[5,4,3],[1,11,3],[4,4,4],[10,8,4],[8,9,4],[1,11,4],[9,2,5],[4,3,5],[9,3,5],[9,8,5],[10,8,5],[8,9,5],[10,9,5],[11,10,5],[9,2,6],[1,8,6],[10,8,6],[7,4,7],[9,8,7],[11,10,7],[5,2,8],[6,2,8],[7,2,8],[9,3,8],[3,4,8],[5,6,8],[2,8,8],[10,10,8],[11,10,8],[1,3,9],[9,3,9],[7,4,9],[2,7,9],[2,10,9],[11,10,9],[5,7,10],[4,8,10],[11,9,10],[1,4,11],[1,8,11],[5,8,11],[11,9,11]],"colors":[[0.03921569,1,0,1]],"radii":[[0.2055114]],"centers":[[6,7,1],[8,9,1],[9,3,2],[5,6,2],[6,7,2],[3,8,2],[3,11,2],[5,4,3],[1,11,3],[4,4,4],[10,8,4],[8,9,4],[1,11,4],[9,2,5],[4,3,5],[9,3,5],[9,8,5],[10,8,5],[8,9,5],[10,9,5],[11,10,5],[9,2,6],[1,8,6],[10,8,6],[7,4,7],[9,8,7],[11,10,7],[5,2,8],[6,2,8],[7,2,8],[9,3,8],[3,4,8],[5,6,8],[2,8,8],[10,10,8],[11,10,8],[1,3,9],[9,3,9],[7,4,9],[2,7,9],[2,10,9],[11,10,9],[5,7,10],[4,8,10],[11,9,10],[1,4,11],[1,8,11],[5,8,11],[11,9,11]],"ignoreExtent":false,"flags":3},"89":{"id":89,"type":"spheres","material":{},"vertices":[[7,1,1],[6,4,1],[9,7,1],[10,9,1],[2,10,1],[4,11,1],[6,11,1],[8,1,2],[6,4,2],[6,8,2],[7,10,2],[5,5,3],[5,7,3],[7,10,3],[9,2,4],[5,4,4],[8,5,4],[8,6,4],[6,8,4],[5,5,5],[5,1,6],[8,1,6],[9,1,6],[1,10,6],[11,10,6],[9,1,7],[6,2,7],[5,6,7],[5,7,7],[8,1,8],[4,2,8],[8,4,8],[1,8,8],[5,8,8],[9,11,8],[10,11,8],[8,1,9],[2,4,9],[3,6,9],[4,8,9],[10,8,9],[10,10,9],[8,2,10],[5,3,10],[3,8,10],[2,10,10],[3,10,10],[11,10,10],[4,8,11],[11,8,11],[2,9,11],[3,9,11],[11,10,11],[4,11,11],[11,11,11]],"colors":[[0,1,0.08235294,1]],"radii":[[0.2201021]],"centers":[[7,1,1],[6,4,1],[9,7,1],[10,9,1],[2,10,1],[4,11,1],[6,11,1],[8,1,2],[6,4,2],[6,8,2],[7,10,2],[5,5,3],[5,7,3],[7,10,3],[9,2,4],[5,4,4],[8,5,4],[8,6,4],[6,8,4],[5,5,5],[5,1,6],[8,1,6],[9,1,6],[1,10,6],[11,10,6],[9,1,7],[6,2,7],[5,6,7],[5,7,7],[8,1,8],[4,2,8],[8,4,8],[1,8,8],[5,8,8],[9,11,8],[10,11,8],[8,1,9],[2,4,9],[3,6,9],[4,8,9],[10,8,9],[10,10,9],[8,2,10],[5,3,10],[3,8,10],[2,10,10],[3,10,10],[11,10,10],[4,8,11],[11,8,11],[2,9,11],[3,9,11],[11,10,11],[4,11,11],[11,11,11]],"ignoreExtent":false,"flags":3},"90":{"id":90,"type":"spheres","material":{},"vertices":[[9,3,1],[9,4,1],[9,6,1],[11,10,1],[9,4,2],[9,6,2],[9,9,2],[10,10,2],[9,4,3],[6,5,3],[8,5,3],[5,6,3],[8,7,3],[9,7,3],[5,8,3],[6,8,3],[8,8,3],[9,8,3],[6,9,3],[9,9,4],[2,10,4],[2,11,4],[5,7,5],[11,8,5],[1,9,5],[1,10,5],[10,10,5],[1,11,5],[10,1,6],[9,3,6],[10,10,6],[8,4,7],[5,8,7],[10,11,7],[10,8,8],[9,1,9],[2,2,9],[7,2,9],[2,3,9],[3,3,9],[4,4,9],[10,4,9],[3,5,9],[2,6,9],[4,7,9],[1,8,9],[6,8,9],[3,1,10],[9,2,10],[1,3,10],[8,3,10],[6,4,10],[2,6,10],[2,9,10],[4,11,10],[11,11,10]],"colors":[[0,1,0.2039216,1]],"radii":[[0.2348559]],"centers":[[9,3,1],[9,4,1],[9,6,1],[11,10,1],[9,4,2],[9,6,2],[9,9,2],[10,10,2],[9,4,3],[6,5,3],[8,5,3],[5,6,3],[8,7,3],[9,7,3],[5,8,3],[6,8,3],[8,8,3],[9,8,3],[6,9,3],[9,9,4],[2,10,4],[2,11,4],[5,7,5],[11,8,5],[1,9,5],[1,10,5],[10,10,5],[1,11,5],[10,1,6],[9,3,6],[10,10,6],[8,4,7],[5,8,7],[10,11,7],[10,8,8],[9,1,9],[2,2,9],[7,2,9],[2,3,9],[3,3,9],[4,4,9],[10,4,9],[3,5,9],[2,6,9],[4,7,9],[1,8,9],[6,8,9],[3,1,10],[9,2,10],[1,3,10],[8,3,10],[6,4,10],[2,6,10],[2,9,10],[4,11,10],[11,11,10]],"ignoreExtent":false,"flags":3},"91":{"id":91,"type":"spheres","material":{},"vertices":[[6,5,1],[9,5,1],[6,8,1],[8,8,1],[3,11,1],[10,1,2],[6,5,2],[8,6,2],[7,8,2],[8,8,2],[6,9,2],[11,1,3],[7,5,3],[6,6,3],[9,11,3],[11,1,4],[9,4,4],[6,5,4],[9,6,4],[6,7,4],[4,4,5],[6,7,5],[9,7,5],[10,7,5],[7,2,6],[7,2,7],[10,2,7],[7,5,7],[10,8,7],[10,2,8],[5,7,8],[3,4,9],[6,5,9],[5,6,9],[5,7,9],[11,11,9],[2,4,10],[7,4,10],[8,7,11],[3,8,11],[2,11,11]],"colors":[[0,1,0.3254902,1]],"radii":[[0.249766]],"centers":[[6,5,1],[9,5,1],[6,8,1],[8,8,1],[3,11,1],[10,1,2],[6,5,2],[8,6,2],[7,8,2],[8,8,2],[6,9,2],[11,1,3],[7,5,3],[6,6,3],[9,11,3],[11,1,4],[9,4,4],[6,5,4],[9,6,4],[6,7,4],[4,4,5],[6,7,5],[9,7,5],[10,7,5],[7,2,6],[7,2,7],[10,2,7],[7,5,7],[10,8,7],[10,2,8],[5,7,8],[3,4,9],[6,5,9],[5,6,9],[5,7,9],[11,11,9],[2,4,10],[7,4,10],[8,7,11],[3,8,11],[2,11,11]],"ignoreExtent":false,"flags":3},"92":{"id":92,"type":"spheres","material":{},"vertices":[[8,2,1],[8,5,1],[7,8,1],[7,10,1],[9,5,2],[6,6,2],[8,7,2],[8,9,2],[8,9,3],[5,5,4],[7,7,4],[10,7,4],[5,8,4],[9,10,4],[7,1,5],[10,2,5],[7,7,5],[8,7,5],[6,8,5],[10,2,6],[5,6,6],[7,7,6],[9,7,6],[10,7,6],[10,11,6],[10,1,7],[1,8,7],[10,3,8],[3,1,9],[3,2,9],[10,2,9],[4,3,9],[8,4,9],[11,4,9],[4,6,9],[8,1,10],[7,2,10],[11,4,10],[3,5,10],[7,7,10],[2,11,10],[3,1,11],[3,2,11],[3,3,11],[5,3,11],[11,4,11],[9,7,11],[10,7,11]],"colors":[[0,1,0.4470588,1]],"radii":[[0.2648259]],"centers":[[8,2,1],[8,5,1],[7,8,1],[7,10,1],[9,5,2],[6,6,2],[8,7,2],[8,9,2],[8,9,3],[5,5,4],[7,7,4],[10,7,4],[5,8,4],[9,10,4],[7,1,5],[10,2,5],[7,7,5],[8,7,5],[6,8,5],[10,2,6],[5,6,6],[7,7,6],[9,7,6],[10,7,6],[10,11,6],[10,1,7],[1,8,7],[10,3,8],[3,1,9],[3,2,9],[10,2,9],[4,3,9],[8,4,9],[11,4,9],[4,6,9],[8,1,10],[7,2,10],[11,4,10],[3,5,10],[7,7,10],[2,11,10],[3,1,11],[3,2,11],[3,3,11],[5,3,11],[11,4,11],[9,7,11],[10,7,11]],"ignoreExtent":false,"flags":3},"93":{"id":93,"type":"spheres","material":{},"vertices":[[9,2,1],[6,6,1],[11,11,1],[2,10,2],[10,2,3],[7,7,3],[2,10,3],[9,10,3],[7,9,4],[11,1,5],[8,8,5],[6,7,6],[6,8,6],[7,8,6],[5,1,7],[8,1,7],[9,3,7],[10,3,7],[11,7,7],[10,1,8],[10,4,8],[7,5,8],[5,2,9],[6,2,9],[10,3,9],[2,2,10],[3,6,10],[6,7,10],[1,2,11],[10,6,11],[11,7,11],[2,8,11]],"colors":[[0,1,0.572549,1]],"radii":[[0.28003]],"centers":[[9,2,1],[6,6,1],[11,11,1],[2,10,2],[10,2,3],[7,7,3],[2,10,3],[9,10,3],[7,9,4],[11,1,5],[8,8,5],[6,7,6],[6,8,6],[7,8,6],[5,1,7],[8,1,7],[9,3,7],[10,3,7],[11,7,7],[10,1,8],[10,4,8],[7,5,8],[5,2,9],[6,2,9],[10,3,9],[2,2,10],[3,6,10],[6,7,10],[1,2,11],[10,6,11],[11,7,11],[2,8,11]],"ignoreExtent":false,"flags":3},"94":{"id":94,"type":"spheres","material":{},"vertices":[[2,11,1],[11,1,2],[10,2,2],[7,5,2],[8,6,3],[9,9,3],[11,9,4],[9,4,5],[8,5,5],[10,11,5],[9,4,6],[8,5,6],[7,6,6],[8,7,6],[11,7,6],[7,8,7],[4,1,8],[11,4,8],[6,8,8],[9,4,9],[10,2,10],[5,4,10],[10,4,10],[5,5,10],[5,6,10],[2,7,10],[8,7,10],[2,8,10],[6,3,11],[3,4,11],[11,5,11]],"colors":[[0,1,0.6941177,1]],"radii":[[0.2953729]],"centers":[[2,11,1],[11,1,2],[10,2,2],[7,5,2],[8,6,3],[9,9,3],[11,9,4],[9,4,5],[8,5,5],[10,11,5],[9,4,6],[8,5,6],[7,6,6],[8,7,6],[11,7,6],[7,8,7],[4,1,8],[11,4,8],[6,8,8],[9,4,9],[10,2,10],[5,4,10],[10,4,10],[5,5,10],[5,6,10],[2,7,10],[8,7,10],[2,8,10],[6,3,11],[3,4,11],[11,5,11]],"ignoreExtent":false,"flags":3},"95":{"id":95,"type":"spheres","material":{},"vertices":[[10,8,1],[7,9,1],[7,7,2],[7,9,2],[10,11,2],[9,6,3],[2,11,3],[10,2,4],[7,6,4],[5,7,4],[7,8,4],[10,3,5],[7,8,5],[10,3,6],[8,8,6],[10,4,7],[7,7,7],[5,1,8],[11,2,8],[2,8,9],[3,3,10],[3,4,10],[4,5,10],[3,7,10],[4,7,10],[2,2,11],[2,4,11],[6,7,11],[7,7,11]],"colors":[[0,1,0.8156863,1]],"radii":[[0.3108499]],"centers":[[10,8,1],[7,9,1],[7,7,2],[7,9,2],[10,11,2],[9,6,3],[2,11,3],[10,2,4],[7,6,4],[5,7,4],[7,8,4],[10,3,5],[7,8,5],[10,3,6],[8,8,6],[10,4,7],[7,7,7],[5,1,8],[11,2,8],[2,8,9],[3,3,10],[3,4,10],[4,5,10],[3,7,10],[4,7,10],[2,2,11],[2,4,11],[6,7,11],[7,7,11]],"ignoreExtent":false,"flags":3},"96":{"id":96,"type":"spheres","material":{},"vertices":[[11,1,1],[6,10,1],[9,5,3],[7,8,3],[10,8,3],[7,9,3],[9,5,4],[6,6,4],[10,6,4],[9,11,4],[5,6,5],[7,6,5],[11,7,5],[11,11,5],[6,6,6],[9,7,7],[8,8,7],[9,4,8],[11,11,8],[10,1,9],[4,2,9],[11,2,9],[9,1,10],[6,2,10],[2,3,10],[9,3,10],[3,11,10],[4,3,11],[1,7,11],[5,7,11]],"colors":[[0,1,0.9372549,1]],"radii":[[0.3264565]],"centers":[[11,1,1],[6,10,1],[9,5,3],[7,8,3],[10,8,3],[7,9,3],[9,5,4],[6,6,4],[10,6,4],[9,11,4],[5,6,5],[7,6,5],[11,7,5],[11,11,5],[6,6,6],[9,7,7],[8,8,7],[9,4,8],[11,11,8],[10,1,9],[4,2,9],[11,2,9],[9,1,10],[6,2,10],[2,3,10],[9,3,10],[3,11,10],[4,3,11],[1,7,11],[5,7,11]],"ignoreExtent":false,"flags":3},"97":{"id":97,"type":"spheres","material":{},"vertices":[[7,5,1],[10,6,1],[2,11,2],[10,3,3],[10,9,4],[8,6,5],[6,1,6],[10,4,6],[8,6,6],[11,1,7],[11,2,7],[10,7,7],[11,3,8],[7,7,8],[4,1,9],[5,1,9],[10,3,10],[4,6,10],[8,1,11],[8,2,11],[1,3,11],[7,3,11],[4,4,11],[5,4,11],[10,5,11],[11,6,11]],"colors":[[0,0.9372549,1,1]],"radii":[[0.3421884]],"centers":[[7,5,1],[10,6,1],[2,11,2],[10,3,3],[10,9,4],[8,6,5],[6,1,6],[10,4,6],[8,6,6],[11,1,7],[11,2,7],[10,7,7],[11,3,8],[7,7,8],[4,1,9],[5,1,9],[10,3,10],[4,6,10],[8,1,11],[8,2,11],[1,3,11],[7,3,11],[4,4,11],[5,4,11],[10,5,11],[11,6,11]],"ignoreExtent":false,"flags":3},"98":{"id":98,"type":"spheres","material":{},"vertices":[[6,9,1],[10,3,2],[10,8,2],[5,6,4],[11,8,4],[6,6,5],[11,1,6],[8,5,7],[8,7,7],[8,7,8],[11,7,8],[11,3,9],[10,1,10],[9,2,11]],"colors":[[0,0.8156863,1,1]],"radii":[[0.3580418]],"centers":[[6,9,1],[10,3,2],[10,8,2],[5,6,4],[11,8,4],[6,6,5],[11,1,6],[8,5,7],[8,7,7],[8,7,8],[11,7,8],[11,3,9],[10,1,10],[9,2,11]],"ignoreExtent":false,"flags":3},"99":{"id":99,"type":"spheres","material":{},"vertices":[[8,6,1],[7,7,1],[11,10,2],[11,11,2],[10,3,4],[11,10,4],[9,6,5],[10,6,5],[11,4,7],[11,1,8],[8,5,8],[9,7,8],[7,1,9],[7,5,9],[10,5,9],[11,7,9],[3,2,10],[5,2,10],[9,7,10],[10,2,11],[6,4,11],[2,5,11],[3,11,11]],"colors":[[0,0.6941177,1,1]],"radii":[[0.3740132]],"centers":[[8,6,1],[7,7,1],[11,10,2],[11,11,2],[10,3,4],[11,10,4],[9,6,5],[10,6,5],[11,4,7],[11,1,8],[8,5,8],[9,7,8],[7,1,9],[7,5,9],[10,5,9],[11,7,9],[3,2,10],[5,2,10],[9,7,10],[10,2,11],[6,4,11],[2,5,11],[3,11,11]],"ignoreExtent":false,"flags":3},"100":{"id":100,"type":"spheres","material":{},"vertices":[[8,7,1],[10,9,2],[10,7,3],[10,10,3],[11,2,4],[10,10,4],[10,4,5],[7,1,6],[11,3,7],[11,5,7],[7,6,7],[6,7,7],[6,8,7],[7,1,8],[10,7,8],[7,7,9],[4,1,10],[5,1,10],[7,1,10],[8,4,10],[4,2,11],[2,3,11],[10,4,11],[4,7,11]],"colors":[[0,0.572549,1,1]],"radii":[[0.390099]],"centers":[[8,7,1],[10,9,2],[10,7,3],[10,10,3],[11,2,4],[10,10,4],[10,4,5],[7,1,6],[11,3,7],[11,5,7],[7,6,7],[6,7,7],[6,8,7],[7,1,8],[10,7,8],[7,7,9],[4,1,10],[5,1,10],[7,1,10],[8,4,10],[4,2,11],[2,3,11],[10,4,11],[4,7,11]],"ignoreExtent":false,"flags":3},"101":{"id":101,"type":"spheres","material":{},"vertices":[[10,5,1],[11,9,1],[10,6,3],[11,11,4],[11,2,5],[11,3,6],[10,6,6],[11,11,6],[9,4,7],[6,6,7],[10,5,8],[11,5,8],[6,6,8],[7,6,8],[6,7,8],[9,7,9],[10,7,9],[4,4,10],[10,5,10],[7,2,11]],"colors":[[0,0.4470588,1,1]],"radii":[[0.4062962]],"centers":[[10,5,1],[11,9,1],[10,6,3],[11,11,4],[11,2,5],[11,3,6],[10,6,6],[11,11,6],[9,4,7],[6,6,7],[10,5,8],[11,5,8],[6,6,8],[7,6,8],[6,7,8],[9,7,9],[10,7,9],[4,4,10],[10,5,10],[7,2,11]],"ignoreExtent":false,"flags":3},"102":{"id":102,"type":"spheres","material":{},"vertices":[[10,1,1],[10,7,1],[11,2,2],[10,6,2],[11,2,3],[7,6,3],[11,3,5],[9,5,5],[11,4,6],[10,5,6],[11,5,6],[10,5,7],[11,11,7],[6,1,9],[6,7,9],[8,7,9],[6,1,10],[4,3,10],[9,4,10],[6,5,10],[11,7,10],[4,5,11],[5,5,11],[4,6,11],[5,6,11]],"colors":[[0,0.3254902,1,1]],"radii":[[0.4226018]],"centers":[[10,1,1],[10,7,1],[11,2,2],[10,6,2],[11,2,3],[7,6,3],[11,3,5],[9,5,5],[11,4,6],[10,5,6],[11,5,6],[10,5,7],[11,11,7],[6,1,9],[6,7,9],[8,7,9],[6,1,10],[4,3,10],[9,4,10],[6,5,10],[11,7,10],[4,5,11],[5,5,11],[4,6,11],[5,6,11]],"ignoreExtent":false,"flags":3},"103":{"id":103,"type":"spheres","material":{},"vertices":[[10,4,1],[11,11,3],[11,3,4],[11,2,6],[9,6,6],[11,6,7],[11,5,9],[11,2,10],[11,3,10],[11,5,10],[10,7,10],[4,1,11],[5,2,11],[10,3,11],[3,5,11]],"colors":[[0,0.2039216,1,1]],"radii":[[0.4390129]],"centers":[[10,4,1],[11,11,3],[11,3,4],[11,2,6],[9,6,6],[11,6,7],[11,5,9],[11,2,10],[11,3,10],[11,5,10],[10,7,10],[4,1,11],[5,2,11],[10,3,11],[3,5,11]],"ignoreExtent":false,"flags":3},"104":{"id":104,"type":"spheres","material":{},"vertices":[[11,8,1],[10,4,2],[7,6,2],[10,4,4],[10,5,5],[9,5,6],[6,1,8],[11,1,9],[10,6,10],[9,1,11],[2,6,11],[6,6,11],[8,6,11]],"colors":[[0,0.08235294,1,1]],"radii":[[0.4555269]],"centers":[[11,8,1],[10,4,2],[7,6,2],[10,4,4],[10,5,5],[9,5,6],[6,1,8],[11,1,9],[10,6,10],[9,1,11],[2,6,11],[6,6,11],[8,6,11]],"ignoreExtent":false,"flags":3},"105":{"id":105,"type":"spheres","material":{},"vertices":[[10,2,1],[10,3,1],[10,7,2],[10,9,3],[11,10,3],[11,7,4],[10,11,4],[8,5,9],[4,2,10],[7,5,10],[6,6,10],[7,1,11],[8,3,11],[11,3,11],[9,6,11]],"colors":[[0.03921569,0,1,1]],"radii":[[0.4721413]],"centers":[[10,2,1],[10,3,1],[10,7,2],[10,9,3],[11,10,3],[11,7,4],[10,11,4],[8,5,9],[4,2,10],[7,5,10],[6,6,10],[7,1,11],[8,3,11],[11,3,11],[9,6,11]],"ignoreExtent":false,"flags":3},"106":{"id":106,"type":"spheres","material":{},"vertices":[[11,2,1],[11,3,2],[11,4,5],[11,6,6],[7,1,7]],"colors":[[0.1647059,0,1,1]],"radii":[[0.4888537]],"centers":[[11,2,1],[11,3,2],[11,4,5],[11,6,6],[7,1,7]],"ignoreExtent":false,"flags":3},"107":{"id":107,"type":"spheres","material":{},"vertices":[[10,11,3],[11,6,8],[5,1,11],[10,1,11],[11,2,11],[9,3,11],[7,4,11],[3,6,11]],"colors":[[0.2862745,0,1,1]],"radii":[[0.5056619]],"centers":[[10,11,3],[11,6,8],[5,1,11],[10,1,11],[11,2,11],[9,3,11],[7,4,11],[3,6,11]],"ignoreExtent":false,"flags":3},"108":{"id":108,"type":"spheres","material":{},"vertices":[[9,1,1],[11,3,1],[11,6,1],[11,7,1],[10,4,3],[11,4,4],[11,5,5],[11,6,5],[6,1,7],[9,5,9],[6,6,9],[6,2,11],[6,5,11]],"colors":[[0.4078431,0,1,1]],"radii":[[0.5225638]],"centers":[[9,1,1],[11,3,1],[11,6,1],[11,7,1],[10,4,3],[11,4,4],[11,5,5],[11,6,5],[6,1,7],[9,5,9],[6,6,9],[6,2,11],[6,5,11]],"ignoreExtent":false,"flags":3},"109":{"id":109,"type":"spheres","material":{},"vertices":[[7,6,1],[11,8,2],[11,9,2],[11,3,3],[11,6,3],[11,8,3],[10,5,4],[8,6,7],[7,6,9],[10,6,9],[11,6,9]],"colors":[[0.5294118,0,1,1]],"radii":[[0.5395573]],"centers":[[7,6,1],[11,8,2],[11,9,2],[11,3,3],[11,6,3],[11,8,3],[10,5,4],[8,6,7],[7,6,9],[10,6,9],[11,6,9]],"ignoreExtent":false,"flags":3},"110":{"id":110,"type":"spheres","material":{},"vertices":[[10,5,2],[11,9,3],[11,6,4],[7,6,10],[11,6,10],[9,5,11]],"colors":[[0.654902,0,1,1]],"radii":[[0.5566405]],"centers":[[10,5,2],[11,9,3],[11,6,4],[7,6,10],[11,6,10],[9,5,11]],"ignoreExtent":false,"flags":3},"111":{"id":111,"type":"spheres","material":{},"vertices":[[9,5,7],[10,6,7],[11,1,10],[7,6,11]],"colors":[[0.7764706,0,1,1]],"radii":[[0.5738115]],"centers":[[9,5,7],[10,6,7],[11,1,10],[7,6,11]],"ignoreExtent":false,"flags":3},"112":{"id":112,"type":"spheres","material":{},"vertices":[[11,5,1],[11,7,3],[9,5,8],[8,6,10],[2,7,11]],"colors":[[0.8980392,0,1,1]],"radii":[[0.5910686]],"centers":[[11,5,1],[11,7,3],[9,5,8],[8,6,10],[2,7,11]],"ignoreExtent":false,"flags":3},"113":{"id":113,"type":"spheres","material":{},"vertices":[[10,5,3],[8,5,10],[6,1,11],[3,7,11]],"colors":[[1,0,0.9803922,1]],"radii":[[0.6084101]],"centers":[[10,5,3],[8,5,10],[6,1,11],[3,7,11]],"ignoreExtent":false,"flags":3},"114":{"id":114,"type":"spheres","material":{},"vertices":[[8,6,8],[9,5,10],[7,5,11]],"colors":[[1,0,0.8588235,1]],"radii":[[0.6258343]],"centers":[[8,6,8],[9,5,10],[7,5,11]],"ignoreExtent":false,"flags":3},"115":{"id":115,"type":"spheres","material":{},"vertices":[[8,1,1],[11,5,4],[10,6,8],[9,6,9],[9,6,10]],"colors":[[1,0,0.7333333,1]],"radii":[[0.6433399]],"centers":[[8,1,1],[11,5,4],[10,6,8],[9,6,9],[9,6,10]],"ignoreExtent":false,"flags":3},"116":{"id":116,"type":"spheres","material":{},"vertices":[[11,4,1],[11,6,2],[9,6,7],[8,5,11]],"colors":[[1,0,0.6117647,1]],"radii":[[0.6609251]],"centers":[[11,4,1],[11,6,2],[9,6,7],[8,5,11]],"ignoreExtent":false,"flags":3},"117":{"id":117,"type":"spheres","material":{},"vertices":[[11,4,2],[11,4,3],[8,4,11],[9,4,11]],"colors":[[1,0,0.4901961,1]],"radii":[[0.6785887]],"centers":[[11,4,2],[11,4,3],[8,4,11],[9,4,11]],"ignoreExtent":false,"flags":3},"118":{"id":118,"type":"spheres","material":{},"vertices":[[8,6,9]],"colors":[[1,0,0.3686275,1]],"radii":[[0.6963294]],"centers":[[8,6,9]],"ignoreExtent":false,"flags":3},"119":{"id":119,"type":"spheres","material":{},"vertices":[[11,7,2],[11,5,3]],"colors":[[1,0,0.2431373,1]],"radii":[[0.7141455]],"centers":[[11,7,2],[11,5,3]],"ignoreExtent":false,"flags":3},"120":{"id":120,"type":"spheres","material":{},"vertices":[[11,5,2],[9,6,8],[11,1,11]],"colors":[[1,0,0.1215686,1]],"radii":[[0.7320362]],"centers":[[11,5,2],[9,6,8],[11,1,11]],"ignoreExtent":false,"flags":3},"121":{"id":121,"type":"text","material":{"lit":false},"vertices":[[6.194924,13.41045,13.66314]],"colors":[[0,0,1,1]],"texts":[["QVM Contingency"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[6.194924,13.41045,13.66314]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"122":{"id":122,"type":"text","material":{"lit":false},"vertices":[[6.194924,-1.636826,-1.592032]],"colors":[[0,0,1,1]],"texts":[["Quality.Rank"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[6.194924,-1.636826,-1.592032]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"123":{"id":123,"type":"text","material":{"lit":false},"vertices":[[-1.21927,5.886813,-1.592032]],"colors":[[0,0,1,1]],"texts":[["Value.Rank"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[-1.21927,5.886813,-1.592032]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"124":{"id":124,"type":"text","material":{"lit":false},"vertices":[[-1.21927,-1.636826,6.035556]],"colors":[[0,0,1,1]],"texts":[["Momentum.Rank"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[-1.21927,-1.636826,6.035556]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"125":{"id":125,"type":"lines","material":{"lit":false},"vertices":[[1,0.09939835,0.1681804],[11,0.09939835,0.1681804],[1,0.09939835,0.1681804],[1,-0.1899724,-0.1251883],[2,0.09939835,0.1681804],[2,-0.1899724,-0.1251883],[3,0.09939835,0.1681804],[3,-0.1899724,-0.1251883],[4,0.09939835,0.1681804],[4,-0.1899724,-0.1251883],[6,0.09939835,0.1681804],[6,-0.1899724,-0.1251883],[7,0.09939835,0.1681804],[7,-0.1899724,-0.1251883],[8,0.09939835,0.1681804],[8,-0.1899724,-0.1251883],[9,0.09939835,0.1681804],[9,-0.1899724,-0.1251883],[11,0.09939835,0.1681804],[11,-0.1899724,-0.1251883]],"colors":[[0,0,0,1]],"centers":[[6,0.09939835,0.1681804],[1,-0.04528701,0.02149604],[2,-0.04528701,0.02149604],[3,-0.04528701,0.02149604],[4,-0.04528701,0.02149604],[6,-0.04528701,0.02149604],[7,-0.04528701,0.02149604],[8,-0.04528701,0.02149604],[9,-0.04528701,0.02149604],[11,-0.04528701,0.02149604]],"ignoreExtent":true,"flags":128},"126":{"id":126,"type":"text","material":{"lit":false},"vertices":[[1,-0.7687138,-0.7119259],[2,-0.7687138,-0.7119259],[3,-0.7687138,-0.7119259],[4,-0.7687138,-0.7119259],[6,-0.7687138,-0.7119259],[7,-0.7687138,-0.7119259],[8,-0.7687138,-0.7119259],[9,-0.7687138,-0.7119259],[11,-0.7687138,-0.7119259]],"colors":[[0,0,0,1]],"texts":[["(19,30]"],["(30,40]"],["(40,47]"],["(47,54]"],["(60,66]"],["(66,72]"],["(72,78]"],["(78,84]"],["(89,95]"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[1,-0.7687138,-0.7119259],[2,-0.7687138,-0.7119259],[3,-0.7687138,-0.7119259],[4,-0.7687138,-0.7119259],[6,-0.7687138,-0.7119259],[7,-0.7687138,-0.7119259],[8,-0.7687138,-0.7119259],[9,-0.7687138,-0.7119259],[11,-0.7687138,-0.7119259]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"127":{"id":127,"type":"lines","material":{"lit":false},"vertices":[[0.4916983,1,0.1681804],[0.4916983,11,0.1681804],[0.4916983,1,0.1681804],[0.206537,1,-0.1251883],[0.4916983,2,0.1681804],[0.206537,2,-0.1251883],[0.4916983,3,0.1681804],[0.206537,3,-0.1251883],[0.4916983,4,0.1681804],[0.206537,4,-0.1251883],[0.4916983,6,0.1681804],[0.206537,6,-0.1251883],[0.4916983,7,0.1681804],[0.206537,7,-0.1251883],[0.4916983,8,0.1681804],[0.206537,8,-0.1251883],[0.4916983,9,0.1681804],[0.206537,9,-0.1251883],[0.4916983,11,0.1681804],[0.206537,11,-0.1251883]],"colors":[[0,0,0,1]],"centers":[[0.4916983,6,0.1681804],[0.3491176,1,0.02149604],[0.3491176,2,0.02149604],[0.3491176,3,0.02149604],[0.3491176,4,0.02149604],[0.3491176,6,0.02149604],[0.3491176,7,0.02149604],[0.3491176,8,0.02149604],[0.3491176,9,0.02149604],[0.3491176,11,0.02149604]],"ignoreExtent":true,"flags":128},"128":{"id":128,"type":"text","material":{"lit":false},"vertices":[[-0.3637856,1,-0.7119259],[-0.3637856,2,-0.7119259],[-0.3637856,3,-0.7119259],[-0.3637856,4,-0.7119259],[-0.3637856,6,-0.7119259],[-0.3637856,7,-0.7119259],[-0.3637856,8,-0.7119259],[-0.3637856,9,-0.7119259],[-0.3637856,11,-0.7119259]],"colors":[[0,0,0,1]],"texts":[["(10,17]"],["(17,24]"],["(24,31]"],["(31,38]"],["(45,52]"],["(52,59]"],["(59,66]"],["(66,73]"],["(80,88]"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[-0.3637856,1,-0.7119259],[-0.3637856,2,-0.7119259],[-0.3637856,3,-0.7119259],[-0.3637856,4,-0.7119259],[-0.3637856,6,-0.7119259],[-0.3637856,7,-0.7119259],[-0.3637856,8,-0.7119259],[-0.3637856,9,-0.7119259],[-0.3637856,11,-0.7119259]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"129":{"id":129,"type":"lines","material":{"lit":false},"vertices":[[0.4916983,0.09939835,1],[0.4916983,0.09939835,11],[0.4916983,0.09939835,1],[0.206537,-0.1899724,1],[0.4916983,0.09939835,2],[0.206537,-0.1899724,2],[0.4916983,0.09939835,3],[0.206537,-0.1899724,3],[0.4916983,0.09939835,4],[0.206537,-0.1899724,4],[0.4916983,0.09939835,6],[0.206537,-0.1899724,6],[0.4916983,0.09939835,7],[0.206537,-0.1899724,7],[0.4916983,0.09939835,8],[0.206537,-0.1899724,8],[0.4916983,0.09939835,9],[0.206537,-0.1899724,9],[0.4916983,0.09939835,11],[0.206537,-0.1899724,11]],"colors":[[0,0,0,1]],"centers":[[0.4916983,0.09939835,6],[0.3491176,-0.04528701,1],[0.3491176,-0.04528701,2],[0.3491176,-0.04528701,3],[0.3491176,-0.04528701,4],[0.3491176,-0.04528701,6],[0.3491176,-0.04528701,7],[0.3491176,-0.04528701,8],[0.3491176,-0.04528701,9],[0.3491176,-0.04528701,11]],"ignoreExtent":true,"flags":128},"130":{"id":130,"type":"text","material":{"lit":false},"vertices":[[-0.3637856,-0.7687138,1],[-0.3637856,-0.7687138,2],[-0.3637856,-0.7687138,3],[-0.3637856,-0.7687138,4],[-0.3637856,-0.7687138,6],[-0.3637856,-0.7687138,7],[-0.3637856,-0.7687138,8],[-0.3637856,-0.7687138,9],[-0.3637856,-0.7687138,11]],"colors":[[0,0,0,1]],"texts":[["(17,29]"],["(29,38]"],["(38,46]"],["(46,53]"],["(61,68]"],["(68,74]"],["(74,80]"],["(80,85]"],["(90,95]"]],"cex":[[1]],"adj":[[0.5,0.5]],"centers":[[-0.3637856,-0.7687138,1],[-0.3637856,-0.7687138,2],[-0.3637856,-0.7687138,3],[-0.3637856,-0.7687138,4],[-0.3637856,-0.7687138,6],[-0.3637856,-0.7687138,7],[-0.3637856,-0.7687138,8],[-0.3637856,-0.7687138,9],[-0.3637856,-0.7687138,11]],"family":[["sans"]],"font":[[1]],"ignoreExtent":true,"flags":4136},"70":{"id":70,"type":"light","vertices":[[0,0,1]],"colors":[[1,1,1,1],[1,1,1,1],[1,1,1,1]],"viewpoint":true,"finite":false},"69":{"id":69,"type":"background","material":{"fog":true},"colors":[[0.2980392,0.2980392,0.2980392,1]],"centers":[[0,0,0]],"sphere":false,"fogtype":"none","flags":0},"71":{"id":71,"type":"background","material":{"lit":false,"back":"lines"},"colors":[[1,1,1,1]],"centers":[[0,0,0]],"sphere":false,"fogtype":"none","flags":0},"66":{"id":66,"type":"subscene","par3d":{"antialias":0,"FOV":30,"ignoreExtent":false,"listeners":66,"mouseMode":{"left":"trackball","right":"zoom","middle":"zoom","wheel":"push"},"observer":[0,0,37.59544],"modelMatrix":[[1,0,0,-6.194924],[0,0.3420202,0.9396926,-7.684976],[0,-0.9396926,0.3420202,-34.12792],[0,0,0,1]],"projMatrix":[[3.732051,0,0,0],[0,3.732051,0,0],[0,0,-3.863703,-135.5272],[0,0,-1,0]],"skipRedraw":false,"userMatrix":[[1,0,0,0],[0,0.3420201,0.9396926,0],[0,-0.9396926,0.3420201,0],[0,0,0,1]],"scale":[1,1,1],"viewport":{"x":0,"y":0,"width":1,"height":1},"zoom":1,"bbox":[0.6578116,11.73204,0.2679638,11.50566,0.3390749,11.73204],"windowRect":[268,291,524,547],"family":"sans","font":1,"cex":1,"useFreeType":false,"fontname":"TT Arial","maxClipPlanes":6,"glVersion":1.1},"embeddings":{"viewport":"replace","projection":"replace","model":"replace"},"objects":[71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,70],"subscenes":[],"flags":5291}},"snapshot":"data:image/png;base64,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","width":1000,"height":1000,"sphereVerts":{"vb":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1950903,-0.3826834,-0.5555702,-0.7071068,-0.8314696,-0.9238795,-0.9807853,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1],[0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1950903,-0.3826834,-0.5555702,-0.7071068,-0.8314696,-0.9238795,-0.9807853,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0]],"it":[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270],[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271]],"primitivetype":"triangle","material":null,"normals":null,"texcoords":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,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.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1]]}});
rgl.prefix = "";
</script>
<p id="debug">
You must enable Javascript to view this page properly.</p>
</div>
<br>Drag mouse to rotate model. Use mouse wheel or middle button
to zoom it.
<hr>
<br>
Object written from rgl 0.98.1 by writeWebGL.
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment