diff options
Diffstat (limited to 'demos/webgl/CubicVR.js')
| -rw-r--r-- | demos/webgl/CubicVR.js | 11660 |
1 files changed, 0 insertions, 11660 deletions
diff --git a/demos/webgl/CubicVR.js b/demos/webgl/CubicVR.js deleted file mode 100644 index 897fc887..00000000 --- a/demos/webgl/CubicVR.js +++ /dev/null @@ -1,11660 +0,0 @@ -/* - Javascript port of CubicVR 3D engine for WebGL - by Charles J. Cliffe - http://www.cubicvr.org/ - - May be used under the terms of LGPL v3.0 or greater. -*/ - -/*globals alert: false */ - -/** Global Constants **/ -var M_PI = 3.1415926535897932384626433832795028841968; -var M_TWO_PI = 2.0 * M_PI; -var M_HALF_PI = M_PI / 2.0; - -var SCRIPT_LOCATION = ""; - -try { - Array.forEach(document.querySelectorAll("script"), function (a) { - var pos = a.src.lastIndexOf('/CubicVR.js'); - if (pos > -1) { - SCRIPT_LOCATION = a.src.substr(0, pos) + "/"; - } //if - }); -} -catch(e) { - // likely that 'document' is not defined (doesn't really matter) -} //try - -(function(undef) { - - var CubicVR = this.CubicVR = {}; - - var GLCore = {}; - var Materials = []; - var Material_ref = []; - var Textures = []; - var Textures_obj = []; - var Texture_ref = []; - var Images = []; - var ShaderPool = []; - var MeshPool = []; - - var CoreShader_vs = null; - var CoreShader_fs = null; - - var log; - try { - log = (console !== undefined && console.log) ? - function(msg) { console.log("CubicVR Log: " + msg); } : - function() {}; - } - catch(e) { - log = function() {}; - } //try - - var enums = { - // Math - math: {}, - - frustum: { - plane: { - LEFT: 0, - RIGHT: 1, - TOP: 2, - BOTTOM: 3, - NEAR: 4, - FAR: 5 - } - }, - - octree: { - TOP_NW: 0, - TOP_NE: 1, - TOP_SE: 2, - TOP_SW: 3, - BOTTOM_NW: 4, - BOTTOM_NE: 5, - BOTTOM_SE: 6, - BOTTOM_SW: 7 - }, - - - // Light Types - light: { - type: { - NULL: 0, - POINT: 1, - DIRECTIONAL: 2, - SPOT: 3, - AREA: 4, - MAX: 5 - }, - method: { - GLOBAL: 0, - STATIC: 1, - DYNAMIC: 2 - } - }, - - // Texture Types - texture: { - map: { - COLOR: 0, - ENVSPHERE: 1, - NORMAL: 2, - BUMP: 3, - REFLECT: 4, - SPECULAR: 5, - AMBIENT: 6, - ALPHA: 7, - MAX: 8 - }, - filter: { - LINEAR: 0, - LINEAR_MIP: 1, - NEAREST: 2, - NEAREST_MIP: 3 - } - }, - - uv: { - /* UV Axis enums */ - axis: { - X: 0, - Y: 1, - Z: 2 - }, - - /* UV Projection enums */ - projection: { - UV: 0, - PLANAR: 1, - CYLINDRICAL: 2, - SPHERICAL: 3, - CUBIC: 4, - SKY: 5 - } - }, - - // Shader Map Inputs (binary hash index) - shader: { - map: { - COLOR: 1, - SPECULAR: 2, - NORMAL: 4, - BUMP: 8, - REFLECT: 16, - ENVSPHERE: 32, - AMBIENT: 64, - ALPHA: 128 - }, - - /* Uniform types */ - uniform: { - MATRIX: 0, - VECTOR: 1, - FLOAT: 2, - ARRAY_VERTEX: 3, - ARRAY_UV: 4, - ARRAY_FLOAT: 5, - INT: 6 - } - - }, - - motion: { - POS: 0, - ROT: 1, - SCL: 2, - FOV: 3, - LENS: 4, - NEARCLIP: 5, - FARCLIP: 6, - INTENSITY: 7, - X: 0, - Y: 1, - Z: 2, - V: 3 - }, - - envelope: { - shape: { - TCB: 0, - HERM: 1, - BEZI: 2, - LINE: 3, - STEP: 4, - BEZ2: 5 - }, - behavior: { - RESET: 0, - CONSTANT: 1, - REPEAT: 2, - OSCILLATE: 3, - OFFSET: 4, - LINEAR: 5 - } - }, - - /* Post Processing */ - post: { - output: { - REPLACE: 0, - BLEND: 1, - ADD: 2, - ALPHACUT: 3 - } - } - }; - - var cubicvr_identity = [1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0]; - - /* Base functions */ - var vec2 = { - equal: function(a, b) { - var epsilon = 0.00000001; - - if ((a === undef) && (b === undef)) { - return true; - } - if ((a === undef) || (b === undef)) { - return false; - } - - return (Math.abs(a[0] - b[0]) < epsilon && Math.abs(a[1] - b[1]) < epsilon); - } - }; - - var vec3 = { - length: function(pt) { - return Math.sqrt(pt[0] * pt[0] + pt[1] * pt[1] + pt[2] * pt[2]); - }, - normalize: function(pt) { - var d = Math.sqrt((pt[0] * pt[0]) + (pt[1] * pt[1]) + (pt[2] * pt[2])); - if (d === 0) { - return [0, 0, 0]; - } - return [pt[0] / d, pt[1] / d, pt[2] / d]; - }, - dot: function(v1, v2) { - return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; - }, - angle: function(v1, v2) { - var a = Math.acos((v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]) * Math.sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]))); - - return a; - }, - cross: function(vectA, vectB) { - return [ - vectA[1] * vectB[2] - vectB[1] * vectA[2], vectA[2] * vectB[0] - vectB[2] * vectA[0], vectA[0] * vectB[1] - vectB[0] * vectA[1]]; - }, - multiply: function(vectA, constB) { - return [vectA[0] * constB, vectA[1] * constB, vectA[2] * constB]; - }, - add: function(vectA, vectB) { - return [vectA[0] + vectB[0], vectA[1] + vectB[1], vectA[2] + vectB[2]]; - }, - subtract: function(vectA, vectB) { - return [vectA[0] - vectB[0], vectA[1] - vectB[1], vectA[2] - vectB[2]]; - }, - equal: function(a, b) { - var epsilon = 0.0000001; - - if ((a === undef) && (b === undef)) { - return true; - } - if ((a === undef) || (b === undef)) { - return false; - } - - return (Math.abs(a[0] - b[0]) < epsilon && Math.abs(a[1] - b[1]) < epsilon && Math.abs(a[2] - b[2]) < epsilon); - }, - moveViewRelative: function(position, target, xdelta, zdelta, alt_source) { - var ang = Math.atan2(zdelta, xdelta); - var cam_ang = Math.atan2(target[2] - position[2], target[0] - position[0]); - var mag = Math.sqrt(xdelta * xdelta + zdelta * zdelta); - - var move_ang = cam_ang + ang + M_HALF_PI; - - if (typeof(alt_source) === 'object') { - return [alt_source[0] + mag * Math.cos(move_ang), alt_source[1], alt_source[2] + mag * Math.sin(move_ang)]; - } - - return [position[0] + mag * Math.cos(move_ang), position[1], position[2] + mag * Math.sin(move_ang)]; - }, - trackTarget: function(position, target, trackingSpeed, safeDistance) { - var camv = vec3.subtract(target, position); - var dist = camv; - var fdist = vec3.length(dist); - var motionv = camv; - - motionv = vec3.normalize(motionv); - motionv = vec3.multiply(motionv, trackingSpeed * (1.0 / (1.0 / (fdist - safeDistance)))); - - var ret_pos; - - if (fdist > safeDistance) { - ret_pos = vec3.add(position, motionv); - } else if (fdist < safeDistance) { - motionv = camv; - motionv = vec3.normalize(motionv); - motionv = vec3.multiply(motionv, trackingSpeed * (1.0 / (1.0 / (Math.abs(fdist - safeDistance))))); - ret_pos = vec3.subtract(position, motionv); - } else { - ret_pos = [position[0], position[1] + motionv[2], position[2]]; - } - - return ret_pos; - }, - get_closest_to: function(ptA, ptB, ptTest) { - var S, T, U; - - S = vec3.subtract(ptB, ptA); - T = vec3.subtract(ptTest, ptA); - U = vec3.add(vec3.multiply(S, vec3.dot(S, T) / vec3.dot(S, S)), ptA); - - return U; - } - }; - - var triangle = { - normal: function(pt1, pt2, pt3) { - - var v10 = pt1[0] - pt2[0]; - var v11 = pt1[1] - pt2[1]; - var v12 = pt1[2] - pt2[2]; - var v20 = pt2[0] - pt3[0]; - var v21 = pt2[1] - pt3[1]; - var v22 = pt2[2] - pt3[2]; - - return [v11 * v22 - v12 * v21, v12 * v20 - v10 * v22, v10 * v21 - v11 * v20]; - } - }; - - - var mat3 = { - transpose_inline: function(mat) { - var a01 = mat[1], a02 = mat[2], a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - } - } - - var mat4 = { - lookat: function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz) { - var forward = [], side = [], up = []; - var m = []; - - forward[0] = centerx - eyex; - forward[1] = centery - eyey; - forward[2] = centerz - eyez; - - up[0] = upx; - up[1] = upy; - up[2] = upz; - - forward = vec3.normalize(forward); - - /* Side = forward x up */ - var side = vec3.cross(forward, up); - side = vec3.normalize(side); - - /* Recompute up as: up = side x forward */ - up = vec3.cross(side, forward); - - var m = [ side[0], up[0], -forward[0], 0, side[1], up[1], -forward[1], 0, side[2], up[2], -forward[2], 0, 0, 0, 0, 1]; - - var t = new Transform(m); - t.translate([-eyex,-eyey,-eyez]); - - return t.getResult(); - }, - multiply: function (m1, m2) { - var mOut = []; - - mOut[0] = m2[0] * m1[0] + m2[4] * m1[1] + m2[8] * m1[2] + m2[12] * m1[3]; - mOut[1] = m2[1] * m1[0] + m2[5] * m1[1] + m2[9] * m1[2] + m2[13] * m1[3]; - mOut[2] = m2[2] * m1[0] + m2[6] * m1[1] + m2[10] * m1[2] + m2[14] * m1[3]; - mOut[3] = m2[3] * m1[0] + m2[7] * m1[1] + m2[11] * m1[2] + m2[15] * m1[3]; - mOut[4] = m2[0] * m1[4] + m2[4] * m1[5] + m2[8] * m1[6] + m2[12] * m1[7]; - mOut[5] = m2[1] * m1[4] + m2[5] * m1[5] + m2[9] * m1[6] + m2[13] * m1[7]; - mOut[6] = m2[2] * m1[4] + m2[6] * m1[5] + m2[10] * m1[6] + m2[14] * m1[7]; - mOut[7] = m2[3] * m1[4] + m2[7] * m1[5] + m2[11] * m1[6] + m2[15] * m1[7]; - mOut[8] = m2[0] * m1[8] + m2[4] * m1[9] + m2[8] * m1[10] + m2[12] * m1[11]; - mOut[9] = m2[1] * m1[8] + m2[5] * m1[9] + m2[9] * m1[10] + m2[13] * m1[11]; - mOut[10] = m2[2] * m1[8] + m2[6] * m1[9] + m2[10] * m1[10] + m2[14] * m1[11]; - mOut[11] = m2[3] * m1[8] + m2[7] * m1[9] + m2[11] * m1[10] + m2[15] * m1[11]; - mOut[12] = m2[0] * m1[12] + m2[4] * m1[13] + m2[8] * m1[14] + m2[12] * m1[15]; - mOut[13] = m2[1] * m1[12] + m2[5] * m1[13] + m2[9] * m1[14] + m2[13] * m1[15]; - mOut[14] = m2[2] * m1[12] + m2[6] * m1[13] + m2[10] * m1[14] + m2[14] * m1[15]; - mOut[15] = m2[3] * m1[12] + m2[7] * m1[13] + m2[11] * m1[14] + m2[15] * m1[15]; - - return mOut; - }, - vec4_multiply: function (m1, m2) { - var mOut = []; - - mOut[0] = m2[0] * m1[0] + m2[4] * m1[1] + m2[8] * m1[2] + m2[12] * m1[3]; - mOut[1] = m2[1] * m1[0] + m2[5] * m1[1] + m2[9] * m1[2] + m2[13] * m1[3]; - mOut[2] = m2[2] * m1[0] + m2[6] * m1[1] + m2[10] * m1[2] + m2[14] * m1[3]; - mOut[3] = m2[3] * m1[0] + m2[7] * m1[1] + m2[11] * m1[2] + m2[15] * m1[3]; - - return mOut; - }, - vec3_multiply: function (m1, m2) { - var mOut = []; - - mOut[0] = m2[0] * m1[0] + m2[4] * m1[1] + m2[8] * m1[2] + m2[12]; - mOut[1] = m2[1] * m1[0] + m2[5] * m1[1] + m2[9] * m1[2] + m2[13]; - mOut[2] = m2[2] * m1[0] + m2[6] * m1[1] + m2[10] * m1[2] + m2[14]; - - return mOut; - }, - perspective: function (fovy, aspect, near, far) { - var yFac = Math.tan(fovy * M_PI / 360.0); - var xFac = yFac * aspect; - - return [ - 1.0 / xFac, 0, 0, 0, 0, 1.0 / yFac, 0, 0, 0, 0, -(far + near) / (far - near), -1, 0, 0, -(2.0 * far * near) / (far - near), 0]; - }, - determinant: function (m) { - - var a0 = m[0] * m[5] - m[1] * m[4]; - var a1 = m[0] * m[6] - m[2] * m[4]; - var a2 = m[0] * m[7] - m[3] * m[4]; - var a3 = m[1] * m[6] - m[2] * m[5]; - var a4 = m[1] * m[7] - m[3] * m[5]; - var a5 = m[2] * m[7] - m[3] * m[6]; - var b0 = m[8] * m[13] - m[9] * m[12]; - var b1 = m[8] * m[14] - m[10] * m[12]; - var b2 = m[8] * m[15] - m[11] * m[12]; - var b3 = m[9] * m[14] - m[10] * m[13]; - var b4 = m[9] * m[15] - m[11] * m[13]; - var b5 = m[10] * m[15] - m[11] * m[14]; - - var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0; - - return det; - }, - coFactor: function (m, n, out) { - // .. todo.. - }, - - transpose: function (m) { - return [m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]]; - }, - - inverse_mat3: function(mat) { - var dest = []; - - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[4], a11 = mat[5], a12 = mat[6], - a20 = mat[8], a21 = mat[9], a22 = mat[10]; - - var b01 = a22*a11-a12*a21, - b11 = -a22*a10+a12*a20, - b21 = a21*a10-a11*a20; - - var d = a00*b01 + a01*b11 + a02*b21; - if (!d) { return null; } - var id = 1/d; - - dest[0] = b01*id; - dest[1] = (-a22*a01 + a02*a21)*id; - dest[2] = (a12*a01 - a02*a11)*id; - dest[3] = b11*id; - dest[4] = (a22*a00 - a02*a20)*id; - dest[5] = (-a12*a00 + a02*a10)*id; - dest[6] = b21*id; - dest[7] = (-a21*a00 + a01*a20)*id; - dest[8] = (a11*a00 - a01*a10)*id; - - return dest; - }, - - // not sure which is faster yet.. - - inverse$1: function (m) { - var tmp = []; - var src = []; - var dst = []; - - // Transpose matrix - for (var i = 0; i < 4; i++) { - src[i + 0] = m[i*4 + 0]; - src[i + 4] = m[i*4 + 1]; - src[i + 8] = m[i*4 + 2]; - src[i + 12] = m[i*4 + 3]; - } - - // Calculate pairs for first 8 elements (cofactors) - tmp[0] = src[10] * src[15]; - tmp[1] = src[11] * src[14]; - tmp[2] = src[9] * src[15]; - tmp[3] = src[11] * src[13]; - tmp[4] = src[9] * src[14]; - tmp[5] = src[10] * src[13]; - tmp[6] = src[8] * src[15]; - tmp[7] = src[11] * src[12]; - tmp[8] = src[8] * src[14]; - tmp[9] = src[10] * src[12]; - tmp[10] = src[8] * src[13]; - tmp[11] = src[9] * src[12]; - - // Calculate first 8 elements (cofactors) - dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7]; - dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7]; - dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7]; - dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7]; - dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7]; - dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7]; - dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6]; - dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6]; - dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3]; - dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3]; - dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3]; - dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3]; - dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3]; - dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3]; - dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2]; - dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2]; - - // Calculate pairs for second 8 elements (cofactors) - tmp[0] = src[2]*src[7]; - tmp[1] = src[3]*src[6]; - tmp[2] = src[1]*src[7]; - tmp[3] = src[3]*src[5]; - tmp[4] = src[1]*src[6]; - tmp[5] = src[2]*src[5]; - tmp[6] = src[0]*src[7]; - tmp[7] = src[3]*src[4]; - tmp[8] = src[0]*src[6]; - tmp[9] = src[2]*src[4]; - tmp[10] = src[0]*src[5]; - tmp[11] = src[1]*src[4]; - - // Calculate second 8 elements (cofactors) - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; - dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; - dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; - dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]; - dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10]* src[15]; - dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11]* src[15]; - dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11]* src[14]; - dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10]* src[14]; - dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]; - dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]; - dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]; - dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]; - dst[14] = tmp[6] * src[9] + tmp[11]* src[11] + tmp[3] * src[8]; - dst[14] -= tmp[10]* src[11 ] + tmp[2] * src[8] + tmp[7] * src[9]; - dst[15] = tmp[10]* src[10] + tmp[4] * src[8] + tmp[9] * src[9]; - dst[15] -= tmp[8] * src[9] + tmp[11]* src[10] + tmp[5] * src[8]; - - // Calculate determinant - var det = src[0]*dst[0] + src[1]*dst[1] + src[2]*dst[2] + src[3]*dst[3]; - - var ret = []; - - // Calculate matrix inverse - det = 1.0 / det; - for (var i = 0; i < 16; i++) { - ret[i] = dst[i] * det; - } - - return ret; - }, - - inverse$2: function (m) { - var inv = []; - - inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] - + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10]; - inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] - - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10]; - inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] - + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9]; - inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] - - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9]; - inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] - - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10]; - inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] - + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10]; - inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] - - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9]; - inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] - + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9]; - inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] - + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6]; - inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] - - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6]; - inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] - + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5]; - inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] - - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5]; - inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] - - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6]; - inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] - + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6]; - inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] - - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5]; - inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] - + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5]; - - det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12]; - - if (det == 0) return null; - - inverse_det = 1.0 / det; - - inv[0] *= inverse_det; - inv[1] *= inverse_det; - inv[2] *= inverse_det; - inv[3] *= inverse_det; - inv[4] *= inverse_det; - inv[5] *= inverse_det; - inv[6] *= inverse_det; - inv[7] *= inverse_det; - inv[8] *= inverse_det; - inv[9] *= inverse_det; - inv[10] *= inverse_det; - inv[11] *= inverse_det; - inv[12] *= inverse_det; - inv[13] *= inverse_det; - inv[14] *= inverse_det; - inv[15] *= inverse_det; - - return inv; - }, - - inverse: function (m) { - var a0 = m[0] * m[5] - m[1] * m[4]; - var a1 = m[0] * m[6] - m[2] * m[4]; - var a2 = m[0] * m[7] - m[3] * m[4]; - var a3 = m[1] * m[6] - m[2] * m[5]; - var a4 = m[1] * m[7] - m[3] * m[5]; - var a5 = m[2] * m[7] - m[3] * m[6]; - var b0 = m[8] * m[13] - m[9] * m[12]; - var b1 = m[8] * m[14] - m[10] * m[12]; - var b2 = m[8] * m[15] - m[11] * m[12]; - var b3 = m[9] * m[14] - m[10] * m[13]; - var b4 = m[9] * m[15] - m[11] * m[13]; - var b5 = m[10] * m[15] - m[11] * m[14]; - - var determinant = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0; - - if (determinant != 0) { - var m_inv = []; - m_inv[0] = 0 + m[5] * b5 - m[6] * b4 + m[7] * b3; - m_inv[4] = 0 - m[4] * b5 + m[6] * b2 - m[7] * b1; - m_inv[8] = 0 + m[4] * b4 - m[5] * b2 + m[7] * b0; - m_inv[12] = 0 - m[4] * b3 + m[5] * b1 - m[6] * b0; - m_inv[1] = 0 - m[1] * b5 + m[2] * b4 - m[3] * b3; - m_inv[5] = 0 + m[0] * b5 - m[2] * b2 + m[3] * b1; - m_inv[9] = 0 - m[0] * b4 + m[1] * b2 - m[3] * b0; - m_inv[13] = 0 + m[0] * b3 - m[1] * b1 + m[2] * b0; - m_inv[2] = 0 + m[13] * a5 - m[14] * a4 + m[15] * a3; - m_inv[6] = 0 - m[12] * a5 + m[14] * a2 - m[15] * a1; - m_inv[10] = 0 + m[12] * a4 - m[13] * a2 + m[15] * a0; - m_inv[14] = 0 - m[12] * a3 + m[13] * a1 - m[14] * a0; - m_inv[3] = 0 - m[9] * a5 + m[10] * a4 - m[11] * a3; - m_inv[7] = 0 + m[8] * a5 - m[10] * a2 + m[11] * a1; - m_inv[11] = 0 - m[8] * a4 + m[9] * a2 - m[11] * a0; - m_inv[15] = 0 + m[8] * a3 - m[9] * a1 + m[10] * a0; - - var inverse_det = 1.0 / determinant; - - m_inv[0] *= inverse_det; - m_inv[1] *= inverse_det; - m_inv[2] *= inverse_det; - m_inv[3] *= inverse_det; - m_inv[4] *= inverse_det; - m_inv[5] *= inverse_det; - m_inv[6] *= inverse_det; - m_inv[7] *= inverse_det; - m_inv[8] *= inverse_det; - m_inv[9] *= inverse_det; - m_inv[10] *= inverse_det; - m_inv[11] *= inverse_det; - m_inv[12] *= inverse_det; - m_inv[13] *= inverse_det; - m_inv[14] *= inverse_det; - m_inv[15] *= inverse_det; - - return m_inv; - } - - return null; - } - }; - - - var util = { - getScriptContents: function(id) { - var shaderScript = document.getElementById(id); - - var str = ""; - var srcUrl = ""; - - if (!shaderScript) { - srcUrl = id; - } else { - if (shaderScript.src !== "" || shaderScript.attributes['srcUrl'] !== undef) { - srcUrl = (shaderScript.src !== '') ? shaderScript.src : (shaderScript.attributes['srcUrl'].value); - } - } - - if (srcUrl.length !== 0) { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open('GET', srcUrl, false); - xmlHttp.send(null); - - if (xmlHttp.status === 200 || xmlHttp.status === 0) { - str = xmlHttp.responseText; - } - } else { - var k = shaderScript.firstChild; - while (k) { - if (k.nodeType === 3) { - str += k.textContent; - } - k = k.nextSibling; - } - } - - return str; - }, - getURL: function(srcUrl) { - try { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open('GET', srcUrl, false); - xmlHttp.send(null); - - if (xmlHttp.status === 200 || xmlHttp.status === 0) { - if (xmlHttp.responseText.length) { - return xmlHttp.responseText; - } else if (xmlHttp.responseXML) { - return xmlHttp.responseXML; - } - } - } - catch(e) { - alert(srcUrl + " failed to load."); - } - - - return null; - }, - getXML: function(srcUrl) { - try { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open('GET', srcUrl, false); - xmlHttp.overrideMimeType("application/xml"); - xmlHttp.send(null); - - if (xmlHttp.status === 200 || xmlHttp.status === 0) { - return xmlHttp.responseXML; - } - } - catch(e) { - try { - alert(srcUrl + " failed to load."); - } - catch (ex) { - throw(e); - } - } - - - return null; - }, - repackArray: function(data, stride, count) { - if (data.length !== parseInt(stride, 10) * parseInt(count, 10)) { - log("array repack error, data size !== stride*count: data.length=" + - data.length + " stride=" + stride + " count=" + count); - } - - var returnData = []; - - var c = 0; - for (var i = 0, iMax = data.length; i < iMax; i++) { - var ims = i % stride; - - if (ims === 0) { - returnData[c] = []; - } - - returnData[c][ims] = data[i]; - - if (ims === stride - 1) { - c++; - } - } - - return returnData; - }, - collectTextNode: function(tn) { - if (!tn) { - return ""; - } - - var s = ""; - var textNodeChildren = tn.childNodes; - for (var i = 0, tnl = textNodeChildren.length; i < tnl; i++) { - s += textNodeChildren[i].nodeValue; - } - return s; - }, - floatDelimArray: function(float_str, delim) { -// if (!float_str) return []; - var fa = float_str.split(delim ? delim : ","); - for (var i = 0, imax = fa.length; i < imax; i++) { - fa[i] = parseFloat(fa[i]); - } - if (fa[fa.length - 1] !== fa[fa.length - 1]) { - fa.pop(); - } - return fa; - }, - intDelimArray: function(float_str, delim) { -// if (!float_str) return []; - var fa = float_str.split(delim ? delim : ","); - for (var i = 0, imax = fa.length; i < imax; i++) { - fa[i] = parseInt(fa[i], 10); - } - if (fa[fa.length - 1] !== fa[fa.length - 1]) { - fa.pop(); - } - return fa; - }, - textDelimArray: function(text_str, delim) { -// if (!text_str) return ""; - var fa = text_str.split(delim ? delim : ","); - for (var i = 0, imax = fa.length; i < imax; i++) { - fa[i] = fa[i]; - } - return fa; - } - }; - - - var MAX_LIGHTS=6; - - - /* Core Init, single context only at the moment */ - GLCore.init = function(gl_in, vs_in, fs_in) { - var gl; - - if (gl_in.getContext!==undef&&gl_in.width!==undef&&gl_in.height!==undef) - { - try { - gl = gl_in.getContext("experimental-webgl"); - gl.viewport(0, 0, gl_in.width, gl_in.height); - - // set these default, can always be easily over-ridden - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clearDepth(1.0); - gl.enable(gl.DEPTH_TEST); - gl.depthFunc(gl.LEQUAL); - } catch (e) {} - - if (!gl) { -// alert("Could not initialise WebGL, sorry :-("); - return null; - } - } - else - { - gl = gl_in; - } - - - GLCore.gl = gl; - GLCore.CoreShader_vs = util.getScriptContents(vs_in); - GLCore.CoreShader_fs = util.getScriptContents(fs_in); - GLCore.depth_alpha = false; - GLCore.default_filter = enums.texture.filter.LINEAR_MIP; - GLCore.mainloop = null; - - gl.enable(gl.CULL_FACE); - gl.cullFace(gl.BACK); - gl.frontFace(gl.CCW); - - - for (var i = enums.light.type.NULL; i < enums.light.type.MAX; i++) { - ShaderPool[i] = []; - } - - var dummyTex = new CubicVR.Texture(); - var lightTest = new CubicVR.Material(); - - for (var i = 0; i < enums.texture.map.MAX; i++) { - if (i===enums.texture.map.BUMP) continue; // fix for crashy fglrx driver, todo: check it against newer revisions. - lightTest.setTexture(dummyTex,i); - } - lightTest.opacity = 0.5; - - var lc = 1; - - try { - while (1) { - lightTest.use(enums.light.type.POINT,lc); - if (lc === 8) { - MAX_LIGHTS=lc; - break; - } - lc++; - } - } catch (e) { - MAX_LIGHTS=lc; - // console.log(e); - } - - log("Calibrated maximum lights per pass to: "+lc); - - - for (var i = enums.light.type.NULL; i < enums.light.type.MAX; i++) { - ShaderPool[i] = []; - } - - - return gl; - }; - - GLCore.setDepthAlpha = function(da, near, far) { - GLCore.depth_alpha = da; - GLCore.depth_alpha_near = near; - GLCore.depth_alpha_far = far; - }; - - GLCore.setDefaultFilter = function(filterType) { - GLCore.default_filter = filterType; - }; - - - - - var cubicvr_compileShader = function(gl, str, type) { - var shader; - - if (type === "x-shader/x-fragment") { - shader = gl.createShader(gl.FRAGMENT_SHADER); - } else if (type === "x-shader/x-vertex") { - shader = gl.createShader(gl.VERTEX_SHADER); - } else { - return null; - } - - gl.shaderSource(shader, str); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; - }; - - var cubicvr_getShader = function(gl, id) { - var shaderScript = document.getElementById(id); - - if (!shaderScript) { - return null; - } - - var str = ""; - var k = shaderScript.firstChild; - while (k) { - if (k.nodeType === 3) { - str += k.textContent; - } - k = k.nextSibling; - } - - var shader; - - if (shaderScript.type === "x-shader/x-fragment") { - shader = gl.createShader(gl.FRAGMENT_SHADER); - } else if (shaderScript.type === "x-shader/x-vertex") { - shader = gl.createShader(gl.VERTEX_SHADER); - } else { - return null; - } - - gl.shaderSource(shader, str); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - log(gl.getShaderInfoLog(shader)); -// return null; - } - - return shader; - }; - - /***************************************************************************** - * Workers - *****************************************************************************/ - - function CubicVR_Worker(settings) { - this.worker = new Worker(SCRIPT_LOCATION + "CubicVR.js"); - this.message = settings.message; - this.error = settings.error; - this.type = settings.type; - var that = this; - this.worker.onmessage = function(e) { - if (that.message) { - that.message(e.data); - } //if - }; - this.worker.onerror = function(e) { - if (that.error) { - that.error(e); - } else { - log("Error: " + e.message + ": " + e.lineno); - } //if - }; //onerror - this.fn = function(fn, options) { - that.worker.postMessage({ - message: "function", - data: fn, - options: options, - }); - }; - this.start = function(options) { - that.worker.postMessage({ - message: "start", - data: that.type, - options: options - }); - }; - this.init = function(data) { - that.send({message:'init', data:data}); - }; - this.stop = function() { - that.worker.postMessage({ - message: "stop", - data: null - }); - }; - this.send = function(message) { - that.worker.postMessage({ - message: "data", - data: message - }); - }; - }; //CubicVR_Worker::Constructor - - function CubicVR_TestWorker() { - var that = this; - this.onmessage = function(message) { - if (message.test) { - setTimeout(function(){postMessage(message.test);}, 1000); - } - else { - setTimeout(function(){throw new Error(message);}, 1000); - } //if - }; //onmessage - }; //CubicVR_TestWorker - - function CubicVR_ColladaLoadWorker() { - var that = this; - this.onmessage = function(message) { - }; //onmessage - }; //CubicVR_ColladaLoadWorker - - function CubicVR_WorkerConnection() { - this.listener = null; - } //CubicVR_WorkerConnection - var WorkerConnection = new CubicVR_WorkerConnection(); - - if (1) { - self.addEventListener('message', function(e) { - var message = e.data.message; - var type = e.data.data; - if (message === "start") { - if (type === "test") { - WorkerConnection.listener = new CubicVR_TestWorker(); - } - else if (type === "load_collada") { - WorkerConnection.listener = new CubicVR_ColladaLoadWorker(); - } - else if (type === "octree") { - WorkerConnection.listener = new CubicVR_OctreeWorker(); - } //if - } - else if (message === "function") { - var data = e.data.data; - var options = e.data.options; - var parts = data.split('('); - if (parts.length > 1 && parts[1].indexOf(')') > -1) { - var prefix = parts[0]; - var suffix = parts[1].substr(0,parts[1].length-1); - var args = options || suffix.split(','); - var chain = prefix.split('.'); - var fn = CubicVR; - for (var i=0; i<chain.length; ++i) { - fn = fn[chain[i]]; - } //for - if (fn && typeof fn === 'function') { - var ret = fn.apply(fn, args); - postMessage(ret); - } //if - } - else { - throw new Error('Worker command not formatted properly.'); - } //if - } - else if (message === "data") { - if (WorkerConnection.listener !== null) { - var data = e.data ? e.data.data : null; - WorkerConnection.listener.onmessage(e.data.data); - } //if - } - else if (message === "stop") { - if (WorkerConnection.listener !== null && WorkerConnection.listener.stop) { - WorkerConnection.listener.stop(); - } //if - } //if - }, false); - } //if - - /* Timer */ - - function Timer() { - this.time_elapsed = 0; - this.system_milliseconds = 0; - this.start_time = 0; - this.end_time = 0; - this.last_update = 0; - this.paused_time = 0; - this.offset = 0; - this.paused_state = 0; - } - - - Timer.prototype.start = function () { - this.update(); - this.num_updates = 0; - this.start_time = this.system_milliseconds; - this.last_update = this.start_time; - this.paused_state = false; - this.lock_state = false; - this.lock_rate = 0; - this.paused_time = 0; - this.offset = 0; - } - - - Timer.prototype.stop = function () { - this.end_time = this.system_milliseconds; - } - - - Timer.prototype.reset = function () { - this.start(); - } - - - Timer.prototype.lockFramerate = function (f_rate) { - this.lock_rate = 1.0 / this.f_rate; - this.lock_state = true; - } - - - Timer.prototype.unlock = function () { - var msec_tmp = this.system_milliseconds; - this.lock_state = false; - this.update(); - this.last_update = this.system_milliseconds - this.lock_rate; - this.offset += msec_tmp - this.system_milliseconds; - this.lock_rate = 0; - } - - Timer.prototype.locked = function () { - return this.lock_state; - } - - Timer.prototype.update = function () { - this.num_updates++; - this.last_update = this.system_milliseconds; - - if (this.lock_state) { - this.system_milliseconds += parseInt(lock_rate * 1000); - } else { - this.system_milliseconds = (new Date()).getTime(); - } - - - if (this.paused_state) this.paused_time += this.system_milliseconds - this.last_update; - - this.time_elapsed = this.system_milliseconds - this.start_time - this.paused_time + this.offset; - } - - - Timer.prototype.getMilliseconds = function () { - return this.time_elapsed; - } - - - - Timer.prototype.getSeconds = function () { - return this.getMilliseconds() / 1000.0; - } - - - Timer.prototype.setMilliseconds = function (milliseconds_in) { - this.offset -= (this.system_milliseconds - this.start_time - this.paused_time + this.offset) - milliseconds_in; - } - - - - Timer.prototype.setSeconds = function (seconds_in) { - this.setMilliseconds(parseInt(seconds_in * 1000.0)); - } - - - Timer.prototype.getLastUpdateSeconds = function () { - return this.getLastUpdateMilliseconds() / 1000.0; - } - - - Timer.prototype.getLastUpdateMilliseconds = function () { - return this.system_milliseconds - this.last_update; - } - - Timer.prototype.getTotalMilliseconds = function () { - return this.system_milliseconds - this.start_time; - } - - - Timer.prototype.getTotalSeconds = function () { - return this.getTotalMilliseconds() / 1000.0; - } - - - Timer.prototype.getNumUpdates = function () { - return this.num_updates; - } - - - Timer.prototype.setPaused = function (pause_in) { - this.paused_state = pause_in; - } - - Timer.prototype.getPaused = function () { - return this.paused_state; - } - - - /* Run-Loop Controller */ - - function MainLoopRequest() - { - var gl = GLCore.gl; - - if (CubicVR.GLCore.mainloop === null) return; - - CubicVR.GLCore.mainloop.interval(); - - if (window.requestAnimationFrame) { - window.requestAnimationFrame(MainLoopRequest); - } - } - - function setMainLoop(ml) - { - CubicVR.GLCore.mainloop=ml; - } - - function MainLoop(mlfunc,doclear) - { - if (window.requestAnimationFrame === undef) { - window.requestAnimationFrame = null; // XXX Emscripten - Disable this for now, due to bugginess window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || null; - } - - if (CubicVR.GLCore.mainloop !== null) - { - // kill old mainloop - - if (!(window.requestAnimationFrame) && CubicVR.GLCore.mainloop) - { - clearInterval(CubicVR.GLCore.mainloop.interval); - } - - CubicVR.GLCore.mainloop = null; - } - - if (mlfunc === null) - { - CubicVR.GLCore.mainloop = null; - return; - } - - var timer = new Timer(); - timer.start(); - - this.timer = timer; - this.func = mlfunc; - this.doclear = (doclear!==undef)?doclear:true; - CubicVR.GLCore.mainloop = this; - - var loopFunc = function() { return function() { - var gl = CubicVR.GLCore.gl; - timer.update(); - if (CubicVR.GLCore.mainloop.doclear) gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - mlfunc(timer,CubicVR.GLCore.gl); - }; }(); - - if (window.requestAnimationFrame) { - loopFunc(); - this.interval = loopFunc; - window.requestAnimationFrame(MainLoopRequest); - } else { - this.interval = setInterval(loopFunc, 1000/60); // XXX Emscripten: Need 1/60 for bullet, not the usual 1/50 - } - } - - MainLoop.prototype.setPaused = function(state) { - this.timer.setPaused(state); - }; - - MainLoop.prototype.getPaused = function() { - return this.timer.getPaused(); - }; - - MainLoop.prototype.setTimerSeconds = function(time_in) { - this.timer.setSeconds(time_in); - }; - - - MainLoop.prototype.getTimerSeconds = function() { - return this.timer.getSeconds(); - }; - - - MainLoop.prototype.resetTimer = function() { - this.timer.reset(); - }; - - - /* Simple Orbital View Controller */ - function MouseViewController(canvas,cam_in) - { - this.canvas = canvas; - this.camera = cam_in; - this.mpos = [0,0] - this.mdown = false; - - var ctx = this; - - this.onMouseDown = function () { return function (ev) - { - ctx.mdown = true; - ctx.mpos = [ev.pageX-ev.target.offsetLeft,ev.pageY-ev.target.offsetTop]; - } }(); - - this.onMouseUp = function () { return function (ev) - { - ctx.mdown = false; - ctx.mpos = [ev.pageX-ev.target.offsetLeft,ev.pageY-ev.target.offsetTop]; - } }(); - - this.onMouseMove = function () { return function (ev) - { - var mdelta = []; - - var npos = [ev.pageX-ev.target.offsetLeft,ev.pageY-ev.target.offsetTop]; - - mdelta[0] = ctx.mpos[0]-npos[0]; - mdelta[1] = ctx.mpos[1]-npos[1]; - - ctx.mpos = npos; -// ctx.mpos = [ev.clientX,ev.clientY]; - if (!ctx.mdown) return; - - var dv = vec3.subtract(ctx.camera.target,ctx.camera.position); - var dist = vec3.length(dv); - - ctx.camera.position = vec3.moveViewRelative(ctx.camera.position,ctx.camera.target,dist*mdelta[0]/300.0,0); - ctx.camera.position[1] -= dist*mdelta[1]/300.0; - - ctx.camera.position = vec3.add(ctx.camera.target,vec3.multiply(vec3.normalize(vec3.subtract(ctx.camera.position,ctx.camera.target)),dist)); - } }(); - - this.onMouseWheel = function() { return function (ev) - { - var delta = ev.wheelDelta?ev.wheelDelta:(-ev.detail*10.0); - - var dv = vec3.subtract(ctx.camera.target,ctx.camera.position); - var dist = vec3.length(dv); - - dist -= delta/1000.0; - - if (dist < 0.1) dist = 0.1; - if (dist > 1000) dist = 1000; - // if (camDist > 20.0) camDist = 20.0; - - ctx.camera.position = vec3.add(ctx.camera.target,vec3.multiply(vec3.normalize(vec3.subtract(ctx.camera.position,ctx.camera.target)),dist)); - } }(); - - this.bind(); - } - - MouseViewController.prototype.bind = function() { - this.canvas.addEventListener('mousemove', this.onMouseMove, false); - this.canvas.addEventListener('mousedown', this.onMouseDown, false); - this.canvas.addEventListener('mouseup', this.onMouseUp, false); - this.canvas.addEventListener('mousewheel', this.onMouseWheel, false); - this.canvas.addEventListener('DOMMouseScroll', this.onMouseWheel, false); - }; - - MouseViewController.prototype.unbind = function() { - this.canvas.removeEventListener('mousemove', this.onMouseMove, false); - this.canvas.removeEventListener('mousedown', this.onMouseDown, false); - this.canvas.removeEventListener('mouseup', this.onMouseUp, false); - this.canvas.removeEventListener('mousewheel', this.onMouseWheel, false); - this.canvas.removeEventListener('DOMMouseScroll', this.onMouseWheel, false); - }; - - MouseViewController.prototype.setCamera = function(cam_in) { - this.camera = cam_in; - } - - MouseViewController.prototype.getMousePosition = function() { - return this.mpos; - } - - - /* Transform Controller */ - - function Transform(init_mat) { - return this.clearStack(init_mat); - } - - Transform.prototype.setIdentity = function() { - this.m_stack[this.c_stack] = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]; - if (this.valid === this.c_stack && this.c_stack) { - this.valid--; - } - return this; - }; - - - Transform.prototype.getIdentity = function() { - return [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]; - }; - - Transform.prototype.invalidate = function() { - this.valid = 0; - this.result = null; - return this; - }; - - - Transform.prototype.getResult = function() { - if (!this.c_stack) { - return this.m_stack[0]; - } - - var m = cubicvr_identity; - - if (this.valid > this.c_stack-1) this.valid = this.c_stack-1; - - for (var i = this.valid; i < this.c_stack+1; i++) { - m = mat4.multiply(this.m_stack[i],m); - this.m_cache[i] = m; - } - - this.valid = this.c_stack-1; - - this.result = this.m_cache[this.c_stack]; - - return this.result; - }; - - Transform.prototype.pushMatrix = function(m) { - this.c_stack++; - this.m_stack[this.c_stack] = (m ? m : cubicvr_identity); - return this; - }; - - Transform.prototype.popMatrix = function() { - if (this.c_stack === 0) { - return; - } - this.c_stack--; - return this; - }; - - Transform.prototype.clearStack = function(init_mat) { - this.m_stack = []; - this.m_cache = []; - this.c_stack = 0; - this.valid = 0; - this.result = null; - - if (init_mat !== undef) { - this.m_stack[0] = init_mat; - } else { - this.setIdentity(); - } - - return this; - }; - - Transform.prototype.translate = function(x, y, z) { - if (typeof(x) === 'object') { - return this.translate(x[0], x[1], x[2]); - } - - var m = this.getIdentity(); - - m[12] = x; - m[13] = y; - m[14] = z; - - this.m_stack[this.c_stack] = mat4.multiply(m,this.m_stack[this.c_stack]); - if (this.valid === this.c_stack && this.c_stack) { - this.valid--; - } - - return this; - }; - - - Transform.prototype.scale = function(x, y, z) { - if (typeof(x) === 'object') { - return this.scale(x[0], x[1], x[2]); - } - - - var m = this.getIdentity(); - - m[0] = x; - m[5] = y; - m[10] = z; - - this.m_stack[this.c_stack] = mat4.multiply(m,this.m_stack[this.c_stack]); - if (this.valid === this.c_stack && this.c_stack) { - this.valid--; - } - - return this; - }; - - - Transform.prototype.rotate = function(ang, x, y, z) { - if (typeof(ang) === 'object') { - this.rotate(ang[0], 1, 0, 0); - this.rotate(ang[1], 0, 1, 0); - this.rotate(ang[2], 0, 0, 1); - return this; - } - - var sAng, cAng; - - if (x || y || z) { - sAng = Math.sin(-ang * (M_PI / 180.0)); - cAng = Math.cos(-ang * (M_PI / 180.0)); - } - - if (z) { - var Z_ROT = this.getIdentity(); - - Z_ROT[0] = cAng * z; - Z_ROT[4] = sAng * z; - Z_ROT[1] = -sAng * z; - Z_ROT[5] = cAng * z; - - this.m_stack[this.c_stack] = mat4.multiply(this.m_stack[this.c_stack],Z_ROT); - } - - if (y) { - var Y_ROT = this.getIdentity(); - - Y_ROT[0] = cAng * y; - Y_ROT[8] = -sAng * y; - Y_ROT[2] = sAng * y; - Y_ROT[10] = cAng * y; - - this.m_stack[this.c_stack] = mat4.multiply(this.m_stack[this.c_stack],Y_ROT); - } - - - if (x) { - var X_ROT = this.getIdentity(); - - X_ROT[5] = cAng * x; - X_ROT[9] = sAng * x; - X_ROT[6] = -sAng * x; - X_ROT[10] = cAng * x; - - this.m_stack[this.c_stack] = mat4.multiply(this.m_stack[this.c_stack],X_ROT); - } - - if (this.valid === this.c_stack && this.c_stack) { - this.valid--; - } - - return this; - }; - - /* Quaternions */ - - function Quaternion() { - if (arguments.length === 1) { - this.x = arguments[0][0]; - this.y = arguments[0][1]; - this.z = arguments[0][2]; - this.w = arguments[0][3]; - } - if (arguments.length === 4) { - this.x = arguments[0]; - this.y = arguments[1]; - this.z = arguments[2]; - this.w = arguments[3]; - } - } - - Quaternion.prototype.length = function() { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); - }; - - Quaternion.prototype.normalize = function() { - var n = Math.sqrt(this.length()); - this.x /= n; - this.y /= n; - this.z /= n; - this.w /= n; - }; - - Quaternion.prototype.fromEuler = function(bank, heading, pitch) // x,y,z - { - var c1 = Math.cos((M_PI / 180.0) * heading / 2.0); - var s1 = Math.sin((M_PI / 180.0) * heading / 2.0); - var c2 = Math.cos((M_PI / 180.0) * pitch / 2.0); - var s2 = Math.sin((M_PI / 180.0) * pitch / 2.0); - var c3 = Math.cos((M_PI / 180.0) * bank / 2.0); - var s3 = Math.sin((M_PI / 180.0) * bank / 2.0); - var c1c2 = c1 * c2; - var s1s2 = s1 * s2; - - this.w = c1c2 * c3 - s1s2 * s3; - this.x = c1c2 * s3 + s1s2 * c3; - this.y = s1 * c2 * c3 + c1 * s2 * s3; - this.z = c1 * s2 * c3 - s1 * c2 * s3; - }; - - - Quaternion.prototype.toEuler = function() { - var sqw = this.w * this.w; - var sqx = this.x * this.x; - var sqy = this.y * this.y; - var sqz = this.z * this.z; - - var x = (180 / M_PI) * ((Math.atan2(2.0 * (this.y * this.z + this.x * this.w), (-sqx - sqy + sqz + sqw)))); - var y = (180 / M_PI) * ((Math.asin(-2.0 * (this.x * this.z - this.y * this.w)))); - var z = (180 / M_PI) * ((Math.atan2(2.0 * (this.x * this.y + this.z * this.w), (sqx - sqy - sqz + sqw)))); - - return [x, y, z]; - }; - - Quaternion.prototype.multiply = function(q1, q2) { - var selfSet = false; - - if (q2 === undef) { - q2 = q1; - q1 = this; - } - - var x = q1.x * q2.w + q1.w * q2.x + q1.y * q2.z - q1.z * q2.y; - var y = q1.y * q2.w + q1.w * q2.y + q1.z * q2.x - q1.x * q2.z; - var z = q1.z * q2.w + q1.w * q2.z + q1.x * q2.y - q1.y * q2.x; - var w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; - - if (selfSet) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } else { - return new Quaternion(x, y, z, w); - } - }; - - - /* Faces */ - - function Face() { - this.points = []; - this.point_normals = []; - this.uvs = []; - this.normal = [0, 0, 0]; - this.material = 0; - this.segment = 0; - } - - Face.prototype.setUV = function(uvs, point_num) { - if (this.uvs === undef) { - this.uvs = []; - } - - if (point_num !== undef) { - this.uvs[point_num] = uvs; - } else { - if (uvs.length !== 2) { - this.uvs = uvs; - } else { - this.uvs.push(uvs); - } - } - }; - - Face.prototype.flip = function() { - for (var i = 0, iMax = this.point_normals.length; i < iMax; i++) { - this.point_normals[i] = [this.point_normals[i][0], this.point_normals[i][1], this.point_normals[i][2]]; - } - - this.points.reverse(); - this.point_normals.reverse(); - this.uvs.reverse(); - this.normal = [-this.normal[0], -this.normal[1], -this.normal[2]]; - }; - - function Mesh(objName) { - this.points = []; // point list - this.faces = []; // faces with point references - this.currentFace = -1; // start with no faces - this.currentMaterial = 0; // null material - this.currentSegment = 0; // default segment - this.compiled = null; // VBO data - this.bb = null; - this.name = objName ? objName : null; - this.hasUV = false; - this.hasNorm = false; - } - - Mesh.prototype.showAllSegments = function() { - for (var i in this.segment_state) { - if (this.segment_state.hasOwnProperty(i)) { - this.segment_state[i] = true; - } - } - }; - - Mesh.prototype.hideAllSegments = function() { - for (var i in this.segment_state) { - if (this.segment_state.hasOwnProperty(i)) { - this.segment_state[i] = false; - } - } - }; - - Mesh.prototype.setSegment = function(i, val) { - if (val !== undef) { - this.segment_state[i] = val; - } else { - this.currentSegment = i; - } - }; - - Mesh.prototype.addPoint = function(p) { - if (p.length !== 3 || typeof(p[0]) === 'object') { - for (var i = 0, iMax = p.length; i < iMax; i++) { - this.points.push(p[i]); - } - } else { - this.points.push(p); - } - - return this.points.length - 1; - }; - - Mesh.prototype.setFaceMaterial = function(mat,facenum) { - var mat_id = (typeof(mat) === 'object') ? mat.material_id : mat; - - if (facenum !== undef) { - if (this.faces[facenum] !== undef) { - this.faces[facenum].material = mat_id; - } - } else { - this.currentMaterial = mat_id; - } - }; - - Mesh.prototype.addFace = function(p_list, face_num, face_mat, face_seg) { - if (typeof(p_list[0]) !== 'number') { - for (var i = 0, iMax = p_list.length; i < iMax; i++) { - if (!p_list.hasOwnProperty(i)) { - continue; - } - - this.addFace(p_list[i]); - } - - return; - } - - if (face_num === undef) { - this.currentFace = this.faces.length; - this.faces.push(new Face()); - } else { - if (this.faces[face_num] === undef) { - this.faces[face_num] = new Face(); - } - - this.currentFace = face_num; - } - - if (typeof(p_list) === 'object') { - this.faces[this.currentFace].points = p_list; - } - - if (face_mat !== undef) { - this.faces[this.currentFace].material = (typeof(face_mat) === 'object') ? face_mat.material_id : face_mat; - } else { - this.faces[this.currentFace].material = this.currentMaterial; - } - - if (face_seg !== undef) { - this.faces[this.currentFace].segment = face_seg; - } else { - this.faces[this.currentFace].segment = this.currentSegment; - } - - - return this.currentFace; - }; - - - Mesh.prototype.triangulateQuads = function() { - for (var i = 0, iMax = this.faces.length; i < iMax; i++) { - if (this.faces[i].points.length === 4) { - var p = this.faces.length; - - this.addFace([this.faces[i].points[2], this.faces[i].points[3], this.faces[i].points[0]], this.faces.length, this.faces[i].material, this.faces[i].segment); - this.faces[i].points.pop(); - this.faces[p].normal = this.faces[i].normal; - - if (this.faces[i].uvs !== undef) { - if (this.faces[i].uvs.length === 4) { - this.faces[p].setUV(this.faces[i].uvs[2], 0); - this.faces[p].setUV(this.faces[i].uvs[3], 1); - this.faces[p].setUV(this.faces[i].uvs[0], 2); - - this.faces[i].uvs.pop(); - } - } - - if (this.faces[i].point_normals.length === 4) { - this.faces[p].point_normals[0] = this.faces[i].point_normals[2]; - this.faces[p].point_normals[1] = this.faces[i].point_normals[3]; - this.faces[p].point_normals[2] = this.faces[i].point_normals[0]; - - this.faces[i].point_normals.pop(); - } - - } - } - - return this; - }; - - - Mesh.prototype.booleanAdd = function(objAdd, transform) { - var pofs = this.points.length; - var fofs = this.faces.length; - - var i, j, iMax, jMax; - - if (transform !== undef) { - var m = transform.getResult(); - for (i = 0, iMax = objAdd.points.length; i < iMax; i++) { - this.addPoint(mat4.vec3_multiply(objAdd.points[i], m)); - } - } else { - for (i = 0, iMax = objAdd.points.length; i < iMax; i++) { - this.addPoint([objAdd.points[i][0], objAdd.points[i][1], objAdd.points[i][2]]); - } - } - - for (i = 0, iMax = objAdd.faces.length; i < iMax; i++) { - var newFace = []; - - for (j = 0, jMax = objAdd.faces[i].points.length; j < jMax; j++) { - newFace.push(objAdd.faces[i].points[j] + pofs); - } - - var nFaceNum = this.addFace(newFace); - var nFace = this.faces[nFaceNum]; - - nFace.segment = objAdd.faces[i].segment; - nFace.material = objAdd.faces[i].material; - - for (j = 0, jMax = objAdd.faces[i].uvs.length; j < jMax; j++) { - nFace.uvs[j] = [objAdd.faces[i].uvs[j][0], objAdd.faces[i].uvs[j][1]]; - } - - for (j = 0, jMax = objAdd.faces[i].point_normals.length; j < jMax; j++) { - nFace.point_normals[j] = [objAdd.faces[i].point_normals[j][0], objAdd.faces[i].point_normals[j][1], objAdd.faces[i].point_normals[j][2]]; - } - } - - return this; - }; - - Mesh.prototype.calcFaceNormals = function() { - for (var i = 0, iMax = this.faces.length; i < iMax; i++) { - if (this.faces[i].points.length < 3) { - this.faces[i].normal = [0, 0, 0]; - continue; - } - - this.faces[i].normal = vec3.normalize(triangle.normal(this.points[this.faces[i].points[0]], this.points[this.faces[i].points[1]], this.points[this.faces[i].points[2]])); - } - - return this; - }; - - - Mesh.prototype.getMaterial = function(m_name) { - - if (this.compiled !== null) - { - for (var i in this.compiled.elements) { - if (this.compiled.elements.hasOwnProperty(i)) { - if (Materials[i].name === m_name) { - return Materials[i]; - } - } - } - } - else - { - var matVisit = []; - - for (var j = 0, jMax = this.faces.length; j < jMax; j++) - { - var matId = this.faces[j].material; - - if (matVisit.indexOf(matId)===-1) - { - if (Materials[matId].name === m_name) - { - return Materials[matId]; - } - matVisit.push(matId); - } - } - } - - - return null; - }; - - - Mesh.prototype.calcNormals = function() { - this.calcFaceNormals(); - - var i, j, k, iMax; - - var point_smoothRef = new Array(this.points.length); - for (i = 0, iMax = point_smoothRef.length; i < iMax; i++) { - point_smoothRef[i] = []; - } - - var numFaces = this.faces.length; - - // build a quick list of point/face sharing - for (i = 0; i < numFaces; i++) { - var numFacePoints = this.faces[i].points.length; - - for (j = 0; j < numFacePoints; j++) { - var idx = this.faces[i].points[j]; - - // if (point_smoothRef[idx] === undef) point_smoothRef[idx] = []; - point_smoothRef[idx].push([i, j]); - } - } - - - // step through smoothing references and compute normals - for (i = 0, iMax = this.points.length; i < iMax; i++) { - // if(!point_smoothRef.hasOwnProperty(i)) { continue; } - // if (typeof(point_smoothRef[i]) === undef) { continue; } - var numPts = point_smoothRef[i].length; - - for (j = 0; j < numPts; j++) { - var ptCount = 1; - var faceNum = point_smoothRef[i][j][0]; - var pointNum = point_smoothRef[i][j][1]; - var max_smooth = Materials[this.faces[faceNum].material].max_smooth; - var thisFace = this.faces[faceNum]; - - // set point to it's face's normal - var tmpNorm = new Array(3); - - tmpNorm[0] = thisFace.normal[0]; - tmpNorm[1] = thisFace.normal[1]; - tmpNorm[2] = thisFace.normal[2]; - - // step through all other faces which share this point - if (max_smooth !== 0) { - for (k = 0; k < numPts; k++) { - if (j === k) { - continue; - } - var faceRefNum = point_smoothRef[i][k][0]; - var thisFaceRef = this.faces[faceRefNum]; - - var ang = vec3.angle(thisFaceRef.normal, thisFace.normal); - - if ((ang !== ang) || ((ang * (180.0 / M_PI)) <= max_smooth)) { - tmpNorm[0] += thisFaceRef.normal[0]; - tmpNorm[1] += thisFaceRef.normal[1]; - tmpNorm[2] += thisFaceRef.normal[2]; - - ptCount++; - } - } - } - - tmpNorm[0] /= ptCount; - tmpNorm[1] /= ptCount; - tmpNorm[2] /= ptCount; - - this.faces[faceNum].point_normals[pointNum] = vec3.normalize(tmpNorm); - } - } - - return this; - }; - - - Mesh.prototype.clean = function() { - var i,iMax; - - - for (i = 0, iMax=this.points.length; i < iMax; i++) - { - delete(this.points[i]); - this.points[i]=null; - } - this.points = []; - - for (i = 0, iMax=this.faces.length; i < iMax; i++) - { - delete(this.faces[i].points); - delete(this.faces[i].point_normals); - delete(this.faces[i].uvs); - delete(this.faces[i].normal); - delete(this.faces[i]); - this.faces[i]=null; - } - this.faces = []; - - - return this; - } - - Mesh.prototype.compile = function() { - this.compiled = {}; - - this.bb = []; - - var compileRef = []; - - var i, j, k, x, y, iMax, kMax, yMax; - - for (i = 0, iMax = this.faces.length; i < iMax; i++) { - if (this.faces[i].points.length === 3) { - var matId = this.faces[i].material; - var segId = this.faces[i].segment; - - if (compileRef[matId] === undef) { - compileRef[matId] = []; - } - if (compileRef[matId][segId] === undef) { - compileRef[matId][segId] = []; - } - - compileRef[matId][segId].push(i); - } - } - - var vtxRef = []; - - this.compiled.vbo_normals = []; - this.compiled.vbo_points = []; - this.compiled.vbo_uvs = []; - - var idxCount = 0; - var hasUV = false; - var hasNorm = false; - var faceNum; - - for (i in compileRef) { - if (compileRef.hasOwnProperty(i)) { - for (j in compileRef[i]) { - if (compileRef[i].hasOwnProperty(j)) { - for (k = 0; k < compileRef[i][j].length; k++) { - faceNum = compileRef[i][j][k]; - hasUV = hasUV || (this.faces[faceNum].uvs.length !== 0); - hasNorm = hasNorm || (this.faces[faceNum].point_normals.length !== 0); - } - } - } - } - } - - if (hasUV) { - for (i = 0; i < this.faces.length; i++) { - if (!this.faces[i].uvs.length) { - for (j = 0; j < this.faces[i].points.length; j++) { - this.faces[i].uvs.push([0, 0]); - } - } - } - } - - if (hasNorm) { - for (i = 0; i < this.faces.length; i++) { - if (!this.faces[i].point_normals.length) { - for (j = 0; j < this.faces[i].points.length; j++) { - this.faces[i].point_normals.push([0, 0, 0]); - } - } - } - } - - this.hasUV = hasUV; - this.hasNorm = hasNorm; - - var pVisitor = []; - - for (i in compileRef) { - if (compileRef.hasOwnProperty(i)) { - for (j in compileRef[i]) { - if (compileRef[i].hasOwnProperty(j)) { - for (k = 0, kMax = compileRef[i][j].length; k < kMax; k++) { - faceNum = compileRef[i][j][k]; - var found = false; - - for (x = 0; x < 3; x++) { - var ptNum = this.faces[faceNum].points[x]; - - var foundPt = -1; - - if (vtxRef[ptNum] !== undef) { - for (y = 0, yMax = vtxRef[ptNum].length; y < yMax; y++) { - // face / point - var oFace = vtxRef[ptNum][y][0]; // faceNum - var oPoint = vtxRef[ptNum][y][1]; // pointNum - var oIndex = vtxRef[ptNum][y][2]; // index - foundPt = oIndex; - - if (hasNorm) { - foundPt = (vec3.equal( - this.faces[oFace].point_normals[oPoint], this.faces[faceNum].point_normals[x])) ? foundPt : -1; - } - - if (hasUV) { - foundPt = (vec2.equal( - this.faces[oFace].uvs[oPoint], this.faces[faceNum].uvs[x])) ? foundPt : -1; - } - } - } - - if (foundPt !== -1) { - if (this.compiled.elements === undef) { - this.compiled.elements = []; - } - if (this.compiled.elements[i] === undef) { - this.compiled.elements[i] = []; - } - if (this.compiled.elements[i][j] === undef) { - this.compiled.elements[i][j] = []; - } - this.compiled.elements[i][j].push(foundPt); - } else { - this.compiled.vbo_points.push(this.points[ptNum][0]); - this.compiled.vbo_points.push(this.points[ptNum][1]); - this.compiled.vbo_points.push(this.points[ptNum][2]); - - if (this.bb.length === 0) { - this.bb[0] = [this.points[ptNum][0], - this.points[ptNum][1], - this.points[ptNum][2]]; - - this.bb[1] = [this.points[ptNum][0], - this.points[ptNum][1], - this.points[ptNum][2]]; - } else { - if (this.points[ptNum][0] < this.bb[0][0]) { - this.bb[0][0] = this.points[ptNum][0]; - } - if (this.points[ptNum][1] < this.bb[0][1]) { - this.bb[0][1] = this.points[ptNum][1]; - } - if (this.points[ptNum][2] < this.bb[0][2]) { - this.bb[0][2] = this.points[ptNum][2]; - } - - if (this.points[ptNum][0] > this.bb[1][0]) { - this.bb[1][0] = this.points[ptNum][0]; - } - if (this.points[ptNum][1] > this.bb[1][1]) { - this.bb[1][1] = this.points[ptNum][1]; - } - if (this.points[ptNum][2] > this.bb[1][2]) { - this.bb[1][2] = this.points[ptNum][2]; - } - } - - if (hasNorm) { - this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][0]); - this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][1]); - this.compiled.vbo_normals.push(this.faces[faceNum].point_normals[x][2]); - } - - if (hasUV) { - this.compiled.vbo_uvs.push(this.faces[faceNum].uvs[x][0]); - this.compiled.vbo_uvs.push(this.faces[faceNum].uvs[x][1]); - } - - if (this.compiled.elements === undef) { - this.compiled.elements = []; - } - if (this.compiled.elements[i] === undef) { - this.compiled.elements[i] = []; - } - if (this.compiled.elements[i][j] === undef) { - this.compiled.elements[i][j] = []; - } - - this.compiled.elements[i][j].push(idxCount); - - if (vtxRef[ptNum] === undef) { - vtxRef[ptNum] = []; - } - - vtxRef[ptNum].push([faceNum, x, idxCount]); - idxCount++; - } - } - } - } - } - } - } - - this.compiled.gl_points = GLCore.gl.createBuffer(); - GLCore.gl.bindBuffer(GLCore.gl.ARRAY_BUFFER, this.compiled.gl_points); - GLCore.gl.bufferData(GLCore.gl.ARRAY_BUFFER, new Float32Array(this.compiled.vbo_points), GLCore.gl.STATIC_DRAW); - - if (hasNorm) { - this.compiled.gl_normals = GLCore.gl.createBuffer(); - GLCore.gl.bindBuffer(GLCore.gl.ARRAY_BUFFER, this.compiled.gl_normals); - GLCore.gl.bufferData(GLCore.gl.ARRAY_BUFFER, new Float32Array(this.compiled.vbo_normals), GLCore.gl.STATIC_DRAW); - } - else - { - this.compiled.gl_normals = null; - } - - if (hasUV) { - this.compiled.gl_uvs = GLCore.gl.createBuffer(); - GLCore.gl.bindBuffer(GLCore.gl.ARRAY_BUFFER, this.compiled.gl_uvs); - GLCore.gl.bufferData(GLCore.gl.ARRAY_BUFFER, new Float32Array(this.compiled.vbo_uvs), GLCore.gl.STATIC_DRAW); - } - else - { - this.compiled.gl_uvs = null; - } - - var gl_elements = []; - - this.segment_state = []; - this.compiled.elements_ref = []; - - var ictr = 0; - - for (i in this.compiled.elements) { - if (this.compiled.elements.hasOwnProperty(i)) { - this.compiled.elements_ref[ictr] = []; - - var jctr = 0; - - for (j in this.compiled.elements[i]) { - if (this.compiled.elements[i].hasOwnProperty(j)) { - for (k in this.compiled.elements[i][j]) { - if (this.compiled.elements[i][j].hasOwnProperty(k)) { - gl_elements.push(this.compiled.elements[i][j][k]); - } - } - - this.segment_state[j] = true; - - this.compiled.elements_ref[ictr][jctr] = [parseInt(i), parseInt(j), parseInt(this.compiled.elements[i][j].length)]; - - jctr++; - } - } - ictr++; - } - } - - this.compiled.gl_elements = GLCore.gl.createBuffer(); - GLCore.gl.bindBuffer(GLCore.gl.ELEMENT_ARRAY_BUFFER, this.compiled.gl_elements); - GLCore.gl.bufferData(GLCore.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(gl_elements), GLCore.gl.STATIC_DRAW); - - // dump temporary buffers - this.compiled.vbo_normals = null; - this.compiled.vbo_points = null; - this.compiled.vbo_uvs = null; - this.compiled.elements = null; - - GLCore.gl.bindBuffer(GLCore.gl.ELEMENT_ARRAY_BUFFER, null); - - return this; - }; - - - - function UVMapper(obj_in) { - if (obj_in!==undef) { - this.rotation = (obj_in.rotation===undef)?[0, 0, 0]:obj_in.rotation; - this.scale = (obj_in.scale===undef)?[1, 1, 1]:obj_in.scale; - this.center = (obj_in.center===undef)?[0, 0, 0]:obj_in.center; - this.projection_mode = (obj_in.projectionMode===undef)?enums.uv.projection.PLANAR:obj_in.projectionMode; - this.projection_axis = (obj_in.projectionAxis===undef)?enums.uv.axis.X:obj_in.projectionAxis; - this.wrap_w_count = (obj_in.wrapW===undef)?1:obj_in.wrapW; - this.wrap_h_count = (obj_in.wrapH===undef)?1:obj_in.wrapH; - } else { - this.rotation = [0, 0, 0]; - this.scale = [1, 1, 1]; - this.center = [0, 0, 0]; - this.projection_mode = enums.uv.projection.PLANAR; - this.projection_axis = enums.uv.axis.X; - this.wrap_w_count = 1; - this.wrap_h_count = 1; - } - } - - - UVMapper.prototype.setRotation = function(rotation) { - this.rotation = rotation; - } - - UVMapper.prototype.setScale = function(scale) { - this.scale = scale; - } - - UVMapper.prototype.setCenter = function(center) { - this.center = center; - } - - UVMapper.prototype.setProjectionAxis = function(projection_axis) { - this.projection_axis = projection_axis; - } - - UVMapper.prototype.setProjectionMode = function(projection_mode) { - this.projection_mode = projection_mode; - } - - UVMapper.prototype.setWrapW = function(wrap_w) { - this.wrap_w_count = wrap_w; - } - - UVMapper.prototype.setWrapH = function(wrap_h) { - this.wrap_h_count = wrap_h; - } - - - // convert XYZ space to longitude - var xyz_to_h = function(x, y, z) { - var h; - - if (x === 0 && z === 0) { - h = 0; - } else { - if (z === 0) { - h = (x < 0) ? M_HALF_PI : -M_HALF_PI; - } else if (z < 0) { - h = -Math.atan(x / z) + M_PI; - } else { - h = -Math.atan(x / z); - } - } - - return h; - }; - - - // convert XYZ space to latitude and longitude - var xyz_to_hp = function(x, y, z) { - var h, p; - - if (x === 0 && z === 0) { - h = 0; - - if (y !== 0) { - p = (y < 0) ? -M_HALF_PI : M_HALF_PI; - } else { - p = 0; - } - } else { - if (z === 0) { - h = (x < 0) ? M_HALF_PI : -M_HALF_PI; - } else if (z < 0) { - h = -Math.atan(x / z) + M_PI; - } else { - h = -Math.atan(x / z); - } - - x = Math.sqrt(x * x + z * z); - - if (x === 0) { - p = (y < 0) ? -M_HALF_PI : M_HALF_PI; - } else { - p = Math.atan(y / x); - } - } - - return [h, p]; - }; - - - UVMapper.prototype.apply = function(obj, mat_num, seg_num) { - var u, v, s, t, lat, lon; - - var trans = new Transform(); - var transformed = false; - var t_result = null; - - if (this.center[0] || this.center[1] || this.center[2]) { - trans.translate(-this.center[0], -this.center[1], -this.center[2]); - transformed = true; - } - - if (this.rotation[0] || this.rotation[1] || this.rotation[2]) { - if (this.rotation[0]) { - trans.rotate(this.rotation[2], 0, 0, 1); - } - if (this.rotation[1]) { - trans.rotate(this.rotation[1], 0, 1, 0); - } - if (this.rotation[2]) { - trans.rotate(this.rotation[0], 1, 0, 0); - } - transformed = true; - } - - if (transformed) { - t_result = trans.getResult(); - } - - if (typeof(mat_num) === 'object') { - mat_num = mat_num.material_id; - } - - for (var i = 0, iMax = obj.faces.length; i < iMax; i++) { - if (obj.faces[i].material !== mat_num) { - continue; - } - if (seg_num !== undef) { - if (obj.faces[i].segment !== seg_num) { - continue; - } - } - - var nx, ny, nz; - - if (this.projection_mode === enums.uv.projection.CUBIC || this.projection_mode === enums.uv.projection.SKY) { - nx = Math.abs(obj.faces[i].normal[0]); - ny = Math.abs(obj.faces[i].normal[1]); - nz = Math.abs(obj.faces[i].normal[2]); - } - - for (var j = 0, jMax = obj.faces[i].points.length; j < jMax; j++) { - var uvpoint = obj.points[obj.faces[i].points[j]]; - - if (transformed) { - uvpoint = mat4.vec3_multiply(uvpoint, t_result); - } - - /* calculate the uv for the points referenced by this face's pointref vector */ - var p_mode = this.projection_mode; - //switch (this.projection_mode) { - if (p_mode === enums.uv.projection.SKY) { - //case enums.uv.projection.SKY: - var mapping = obj.sky_mapping; - /* see enums.uv.projection.CUBIC for normalization reasoning */ - if (nx >= ny && nx >= nz) { - s = uvpoint[2] / (this.scale[2]) + this.scale[2] / 2; - t = -uvpoint[1] / (this.scale[1]) + this.scale[1] / 2; - if (obj.faces[i].normal[0] < 0) { - //left - s = (mapping[2][2] - mapping[2][0]) * (1-s); - t = 1-((mapping[2][3] - mapping[2][1]) * (t)); - s += mapping[2][0]; - t += mapping[2][1]; - } - else { - //right - s = (mapping[3][2] - mapping[3][0]) * (s); - t = 1-((mapping[3][3] - mapping[3][1]) * (t)); - s += mapping[3][0]; - t += mapping[3][1]; - } //if - } //if - if (ny >= nx && ny >= nz) { - s = uvpoint[0] / (this.scale[0]) + this.scale[0] / 2; - t = -uvpoint[2] / (this.scale[2]) + this.scale[2] / 2; - if (obj.faces[i].normal[1] < 0) { - //down - s = ((mapping[1][2] - mapping[1][0]) * (s)); - t = 1-((mapping[1][3] - mapping[1][1]) * (t)); - s += mapping[1][0]; - t -= mapping[1][1]; - } - else { - //up - s = ((mapping[0][2] - mapping[0][0]) * (s)); - t = 1-((mapping[0][3] - mapping[0][1]) * (t)); - s += mapping[0][0]; - t -= mapping[0][1]; - } //if - } //if - if (nz >= nx && nz >= ny) { - s = uvpoint[0] / (this.scale[0]) + this.scale[0] / 2; - t = uvpoint[1] / (this.scale[1]) + this.scale[1] / 2; - if (obj.faces[i].normal[2] < 0) { - //front - s = ((mapping[4][2] - mapping[4][0]) * (s)); - t = 1-((mapping[4][3] - mapping[4][1]) * (1-t)); - s += mapping[4][0]; - t -= mapping[4][1]; - } - else { - //back - s = ((mapping[5][2] - mapping[5][0]) * (1-s)); - t = 1-((mapping[5][3] - mapping[5][1]) * (1-t)); - s += mapping[5][0]; - t += mapping[5][1]; - } //if - } //if - obj.faces[i].setUV([s, t], j); - //break; - } - else if (p_mode === enums.uv.projection.CUBIC) { - //case enums.uv.projection.CUBIC: - /* cubic projection needs to know the surface normal */ - /* x portion of vector is dominant, we're mapping in the Y/Z plane */ - if (nx >= ny && nx >= nz) { - /* we use a .5 offset because texture coordinates range from 0->1, so to center it we need to offset by .5 */ - s = uvpoint[2] / this.scale[2] + 0.5; - /* account for scale here */ - t = uvpoint[1] / this.scale[1] + 0.5; - } - - /* y portion of vector is dominant, we're mapping in the X/Z plane */ - if (ny >= nx && ny >= nz) { - - s = -uvpoint[0] / this.scale[0] + 0.5; - t = uvpoint[2] / this.scale[2] + 0.5; - } - - /* z portion of vector is dominant, we're mapping in the X/Y plane */ - if (nz >= nx && nz >= ny) { - s = -uvpoint[0] / this.scale[0] + 0.5; - t = uvpoint[1] / this.scale[1] + 0.5; - } - - if (obj.faces[i].normal[0] > 0) { - s = -s; - } - if (obj.faces[i].normal[1] < 0) { - s = -s; - } - if (obj.faces[i].normal[2] > 0) { - s = -s; - } - - obj.faces[i].setUV([s, t], j); - //break; - } - else if (p_mode === enums.uv.projection.PLANAR) { - //case enums.uv.projection.PLANAR: - s = ((this.projection_axis === enums.uv.axis.X) ? uvpoint[2] / this.scale[2] + 0.5 : -uvpoint[0] / this.scale[0] + 0.5); - t = ((this.projection_axis === enums.uv.axis.Y) ? uvpoint[2] / this.scale[2] + 0.5 : uvpoint[1] / this.scale[1] + 0.5); - - obj.faces[i].setUV([s, t], j); - //break; - } - else if (p_mode === enums.uv.projection.CYLINDRICAL) { - //case enums.uv.projection.CYLINDRICAL: - // Cylindrical is a little more tricky, we map based on the degree around the center point - var p_axis = this.projection_axis; - //switch (this.projection_axis) { - if (p_axis === enums.uv.axis.X) { - //case enums.uv.axis.X: - // xyz_to_h takes the point and returns a value representing the 'unwrapped' height position of this point - lon = xyz_to_h(uvpoint[2], uvpoint[0], -uvpoint[1]); - t = -uvpoint[0] / this.scale[0] + 0.5; - //break; - } - else if (p_axis === enums.uv.axis.Y) { - //case enums.uv.axis.Y: - lon = xyz_to_h(-uvpoint[0], uvpoint[1], uvpoint[2]); - t = -uvpoint[1] / this.scale[1] + 0.5; - //break; - } - else if (p_axis === enums.uv.axis.Z) { - //case enums.uv.axis.Z: - lon = xyz_to_h(-uvpoint[0], uvpoint[2], -uvpoint[1]); - t = -uvpoint[2] / this.scale[2] + 0.5; - //break; - } //if - - // convert it from radian space to texture space 0 to 1 * wrap, TWO_PI = 360 degrees - lon = 1.0 - lon / (M_TWO_PI); - - if (this.wrap_w_count !== 1.0) { - lon = lon * this.wrap_w_count; - } - - u = lon; - v = t; - - obj.faces[i].setUV([u, v], j); - //break; - } - else if (p_mode === enums.uv.projection.SPHERICAL) { - //case enums.uv.projection.SPHERICAL: - var latlon; - - // spherical is similar to cylindrical except we also unwrap the 'width' - var p_axis = this.projection_axis; - //switch (this.projection_axis) { - if (p_axis === enums.uv.axis.X) { - //case enums.uv.axis.X: - // xyz to hp takes the point value and 'unwraps' the latitude and longitude that projects to that point - latlon = xyz_to_hp(uvpoint[2], uvpoint[0], -uvpoint[1]); - //break; - } - else if (p_axis === enums.uv.axis.Y) { - //case enums.uv.axis.Y: - latlon = xyz_to_hp(uvpoint[0], -uvpoint[1], uvpoint[2]); - //break; - } - else if (p_axis === enums.uv.axis.Z) { - //case enums.uv.axis.Z: - latlon = xyz_to_hp(-uvpoint[0], uvpoint[2], -uvpoint[1]); - //break; - } //if - - // convert longitude and latitude to texture space coordinates, multiply by wrap height and width - lon = 1.0 - latlon[0] / M_TWO_PI; - lat = 0.5 - latlon[1] / M_PI; - - if (this.wrap_w_count !== 1.0) { - lon = lon * this.wrap_w_count; - } - if (this.wrap_h_count !== 1.0) { - lat = lat * this.wrap_h_count; - } - - u = lon; - v = lat; - - obj.faces[i].setUV([u, v], j); - //break; - } - else { - - // case enums.uv.projection.UV: - // // not handled here.. - // break; - //default: - // else mapping cannot be handled here, this shouldn't have happened :P - u = 0; - v = 0; - obj.faces[i].setUV([u, v], j); - //break; - } //if - } //for - } //for - faces - - return this; - }; - - function AABB_size(aabb) { - var x = aabb[0][0] < aabb[1][0] ? aabb[1][0] - aabb[0][0] : aabb[0][0] - aabb[1][0]; - var y = aabb[0][1] < aabb[1][1] ? aabb[1][1] - aabb[0][1] : aabb[0][1] - aabb[1][1]; - var z = aabb[0][2] < aabb[1][2] ? aabb[1][2] - aabb[0][2] : aabb[0][2] - aabb[1][2]; - return [x,y,z]; - } //AABB_size - function AABB_reset(aabb, point) { - if (point === undefined) { - point = [0,0,0]; - } //if - aabb[0][0] = point[0]; - aabb[0][1] = point[1]; - aabb[0][2] = point[2]; - aabb[1][0] = point[0]; - aabb[1][1] = point[1]; - aabb[1][2] = point[2]; - } //AABB_reset - function AABB_engulf(aabb, point) { - if (aabb[0][0] > point[0]) { - aabb[0][0] = point[0]; - } - if (aabb[0][1] > point[1]) { - aabb[0][1] = point[1]; - } - if (aabb[0][2] > point[2]) { - aabb[0][2] = point[2]; - } - if (aabb[1][0] < point[0]) { - aabb[1][0] = point[0]; - } - if (aabb[1][1] < point[1]) { - aabb[1][1] = point[1]; - } - if (aabb[1][2] < point[2]) { - aabb[1][2] = point[2]; - } - } //AABB::engulf - - -/* Lights */ - -function Light(light_type, lighting_method) { - if (light_type === undef) { - light_type = enums.light.type.POINT; - } - if (lighting_method === undef) { - lighting_method = enums.light.method.DYNAMIC; - } - - if (typeof(light_type)=='object') { - this.light_type = (light_type.type!==undef)?light_type.type:enums.light.type.POINT; - this.diffuse = (light_type.diffuse!==undef)?light_type.diffuse:[1, 1, 1]; - this.specular = (light_type.specular!==undef)?light_type.specular:[1.0,1.0,1.0]; - this.intensity = (light_type.intensity!==undef)?light_type.intensity:1.0; - this.position = (light_type.position!==undef)?light_type.position:[0, 0, 0]; - this.direction = (light_type.direction!==undef)?light_type.direction:[0, 0, 0]; - this.distance = (light_type.distance!==undef)?light_type.distance:10; - this.method = (light_type.method!==undef)?light_type.method:lighting_method; - } else { - this.light_type = light_type; - this.diffuse = [1, 1, 1]; - this.specular = [1.0,1.0,1.0]; - this.intensity = 1.0; - this.position = [0, 0, 0]; - this.direction = [0, 0, 0]; - this.distance = 10; - this.method = lighting_method; - } - - this.trans = new Transform(); - this.lposition = [0, 0, 0]; - this.tMatrix = this.trans.getResult(); - this.dirty = true; - this.octree_leaves = []; - this.octree_common_root = null; - this.octree_aabb = [[0, 0, 0], [0, 0, 0]]; - this.ignore_octree = false; - this.visible = true; - this.culled = true; - this.was_culled = true; - this.aabb = [[0,0,0],[0,0,0]]; - AABB_reset(this.aabb, this.position); - this.adjust_octree = SceneObject.prototype.adjust_octree; - this.motion = null; -} - -Light.prototype.setType = function(light_type) { - this.light_type = type; -} - -Light.prototype.setMethod = function(method) { - this.method = method; -} - -Light.prototype.setDiffuse = function(diffuse) { - this.diffuse = diffuse; -} -Light.prototype.setSpecular = function(specular) { - this.specular = specular; -} -Light.prototype.setIntensity = function(intensity) { - this.intensity = intensity; -} -Light.prototype.setPosition = function(position) { - this.position = position; -} -Light.prototype.setDistance = function(distance) { - this.distance = distance; -} - - -Light.prototype.control = function(controllerId, motionId, value) { - if (controllerId === enums.motion.POS) { - this.position[motionId] = value; - } else if (controllerId === enums.motion.INTENSITY) { - this.intensity = value; - } - - // else if (controllerId === enums.motion.ROT) { - // this.rotation[motionId] = value; - // } -} - -Light.prototype.doTransform = function(mat) { - if (!vec3.equal(this.lposition, this.position) || (mat !== undef)) { - this.trans.clearStack(); - this.trans.translate(this.position); - if ((mat !== undef)) { - this.trans.pushMatrix(mat); - } - this.tMatrix = this.trans.getResult(); - this.lposition[0] = this.position[0]; - this.lposition[1] = this.position[1]; - this.lposition[2] = this.position[2]; - this.dirty = true; - this.adjust_octree(); - } //if -} //Light::doTransform - -Light.prototype.getAABB = function() { - var aabb = [[0, 0, 0], [0, 0, 0]]; - AABB_engulf(aabb, [this.distance, this.distance, this.distance]); - AABB_engulf(aabb, [-this.distance, -this.distance, -this.distance]); - aabb[0] = vec3.add(aabb[0], this.position); - aabb[1] = vec3.add(aabb[1], this.position); - this.aabb = aabb; - return this.aabb; -}; - -Light.prototype.setDirection = function(x, y, z) { - if (typeof(x) === 'object') { - this.setDirection(x[0], x[1], x[2]); - return; - } - - - this.direction = vec3.normalize([x, y, z]); - - return this; -}; - -Light.prototype.setRotation = function(x, y, z) { - if (typeof(x) === 'object') { - this.setRotation(x[0], x[1], x[2]); - return; - } - - var t = new Transform(); - t.rotate([-x, -y, -z]); - t.pushMatrix(); - - this.direction = vec3.normalize(mat4.vec3_multiply([1, 0, 0], t.getResult())); - - return this; -}; - - -Light.prototype.setupShader = function(lShader,lNum) { - // lShader.setVector("lights["+lNum+"].lDiff", this.diffuse); - // lShader.setVector("lights["+lNum+"].lSpec", this.specular); - // lShader.setFloat("lights["+lNum+"].lInt", this.intensity); - // lShader.setFloat("lights["+lNum+"].lDist", this.distance); - // lShader.setVector("lights["+lNum+"].lPos", this.position); - // lShader.setVector("lights["+lNum+"].lDir", this.direction); - - var gl = GLCore.gl; - - gl.uniform3fv(lShader.lights[lNum].lDiff, this.diffuse); - gl.uniform3fv(lShader.lights[lNum].lSpec, this.specular); - gl.uniform3fv(lShader.lights[lNum].lPos, this.position); - gl.uniform3fv(lShader.lights[lNum].lDir, this.direction); - - gl.uniform1f(lShader.lights[lNum].lInt, this.intensity); - gl.uniform1f(lShader.lights[lNum].lDist, this.distance); - -}; - -var emptyLight = new Light(enums.light.type.POINT); -emptyLight.diffuse = [0, 0, 0]; -emptyLight.specular = [0, 0, 0]; -emptyLight.distance = 0; -emptyLight.intensity = 0; - -/* Shaders */ - -function Shader(vs_id, fs_id) { - var vertexShader; - var fragmentShader; - var loadedShader; - - this.uniforms = []; - this.uniform_type = []; - this.uniform_typelist = []; - - if (vs_id.indexOf("\n") !== -1) { - vertexShader = cubicvr_compileShader(GLCore.gl, vs_id, "x-shader/x-vertex"); - } else { - vertexShader = cubicvr_getShader(GLCore.gl, vs_id); - - if (vertexShader === null) { - loadedShader = util.getURL(vs_id); - - vertexShader = cubicvr_compileShader(GLCore.gl, loadedShader, "x-shader/x-vertex"); - } - } - - if (fs_id.indexOf("\n") !== -1) { - fragmentShader = cubicvr_compileShader(GLCore.gl, fs_id, "x-shader/x-fragment"); - } else { - fragmentShader = cubicvr_getShader(GLCore.gl, fs_id); - - if (fragmentShader === null) { - loadedShader = util.getURL(fs_id); - - fragmentShader = cubicvr_compileShader(GLCore.gl, loadedShader, "x-shader/x-fragment"); - } - - } - - - this.shader = GLCore.gl.createProgram(); - GLCore.gl.attachShader(this.shader, vertexShader); - GLCore.gl.attachShader(this.shader, fragmentShader); - GLCore.gl.linkProgram(this.shader); - - if (!GLCore.gl.getProgramParameter(this.shader, GLCore.gl.LINK_STATUS)) { -// alert("Could not initialise shader vert(" + vs_id + "), frag(" + fs_id + ")"); - throw new Error("Could not initialise shader vert(" + vs_id + "), frag(" + fs_id + ")"); - return; - } -} - - -Shader.prototype.bindSelf = function(uniform_id) { - var t,k,p,v; - - if (uniform_id.indexOf(".")!==-1) { - if (uniform_id.indexOf("[")!==-1) { - t = uniform_id.split("["); - p = t[0]; - t = t[1].split("]"); - k = t[0]; - t = t[1].split("."); - v = t[1]; - - if (this[p] === undef) { - this[p] = []; - } - if (this[p][k] === undef) { - this[p][k] = {}; - } - - this[p][k][v] = this.uniforms[uniform_id]; - - } else { // untested - t = uniform_id.split("."); - p = t[0]; - v = t[1]; - - if (this[p] === undef) { - this[p] = {}; - } - - this[p][v] = this.uniforms[uniform_id]; - - } - } else if ( uniform_id.indexOf("[") !== -1){ // untested - t = uniform_id.split("["); - p = t[0]; - t = t[1].split("]"); - k = t[0]; - - if (this[p] === undef) { - this[p] = []; - } - - this[p][k] = this.uniforms[uniform_id]; - } - else { - this[uniform_id] = this.uniforms[uniform_id]; - } -} - -Shader.prototype.addMatrix = function(uniform_id, default_val) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getUniformLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.MATRIX; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - if (default_val !== undef) { - this.setMatrix(uniform_id, default_val); - } - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.addVector = function(uniform_id, default_val) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getUniformLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.VECTOR; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - if (default_val !== undef) { - this.setVector(uniform_id, default_val); - } - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.addFloat = function(uniform_id, default_val) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getUniformLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.FLOAT; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - if (default_val !== undef) { - this.setFloat(uniform_id, default_val); - } - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - - -Shader.prototype.addVertexArray = function(uniform_id) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getAttribLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.ARRAY_VERTEX; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.addUVArray = function(uniform_id) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getAttribLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.ARRAY_UV; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.addFloatArray = function(uniform_id) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getAttribLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.ARRAY_FLOAT; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.addInt = function(uniform_id, default_val) { - this.use(); - this.uniforms[uniform_id] = GLCore.gl.getUniformLocation(this.shader, uniform_id); - this.uniform_type[uniform_id] = enums.shader.uniform.INT; - this.uniform_typelist.push([this.uniforms[uniform_id], this.uniform_type[uniform_id]]); - - if (default_val !== undef) { - this.setInt(uniform_id, default_val); - } - - this.bindSelf(uniform_id); - return this.uniforms[uniform_id]; -}; - -Shader.prototype.use = function() { - GLCore.gl.useProgram(this.shader); -}; - -Shader.prototype.setMatrix = function(uniform_id, mat) { - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - var l = mat.length; - - if (l===16) { - GLCore.gl.uniformMatrix4fv(u, false, mat); - } else if (l === 9) { - GLCore.gl.uniformMatrix3fv(u, false, mat); - } else if (l === 4) { - GLCore.gl.uniformMatrix2fv(u, false, mat); - } -}; - -Shader.prototype.setInt = function(uniform_id, val) { - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - GLCore.gl.uniform1i(u, val); -}; - -Shader.prototype.setFloat = function(uniform_id, val) { - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - GLCore.gl.uniform1f(u, val); -}; - -Shader.prototype.setVector = function(uniform_id, val) { - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - var l = val.length; - - if (l==3) { - GLCore.gl.uniform3fv(u, val); - } else if (l==2) { - GLCore.gl.uniform2fv(u, val); - } else { - GLCore.gl.uniform4fv(u, val); - } -}; - - -Shader.prototype.clearArray = function(uniform_id) { - var gl = GLCore.gl; - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - gl.disableVertexAttribArray(u); -}; - -Shader.prototype.bindArray = function(uniform_id, buf) { - var gl = GLCore.gl; - var u = this.uniforms[uniform_id]; - if (u === null) { - return; - } - - var t = this.uniform_type[uniform_id]; - - if (t === enums.shader.uniform.ARRAY_VERTEX) { - gl.bindBuffer(gl.ARRAY_BUFFER, buf); - gl.vertexAttribPointer(u, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(u); - } else if (t === enums.shader.uniform.ARRAY_UV) { - gl.bindBuffer(gl.ARRAY_BUFFER, buf); - gl.vertexAttribPointer(u, 2, gl.FLOAT, false, 0, 0); - } else if (t === enums.shader.uniform.ARRAY_FLOAT) { - gl.bindBuffer(gl.ARRAY_BUFFER, buf); - gl.vertexAttribPointer(u, 1, gl.FLOAT, false, 0, 0); - } -}; - - -/* Materials */ - -var Material = function(mat_name) { - this.material_id = -1; - - /* - if (mat_name !== undef) { - var old_mat = Material_ref[mat_name]; - if (old_mat) { - var old_id = old_mat.material_id; - Materials[old_id] = this; - old_mat = null; - } //if - Material_ref[mat_name] = this; - } - */ - - //if (this.material_id === -1) { - this.material_id = Materials.length; - Materials.push(this); - //} //if - - this.initialized = false; - this.textures = []; - this.shader = []; - this.customShader = null; - - if (typeof(mat_name)==='object') { - this.diffuse = (mat_name.diffuse===undef)?[1.0, 1.0, 1.0]:mat_name.diffuse; - this.specular = (mat_name.specular===undef)?[0.1, 0.1, 0.1]:mat_name.specular; - this.color = (mat_name.color===undef)?[1, 1, 1]:mat_name.color; - this.ambient = (mat_name.ambient===undef)?[0, 0, 0]:mat_name.ambient; - this.opacity = (mat_name.opacity===undef)?1.0:mat_name.opacity; - this.shininess = (mat_name.shininess===undef)?1.0:mat_name.shininess; - this.max_smooth = (mat_name.max_smooth===undef)?60.0:mat_name.max_smooth; - this.env_amount = (mat_name.env_amount===undef)?0.75:mat_name.env_amount; - this.name = (mat_name.name===undef)?undef:mat_name.name; - - if (typeof(mat_name.textures)==='object') { - if (mat_name.textures.color!==undef) this.setTexture(mat_name.textures.color,enums.texture.map.COLOR); - if (mat_name.textures.envsphere!==undef) this.setTexture(mat_name.textures.envsphere,enums.texture.map.ENVSPHERE); - if (mat_name.textures.normal!==undef) this.setTexture(mat_name.textures.normal,enums.texture.map.NORMAL); - if (mat_name.textures.bump!==undef) this.setTexture(mat_name.textures.bump,enums.texture.map.BUMP); - if (mat_name.textures.reflect!==undef) this.setTexture(mat_name.textures.reflect,enums.texture.map.REFLECT); - if (mat_name.textures.specular!==undef) this.setTexture(mat_name.textures.specular,enums.texture.map.SPECULAR); - if (mat_name.textures.ambient!==undef) this.setTexture(mat_name.textures.ambient,enums.texture.map.AMBIENT); - if (mat_name.textures.alpha!==undef) this.setTexture(mat_name.textures.alpha,enums.texture.map.ALPHA); - } - } else { - this.diffuse = [1.0, 1.0, 1.0]; - this.specular = [0.1, 0.1, 0.1]; - this.color = [1, 1, 1]; - this.ambient = [0, 0, 0]; - this.opacity = 1.0; - this.shininess = 1.0; - this.max_smooth = 60.0; - this.name = mat_name; - } - -}; - -Material.prototype.setTexture = function(tex, tex_type) { - if (tex_type === undef) { - tex_type = 0; - } - this.textures[tex_type] = tex; -}; - - - -Material.prototype.calcShaderMask = function() { - var shader_mask = 0; - - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.COLOR]) === 'object') ? enums.shader.map.COLOR : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.SPECULAR]) === 'object') ? enums.shader.map.SPECULAR : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.NORMAL]) === 'object') ? enums.shader.map.NORMAL : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.BUMP]) === 'object') ? enums.shader.map.BUMP : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.REFLECT]) === 'object') ? enums.shader.map.REFLECT : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.ENVSPHERE]) === 'object') ? enums.shader.map.ENVSPHERE : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.AMBIENT]) === 'object') ? enums.shader.map.AMBIENT : 0); - shader_mask = shader_mask + ((typeof(this.textures[enums.texture.map.ALPHA]) === 'object') ? enums.shader.map.ALPHA : 0); - shader_mask = shader_mask + ((this.opacity !== 1.0) ? enums.shader.map.ALPHA : 0); - - return shader_mask; -}; - - -Material.prototype.getShaderHeader = function(light_type,light_count) { - return ((light_count !== undef) ? ("#define loopCount "+light_count+"\n"):"") + - "#define hasColorMap " + ((typeof(this.textures[enums.texture.map.COLOR]) === 'object') ? 1 : 0) + "\n#define hasSpecularMap " + ((typeof(this.textures[enums.texture.map.SPECULAR]) === 'object') ? 1 : 0) + "\n#define hasNormalMap " + ((typeof(this.textures[enums.texture.map.NORMAL]) === 'object') ? 1 : 0) + "\n#define hasBumpMap " + ((typeof(this.textures[enums.texture.map.BUMP]) === 'object') ? 1 : 0) + "\n#define hasReflectMap " + ((typeof(this.textures[enums.texture.map.REFLECT]) === 'object') ? 1 : 0) + "\n#define hasEnvSphereMap " + ((typeof(this.textures[enums.texture.map.ENVSPHERE]) === 'object') ? 1 : 0) + "\n#define hasAmbientMap " + ((typeof(this.textures[enums.texture.map.AMBIENT]) === 'object') ? 1 : 0) + "\n#define hasAlphaMap " + ((typeof(this.textures[enums.texture.map.ALPHA]) === 'object') ? 1 : 0) + "\n#define hasAlpha " + ((this.opacity !== 1.0) ? 1 : 0) + "\n#define lightPoint " + ((light_type === enums.light.type.POINT) ? 1 : 0) + "\n#define lightDirectional " + ((light_type === enums.light.type.DIRECTIONAL) ? 1 : 0) + "\n#define lightSpot " + ((light_type === enums.light.type.SPOT) ? 1 : 0) + "\n#define lightArea " + ((light_type === enums.light.type.AREA) ? 1 : 0) + "\n#define alphaDepth " + (GLCore.depth_alpha ? 1 : 0) + "\n\n"; -}; - - -Material.prototype.bindObject = function(obj_in, light_shader) { - var gl = GLCore.gl; - - var u = light_shader; - var up = u.aVertexPosition; - var uv = u.aTextureCoord; - var un = u.aNormal; - - gl.bindBuffer(gl.ARRAY_BUFFER, obj_in.compiled.gl_points); - gl.vertexAttribPointer(up, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(up); - - if (obj_in.compiled.gl_uvs!==null && uv !==-1) { - gl.bindBuffer(gl.ARRAY_BUFFER, obj_in.compiled.gl_uvs); - gl.vertexAttribPointer(uv, 2, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(uv); - } - - if (obj_in.compiled.gl_normals!==null && un !==-1) { - gl.bindBuffer(gl.ARRAY_BUFFER, obj_in.compiled.gl_normals); - gl.vertexAttribPointer(un, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(un); - } - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj_in.compiled.gl_elements); -}; - -Material.prototype.clearObject = function(obj_in,light_shader) { - var gl = GLCore.gl; - - var u = light_shader; - var uv = u.aTextureCoord; - var un = u.aNormal; - - if (obj_in.compiled.gl_uvs!==null && uv !==-1) { - gl.disableVertexAttribArray(uv); - } - - if (obj_in.compiled.gl_normals!==null && un !==-1) { - gl.disableVertexAttribArray(un); - } - -} - - -Material.prototype.use = function(light_type,num_lights) { - if (num_lights === undef) { - num_lights = 0; - } - - if (this.customShader !== null) { - this.customShader.use(); - return; - } - - if (light_type === undef) { - light_type = 0; - } - - var m; - var thistex = this.textures; - - if (this.shader[light_type] === undef) { - this.shader[light_type] = []; - } - - if (this.shader[light_type][num_lights] === undef) { - - var smask = this.calcShaderMask(light_type); - - if (ShaderPool[light_type][smask] === undef) { - ShaderPool[light_type][smask] = []; - } - - if (ShaderPool[light_type][smask][num_lights] === undef) { - var hdr = this.getShaderHeader(light_type,num_lights); - var vs = hdr + GLCore.CoreShader_vs; - var fs = hdr + GLCore.CoreShader_fs; - - var l = new Shader(vs, fs); - - ShaderPool[light_type][smask][num_lights] = l; - - m = 0; - - if (typeof(thistex[enums.texture.map.COLOR]) === 'object') { - l.addInt("colorMap", m++); - } - if (typeof(thistex[enums.texture.map.ENVSPHERE]) === 'object') { - l.addInt("envSphereMap", m++); - } - if (typeof(thistex[enums.texture.map.NORMAL]) === 'object') { - l.addInt("normalMap", m++); - } - if (typeof(thistex[enums.texture.map.BUMP]) === 'object') { - l.addInt("bumpMap", m++); - } - if (typeof(thistex[enums.texture.map.REFLECT]) === 'object') { - l.addInt("reflectMap", m++); - } - if (typeof(thistex[enums.texture.map.SPECULAR]) === 'object') { - l.addInt("specularMap", m++); - } - if (typeof(thistex[enums.texture.map.AMBIENT]) === 'object') { - l.addInt("ambientMap", m++); - } - if (typeof(thistex[enums.texture.map.ALPHA]) === 'object') { - l.addInt("alphaMap", m++); - } - - l.addMatrix("uMVMatrix"); - l.addMatrix("uPMatrix"); - l.addMatrix("uOMatrix"); - l.addMatrix("uNMatrix"); - - l.addVertexArray("aVertexPosition"); - l.addVertexArray("aNormal"); - - for (var mLight = 0; mLight < num_lights; mLight++) { - l.addVector("lights["+mLight+"].lDiff"); - l.addVector("lights["+mLight+"].lSpec"); - l.addFloat("lights["+mLight+"].lInt"); - l.addFloat("lights["+mLight+"].lDist"); - l.addVector("lights["+mLight+"].lPos"); - l.addVector("lights["+mLight+"].lDir"); - } - - l.addVector("lAmb"); - l.addVector("mDiff"); - l.addVector("mColor"); - l.addVector("mAmb"); - l.addVector("mSpec"); - l.addFloat("mShine"); - l.addFloat("mAlpha"); - l.addFloat("envAmount"); - - if (GLCore.depth_alpha) { - l.addVector("depthInfo"); - } - - l.addUVArray("aTextureCoord"); - } - - this.shader[light_type][num_lights] = ShaderPool[light_type][smask][num_lights]; - } - - var sh = this.shader[light_type][num_lights]; - var gl = GLCore.gl - - sh.use(); - - m = 0; - var t; - - if (t = thistex[enums.texture.map.COLOR]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.ENVSPHERE]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - // sh.setFloat("envAmount", this.env_amount); - gl.uniform1f(sh.envAmount,this.env_amount); - } - if (t = thistex[enums.texture.map.NORMAL]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.BUMP]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.REFLECT]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.SPECULAR]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.AMBIENT]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - if (t = thistex[enums.texture.map.ALPHA]) { - t.use(GLCore.gl.TEXTURE0+m); m++; - } - - // sh.setVector("mColor", this.color); - // sh.setVector("mDiff", this.diffuse); - // sh.setVector("mAmb", this.ambient); - // sh.setVector("mSpec", this.specular); - // sh.setFloat("mShine", this.shininess); - // sh.setVector("lAmb", CubicVR.globalAmbient); - - gl.uniform3fv(sh.mColor,this.color); - gl.uniform3fv(sh.mDiff,this.diffuse); - gl.uniform3fv(sh.mAmb,this.ambient); - gl.uniform3fv(sh.mSpec,this.specular); - gl.uniform1f(sh.mShine,this.shininess*128.0); - gl.uniform3fv(sh.lAmb, CubicVR.globalAmbient); - - - if (GLCore.depth_alpha) { - //sh.setVector("depthInfo", [GLCore.depth_alpha_near, GLCore.depth_alpha_far, 0.0]); - gl.uniform3fv(sh.depthInfo, [GLCore.depth_alpha_near, GLCore.depth_alpha_far, 0.0]); - } - - if (this.opacity !== 1.0) { - gl.uniform1f(sh.mAlpha, this.opacity); - } -}; - -/* Textures */ -var DeferredLoadTexture = function(img_path, filter_type) { - this.img_path = img_path; - this.filter_type = filter_type; -} //DefferedLoadTexture - -DeferredLoadTexture.prototype.getTexture = function(deferred_bin, binId) { - return new Texture(this.img_path, this.filter_type, deferred_bin, binId); -} //getTexture - -var Texture = function(img_path,filter_type,deferred_bin,binId,ready_func) { - var gl = GLCore.gl; - - this.tex_id = Textures.length; - this.filterType = -1; - this.onready = ready_func; - this.loaded = false; - Textures[this.tex_id] = gl.createTexture(); - Textures_obj[this.tex_id] = this; - - if (img_path) { - Images[this.tex_id] = new Image(); - Texture_ref[img_path] = this.tex_id; - } - - gl.bindTexture(gl.TEXTURE_2D, Textures[this.tex_id]); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - if (img_path) { - var texId = this.tex_id; - var filterType = (filter_type!==undef)?filter_type:GLCore.default_filter; - - var that = this; - - Images[this.tex_id].onload = function() { - gl.bindTexture(gl.TEXTURE_2D, Textures[texId]); - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); - - var img = Images[texId]; - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); - - var tw = img.width, th = img.height; - - var isPOT = true; - - if (tw===1||th===1) { - isPOT = false; - } else { - if (tw!==1) { while ((tw % 2) === 0) { tw /= 2; } } - if (th!==1) { while ((th % 2) === 0) { th /= 2; } } - if (tw>1) { isPOT = false; } - if (th>1) { isPOT = false; } - } - - if (!isPOT) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - - if (Textures_obj[texId].filterType===-1) { - if (!isPOT) { - if (filterType === enums.texture.filter.LINEAR_MIP) { - filterType = enums.texture.filter.LINEAR; - } - } - - if (Textures_obj[texId].filterType===-1) { - Textures_obj[texId].setFilter(filterType); - } - } - else - { - Textures_obj[texId].setFilter(Textures_obj[texId].filterType); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - - if (that.onready) { - that.onready(); - } //if - that.loaded = true; - }; - - if (!deferred_bin) - { - Images[this.tex_id].src = img_path; - } - else - { - Images[this.tex_id].deferredSrc = img_path; - //console.log('adding image to binId=' + binId + ' img_path=' + img_path); - deferred_bin.addImage(binId,img_path,Images[this.tex_id]); - } - } - - this.active_unit = -1; -}; - - -Texture.prototype.setFilter = function(filterType) { - var gl = CubicVR.GLCore.gl; - - gl.bindTexture(gl.TEXTURE_2D, Textures[this.tex_id]); - /* - switch (filterType) - { - case enums.texture.filter.LINEAR: - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - break; - case enums.texture.filter.LINEAR_MIP: - 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); - break; - case enums.texture.filter.NEAREST: - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - break; - } - */ - - if (filterType === enums.texture.filter.LINEAR) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - } else if (filterType === enums.texture.filter.LINEAR_MIP) { - 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); - } else if (filterType === enums.texture.filter.NEAREST) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - } else if (filterType === enums.texture.filter.NEAREST_MIP) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR); - gl.generateMipmap(gl.TEXTURE_2D); - } - - this.filterType = filterType; -}; - -Texture.prototype.use = function(tex_unit) { - GLCore.gl.activeTexture(tex_unit); - GLCore.gl.bindTexture(GLCore.gl.TEXTURE_2D, Textures[this.tex_id]); - this.active_unit = tex_unit; -}; - -Texture.prototype.clear = function() { - if (this.active_unit !== -1) { - GLCore.gl.activeTexture(this.active_unit); - GLCore.gl.bindTexture(GLCore.gl.TEXTURE_2D, null); - this.active_unit = -1; - } -}; - -function CanvasTexture(canvasElement) { - var gl = CubicVR.GLCore.gl; - this.canvasSource = canvasElement; - this.texture = new CubicVR.Texture(); -}; //CanvasTexture - -CanvasTexture.prototype.use = function(tex_unit) { - this.texture.use(tex_unit); -}; //CanvasTexture.use - -CanvasTexture.prototype.setFilter = function(filterType) { - this.texture.setFilter(filterType); -}; //CanvasTexture.setFilter - -CanvasTexture.prototype.clear = function() { - this.texture.clear(); -}; //CanvasTexture.clear - -CanvasTexture.prototype.update = function() { - var gl = CubicVR.GLCore.gl; - gl.bindTexture(gl.TEXTURE_2D, CubicVR.Textures[this.texture.tex_id]); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.canvasSource); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.bindTexture(gl.TEXTURE_2D, null); -}; //CanvasTexture.update - -function TextTexture(text, options) { - var color = (options && options.color) || '#fff'; - var bgcolor = (options && options.bgcolor); - var font = (options && options.font) || '18pt Arial'; - var align = (options && options.align) || 'start'; - var y = (options && options.y) || 0; - var width = (options && options.width) || undef; - var height = (options && options.height) || undef; - - var canvas = document.createElement('CANVAS'); - var ctx = canvas.getContext('2d'); - - var lines = 0; - if (typeof(text) === 'string') { - lines = 1; - } - else { - lines = text.length; - } //if - - ctx.font = font; - - // This approximation is awful. There has to be a better way to find the height of a text block - var lineHeight = (options && options.lineHeight) || ctx.measureText('OO').width; - var widest; - if (lines === 1) { - widest = ctx.measureText(text).width; - } - else { - widest = 0; - for (var i=0; i<lines; ++i) { - var w = ctx.measureText(text[i]).width; - if (w > widest) { - widest = w; - } //if - } //for - } //if - - canvas.width = width || widest; - canvas.height = height || lineHeight * lines; - - if (bgcolor) { - ctx.fillStyle = bgcolor; - ctx.fillRect(0, 0, canvas.width, canvas.height); - } //if - ctx.fillStyle = color; - ctx.font = font; - ctx.textAlign = align; - ctx.textBaseline = 'top'; - if (lines === 1) { - var x = (options && options.x) || align === 'center' ? canvas.width/2 : align === 'right' ? canvas.width : 0; - ctx.fillText(text, x, y); - } - else { - for (var i=0; i<lines; ++i) { - var x = (options && options.x) || align === 'center' ? canvas.width/2 : align === 'right' ? canvas.width : 0; - ctx.fillText(text[i], x, y+i*lineHeight); - } //for - } //if - ctx.fill(); - - this.use = CanvasTexture.prototype.use; - this.clear = CanvasTexture.prototype.clear; - this.update = CanvasTexture.prototype.update; - CanvasTexture.apply(this, [canvas]); - - this.update(); - this.canvasSource = canvas = ctx = null; -}; //TextTexture - -function PJSTexture(pjsURL, width, height) { - var gl = CubicVR.GLCore.gl; - this.texture = new CubicVR.Texture(); - this.canvas = document.createElement("CANVAS"); - this.canvas.width = width; - this.canvas.height = height; - - // this assumes processing is already included.. - this.pjs = new Processing(this.canvas,CubicVR.util.getURL(pjsURL)); - this.pjs.noLoop(); - this.pjs.redraw(); - - var tw = this.canvas.width, th = this.canvas.height; - - var isPOT = true; - - if (tw===1||th===1) { - isPOT = false; - } else { - if (tw !== 1) { while ((tw % 2) === 0) { tw /= 2; } } - if (th !== 1) { while ((th % 2) === 0) { th /= 2; } } - if (tw > 1) { isPOT = false; } - if (th > 1) { isPOT = false; } - } - - // bind functions to "subclass" a texture - this.setFilter=this.texture.setFilter; - this.clear=this.texture.clear; - this.use=this.texture.use; - this.tex_id=this.texture.tex_id; - this.filterType=this.texture.filterType; - - - if (!isPOT) { - this.setFilter(enums.texture.filter.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } else { - this.setFilter(enums.texture.filter.LINEAR_MIP); - } -} - -PJSTexture.prototype.update = function() { - var gl = CubicVR.GLCore.gl; - - this.pjs.redraw(); - - gl.bindTexture(gl.TEXTURE_2D, CubicVR.Textures[this.texture.tex_id]); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.canvas); - - if (this.filterType === enums.texture.filter.LINEAR_MIP) { - gl.generateMipmap(gl.TEXTURE_2D); - } - - gl.bindTexture(gl.TEXTURE_2D, null); -}; - - -/* Render functions */ - - -function cubicvr_renderObject(obj_in,camera,o_matrix,lighting) { - - if (obj_in.compiled===null) { - return; - } - - var ofs = 0; - var gl = CubicVR.GLCore.gl; - var numLights = (lighting === undef) ? 0: lighting.length; - var mshader, last_ltype, l; - var lcount = 0; - var j; - var mat = null; -// var nullAmbient = [0,0,0]; -// var tmpAmbient = CubicVR.globalAmbient; - - var bound = false; - - gl.depthFunc(gl.LEQUAL); - - if (o_matrix === undef) { o_matrix = cubicvr_identity; } - - for (var ic = 0, icLen = obj_in.compiled.elements_ref.length; ic < icLen; ic++) { - var i = obj_in.compiled.elements_ref[ic][0][0]; - - mat = Materials[i]; - - var len = 0; - var drawn = false; - - if (mat.opacity !== 1.0) { - gl.enable(gl.BLEND); - gl.depthMask(0); - gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); - } else { - gl.depthMask(1); - gl.disable(gl.BLEND); - gl.blendFunc(gl.ONE,gl.ONE); - } - - for (var jc = 0, jcLen = obj_in.compiled.elements_ref[ic].length; jc < jcLen; jc++) { - j = obj_in.compiled.elements_ref[ic][jc][1]; - - drawn = false; - - var this_len = obj_in.compiled.elements_ref[ic][jc][2]; - - len += this_len; - - if (obj_in.segment_state[j]) { - // ... - } else if (len > this_len) { - ofs += this_len*2; - len -= this_len; - - // start lighting loop - // start inner - if (!numLights) { - mat.use(0,0); - - gl.uniformMatrix4fv(mat.shader[0][0].uMVMatrix,false,camera.mvMatrix); - gl.uniformMatrix4fv(mat.shader[0][0].uPMatrix,false,camera.pMatrix); - gl.uniformMatrix4fv(mat.shader[0][0].uOMatrix,false,o_matrix); - gl.uniformMatrix3fv(mat.shader[0][0].uNMatrix,false,camera.nMatrix); - - if (!bound) { mat.bindObject(obj_in,mat.shader[0][0]); bound = true; } - - gl.drawElements(gl.TRIANGLES, len, gl.UNSIGNED_SHORT, ofs); - - } else { - var subcount = 0; - var blended = false; - - for (subcount = 0; subcount < numLights; ) - { - nLights = numLights-subcount; - if (nLights>MAX_LIGHTS) { - nLights=MAX_LIGHTS; - } - - if (subcount>0 && !blended) { - gl.enable(gl.BLEND); - gl.blendFunc(gl.ONE,gl.ONE); - gl.depthFunc(gl.EQUAL); - blended = true; - } - - mshader = undef; - l = lighting[subcount]; - var lt = l.light_type - - for (lcount = 0; lcount < nLights; lcount++) { - if (lighting[lcount+subcount].light_type!=lt) { - nLights = lcount; - break; - } - } - - mat.use(l.light_type,nLights); - - mshader = mat.shader[l.light_type][nLights]; - - gl.uniformMatrix4fv(mshader.uMVMatrix,false,camera.mvMatrix); - gl.uniformMatrix4fv(mshader.uPMatrix,false,camera.pMatrix); - gl.uniformMatrix4fv(mshader.uOMatrix,false,o_matrix); - gl.uniformMatrix3fv(mshader.uNMatrix,false,camera.nMatrix); - - if (!bound) { mat.bindObject(obj_in,mshader); bound = true; } - - for (lcount = 0; lcount < nLights; lcount++) { - lighting[lcount+subcount].setupShader(mshader,lcount); - } - - gl.drawElements(gl.TRIANGLES, len, gl.UNSIGNED_SHORT, ofs); - // var err = gl.getError(); - // if (err) { - // var uv = mshader.uniforms["aTextureCoord"]; - // var un = mshader.uniforms["aNormal"]; - // console.log(obj_in.compiled.gl_uvs!==null,obj_in.compiled.gl_normals!==null, un, uv, len, ofs, subcount); - // - // throw new Error('webgl error on mesh: ' + obj_in.name); - // } - - subcount += nLights; - } - - if (blended) - { - gl.disable(gl.BLEND); - gl.depthFunc(gl.LEQUAL); - } - } - - /// end inner - - - ofs += len*2; // Note: unsigned short = 2 bytes - len = 0; - drawn = true; - } else { - ofs += len*2; - len = 0; - } - } - - if (!drawn && obj_in.segment_state[j]) { - // this is an exact copy/paste of above - // start lighting loop - // start inner - if (!numLights) { - mat.use(0,0); - - gl.uniformMatrix4fv(mat.shader[0][0].uMVMatrix,false,camera.mvMatrix); - gl.uniformMatrix4fv(mat.shader[0][0].uPMatrix,false,camera.pMatrix); - gl.uniformMatrix4fv(mat.shader[0][0].uOMatrix,false,o_matrix); - gl.uniformMatrix3fv(mat.shader[0][0].uNMatrix,false,camera.nMatrix); - - if (!bound) { mat.bindObject(obj_in,mat.shader[0][0]); bound = true; } - - gl.drawElements(gl.TRIANGLES, len, gl.UNSIGNED_SHORT, ofs); - - } else { - var subcount = 0; - var blended = false; - - for (subcount = 0; subcount < numLights; ) - { - nLights = numLights-subcount; - if (nLights>MAX_LIGHTS) { - nLights=MAX_LIGHTS; - } - - if (subcount>0 && !blended) { - gl.enable(gl.BLEND); - gl.blendFunc(gl.ONE,gl.ONE); - gl.depthFunc(gl.EQUAL); - blended = true; - } - - mshader = undef; - l = lighting[subcount]; - var lt = l.light_type - - for (lcount = 0; lcount < nLights; lcount++) { - if (lighting[lcount+subcount].light_type!=lt) { - nLights = lcount; - break; - } - } - - mat.use(l.light_type,nLights); - - mshader = mat.shader[l.light_type][nLights]; - - gl.uniformMatrix4fv(mshader.uMVMatrix,false,camera.mvMatrix); - gl.uniformMatrix4fv(mshader.uPMatrix,false,camera.pMatrix); - gl.uniformMatrix4fv(mshader.uOMatrix,false,o_matrix); - gl.uniformMatrix3fv(mshader.uNMatrix,false,camera.nMatrix); - - if (!bound) { mat.bindObject(obj_in,mshader); bound = true; } - - for (lcount = 0; lcount < nLights; lcount++) { - lighting[lcount+subcount].setupShader(mshader,lcount); - } - - gl.drawElements(gl.TRIANGLES, len, gl.UNSIGNED_SHORT, ofs); - // var err = gl.getError(); - // if (err) { - // var uv = mshader.uniforms["aTextureCoord"]; - // var un = mshader.uniforms["aNormal"]; - // console.log(obj_in.compiled.gl_uvs!==null,obj_in.compiled.gl_normals!==null, un, uv, len, ofs, subcount); - // - // throw new Error('webgl error on mesh: ' + obj_in.name); - // } - - subcount += nLights; - } - - if (blended) - { - gl.disable(gl.BLEND); - gl.depthFunc(gl.LEQUAL); - } - } - - /// end inner - - ofs += len*2; - } - } - - if (mat && mshader) { - mat.clearObject(obj_in,mshader); - } - - // gl.disableVertexAttribArray(0); - // gl.disableVertexAttribArray(2); - // gl.disableVertexAttribArray(3); - - gl.depthMask(1); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); -} - - -/* Procedural Objects */ - -function cubicvr_latheObject(obj_in, pointList, lathe_divisions, material, transform, uvmapper) { - var slices = []; - var sliceNum; - - var up = [0, 1, 0]; - var right = [1, 0, 0]; - var pos = [0, 0, 0]; - var pofs = obj_in.points.length; - - var i, j, jMax, k, kMax; - - sliceNum = 0; - - for (i = 0; i < M_TWO_PI; i += (M_TWO_PI / lathe_divisions)) { - if (sliceNum === lathe_divisions) { - break; - } - - right = [Math.cos(i), 0, Math.sin(i)]; - - for (j = 0, jMax = pointList.length; j < jMax; j++) { - pos = vec3.add(vec3.multiply(right, pointList[j][0]), vec3.multiply(up, pointList[j][1])); - - if (slices[sliceNum] === undef) { - slices[sliceNum] = []; - } - - slices[sliceNum].push(pos); - } - - sliceNum++; - } - - var m = null; - - if (transform!==undef) m = (transform.getResult!==undef)?transform.getResult():transform; - - for (j = 0; j < lathe_divisions; j++) { - for (k = 0, kMax = pointList.length; k < kMax; k++) { - if (m) { - obj_in.addPoint(mat4.vec3_multiply(slices[j][k], m)); - } else { - obj_in.addPoint(slices[j][k]); - } - } - } - - obj_in.setFaceMaterial(material); - - for (k = 0; k < lathe_divisions; k++) { - for (j = 0, jMax = pointList.length - 1; j < jMax; j++) { - var pt = j + (pointList.length * k); - var pt_r = j + (pointList.length * ((k + 1) % (lathe_divisions))); - - if (vec3.equal(obj_in.points[pofs + pt], obj_in.points[pofs + pt_r])) { - obj_in.addFace([pofs + pt + 1, pofs + pt_r + 1, pofs + pt_r]); - } else if (vec3.equal(obj_in.points[pofs + pt + 1], obj_in.points[pofs + pt_r + 1])) { - obj_in.addFace([pofs + pt, pofs + pt + 1, pofs + pt_r]); - } else { - obj_in.addFace([pofs + pt, pofs + pt + 1, pofs + pt_r + 1, pofs + pt_r]); - } - } - } - - - if (uvmapper !== undef) - { - var uvm = null; - - if (uvmapper.apply !== undef) - { - uvm = uvmapper; - } - else if (uvmapper) - { - uvm = new UVMapper(uvmapper); - } - - if (uvm !== null) - { - // Calculate face normals (used for UV mapping and lighting), todo: face range+offset - obj_in.calcNormals(); - - uvm.apply(obj_in, material); - } - } - -} - -function cubicvr_planeObject(mesh, size, mat, transform, uvmapper) { - var half_size = size*0.5; - var pofs = mesh.points.length; - - mesh.setFaceMaterial(mat); - - if (transform !== undef) { - var m = (transform.getResult!==undef)?transform.getResult():transform; - mesh.addPoint([ - mat4.vec3_multiply([half_size, -half_size, 0],m), - mat4.vec3_multiply([half_size, half_size, 0],m), - mat4.vec3_multiply([-half_size, half_size, 0],m), - mat4.vec3_multiply([-half_size, -half_size, 0],m) - ]); - } - else { - mesh.addPoint([ - [half_size, -half_size, 0], - [half_size, half_size, 0], - [-half_size, half_size, 0], - [-half_size, -half_size, 0] - ]); - } - mesh.addFace([ - [pofs+0, pofs+1, pofs+2, pofs+3], //back - [pofs+3, pofs+2, pofs+1, pofs+0] //front - ]); - - if (uvmapper !== undef) - { - var uvm = null; - - if (uvmapper.apply !== undef) - { - uvm = uvmapper; - } - else if (uvmapper) - { - uvm = new UVMapper(uvmapper); - } - - if (uvm !== null) - { - // Calculate face normals (used for UV mapping and lighting), todo: face range+offset - mesh.calcNormals(); - - uvm.apply(mesh, mat); - } - } - -} //cubicvr_planeObject - -function cubicvr_boxObject(boxObj, box_size, box_mat, transform, uvmapper) { - var half_box = box_size / 2.0; - var pofs = boxObj.points.length; - - boxObj.setFaceMaterial(box_mat); - - if (transform !== undef) { - var m = (transform.getResult!==undef)?transform.getResult():transform; - boxObj.addPoint([ - mat4.vec3_multiply([half_box, -half_box, half_box], m), - mat4.vec3_multiply([half_box, half_box, half_box], m), - mat4.vec3_multiply([-half_box, half_box, half_box], m), - mat4.vec3_multiply([-half_box, -half_box, half_box], m), - mat4.vec3_multiply([half_box, -half_box, -half_box], m), - mat4.vec3_multiply([half_box, half_box, -half_box], m), - mat4.vec3_multiply([-half_box, half_box, -half_box], m), - mat4.vec3_multiply([-half_box, -half_box, -half_box], m) - ]); - } else { - boxObj.addPoint([ - [half_box, -half_box, half_box], - [half_box, half_box, half_box], - [-half_box, half_box, half_box], - [-half_box, -half_box, half_box], - [half_box, -half_box, -half_box], - [half_box, half_box, -half_box], - [-half_box, half_box, -half_box], - [-half_box, -half_box, -half_box] - ]); - -} - -boxObj.addFace([ - [pofs + 0, pofs + 1, pofs + 2, pofs + 3], - [pofs + 7, pofs + 6, pofs + 5, pofs + 4], - [pofs + 4, pofs + 5, pofs + 1, pofs + 0], - [pofs + 5, pofs + 6, pofs + 2, pofs + 1], - [pofs + 6, pofs + 7, pofs + 3, pofs + 2], - [pofs + 7, pofs + 4, pofs + 0, pofs + 3] - ]); - - if (uvmapper !== undef) - { - var uvm = null; - - if (uvmapper.apply !== undef) - { - uvm = uvmapper; - } - else if (uvmapper) - { - uvm = new UVMapper(uvmapper); - } - - if (uvm !== null) - { - // Calculate face normals (used for UV mapping and lighting), todo: face range+offset - boxObj.calcNormals(); - - uvm.apply(boxObj, box_mat); - } - } -} - -function cubicvr_torusObject(mesh, inner_radius, outer_radius, lon, lat, material, transform, uvmapper) { - var pointList = new Array(); - - var thick = outer_radius-inner_radius; - var radius = inner_radius+(thick)/2.0; - - // generate a circle on the right side (radius) of the X/Y axis, circle radius of (thick) - var step = (M_TWO_PI / lat); - var theta = 0; - for (var i = 0; i <= lat; i ++) { - pointList.push([radius + Math.cos(theta) * thick, Math.sin(theta) * thick, 0]); - theta += step; - } - - CubicVR.genLatheObject(mesh, pointList, lon, material, transform, uvmapper); -} - - -function cubicvr_coneObject(mesh, base, height, lon, material, transform, uvmapper) { - CubicVR.genLatheObject(mesh, [[0,-height/2,0],[base/2.0,-height/2,0],[0,height/2,0]], lon, material, transform, uvmapper); -} - - -function cubicvr_cylinderObject(mesh, radius, height, lon, material, transform, uvmapper) { - CubicVR.genLatheObject(mesh, [[0,-height/2,0],[radius,-height/2,0],[radius,height/2,0],[0,height/2,0]], lon, material, transform, uvmapper); -} - -function cubicvr_sphereObject(mesh, radius, lon, lat, material, transform, uvmapper) { - var pointList = new Array(); - - lat = parseInt(lat /= 2); - lon = parseInt(lon); - - // generate a half-circle on the right side of the x/y axis - var step = (M_PI / lat); - var theta = -M_HALF_PI; - for (var i = 0; i <= lat; i ++) { - pointList.push([Math.cos(theta) * radius, Math.sin(theta) * radius, 0]); - theta += step; - } - - CubicVR.genLatheObject(mesh, pointList, lon, material, transform, uvmapper); -} - -var primitives = { - - lathe: function(obj_init) { - var obj_in, material, transform, uvmapper; - var pointList, lathe_divisions; - - if (obj_init.points==undef) return null; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - lathe_divisions = (obj_init.divisions!==undef)?obj_init.divisions:24; - - cubicvr_latheObject(obj_in,obj_init.points,lathe_divisions,material,transform,uvmapper); - - return obj_in; - }, - box: function(obj_init) { - var obj_in, material, transform, uvmapper; - var size; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - size = (obj_init.size!==undef)?obj_init.size:1.0; - - cubicvr_boxObject(obj_in, size, material, transform, uvmapper); - - return obj_in; - }, - plane: function(obj_init) { - var obj_in, material, transform, uvmapper; - var size; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - size = (obj_init.size!==undef)?obj_init.size:1.0; - - cubicvr_planeObject(obj_in, size, material, transform, uvmapper); - - return obj_in; - }, - sphere: function(obj_init) { - var obj_in, material, transform, uvmapper; - var radius, lon, lat; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - radius = (obj_init.radius!==undef)?obj_init.radius:1.0; - lon = (obj_init.lon!==undef)?obj_init.lon:24; - lat = (obj_init.lat!==undef)?obj_init.lat:24; - - cubicvr_sphereObject(obj_in, radius, lon, lat, material, transform, uvmapper); - - return obj_in; - }, - torus: function(obj_init) { - var obj_in, material, transform, uvmapper; - var innerRadius, outerRadius, lon, lat; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - innerRadius = (obj_init.innerRadius!==undef)?obj_init.innerRadius:0.75; - outerRadius = (obj_init.outerRadius!==undef)?obj_init.outerRadius:1.0; - lon = (obj_init.lon!==undef)?obj_init.lon:24; - lat = (obj_init.lat!==undef)?obj_init.lat:24; - - cubicvr_torusObject(obj_in, innerRadius, outerRadius, lon, lat, material, transform, uvmapper); - - return obj_in; - }, - cone: function(obj_init) { - var obj_in, material, transform, uvmapper; - var base, height, lon; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - base = (obj_init.base!==undef)?obj_init.base:1.0; - height = (obj_init.height!==undef)?obj_init.height:1.0; - lon = (obj_init.lon!==undef)?obj_init.lon:24; - - cubicvr_coneObject(obj_in, base, height, lon, material, transform, uvmapper); - - return obj_in; - }, - cylinder: function(obj_init) { - var obj_in, material, transform, uvmapper; - var radius, height; - - obj_in = (obj_init.mesh!==undef)?obj_init.mesh:(new CubicVR.Mesh((obj_init.name!==undef)?obj_init.name:undef)); - material = (obj_init.material!==undef)?obj_init.material:(new CubicVR.Material()); - transform = (obj_init.transform!==undef)?obj_init.transform:undef; - uvmapper = (obj_init.uvmapper!==undef)?obj_init.uvmapper:undef; - - radius = (obj_init.radius!==undef)?obj_init.radius:1.0; - height = (obj_init.height!==undef)?obj_init.height:1.0; - lon = (obj_init.lon!==undef)?obj_init.lon:24; - - cubicvr_cylinderObject(obj_in, radius, height, lon, material, transform, uvmapper); - - return obj_in; - } -} - - - -function Landscape(size_in, divisions_in_w, divisions_in_h, matRef_in) { - this.doTransform = function() {}; - this.tMatrix = cubicvr_identity; - - this.parent = null; - this.position = [0, 0, 0]; - this.scale = [1, 1, 1]; - this.size = size_in; - this.divisions_w = divisions_in_w; - this.divisions_h = divisions_in_h; - this.matRef = matRef_in; - this.children = null; - - this.obj = new Mesh(); - - var i, j; - - if (this.divisions_w > this.divisions_h) { - this.size_w = size_in; - this.size_h = (size_in / this.divisions_w) * this.divisions_h; - } else if (this.divisions_h > this.divisions_w) { - this.size_w = (size_in / this.divisions_h) * this.divisions_w; - this.size_h = size_in; - } else { - this.size_w = size_in; - this.size_h = size_in; - } - - for (j = -(this.size_h / 2.0); j < (this.size_h / 2.0); j += (this.size_h / this.divisions_h)) { - for (i = -(this.size_w / 2.0); i < (this.size_w / 2.0); i += (this.size_w / this.divisions_w)) { - this.obj.addPoint([i + ((this.size_w / (this.divisions_w)) / 2.0), 0, j + ((this.size_h / (this.divisions_h)) / 2.0)]); - } - } - - var k, l; - - this.obj.setFaceMaterial(this.matRef); - - for (l = 0; l < this.divisions_h - 1; l++) { - for (k = 0; k < this.divisions_w - 1; k++) { - this.obj.addFace([(k) + ((l + 1) * this.divisions_w), - (k + 1) + ((l) * this.divisions_w), - (k) + ((l) * this.divisions_w)]); - - this.obj.addFace([(k) + ((l + 1) * this.divisions_w), - (k + 1) + ((l + 1) * this.divisions_w), - (k + 1) + ((l) * this.divisions_w)]); - } - } -} - -Landscape.prototype.getMesh = function() { - return this.obj; -} - -Landscape.prototype.setIndexedHeight = function(ipos, jpos, val) { - obj.points[(ipos) + (jpos * this.divisions_w)][1] = val; -} - -Landscape.prototype.mapGen = function(w_func, ipos, jpos, ilen, jlen) { - var pt; - - if (ipos!==undef && jpos !==undef && ilen !==undef && jlen!==undef) { - if (ipos>=this.divisions_w) return; - if (jpos>=this.divisions_h) return; - if (ipos+ilen>=this.divisions_w) ilen = this.divisions_w-1-ipos; - if (jpos+jlen>=this.divisions_h) jlen = this.divisions_h-1-jpos; - if (ilen<=0 || jlen<=0) return; - - for (var i = ipos, imax = ipos+ilen; i < imax; i++) { - for (var j = jpos, jmax = jpos+jlen; j < jmax; j++) { - pt = this.obj.points[(i) + (j * this.divisions_w)]; - - pt[1] = w_func(pt[0],pt[2]); - } - } - } else { - for (var x = 0, xmax = this.obj.points.length; x < xmax; x++) { - pt = this.obj.points[x]; - - pt[1] = w_func(pt[0],pt[2]); - } - } -} - - -Landscape.prototype.getFaceAt = function(x, z) { - if (typeof(x) === 'object') { - return this.getFaceAt(x[0], x[2]); - } - - var ofs_w = (this.size_w / 2.0) - ((this.size_w / (this.divisions_w)) / 2.0); - var ofs_h = (this.size_h / 2.0) - ((this.size_h / (this.divisions_h)) / 2.0); - - var i = parseInt(Math.floor(((x + ofs_w) / this.size_w) * (this.divisions_w)), 10); - var j = parseInt(Math.floor(((z + ofs_h) / this.size_h) * (this.divisions_h)), 10); - - if (i < 0) { - return -1; - } - if (i >= this.divisions_w - 1) { - return -1; - } - if (j < 0) { - return -1; - } - if (j >= this.divisions_h - 1) { - return -1; - } - - var faceNum1 = parseInt(i + (j * (this.divisions_w - 1)), 10) * 2; - var faceNum2 = parseInt(faceNum1 + 1, 10); - - var testPt = this.obj.points[this.obj.faces[faceNum1].points[0]]; - - var slope = Math.abs(z - testPt[2]) / Math.abs(x - testPt[0]); - - if (slope >= 1.0) { - return (faceNum1); - } else { - return (faceNum2); - } -}; - - -/* - cvrFloat Landscape::getHeightValue(XYZ &pt) - { - Face *tmpFace; - XYZ *tmpPoint; - - int faceNum = getFaceAt(pt); - - if (faceNum === -1) return 0; - - tmpFace = obj->faces[faceNum]; - tmpPoint = obj->points[obj->faces[faceNum]->pointref[0]]; - - tmpFace->calcFaceNormal(); - - cvrFloat na = tmpFace->face_normal.x; - cvrFloat nb = tmpFace->face_normal.y; - cvrFloat nc = tmpFace->face_normal.z; - - cvrFloat d = -na * tmpPoint->x - nb * tmpPoint->y - nc * tmpPoint->z; - - return ((na * pt.x + nc * pt.z+d)/-nb)+getPosition().y; - }; - */ - -Landscape.prototype.getHeightValue = function(x, z) { - - if (typeof(x) === 'object') { - return this.getHeightValue(x[0], x[2]); - } - - var tmpFace; - var tmpPoint; - - var faceNum = this.getFaceAt(x, z); - - if (faceNum === -1) { - return 0; - } - - tmpFace = this.obj.faces[faceNum]; - tmpPoint = this.obj.points[this.obj.faces[faceNum].points[0]]; - - var tmpNorm = triangle.normal(this.obj.points[this.obj.faces[faceNum].points[0]], this.obj.points[this.obj.faces[faceNum].points[1]], this.obj.points[this.obj.faces[faceNum].points[2]]); - - var na = tmpNorm[0]; - var nb = tmpNorm[1]; - var nc = tmpNorm[2]; - - var d = -(na * tmpPoint[0]) - (nb * tmpPoint[1]) - (nc * tmpPoint[2]); - - return (((na * x) + (nc * z) + d) / (-nb)); // add height ofs here -}; - - -Landscape.prototype.orient = function(x, z, width, length, heading, center) { - if (center === undef) { - center = 0; - } - - var xpos, zpos; - var xrot, zrot; - var heightsample = []; - var xyzTmp; - - var halfw = width / 2.0; - var halfl = length / 2.0; - - var mag = Math.sqrt(halfl * halfl + halfw * halfw); - var ang = Math.atan2(halfl, halfw); - - heading *= (M_PI / 180.0); - - xpos = x + (Math.sin(heading) * center); - zpos = z + (Math.cos(heading) * center); - - heightsample[0] = this.getHeightValue([xpos + mag * Math.cos(-ang - M_HALF_PI + heading), 0, zpos + mag * -Math.sin(-ang - M_HALF_PI + heading)]); - heightsample[1] = this.getHeightValue([xpos + mag * Math.cos(ang - M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(ang - M_HALF_PI + heading))]); - heightsample[2] = this.getHeightValue([xpos + mag * Math.cos(-ang + M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(-ang + M_HALF_PI + heading))]); - heightsample[3] = this.getHeightValue([xpos + mag * Math.cos(ang + M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(ang + M_HALF_PI + heading))]); - - xrot = -Math.atan2((heightsample[1] - heightsample[2]), width); - zrot = -Math.atan2((heightsample[0] - heightsample[1]), length); - - xrot += -Math.atan2((heightsample[0] - heightsample[3]), width); - zrot += -Math.atan2((heightsample[3] - heightsample[2]), length); - - xrot /= 2.0; // average angles - zrot /= 2.0; - - - return [[x, ((heightsample[2] + heightsample[3] + heightsample[1] + heightsample[0])) / 4.0, z], // - [xrot * (180.0 / M_PI), heading, zrot * (180.0 / M_PI)]]; -}; - -var scene_object_uuid = 0; - -function SceneObject(obj, name) { - var obj_init = null; - - if (obj!==undef && obj!==null) - { - if (obj.compile) - { - obj_init = null; - } else { - obj_init = obj; - } - } - - if (obj_init) { - this.position = (obj_init.position===undef)?[0, 0, 0]:obj_init.position; - this.rotation = (obj_init.rotation===undef)?[0, 0, 0]:obj_init.rotation; - this.scale = (obj_init.scale===undef)?[1, 1, 1]:obj_init.scale; - - this.motion = (obj_init.motion===undef)?null:obj_init.motion; - this.obj = (obj_init.mesh===undef)?((obj !== undef && obj_init.faces !== undef) ? obj : null):obj_init.mesh; - this.name = (obj_init.name===undef)?((name !== undef) ? name : null):obj_init.name; - } else { - this.position = [0, 0, 0]; - this.rotation = [0, 0, 0]; - this.scale = [1, 1, 1]; - - this.motion = null; - this.obj = obj; - this.name = name; - } - - this.children = null; - this.parent = null; - - this.drawn_this_frame = false; - - this.lposition = [0, 0, 0]; - this.lrotation = [0, 0, 0]; - this.lscale = [0, 0, 0]; - - this.trans = new Transform(); - - this.tMatrix = this.trans.getResult(); - - this.dirty = true; - - this.aabb = []; - - this.id = -1; - - this.octree_leaves = []; - this.octree_common_root = null; - this.octree_aabb = [[0,0,0],[0,0,0]]; - AABB_reset(this.octree_aabb, [0,0,0]); - this.ignore_octree = false; - this.visible = true; - this.culled = true; - this.was_culled = true; - - this.dynamic_lights = []; - this.static_lights = []; -} - -SceneObject.prototype.doTransform = function(mat) { - if (!vec3.equal(this.lposition, this.position) || !vec3.equal(this.lrotation, this.rotation) || !vec3.equal(this.lscale, this.scale) || (mat !== undef)) { - - this.trans.clearStack(); - - if ((mat !== undef)) { - this.trans.pushMatrix(mat); - } - - this.trans.translate(this.position); - - if (! (this.rotation[0] === 0 && this.rotation[1] === 0 && this.rotation[2] === 0)) { - this.trans.pushMatrix(); - this.trans.rotate(this.rotation); - } - - if (! (this.scale[0] === 1 && this.scale[1] === 1 && this.scale[2] === 1)) { - this.trans.pushMatrix(); - this.trans.scale(this.scale); - } - - - - - this.tMatrix = this.trans.getResult(); - - this.lposition[0] = this.position[0]; - this.lposition[1] = this.position[1]; - this.lposition[2] = this.position[2]; - this.lrotation[0] = this.rotation[0]; - this.lrotation[1] = this.rotation[1]; - this.lrotation[2] = this.rotation[2]; - this.lscale[0] = this.scale[0]; - this.lscale[1] = this.scale[1]; - this.lscale[2] = this.scale[2]; - this.dirty = true; - } -}; - -SceneObject.prototype.adjust_octree = function() { - var aabb = this.getAABB(); - var taabb = this.octree_aabb; - var px0 = aabb[0][0]; - var py0 = aabb[0][1]; - var pz0 = aabb[0][2]; - var px1 = aabb[1][0]; - var py1 = aabb[1][1]; - var pz1 = aabb[1][2]; - var tx0 = taabb[0][0]; - var ty0 = taabb[0][1]; - var tz0 = taabb[0][2]; - var tx1 = taabb[1][0]; - var ty1 = taabb[1][1]; - var tz1 = taabb[1][2]; - if (this.octree_leaves.length > 0 && (px0 < tx0 || py0 < ty0 || pz0 < tz0 || px1 > tx1 || py1 > ty1 || pz1 > tz1)) { - for (var i = 0; i < this.octree_leaves.length; ++i) { - this.octree_leaves[i].remove(this); - } //for - this.octree_leaves = []; - this.static_lights = []; - var common_root = this.octree_common_root; - this.octree_common_root = null; - if (common_root !== null) { - - while (true) { - if (!common_root.contains_point(aabb[0]) || !common_root.contains_point(aabb[1])) { - if (common_root._root !== undef && common_root._root !== null) { - common_root = common_root._root; - } else { - break; - } //if - } else { - break; - } //if - } //while - AABB_reset(this.octree_aabb, this.position); - common_root.insert(this); - } //if - } //if -}; //SceneObject::adjust_octree -SceneObject.prototype.bindChild = function(childSceneObj) { - if (this.children === null) { - this.children = []; - } - - childSceneObj.parent = this; - this.children.push(childSceneObj); -}; - - -SceneObject.prototype.control = function(controllerId, motionId, value) { - if (controllerId === enums.motion.POS) { - this.position[motionId] = value; - } else if (controllerId === enums.motion.SCL) { - this.scale[motionId] = value; - } else if (controllerId === enums.motion.ROT) { - this.rotation[motionId] = value; - } - - /* - switch (controllerId) { - case enums.motion.POS: - this.position[motionId] = value; - break; - case enums.motion.SCL: - this.scale[motionId] = value; - break; - case enums.motion.ROT: - this.rotation[motionId] = value; - break; - } - */ -}; - -SceneObject.prototype.getAABB = function() { - if (this.dirty) { - var p = new Array(8); - - this.doTransform(); - - var aabbMin; - var aabbMax; - - - - if (this.obj !== null) - { - if (this.obj.bb === null) - { - this.aabb = [vec3.add([-1,-1,-1],this.position),vec3.add([1,1,1],this.position)]; - return this.aabb; - } - - aabbMin = this.obj.bb[0]; - aabbMax = this.obj.bb[1]; - } - - if (this.obj === null || aabbMin === undef || aabbMax === undef) - { - // aabbMin=[-1,-1,-1]; - // aabbMax=[1,1,1]; - // - // if (this.obj.bb.length===0) - // { - this.aabb = [vec3.add([-1,-1,-1],this.position),vec3.add([1,1,1],this.position)]; - return this.aabb; - // } - } - - /* - if (this.scale[0] !== 1 || this.scale[1] !== 1 || this.scale[2] !== 1) { - aabbMin[0] *= this.scale[0]; - aabbMin[1] *= this.scale[1]; - aabbMin[2] *= this.scale[2]; - aabbMax[0] *= this.scale[0]; - aabbMax[1] *= this.scale[1]; - aabbMax[2] *= this.scale[2]; - } - */ - - var obj_aabb = aabbMin; - var obj_bounds = vec3.subtract(aabbMax, aabbMin); - - p[0] = [obj_aabb[0], obj_aabb[1], obj_aabb[2]]; - p[1] = [obj_aabb[0], obj_aabb[1], obj_aabb[2] + obj_bounds[2]]; - p[2] = [obj_aabb[0] + obj_bounds[0], obj_aabb[1], obj_aabb[2]]; - p[3] = [obj_aabb[0] + obj_bounds[0], obj_aabb[1], obj_aabb[2] + obj_bounds[2]]; - p[4] = [obj_aabb[0], obj_aabb[1] + obj_bounds[1], obj_aabb[2]]; - p[5] = [obj_aabb[0], obj_aabb[1] + obj_bounds[1], obj_aabb[2] + obj_bounds[2]]; - p[6] = [obj_aabb[0] + obj_bounds[0], obj_aabb[1] + obj_bounds[1], obj_aabb[2]]; - p[7] = [obj_aabb[0] + obj_bounds[0], obj_aabb[1] + obj_bounds[1], obj_aabb[2] + obj_bounds[2]]; - - var aabbTest; - - aabbTest = mat4.vec3_multiply(p[0], this.tMatrix); - - aabbMin = [aabbTest[0], aabbTest[1], aabbTest[2]]; - aabbMax = [aabbTest[0], aabbTest[1], aabbTest[2]]; - - for (var i = 1; i < 8; ++i) { - aabbTest = mat4.vec3_multiply(p[i], this.tMatrix); - - if (aabbMin[0] > aabbTest[0]) { - aabbMin[0] = aabbTest[0]; - } - if (aabbMin[1] > aabbTest[1]) { - aabbMin[1] = aabbTest[1]; - } - if (aabbMin[2] > aabbTest[2]) { - aabbMin[2] = aabbTest[2]; - } - - if (aabbMax[0] < aabbTest[0]) { - aabbMax[0] = aabbTest[0]; - } - if (aabbMax[1] < aabbTest[1]) { - aabbMax[1] = aabbTest[1]; - } - if (aabbMax[2] < aabbTest[2]) { - aabbMax[2] = aabbTest[2]; - } - } - - this.aabb[0] = aabbMin; - this.aabb[1] = aabbMax; - - this.dirty = false; - } - - return this.aabb; -}; - -var cubicvr_env_range = function(v, lo, hi) { - var v2, i = 0, - r; - - r = hi - lo; - - if (r === 0.0) { - return [lo, 0]; - } - - v2 = v - r * Math.floor((v - lo) / r); - - i = -parseInt((v2 - v) / r + (v2 > v ? 0.5 : -0.5), 10); - - return [v2, i]; -}; - -var cubicvr_env_hermite = function(t) { - var h1, h2, h3, h4; - var t2, t3; - - t2 = t * t; - t3 = t * t2; - - h2 = 3.0 * t2 - t3 - t3; - h1 = 1.0 - h2; - h4 = t3 - t2; - h3 = h4 - t2 + t; - - return [h1, h2, h3, h4]; -}; - -var cubicvr_env_bezier = function(x0, x1, x2, x3, t) { - var a, b, c, t2, t3; - - t2 = t * t; - t3 = t2 * t; - - c = 3.0 * (x1 - x0); - b = 3.0 * (x2 - x1) - c; - a = x3 - x0 - c - b; - - return a * t3 + b * t2 + c * t + x0; -}; - - - -var cubicvr_env_bez2_time = function(x0, x1, x2, x3, time, t0, t1) { - - var v, t; - - t = t0 + (t1 - t0) * 0.5; - v = cubicvr_env_bezier(x0, x1, x2, x3, t); - if (Math.abs(time - v) > 0.0001) { - if (v > time) { - t1 = t; - } else { - t0 = t; - } - return cubicvr_env_bez2_time(x0, x1, x2, x3, time, t0, t1); - } else { - return t; - } -}; - - - -var cubicvr_env_bez2 = function(key0, key1, time) -{ - var x, y, t, t0 = 0.0, t1 = 1.0; - - if ( key0.shape === enums.envelope.shape.BEZ2 ) { - - x = key0.time + key0.param[ 2 ]; - } else { - x = key0.time + ( key1.time - key0.time ) / 3.0; - } - - t = cubicvr_env_bez2_time( key0.time, x, key1.time + key1.param[ 0 ], key1.time, time, t0, t1 ); - - if ( key0.shape === enums.envelope.shape.BEZ2 ){ - y = key0.value + key0.param[ 3 ]; - } - else { - y = key0.value + key0.param[ 1 ] / 3.0; - } - - return cubicvr_env_bezier( key0.value, y, key1.param[ 1 ] + key1.value, key1.value, t ); -} - - -var cubicvr_env_outgoing = function(key0, key1) { - var a, b, d, t, out; - - if (key0.shape === enums.envelope.shape.TCB) { - a = (1.0 - key0.tension) * (1.0 + key0.continuity) * (1.0 + key0.bias); - b = (1.0 - key0.tension) * (1.0 - key0.continuity) * (1.0 - key0.bias); - d = key1.value - key0.value; - - if (key0.prev) { - t = (key1.time - key0.time) / (key1.time - (key0.prev).time); - out = t * (a * (key0.value - (key0.prev).value) + b * d); - } else { - out = b * d; - } - } else if (key0.shape === enums.envelope.shape.LINE) { - d = key1.value - key0.value; - if (key0.prev) { - t = (key1.time - key0.time) / (key1.time - (key0.prev).time); - out = t * (key0.value - (key0.prev).value + d); - } else { - out = d; - } - } else if ((key0.shape === enums.envelope.shape.BEZI)||(key0.shape === enums.envelope.shape.HERM)) { - out = key0.param[1]; - if (key0.prev) { - out *= (key1.time - key0.time) / (key1.time - (key0.prev).time); - } - } else if (key0.shape === enums.envelope.shape.BEZ2) { - out = key0.param[3] * (key1.time - key0.time); - if (Math.abs(key0.param[2]) > 1e-5) { - out /= key0.param[2]; - } else { - out *= 1e5; - } - } else if (key0.shape === enums.envelope.shape.STEP) { - out = 0.0; - } else { - out = 0.0; - } - - return out; -}; - - - -var cubicvr_env_incoming = function(key0, key1) { - var a, b, d, t, inval; - - if (key1.shape === enums.envelope.shape.LINE) { - d = key1.value - key0.value; - if (key1.next) { - t = (key1.time - key0.time) / ((key1.next).time - key0.time); - inval = t * ((key1.next).value - key1.value + d); - } else { - inval = d; - } - } else if (key1.shape === enums.envelope.shape.TCB) { - a = (1.0 - key1.tension) * (1.0 - key1.continuity) * (1.0 + key1.bias); - b = (1.0 - key1.tension) * (1.0 + key1.continuity) * (1.0 - key1.bias); - d = key1.value - key0.value; - - if (key1.next) { - t = (key1.time - key0.time) / ((key1.next).time - key0.time); - inval = t * (b * ((key1.next).value - key1.value) + a * d); - } else { - inval = a * d; - } - } else if ((key1.shape === enums.envelope.shape.HERM) || (key1.shape === enums.envelope.shape.BEZI)) { - inval = key1.param[0]; - if (key1.next) { - inval *= (key1.time - key0.time) / ((key1.next).time - key0.time); - } - } else if (key1.shape === enums.envelope.shape.BEZ2) { - inval = key1.param[1] * (key1.time - key0.time); - if (Math.abs(key1.param[0]) > 1e-5) { - inval /= key1.param[0]; - } else { - inval *= 1e5; - } - } else if (key1.shape === enums.envelope.shape.STEP) { - inval = 0.0; - } else { - inval = 0.0; - } - - return inval; -}; - - -function EnvelopeKey() { - this.value = 0; - this.time = 0; - this.shape = enums.envelope.shape.TCB; - this.tension = 0; - this.continuity = 0; - this.bias = 0; - this.prev = null; - this.next = null; - - this.param = [0,0,0,0]; -} - - -function Envelope(obj_init) { - this.nKeys = 0; - this.keys = null; - this.firstKey = null; - this.lastKey = null; - - if (obj_init) - { - this.in_behavior = obj_init.in_behavior?obj_init.in_behavior:enums.envelope.behavior.CONSTANT; - this.out_behavior = obj_init.out_behavior?obj_init.out_behavior:enums.envelope.behavior.CONSTANT; - } - else - { - this.in_behavior = enums.envelope.behavior.CONSTANT; - this.out_behavior = enums.envelope.behavior.CONSTANT; - } -} - -Envelope.prototype.setBehavior = function(in_b, out_b) { - this.in_behavior = in_b; - this.out_behavior = out_b; -}; - - -Envelope.prototype.empty = function() { - return (this.nKeys === 0); -}; - - -Envelope.prototype.addKey = function(time, value, key_init) { - var tempKey; - - var obj = (typeof(time)=='object')?time:key_init; - - if (!value) value = 0; - if (!time) time = 0; - - if (obj) { - obj = time; - time = obj.time; - - tempKey = this.insertKey(time); - - tempKey.value = obj.value?obj.value:value; - tempKey.time = obj.time?obj.time:time;; - tempKey.shape = obj.shape?obj.shape:enums.envelope.shape.TCB; - tempKey.tension = obj.tension?obj.tension:0; - tempKey.continuity = obj.continuity?obj.continuity:0; - tempKey.bias = obj.bias?obj.bias:0; - tempKey.param = obj.param?obj.param:[0,0,0,0]; - - } else { - tempKey = this.insertKey(time); - tempKey.value = value; - } - - - return tempKey; -}; - - -Envelope.prototype.insertKey = function(time) { - var tempKey = new EnvelopeKey(); - - tempKey.time = time; - if (!this.nKeys) { - this.keys = tempKey; - this.firstKey = tempKey; - this.lastKey = tempKey; - this.nKeys++; - - return tempKey; - } - - var k1 = this.keys; - - while (k1) { - // update first/last key - if (this.firstKey.time > time) { - this.firstKey = tempKey; - } else if (this.lastKey.time < time) { - this.lastKey = tempKey; - } - - if (k1.time > tempKey.time) { - tempKey.prev = k1.prev; - if (tempKey.prev) { - tempKey.prev.next = tempKey; - } - - tempKey.next = k1; - tempKey.next.prev = tempKey; - - this.nKeys++; - - return tempKey; - } else if (!k1.next) { - tempKey.prev = k1; - k1.next = tempKey; - - this.nKeys++; - - return tempKey; - } - - k1 = k1.next; - } - - return null; // you should not be here, time and space has imploded -}; - -Envelope.prototype.evaluate = function(time) { - var key0, key1, skey, ekey; - var t, h1, h2, h3, h4, inval, out, offset = 0.0; - var noff; - - /* if there's no key, the value is 0 */ - if (this.nKeys === 0) { - return 0.0; - } - - /* if there's only one key, the value is constant */ - if (this.nKeys === 1) { - return (this.keys).value; - } - - /* find the first and last keys */ - skey = this.firstKey; - ekey = this.lastKey; - - var tmp, behavior; - - /* use pre-behavior if time is before first key time */ - if (time < skey.time) { - behavior = this.in_behavior; - - if (behavior === enums.envelope.behavior.RESET) { - return 0.0; - } else if (behavior === enums.envelope.behavior.CONSTANT) { - return skey.value; - } else if (behavior === enums.envelope.behavior.REPEAT) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - } else if (behavior === enums.envelope.behavior.OCILLATE) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - - if (noff % 2) { - time = ekey.time - skey.time - time; - } - } else if (behavior === enums.envelope.behavior.OFFSET) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - offset = noff * (ekey.value - skey.value); - } else if (behavior === enums.envelope.behavior.LINEAR) { - out = cubicvr_env_outgoing(skey, skey.next) / (skey.next.time - skey.time); - return out * (time - skey.time) + skey.value; - } - - /* - switch (this.in_behavior) { - case enums.envelope.behavior.RESET: - return 0.0; - - case enums.envelope.behavior.CONSTANT: - return skey.value; - - case enums.envelope.behavior.REPEAT: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - break; - - case enums.envelope.behavior.OSCILLATE: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - - if (noff % 2) { - time = ekey.time - skey.time - time; - } - break; - - case enums.envelope.behavior.OFFSET: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - offset = noff * (ekey.value - skey.value); - break; - - case enums.envelope.behavior.LINEAR: - out = cubicvr_env_outgoing(skey, skey.next) / (skey.next.time - skey.time); - return out * (time - skey.time) + skey.value; - } - */ - } - - /* use post-behavior if time is after last key time */ - else if (time > ekey.time) { - behavior = this.out_behavior; - - if (behavior === enums.envelope.behavior.RESET) { - return 0.0; - } else if (behavior === enums.envelope.behavior.CONSTANT) { - return ekey.value; - } else if (behavior === enums.envelope.behavior.REPEAT) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - } else if (behavior === enums.envelope.behavior.OCILLATE) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - - if (noff % 2) { - time = ekey.time - skey.time - time; - } - } else if (behavior === enums.envelope.behavior.OFFSET) { - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - offset = noff * (ekey.value - skey.value); - } else if (behavior === enums.envelope.behavior.LINEAR) { - inval = cubicvr_env_incoming(ekey.prev, ekey) / (ekey.time - ekey.prev.time); - return inval * (time - ekey.time) + ekey.value; - } - /* - switch (this.out_behavior) { - case enums.envelope.behavior.RESET: - return 0.0; - - case enums.envelope.behavior.CONSTANT: - return ekey.value; - - case enums.envelope.behavior.REPEAT: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - break; - - case enums.envelope.behavior.OSCILLATE: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - - if (noff % 2) { - time = ekey.time - skey.time - time; - } - break; - - case enums.envelope.behavior.OFFSET: - tmp = cubicvr_env_range(time, skey.time, ekey.time); - time = tmp[0]; - noff = tmp[1]; - offset = noff * (ekey.value - skey.value); - break; - - case enums.envelope.behavior.LINEAR: - inval = cubicvr_env_incoming(ekey.prev, ekey) / (ekey.time - ekey.prev.time); - return inval * (time - ekey.time) + ekey.value; - } - */ - } - - // get the endpoints of the interval being evaluated - key0 = this.keys; - while (time > key0.next.time) { - key0 = key0.next; - } - key1 = key0.next; - - // check for singularities first - if (time === key0.time) { - return key0.value + offset; - } else if (time === key1.time) { - return key1.value + offset; - } - - // get interval length, time in [0, 1] - t = (time - key0.time) / (key1.time - key0.time); - - // interpolate - /* - switch (key1.shape) { - case enums.envelope.shape.TCB: - case enums.envelope.shape.BEZI: - case enums.envelope.shape.HERM: - out = cubicvr_env_outgoing(key0, key1); - inval = cubicvr_env_incoming(key0, key1); - var h = cubicvr_env_hermite(t); - return h[0] * key0.value + h[1] * key1.value + h[2] * out + h[3] * inval + offset; - - case enums.envelope.shape.BEZ2: - return cubicvr_env_bez2_time(key0, key1, time) + offset; - - case enums.envelope.shape.LINE: - return key0.value + t * (key1.value - key0.value) + offset; - - case enums.envelope.shape.STEP: - return key0.value + offset; - - default: - return offset; - } - */ - - var keyShape = key1.shape; - - if (keyShape === enums.envelope.shape.TCB || keyShape === enums.envelope.shape.BEZI || keyShape === enums.envelope.shape.HERM) { - out = cubicvr_env_outgoing(key0, key1); - inval = cubicvr_env_incoming(key0, key1); - var h = cubicvr_env_hermite(t); - return h[0] * key0.value + h[1] * key1.value + h[2] * out + h[3] * inval + offset; - } else if (keyShape === enums.envelope.shape.BEZ2) { - return cubicvr_env_bez2(key0, key1, time) + offset; - } else if (keyShape === enums.envelope.shape.LINE) { - return key0.value + t * (key1.value - key0.value) + offset; - } else if (keyShape === enums.envelope.shape.STEP) { - return key0.value + offset; - } else { - return offset; - } -}; - -function Motion(env_init, key_init) { - this.env_init = env_init; - this.key_init = key_init; - this.controllers = []; - this.yzflip = false; -// this.rscale = 1; -} - -Motion.prototype.envelope = function(controllerId, motionId) { - if (this.controllers[controllerId] === undef) { - this.controllers[controllerId] = []; - } - if (this.controllers[controllerId][motionId] === undef) { - this.controllers[controllerId][motionId] = new Envelope(this.env_init); - } - - return this.controllers[controllerId][motionId]; -}; - -Motion.prototype.evaluate = function(index) { - var retArr = []; - - for (var i in this.controllers) { - if (this.controllers.hasOwnProperty(i)) { - retArr[i] = []; - - for (var j in this.controllers[i]) { - if (this.controllers[i].hasOwnProperty(j)) { - retArr[i][j] = this.controllers[i][j].evaluate(index); - } - } - } - } - - return retArr; -}; - -Motion.prototype.apply = function(index, target) { - for (var i in this.controllers) { - if (this.controllers.hasOwnProperty(i)) { - var ic = parseInt(i, 10); - - /* Special case quaternion fix for ZY->YZ rotation envelopes */ - if (this.yzflip && ic === enums.motion.ROT) // assume channel 0,1,2 - { - if (!this.q) { - this.q = new Quaternion(); - } - var q = this.q; - - var x = this.controllers[i][0].evaluate(index); - var y = this.controllers[i][1].evaluate(index); - var z = this.controllers[i][2].evaluate(index); - - //q.fromEuler(x*this.rscale, z*this.rscale, -y*this.rscale); - q.fromEuler(x, z, -y); - - - var qr = q.toEuler(); - - target.control(ic, 0, qr[0]); - target.control(ic, 1, qr[1]); - target.control(ic, 2, qr[2]); - } - else { - for (var j in this.controllers[i]) { - if (this.controllers[i].hasOwnProperty(j)) { - target.control(ic, parseInt(j, 10), this.controllers[i][j].evaluate(index)); - } - } - } - } - } -}; - - -Motion.prototype.setKey = function(controllerId, motionId, index, value, key_init) { - var ev = this.envelope(controllerId, motionId); - return ev.addKey(index, value, key_init?key_init:this.key_init); -}; - -Motion.prototype.setArray = function(controllerId, index, value, key_init) { - var tmpKeys = []; - - for (var i in value) { - if (value.hasOwnProperty(i)) { - var ev = this.envelope(controllerId, i); - tmpKeys[i] = ev.addKey(index, value[i], key_init?key_init:this.key_init); - } - } - - return tmpKeys; -}; - - -Motion.prototype.setBehavior = function(controllerId, motionId, behavior_in, behavior_out) { - var ev = this.envelope(controllerId, motionId); - ev.setBehavior(behavior_in, behavior_out); -}; - - -Motion.prototype.setBehaviorArray = function(controllerId, behavior_in, behavior_out) { - for (var motionId in this.controllers[controllerId]) { - if (this.controllers[controllerId].hasOwnProperty(motionId)) { - var ev = this.envelope(controllerId, motionId); - ev.setBehavior(behavior_in, behavior_out); - } - } -}; - - - -function cubicvr_nodeToMotion(node, controllerId, motion) { - var c = []; - c[0] = node.getElementsByTagName("x"); - c[1] = node.getElementsByTagName("y"); - c[2] = node.getElementsByTagName("z"); - c[3] = node.getElementsByTagName("fov"); - - var etime, evalue, ein, eout, etcb; - - for (var k in c) { - if (c.hasOwnProperty(k)) { - if (c[k] !== undef) { - if (c[k].length) { - etime = c[k][0].getElementsByTagName("time"); - evalue = c[k][0].getElementsByTagName("value"); - ein = c[k][0].getElementsByTagName("in"); - eout = c[k][0].getElementsByTagName("out"); - etcb = c[k][0].getElementsByTagName("tcb"); - - var time = null, - value = null, - tcb = null; - - var intype = null, - outtype = null; - - if (ein.length) { - intype = util.collectTextNode(ein[0]); - } - - if (eout.length) { - outtype = util.collectTextNode(eout[0]); - } - - if (etime.length) { - time = util.floatDelimArray(util.collectTextNode(etime[0]), " "); - } - - if (evalue.length) { - value = util.floatDelimArray(util.collectTextNode(evalue[0]), " "); - } - - if (etcb.length) { - tcb = util.floatDelimArray(util.collectTextNode(etcb[0]), " "); - } - - - if (time !== null && value !== null) { - for (var i = 0, iMax = time.length; i < iMax; i++) { - var mkey = motion.setKey(controllerId, k, time[i], value[i]); - - if (tcb) { - mkey.tension = tcb[i * 3]; - mkey.continuity = tcb[i * 3 + 1]; - mkey.bias = tcb[i * 3 + 2]; - } - } - } - - var in_beh = enums.envelope.behavior.CONSTANT; - var out_beh = enums.envelope.behavior.CONSTANT; - - if (intype) { - switch (intype) { - case "reset": - in_beh = enums.envelope.behavior.RESET; - break; - case "constant": - in_beh = enums.envelope.behavior.CONSTANT; - break; - case "repeat": - in_beh = enums.envelope.behavior.REPEAT; - break; - case "oscillate": - in_beh = enums.envelope.behavior.OSCILLATE; - break; - case "offset": - in_beh = enums.envelope.behavior.OFFSET; - break; - case "linear": - in_beh = enums.envelope.behavior.LINEAR; - break; - } - } - - if (outtype) { - switch (outtype) { - case "reset": - out_beh = enums.envelope.behavior.RESET; - break; - case "constant": - out_beh = enums.envelope.behavior.CONSTANT; - break; - case "repeat": - out_beh = enums.envelope.behavior.REPEAT; - break; - case "oscillate": - out_beh = enums.envelope.behavior.OSCILLATE; - break; - case "offset": - out_beh = enums.envelope.behavior.OFFSET; - break; - case "linear": - out_beh = enums.envelope.behavior.LINEAR; - break; - } - } - - motion.setBehavior(controllerId, k, in_beh, out_beh); - } - } - } - } -} - - -function cubicvr_isMotion(node) { - if (node === null) { - return false; - } - - return (node.getElementsByTagName("x").length || node.getElementsByTagName("y").length || node.getElementsByTagName("z").length || node.getElementsByTagName("fov").length); -} - -/*********************************************** - * Plane - ***********************************************/ - -function Plane() { - this.a = 0; - this.b = 0; - this.c = 0; - this.d = 0; -} //Plane::Constructor -Plane.prototype.classify_point = function(pt) { - var dist = (this.a * pt[0]) + (this.b * pt[1]) + (this.c * pt[2]) + (this.d); - if (dist < 0) { - return -1; - } - if (dist > 0) { - return 1; - } - return 0; -}; //Plane::classify_point -Plane.prototype.normalize = function() { - var mag = Math.sqrt(this.a * this.a + this.b * this.b + this.c * this.c); - this.a = this.a / mag; - this.b = this.b / mag; - this.c = this.c / mag; - this.d = this.d / mag; -}; //Plane::normalize -Plane.prototype.toString = function() { - return "[Plane " + this.a + ", " + this.b + ", " + this.c + ", " + this.d + "]"; -}; //Plane::toString -/*********************************************** - * Sphere - ***********************************************/ - -function Sphere(position, radius) { - this.position = position; - if (this.position === undef) { - this.position = [0, 0, 0]; - } - this.radius = radius; -} //Sphere::Constructor -Sphere.prototype.intersects = function(other_sphere) { - var diff = vec3.subtract(this.position, other_sphere.position); - var mag = Math.sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); - var sum_radii = this.radius + other_sphere.radius; - if (mag * mag < sum_radii * sum_radii) { - return true; - } - return false; -}; //Sphere::intersects - -function OctreeWorkerProxy(size, depth) { - var that = this; - this.size = size; - this.depth = depth; - this.worker = new CubicVR_Worker({ - message: function(e) { - console.log('Octree Worker Message:', e); - }, - error: function(e) { - console.log('Octree Worker Error:', e); - }, - type: 'octree'}); - this.worker.start(); - - this.init = function(scene) { - that.scene = scene; - that.worker.init({ - size: that.size, - max_depth: that.depth, - camera: scene.camera - }); - }; //init - this.insert = function(node) { - that.worker.send({message:'insert', node:node}); - }; //insert - this.draw_on_map = function() { - return; - }; //draw_on_map - this.reset_node_visibility = function() { - return; - }; //reset_node_visibility - this.get_frustum_hits = function() { - }; //get_frustum_hits -} //OctreeWorkerProxy - -function Octree(size, max_depth, root, position, child_index) { - this._children = []; - this._dirty = false; - this._children[0] = null; - this._children[1] = null; - this._children[2] = null; - this._children[3] = null; - this._children[4] = null; - this._children[5] = null; - this._children[6] = null; - this._children[7] = null; - - if (child_index === undef) { - this._child_index = -1; - } else { - this._child_index = child_index; - } - - if (size === undef) { - this._size = 0; - } else { - this._size = size; - } - - if (max_depth === undef) { - this._max_depth = 0; - } else { - this._max_depth = max_depth; - } - - if (root === undef) { - this._root = null; - } else { - this._root = root; - } - - if (position === undef) { - this._position = [0, 0, 0]; - } else { - this._position = position; - } - - this._nodes = []; - //this._static_nodes = []; - this._lights = []; - this._static_lights = []; - - this._sphere = new Sphere(this._position, Math.sqrt(3 * (this._size / 2 * this._size / 2))); - this._bbox = [[0,0,0],[0,0,0]]; - AABB_reset(this._bbox, this._position); - - var s = this._size/2; - AABB_engulf(this._bbox, [this._position[0] + s, this._position[1] + s, this._position[2] + s]); - AABB_engulf(this._bbox, [this._position[0] - s, this._position[1] - s, this._position[2] - s]); - this._debug_visible = false; -} //Octree::Constructor -Array_remove = function(arr, from, to) { - var rest = arr.slice((to || from) + 1 || arr.length); - arr.length = from < 0 ? arr.length + from : from; - return arr.push.apply(arr, rest); -}; -Octree.prototype.destroy = function() { - for (var i=0, li = this._static_lights.length; i<li; ++i) { - var light = this._static_lights[i]; - light.octree_leaves = null; - light.octree_common_root = null; - light.octree_aabb = null; - } //for - for (var i=0, li = this._lights.length; i<li; ++i) { - var light = this._lights[i]; - light.octree_leaves = null; - light.octree_common_root = null; - light.octree_aabb = null; - } //for - this._static_lights = null; - this._lights = null; - for (var i = 0, len = this._children.length; i < len; ++i) { - if (this._children[i] !== null) { - this._children[i].destroy(); - } //if - } //for - for (var i = 0, max_i = this._nodes.length; i < max_i; ++i) { - var node = this._nodes[i]; - node.octree_leaves = null; - node.octree_common_root = null; - node.octree_aabb = null; - node.dynamic_lights = []; - node.static_lights = []; - } //for - this._children[0] = null; - this._children[1] = null; - this._children[2] = null; - this._children[3] = null; - this._children[4] = null; - this._children[5] = null; - this._children[6] = null; - this._children[7] = null; - this._children = null; - this._root = null; - this._position = null; - this._nodes = null; - this._lights = null; - this._static_lights = null; - this._sphere = null; - this._bbox = null; -} //Octree::destroy -Octree.prototype.toString = function() { - var real_size = [this._bbox[1][0] - this._bbox[0][0], this._bbox[1][2] - this._bbox[0][2]]; - return "[Octree: @" + this._position + ", depth: " + this._max_depth + ", size: " + this._size + ", nodes: " + this._nodes.length + ", measured size:" + real_size + "]"; -}; //Octree::toString -Octree.prototype.remove = function(node) { - var dont_check_lights = false; - var len = this._nodes.length; - var i; - for (i = len - 1, len = this._nodes.length; i >= 0; --i) { - if (node === this._nodes[i]) { - Array_remove(this._nodes, i); - this.dirty_lineage(); - dont_check_lights = true; - break; - } //if - } //for - if (!dont_check_lights) { - for (i = len - 1, len = this._lights.length; i >= 0; --i) { - if (node === this._lights[i]) { - Array_remove(this._lights, i); - this.dirty_lineage(); - break; - } //if - } //for - } //if -}; //Octree::remove -Octree.prototype.dirty_lineage = function() { - this._dirty = true; - if (this._root !== null) { this._root.dirty_lineage(); } -} //Octree::dirty_lineage -Octree.prototype.cleanup = function() { - var num_children = this._children.length; - var num_keep_children = 0; - for (var i = 0; i < num_children; ++i) { - var child = this._children[i]; - if (child !== null) { - var keep = true; - if (child._dirty === true) { - keep = child.cleanup(); - } //if - if (!keep) { - this._children[i] = null; - } else { - ++num_keep_children; - } - } //if - } //for - if ((this._nodes.length === 0 && this._static_lights.length === 0 && this._lights.length === 0) && (num_keep_children === 0 || num_children === 0)) { - return false; - } - return true; -}; //Octree::cleanup -Octree.prototype.insert_light = function(light) { - this.insert(light, true); -}; //insert_light -Octree.prototype.propagate_static_light = function(light) { - var i,l; - for (i = 0, l = this._nodes.length; i < l; ++i) { - if (this._nodes[i].static_lights.indexOf(light) === -1) { - this._nodes[i].static_lights.push(light); - } //if - } //for - for (i = 0; i < 8; ++i) { - if (this._children[i] !== null) { - this._children[i].propagate_static_light(light); - } //if - } //for -}; //propagate_static_light -Octree.prototype.collect_static_lights = function(node) { - for (var i=0, li = this._static_lights.length; i<li; ++i) { - if (node.static_lights.indexOf(this._static_lights[i]) === -1) { - node.static_lights.push(this._static_lights[i]); - } //if - } //for - for (var i = 0; i < 8; ++i) { - if (this._children[i] !== null) { - this._children[i].collect_static_lights(node); - } //if - } //for -}; //collect_static_lights -Octree.prototype.insert = function(node, is_light) { - if (is_light === undef) { is_light = false; } - function $insert(octree, node, is_light, root) { - var i, li; - if (is_light) { - if (node.method === enums.light.method.STATIC) { - if (octree._static_lights.indexOf(node) === -1) { - octree._static_lights.push(node); - } //if - for (i=0; i<octree._nodes.length; ++i) { - if (octree._nodes[i].static_lights.indexOf(node) === -1) { - octree._nodes[i].static_lights.push(node); - } //if - } //for - var root_tree = octree._root; - while (root_tree !== null) { - for (var i=0, l=root_tree._nodes.length; i<l; ++i) { - var n = root_tree._nodes[i]; - if (n.static_lights.indexOf(node) === -1) { - n.static_lights.push(node); - } //if - } //for - root_tree = root_tree._root; - } //while - } - else { - if (octree._lights.indexOf(node) === -1) { - octree._lights.push(node); - } //if - } //if - } else { - octree._nodes.push(node); - for (i=0, li = octree._static_lights.length; i<li; ++i) { - if (node.static_lights.indexOf(octree._static_lights[i]) === -1) { - node.static_lights.push(octree._static_lights[i]); - } //if - } //for - var root_tree = octree._root; - while (root_tree !== null) { - for (var i=0, l=root_tree._static_lights.length; i<l; ++i) { - var light = root_tree._static_lights[i]; - if (node.static_lights.indexOf(light) === -1) { - node.static_lights.push(light); - } //if - } //for - root_tree = root_tree._root; - } //while - } //if - node.octree_leaves.push(octree); - node.octree_common_root = root; - AABB_engulf(node.octree_aabb, octree._bbox[0]); - AABB_engulf(node.octree_aabb, octree._bbox[1]); - } //$insert - if (this._root === null) { - node.octree_leaves = []; - node.octree_common_root = null; - } //if - if (this._max_depth === 0) { - $insert(this, node, is_light, this._root); - return; - } //if - //Check to see where the node is - var p = this._position; - var t_nw, t_ne, t_sw, t_se, b_nw, b_ne, b_sw, b_se; - var aabb = node.getAABB(); - var min = [aabb[0][0], aabb[0][1], aabb[0][2]]; - var max = [aabb[1][0], aabb[1][1], aabb[1][2]]; - - t_nw = min[0] < p[0] && min[1] < p[1] && min[2] < p[2]; - t_ne = max[0] > p[0] && min[1] < p[1] && min[2] < p[2]; - b_nw = min[0] < p[0] && max[1] > p[1] && min[2] < p[2]; - b_ne = max[0] > p[0] && max[1] > p[1] && min[2] < p[2]; - t_sw = min[0] < p[0] && min[1] < p[1] && max[2] > p[2]; - t_se = max[0] > p[0] && min[1] < p[1] && max[2] > p[2]; - b_sw = min[0] < p[0] && max[1] > p[1] && max[2] > p[2]; - b_se = max[0] > p[0] && max[1] > p[1] && max[2] > p[2]; - - //Is it in every sector? - if (t_nw && t_ne && b_nw && b_ne && t_sw && t_se && b_sw && b_se) { - $insert(this, node, is_light, this); - if (is_light) { - if (node.method == enums.light.method.STATIC) { - this.propagate_static_light(node); - } //if - } - else { - this.collect_static_lights(node); - } //if - } else { - - //Add static lights in this octree - for (var i=0, ii=this._static_lights.length; i<ii; ++i) { - if (node.static_lights === undef) node.static_lights = []; - if (node.static_lights.indexOf(this._static_lights[i]) === -1) { - node.static_lights.push(this._static_lights[i]); - } //if - } //for - - var new_size = this._size / 2; - var offset = this._size / 4; - var new_position; - - var num_inserted = 0; - //Create & check children to see if node fits there too - var x = this._position[0]; - var y = this._position[1]; - var z = this._position[2]; - if (t_nw) { - new_position = [x - offset, y - offset, z - offset]; - if (this._children[enums.octree.TOP_NW] === null) { - this._children[enums.octree.TOP_NW] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.TOP_NW); - } - this._children[enums.octree.TOP_NW].insert(node, is_light); - ++num_inserted; - } //if - if (t_ne) { - new_position = [x + offset, y - offset, z - offset]; - if (this._children[enums.octree.TOP_NE] === null) { - this._children[enums.octree.TOP_NE] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.TOP_NE); - } - this._children[enums.octree.TOP_NE].insert(node, is_light); - ++num_inserted; - } //if - if (b_nw) { - new_position = [x - offset, y + offset, z - offset]; - if (this._children[enums.octree.BOTTOM_NW] === null) { - this._children[enums.octree.BOTTOM_NW] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.BOTTOM_NW); - } - this._children[enums.octree.BOTTOM_NW].insert(node, is_light); - ++num_inserted; - } //if - if (b_ne) { - new_position = [x + offset, y + offset, z - offset]; - if (this._children[enums.octree.BOTTOM_NE] === null) { - this._children[enums.octree.BOTTOM_NE] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.BOTTOM_NE); - } - this._children[enums.octree.BOTTOM_NE].insert(node, is_light); - ++num_inserted; - } //if - if (t_sw) { - new_position = [x - offset, y - offset, z + offset]; - if (this._children[enums.octree.TOP_SW] === null) { - this._children[enums.octree.TOP_SW] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.TOP_SW); - } - this._children[enums.octree.TOP_SW].insert(node, is_light); - ++num_inserted; - } //if - if (t_se) { - new_position = [x + offset, y - offset, z + offset]; - if (this._children[enums.octree.TOP_SE] === null) { - this._children[enums.octree.TOP_SE] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.TOP_SE); - } - this._children[enums.octree.TOP_SE].insert(node, is_light); - ++num_inserted; - } //if - if (b_sw) { - new_position = [x - offset, y + offset, z + offset]; - if (this._children[enums.octree.BOTTOM_SW] === null) { - this._children[enums.octree.BOTTOM_SW] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.BOTTOM_SW); - } - this._children[enums.octree.BOTTOM_SW].insert(node, is_light); - ++num_inserted; - } //if - if (b_se) { - new_position = [x + offset, y + offset, z + offset]; - if (this._children[enums.octree.BOTTOM_SE] === null) { - this._children[enums.octree.BOTTOM_SE] = new Octree(new_size, this._max_depth - 1, this, new_position, enums.octree.BOTTOM_SE); - } - this._children[enums.octree.BOTTOM_SE].insert(node, is_light); - ++num_inserted; - } //if - if (num_inserted > 1 || node.octree_common_root === null) { - node.octree_common_root = this; - } //if - } //if -}; //Octree::insert -Octree.prototype.draw_on_map = function(map_canvas, map_context, target) { - var mhw = map_canvas.width/2; - var mhh = map_canvas.height/2; - var x, y, w, h; - var i, len; - - if (target === undef || target === "map") { - map_context.save(); - if (this._debug_visible !== false) { - map_context.fillStyle = "rgba(0,0,0,0)"; - map_context.strokeStyle = "#FF0000"; - } - else { - map_context.fillStyle = "rgba(0,0,0,0)"; - map_context.strokeStyle = "rgba(0,0,0,0)"; - } //if - map_context.beginPath(); - var offset = this._size / 2; - x = this._position[0]; - y = this._position[2]; - map_context.moveTo(mhw + x - offset, mhw + y - offset); - map_context.lineTo(mhw + x - offset, mhw + y + offset); - map_context.lineTo(mhw + x + offset, mhw + y + offset); - map_context.lineTo(mhw + x + offset, mhw + y - offset); - map_context.stroke(); - map_context.fill(); - map_context.restore(); - } - - if (target === undef || target === "objects") { - map_context.save(); - for (i = 0, len = this._nodes.length; i < len; ++i) { - var n = this._nodes[i]; - map_context.fillStyle = "#5500FF"; - if (n.visible === true && n.culled === false) { - map_context.strokeStyle = "#FFFFFF"; - } else { - map_context.strokeStyle = "#000000"; - } //if - map_context.beginPath(); - x = n.aabb[0][0]; - y = n.aabb[0][2]; - w = n.aabb[1][0] - x; - h = n.aabb[1][2] - y; - map_context.rect(mhw + x, mhh + y, w, h); - map_context.stroke(); - } //for - map_context.restore(); - } - - if (target === undef || target === "lights") { - for (i = 0, len = this._lights.length; i < len; ++i) { - var l = this._lights[i]; - if (l.culled === false && l.visible === true) { - map_context.fillStyle = "rgba(255, 255, 255, 0.1)"; - } else { - map_context.fillStyle = "rgba(255, 255, 255, 0.0)"; - } - map_context.strokeStyle = "#FFFF00"; - map_context.beginPath(); - var d = l.distance; - x = l.position[0]; - y = l.position[2]; - map_context.arc(mhw + x, mhh + y, d, 0, Math.PI * 2, true); - map_context.closePath(); - map_context.stroke(); - map_context.fill(); - map_context.beginPath(); - x = l.aabb[0][0]; - y = l.aabb[0][2]; - w = l.aabb[1][0] - x; - h = l.aabb[1][2] - y; - map_context.rect(mhw + x, mhh + y, w, h); - map_context.closePath(); - map_context.stroke(); - } //for - for (i = 0, len = this._static_lights.length; i < len; ++i) { - var l = this._static_lights[i]; - if (l.culled === false && l.visible === true) { - map_context.fillStyle = "rgba(255, 255, 255, 0.01)"; - } else { - map_context.fillStyle = "rgba(255, 255, 255, 0.0)"; - } - map_context.strokeStyle = "#FF66BB"; - map_context.beginPath(); - var d = l.distance; - x = l.position[0]; - y = l.position[2]; - map_context.arc(mhw + x, mhh + y, d, 0, Math.PI * 2, true); - map_context.closePath(); - map_context.stroke(); - map_context.fill(); - map_context.beginPath(); - x = l.aabb[0][0]; - y = l.aabb[0][2]; - w = l.aabb[1][0] - x; - h = l.aabb[1][2] - y; - map_context.rect(mhw + x, mhh + y, w, h); - map_context.closePath(); - map_context.stroke(); - } //for - } //if - - function $draw_box(x1, y1, x2, y2, fill) { - var x = x1 < x2 ? x1 : x2; - var y = y1 < y2 ? y1 : y2; - var w = x1 < x2 ? x2-x1 : x1-x2; - var h = y1 < y2 ? y2-y1 : y1-y2; - map_context.save(); - if (fill !== undefined) { - map_context.fillStyle = fill; - map_context.fillRect(mhw+x,mhh+y,w,h); - } //if - map_context.strokeRect(mhw+x,mhh+y,w,h); - map_context.restore(); - } //$draw_box - - function $draw_oct(oct, fill) { - var x1 = oct._bbox[0][0]; - var y1 = oct._bbox[0][2]; - var x2 = oct._bbox[1][0]; - var y2 = oct._bbox[1][2]; - $draw_box(x1, y1, x2, y2, fill); - } //$draw_oct - if (target != "lights" && target != "objects" && target != "map") { - map_context.save(); - var nodes = this._nodes; - for (var i=0,l=nodes.length;i<l;++i) { - var n = nodes[i]; - if (n.name == target) { - map_context.strokeStyle = "#FFFF00"; - map_context.lineWidth = 3; - map_context.beginPath(); - x = n.aabb[0][0]; - y = n.aabb[0][2]; - w = n.aabb[1][0] - x; - h = n.aabb[1][2] - y; - map_context.rect(mhw + x, mhh + y, w, h); - map_context.closePath(); - map_context.stroke(); - - var oab = n.octree_aabb; - map_context.strokeStyle = "#0000FF"; - $draw_box(oab[0][0], oab[0][2], oab[1][0], oab[1][2]); - map_context.lineWidth = 1; - if (n.common_root !== null) { - map_context.strokeStyle = "#00FF00"; - //$draw_oct(n.octree_common_root); - } //if - break; - } //if - } //for - map_context.lineWidth = 1; - map_context.strokeStyle = "#FFFF00"; - $draw_oct(this, "#444444"); - map_context.fill(); - map_context.restore(); - - } //if - - for (i = 0, len = this._children.length; i < len; ++i) { - if (this._children[i] !== null) { - this._children[i].draw_on_map(map_canvas, map_context, target); - } - } //for -}; //Octree::draw_on_map -Octree.prototype.contains_point = function(position) { - return position[0] <= this._position[0] + this._size / 2 && position[1] <= this._position[1] + this._size / 2 && position[2] <= this._position[2] + this._size / 2 && position[0] >= this._position[0] - this._size / 2 && position[1] >= this._position[1] - this._size / 2 && position[2] >= this._position[2] - this._size / 2; -}; //Octree::contains_point -Octree.prototype.get_frustum_hits = function(camera, test_children) { - var hits = { - objects: [], - lights: [] - }; - if (test_children === undef || test_children === true) { - if (! (this.contains_point(camera.position))) { - if (camera.frustum.sphere.intersects(this._sphere) === false) { - return hits; - } - //if(_sphere.intersects(c.get_frustum().get_cone()) === false) return; - var contains_sphere = camera.frustum.contains_sphere(this._sphere); - if (contains_sphere === -1) { - this._debug_visible = false; - return hits; - } - else if (contains_sphere === 1) { - this._debug_visible = 2; - test_children = false; - } - else if (contains_sphere === 0) { - this._debug_visible = true; - var contains_box = camera.frustum.contains_box(this._bbox); - if (contains_box === -1) { - this._debug_visible = false; - return hits; - } - else if (contains_box === 1) { - this._debug_visible = 3; - test_children = false; - } //if - } //if - } //if - } //if - var i, max_i; - for (i = 0, max_i = this._nodes.length; i < max_i; ++i) { - var n = this._nodes[i]; - hits.objects.push(n); - n.dynamic_lights = [].concat(this._lights); - n.was_culled = n.culled; - n.culled = false; - n.drawn_this_frame = false; - } //for objects - this._debug_visible = this._lights.length > 0 ? 4 : this._debug_visible; - for (i = 0, max_i = this._lights.length; i < max_i; ++i) { - var l = this._lights[i]; - if (l.visible === true) { - hits.lights.push(l); - l.was_culled = l.culled; - l.culled = false; - } //if - } //for dynamic lights - for (i = 0, max_i = this._static_lights.length; i < max_i; ++i) { - var l = this._static_lights[i]; - if (l.visible === true) { - l.culled = false; - } //if - } //for static lights - for (i = 0; i < 8; ++i) { - if (this._children[i] !== null) { - var child_hits = this._children[i].get_frustum_hits(camera, test_children); - var o, max_o; - for (o = 0, max_o = child_hits.objects.length; o < max_o; ++o) { - hits.objects.push(child_hits.objects[o]); - var obj_lights = child_hits.objects[o].dynamic_lights; - for (var j=0, lj=this._lights.length; j<lj; ++j) { - if(obj_lights.indexOf(this._lights[j]) < 0) { - obj_lights.push(this._lights[j]); - } //if - } //for j - } //for o - //hits.lights = hits.lights.concat(child_hits.lights); - //collect lights and make sure they're unique <- really slow - for (o = 0, max_o = child_hits.lights.length; o < max_o; ++o) { - if (hits.lights.indexOf(child_hits.lights[o]) < 0) { - hits.lights.push(child_hits.lights[o]); - } //if - } //for o - } //if - } //for - return hits; -}; //Octree::get_frustum_hits -Octree.prototype.reset_node_visibility = function() { - this._debug_visible = false; - - var i, l; - for (i = 0, l = this._nodes.length; i < l; ++i) { - this._nodes[i].culled = true; - } //for - for (i = 0, l = this._lights.length; i < l; ++i) { - this._lights[i].culled = true; - } //for - for (i = 0, l = this._static_lights.length; i < l; ++i) { - this._static_lights[i].culled = true; - } //for - for (i = 0, l = this._children.length; i < l; ++i) { - if (this._children[i] !== null) { - this._children[i].reset_node_visibility(); - } //if - } //for -}; //Octree::reset_visibility -/*********************************************** - * OctreeNode - ***********************************************/ - -function OctreeNode() { - this.position = [0, 0, 0]; - this.visible = false; - this._object = null; -} //OctreeNode::Constructor -OctreeNode.prototype.toString = function() { - return "[OctreeNode " + this.position + "]"; -}; //OctreeNode::toString -OctreeNode.prototype.attach = function(obj) { - this._object = obj; -}; //OctreeNode::attach - -function CubicVR_OctreeWorker() { - this.octree = null; - this.nodes = []; - this.camera = null; -} //CubicVR_OctreeWorker::Constructor -CubicVR_OctreeWorker.prototype.onmessage = function(input) { - var message = input.message; - if (message === "init") { - var params = input.data; - this.octree = new Octree(params.size, params.max_depth); - this.camera = new Camera(); - } - else if (type === "set_camera") { - var data = message.data; - this.camera.mvMatrix = data.mvMatrix; - this.camera.pMatrix = data.pMatrix; - this.camera.position = data.position; - this.camera.target = data.target; - this.camera.frustum.extract(this.camera, this.camera.mvMatrix, this.camera.pMatrix); - } - else if (type === "insert") { - var json_node = JSON.parse(message.data); - var node = new SceneObject(); - var trans = new Transform(); - - for (var i in json_node) { - if (json_node.hasOwnProperty(i)) { - node[i] = json_node[i]; - } //if - } //for - - for (var i in json_node.trans) { - if (json_node.trans.hasOwnProperty(i)) { - trans[i] = json_node.trans[i]; - } //if - } //for - - node.trans = trans; - node.id = json_node.id; - - this.octree.insert(node); - this.nodes[node.id] = node; - } - else if (type === "cleaup") { - this.octree.cleanup(); - } //if -}; //onmessage - -/*********************************************** - * Frustum - ***********************************************/ - -function FrustumWorkerProxy(worker, camera) { - this.camera = camera; - this.worker = worker; - this.draw_on_map = function(map_context) { - return; - }; -} //FrustumWorkerProxy -FrustumWorkerProxy.prototype.extract = function(camera, mvMatrix, pMatrix) { - this.worker.send({ - type: "set_camera", - data: { - mvMatrix: this.camera.mvMatrix, - pMatrix: this.camera.pMatrix, - position: this.camera.position, - target: this.camera.target - } - }); -}; //FrustumWorkerProxy::extract - -function Frustum() { - this.last_in = []; - this._planes = []; - this.sphere = null; - for (var i = 0; i < 6; ++i) { - this._planes[i] = new Plane(); - } //for -} //Frustum::Constructor -Frustum.prototype.extract = function(camera, mvMatrix, pMatrix) { - if (mvMatrix === undef || pMatrix === undef) { - return; - } - var comboMatrix = mat4.multiply(mvMatrix, pMatrix); - - // Left clipping plane - this._planes[enums.frustum.plane.LEFT].a = comboMatrix[3] + comboMatrix[0]; - this._planes[enums.frustum.plane.LEFT].b = comboMatrix[7] + comboMatrix[4]; - this._planes[enums.frustum.plane.LEFT].c = comboMatrix[11] + comboMatrix[8]; - this._planes[enums.frustum.plane.LEFT].d = comboMatrix[15] + comboMatrix[12]; - - // Right clipping plane - this._planes[enums.frustum.plane.RIGHT].a = comboMatrix[3] - comboMatrix[0]; - this._planes[enums.frustum.plane.RIGHT].b = comboMatrix[7] - comboMatrix[4]; - this._planes[enums.frustum.plane.RIGHT].c = comboMatrix[11] - comboMatrix[8]; - this._planes[enums.frustum.plane.RIGHT].d = comboMatrix[15] - comboMatrix[12]; - - // Top clipping plane - this._planes[enums.frustum.plane.TOP].a = comboMatrix[3] - comboMatrix[1]; - this._planes[enums.frustum.plane.TOP].b = comboMatrix[7] - comboMatrix[5]; - this._planes[enums.frustum.plane.TOP].c = comboMatrix[11] - comboMatrix[9]; - this._planes[enums.frustum.plane.TOP].d = comboMatrix[15] - comboMatrix[13]; - - // Bottom clipping plane - this._planes[enums.frustum.plane.BOTTOM].a = comboMatrix[3] + comboMatrix[1]; - this._planes[enums.frustum.plane.BOTTOM].b = comboMatrix[7] + comboMatrix[5]; - this._planes[enums.frustum.plane.BOTTOM].c = comboMatrix[11] + comboMatrix[9]; - this._planes[enums.frustum.plane.BOTTOM].d = comboMatrix[15] + comboMatrix[13]; - - // Near clipping plane - this._planes[enums.frustum.plane.NEAR].a = comboMatrix[3] + comboMatrix[2]; - this._planes[enums.frustum.plane.NEAR].b = comboMatrix[7] + comboMatrix[6]; - this._planes[enums.frustum.plane.NEAR].c = comboMatrix[11] + comboMatrix[10]; - this._planes[enums.frustum.plane.NEAR].d = comboMatrix[15] + comboMatrix[14]; - - // Far clipping plane - this._planes[enums.frustum.plane.FAR].a = comboMatrix[3] - comboMatrix[2]; - this._planes[enums.frustum.plane.FAR].b = comboMatrix[7] - comboMatrix[6]; - this._planes[enums.frustum.plane.FAR].c = comboMatrix[11] - comboMatrix[10]; - this._planes[enums.frustum.plane.FAR].d = comboMatrix[15] - comboMatrix[14]; - - for (var i = 0; i < 6; ++i) { - this._planes[i].normalize(); - } - - //Sphere - var fov = 1 / pMatrix[5]; - var near = -this._planes[enums.frustum.plane.NEAR].d; - var far = this._planes[enums.frustum.plane.FAR].d; - var view_length = far - near; - var height = view_length * fov; - var width = height; - - var P = [0, 0, near + view_length * 0.5]; - var Q = [width, height, near + view_length]; - var diff = vec3.subtract(P, Q); - var diff_mag = vec3.length(diff); - - var look_v = [comboMatrix[3], comboMatrix[9], comboMatrix[10]]; - var look_mag = vec3.length(look_v); - look_v = vec3.multiply(look_v, 1 / look_mag); - - this.sphere = new Sphere([camera.position[0], camera.position[1], camera.position[2]], diff_mag); - this.sphere.position = vec3.add(this.sphere.position, vec3.multiply(look_v, view_length * 0.5)); - this.sphere.position = vec3.add(this.sphere.position, vec3.multiply(look_v, 1)); - -}; //Frustum::extract -Frustum.prototype.contains_sphere = function(sphere) { - for (var i = 0; i < 6; ++i) { - var p = this._planes[i]; - var normal = [p.a, p.b, p.c]; - var distance = vec3.dot(normal, sphere.position) + p.d; - this.last_in[i] = 1; - - //OUT - if (distance < -sphere.radius) { - return -1; - } - - //INTERSECT - if (Math.abs(distance) < sphere.radius) { - return 0; - } - - } //for - //IN - return 1; -}; //Frustum::contains_sphere -Frustum.prototype.draw_on_map = function(map_canvas, map_context) { - var mhw = map_canvas.width/2; - var mhh = map_canvas.height/2; - map_context.save(); - for (var pi = 0, l = this._planes.length; pi < l; ++pi) { - if (pi === 2 || pi === 3) {continue;} - map_context.strokeStyle = "#FF00FF"; - if (pi < this.last_in.length) { - if (this.last_in[pi]) { - map_context.strokeStyle = "#FFFF00"; - } - } //if - var p = this._planes[pi]; - var x1 = -mhw; - var y1 = (-p.d - p.a * x1) / p.c; - var x2 = mhw; - var y2 = (-p.d - p.a * x2) / p.c; - map_context.moveTo(mhw + x1, mhh + y1); - map_context.lineTo(mhw + x2, mhh + y2); - map_context.stroke(); - } //for - map_context.strokeStyle = "#0000FF"; - map_context.beginPath(); - map_context.arc(mhw + this.sphere.position[0], mhh + this.sphere.position[2], this.sphere.radius, 0, Math.PI * 2, false); - map_context.closePath(); - map_context.stroke(); - map_context.restore(); -}; //Frustum::draw_on_map -Frustum.prototype.contains_box = function(bbox) { - var total_in = 0; - - var points = []; - points[0] = bbox[0]; - points[1] = [bbox[0][0], bbox[0][1], bbox[1][2]]; - points[2] = [bbox[0][0], bbox[1][1], bbox[0][2]]; - points[3] = [bbox[0][0], bbox[1][1], bbox[1][2]]; - points[4] = [bbox[1][0], bbox[0][1], bbox[0][2]]; - points[5] = [bbox[1][0], bbox[0][1], bbox[1][2]]; - points[6] = [bbox[1][0], bbox[1][1], bbox[0][2]]; - points[7] = bbox[1]; - - for (var i = 0; i < 6; ++i) { - var in_count = 8; - var point_in = 1; - - for (var j = 0; j < 8; ++j) { - if (this._planes[i].classify_point(points[j]) === -1) { - point_in = 0; - --in_count; - } //if - } //for j - this.last_in[i] = point_in; - - //OUT - if (in_count === 0) { - return -1; - } - - total_in += point_in; - } //for i - //IN - if (total_in === 6) { - return 1; - } - - return 0; -}; //Frustum::contains_box - -function Camera(width, height, fov, nearclip, farclip) { - this.frustum = new Frustum(); - - if (typeof(width)=='object') { - this.position = width.position?width.position:[0, 0, 0]; - this.rotation = width.rotation?width.rotation:[0, 0, 0]; - this.target = width.target?width.target:[0, 0, 0]; - this.fov = width.fov?width.fov:60.0; - this.nearclip = width.nearclip?width.nearclip:0.1; - this.farclip = width.farclip?width.farclip:400.0; - this.targeted = width.targeted?width.targeted:true; - height = width.height?width.height:undef; - width = width.width?width.width:undef; - } else { - this.position = [0, 0, 0]; - this.rotation = [0, 0, 0]; - this.target = [0, 0, 0]; - this.fov = (fov !== undef) ? fov : 60.0; - this.nearclip = (nearclip !== undef) ? nearclip : 0.1; - this.farclip = (farclip !== undef) ? farclip : 400.0; - this.targeted = true; - } - - this.targetSceneObject = null; - this.motion = null; - this.transform = new Transform(); - - this.manual = false; - - this.setDimensions((width !== undef) ? width : 512, (height !== undef) ? height : 512); - - this.mvMatrix = cubicvr_identity; - this.pMatrix = null; - this.calcProjection(); -} - -Camera.prototype.control = function(controllerId, motionId, value) { - if (controllerId === enums.motion.ROT) { - this.rotation[motionId] = value; - } else if (controllerId === enums.motion.POS) { - this.position[motionId] = value; - } else if (controllerId === enums.motion.FOV) { - this.setFOV(value); - } else if (controllerId === enums.motion.LENS) { - this.setLENS(value); - } else if (controllerId === enums.motion.NEARCLIP) { - this.setClip(value,this.farclip); - } else if (controllerId === enums.motion.FARCLIP) { - this.setClip(this.nearclip,value); - } - /* - switch (controllerId) { - case enums.motion.ROT: - this.rotation[motionId] = value; - break; - case enums.motion.POS: - this.position[motionId] = value; - break; - case enums.motion.FOV: - this.setFOV(value); - break; - } - */ -}; - - -Camera.prototype.makeFrustum = function(left, right, bottom, top, zNear, zFar) { - var A = (right + left) / (right - left); - var B = (top + bottom) / (top - bottom); - var C = -(zFar + zNear) / (zFar - zNear); - var D = -2.0 * zFar * zNear / (zFar - zNear); - - return [2.0 * zNear / (right - left), 0.0, 0.0, 0.0, 0.0, 2.0 * zNear / (top - bottom), 0.0, 0.0, A, B, C, -1.0, 0.0, 0.0, D, 0.0]; -}; - - -Camera.prototype.setTargeted = function(targeted) { - this.targeted = targeted; -}; - -Camera.prototype.calcProjection = function() { - this.pMatrix = mat4.perspective(this.fov, this.aspect, this.nearclip, this.farclip); - if (!this.targeted) { - this.transform.clearStack(); - //this.transform.translate(vec3.subtract([0,0,0],this.position)).pushMatrix().rotate(vec3.subtract([0,0,0],this.rotation)).getResult(); - this.transform.translate(-this.position[0], -this.position[1], -this.position[2]); - this.transform.pushMatrix(); - this.transform.rotate(-this.rotation[2], 0, 0, 1); - this.transform.rotate(-this.rotation[1], 0, 1, 0); - this.transform.rotate(-this.rotation[0], 1, 0, 0); - this.transform.pushMatrix(); - this.mvMatrix = this.transform.getResult(); - this.nMatrix = mat4.inverse_mat3(this.mvMatrix); - mat3.transpose_inline(this.nMatrix); - } - this.frustum.extract(this, this.mvMatrix, this.pMatrix); -}; - - -Camera.prototype.setClip = function(nearclip, farclip) { - this.nearclip = nearclip; - this.farclip = farclip; - this.calcProjection(); -}; - - -Camera.prototype.setDimensions = function(width, height) { - this.width = width; - this.height = height; - - this.aspect = width / height; - this.calcProjection(); -}; - - -Camera.prototype.setFOV = function(fov) { - this.fov = fov; - this.calcProjection(); -}; - -Camera.prototype.setLENS = function(lens) { - this.setFOV(2.0*Math.atan(16.0/lens)*(180.0/M_PI)); -}; - -Camera.prototype.lookat = function(eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ) { - - if (typeof(eyeX)=='object') { - this.lookat(this.position[0],this.position[1],this.position[2],eyeX[0],eyeX[1],eyeX[2],0,1,0); - return; - } - - this.mvMatrix = mat4.lookat(eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ); - this.nMatrix = mat4.inverse_mat3(this.mvMatrix); - mat3.transpose_inline(this.nMatrix); - this.frustum.extract(this, this.mvMatrix, this.pMatrix); -}; - - -Camera.prototype.unProject = function (winx, winy, winz) { - - var tmpClip = this.nearclip; - - if (tmpClip < 1.0) { this.nearclip = 1.0; this.calcProjection(); } - - var viewport = [0, 0, this.width, this.height]; - - if (winz === undef) winz = this.farclip; - - var p = [(((winx - viewport[0]) / (viewport[2])) * 2) - 1, -((((winy - viewport[1]) / (viewport[3])) * 2) - 1), (winz - this.nearclip) / (this.farclip - this.nearclip), 1.0]; - - var invp = mat4.vec4_multiply(mat4.vec4_multiply(p, mat4.inverse(this.pMatrix)), mat4.inverse(this.mvMatrix)); - - if (tmpClip < 1.0) { this.nearclip = tmpClip; this.calcProjection(); } - - return [invp[0] / invp[3], invp[1] / invp[3], invp[2] / invp[3]]; -} - - -Camera.prototype.project = function (objx, objy, objz) { - - var p = [objx,objy,objz,1.0]; - - var mp = mat4.vec4_multiply(mat4.vec4_multiply(p,this.mvMatrix),this.pMatrix); - - return [((mp[0]/mp[3]+1.0)/2.0)*this.width,((-mp[1]/mp[3]+1.0)/2.0)*this.height,((mp[2]/mp[3]))*(this.farclip-this.nearclip)+this.nearclip]; - -} - - -/*** Auto-Cam Prototype ***/ - -function AutoCameraNode(pos) { - this.position = (pos !== undef) ? pos : [0, 0, 0]; -} - -AutoCameraNode.prototype.control = function(controllerId, motionId, value) { - if (controllerId === enums.motion.POS) { - this.position[motionId] = value; - } -}; - -function AutoCamera(start_position, target, bounds) { - this.camPath = new Motion(); - this.targetPath = new Motion(); - - this.start_position = (start_position !== undef) ? start_position : [8, 8, 8]; - this.target = (target !== undef) ? target : [0, 0, 0]; - - this.bounds = (bounds !== undef) ? bounds : [[-15, 3, -15], [15, 20, 15]]; - -this.safe_bb = []; -this.avoid_sphere = []; - -this.segment_time = 3.0; -this.buffer_time = 20.0; -this.start_time = 0.0; -this.current_time = 0.0; - -this.path_time = 0.0; -this.path_length = 0; - -this.min_distance = 2.0; -this.max_distance = 40.0; - -this.angle_min = 40; -this.angle_max = 180; -} - - -AutoCamera.prototype.inBounds = function(pt) { - if (! (pt[0] > this.bounds[0][0] && pt[1] > this.bounds[0][1] && pt[2] > this.bounds[0][2] && pt[0] < this.bounds[1][0] && pt[1] < this.bounds[1][1] && pt[2] < this.bounds[1][2])) { - return false; - } - - for (var i = 0, iMax = this.avoid_sphere.length; i < iMax; i++) { - var l = vec3.length(pt, this.avoid_sphere[i][0]); - if (l < this.avoid_sphere[i][1]) { - return false; - } - } - - return true; -}; - -AutoCamera.prototype.findNextNode = function(aNode, bNode) { - var d = [this.bounds[1][0] - this.bounds[0][0], this.bounds[1][1] - this.bounds[0][1], this.bounds[1][2] - this.bounds[0][2]]; - - var nextNodePos = [0, 0, 0]; - var randVector = [0, 0, 0]; - var l = 0.0; - var loopkill = 0; - var valid = false; - - do { - randVector[0] = Math.random() - 0.5; - randVector[1] = Math.random() - 0.5; - randVector[2] = Math.random() - 0.5; - - randVector = vec3.normalize(randVector); - - var r = Math.random(); - - l = (r * (this.max_distance - this.min_distance)) + this.min_distance; - - nextNodePos = vec3.add(bNode.position, vec3.multiply(randVector, l)); - - valid = this.inBounds(nextNodePos); - - loopkill++; - - if (loopkill > 30) { - nextNodePos = bNode.position; - break; - } - } while (!valid); - - return nextNodePos; -}; - -AutoCamera.prototype.run = function(timer) { - this.current_time = timer; - - if (this.path_time === 0.0) { - this.path_time = this.current_time; - - this.camPath.setKey(enums.motion.POS, enums.motion.X, this.path_time, this.start_position[0]); - this.camPath.setKey(enums.motion.POS, enums.motion.Y, this.path_time, this.start_position[1]); - this.camPath.setKey(enums.motion.POS, enums.motion.Z, this.path_time, this.start_position[2]); - } - - while (this.path_time < this.current_time + this.buffer_time) { - this.path_time += this.segment_time; - - var tmpNodeA = new AutoCameraNode(); - var tmpNodeB = new AutoCameraNode(); - - if (this.path_length) { - this.camPath.apply(this.path_time - (this.segment_time * 2.0), tmpNodeA); - } - - this.camPath.apply(this.path_time - this.segment_time, tmpNodeB); - - var nextPos = this.findNextNode(tmpNodeA, tmpNodeB); - - this.camPath.setKey(enums.motion.POS, enums.motion.X, this.path_time, nextPos[0]); - this.camPath.setKey(enums.motion.POS, enums.motion.Y, this.path_time, nextPos[1]); - this.camPath.setKey(enums.motion.POS, enums.motion.Z, this.path_time, nextPos[2]); - - this.path_length++; - } - - var tmpNodeC = new AutoCameraNode(); - - this.camPath.apply(timer, tmpNodeC); - - return tmpNodeC.position; -}; - - -AutoCamera.prototype.addSafeBound = function(min, max) { - this.safe_bb.push([min, max]); -}; - -AutoCamera.prototype.addAvoidSphere = function(center, radius) { - this.avoid_sphere.push([center, radius]); -}; - -function Scene(width, height, fov, nearclip, farclip, octree) { - this.frames = 0; - - this.sceneObjects = []; - this.sceneObjectsByName = []; - this.sceneObjectsById = []; - this.lights = []; - this.global_lights = []; - this.dynamic_lights = []; - this.pickables = []; - this.octree = octree; - this.skybox = null; - this.camera = new Camera(width, height, fov, nearclip, farclip); - this._workers = null; - this.stats = []; - this.collect_stats = false; -} - -Scene.prototype.attachOctree = function(octree) { - this.octree = octree; - if (octree.init) { - octree.init(this); - } //if - - // rebind any active lights - var tmpLights = this.lights; - this.lights = []; - - for (var l = 0, lMax = tmpLights.length; l < lMax; l++) { - this.bindLight(tmpLights[l]); - } //for - - var objs = this.sceneObjects; - if (this.octree !== undef) { - for (var i=0, l=objs.length; i<l; ++i) { - var obj = objs[i]; - if (obj.obj === null) { continue; } - if (obj.id < 0) { - obj.id = scene_object_uuid; - ++scene_object_uuid; - } //if - this.sceneObjectsById[obj.id] = obj; - AABB_reset(obj.octree_aabb, obj.position); - this.octree.insert(obj); - if (obj.octree_common_root === undefined || obj.octree_common_root === null) { - log("!!", obj.name, "octree_common_root is null"); - } //if - } //for - } //if - - -} //Scene::attachOctree - -Scene.prototype.setSkyBox = function(skybox) { - this.skybox = skybox; - //this.bindSceneObject(skybox.scene_object, null, false); -}; - -Scene.prototype.getSceneObject = function(name) { - return this.sceneObjectsByName[name]; -}; - -Scene.prototype.bindSceneObject = function(sceneObj, pickable, use_octree) { - this.sceneObjects.push(sceneObj); - if (pickable !== undef) { - if (pickable) { - this.pickables.push(sceneObj); - } - } - - if (sceneObj.name !== null) { - this.sceneObjectsByName[sceneObj.name] = sceneObj; - } - - if (this.octree !== undef && (use_octree === undef || use_octree === "true")) { - if (sceneObj.id < 0) { - sceneObj.id = scene_object_uuid; - ++scene_object_uuid; - } //if - this.sceneObjectsById[sceneObj.id] = sceneObj; - AABB_reset(sceneObj.octree_aabb, sceneObj.position); - this.octree.insert(sceneObj); - } //if -}; - -Scene.prototype.bindLight = function(lightObj, use_octree) { - this.lights.push(lightObj); - if (this.octree !== undef && (use_octree === undef || use_octree === "true")) { - if (lightObj.method === enums.light.method.GLOBAL) { - this.global_lights.push(lightObj); - } - else { - if (lightObj.method === enums.light.method.DYNAMIC) { - this.dynamic_lights.push(lightObj); - } //if - this.octree.insert_light(lightObj); - } //if - } //if - - this.lights=this.lights.sort(cubicvr_lightPackTypes); -}; - -Scene.prototype.bindCamera = function(cameraObj) { - this.camera = cameraObj; -}; - - -Scene.prototype.evaluate = function(index) { - var i,iMax; - - for (i = 0, iMax = this.sceneObjects.length; i < iMax; i++) { - if (!(this.sceneObjects[i].motion)) { - continue; - } - this.sceneObjects[i].motion.apply(index, this.sceneObjects[i]); - } - - if (this.camera.motion !== null) { - if (this.camera.targetSceneObject !== null) { - this.camera.target = this.camera.targetSceneObject.position; - } - - this.camera.motion.apply(index, this.camera); - } - - for (var i = 0, iMax = this.lights.length; i < iMax; i++) { - var l = this.lights[i]; - - if (l.motion !== null) { - l.motion.apply(index, l); - } - } -}; - -Scene.prototype.renderSceneObjectChildren = function(sceneObj) { - var gl = GLCore.gl; - var sflip = false; - - for (var i = 0, iMax = sceneObj.children.length; i < iMax; i++) { - - try { - sceneObj.children[i].doTransform(sceneObj.tMatrix); - }catch(e){break;} - - if (sceneObj.children[i].scale[0] < 0) { - sflip = !sflip; - } - if (sceneObj.children[i].scale[1] < 0) { - sflip = !sflip; - } - if (sceneObj.children[i].scale[2] < 0) { - sflip = !sflip; - } - - if (sflip) { - gl.cullFace(gl.FRONT); - } - - cubicvr_renderObject(sceneObj.children[i].obj, this.camera, sceneObj.children[i].tMatrix, this.lights); - - if (sflip) { - gl.cullFace(gl.BACK); - } - - if (sceneObj.children[i].children !== null) { - this.renderSceneObjectChildren(sceneObj.children[i]); - } - } -}; - -function cubicvr_lightPackTypes(a,b) { - return a.light_type - b.light_type; -} - -Scene.prototype.render = function() { - ++this.frames; - - var gl = GLCore.gl; - var frustum_hits; - - if (this.camera.manual===false) - { - if (this.camera.targeted) { - this.camera.lookat(this.camera.position[0], this.camera.position[1], this.camera.position[2], this.camera.target[0], this.camera.target[1], this.camera.target[2], 0, 1, 0); - } else { - this.camera.calcProjection(); - } - } - - var use_octree = this.octree !== undef; - var lights_rendered = 0; - if (use_octree) { - for (var i = 0, l = this.dynamic_lights.length; i < l; ++i) { - var light = this.dynamic_lights[i]; - light.doTransform(); - } //for - this.octree.reset_node_visibility(); - this.octree.cleanup(); - frustum_hits = this.octree.get_frustum_hits(this.camera); - lights_rendered = frustum_hits.lights.length; - } //if - var sflip = false; - var objects_rendered = 0; - var lights_list = []; - - for (var i = 0, iMax = this.sceneObjects.length; i < iMax; i++) { - - var lights = this.lights; - var scene_object = this.sceneObjects[i]; - if (scene_object.parent !== null) { - continue; - } //if - - scene_object.doTransform(); - - if (use_octree) - { - lights = []; - if (scene_object.dirty && scene_object.obj !== null) { - scene_object.adjust_octree(); - } //if - - if (scene_object.visible === false || (use_octree && (scene_object.ignore_octree || scene_object.drawn_this_frame === true || scene_object.culled === true))) { - continue; - } //if - - //lights = frustum_hits.lights; - lights = scene_object.dynamic_lights; - //lights = this.lights; - - lights = lights.concat(scene_object.static_lights); - lights = lights.concat(this.global_lights); - if (this.collect_stats) { - lights_rendered = Math.max(lights.length, lights_rendered); - if (lights_rendered === lights.length) { - lights_list = lights; - } //if - ++objects_rendered; - } //if - - if (lights.length === 0) { - lights = [emptyLight]; - } //if - - scene_object.drawn_this_frame = true; - } - else if (scene_object.visible === false) { - continue; - } //if - - if (scene_object.obj !== null) { - if (scene_object.scale[0] < 0) { - sflip = !sflip; - } - if (scene_object.scale[1] < 0) { - sflip = !sflip; - } - if (scene_object.scale[2] < 0) { - sflip = !sflip; - } - - if (sflip) { - gl.cullFace(gl.FRONT); - } - - - cubicvr_renderObject(scene_object.obj, this.camera, scene_object.tMatrix, lights.sort(cubicvr_lightPackTypes)); - - if (sflip) { - gl.cullFace(gl.BACK); - } - - sflip = false; - } //if - - if (scene_object.children !== null) { - this.renderSceneObjectChildren(scene_object); - } //if - } //for - - if (this.collect_stats) { - this.stats['objects.num_rendered'] = objects_rendered; - this.stats['lights.num_rendered'] = lights_rendered; - this.stats['lights.rendered'] = lights_list; - this.stats['lights.num_global'] = this.global_lights.length; - this.stats['lights.num_dynamic'] = this.dynamic_lights.length; - } //if - - if (this.skybox !== null && this.skybox.ready === true) { - gl.cullFace(gl.FRONT); - var size = (this.camera.farclip * 2) / Math.sqrt(3.0); - this.skybox.scene_object.position = [this.camera.position[0], this.camera.position[1], this.camera.position[2]]; - this.skybox.scene_object.scale = [size, size, size]; - this.skybox.scene_object.doTransform(); - cubicvr_renderObject(this.skybox.scene_object.obj, this.camera, this.skybox.scene_object.tMatrix, []); - gl.cullFace(gl.BACK); - } //if -}; - -Scene.prototype.bbRayTest = function(pos, ray, axisMatch) { - var pt1, pt2; - var selList = []; - - if (ray.length === 2) { - ray = this.camera.unProject(ray[0], ray[1]); - } else { - ray = vec3.add(pos, ray); - } - - pt1 = pos; - pt2 = ray; - - for (var obj_i in this.pickables) { - if (this.pickables.hasOwnProperty(obj_i)) { - var obj = this.pickables[obj_i]; - if (obj.visible !== true) continue; - - var bb1, bb2; - var aabb = obj.getAABB(); - bb1 = aabb[0]; - bb2 = aabb[1]; - - var mindepth = 0.2; - - if (bb2[0]-bb1[0] < mindepth) {bb1[0] -= mindepth/2; bb2[0] += mindepth/2;} - if (bb2[1]-bb1[1] < mindepth) {bb1[1] -= mindepth/2; bb2[1] += mindepth/2;} - if (bb2[2]-bb1[2] < mindepth) {bb1[2] -= mindepth/2; bb2[2] += mindepth/2;} - - var center = vec3.multiply(vec3.add(bb1, bb2), 0.5); - var testPt = vec3.get_closest_to(pt1, pt2, center); - var testDist = vec3.length(vec3.subtract(testPt, center)); - - var matches = - ((testPt[0] >= bb1[0] && testPt[0] <= bb2[0]) ? 1 : 0) + - ((testPt[1] >= bb1[1] && testPt[1] <= bb2[1]) ? 1 : 0) + - ((testPt[2] >= bb1[2] && testPt[2] <= bb2[2]) ? 1 : 0); - - if (matches >= axisMatch) { - selList.push({dist:testDist, obj:obj}); - } - } - } - - if (selList.length) { - selList.sort(function(a,b) { if (a.dist==b.dist) return 0; return (a.dist<b.dist) ?-1:1; }); - } - - return selList; -}; - -function cubicvr_loadMesh(meshUrl, prefix) { - if (MeshPool[meshUrl] !== undef) { - return MeshPool[meshUrl]; - } - - var i, j, p, iMax, jMax, pMax; - - var obj = new Mesh(); - var mesh = util.getXML(meshUrl); - var pts_elem = mesh.getElementsByTagName("points"); - - var pts_str = util.collectTextNode(pts_elem[0]); - var pts = pts_str.split(" "); - - var texName, tex; - - for (i = 0, iMax = pts.length; i < iMax; i++) { - pts[i] = pts[i].split(","); - for (j = 0, jMax = pts[i].length; j < jMax; j++) { - pts[i][j] = parseFloat(pts[i][j]); - } - } - - obj.addPoint(pts); - - var material_elem = mesh.getElementsByTagName("material"); - var mappers = []; - - - for (i = 0, iMax = material_elem.length; i < iMax; i++) { - var melem = material_elem[i]; - - var matName = (melem.getElementsByTagName("name").length) ? (melem.getElementsByTagName("name")[0].firstChild.nodeValue) : null; - var mat = new Material(matName); - - if (melem.getElementsByTagName("alpha").length) { - mat.opacity = parseFloat(melem.getElementsByTagName("alpha")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("shininess").length) { - mat.shininess = (parseFloat(melem.getElementsByTagName("shininess")[0].firstChild.nodeValue) / 100.0); - } - if (melem.getElementsByTagName("max_smooth").length) { - mat.max_smooth = parseFloat(melem.getElementsByTagName("max_smooth")[0].firstChild.nodeValue); - } - - if (melem.getElementsByTagName("color").length) { - mat.color = util.floatDelimArray(melem.getElementsByTagName("color")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("ambient").length) { - mat.ambient = util.floatDelimArray(melem.getElementsByTagName("ambient")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("diffuse").length) { - mat.diffuse = util.floatDelimArray(melem.getElementsByTagName("diffuse")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("specular").length) { - mat.specular = util.floatDelimArray(melem.getElementsByTagName("specular")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("texture").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.COLOR); - } - - if (melem.getElementsByTagName("texture_luminosity").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_luminosity")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.AMBIENT); - } - - if (melem.getElementsByTagName("texture_normal").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_normal")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.NORMAL); - } - - if (melem.getElementsByTagName("texture_specular").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_specular")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.SPECULAR); - } - - if (melem.getElementsByTagName("texture_bump").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_bump")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.BUMP); - } - - if (melem.getElementsByTagName("texture_envsphere").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_envsphere")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.ENVSPHERE); - } - - if (melem.getElementsByTagName("texture_alpha").length) { - texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_alpha")[0].firstChild.nodeValue; - tex = (Texture_ref[texName] !== undef) ? Textures_obj[Texture_ref[texName]] : (new Texture(texName)); - mat.setTexture(tex, enums.texture.map.ALPHA); - } - - var uvSet = null; - - if (melem.getElementsByTagName("uvmapper").length) { - var uvm = new UVMapper(); - var uvelem = melem.getElementsByTagName("uvmapper")[0]; - var uvmType = ""; - - if (uvelem.getElementsByTagName("type").length) { - uvmType = melem.getElementsByTagName("type")[0].firstChild.nodeValue; - - switch (uvmType) { - case "uv": - break; - case "planar": - uvm.projection_mode = enums.uv.projection.PLANAR; - break; - case "cylindrical": - uvm.projection_mode = enums.uv.projection.CYLINDRICAL; - break; - case "spherical": - uvm.projection_mode = enums.uv.projection.SPHERICAL; - break; - case "cubic": - uvm.projection_mode = enums.uv.projection.CUBIC; - break; - } - } - - if (uvmType === "uv") { - if (uvelem.getElementsByTagName("uv").length) { - var uvText = util.collectTextNode(melem.getElementsByTagName("uv")[0]); - - uvSet = uvText.split(" "); - - for (j = 0, jMax = uvSet.length; j < jMax; j++) { - uvSet[j] = util.floatDelimArray(uvSet[j]); - } - } - } - - if (uvelem.getElementsByTagName("axis").length) { - var uvmAxis = melem.getElementsByTagName("axis")[0].firstChild.nodeValue; - - switch (uvmAxis) { - case "x": - uvm.projection_axis = enums.uv.axis.X; - break; - case "y": - uvm.projection_axis = enums.uv.axis.Y; - break; - case "z": - uvm.projection_axis = enums.uv.axis.Z; - break; - } - - } - - if (melem.getElementsByTagName("center").length) { - uvm.center = util.floatDelimArray(melem.getElementsByTagName("center")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("rotation").length) { - uvm.rotation = util.floatDelimArray(melem.getElementsByTagName("rotation")[0].firstChild.nodeValue); - } - if (melem.getElementsByTagName("scale").length) { - uvm.scale = util.floatDelimArray(melem.getElementsByTagName("scale")[0].firstChild.nodeValue); - } - - if (uvmType !== "" && uvmType !== "uv") { - mappers.push([uvm, mat]); - } - } - - - var seglist = null; - var triangles = null; - - if (melem.getElementsByTagName("segments").length) { - seglist = util.intDelimArray(util.collectTextNode(melem.getElementsByTagName("segments")[0]), " "); - } - if (melem.getElementsByTagName("triangles").length) { - triangles = util.intDelimArray(util.collectTextNode(melem.getElementsByTagName("triangles")[0]), " "); - } - - - if (seglist === null) { - seglist = [0, parseInt((triangles.length) / 3, 10)]; - } - - var ofs = 0; - - if (triangles.length) { - for (p = 0, pMax = seglist.length; p < pMax; p += 2) { - var currentSegment = seglist[p]; - var totalPts = seglist[p + 1] * 3; - - obj.setSegment(currentSegment); - obj.setFaceMaterial(mat); - - for (j = ofs, jMax = ofs + totalPts; j < jMax; j += 3) { - var newFace = obj.addFace([triangles[j], triangles[j + 1], triangles[j + 2]]); - if (uvSet) { - obj.faces[newFace].setUV([uvSet[j], uvSet[j + 1], uvSet[j + 2]]); - } - } - - ofs += totalPts; - } - } - } - - obj.calcNormals(); - - for (i = 0, iMax = mappers.length; i < iMax; i++) { - mappers[i][0].apply(obj, mappers[i][1]); - } - - obj.compile(); - - MeshPool[meshUrl] = obj; - - return obj; -} - - - - - - - -function cubicvr_loadScene(sceneUrl, model_prefix, image_prefix) { - if (model_prefix === undef) { - model_prefix = ""; - } - if (image_prefix === undef) { - image_prefix = ""; - } - - var obj = new Mesh(); - var scene = util.getXML(sceneUrl); - - var sceneOut = new Scene(); - - var parentingSet = []; - - var sceneobjs = scene.getElementsByTagName("sceneobjects"); - - var tempNode; - - var position, rotation, scale; - - // var pts_str = util.collectTextNode(pts_elem[0]); - for (var i = 0, iMax = sceneobjs[0].childNodes.length; i < iMax; i++) { - var sobj = sceneobjs[0].childNodes[i]; - - if (sobj.tagName === "sceneobject") { - - var name = "unnamed"; - var parent = ""; - var model = ""; - - tempNode = sobj.getElementsByTagName("name"); - if (tempNode.length) { - name = util.collectTextNode(tempNode[0]); - } - - tempNode = sobj.getElementsByTagName("parent"); - if (tempNode.length) { - parent = util.collectTextNode(tempNode[0]); - } - - tempNode = sobj.getElementsByTagName("model"); - if (tempNode.length) { - model = util.collectTextNode(tempNode[0]); - } - - position = null; - rotation = null; - scale = null; - - tempNode = sobj.getElementsByTagName("position"); - if (tempNode.length) { - position = tempNode[0]; - } - - tempNode = sobj.getElementsByTagName("rotation"); - if (tempNode.length) { - rotation = tempNode[0]; - } - - tempNode = sobj.getElementsByTagName("scale"); - if (tempNode.length) { - scale = tempNode[0]; - } - - obj = null; - - if (model !== "") { - obj = cubicvr_loadMesh(model_prefix + model, image_prefix); - } - - var sceneObject = new SceneObject(obj, name); - - if (cubicvr_isMotion(position)) { - if (!sceneObject.motion) { - sceneObject.motion = new Motion(); - } - cubicvr_nodeToMotion(position, enums.motion.POS, sceneObject.motion); - } else if (position) { - sceneObject.position = util.floatDelimArray(util.collectTextNode(position)); - } - - if (cubicvr_isMotion(rotation)) { - if (!sceneObject.motion) { - sceneObject.motion = new Motion(); - } - cubicvr_nodeToMotion(rotation, enums.motion.ROT, sceneObject.motion); - } else { - sceneObject.rotation = util.floatDelimArray(util.collectTextNode(rotation)); - } - - if (cubicvr_isMotion(scale)) { - if (!sceneObject.motion) { - sceneObject.motion = new Motion(); - } - cubicvr_nodeToMotion(scale, enums.motion.SCL, sceneObject.motion); - } else { - sceneObject.scale = util.floatDelimArray(util.collectTextNode(scale)); - - } - - sceneOut.bindSceneObject(sceneObject); - - if (parent !== "") { - parentingSet.push([sceneObject, parent]); - } - } - } - - for (var j in parentingSet) { - if (parentingSet.hasOwnProperty(j)) { - sceneOut.getSceneObject(parentingSet[j][1]).bindChild(parentingSet[j][0]); - } - } - - var camera = scene.getElementsByTagName("camera"); - - if (camera.length) { - position = null; - rotation = null; - - var target = ""; - - tempNode = camera[0].getElementsByTagName("name"); - - var cam = sceneOut.camera; - - var fov = null; - - if (tempNode.length) { - target = tempNode[0].firstChild.nodeValue; - } - - tempNode = camera[0].getElementsByTagName("target"); - if (tempNode.length) { - target = tempNode[0].firstChild.nodeValue; - } - - if (target !== "") { - cam.targetSceneObject = sceneOut.getSceneObject(target); - } - - tempNode = camera[0].getElementsByTagName("position"); - if (tempNode.length) { - position = tempNode[0]; - } - - tempNode = camera[0].getElementsByTagName("rotation"); - if (tempNode.length) { - rotation = tempNode[0]; - } - - tempNode = camera[0].getElementsByTagName("fov"); - if (tempNode.length) { - fov = tempNode[0]; - } - - if (cubicvr_isMotion(position)) { - if (!cam.motion) { - cam.motion = new Motion(); - } - cubicvr_nodeToMotion(position, enums.motion.POS, cam.motion); - } else if (position) { - cam.position = util.floatDelimArray(position.firstChild.nodeValue); - } - - if (cubicvr_isMotion(rotation)) { - if (!cam.motion) { - cam.motion = new Motion(); - } - cubicvr_nodeToMotion(rotation, enums.motion.ROT, cam.motion); - } else if (rotation) { - cam.rotation = util.floatDelimArray(rotation.firstChild.nodeValue); - } - - if (cubicvr_isMotion(fov)) { - if (!cam.motion) { - cam.motion = new Motion(); - } - cubicvr_nodeToMotion(fov, enums.motion.FOV, cam.motion); - } else if (fov) { - cam.fov = parseFloat(fov.firstChild.nodeValue); - } - - } - - - return sceneOut; -} - - -function RenderBuffer(width, height, depth_enabled) { - this.createBuffer(width, height, depth_enabled); -} - -RenderBuffer.prototype.createBuffer = function(width, height, depth_enabled) { - this.fbo = null; - this.depth = null; - this.texture = null; - this.width = parseInt(width, 10); - this.height = parseInt(height, 10); - - var w = this.sizeParam(width); - var h = this.sizeParam(height); - - var gl = GLCore.gl; - - this.fbo = gl.createFramebuffer(); - - if (depth_enabled) { - this.depth = gl.createRenderbuffer(); - } - - // configure fbo - gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo); - - if (depth_enabled) { - gl.bindRenderbuffer(gl.RENDERBUFFER, this.depth); - - if (navigator.appVersion.indexOf("Windows")!==-1 || 1) - { - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.depth); - } - else - { - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, w, h); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.depth); - } - } - - - // if (depth_enabled) { - // gl.bindRenderbuffer(gl.RENDERBUFFER, this.depth); - // gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h); - // } - - // GL_DEPTH_COMPONENT32 0x81A7 - // if (depth_enabled) { gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT, w, h); } - // if (depth_enabled) { - // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.depth); - // } - - - - // init texture - this.texture = new Texture(); - gl.bindTexture(gl.TEXTURE_2D, Textures[this.texture.tex_id]); - - // configure texture params - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - // clear buffer - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, Textures[this.texture.tex_id], 0); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); -}; - -RenderBuffer.prototype.destroyBuffer = function() { - var gl = GLCore.gl; - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - gl.deleteRenderbuffer(this.depth); - gl.deleteFramebuffer(this.fbo); - gl.deleteTexture(Textures[this.texture.tex_id]); - Textures[this.texture.tex_id] = null; -}; - -RenderBuffer.prototype.sizeParam = function(t) { - return t; - // var s = 32; - // - // while (t > s) s *= 2; - // - // return s; -}; - - -RenderBuffer.prototype.use = function() { - var gl = GLCore.gl; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo); - // if (this.depth !== null) { gl.bindRenderbuffer(gl.RENDERBUFFER, this.depth); } - // gl.viewport(0, 0, this.width, this.height); -}; - - - -function PostProcessFX(width, height) { - this.bloom = true; - - this.renderBuffer = new RenderBuffer(width, height, true); - this.blurBuffer = new RenderBuffer(width, height, false); - this.bloomBuffer = new RenderBuffer(parseInt(width / 6, 10), parseInt(height / 6, 10), false); - - this.copyShader = new Shader("attribute vec3 aVertex;\n" + "attribute vec2 aTex;\n" + "varying vec2 vTex;\n" + "void main(void)\n" + "{\n" + "vTex = aTex;\n" + "vec4 vPos = vec4(aVertex.xyz,1.0);\n" + "gl_Position = vPos;\n" + "}\n", "#ifdef GL_ES\nprecision highp float;\n#endif\n" + "uniform sampler2D srcTex;\n" + "varying vec2 vTex;\n" + "void main(void)\n" + "{\n" + "gl_FragColor = texture2D(srcTex, vTex);\n" + "}\n"); - - - this.copyShader.use(); - this.copyShader.addUVArray("aTex"); - this.copyShader.addVertexArray("aVertex"); - this.copyShader.addInt("srcTex", 0); - - this.fsQuad = this.makeFSQuad(width, height); - - this.bloomShader = new Shader("attribute vec3 aVertex;\n" + "attribute vec2 aTex;\n" + "varying vec2 vTex;\n" + "void main(void)\n" + "{\n" + "vTex = aTex;\n" + "vec4 vPos = vec4(aVertex.xyz,1.0);\n" + "gl_Position = vPos;\n" + "}\n", - - "#ifdef GL_ES\nprecision highp float;\n#endif\n" + "uniform sampler2D srcTex;\n" + "uniform vec3 texel_ofs;\n" + "varying vec2 vTex;\n" + "vec3 rangeValHDR(vec3 src)\n" + "{\n" + "return (src.r>0.90||src.g>0.90||src.b>0.90)?(src):vec3(0.0,0.0,0.0);\n" + "}\n" + "vec4 hdrSample(float rad)\n" + "{\n" + "vec3 accum;\n" + "float radb = rad*0.707106781;\n" + "accum = rangeValHDR(texture2D(srcTex, vec2(vTex.s+texel_ofs.x*rad, vTex.t)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s, vTex.t+texel_ofs.y*rad)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s-texel_ofs.x*rad, vTex.t)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s, vTex.t-texel_ofs.y*rad)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s+texel_ofs.x*radb, vTex.t+texel_ofs.y*radb)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s-texel_ofs.x*radb, vTex.t-texel_ofs.y*radb)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s+texel_ofs.x*radb, vTex.t-texel_ofs.y*radb)).rgb);\n" + "accum += rangeValHDR(texture2D(srcTex, vec2(vTex.s-texel_ofs.x*radb, vTex.t+texel_ofs.y*radb)).rgb);\n" + "accum /= 8.0;\n" + "return vec4(accum,1.0);\n" + "}\n" + "void main(void)\n" + "{\n" + "vec4 color;\n" + "color = hdrSample(2.0);\n" + "color += hdrSample(8.0);\n" + "color += hdrSample(12.0);\n" + "gl_FragColor = color/2.0;\n" + "}\n"); - - this.bloomShader.use(); - this.bloomShader.addUVArray("aTex"); - this.bloomShader.addVertexArray("aVertex"); - this.bloomShader.addInt("srcTex", 0); - this.bloomShader.addVector("texel_ofs"); - this.bloomShader.setVector("texel_ofs", [1.0 / this.renderBuffer.sizeParam(width), 1.0 / this.renderBuffer.sizeParam(height), 0]); - - this.fsQuadBloom = this.makeFSQuad(this.bloomBuffer.width, this.bloomBuffer.height); - - this.blurShader = new Shader("attribute vec3 aVertex;\n" + "attribute vec2 aTex;\n" + "varying vec2 vTex;\n" + "void main(void)\n" + "{\n" + "vTex = aTex;\n" + "vec4 vPos = vec4(aVertex.xyz,1.0);\n" + "gl_Position = vPos;\n" + "}\n", "#ifdef GL_ES\nprecision highp float;\n#endif\n" + "uniform sampler2D srcTex;\n" + "varying vec2 vTex;\n" + "uniform float opacity;\n" + "void main(void)\n" + "{\n" + "gl_FragColor = vec4(texture2D(srcTex, vTex).rgb, opacity);\n" + "}\n"); - - this.blurShader.use(); - this.blurShader.addUVArray("aTex"); - this.blurShader.addVertexArray("aVertex"); - this.blurShader.addInt("srcTex", 0); - this.blurShader.addFloat("opacity"); - this.blurOpacity = 0.1; - - - var gl = GLCore.gl; - - this.blurBuffer.use(); - gl.clear(gl.COLOR_BUFFER_BIT); - this.end(); -} - -PostProcessFX.prototype.resize = function(width, height) { - this.renderBuffer.destroyBuffer(); - this.blurBuffer.destroyBuffer(); - this.bloomBuffer.destroyBuffer(); - this.renderBuffer.createBuffer(width, height, true); - this.blurBuffer.createBuffer(width, height, false); - this.bloomBuffer.createBuffer(parseInt(width / 6, 10), parseInt(height / 6, 10), false); - - this.bloomShader.use(); - this.bloomShader.setVector("texel_ofs", [1.0 / this.renderBuffer.sizeParam(width), 1.0 / this.renderBuffer.sizeParam(height), 0]); - - this.destroyFSQuad(this.fsQuad); - this.fsQuad = this.makeFSQuad(width, height); - this.destroyFSQuad(this.fsQuadBloom); - this.fsQuadBloom = this.makeFSQuad(this.bloomBuffer.width, this.bloomBuffer.height); -}; - -PostProcessFX.prototype.begin = function() { - this.renderBuffer.use(); -}; - -PostProcessFX.prototype.end = function() { - var gl = GLCore.gl; - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - // if (this.depth !== null) { gl.bindRenderbuffer(gl.RENDERBUFFER, null); } -}; - -PostProcessFX.prototype.makeFSQuad = function(width, height) { - var gl = GLCore.gl; - var fsQuad = []; // intentional empty object - // var w = this.renderBuffer.sizeParam(width); - // var h = this.renderBuffer.sizeParam(height); - - // var uscale = (width / w); - // var vscale = (height / h); - - var uscale, vscale; - - uscale=vscale=1; - - // fsQuad.addPoint([[-1,-1,0],[1, -1, 0],[1, 1, 0],[-1, 1, 0]]); - // var faceNum = fsQuad.addFace([0,1,2,3]); - // fsQuad.faces[faceNum].setUV([[0, 0],[uscale, 0],[uscale, vscale],[0, vscale]]); - // fsQuad.triangulateQuads(); - // fsQuad.calcNormals(); - // fsQuad.compile(); - fsQuad.vbo_points = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0]); - fsQuad.vbo_uvs = new Float32Array([0, 0, uscale, 0, uscale, vscale, 0, vscale, 0, 0, uscale, vscale]); - - fsQuad.gl_points = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, fsQuad.gl_points); - gl.bufferData(gl.ARRAY_BUFFER, fsQuad.vbo_points, gl.STATIC_DRAW); - - fsQuad.gl_uvs = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, fsQuad.gl_uvs); - gl.bufferData(gl.ARRAY_BUFFER, fsQuad.vbo_uvs, gl.STATIC_DRAW); - - - return fsQuad; -}; - -PostProcessFX.prototype.destroyFSQuad = function(fsQuad) { - var gl = GLCore.gl; - - gl.deleteBuffer(fsQuad.gl_points); - gl.deleteBuffer(fsQuad.gl_uvs); -}; - -PostProcessFX.prototype.renderFSQuad = function(shader, fsq) { - var gl = GLCore.gl; - - shader.use(); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - - gl.bindBuffer(gl.ARRAY_BUFFER, fsq.gl_points); - gl.vertexAttribPointer(shader.aVertex, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribPointer(shader.aVertex); - gl.bindBuffer(gl.ARRAY_BUFFER, fsq.gl_uvs); - gl.vertexAttribPointer(shader.aTex, 2, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribPointer(shader.aTex); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - gl.drawArrays(gl.TRIANGLES, 0, 6); - -}; - -PostProcessFX.prototype.render = function() { - var gl = GLCore.gl; - - gl.disable(gl.DEPTH_TEST); - - this.renderBuffer.texture.use(gl.TEXTURE0); - this.copyShader.use(); - this.copyShader.setInt("srcTex", 0); - - this.renderFSQuad(this.copyShader, this.fsQuad); - - if (this.blur) { - this.renderBuffer.texture.use(gl.TEXTURE0); - this.blurShader.use(); - this.blurShader.setInt("srcTex", 0); - this.blurShader.setFloat("opacity", this.blurOpacity); - - this.blurBuffer.use(); - gl.enable(gl.BLEND); - gl.depthMask(0); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - this.renderFSQuad(this.blurShader, this.fsQuad); - gl.disable(gl.BLEND); - gl.depthMask(1); - gl.blendFunc(gl.ONE, gl.ONE); - this.end(); - - this.blurBuffer.texture.use(gl.TEXTURE0); - - this.blurShader.setFloat("opacity", 0.5); - - gl.enable(gl.BLEND); - gl.depthMask(0); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - - this.renderFSQuad(this.blurShader, this.fsQuad); - - gl.disable(gl.BLEND); - gl.depthMask(1); - gl.blendFunc(gl.ONE, gl.ONE); - } - - if (this.bloom) { - this.renderBuffer.texture.use(gl.TEXTURE0); - - gl.viewport(0, 0, this.bloomBuffer.width, this.bloomBuffer.height); - - this.bloomShader.use(); - this.bloomShader.setInt("srcTex", 0); - - this.bloomBuffer.use(); - this.renderFSQuad(this.bloomShader, this.fsQuad); - this.end(); - - this.bloomBuffer.texture.use(gl.TEXTURE0); - this.copyShader.use(); - this.copyShader.setInt("srcTex", 0); - - gl.viewport(0, 0, this.renderBuffer.width, this.renderBuffer.height); - - gl.enable(gl.BLEND); - gl.depthMask(0); - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - - this.renderFSQuad(this.copyShader, this.fsQuadBloom); - - gl.disable(gl.BLEND); - gl.depthMask(1); - gl.blendFunc(gl.ONE, gl.ONE); - - } - - gl.enable(gl.DEPTH_TEST); -}; - -/* - PostProcessShader: - - shaderInfo - { - enabled: enabled (default true) - shader_vertex: id or url for vertex shader - shader_fragment: id or url for fragment shader - outputMode: method of output for this shader - init: function to perform to initialize shader - onresize: function to perform on resize; params ( shader, width, height ) - onupdate: function to perform on update; params ( shader ) - outputDivisor: use custom output buffer size, divisor of (outputDivisor) eg. 1 (default) = 1024x768, 2 = 512x384, 3 = 256x192 - } - - */ - -var postProcessDivisorBuffers = []; -var postProcessDivisorQuads = []; - -function PostProcessShader(shaderInfo) { - if (shaderInfo.shader_vertex === undef) { - return null; - } - if (shaderInfo.shader_fragment === undef) { - return null; - } - - this.outputMode = (shaderInfo.outputMode === undef) ? enums.post.output.REPLACE : shaderInfo.outputMode; - this.onresize = (shaderInfo.onresize === undef) ? null : shaderInfo.onresize; - this.onupdate = (shaderInfo.onupdate === undef) ? null : shaderInfo.onupdate; - this.init = (shaderInfo.init === undef) ? null : shaderInfo.init; - this.enabled = (shaderInfo.enabled === undef) ? true : shaderInfo.enabled; - this.outputDivisor = (shaderInfo.outputDivisor === undef) ? 1 : shaderInfo.outputDivisor; - - this.shader = new Shader(shaderInfo.shader_vertex, shaderInfo.shader_fragment); - this.shader.use(); - - // set defaults - this.shader.addUVArray("aTex"); - this.shader.addVertexArray("aVertex"); - this.shader.addInt("srcTex", 0); - this.shader.addInt("captureTex", 1); - this.shader.addVector("texel"); - - if (this.init !== null) { - this.init(this.shader); - } -} - -/* New post-process shader chain -- to replace postProcessFX */ - -function PostProcessChain(width, height, accum) { - var gl = GLCore.gl; - - this.width = width; - this.height = height; - this.accum = (accum === undef)?false:true; - this.vTexel = [1.0 / this.width, 1.0 / this.height, 0]; - - // buffers - this.captureBuffer = new RenderBuffer(width, height, true); - this.bufferA = new RenderBuffer(width, height, false); - this.bufferB = new RenderBuffer(width, height, false); - this.bufferC = new RenderBuffer(width, height, false); - - this.accumOpacity = 1.0; - this.accumIntensity = 0.3; - - if (this.accum) { - this.accumBuffer = new RenderBuffer(width, height, false); - this.accumBuffer.use(); - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - this.blur_shader = new PostProcessShader({ - shader_vertex: ["attribute vec3 aVertex;", - "attribute vec2 aTex;", - "varying vec2 vTex;", - "void main(void)", - "{", - "vTex = aTex;", - "vec4 vPos = vec4(aVertex.xyz,1.0);", - "gl_Position = vPos;", - "}"].join("\n"), - shader_fragment: ["#ifdef GL_ES", - "precision highp float;", - "#endif", - "uniform sampler2D srcTex;", - "varying vec2 vTex;", - "uniform float opacity;", - "void main(void)", - "{ gl_FragColor = vec4(texture2D(srcTex, vTex).rgb, opacity);", - "}"].join("\n"), - init: function(shader) { - shader.addFloat("opacity"); - shader.setFloat("opacity",1.0); - }}); - } - - this.bufferA.use(); - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - this.bufferB.use(); - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - this.end(); - - // quad - this.fsQuad = this.makeFSQuad(this.width, this.height); - - this.shaders = []; - - this.copy_shader = new PostProcessShader({ - shader_vertex: ["attribute vec3 aVertex;", - "attribute vec2 aTex;", - "varying vec2 vTex;", - "void main(void) {", - "vTex = aTex;", - "vec4 vPos = vec4(aVertex.xyz,1.0);", - "gl_Position = vPos;", - "}"].join("\n"), - shader_fragment: [ - "#ifdef GL_ES", - "precision highp float;", - "#endif", - "uniform sampler2D srcTex;", - "varying vec2 vTex;", - "void main(void) {", - "gl_FragColor = texture2D(srcTex, vTex);", - "}"].join("\n") - }); - - this.resize(width, height); -} - -PostProcessChain.prototype.setBlurOpacity = function (opacity) -{ - this.accumOpacity = opacity; -} - -PostProcessChain.prototype.setBlurIntensity = function (intensity) -{ - this.accumIntensity = intensity; -} - - -PostProcessChain.prototype.makeFSQuad = makeFSQuad = function(width, height) { - var gl = GLCore.gl; - var fsQuad = []; // intentional empty object - var w = width; - var h = height; - - var uscale = (width / w); - var vscale = (height / h); - - fsQuad.vbo_points = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0]); - fsQuad.vbo_uvs = new Float32Array([0, 0, uscale, 0, uscale, vscale, 0, vscale, 0, 0, uscale, vscale]); - - fsQuad.gl_points = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, fsQuad.gl_points); - gl.bufferData(gl.ARRAY_BUFFER, fsQuad.vbo_points, gl.STATIC_DRAW); - - fsQuad.gl_uvs = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, fsQuad.gl_uvs); - gl.bufferData(gl.ARRAY_BUFFER, fsQuad.vbo_uvs, gl.STATIC_DRAW); - - return fsQuad; -}; - -PostProcessChain.prototype.destroyFSQuad = destroyFSQuad = function(fsQuad) { - var gl = GLCore.gl; - - gl.deleteBuffer(fsQuad.gl_points); - gl.deleteBuffer(fsQuad.gl_uvs); -}; - -PostProcessChain.prototype.renderFSQuad = renderFSQuad = function(shader, fsq) { - var gl = GLCore.gl; - - shader.use(); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - - gl.bindBuffer(gl.ARRAY_BUFFER, fsq.gl_points); - gl.vertexAttribPointer(shader.aVertex, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(shader.aVertex); - gl.bindBuffer(gl.ARRAY_BUFFER, fsq.gl_uvs); - gl.vertexAttribPointer(shader.aTex, 2, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(shader.aTex); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - gl.drawArrays(gl.TRIANGLES, 0, 6); - -}; - - -PostProcessChain.prototype.addShader = function(shader) { - this.shaders[this.shaders.length] = shader; - shader.shader.use(); - shader.shader.setVector("texel", this.vTexel); - - if (shader.outputDivisor && shader.outputDivisor != 1) - { - if (postProcessDivisorBuffers[shader.outputDivisor] === undef) - - var divw = parseInt(this.width/shader.outputDivisor); - var divh = parseInt(this.height/shader.outputDivisor); - - postProcessDivisorBuffers[shader.outputDivisor] = new RenderBuffer(divw, divh, false); - postProcessDivisorQuads[shader.outputDivisor] = this.makeFSQuad(divw, divh); - - } -}; - -PostProcessChain.prototype.resize = function(width, height) { - var gl = GLCore.gl; - - this.width = width; - this.height = height; - - this.vTexel = [1.0 / this.width, 1.0 / this.height, 0]; - - this.captureBuffer.destroyBuffer(); - this.captureBuffer.createBuffer(this.width, this.height, true); - - this.bufferA.destroyBuffer(); - this.bufferA.createBuffer(this.width, this.height, false); - - this.bufferB.destroyBuffer(); - this.bufferB.createBuffer(this.width, this.height, false); - - this.bufferC.destroyBuffer(); - this.bufferC.createBuffer(this.width, this.height, false); - - if (this.accum) { - this.accumBuffer.destroyBuffer(); - this.accumBuffer.createBuffer(this.width, this.height, false); - this.accumBuffer.use(); - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - for (var p in postProcessDivisorBuffers) - { - var divw = parseInt(this.width/p); - var divh = parseInt(this.height/p); - - postProcessDivisorBuffers[p].destroyBuffer(); - postProcessDivisorBuffers[p].createBuffer(divw, divh, false); - - this.destroyFSQuad(postProcessDivisorQuads[p]); - postProcessDivisorQuads[p] = this.makeFSQuad(divw, divh); - } - - this.inputBuffer = this.bufferA; - this.outputBuffer = this.bufferB; - - for (var i = 0, iMax = this.shaders.length; i < iMax; i++) { - this.shaders[i].shader.use(); - this.shaders[i].shader.setVector("texel", this.vTexel); - if (this.shaders[i].onresize !== null) { - this.shaders[i].onresize(this.shaders[i].shader, this.width, this.height); - } - } - - this.destroyFSQuad(this.fsQuad); - this.fsQuad = this.makeFSQuad(this.width, this.height); -}; - -PostProcessChain.prototype.swap = function() { - var t = this.inputBuffer; - - this.inputBuffer = this.outputBuffer; - this.outputBuffer = t; -}; - -PostProcessChain.prototype.begin = function() { - this.captureBuffer.use(); -}; - -PostProcessChain.prototype.end = function() { - var gl = GLCore.gl; - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); -}; - -PostProcessChain.prototype.render = function() { - var gl = GLCore.gl; - - var initBuffer = null; - - this.captureBuffer.texture.use(gl.TEXTURE1); - - this.outputBuffer.use(); - this.captureBuffer.texture.use(gl.TEXTURE0); - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - this.end(); - - var c = 0; - for (var i = 0, iMax = this.shaders.length; i < iMax; i++) { - var s = this.shaders[i]; - if (!s.enabled) { - continue; - } - this.swap(); - this.inputBuffer.texture.use(gl.TEXTURE0); - - var o_mode = s.outputMode; - //switch (s.outputMode) { - if (o_mode === enums.post.output.REPLACE) { - //case enums.post.output.REPLACE: - if (s.outputDivisor !== 1) { - postProcessDivisorBuffers[s.outputDivisor].use(); - } - else { - this.outputBuffer.use(); - } //if - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - //break; - } - else if (o_mode === enums.post.output.ADD || o_mode === enums.post.output.BLEND) { - //case enums.post.output.ADD: - //case enums.post.output.BLEND: - if (s.outputDivisor !== 1) { - postProcessDivisorBuffers[s.outputDivisor].use(); - } - else { - this.bufferC.use(); - } //if - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - //break; - } //if - - if (s.onupdate !== null) { - s.shader.use(); - s.onupdate(s.shader); - } //if - - if (s.outputDivisor !== 1) { - gl.viewport(0, 0, postProcessDivisorBuffers[s.outputDivisor].width, postProcessDivisorBuffers[s.outputDivisor].height); - - this.renderFSQuad(s.shader, postProcessDivisorQuads[s.outputDivisor]); - - if (s.outputMode === enums.post.output.REPLACE) { - this.outputBuffer.use(); - - postProcessDivisorBuffers[s.outputDivisor].texture.use(gl.TEXTURE0); - - gl.viewport(0, 0, this.width, this.height); - - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - } - else { - gl.viewport(0, 0, this.width, this.height); - } //if - } - else { - this.renderFSQuad(s.shader, this.fsQuad); - } //if - - //switch (s.outputMode) { - - //case enums.post.output.REPLACE: - // break; - if (o_mode === enums.post.output.BLEND) { - //case enums.post.output.BLEND: - this.swap(); - this.outputBuffer.use(); - - gl.enable(gl.BLEND); - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - this.inputBuffer.texture.use(gl.TEXTURE0); - - if (s.outputDivisor !== 1) { - postProcessDivisorBuffers[s.outputDivisor].texture.use(gl.TEXTURE0); - } - else { - this.bufferC.texture.use(gl.TEXTURE0); - } //if - - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - - gl.disable(gl.BLEND); - //break; - } - else if (o_mode === enums.post.output.ADD) { - //case enums.post.output.ADD: - this.swap(); - this.outputBuffer.use(); - - gl.enable(gl.BLEND); - gl.blendFunc(gl.ONE, gl.ONE); - - if (s.outputDivisor !== 1) { - postProcessDivisorBuffers[s.outputDivisor].texture.use(gl.TEXTURE0); - } - else { - this.bufferC.texture.use(gl.TEXTURE0); - } //if - - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - - gl.disable(gl.BLEND); - //break; - } //if - - this.end(); - c++; - } //for - - if (c === 0) { - this.captureBuffer.texture.use(gl.TEXTURE0); - } else { - this.outputBuffer.texture.use(gl.TEXTURE0); - } //if - - if (this.accum && this.accumOpacity !== 1.0) - { - this.blur_shader.shader.use(); - this.blur_shader.shader.setFloat("opacity",this.accumOpacity); - - this.accumBuffer.use(); - - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); - - this.renderFSQuad(this.blur_shader.shader, this.fsQuad); - - this.end(); - - gl.disable(gl.BLEND); - - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); - - this.blur_shader.shader.use(); - this.blur_shader.shader.setFloat("opacity",this.accumIntensity); - - this.accumBuffer.texture.use(gl.TEXTURE0); - - this.renderFSQuad(this.blur_shader.shader, this.fsQuad); - - gl.disable(gl.BLEND); - } - else - { - this.renderFSQuad(this.copy_shader.shader, this.fsQuad); - } - -}; - - - - function NormalMapGen(inTex,width,height) - { - var gl = GLCore.gl; - - this.width = width; - this.height = height; - this.srcTex = inTex; - this.outTex = new RenderBuffer(width,height); - - var tw = width, th = height; - - var isPOT = true; - - if (tw===1||th===1) { - isPOT = false; - } else { - if (tw !== 1) { while ((tw % 2) === 0) { tw /= 2; } } - if (th !== 1) { while ((th % 2) === 0) { th /= 2; } } - if (tw > 1) { isPOT = false; } - if (th > 1) { isPOT = false; } - } - - var vTexel = [1.0/width,1.0/height,0]; - - // buffers - this.outputBuffer = new RenderBuffer(width,height,false); - - // quads - this.fsQuad = PostProcessChain.prototype.makeFSQuad(width,height); - - var vs = ["attribute vec3 aVertex;", - "attribute vec2 aTex;", - "varying vec2 vTex;", - "void main(void)", - "{", - " vTex = aTex;", - " vec4 vPos = vec4(aVertex.xyz,1.0);", - " gl_Position = vPos;", - "}"].join("\n"); - - - // simple convolution test shader - shaderNMap = new Shader(vs, - ["#ifdef GL_ES", - "precision highp float;", - "#endif", - "uniform sampler2D srcTex;", - "varying vec2 vTex;", - "uniform vec3 texel;", - "void main(void)", - "{", - " vec3 color;", - " color.r = (texture2D(srcTex,vTex + vec2(texel.x,0)).r-texture2D(srcTex,vTex + vec2(-texel.x,0)).r)/2.0 + 0.5;", - " color.g = (texture2D(srcTex,vTex + vec2(0,-texel.y)).r-texture2D(srcTex,vTex + vec2(0,texel.y)).r)/2.0 + 0.5;", - " color.b = 1.0;", - " gl_FragColor.rgb = color;", - " gl_FragColor.a = 1.0;", - "}"].join("\n")); - - shaderNMap.use(); - shaderNMap.addUVArray("aTex"); - shaderNMap.addVertexArray("aVertex"); - shaderNMap.addInt("srcTex",0); - shaderNMap.addVector("texel"); - shaderNMap.setVector("texel",vTexel); - - this.shaderNorm = shaderNMap; - - // bind functions to "subclass" a texture - this.setFilter=this.outputBuffer.texture.setFilter; - this.clear=this.outputBuffer.texture.clear; - this.use=this.outputBuffer.texture.use; - this.tex_id=this.outputBuffer.texture.tex_id; - this.filterType=this.outputBuffer.texture.filterType; - - this.outTex.use(gl.TEXTURE0); - // - // if (!isPOT) { - // this.setFilter(enums.texture.filter.LINEAR); - // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - // } else { - this.setFilter(enums.texture.filter.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) - // } - - } - - - - NormalMapGen.prototype.update = function() - { - var gl = GLCore.gl; - - var dims = gl.getParameter(gl.VIEWPORT); - - this.outputBuffer.use(); - - gl.viewport(0, 0, this.width, this.height); - - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - this.srcTex.use(gl.TEXTURE0); - - PostProcessChain.prototype.renderFSQuad(this.shaderNorm,this.fsQuad); // copy the output buffer to the screen via fullscreen quad - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.viewport(dims[0], dims[1], dims[2], dims[3]); - } - - - - function DeferredBin() - { - this.meshBin = {}; - this.imageBin = {}; - - this.meshMap = {}; - this.imageMap = {}; - - this.imageBinPtr = {}; - this.meshBinPtr = {}; - } - - DeferredBin.prototype.addMesh = function(binId,meshId,meshObj) { - if (this.meshBin[binId] === undef) - { - this.meshBin[binId] = []; - if (this.meshBinPtr[binId]===undef) { - this.meshBinPtr[binId] = 0; - } - } - - if (this.meshMap[meshId] === undef) - { - this.meshMap[meshId] = meshObj; - this.meshBin[binId].push(meshObj); - } - } - - DeferredBin.prototype.addImage = function(binId,imageId,imageObj) { - if (this.imageBin[binId] === undef) - { - this.imageBin[binId] = []; - if (this.imageBinPtr[binId]===undef) { - this.imageBinPtr[binId] = 0; - } - } - - if (this.imageMap[imageId] === undef) - { - this.imageMap[imageId] = imageObj; - this.imageBin[binId].push(imageObj); - } - }; - - DeferredBin.prototype.getMeshes = function(binId) { - return this.meshBin[binId]; - }; - - DeferredBin.prototype.getImages = function(binId) { - return this.imageBin[binId]; - }; - - DeferredBin.prototype.rewindMeshes = function(binId) { - this.meshBinPtr[binId] = 0; - }; - - DeferredBin.prototype.rewindImages = function(binId) { - this.imageBinPtr[binId] = 0; - }; - - DeferredBin.prototype.getNextMesh = function(binId) { - var cBin = this.meshBinPtr[binId]; - - if (cBin<this.meshBin[binId].length) - { - this.meshBinPtr[binId]++; - return this.meshBin[binId][cBin]; - } - - return null; - }; - - DeferredBin.prototype.loadNextMesh = function(binId) - { - var mesh = this.getNextMesh(binId); - - if (mesh !== null) - { - if (mesh.compiled===null) - { - mesh.triangulateQuads(); - mesh.compile(); - mesh.clean(); - } - - return true; - } - - return false; - }; - - DeferredBin.prototype.isMeshBinEmpty = function(binId) { - //console.log('isMeshBinEmpty[' + binId + '] = ' + (this.meshBinPtr[binId] === this.meshBin[binId].length) + ' meshBinPtr = ' + this.meshBinPtr[binId] + ' meshBin.length = ' + this.meshBin[binId].length); - return this.meshBinPtr[binId] === this.meshBin[binId].length; - }; - - DeferredBin.prototype.loadNextImage = function(binId) - { - var img = this.getNextImage(binId); - - if (img !== null) { - img.src = img.deferredSrc; -// return true; - } - -// return false; - }; - - - DeferredBin.prototype.getNextImage = function(binId) { - var cBin = this.imageBinPtr[binId]; - - if (cBin<this.imageBin[binId].length) - { - this.imageBinPtr[binId]++; - return this.imageBin[binId][cBin]; - } - - return null; - }; - - DeferredBin.prototype.isImageBinEmpty = function(binId) { - //console.log('isImageBinEmpty[' + binId + '] = ' + (this.imageBinPtr[binId] === this.imageBin[binId].length)); - return this.imageBinPtr[binId] === this.imageBin[binId].length ; - }; - -function cubicvr_loadColladaWorker(meshUrl, prefix, callback, deferred_bin) { - var worker; - try { - worker = new Worker(SCRIPT_LOCATION + 'collada.js'); - } - catch(e) { - throw new Error("Can't find collada.js"); - } //try - - var materials_map = []; - var meshes_map = []; - - worker.onmessage = function(e) { - - function copyObjectFromJSON(json, obj) { - for (var i in json) { - obj[i] = json[i]; - } //for - } //new_obj - - var message = e.data.message; - if (message == 'materials') { - var mats = JSON.parse(e.data.data); - for (var i=0, maxI=mats.length; i<maxI; ++i) { - var new_mat = new Material(mats[i].name); - var mat_id = new_mat.material_id; - copyObjectFromJSON(mats[i], new_mat); - new_mat.material_id = mat_id; - materials_map[mats[i].material_id] = mat_id; - for (var j=0, maxJ=mats[i].textures.length; j<maxJ; ++j) { - var dt = mats[i].textures[j]; - if (dt) { - var stored_tex = Texture_ref[dt.img_path]; - - if (stored_tex === undefined) { - var t = new Texture(dt.img_path, dt.filter_type, deferred_bin, meshUrl); - new_mat.textures[j] = t; - } - else { - new_mat.textures[j] = Textures_obj[stored_tex]; - } //if - } - else { - new_mat.textures[j] = 0; - } //if - } //for - } //for - } - else if (message == 'scene') { - var scene = JSON.parse(e.data.data); - - function reassembleMotion(obj) { - //reassemble linked-list for sceneObject motion envelope keys - if (obj.motion) { - var co = obj.motion.controllers; - var new_controllers = []; - for (var j=0, maxJ=co.length; j<maxJ; ++j) { - var con = co[j]; - if (!con) { - co[j] = undefined; - continue; - } - var new_con = []; - for (var k=0, maxK=con.length; k<maxK; ++k) { - var env = con[k]; - if (!env) { - con[k] = undefined; - continue; - } - var keys = env.keys[0]; - if (env.keys.length > 1) { - keys.prev = null; - keys.next = env.keys[1]; - keys = env.keys[1]; - } //if - for (var keyI=1,maxKeyI=env.keys.length-1; keyI<maxKeyI; ++keyI) { - keys.prev = env.keys[keyI-1]; - keys.next = env.keys[keyI+1]; - keys = env.keys[keyI+1]; - } //for keyI - if (env.keys.length > 1) { - keys = env.keys[env.keys.length-1]; - keys.prev = env.keys[env.keys.length-2]; - keys.next = null; - } //if - env.firstKey = env.keys[0]; - env.lastKey = env.keys[env.keys.length-1]; - env.keys = env.firstKey; - - var envelope = new Envelope(); - copyObjectFromJSON(env, envelope); - new_con[k]=envelope; - } //for k - new_controllers[j] = new_con; - } //for j - obj.motion.controllers = new_controllers; - var motion = new Motion(); - copyObjectFromJSON(obj.motion, motion); - obj.motion = motion; - } //if - } //reassembleMotion - - for (var i=0, maxI=scene.sceneObjects.length; i<maxI; ++i) { - var so = scene.sceneObjects[i]; - - if (so.obj !== null) { - - } //if - - if (so.reassembled === undefined) { - reassembleMotion(so); - so.reassembled = true; - } //if - - function createSceneObject(scene_obj) { - var sceneObject = new SceneObject(); - copyObjectFromJSON(scene_obj, sceneObject); - if (scene_obj.obj !== null) { - var stored_mesh = meshes_map[scene_obj.obj.id]; - if (stored_mesh === undefined) { - var mesh = new Mesh(); - copyObjectFromJSON(scene_obj.obj, mesh); - sceneObject.obj = mesh; - meshes_map[scene_obj.obj.id] = mesh; - if (deferred_bin) { - if (mesh.points.length > 0) { - deferred_bin.addMesh(meshUrl,meshUrl+":"+mesh.id,mesh) - for (var f=0,maxF=mesh.faces.length; f<maxF; ++f) { - var face = mesh.faces[f]; - var m_index = face.material; - var mapped = materials_map[m_index]; - if (mapped !== undefined) { - face.material = materials_map[m_index]; - } - else { - face.material = 0; - } //if - } //for - } //if - } - else { - sceneObject.obj.triangulateQuads(); - sceneObject.obj.calcNormals(); - sceneObject.obj.compile(); - sceneObject.obj.clean(); - } //if - } - else { - sceneObject.obj = stored_mesh; - } //if - } //if - - sceneObject.trans = new Transform(); - - if (scene_obj.children && scene_obj.children.length > 0) { - sceneObject.children = []; - createChildren(scene_obj, sceneObject); - } //if - - return sceneObject; - } //createSceneObject - - function createChildren(scene_obj, sceneObject) { - if (scene_obj.children) { - for (var j=0, maxJ=scene_obj.children.length; j<maxJ; ++j) { - var child = createSceneObject(scene_obj.children[j]); - sceneObject.bindChild(child); - } //for - } //if - } //createChildren - - scene.sceneObjects[i] = createSceneObject(so); - - } //for i - - var new_scene = new Scene(); - // place parsed scene elements into new scene (since parse scene has no prototype) - var camera = new_scene.camera; - var camera_transform = camera.transform; - copyObjectFromJSON(scene.camera, camera); - copyObjectFromJSON(scene.camera.transform, camera_transform); - reassembleMotion(camera); - new_scene.camera = camera; - new_scene.camera.transform = camera_transform; - new_scene.camera.frustum = new Frustum(); - - for (var i=0, maxI=scene.sceneObjects.length; i<maxI; ++i) { - var o = scene.sceneObjects[i]; - new_scene.bindSceneObject(o); - try { - o.getAABB(); - } - catch(e) { - //console.log(o); - } //try - - } //for - - for (var i=0, maxI=scene.lights.length; i<maxI; ++i) { - var l = new Light(); - copyObjectFromJSON(scene.lights[i], l); - l.trans = new Transform(); - reassembleMotion(l); - new_scene.bindLight(l); - } //for - - callback(new_scene); - } - else { - console.log("message from collada worker:", e.data.message); - } //if - } //onmessage - - worker.onerror = function(e) { - console.log("error from collada worker:", e.message); - } //onerror - - worker.postMessage({message:'start', params: {meshUrl: meshUrl, prefix: prefix, rootDir: SCRIPT_LOCATION}}); -} //cubicvr_loadColladaWorker - - -function xml2badgerfish(xmlDoc) { - var jsonData = {}; - var nodeStack = []; - - var i, iMax, iMin; - - var n = xmlDoc; - var j = jsonData; - var cn, tn; - var regEmpty = /^\s+|\s+$/g; - - xmlDoc.jsonParent = j; - nodeStack.push(xmlDoc); - - while (nodeStack.length) { - var n = nodeStack.pop(); - var tagGroup = null; - - j = n.jsonParent; - - for (i = 0, iMax = n.childNodes.length; i < iMax; i++) { - cn = n.childNodes[i]; - tn = cn.tagName; - - if (tn !== undef) { - tagGroup = tagGroup || {}; - tagGroup[tn] = tagGroup[tn] || 0; - tagGroup[tn]++; - } - } - - if (n.attributes) if (n.attributes.length) { - for (i = 0, iMax = n.attributes.length; i < iMax; i++) { - var att = n.attributes[i]; - - j["@" + att.name] = att.value; - } - } - - for (i = 0, iMax = n.childNodes.length; i < iMax; i++) { - cn = n.childNodes[i]; - tn = cn.tagName; - - if (cn.nodeType === 1) { - if (tagGroup[tn] > 1) { - j[tn] = j[tn] || []; - j[tn].push({}); - cn.jsonParent = j[tn][j[tn].length - 1]; - } else { - j[tn] = j[tn] || {}; - cn.jsonParent = j[tn]; - } - nodeStack.push(cn); - } else if (cn.nodeType === 3) { - if (cn.nodeValue.replace(regEmpty, "") !== "") { - j.$ = j.$ || ""; - j.$ += cn.nodeValue; - } - } - } - } - - return jsonData; -} - -var collada_tools = { - fixuaxis: function (up_axis, v) { - if (up_axis === 0) { // untested - return [v[1], v[0], v[2]]; - } else if (up_axis === 1) { - return v; - } else if (up_axis === 2) { - return [v[0], v[2], -v[1]]; - } - }, - fixscaleaxis: function (up_axis, v) { - if (up_axis === 0) { // untested - return [v[1], v[0], v[2]]; - } else if (up_axis === 1) { - return v; - } else if (up_axis === 2) { - return [v[0], v[2], v[1]]; - } - }, - fixukaxis: function (up_axis, mot, chan, val) { - // if (mot === enums.motion.POS && chan === enums.motion.Y && up_axis === enums.motion.Z) return -val; - if (mot === enums.motion.POS && chan === enums.motion.Z && up_axis === enums.motion.Z) { - return -val; - } - return val; - }, - getAllOf: function (root_node, leaf_name) { - var nStack = [root_node]; - var results = []; - - while (nStack.length) { - var n = nStack.pop(); - - for (var i in n) { - if (!n.hasOwnProperty(i)) continue; - - if (i === leaf_name) { - if (n[i].length) { - for (var p = 0, pMax = n[i].length; p < pMax; p++) { - results.push(n[i][p]); - } - } else { - results.push(n[i]); - } - } - if (typeof(n[i]) == 'object') { - if (n[i].length) { - for (var p = 0, pMax = n[i].length; p < pMax; p++) { - nStack.push(n[i][p]); - } - } else { - nStack.push(n[i]); - } - } - } - } - - return results; - }, - quaternionFilterZYYZ: function (rot, ofs) { - var r = rot; - var temp_q = new Quaternion(); - - if (ofs !== undef) { - r = vec3.add(rot, ofs); - } - - temp_q.fromEuler(r[0], r[2], -r[1]); - - return temp_q.toEuler(); - }, - cl_getInitalTransform: function (up_axis, scene_node) { - var retObj = { - position: [0, 0, 0], - rotation: [0, 0, 0], - scale: [1, 1, 1] - }; - - var translate = scene_node.translate; - var rotate = scene_node.rotate; - var scale = scene_node.scale; - - if (translate) { - retObj.position = collada_tools.fixuaxis(up_axis, util.floatDelimArray(translate.$, " ")); - } - - - if (rotate) { - for (var r = 0, rMax = rotate.length; r < rMax; r++) { - var cl_rot = rotate[r]; - - var rType = cl_rot["@sid"]; - - var rVal = util.floatDelimArray(cl_rot.$, " "); - - if (rType == "rotateX" || rType == "rotationX") { - retObj.rotation[0] = rVal[3]; - } else if (rType == "rotateY" || rType == "rotationY") { - retObj.rotation[1] = rVal[3]; - } else if (rType == "rotateZ" || rType == "rotationZ") { - retObj.rotation[2] = rVal[3]; - } //if - } //for - } //if - if (scale) { - retObj.scale = collada_tools.fixscaleaxis(up_axis, util.floatDelimArray(scale.$, " ")); - } - - // var cl_matrix = scene_node.getElementsByTagName("matrix"); - // - // if (cl_matrix.length) - // { - // console.log(util.collectTextNode(cl_matrix[0])); - // } - return retObj; - } -}; - - - -function cubicvr_parseCollada(meshUrl, prefix, deferred_bin) { - // if (MeshPool[meshUrl] !== undef) return MeshPool[meshUrl]; - var obj = new Mesh(); - var scene = new Scene(); - var cl = util.getXML(meshUrl); - var tech; - var sourceId; - var materialRef, nameRef, nFace, meshName; - - var norm, vert, uv, mapLen, computedLen; - - var i, iCount, iMax, iMod, mCount, mMax, k, kMax, cCount, cMax, sCount, sMax, pCount, pMax, j, jMax; - - var cl_source = xml2badgerfish(cl); - - cl = null; - - if (!cl_source.COLLADA) { - throw new Error(meshUrl + " does not appear to be a valid COLLADA file."); - } - - cl_source = cl_source.COLLADA; - - var clib = { - up_axis: 1, - images: [], - effects: [], - materials: [], - meshes: [], - scenes: [], - lights: [], - cameras: [], - animations: [], - }; - - - // var up_axis = 1; // Y - if (cl_source.asset) { - var sAxis = cl_source.asset.up_axis.$; - if (sAxis === "X_UP") { - clib.up_axis = 0; - } else if (sAxis === "Y_UP") { - clib.up_axis = 1; - } else if (sAxis === "Z_UP") { - clib.up_axis = 2; - } - } - - var up_axis = clib.up_axis; - - if (cl_source.library_images) if (cl_source.library_images.image.length) { - var cl_images = cl_source.library_images.image; - for (var imgCount = 0, imgCountMax = cl_images.length; imgCount < imgCountMax; imgCount++) { - var cl_img = cl_images[imgCount]; - var imageId = cl_img["@id"]; - var imageName = cl_img["@name"]; - var cl_imgsrc = cl_img.init_from; - - if (cl_imgsrc.$) { - var imageSource = cl_imgsrc.$; - - if (prefix !== undef && (imageSource.lastIndexOf("/") !== -1)) { - imageSource = imageSource.substr(imageSource.lastIndexOf("/") + 1); - } - if (prefix !== undef && (imageSource.lastIndexOf("\\") !== -1)) { - imageSource = imageSource.substr(imageSource.lastIndexOf("\\") + 1); - } - - // console.log("Image reference: "+imageSource+" @"+imageId+":"+imageName); - clib.images[imageId] = { - source: imageSource, - id: imageId, - name: imageName - }; - } - } - } - - // Effects - var effectId; - var effectCount, effectMax; - var tCount, tMax, inpCount, inpMax; - var cl_params, cl_inputs, cl_input, cl_inputmap, cl_samplers, cl_camera, cl_cameras, cl_scene; - var ofs; - - - if (cl_source.library_effects) { - var cl_effects = cl_source.library_effects.effect; - - if (cl_effects && !cl_effects.length) cl_effects = [cl_effects]; - - for (effectCount = 0, effectMax = cl_effects.length; effectCount < effectMax; effectCount++) { - var cl_effect = cl_effects[effectCount]; - - effectId = cl_effect["@id"]; - - var effect = {}; - - effect.id = effectId; - - effect.surfaces = []; - effect.samplers = []; - - cl_params = cl_effect.profile_COMMON.newparam; - - if (cl_params && !cl_params.length) { - cl_params = [cl_params]; - }; - - var params = []; - - var cl_init; - - if (cl_params) { - for (pCount = 0, pMax = cl_params.length; pCount < pMax; pCount++) { - var cl_param = cl_params[pCount]; - - var paramId = cl_param["@sid"]; - - if (cl_param.surface) { - effect.surfaces[paramId] = {}; - - var initFrom = cl_param.surface.init_from.$; - - if (typeof(clib.images[initFrom]) === 'object') { - - var img_path = prefix + "/" + clib.images[initFrom].source; - effect.surfaces[paramId].source = img_path; - // console.log(prefix+"/"+clib.images[initFrom].source); - } - } else if (cl_param.sampler2D) { - effect.samplers[paramId] = {}; - - effect.samplers[paramId].source = cl_param.sampler2D.source.$; - - if (cl_param.sampler2D.minfilter) { - effect.samplers[paramId].minfilter = cl_param.sampler2D.minfilter.$; - } - - if (cl_param.sampler2D.magfilter) { - effect.samplers[paramId].magfiter = cl_param.sampler2D.magfilter.$; - } - } - - } - } - - var cl_technique = cl_effect.profile_COMMON.technique; - - if (cl_technique && !cl_technique.length) cl_technique = [cl_technique]; - - var getColorNode = (function () { - return function (n) { - var el = n.color; - if (!el) { - return false; - } - - var cn = n.color; - var ar = cn ? util.floatDelimArray(cn.$, " ") : false; - - return ar; - }; - }()); - - var getFloatNode = (function () { - return function (n) { - var el = n.float; - if (!el) { - return false; - } - - var cn = n.float; - cn = cn ? parseFloat(cn.$) : 0; - - return cn; - }; - }()); - - var getTextureNode = (function () { - return function (n) { - var el = n.texture; - if (!el) { - return false; - } - - var cn = n.texture["@texture"]; - - return cn; - }; - }()); - - // effect.material = new Material(effectId); - effect.material = { - textures_ref: [] - } - - for (tCount = 0, tMax = cl_technique.length; tCount < tMax; tCount++) { - // if (cl_technique[tCount].getAttribute("sid") === 'common') { - tech = cl_technique[tCount].blinn; - - if (!tech) { - tech = cl_technique[tCount].phong; - } - if (!tech) { - tech = cl_technique[tCount].lambert; - } - - if (tech) { - // for (var eCount = 0, eMax = tech[0].childNodes.length; eCount < eMax; eCount++) { - // var node = tech[0].childNodes[eCount]; - for (var tagName in tech) { - var node = tech[tagName]; - - var c = getColorNode(node); - var f = getFloatNode(node); - var t = getTextureNode(node); - - if (c !== false) { - if (c.length > 3) { - c.pop(); - } - } - - if (tagName == "emission") { - if (c !== false) { - effect.material.ambient = c; - } - } else if (tagName == "ambient") {} else if (tagName == "diffuse") { - if (c !== false) { - effect.material.color = c; - } - } else if (tagName == "specular") { - if (c !== false) { - effect.material.specular = c; - } - } else if (tagName == "shininess") { - if (f !== false) { - effect.material.shininess = f; - } - } else if (tagName == "reflective") {} else if (tagName == "reflectivity") {} else if (tagName == "transparent") {} else if (tagName == "index_of_refraction") {} - // case "transparency": if (f!==false) effect.material.opacity = 1.0-f; break; - if (t !== false) { - effect.material - var srcTex = effect.surfaces[effect.samplers[t].source].source; - if (tagName == "emission") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.AMBIENT - }); - } else if (tagName == "ambient") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.AMBIENT - }); - } else if (tagName == "diffuse") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.COLOR - }); - } else if (tagName == "specular") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.SPECULAR - }); - } else if (tagName == "shininess") {} else if (tagName == "reflective") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.REFLECT - }); - } else if (tagName == "reflectivity") {} else if (tagName == "transparent") { - effect.material.textures_ref.push({ - image: srcTex, - type: enums.texture.map.ALPHA - }); - } else if (tagName == "transparency") {} else if (tagName == "index_of_refraction") {} - } - } - } - - clib.effects[effectId] = effect; - } - } - } - - // End Effects - - var cl_lib_mat_inst = collada_tools.getAllOf(cl_source.library_visual_scenes, "instance_material"); - var materialMap = []; - - if (cl_lib_mat_inst.length) { - for (i = 0, iMax = cl_lib_mat_inst.length; i < iMax; i++) { - var cl_mat_inst = cl_lib_mat_inst[i]; - - var symbolId = cl_mat_inst["@symbol"]; - var targetId = cl_mat_inst["@target"].substr(1); - - materialMap[symbolId] = targetId; - } - } - - - var cl_lib_materials = cl_source.library_materials; - - if (cl_lib_materials.material) { - var cl_materials = cl_lib_materials.material; - if (cl_materials && !cl_materials.length) cl_materials = [cl_materials]; - - for (mCount = 0, mMax = cl_materials.length; mCount < mMax; mCount++) { - var cl_material = cl_materials[mCount]; - - var materialId = cl_material["@id"]; - var materialName = cl_material["@name"]; - - var cl_einst = cl_material.instance_effect; - - if (cl_einst) { - effectId = cl_einst["@url"].substr(1); - clib.materials.push({ - id: materialId, - name: materialName, - mat: clib.effects[effectId].material - }); - } - } - } - - var cl_lib_geo = cl_source.library_geometries; - - if (cl_lib_geo) { - var cl_geo_node = cl_lib_geo.geometry; - - if (cl_geo_node && !cl_geo_node.length) cl_geo_node = [cl_geo_node]; - - if (cl_geo_node.length) { - for (var meshCount = 0, meshMax = cl_geo_node.length; meshCount < meshMax; meshCount++) { - var meshData = { - id: undef, - points: [], - parts: [] - }; - - var currentMaterial; - - var cl_geomesh = cl_geo_node[meshCount].mesh; - - // console.log("found "+meshUrl+"@"+meshName); - if (cl_geomesh) { - var meshId = cl_geo_node[meshCount]["@id"]; - meshName = cl_geo_node[meshCount]["@name"]; - - // MeshPool[meshUrl + "@" + meshName] = newObj; - var cl_geosources = cl_geomesh.source; - if (cl_geosources && !cl_geosources.length) cl_geosources = [cl_geosources]; - - var geoSources = []; - - for (var sourceCount = 0, sourceMax = cl_geosources.length; sourceCount < sourceMax; sourceCount++) { - var cl_geosource = cl_geosources[sourceCount]; - - sourceId = cl_geosource["@id"]; - var sourceName = cl_geosource["@name"]; - var cl_floatarray = cl_geosource.float_array; - - - if (cl_floatarray) { - geoSources[sourceId] = { - id: sourceId, - name: sourceName, - data: util.floatDelimArray(cl_floatarray.$?cl_floatarray.$:"", " ") - }; - } - - var cl_accessor = cl_geosource.technique_common.accessor; - - if (cl_accessor) { - geoSources[sourceId].count = parseInt(cl_accessor["@count"]); - geoSources[sourceId].stride = parseInt(cl_accessor["@stride"]); - if (geoSources[sourceId].count) { - geoSources[sourceId].data = util.repackArray(geoSources[sourceId].data, geoSources[sourceId].stride, geoSources[sourceId].count); - } - } - } - - var geoVerticies = []; - - var cl_vertices = cl_geomesh.vertices; - - var pointRef = null; - var pointRefId = null; - var triangleRef = null; - var normalRef = null; - var uvRef = null; - - - if (cl_vertices) { - pointRefId = cl_vertices["@id"]; - cl_inputs = cl_vertices.input; - - if (cl_inputs && !cl_inputs.length) cl_inputs = [cl_inputs]; - - if (cl_inputs) { - for (inpCount = 0, inpMax = cl_inputs.length; inpCount < inpMax; inpCount++) { - cl_input = cl_inputs[inpCount]; - - if (cl_input["@semantic"] === "POSITION") { - pointRef = cl_input["@source"].substr(1); - } - } - } - } - - var CL_VERTEX = 0, - CL_NORMAL = 1, - CL_TEXCOORD = 2, - CL_OTHER = 3; - - - var cl_triangles = cl_geomesh.triangles; - if (cl_triangles && !cl_triangles.length) cl_triangles = [cl_triangles]; - - var v_c = false, - n_c = false, - u_c = false; - - if (cl_triangles) { - for (tCount = 0, tMax = cl_triangles.length; tCount < tMax; tCount++) { - var meshPart = { - material: 0, - faces: [], - normals: [], - texcoords: [] - } - - var cl_trianglesCount = parseInt(cl_triangles[tCount]["@count"], 10); - cl_inputs = cl_triangles[tCount].input; - if (cl_inputs && !cl_inputs.length) cl_inputs = [cl_inputs]; - - cl_inputmap = []; - - if (cl_inputs.length) { - for (inpCount = 0, inpMax = cl_inputs.length; inpCount < inpMax; inpCount++) { - cl_input = cl_inputs[inpCount]; - - ofs = parseInt(cl_input["@offset"], 10); - nameRef = cl_input["@source"].substr(1); - - if (cl_input["@semantic"] === "VERTEX") { - if (nameRef === pointRefId) { - nameRef = triangleRef = pointRef; - } else { - triangleRef = nameRef; - } - v_c = true; - cl_inputmap[ofs] = CL_VERTEX; - } else if (cl_input["@semantic"] === "NORMAL") { - normalRef = nameRef; - if (geoSources[normalRef].count) { - cl_inputmap[ofs] = CL_NORMAL; - } - n_c = true; - } else if (cl_input["@semantic"] === "TEXCOORD") { - uvRef = nameRef; - if (geoSources[uvRef].count) { - cl_inputmap[ofs] = CL_TEXCOORD; - } - u_c = true; - } else { - cl_inputmap[ofs] = CL_OTHER; - } - } - } - mapLen = cl_inputmap.length; - - materialRef = cl_triangles[tCount]["@material"]; - - if (materialRef === null) { - meshPart.material = 0; - } else { - if (materialMap[materialRef] === undef) { - log("missing material [" + materialRef + "]@" + meshName + "?"); - meshPart.material = 0; - } else { - meshPart.material = materialMap[materialRef]; - } - } - - - var cl_triangle_source = cl_triangles[tCount].p; - - var triangleData = []; - - if (cl_triangle_source) { - triangleData = util.intDelimArray(cl_triangle_source.$, " "); - } - - if (triangleData.length) { - computedLen = ((triangleData.length) / cl_inputmap.length) / 3; - - if (computedLen !== cl_trianglesCount) { - // console.log("triangle data doesn't add up, skipping object load: "+computedLen+" !== "+cl_trianglesCount); - } else { - if (meshData.points.length === 0) { - meshData.points = geoSources[pointRef].data; - } - - ofs = 0; - - for (i = 0, iMax = triangleData.length, iMod = cl_inputmap.length; i < iMax; i += iMod * 3) { - norm = []; - vert = []; - uv = []; - - for (j = 0; j < iMod * 3; j++) { - var jMod = j % iMod; - - if (cl_inputmap[jMod] === CL_VERTEX) { - vert.push(triangleData[i + j]); - } else if (cl_inputmap[jMod] === CL_NORMAL) { - norm.push(triangleData[i + j]); - } else if (cl_inputmap[jMod] === CL_TEXCOORD) { - uv.push(triangleData[i + j]); - } - } - - if (vert.length) { - meshPart.faces.push(vert); - - if (norm.length === 3) { - meshPart.normals.push([collada_tools.fixuaxis(clib.up_axis, geoSources[normalRef].data[norm[0]]), collada_tools.fixuaxis(clib.up_axis, geoSources[normalRef].data[norm[1]]), collada_tools.fixuaxis(clib.up_axis, geoSources[normalRef].data[norm[2]])]); - } - - - if (uv.length === 3) { - meshPart.texcoords.push([geoSources[uvRef].data[uv[0]], geoSources[uvRef].data[uv[1]], geoSources[uvRef].data[uv[2]]]); - } - } - } - } - } - - meshData.parts.push(meshPart); - } - } - - - var cl_polylist = cl_geomesh.polylist; - if (!cl_polylist) { - cl_polylist = cl_geomesh.polygons; // try polygons - } - - if (cl_polylist && !cl_polylist.length) cl_polylist = [cl_polylist]; - - if (cl_polylist) { - for (tCount = 0, tMax = cl_polylist.length; tCount < tMax; tCount++) { - var meshPart = { - material: 0, - faces: [], - normals: [], - texcoords: [] - } - - var cl_polylistCount = parseInt(cl_polylist[tCount]["@count"], 10); - - cl_inputs = cl_polylist[tCount].input; - - if (cl_inputs && !cl_inputs.length) cl_inputs = [cl_inputs]; - - cl_inputmap = []; - - if (cl_inputs.length) { - for (inpCount = 0, inpMax = cl_inputs.length; inpCount < inpMax; inpCount++) { - cl_input = cl_inputs[inpCount]; - - var cl_ofs = cl_input["@offset"]; - - if (cl_ofs === null) { - cl_ofs = cl_input["@idx"]; - } - - ofs = parseInt(cl_ofs, 10); - nameRef = cl_input["@source"].substr(1); - - if (cl_input["@semantic"] === "VERTEX") { - if (nameRef === pointRefId) { - nameRef = triangleRef = pointRef; - - } else { - triangleRef = nameRef; - } - cl_inputmap[ofs] = CL_VERTEX; - } else if (cl_input["@semantic"] === "NORMAL") { - normalRef = nameRef; - cl_inputmap[ofs] = CL_NORMAL; - } else if (cl_input["@semantic"] === "TEXCOORD") { - uvRef = nameRef; - cl_inputmap[ofs] = CL_TEXCOORD; - } else { - cl_inputmap[ofs] = CL_OTHER; - } - } - } - - - var cl_vcount = cl_polylist[tCount].vcount; - var vcount = []; - - if (cl_vcount) { - vcount = util.intDelimArray(cl_vcount.$, " "); - } - - materialRef = cl_polylist[tCount]["@material"]; - - if (materialRef === undef) { - meshPart.material = 0; - } else { - meshPart.material = materialMap[materialRef]; - } - - var cl_poly_source = cl_polylist[tCount].p; - - mapLen = cl_inputmap.length; - - var polyData = []; - - if ((cl_poly_source.length > 1) && !vcount.length) // blender 2.49 style - { - var pText = ""; - for (pCount = 0, pMax = cl_poly_source.length; pCount < pMax; pCount++) { - var tmp = util.intDelimArray(cl_poly_source[pCount].$, " "); - - vcount[pCount] = parseInt(tmp.length / mapLen, 10); - - polyData.splice(polyData.length, 0, tmp); - } - } else { - if (cl_poly_source) { - polyData = util.intDelimArray(cl_poly_source.$, " "); - } - } - - if (polyData.length) { - computedLen = vcount.length; - - if (computedLen !== cl_polylistCount) { - log("poly vcount data doesn't add up, skipping object load: " + computedLen + " !== " + cl_polylistCount); - } else { - if (meshData.points.length === 0) { - meshData.points = geoSources[pointRef].data; - } - - ofs = 0; - - for (i = 0, iMax = vcount.length; i < iMax; i++) { - norm = []; - vert = []; - uv = []; - - for (j = 0, jMax = vcount[i] * mapLen; j < jMax; j++) { - if (cl_inputmap[j % mapLen] === CL_VERTEX) { - vert.push(polyData[ofs]); - ofs++; - } else if (cl_inputmap[j % mapLen] === CL_NORMAL) { - norm.push(polyData[ofs]); - ofs++; - } else if (cl_inputmap[j % mapLen] === CL_TEXCOORD) { - uv.push(polyData[ofs]); - ofs++; - } - } - - - if (vert.length) { - // if (up_axis !== 1) - // { - // vert.reverse(); - // } - // nFace = newObj.addFace(vert); - meshPart.faces.push(vert); - - if (norm.length) { - var nlist = []; - for (k = 0, kMax = norm.length; k < kMax; k++) { - // newObj.faces[nFace].point_normals[k] = fixuaxis(geoSources[normalRef].data[norm[k]]); - nlist.push(collada_tools.fixuaxis(clib.up_axis, geoSources[normalRef].data[norm[k]])); - } - meshPart.normals.push(nlist); - } - - if (uv.length) { - var tlist = []; - for (k = 0, kMax = uv.length; k < kMax; k++) { - // newObj.faces[nFace].uvs[k] = geoSources[uvRef].data[uv[k]]; - tlist.push(geoSources[uvRef].data[uv[k]]); - } - meshPart.texcoords.push(tlist); - } - } - } - } - } - } - } - - if (up_axis !== 1) { - for (i = 0, iMax = meshData.points.length; i < iMax; i++) { - meshData.points[i] = collada_tools.fixuaxis(clib.up_axis, meshData.points[i]); - } - } - - - - meshData.id = meshId; - clib.meshes.push(meshData); - - } - } - } - } - - - - - - var cl_lib_cameras = cl_source.library_cameras; - var camerasBoundRef = []; - - if (cl_lib_cameras) { - cl_cameras = cl_lib_cameras.camera; - if (cl_cameras && !cl_cameras.length) cl_cameras = [cl_cameras]; - - for (cCount = 0, cMax = cl_cameras.length; cCount < cMax; cCount++) { - cl_camera = cl_cameras[cCount]; - - var cameraId = cl_camera["@id"]; - var cameraName = cl_camera["@name"]; - - // var cl_perspective = cl_camera.getElementsByTagName("perspective"); - // if (cl_perspective.length) { - // var perspective = cl_perspective[0]; - var cl_yfov = 0; - var cl_znear = 0; - var cl_zfar = 0; - - if (cl_camera.optics) if (cl_camera.optics.technique_common) if (cl_camera.optics.technique_common.perspective) { - cl_yfov = cl_camera.optics.technique_common.perspective.yfov; - cl_znear = cl_camera.optics.technique_common.perspective.znear; - cl_zfar = cl_camera.optics.technique_common.perspective.zfar; - } - - - var yfov; - var znear; - var zfar; - - if (!cl_yfov && !cl_znear && !cl_zfar) { - cl_params = cl_camera.param; - if (cl_params && !cl_params.length) cl_params = [cl_params]; - - for (i = 0, iMax = cl_params.length; i < iMax; i++) { - var txt = cl_params[i].$; - var pName = cl_params[i]["@name"]; - if (pName == "YFOV") { - yfov = parseFloat(txt); - } else if (pName == "ZNEAR") { - znear = parseFloat(txt); - } else if (pName == "ZFAR") { - zfar = parseFloat(txt); - } - } - } else { - yfov = cl_yfov ? parseFloat(cl_yfov.$) : 60; - znear = cl_znear ? parseFloat(cl_znear.$) : 0.1; - zfar = cl_zfar ? parseFloat(cl_zfar.$) : 1000.0; - } - - clib.cameras.push({ - id: cameraId, - targeted: false, - fov: parseFloat(yfov), - nearclip: parseFloat(znear), - farclip: parseFloat(zfar) - }); - } - } - - - var cl_lib_lights = cl_source.library_lights; - - if (cl_lib_lights) { - var cl_lights = cl_lib_lights.light; - if (cl_lights && !cl_lights.length) cl_lights = [cl_lights]; - - if (cl_lights) for (var lightCount = 0, lightMax = cl_lights.length; lightCount < lightMax; lightCount++) { - - var cl_light = cl_lights[lightCount]; - - var cl_point = cl_light.technique_common.point; - var cl_pointLight = cl_point ? cl_point : null; - - var lightId = cl_light["@id"]; - var lightName = cl_light["@name"]; - - if (cl_pointLight !== null) { - - var cl_intensity = cl_pointLight.intensity; - var intensity = cl_intensity ? parseFloat(cl_intensity.$) : 1.0; - var cl_distance = cl_pointLight.distance; - var distance = cl_distance ? parseFloat(cl_distance.$) : 10.0; - - var cl_color = cl_pointLight.color; - var color = [1, 1, 1]; - - if (cl_color) { - color = util.floatDelimArray(cl_color.$, " "); - } - - clib.lights.push({ - id: lightId, - name: lightId, - type: enums.light.type.POINT, - method: enums.light.method.STATIC, - diffuse: color, - specular: [0, 0, 0], - distance: distance, - intensity: intensity - }); - } - } - } - - var cl_lib_scenes = cl_source.library_visual_scenes; - - if (cl_lib_scenes) { - var cl_scenes = null; - - cl_scenes = cl_lib_scenes.visual_scene; - if (cl_scenes && !cl_scenes.length) cl_scenes = [cl_scenes]; - - for (var sceneCount = 0, sceneMax = cl_scenes.length; sceneCount < sceneMax; sceneCount++) { - - cl_scene = cl_scenes[sceneCount]; - - var sceneId = cl_scene["@id"]; - var sceneName = cl_scene["@name"]; - - var sceneData = { - id: sceneName, - sceneObjects: [], - cameras: [], - lights: [], - parentMap: [] - }; - - var nodeMap = {}; - - var cl_nodes = []; - var cl_stack = [cl_scene]; - - while (cl_stack.length) { - var ntemp = cl_stack.pop(); - if (ntemp.node) { - var nlist = ntemp.node; - if (nlist && !nlist.length) nlist = [nlist]; - - if (nlist) { - for (var i = 0, iMax = nlist.length; i < iMax; i++) { - nlist[i].parentNode = ntemp; - cl_nodes.push(nlist[i]); - cl_stack.push(nlist[i]); - } - } - } - } - - if (cl_nodes.length) { - for (var nodeCount = 0, nodeMax = cl_nodes.length; nodeCount < nodeMax; nodeCount++) { - var cl_node = cl_nodes[nodeCount]; - - var cl_geom = cl_node.instance_geometry; - var cl_light = cl_nodes[nodeCount].instance_light; - cl_camera = cl_nodes[nodeCount].instance_camera; - - var nodeId = cl_node["@id"]; - var nodeName = cl_node["@name"]; - - var it = collada_tools.cl_getInitalTransform(clib.up_axis, cl_node); - - if (up_axis === 2) { - it.rotation = collada_tools.quaternionFilterZYYZ(it.rotation, (cl_camera) ? [-90, 0, 0] : undef); - } - - var sceneObject = {}; - - if (cl_geom) { - meshName = cl_geom["@url"].substr(1); - - sceneObject.name = sceneObject.id = (nodeName) ? nodeName : nodeId; - - sceneObject.position = it.position; - sceneObject.rotation = it.rotation; - sceneObject.scale = it.scale; - sceneObject.meshId = meshName; - - sceneData.sceneObjects.push(sceneObject); - - nodeMap[sceneObject.id] = true;; - - if (cl_node.parentNode) { - var parentNodeId = cl_node.parentNode["@id"]; - var parentNodeName = cl_node.parentNode["@name"]; - if (parentNodeId) { - - if (nodeMap[parentNodeId]) { - sceneData.parentMap.push({ - parent: parentNodeId, - child: sceneObject.id - }); - } - } - } - } else if (cl_camera) { - var cam_instance = cl_camera; - - var camRefId = cam_instance["@url"].substr(1); - - sceneData.cameras.push({ - name: (nodeName) ? nodeName : nodeId, - id: (nodeName) ? nodeName : nodeId, - source: camRefId, - position: it.position, - rotation: it.rotation - }); - - - } else if (cl_light) { - - var lightRefId = cl_light["@url"].substr(1); - - sceneData.lights.push({ - name: (nodeName) ? nodeName : nodeId, - id: (nodeName) ? nodeName : nodeId, - source: lightRefId, - position: it.position - }); - - } else { - sceneData.sceneObjects.push({ - id: (nodeName !== null) ? nodeName : nodeId, - name: (nodeName !== null) ? nodeName : nodeId, - position: it.position, - rotation: it.rotation, - scale: it.scale - }); - - } - - } - } - - clib.scenes.push(sceneData); - } - } - - - var cl_lib_anim = cl_source.library_animations; - - var animId; - if (cl_lib_anim) { - var cl_anim_sources = cl_lib_anim.animation; - if (cl_anim_sources && !cl_anim_sources.length) cl_anim_sources = [cl_anim_sources]; - - if (cl_anim_sources) { - for (var aCount = 0, aMax = cl_anim_sources.length; aCount < aMax; aCount++) { - var cl_anim = cl_anim_sources[aCount]; - - animId = cl_anim["@id"]; - var animName = cl_anim["@name"]; - - clib.animations[animId] = {}; - clib.animations[animId].sources = []; - - var cl_sources = cl_anim.source; - if (cl_sources && !cl_sources.length) cl_sources = [cl_sources]; - - if (cl_sources.length) { - for (sCount = 0, sMax = cl_sources.length; sCount < sMax; sCount++) { - var cl_csource = cl_sources[sCount]; - - sourceId = cl_csource["@id"]; - - - var tech_common = cl_csource.technique_common; - - var name_array = null; - var float_array = null; - var data = null; - - if (cl_csource.name_array) { - name_array = util.textDelimArray(cl_csource.name_array.$, " "); - } else if (cl_csource.Name_array) { - name_array = util.textDelimArray(cl_csource.Name_array.$, " "); - } else if (cl_csource.float_array) { - float_array = util.floatDelimArray(cl_csource.float_array.$, " "); - } - - var acCount = 0; - var acSource = ""; - var acStride = 1; - - if (tech_common) { - tech = tech_common; - var acc = tech.accessor; - - acCount = parseInt(acc["@count"], 10); - acSource = acc["@source"].substr(1); - var aStride = acc["@stride"]; - - if (aStride) { - acStride = parseInt(aStride, 10); - } - } - - clib.animations[animId].sources[sourceId] = { - data: name_array ? name_array : float_array, - count: acCount, - source: acSource, - stride: acStride - }; - - if (acStride !== 1) { - clib.animations[animId].sources[sourceId].data = util.repackArray(clib.animations[animId].sources[sourceId].data, acStride, acCount); - } - } - } - - cl_samplers = cl_anim.sampler; - if (cl_samplers && !cl_samplers.length) cl_samplers = [cl_samplers]; - - if (cl_samplers) { - clib.animations[animId].samplers = []; - - for (sCount = 0, sMax = cl_samplers.length; sCount < sMax; sCount++) { - var cl_sampler = cl_samplers[sCount]; - - var samplerId = cl_sampler["@id"]; - - cl_inputs = cl_sampler.input; - - if (cl_inputs && !cl_inputs.length) cl_inputs = [cl_inputs]; - - if (cl_inputs) { - var inputs = []; - - for (iCount = 0, iMax = cl_inputs.length; iCount < iMax; iCount++) { - cl_input = cl_inputs[iCount]; - - var semanticName = cl_input["@semantic"]; - - inputs[semanticName] = cl_input["@source"].substr(1); - } - - clib.animations[animId].samplers[samplerId] = inputs; - } - } - } - - var cl_channels = cl_anim.channel; - if (cl_channels && !cl_channels.length) cl_channels = [cl_channels]; - - - if (cl_channels) { - clib.animations[animId].channels = []; - - for (cCount = 0, cMax = cl_channels.length; cCount < cMax; cCount++) { - var channel = cl_channels[cCount]; - - var channelSource = channel["@source"].substr(1); - var channelTarget = channel["@target"]; - - var channelSplitA = channelTarget.split("/"); - var channelTargetName = channelSplitA[0]; - var channelSplitB = channelSplitA[1].split("."); - var channelParam = channelSplitB[0]; - var channelType = channelSplitB[1]; - - clib.animations[animId].channels.push({ - source: channelSource, - target: channelTarget, - targetName: channelTargetName, - paramName: channelParam, - typeName: channelType - }); - } - } - } - } - } - - var cl_lib_scene = cl_source.scene; - - if (cl_lib_scene) { - cl_scene = cl_lib_scene.instance_visual_scene; - - if (cl_scene) { - var sceneUrl = cl_scene["@url"].substr(1); - clib.scene = sceneUrl; - } - } - - - return clib; -} - - -function cubicvr_loadCollada(meshUrl, prefix, deferred_bin) { - - var clib = cubicvr_parseCollada(meshUrl, prefix, deferred_bin); - - var up_axis = clib.up_axis; - - var materialRef = []; - - for (var m = 0, mMax = clib.materials.length; m < mMax; m++) { - - var material = clib.materials[m]; - var newMaterial = new Material(material.mat); - - for (var t = 0, tMax = material.mat.textures_ref.length; t < tMax; t++) { - var tex = material.mat.textures_ref[t]; - - var texObj = null; - - if (Texture_ref[tex.image] === undefined) { - texObj = new Texture(tex.image, GLCore.default_filter, deferred_bin, meshUrl); - } else { - texObj = Textures_obj[Texture_ref[tex.image]]; - } - - newMaterial.setTexture(texObj, tex.type); - } - - materialRef[material.id] = newMaterial; - } - - - var meshRef = []; - - for (var m = 0, mMax = clib.meshes.length; m < mMax; m++) { - - var meshData = clib.meshes[m]; - - var newObj = new Mesh(meshData.id); - - newObj.points = meshData.points; - - for (var mp = 0, mpMax = meshData.parts.length; mp < mpMax; mp++) { - var part = meshData.parts[mp]; - - if (part.material !== 0) { - newObj.setFaceMaterial(materialRef[part.material]); - } - - var bNorm = part.normals.length ? true : false; - var bTex = part.texcoords.length ? true : false; - - for (var p = 0, pMax = part.faces.length; p < pMax; p++) { - var faceNum = newObj.addFace(part.faces[p]); - if (bNorm) newObj.faces[faceNum].point_normals = part.normals[p]; - if (bTex) newObj.faces[faceNum].uvs = part.texcoords[p]; - } - } - - // newObj.calcNormals(); - if (!deferred_bin) { - newObj.triangulateQuads(); - newObj.compile(); - } else { - deferred_bin.addMesh(meshUrl, meshUrl + ":" + meshId, newObj); - } - - meshRef[meshData.id] = newObj; - } - - - var camerasRef = []; - - for (var c = 0, cMax = clib.cameras.length; c < cMax; c++) { - camerasRef[clib.cameras[c].id] = clib.cameras[c]; - } - - - var lightsRef = []; - - for (var l = 0, lMax = clib.lights.length; l < lMax; l++) { - lightsRef[clib.lights[l].id] = clib.lights[l]; - } - - - - var sceneObjectMap = {}; - var sceneLightMap = {}; - var sceneCameraMap = {}; - - var scenesRef = {}; - - for (var s = 0, sMax = clib.scenes.length; s < sMax; s++) { - var scn = clib.scenes[s]; - - var newScene = new CubicVR.Scene(); - - for (var so = 0, soMax = scn.sceneObjects.length; so < soMax; so++) { - var sceneObj = scn.sceneObjects[so]; - var newSceneObject = new SceneObject(sceneObj); - var srcMesh = meshRef[sceneObj.meshId] || null; - newSceneObject.obj = srcMesh; - - sceneObjectMap[sceneObj.id] = newSceneObject; - newScene.bindSceneObject(newSceneObject); - } - - for (var l = 0, lMax = scn.lights.length; l < lMax; l++) { - var lt = scn.lights[l]; - - var newLight = new Light(lightsRef[lt.source]); - newLight.position = lt.position; - - sceneLightMap[lt.id] = newLight; - newScene.bindLight(newLight); - } - - if (scn.cameras.length) { // single camera for the moment until we support it - var cam = scn.cameras[0]; - var newCam = new Camera(camerasRef[cam.source]); - newCam.position = cam.position; - newCam.rotation = cam.rotation; - - sceneCameraMap[cam.id] = newCam; - newScene.camera = newCam; - } - for (var p = 0, pMax = scn.parentMap.length; p < pMax; p++) { - var pmap = scn.parentMap[p]; - sceneObjectMap[pmap.parent].bindChild(sceneObjectMap[pmap.child]); - } - - scenesRef[scn.id] = newScene; - } - - - - for (animId in clib.animations) { - if (clib.animations.hasOwnProperty(animId)) { - var anim = clib.animations[animId]; - - if (anim.channels.length) { - for (cCount = 0, cMax = anim.channels.length; cCount < cMax; cCount++) { - var chan = anim.channels[cCount]; - var sampler = anim.samplers[chan.source]; - var samplerInput = anim.sources[sampler["INPUT"]]; - var samplerOutput = anim.sources[sampler["OUTPUT"]]; - var samplerInterp = anim.sources[sampler["INTERPOLATION"]]; - var samplerInTangent = anim.sources[sampler["IN_TANGENT"]]; - var samplerOutTangent = anim.sources[sampler["OUT_TANGENT"]]; - var hasInTangent = (sampler["IN_TANGENT"] !== undef); - var hasOutTangent = (sampler["OUT_TANGENT"] !== undef); - var mtn = null; - - var targetSceneObject = sceneObjectMap[chan.targetName]; - var targetCamera = sceneCameraMap[chan.targetName]; - var targetLight = sceneLightMap[chan.targetName]; - - if (targetSceneObject) { - if (targetSceneObject.motion === null) { - targetSceneObject.motion = new Motion(); - } - mtn = targetSceneObject.motion; - } else if (targetCamera) { - if (targetCamera.motion === null) { - targetCamera.motion = new Motion(); - } - - mtn = targetCamera.motion; - } else if (targetLight) { - if (targetLight.motion === null) { - targetLight.motion = new Motion(); - } - - mtn = targetLight.motion; - } - // else - // { - // console.log("missing",chan.targetName); - // console.log("missing",chan.paramName); - // } - if (mtn === null) { - continue; - } - - var controlTarget = enums.motion.POS; - var motionTarget = enums.motion.X; - - if (up_axis === 2) { - mtn.yzflip = true; - } - - var pName = chan.paramName; - - if (pName === "rotateX" || pName === "rotationX") { - controlTarget = enums.motion.ROT; - motionTarget = enums.motion.X; - } else if (pName === "rotateY" || pName === "rotationY") { - controlTarget = enums.motion.ROT; - motionTarget = enums.motion.Y; - } else if (pName === "rotateZ" || pName === "rotationZ") { - controlTarget = enums.motion.ROT; - motionTarget = enums.motion.Z; - } else if (pName === "location") { - controlTarget = enums.motion.POS; - if (chan.typeName === "X") { - motionTarget = enums.motion.X; - } - if (chan.typeName === "Y") { - motionTarget = enums.motion.Y; - } - if (chan.typeName === "Z") { - motionTarget = enums.motion.Z; - } - } else if (pName === "translate") { - controlTarget = enums.motion.POS; - if (chan.typeName === "X") { - motionTarget = enums.motion.X; - } - if (chan.typeName === "Y") { - motionTarget = enums.motion.Y; - } - if (chan.typeName === "Z") { - motionTarget = enums.motion.Z; - } - } else if (pName === "LENS") { - // controlTarget = enums.motion.LENS; - // motionTarget = 4; - controlTarget = 10; - motionTarget = 10; - continue; // disabled, only here for temporary collada files - } else if (pName === "FOV") { - controlTarget = enums.motion.FOV; - motionTarget = 3; // ensure no axis fixes are applied - } else if (pName === "ZNEAR") { - controlTarget = enums.motion.NEARCLIP; - motionTarget = 3; // ensure no axis fixes are applied - } else if (pName === "ZFAR") { - controlTarget = enums.motion.FARCLIP; - motionTarget = 3; // ensure no axis fixes are applied - } else if (pName === "intensity") { - controlTarget = enums.motion.INTENSITY; - motionTarget = 3; // ensure no axis fixes are applied - } - - if (targetLight && controlTarget < 3) targetLight.method = enums.light.method.DYNAMIC; - - // if (up_axis === 2 && motionTarget === enums.motion.Z) motionTarget = enums.motion.Y; - // else if (up_axis === 2 && motionTarget === enums.motion.Y) motionTarget = enums.motion.Z; - // - var ival; - for (mCount = 0, mMax = samplerInput.data.length; mCount < mMax; mCount++) { // in the process of being deprecated - k = null; - - if (typeof(samplerOutput.data[mCount]) === 'object') { - for (i = 0, iMax = samplerOutput.data[mCount].length; i < iMax; i++) { - ival = i; - - if (up_axis === 2 && i === 2) { - ival = 1; - } else if (up_axis === 2 && i === 1) { - ival = 2; - } - - k = mtn.setKey(controlTarget, ival, samplerInput.data[mCount], collada_tools.fixukaxis(clib.up_axis, controlTarget, ival, samplerOutput.data[mCount][i])); - - if (samplerInterp) { - var pInterp = samplerInterp.data[mCount][i]; - if (pInterp === "LINEAR") { - k.shape = enums.envelope.shape.LINE; - } else if (pInterp === "BEZIER") { - if (!(hasInTangent || hasOutTangent)) { - k.shape = enums.envelope.shape.LINEAR; - } else { - k.shape = enums.envelope.shape.BEZI; - } - } - } - } - } else { - ival = motionTarget; - ofs = 0; - - if (targetCamera) { - if (controlTarget === enums.motion.ROT) { - if (up_axis === 2 && ival === 0) { - ofs = -90; - } - } - } - - if (controlTarget === enums.motion.ROT) { - k = mtn.setKey(controlTarget, ival, samplerInput.data[mCount], samplerOutput.data[mCount] + ofs); - } else { - if (up_axis === 2 && motionTarget === 2) { - ival = 1; - } else if (up_axis === 2 && motionTarget === 1) { - ival = 2; - } - - k = mtn.setKey(controlTarget, ival, samplerInput.data[mCount], collada_tools.fixukaxis(clib.up_axis, controlTarget, ival, samplerOutput.data[mCount])); - } - - if (samplerInterp) { - var pInterp = samplerInterp.data[mCount]; - if (pInterp === "LINEAR") { - k.shape = enums.envelope.shape.LINE; - } else if (pInterp === "BEZIER") { - if (!(hasInTangent || hasOutTangent)) { - k.shape = enums.envelope.shape.LINEAR; - k.continutity = 1.0; - } else { - k.shape = enums.envelope.shape.BEZ2; - - var itx = samplerInTangent.data[mCount][0], - ity; - var otx = samplerOutTangent.data[mCount][0], - oty; - - if (controlTarget === enums.motion.ROT) { - ity = samplerInTangent.data[mCount][1]; - oty = samplerOutTangent.data[mCount][1]; - - // k.value = k.value/10; - // mtn.rscale = 10; - k.param[0] = itx - k.time; - k.param[1] = ity - k.value + ofs; - k.param[2] = otx - k.time; - k.param[3] = oty - k.value + ofs; - } else { - ity = collada_tools.fixukaxis(clib.up_axis, controlTarget, ival, samplerInTangent.data[mCount][1]); - oty = collada_tools.fixukaxis(clib.up_axis, controlTarget, ival, samplerOutTangent.data[mCount][1]); - - k.param[0] = itx - k.time; - k.param[1] = ity - k.value; - k.param[2] = otx - k.time; - k.param[3] = oty - k.value; - } - - } - } - } - } - } - } - } - } - } - - - - var sceneRef = null; - - if (clib.scene) { - sceneRef = scenesRef[clib.scene]; - } else { - sceneRef = scenesRef.pop(); - } - - - return sceneRef; -} - -function GML(srcUrl) { - this.strokes = []; - this.bounds = [1, 1, 1]; - this.origin = [0, 0, 0]; - this.upvector = [0, 1, 0]; - this.viewvector = [0, 0, 1]; - this.manual_pos = 0; - - if (srcUrl === undef) { - return; - } - - var gml = util.getXML(srcUrl); - - var gml_header = gml.getElementsByTagName("header"); - - if (!gml_header.length) { - return null; - } - - var header = gml_header[0]; - - var gml_environment = gml.getElementsByTagName("environment"); - - - if (!gml_environment.length) { - return null; - } - - this.name = null; - - var gml_name = header.getElementsByTagName("name"); - - if (gml_name.length) { - this.name = util.collectTextNode(gml_name[0]); - } - - var gml_screenbounds = gml_environment[0].getElementsByTagName("screenBounds"); - - if (gml_screenbounds.length) { - this.bounds = [ - parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("x")[0])), - parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("y")[0])), - parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("z")[0])) - ]; - } - - var gml_origin = gml_environment[0].getElementsByTagName("origin"); - - if (gml_origin.length) { - this.origin = [ - parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("x")[0])), - parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("y")[0])), - parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("z")[0])) - ]; - } - - var gml_upvector = gml_environment[0].getElementsByTagName("up"); - - if (gml_upvector.length) { - this.upvector = [ - parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("x")[0])), - parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("y")[0])), - parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("z")[0])) - ]; - } - - var gml_drawings = gml.getElementsByTagName("drawing"); - - var drawings = []; - - for (var dCount = 0, dMax = gml_drawings.length; dCount < dMax; dCount++) { - var drawing = gml_drawings[dCount]; - var gml_strokes = drawing.getElementsByTagName("stroke"); - - var xm = 0, - ym = 0, - zm = 0, - tm = 0; - - for (var sCount = 0, sMax = gml_strokes.length; sCount < sMax; sCount++) { - var gml_stroke = gml_strokes[sCount]; - var gml_points = gml_stroke.getElementsByTagName("pt"); - var plen = gml_points.length; - - var points = new Array(plen); - var px, py, pz, pt; - - for (var pCount = 0, pMax = plen; pCount < pMax; pCount++) { - var gml_point = gml_points[pCount]; - - px = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("x")[0])); - py = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("y")[0])); - pz = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("z")[0])); - pt = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("time")[0])); - - if (this.upvector[0] === 1) { - points[pCount] = [(py !== py) ? 0 : py, (px !== px) ? 0 : -px, (pz !== pz) ? 0 : pz, pt]; - } else if (this.upvector[1] === 1) { - points[pCount] = [(px !== px) ? 0 : px, (py !== py) ? 0 : py, (pz !== pz) ? 0 : pz, pt]; - } else if (this.upvector[2] === 1) { - points[pCount] = [(px !== px) ? 0 : px, (pz !== pz) ? 0 : -pz, (py !== py) ? 0 : py, pt]; - } - - if (xm < px) { - xm = px; - } - if (ym < py) { - ym = py; - } - if (zm < pz) { - zm = pz; - } - if (tm < pt) { - tm = pt; - } - } - - if (zm > tm) { // fix swapped Z/Time - for (var i = 0, iMax = points.length; i < iMax; i++) { - var t = points[i][3]; - points[i][3] = points[i][2]; - points[i][2] = t / this.bounds[2]; - } - } - - this.strokes[sCount] = points; - } - } -} - -GML.prototype.addStroke = function(points, tstep) { - var pts = []; - - if (tstep === undef) { - tstep = 0.1; - } - - for (var i = 0, iMax = points.length; i < iMax; i++) { - var ta = [points[i][0], points[i][1], points[i][2]]; - this.manual_pos += tstep; - ta.push(this.manual_pos); - pts.push(ta); - } - - this.strokes.push(pts); -}; - - -GML.prototype.recenter = function() { - var min = [0, 0, 0]; - var max = [this.strokes[0][0][0], this.strokes[0][0][1], this.strokes[0][0][2]]; - - var i, iMax, s, sMax; - - for (s = 0, sMax = this.strokes.length; s < sMax; s++) { - for (i = 0, iMax = this.strokes[s].length; i < iMax; i++) { - if (min[0] > this.strokes[s][i][0]) { - min[0] = this.strokes[s][i][0]; - } - if (min[1] > this.strokes[s][i][1]) { - min[1] = this.strokes[s][i][1]; - } - if (min[2] > this.strokes[s][i][2]) { - min[2] = this.strokes[s][i][2]; - } - - if (max[0] < this.strokes[s][i][0]) { - max[0] = this.strokes[s][i][0]; - } - if (max[1] < this.strokes[s][i][1]) { - max[1] = this.strokes[s][i][1]; - } - if (max[2] < this.strokes[s][i][2]) { - max[2] = this.strokes[s][i][2]; - } - } - } - - var center = vec3.multiply(vec3.subtract(max, min), 0.5); - - for (s = 0, sMax = this.strokes.length; s < sMax; s++) { - for (i = 0, iMax = this.strokes[s].length; i < iMax; i++) { - this.strokes[s][i][0] = this.strokes[s][i][0] - center[0]; - this.strokes[s][i][1] = this.strokes[s][i][1] - (this.upvector[1] ? center[1] : (-center[1])); - this.strokes[s][i][2] = this.strokes[s][i][2] - center[2]; - } - } -}; - -GML.prototype.generateObject = function(seg_mod, extrude_depth, pwidth, divsper, do_zmove) { - if (seg_mod === undef) { - seg_mod = 0; - } - if (extrude_depth === undef) { - extrude_depth = 0; - } - if (do_zmove === undef) { - do_zmove = false; - } - - - - // temporary defaults - var divs = 3; -// var divsper = 0.02; - - if (divsper === undef) divsper = 0.02; -// var pwidth = 0.015; - - if (pwidth === undef) pwidth = 0.015; - - var extrude = extrude_depth !== 0; - - var segCount = 0; - var faceSegment = 0; - - var obj = new Mesh(this.name); - - var lx, ly, lz, lt; - - var i, iMax, pCount; - - for (var sCount = 0, sMax = this.strokes.length; sCount < sMax; sCount++) { - var strokeEnvX = new Envelope(); - var strokeEnvY = new Envelope(); - var strokeEnvZ = new Envelope(); - - var pMax = this.strokes[sCount].length; - - var d = 0; - var len_set = []; - var time_set = []; - var start_time = 0; - var strk = this.strokes[sCount]; - - for (pCount = 0; pCount < pMax; pCount++) { - var pt = strk[pCount]; - - var k1 = strokeEnvX.addKey(pt[3], pt[0]); - var k2 = strokeEnvY.addKey(pt[3], pt[1]); - var k3; - - if (do_zmove) { - k3 = strokeEnvZ.addKey(pt[3], pt[2]); - } - else { - k3 = strokeEnvZ.addKey(pt[3], 0); - } - - k1.tension = 0.5; - k2.tension = 0.5; - k3.tension = 0.5; - - if (pCount !== 0) { - var dx = pt[0] - lx; - var dy = pt[1] - ly; - var dz = pt[2] - lz; - var dt = pt[3] - lt; - var dlen = Math.sqrt(dx * dx + dy * dy + dz * dz); - - d += dlen; - - len_set[pCount-1] = dlen; - time_set[pCount-1] = dt; - } else { - start_time = pt[3]; - } - - lx = pt[0]; - ly = pt[1]; - lz = pt[2]; - lt = pt[3]; - } - - var dpos = start_time; - var ptofs = obj.points.length; - - for (pCount = 0; pCount < len_set.length; pCount++) { - var segLen = len_set[pCount]; - var segTime = time_set[pCount]; - var segNum = Math.ceil((segLen / divsper) * divs); - - for (var t = dpos, tMax = dpos + segTime, tInc = (segTime / segNum); t < (tMax - tInc); t += tInc) { - if (t === dpos) { - lx = strokeEnvX.evaluate(t); - ly = strokeEnvY.evaluate(t); - lz = strokeEnvZ.evaluate(t); - } - - var px, py, pz; - - px = strokeEnvX.evaluate(t + tInc); - py = strokeEnvY.evaluate(t + tInc); - pz = strokeEnvZ.evaluate(t + tInc); - - var pdx = (px - lx), - pdy = py - ly, - pdz = pz - lz; - var pd = Math.sqrt(pdx * pdx + pdy * pdy + pdz * pdz); - var a; - - a = vec3.multiply( - vec3.normalize( - vec3.cross(this.viewvector, vec3.normalize([pdx, pdy, pdz]))), pwidth / 2.0); - - obj.addPoint([lx - a[0], -(ly - a[1]), (lz - a[2]) + (extrude ? (extrude_depth / 2.0) : 0)]); - obj.addPoint([lx + a[0], -(ly + a[1]), (lz + a[2]) + (extrude ? (extrude_depth / 2.0) : 0)]); - - lx = px; - ly = py; - lz = pz; - } - - dpos += segTime; - } - - var ptlen = obj.points.length; - - if (extrude) { - for (i = ptofs, iMax = ptlen; i < iMax; i++) { - obj.addPoint([obj.points[i][0], obj.points[i][1], obj.points[i][2] - (extrude ? (extrude_depth / 2.0) : 0)]); - } - } - - for (i = 0, iMax = ptlen - ptofs; i <= iMax - 4; i += 2) { - if (segCount % seg_mod === 0) { - faceSegment++; - } - - obj.setSegment(faceSegment); - - var arFace = [ptofs + i, ptofs + i + 1, ptofs + i + 3, ptofs + i + 2]; - // var ftest = vec3.dot(this.viewvector, triangle.normal(obj.points[arFace[0]], obj.points[arFace[1]], obj.points[arFace[2]])); - - var faceNum = obj.addFace(arFace); - - // if (ftest < 0) { - // this.faces[faceNum].flip(); - // } - - if (extrude) { - var arFace2 = [arFace[3] + ptlen - ptofs, arFace[2] + ptlen - ptofs, arFace[1] + ptlen - ptofs, arFace[0] + ptlen - ptofs]; - faceNum = obj.addFace(arFace2); - - arFace2 = [ptofs + i, ptofs + i + 2, ptofs + i + 2 + ptlen - ptofs, ptofs + i + ptlen - ptofs]; - faceNum = obj.addFace(arFace2); - - arFace2 = [ptofs + i + 1 + ptlen - ptofs, ptofs + i + 3 + ptlen - ptofs, ptofs + i + 3, ptofs + i + 1]; - faceNum = obj.addFace(arFace2); - - if (i === 0) { - arFace2 = [ptofs + i + ptlen - ptofs, ptofs + i + 1 + ptlen - ptofs, ptofs + i + 1, ptofs + i]; - faceNum = obj.addFace(arFace2); - } - if (i === iMax - 4) { - arFace2 = [ptofs + i + 2, ptofs + i + 3, ptofs + i + 3 + ptlen - ptofs, ptofs + i + 2 + ptlen - ptofs]; - faceNum = obj.addFace(arFace2); - } - } - - segCount++; - } - } - - - obj.calcFaceNormals(); - - obj.triangulateQuads(); - obj.calcNormals(); - obj.compile(); - - return obj; -}; - - -/* Particle System */ - -function Particle(pos, start_time, life_time, velocity, accel) { - this.startpos = new Float32Array(pos); - this.pos = new Float32Array(pos); - this.velocity = new Float32Array((velocity !== undef) ? velocity : [0, 0, 0]); - this.accel = new Float32Array((accel !== undef) ? accel : [0, 0, 0]); - this.start_time = (start_time !== undef) ? start_time : 0; - this.life_time = (life_time !== undef) ? life_time : 0; - this.color = null; - this.nextParticle = null; -} - - -function ParticleSystem(maxPts, hasColor, pTex, vWidth, vHeight, alpha, alphaCut) { - var gl = GLCore.gl; - - if (!maxPts) { - return; - } - - this.particles = null; - this.last_particle = null; - this.pTex = (pTex !== undef) ? pTex : null; - this.vWidth = vWidth; - this.vHeight = vHeight; - this.alpha = (alpha !== undef) ? alpha : false; - this.alphaCut = (alphaCut !== undef) ? alphaCut : 0; - - this.pfunc = function(p, time) { - var tdelta = time - p.start_time; - - if (tdelta < 0) { - return 0; - } - if (tdelta > p.life_time && p.life_time) { - return -1; - } - - p.pos[0] = p.startpos[0] + (tdelta * p.velocity[0]) + (tdelta * tdelta * p.accel[0]); - p.pos[1] = p.startpos[1] + (tdelta * p.velocity[1]) + (tdelta * tdelta * p.accel[1]); - p.pos[2] = p.startpos[2] + (tdelta * p.velocity[2]) + (tdelta * tdelta * p.accel[2]); - - if (this.pgov !== null) { - this.pgov(p, time); - } - - return 1; - }; - - this.pgov = null; - - if (hasColor === undef) { - this.hasColor = false; - } else { - this.hasColor = hasColor; - } - - // gl.enable(gl.VERTEX_PROGRAM_POINT_SIZE); - var hasTex = (this.pTex !== null); - - this.vs = [ - "#ifdef GL_ES", - "precision highp float;", - "#endif", - "attribute vec3 aVertexPosition;", - this.hasColor ? "attribute vec3 aColor;" : "", - "uniform mat4 uMVMatrix;", - "uniform mat4 uPMatrix;", - "varying vec4 color;", - "varying vec2 screenPos;", - hasTex ? "varying float pSize;" : "", - "void main(void) {", - "vec4 position = uPMatrix * uMVMatrix * vec4(aVertexPosition,1.0);", - hasTex ? "screenPos=vec2(position.x/position.w,position.y/position.w);" : "", - "gl_Position = position;", - this.hasColor ? "color = vec4(aColor.r,aColor.g,aColor.b,1.0);" : "color = vec4(1.0,1.0,1.0,1.0);", - hasTex ? "pSize=200.0/position.z;" : "float pSize=200.0/position.z;", - "gl_PointSize = pSize;", - "}"].join("\n"); - - this.fs = [ - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - hasTex ? "uniform sampler2D pMap;" : "", - - - "varying vec4 color;", - hasTex ? "varying vec2 screenPos;" : "", - hasTex ? "uniform vec3 screenDim;" : "", - hasTex ? "varying float pSize;" : "", - - "void main(void) {", - "vec4 c = color;", - hasTex ? "vec2 screen=vec2((gl_FragCoord.x/screenDim.x-0.5)*2.0,(gl_FragCoord.y/screenDim.y-0.5)*2.0);" : "", - hasTex ? "vec2 pointCoord=vec2( ((screen.x-screenPos.x)/(pSize/screenDim.x))/2.0+0.5,((screen.y-screenPos.y)/(pSize/screenDim.y))/2.0+0.5);" : "", - hasTex ? "vec4 tc = texture2D(pMap,pointCoord); gl_FragColor = vec4(c.rgb*tc.rgb,1.0);" : "gl_FragColor = c;", - "}"].join("\n"); - - this.maxPoints = maxPts; - this.numParticles = 0; - this.arPoints = new Float32Array(maxPts * 3); - this.glPoints = null; - - if (hasColor) { - this.arColor = new Float32Array(maxPts * 3); - this.glColor = null; - } - - this.shader_particle = new Shader(this.vs, this.fs); - this.shader_particle.use(); - this.shader_particle.addVertexArray("aVertexPosition"); - - if (this.hasColor) { - this.shader_particle.addVertexArray("aColor"); - } - - this.shader_particle.addMatrix("uMVMatrix"); - this.shader_particle.addMatrix("uPMatrix"); - - if (this.pTex !== null) { - this.shader_particle.addInt("pMap", 0); - this.shader_particle.addVector("screenDim"); - this.shader_particle.setVector("screenDim", [vWidth, vHeight, 0]); - } - - this.genBuffer(); -} - - -ParticleSystem.prototype.resizeView = function(vWidth, vHeight) { - this.vWidth = vWidth; - this.vHeight = vHeight; - - if (this.pTex !== null) { - this.shader_particle.addVector("screenDim"); - this.shader_particle.setVector("screenDim", [vWidth, vHeight, 0]); - } -}; - - -ParticleSystem.prototype.addParticle = function(p) { - if (this.last_particle === null) { - this.particles = p; - this.last_particle = p; - } else { - this.last_particle.nextParticle = p; - this.last_particle = p; - } -}; - -ParticleSystem.prototype.genBuffer = function() { - var gl = GLCore.gl; - - this.glPoints = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.glPoints); - gl.bufferData(gl.ARRAY_BUFFER, this.arPoints, gl.DYNAMIC_DRAW); - - if (this.hasColor) { - this.glColor = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.glColor); - gl.bufferData(gl.ARRAY_BUFFER, this.arColor, gl.DYNAMIC_DRAW); - } -}; - -ParticleSystem.prototype.updatePoints = function() { - var gl = GLCore.gl; - - // buffer update - gl.bindBuffer(gl.ARRAY_BUFFER, this.glPoints); - gl.bufferData(gl.ARRAY_BUFFER, this.arPoints, gl.DYNAMIC_DRAW); - // end buffer update -}; - -ParticleSystem.prototype.updateColors = function() { - var gl = GLCore.gl; - - if (!this.hasColor) { - return; - } - // buffer update - gl.bindBuffer(gl.ARRAY_BUFFER, this.glColor); - gl.bufferData(gl.ARRAY_BUFFER, this.arColor, gl.DYNAMIC_DRAW); - // end buffer update -}; - -ParticleSystem.prototype.draw = function(modelViewMat, projectionMat, time) { - var gl = GLCore.gl; - - this.shader_particle.use(); - - if (this.pTex !== null) { - this.pTex.use(gl.TEXTURE0); - } - - this.shader_particle.setMatrix("uMVMatrix", modelViewMat); - this.shader_particle.setMatrix("uPMatrix", projectionMat); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.glPoints); - gl.vertexAttribPointer(this.shader_particle.uniforms["aVertexPosition"], 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(this.shader_particle.uniforms["aVertexPosition"]); - - if (this.hasColor) { - gl.bindBuffer(gl.ARRAY_BUFFER, this.glColor); - gl.vertexAttribPointer(this.shader_particle.uniforms["aColor"], 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(this.shader_particle.uniforms["aColor"]); - } - - if (time === undef) { - time = 0; - } - - if (this.particles === null) { - gl.disable(gl.BLEND); - return; - } - - var p = this.particles; - var lp = null; - - - this.numParticles = 0; - - var c = 0; - - while (p !== null) { - var ofs = this.numParticles * 3; - var pf = this.pfunc(p, time); - - if (pf === 1) { - this.arPoints[ofs] = p.pos[0]; - this.arPoints[ofs + 1] = p.pos[1]; - this.arPoints[ofs + 2] = p.pos[2]; - - if (p.color !== null && this.arColor !== undef) { - this.arColor[ofs] = p.color[0]; - this.arColor[ofs + 1] = p.color[1]; - this.arColor[ofs + 2] = p.color[2]; - } - - this.numParticles++; - c++; - if (this.numParticles === this.maxPoints) { - break; - } - } else if (pf === -1) // particle death - { - if (lp !== null) { - lp.nextParticle = p.nextParticle; - } - } - else if (pf === 0) { - c++; - } - - lp = p; - p = p.nextParticle; - } - - if (!c) { - this.particles = null; - this.last_particle = null; - } - - this.updatePoints(); - if (this.hasColor) { - this.updateColors(); - } - - if (this.alpha) { - gl.enable(gl.BLEND); - gl.enable(gl.DEPTH_TEST); - gl.depthMask(0); - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - - gl.drawArrays(gl.POINTS, 0, this.numParticles); - - if (this.alpha) { - // gl.enable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - gl.depthMask(1); - gl.blendFunc(gl.ONE, gl.ONE); - } - - if (this.hasColor) { - gl.disableVertexAttribArray(this.shader_particle.uniforms["aColor"]); - } -}; - -/* SkyBox */ - -function SkyBox(in_obj) { - var texture = in_obj.texture; - var mapping = in_obj.mapping; - - var that = this; - - this.mapping = null; - this.ready = false; - this.texture = null; - - this.onready = function() { - texture.onready = null; - var tw = 1/Images[that.texture.tex_id].width; - var th = 1/Images[that.texture.tex_id].height; - if (that.mapping === null) { - that.mapping = [[1/3, 0.5, 2/3-tw, 1],//top - [0, 0.5, 1/3, 1], //bottom - [0, 0, 1/3-tw, 0.5], //left - [2/3, 0, 1, 0.5], //right - [2/3+tw, 0.5, 1, 1], //front - [1/3, 0, 2/3, 0.5]]; //back - } //if - - var mat = new Material("skybox"); - var obj = new Mesh(); - obj.sky_mapping = that.mapping; - cubicvr_boxObject(obj, 1, mat); - obj.calcNormals(); - var mat_map = new UVMapper(); - mat_map.projection_mode = enums.uv.projection.SKY; - mat_map.scale = [1, 1, 1]; - mat_map.apply(obj, mat); - obj.triangulateQuads(); - obj.compile(); - mat.setTexture(texture); - that.scene_object = new SceneObject(obj); - - that.ready = true; - } //onready - - if (texture) { - if (typeof(texture) === "string") { - texture = new Texture(texture, null, null, null, this.onready); - } - else if (!texture.loaded){ - texture.onready = this.onready; - } //if - this.texture = texture; - - if (mapping) { - this.mapping = mapping; - this.onready(); - } //if - } //if -} //cubicvr_SkyBox::Constructor - - - - -function View(obj_init) { - - this.texture = obj_init.texture?obj_init.texture:null; - this.width = obj_init.width?obj_init.width:128; - this.height = obj_init.height?obj_init.height:128; - this.x = obj_init.x?obj_init.x:0; - this.y = obj_init.y?obj_init.y:0; - this.blend = obj_init.blend?obj_init.blend:false; - this.opacity = (typeof(obj_init.opacity)!=='undefined')?obj_init.opacity:1.0; - this.tint = obj_init.tint?obj_init.tint:[1.0,1.0,1.0]; - - this.type='view'; - - this.superView = null; - this.childViews = []; - this.panel = null; -} - -View.prototype.addSubview = function(view) { - this.childViews.push(view); -// this.superView.makePanel(view); - view.superView = this; -} - -View.prototype.makePanel = function(view) { - return this.superView.makePanel(view); -} - -function Layout(obj_init) { - - this.texture = obj_init.texture?obj_init.texture:null; - this.width = obj_init.width?obj_init.width:128; - this.height = obj_init.height?obj_init.height:128; - this.x = obj_init.x?obj_init.x:0; - this.y = obj_init.y?obj_init.y:0; - this.blend = obj_init.blend?obj_init.blend:false; - this.opacity = (typeof(obj_init.opacity)!=='undefined')?obj_init.opacity:1.0; - this.tint = obj_init.tint?obj_init.tint:[1.0,1.0,1.0]; - - this.type = 'root'; - - this.superView = null; - this.childViews = []; - this.setupShader(); - - this.panel = null; - this.makePanel(this); -} - -Layout.prototype.setupShader = function() { - - this.shader = new CubicVR.PostProcessShader({ - shader_vertex: ["attribute vec3 aVertex;", - "attribute vec2 aTex;", - "varying vec2 vTex;", - "uniform vec3 screen;", - "uniform vec3 position;", - "uniform vec3 size;", - "void main(void) {", - "vTex = aTex;", - "vec4 vPos = vec4(aVertex.xyz,1.0);", - "vPos.x *= size.x/screen.x;", - "vPos.y *= size.y/screen.y;", - "vPos.x += (size.x/screen.x);", - "vPos.y -= (size.y/screen.y);", - "vPos.x += (position.x/screen.x)*2.0 - 1.0;", - "vPos.y -= (position.y/screen.y)*2.0 - 1.0;", - "gl_Position = vPos;", - "}"].join("\n"), - shader_fragment: [ - "#ifdef GL_ES", - "precision highp float;", - "#endif", - "uniform sampler2D srcTex;", - "uniform vec3 tint;", - "varying vec2 vTex;", - "void main(void) {", - "vec4 color = texture2D(srcTex, vTex)*vec4(tint,1.0);", - "if (color.a == 0.0) discard;", - "gl_FragColor = color;", - "}"].join("\n"), - init: function(shader) - { - shader.setInt("srcTex",0); - shader.addVector("screen"); - shader.addVector("position"); - shader.addVector("tint"); - shader.addVector("size"); - } - }); -} - -Layout.prototype.addSubview = function(view) { - this.childViews.push(view); -// this.makePanel(view); - view.superView = this; -} - -Layout.prototype.makePanel = function(view) { - var gl = CubicVR.GLCore.gl; - var pQuad = {}; // intentional empty object - - pQuad.vbo_points = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0]); - pQuad.vbo_uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1]); - - pQuad.gl_points = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, pQuad.gl_points); - gl.bufferData(gl.ARRAY_BUFFER, pQuad.vbo_points, gl.STATIC_DRAW); - - pQuad.gl_uvs = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, pQuad.gl_uvs); - gl.bufferData(gl.ARRAY_BUFFER, pQuad.vbo_uvs, gl.STATIC_DRAW); - - view.panel = pQuad; -} - - -Layout.prototype.renderPanel = function(view,panel) { - var gl = CubicVR.GLCore.gl; - - if (!view.texture) { - return false; - } - - view.texture.use(gl.TEXTURE0); -}; - - -Layout.prototype.renderView = function(view) { - if (!view.texture) return; - - var gl = CubicVR.GLCore.gl; - - var offsetLeft = view.offsetLeft; - var offsetTop = view.offsetTop; - - if (!offsetLeft) offsetLeft = 0; - if (!offsetTop) offsetTop = 0; - - var shader = this.shader.shader; - - shader.use(); - shader.setVector("screen",[this.width,this.height,0]); - shader.setVector("position",[view.x+offsetLeft,view.y+offsetTop,0]); - shader.setVector("size",[view.width,view.height,0]); - shader.setVector("tint",view.tint); - - if (view.blend) { - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); - } - - view.texture.use(gl.TEXTURE0); - -// this.renderPanel(view,this.panel); - gl.drawArrays(gl.TRIANGLES, 0, 6); - - if (view.blend) { - gl.disable(gl.BLEND); - gl.blendFunc(gl.ONE,gl.ZERO); - } -} - - - -Layout.prototype.render = function() { - var gl = CubicVR.GLCore.gl; - - gl.disable(gl.DEPTH_TEST); - - if (this.texture) this.renderView(this); - - var stack = []; - var framestack = []; - - this.offsetLeft = 0, this.offsetTop = 0; - stack.push(this); - - - shader = this.shader.shader; - shader.use(); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.panel.gl_points); - gl.vertexAttribPointer(shader.uniforms["aVertex"], 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(shader.uniforms["aVertex"]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.panel.gl_uvs); - gl.vertexAttribPointer(shader.uniforms["aTex"], 2, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(shader.uniforms["aTex"]); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - - while (stack.length) { - var view = stack.pop(); - - this.renderView(view); - - if (view.childViews.length) { - for (var i = view.childViews.length-1, iMin = 0; i >= iMin; i--) { - view.childViews[i].offsetLeft = view.x+view.offsetLeft; - view.childViews[i].offsetTop = view.y+view.offsetTop; - stack.push(view.childViews[i]); - } - } - - } - - - gl.disableVertexAttribArray(shader.uniforms["aTex"]); - - gl.enable(gl.DEPTH_TEST); -} - - -// Full-screen quad related -var fsQuad = { - make:makeFSQuad, - destroy:destroyFSQuad, - render:renderFSQuad -}; - - - -// Extend CubicVR module by adding public methods and classes -var extend = { - init: GLCore.init, - enums: enums, - vec2: vec2, - vec3: vec3, - mat4: mat4, - util: util, - fsQuad: fsQuad, - IdentityMatrix: cubicvr_identity, - GLCore: GLCore, - Timer: Timer, - MainLoop: MainLoop, - MouseViewController: MouseViewController, - setMainLoop: setMainLoop, - Transform: Transform, - Light: Light, - Texture: Texture, - PJSTexture: PJSTexture, - CanvasTexture: CanvasTexture, - TextTexture: TextTexture, - UVMapper: UVMapper, - Scene: Scene, - SceneObject: SceneObject, - Face: Face, - Material: Material, - Materials: Materials, - Textures: Textures, - Textures_obj: Textures_obj, - Images: Images, - Shader: Shader, - Landscape: Landscape, - Camera: Camera, - GML: GML, - SkyBox: SkyBox, - Envelope: Envelope, - Motion: Motion, - RenderBuffer: RenderBuffer, - PostProcessFX: PostProcessFX, - PostProcessChain: PostProcessChain, - PostProcessShader: PostProcessShader, - NormalMapGen: NormalMapGen, - Particle: Particle, - ParticleSystem: ParticleSystem, - Octree: Octree, - OctreeWorker: OctreeWorkerProxy, - Quaternion: Quaternion, - AutoCamera: AutoCamera, - Mesh: Mesh, - MeshPool: MeshPool, - genPlaneObject: cubicvr_planeObject, - genBoxObject: cubicvr_boxObject, - genLatheObject: cubicvr_latheObject, - genTorusObject: cubicvr_torusObject, - genConeObject: cubicvr_coneObject, - genCylinderObject: cubicvr_cylinderObject, - genSphereObject: cubicvr_sphereObject, - primitives: primitives, - renderObject: cubicvr_renderObject, - globalAmbient: [0.1, 0.1, 0.1], - setGlobalAmbient: function(c) { - CubicVR.globalAmbient = c; - }, - loadMesh: cubicvr_loadMesh, - DeferredBin: DeferredBin, - DeferredLoadTexture: DeferredLoadTexture, - loadCollada: cubicvr_loadCollada, - loadColladaWorker: cubicvr_loadColladaWorker, - setGlobalDepthAlpha: GLCore.setDepthAlpha, - setDefaultFilter: GLCore.setDefaultFilter, - Worker: CubicVR_Worker, - Layout: Layout, - View: View -}; - -for (var ext in extend) { - if (extend.hasOwnProperty(ext)) { - this.CubicVR[ext] = extend[ext]; - } -} - -Materials.push(new Material("(null)")); -}()); - |
