diff --git a/examples/js/loaders/sea3d/SEA3D.js b/examples/js/loaders/sea3d/SEA3D.js index 541d673d47121b..7602f06db75482 100644 --- a/examples/js/loaders/sea3d/SEA3D.js +++ b/examples/js/loaders/sea3d/SEA3D.js @@ -3,6 +3,8 @@ * @author Sunag / http://www.sunag.com.br/ */ +'use strict'; + var SEA3D = { VERSION : 17000 } SEA3D.getVersion = function() { @@ -11,58 +13,89 @@ SEA3D.getVersion = function() { var v = SEA3D.VERSION.toString(), l = v.length; return v.substring( 0, l - 4 ) + "." + v.substring( l - 4, l - 3 ) + "." + v.substring( l - 3, l - 2 ) + "." + parseFloat( v.substring( l - 2, l ) ).toString(); -} +}; console.log( 'SEA3D ' + SEA3D.getVersion() ); // -// Timer +// STREAM : STANDARD DATA-IO ( LITTLE-ENDIAN ) // -SEA3D.Timer = function() { +SEA3D.Stream = function( buffer ) { - this.time = this.start = Date.now(); + this.position = 0; + this.buffer = buffer || new ArrayBuffer(); -} +}; -SEA3D.Timer.prototype = { - constructor: SEA3D.Timer, +SEA3D.Stream.NONE = 0; - get now () { +// 1D = 0 at 31 +SEA3D.Stream.BOOLEAN = 1; - return Date.now(); +SEA3D.Stream.BYTE = 2; +SEA3D.Stream.UBYTE = 3; - }, +SEA3D.Stream.SHORT = 4; +SEA3D.Stream.USHORT = 5; - get deltaTime () { +SEA3D.Stream.INT24 = 6; +SEA3D.Stream.UINT24 = 7; - return Date.now() - this.time; +SEA3D.Stream.INT = 8; +SEA3D.Stream.UINT = 9; - }, +SEA3D.Stream.FLOAT = 10; +SEA3D.Stream.DOUBLE = 11; +SEA3D.Stream.DECIMAL = 12; - get elapsedTime () { +// 2D = 32 at 63 - return Date.now() - this.start; +// 3D = 64 at 95 +SEA3D.Stream.VECTOR3D = 74; - }, +// 4D = 96 at 127 +SEA3D.Stream.VECTOR4D = 106; - update: function () { +// Undefined Size = 128 at 255 +SEA3D.Stream.STRING_TINY = 128; +SEA3D.Stream.STRING_SHORT = 129; +SEA3D.Stream.STRING_LONG = 130; - this.time = Date.now(); +SEA3D.Stream.ASSET = 200; +SEA3D.Stream.GROUP = 255; - } -} +SEA3D.Stream.BLEND_MODE = [ + "normal", "add", "subtract", "multiply", "dividing", "alpha", "screen", "darken", + "overlay", "colorburn", "linearburn", "lighten", "colordodge", "lineardodge", + "softlight", "hardlight", "pinlight", "spotlight", "spotlightblend", "hardmix", + "average", "difference", "exclusion", "hue", "saturation", "color", "value" +]; -// -// STREAM : STANDARD DATA-IO ( LITTLE-ENDIAN ) -// +SEA3D.Stream.INTERPOLATION_TABLE = [ + "normal", "linear", + "sine.in", "sine.out", "sine.inout", + "cubic.in", "cubic.out", "cubic.inout", + "quint.in", "quint.out", "quint.inout", + "circ.in", "circ.out", "circ.inout", + "back.in", "back.out", "back.inout", + "quad.in", "quad.out", "quad.inout", + "quart.in", "quart.out", "quart.inout", + "expo.in", "expo.out", "expo.inout", + "elastic.in", "elastic.out", "elastic.inout", + "bounce.in", "bounce.out", "bounce.inout" +]; -SEA3D.Stream = function( buffer ) { +SEA3D.Stream.sizeOf = function( kind ) { - this.position = 0; - this.buffer = buffer || new ArrayBuffer(); + if ( kind == 0 ) return 0; + else if ( kind >= 1 && kind <= 31 ) return 1; + else if ( kind >= 32 && kind <= 63 ) return 2; + else if ( kind >= 64 && kind <= 95 ) return 3; + else if ( kind >= 96 && kind <= 125 ) return 4; + return - 1; -} +}; SEA3D.Stream.prototype = { constructor: SEA3D.Stream, @@ -86,7 +119,7 @@ SEA3D.Stream.prototype = { return this.length - this.position; } -} +}; SEA3D.Stream.prototype.readBytes = function( len ) { @@ -94,43 +127,25 @@ SEA3D.Stream.prototype.readBytes = function( len ) { this.position += len; return buf; -} - -SEA3D.Stream.bufferToBase64 = function( buffer ) { - - buffer = new Uint8Array( buffer ); - - var i = 0, - count = buffer.length, - binary = ""; - - while ( i < count ) { - - binary += String.fromCharCode( buffer[ i ++ ] ); - - } - - return window.btoa( binary ); - -} +}; SEA3D.Stream.prototype.readByte = function() { return this.data.getInt8( this.position ++ ); -} +}; SEA3D.Stream.prototype.readUByte = function() { return this.data.getUint8( this.position ++ ); -} +}; SEA3D.Stream.prototype.readBool = function() { return this.data.getInt8( this.position ++ ) != 0; -} +}; SEA3D.Stream.prototype.readShort = function() { @@ -138,7 +153,7 @@ SEA3D.Stream.prototype.readShort = function() { this.position += 2; return v; -} +}; SEA3D.Stream.prototype.readUShort = function() { @@ -146,13 +161,13 @@ SEA3D.Stream.prototype.readUShort = function() { this.position += 2; return v; -} +}; SEA3D.Stream.prototype.readUInt24 = function() { return this.readUShort() | ( this.readUByte() << 16 ); -} +}; SEA3D.Stream.prototype.readInt = function() { @@ -160,7 +175,7 @@ SEA3D.Stream.prototype.readInt = function() { this.position += 4; return v; -} +}; SEA3D.Stream.prototype.readUInt = function() { @@ -168,7 +183,7 @@ SEA3D.Stream.prototype.readUInt = function() { this.position += 4; return v; -} +}; SEA3D.Stream.prototype.readFloat = function() { @@ -176,7 +191,7 @@ SEA3D.Stream.prototype.readFloat = function() { this.position += 4; return v; -} +}; SEA3D.Stream.prototype.readUInteger = function() { @@ -199,25 +214,25 @@ SEA3D.Stream.prototype.readUInteger = function() { return r; -} +}; SEA3D.Stream.prototype.readVector2 = function() { return { x: this.readFloat(), y: this.readFloat() } -} +}; SEA3D.Stream.prototype.readVector3 = function() { return { x: this.readFloat(), y: this.readFloat(), z: this.readFloat() } -} +}; SEA3D.Stream.prototype.readVector4 = function() { return { x: this.readFloat(), y: this.readFloat(), z: this.readFloat(), w: this.readFloat() } -} +}; SEA3D.Stream.prototype.readMatrix = function() { @@ -242,193 +257,299 @@ SEA3D.Stream.prototype.readMatrix = function() { return mtx; -} +}; SEA3D.Stream.prototype.readUTF = function( len ) { - return String.fromCharCode.apply( null, new Uint16Array( new Uint8Array( this.readBytes( len ) ) ) ); + return String.fromCharCode.apply( undefined, new Uint16Array( new Uint8Array( this.readBytes( len ) ) ) ); -} +}; SEA3D.Stream.prototype.readExt = function() { return this.readUTF( 4 ).replace( /\0/g, "" ); -} +}; SEA3D.Stream.prototype.readUTF8 = function() { return this.readUTF( this.readUByte() ); -} +}; SEA3D.Stream.prototype.readUTF8Short = function() { return this.readUTF( this.readUShort() ); -} +}; SEA3D.Stream.prototype.readUTF8Long = function() { return this.readUTF( this.readUInt() ); -} +}; + +SEA3D.Stream.prototype.readUByteArray = function( length ) { + + var v = new Uint8Array( length ); + + SEA3D.Stream.memcpy( + v.buffer, + 0, + this.buffer, + this.position, + length + ); + + this.position += length; + + return v; + +}; + +SEA3D.Stream.prototype.readUShortArray = function( length ) { + + var v = new Uint16Array( length ), + len = length * 2; + + SEA3D.Stream.memcpy( + v.buffer, + 0, + this.buffer, + this.position, + len + ); + + this.position += len; + + return v; + +}; + +SEA3D.Stream.prototype.readUIntArray = function( length ) { + + var v = new Uint32Array( length ), + len = length * 2; + + SEA3D.Stream.memcpy( + v.buffer, + 0, + this.buffer, + this.position, + len + ); + + this.position += len; + + return v; + +}; + +SEA3D.Stream.prototype.readFloatArray = function( length ) { + + var v = new Float32Array( length ), + len = length * 4; + + SEA3D.Stream.memcpy( + v.buffer, + 0, + this.buffer, + this.position, + len + ); + + this.position += len; + + return v; + +}; + SEA3D.Stream.prototype.readBlendMode = function() { - return SEA3D.DataTable.BLEND_MODE[ this.readUByte() ]; + return SEA3D.Stream.BLEND_MODE[ this.readUByte() ]; -} +}; -SEA3D.Stream.prototype.toBase64 = function() { +SEA3D.Stream.prototype.readInterpolation = function() { - return SEA3D.Stream.bufferToBase64( this.data ); + return SEA3D.Stream.INTERPOLATION_TABLE[ this.readUByte() ]; -} +}; -SEA3D.Stream.prototype.append = function( data ) { +SEA3D.Stream.prototype.readTags = function( callback ) { - var tmp = new ArrayBuffer( this.data.byteLength + data.byteLength ); - tmp.set( new ArrayBuffer( this.data ), 0 ); - tmp.set( new ArrayBuffer( data ), this.data.byteLength ); - this.data = tmp; + var numTag = this.readUByte(); -} + for ( var i = 0; i < numTag; ++ i ) { -SEA3D.Stream.prototype.concat = function( position, length ) { + var kind = this.readUShort(); + var size = this.readUInt(); + var pos = this.position; - return new SEA3D.Stream( this.buffer.slice( position, position + length ) ); + callback( kind, data, size ); -} + this.position = pos += size; -// -// Data Table -// + } -SEA3D.DataTable = { - NONE : 0, +}; - // 1D = 0 at 31 - BOOLEAN : 1, +SEA3D.Stream.prototype.readProperties = function( sea ) { - BYTE : 2, - UBYTE : 3, + var count = this.readUByte(), + props = {}, types = {}; - SHORT : 4, - USHORT : 5, + props.__type = types; - INT24 : 6, - UINT24 : 7, + for ( var i = 0; i < count; i ++ ) { - INT : 8, - UINT : 9, + var name = this.readUTF8(), + type = this.readUByte(); - FLOAT : 10, - DOUBLE : 11, - DECIMAL : 12, + props[ name ] = this.readToken( type, sea ); + types[ name ] = type; - // 2D = 32 at 63 + } - // 3D = 64 at 95 - VECTOR3D : 74, + return props; - // 4D = 96 at 127 - VECTOR4D : 106, +}; - // Undefined Size = 128 at 255 - STRING_TINY : 128, - STRING_SHORT : 129, - STRING_LONG : 130, +SEA3D.Stream.prototype.readAnimationList = function( sea ) { - ASSET : 200, - GROUP : 255 -} + var list = [], + count = this.readUByte(); -SEA3D.DataTable.BLEND_MODE = [ - "normal", "add", "subtract", "multiply", "dividing", "alpha", "screen", "darken", - "overlay", "colorburn", "linearburn", "lighten", "colordodge", "lineardodge", - "softlight", "hardlight", "pinlight", "spotlight", "spotlightblend", "hardmix", - "average", "difference", "exclusion", "hue", "saturation", "color", "value" -] + var i = 0; + while ( i < count ) { -SEA3D.DataTable.INTERPOLATION_TABLE = [ - "normal", "linear", - "sine.in", "sine.out", "sine.inout", - "cubic.in", "cubic.out", "cubic.inout", - "quint.in", "quint.out", "quint.inout", - "circ.in", "circ.out", "circ.inout", - "back.in", "back.out", "back.inout", - "quad.in", "quad.out", "quad.inout", - "quart.in", "quart.out", "quart.inout", - "expo.in", "expo.out", "expo.inout", - "elastic.in", "elastic.out", "elastic.inout", - "bounce.in", "bounce.out", "bounce.inout" -] + var attrib = this.readUByte(), + anm = {}; + + anm.relative = ( attrib & 1 ) != 0; + + if ( attrib & 2 ) anm.timeScale = this.readFloat(); + + anm.tag = sea.getObject( this.readUInt() ); + + list[ i ++ ] = anm; -SEA3D.DataTable.readObject = function( data, sea ) { + } + + return list; + +}; + +SEA3D.Stream.prototype.readScriptList = function( sea ) { + + var list = [], + count = this.readUByte(); + + var i = 0; + while ( i < count ) { + + var attrib = this.readUByte(), + script = {}; + + script.priority = ( attrib & 1 ) | ( attrib & 2 ); + + if ( attrib & 4 ) { + + var numParams = data.readUByte(); + + script.params = {}; + + for ( var j = 0; j < numParams; j ++ ) { + + var name = this.readUTF8(); + + script.params[ name ] = this.readObject( sea ); + + } + + } + + if ( attrib & 8 ) { + + script.method = this.readUTF8(); + + } + + script.tag = sea.getObject( this.readUInt() ); + + list[ i ++ ] = script; + + } + + return list; - return SEA3D.DataTable.readToken( data.readUByte(), data, sea ); +}; -} +SEA3D.Stream.prototype.readObject = function( sea ) { -SEA3D.DataTable.readToken = function( type, data, sea ) { + return this.readToken( this.readUByte(), sea ); + +}; + +SEA3D.Stream.prototype.readToken = function( type, sea ) { switch ( type ) { // 1D - case SEA3D.DataTable.BOOLEAN: - return data.readBool(); + case SEA3D.Stream.BOOLEAN: + return this.readBool(); break; - case SEA3D.DataTable.UBYTE: - return data.readUByte(); + case SEA3D.Stream.UBYTE: + return this.readUByte(); break; - case SEA3D.DataTable.USHORT: - return data.readUShort(); + case SEA3D.Stream.USHORT: + return this.readUShort(); break; - case SEA3D.DataTable.UINT24: - return data.readUInt24(); + case SEA3D.Stream.UINT24: + return this.readUInt24(); break; - case SEA3D.DataTable.INT: - return data.readInt(); + case SEA3D.Stream.INT: + return this.readInt(); break; - case SEA3D.DataTable.UINT: - return data.readUInt(); + case SEA3D.Stream.UINT: + return this.readUInt(); break; - case SEA3D.DataTable.FLOAT: - return data.readFloat(); + case SEA3D.Stream.FLOAT: + return this.readFloat(); break; // 3D - case SEA3D.DataTable.VECTOR3D: - return data.readVector3(); + case SEA3D.Stream.VECTOR3D: + return this.readVector3(); break; // 4D - case SEA3D.DataTable.VECTOR4D: - return data.readVector4(); + case SEA3D.Stream.VECTOR4D: + return this.readVector4(); break; // Undefined Values - case SEA3D.DataTable.STRING_TINY: + case SEA3D.Stream.STRING_TINY: return data.readUTF8(); break; - case SEA3D.DataTable.STRING_SHORT: - return data.readUTF8Short(); + case SEA3D.Stream.STRING_SHORT: + return this.readUTF8Short(); break; - case SEA3D.DataTable.STRING_LONG: - return data.readUTF8Long(); + case SEA3D.Stream.STRING_LONG: + return v.readUTF8Long(); break - case SEA3D.DataTable.ASSET: - var asset = data.readUInt(); + case SEA3D.Stream.ASSET: + var asset = this.readUInt(); return asset > 0 ? sea.getObject( asset - 1 ).tag : null; break; @@ -439,103 +560,126 @@ SEA3D.DataTable.readToken = function( type, data, sea ) { return null; -} +}; -SEA3D.DataTable.readVector = function( type, data, out, length, offset ) { +SEA3D.Stream.prototype.readVector = function( type, length, offset ) { - var size = SEA3D.DataTable.sizeOf( type ), + var size = SEA3D.Stream.sizeOf( type ), i = offset * size, count = i + ( length * size ); switch ( type ) { // 1D - case SEA3D.DataTable.BOOLEAN: - while ( i < count ) { + case SEA3D.Stream.BOOLEAN: - out[ i ++ ] = data.readBool() ? 1 : 0; + return this.readUByteArray( count ); - } - break; - case SEA3D.DataTable.UBYTE: - while ( i < count ) { + case SEA3D.Stream.UBYTE: - out[ i ++ ] = data.readUByte(); + return this.readUByteArray( count ); - } - break; - case SEA3D.DataTable.USHORT: - while ( i < count ) { + case SEA3D.Stream.USHORT: - out[ i ++ ] = data.readUShort(); + return this.readUShortArray( count ); - } - break; - case SEA3D.DataTable.UINT24: - while ( i < count ) { + case SEA3D.Stream.UINT24: - out[ i ++ ] = data.readUInt24(); + return this.readUInt24Array( count ); - } - break; - case SEA3D.DataTable.UINT: - while ( i < count ) { + case SEA3D.Stream.UINT: - out[ i ++ ] = data.readUInt(); + return this.readUIntArray( count ); - } - break; - case SEA3D.DataTable.FLOAT: - while ( i < count ) { + case SEA3D.Stream.FLOAT: - out[ i ++ ] = data.readFloat(); + return this.readFloatArray( count ); - } - break; // 3D - case SEA3D.DataTable.VECTOR3D: - while ( i < count ) - { + case SEA3D.Stream.VECTOR3D: - out[ i ++ ] = data.readFloat(); - out[ i ++ ] = data.readFloat(); - out[ i ++ ] = data.readFloat(); + return this.readFloatArray( count ); - } - break; // 4D - case SEA3D.DataTable.VECTOR4D: - while ( i < count ) - { + case SEA3D.Stream.VECTOR4D: - out[ i ++ ] = data.readFloat(); - out[ i ++ ] = data.readFloat(); - out[ i ++ ] = data.readFloat(); - out[ i ++ ] = data.readFloat(); + return this.readFloatArray( count ); - } - break; } -} +}; -SEA3D.DataTable.sizeOf = function( kind ) { +SEA3D.Stream.prototype.append = function( data ) { - if ( kind == 0 ) return 0; - else if ( kind >= 1 && kind <= 31 ) return 1; - else if ( kind >= 32 && kind <= 63 ) return 2; - else if ( kind >= 64 && kind <= 95 ) return 3; - else if ( kind >= 96 && kind <= 125 ) return 4; - return - 1; + var tmp = new ArrayBuffer( this.data.byteLength + data.byteLength ); + tmp.set( new ArrayBuffer( this.data ), 0 ); + tmp.set( new ArrayBuffer( data ), this.data.byteLength ); + this.data = tmp; + +}; -} +SEA3D.Stream.prototype.concat = function( position, length ) { + + return new SEA3D.Stream( this.buffer.slice( position, position + length ) ); + +}; + +/** + * @author DataStream.js + */ + +SEA3D.Stream.memcpy = function( dst, dstOffset, src, srcOffset, byteLength ) { + + var dstU8 = new Uint8Array( dst, dstOffset, byteLength ); + var srcU8 = new Uint8Array( src, srcOffset, byteLength ); + + dstU8.set( srcU8 ); + +}; + +// +// UByteArray +// + +SEA3D.UByteArray = function() { + + this.ubytes = []; + this.length = 0; + +}; + +SEA3D.UByteArray.prototype = { + constructor: SEA3D.UByteArray, + + add : function ( ubytes ) { + + this.ubytes.push( ubytes ); + this.length += ubytes.byteLength; + + }, + + toBuffer : function () { + + var memcpy = new Uint8Array( this.length ); + + for ( var i = 0, offset = 0; i < this.ubytes.length; i ++ ) { + + memcpy.set( this.ubytes[ i ], offset ); + offset += this.ubytes[ i ].byteLength; + + } + + return memcpy.buffer; + + } +}; // // Math @@ -544,7 +688,7 @@ SEA3D.DataTable.sizeOf = function( kind ) { SEA3D.Math = { DEGREES : 180 / Math.PI, RADIANS : Math.PI / 180 -} +}; SEA3D.Math.angle = function( val ) { @@ -553,8 +697,7 @@ SEA3D.Math.angle = function( val ) { val = ( inv ? - val : val ) % 360; - if ( val > ang ) - { + if ( val > ang ) { val = - ang + ( val - ang ); @@ -562,21 +705,18 @@ SEA3D.Math.angle = function( val ) { return ( inv ? - val : val ); -} +}; SEA3D.Math.lerpAngle = function( val, tar, t ) { - if ( Math.abs( val - tar ) > 180 ) - { + if ( Math.abs( val - tar ) > 180 ) { - if ( val > tar ) - { + if ( val > tar ) { tar += 360; } - else - { + else { tar -= 360; @@ -588,7 +728,7 @@ SEA3D.Math.lerpAngle = function( val, tar, t ) { return SEA3D.Math.angle( val ); -} +}; SEA3D.Math.lerpColor = function( val, tar, t ) { @@ -609,19 +749,19 @@ SEA3D.Math.lerpColor = function( val, tar, t ) { return a0 << 24 | r0 << 16 | g0 << 8 | b0; -} +}; SEA3D.Math.lerp = function( val, tar, t ) { return val + ( ( tar - val ) * t ); -} +}; SEA3D.Math.lerp1x = function( val, tar, t ) { val[ 0 ] += ( tar[ 0 ] - val[ 0 ] ) * t; -} +}; SEA3D.Math.lerp3x = function( val, tar, t ) { @@ -629,19 +769,19 @@ SEA3D.Math.lerp3x = function( val, tar, t ) { val[ 1 ] += ( tar[ 1 ] - val[ 1 ] ) * t; val[ 2 ] += ( tar[ 2 ] - val[ 2 ] ) * t; -} +}; SEA3D.Math.lerpAng1x = function( val, tar, t ) { val[ 0 ] = SEA3D.Math.lerpAngle( val[ 0 ], tar[ 0 ], t ); -} +}; SEA3D.Math.lerpColor1x = function( val, tar, t ) { val[ 0 ] = SEA3D.Math.lerpColor( val[ 0 ], tar[ 0 ], t ); -} +}; SEA3D.Math.lerpQuat4x = function( val, tar, t ) { @@ -678,44 +818,362 @@ SEA3D.Math.lerpQuat4x = function( val, tar, t ) { val[ 2 ] = z * l; val[ 3 ] = w * l; -} +}; // -// BlendMethod +// Timer // -SEA3D.AnimationBlendMethod = { - LINEAR : 'linear', - EASING : 'easing' -} +SEA3D.Timer = function() { -// -// AnimationFrame -// + this.time = this.start = Date.now(); -SEA3D.AnimationFrame = function() { +}; - this.data = [ 0, 0, 0, 0 ]; +SEA3D.Timer.prototype = { + constructor: SEA3D.Timer, -} + get now () { -SEA3D.AnimationFrame.prototype.toVector = function() { + return Date.now(); - return { x: this.data[ 0 ], y: this.data[ 1 ], z: this.data[ 2 ], w: this.data[ 3 ] }; + }, -} + get deltaTime () { -SEA3D.AnimationFrame.prototype.toAngles = function( d ) { + return Date.now() - this.time; - var x = this.data[ 0 ], - y = this.data[ 1 ], - z = this.data[ 2 ], - w = this.data[ 3 ]; + }, - var a = 2 * ( w * y - z * x ); + get elapsedTime () { - if ( a < - 1 ) a = - 1; - else if ( a > 1 ) a = 1; + return Date.now() - this.start; + + }, + + update: function () { + + this.time = Date.now(); + + } +}; + +// +// Blend Method +// + +SEA3D.AnimationBlendMethod = { + LINEAR : 'linear', + EASING : 'easing' +}; + +// +// Domain +// + +SEA3D.Domain = function( id ) { + + this.id = id; + this.scripts = []; + this.global = {}; + this.events = new SEA3D.EventDispatcher(); + +}; + +SEA3D.Domain.prototype = { + constructor: SEA3D.Domain, + + add : function( src ) { + + this.scripts.push( src ); + + }, + + remove : function( src ) { + + this.scripts.splice( this.scripts.indexOf( src ), 1 ); + + }, + + contains : function( src ) { + + return this.scripts.indexOf( src ) != - 1; + + }, + + addEvent : function( type, listener ) { + + this.events.addEventListener( type, listener ); + + }, + + hasEvent : function( type, listener ) { + + return this.events.hasEventListener( type, listener ); + + }, + + removeEvent : function( type, listener ) { + + this.events.removeEventListener( type, listener ); + + }, + + print : function() { + + console.log.apply( console, arguments ); + + }, + + watch : function() { + + console.log.apply( console, 'watch:', arguments ); + + }, + + getReference : function( ns ) { + + return eval( ns ); + + }, + + dispatchEvent : function( event ) { + + event.domain = this; + + var scripts = this.scripts.concat(), + i = scripts.length; + + while ( i -- ) { + + scripts[ i ].dispatchEvent( event ); + + } + + this.events.dispatchEvent( event ); + + }, + + dispose : function() { + + var scripts = this.scripts.concat(), + i = scripts.length; + + while ( i -- ) { + + scripts[ i ].dispose(); + + } + + this.dispatchEvent( { type : "dispose" } ); + + } +}; + +// +// Domain Manager +// + +SEA3D.DomainManager = function( autoDisposeRootDomain ) { + + this.domains = []; + this.autoDisposeRootDomain = autoDisposeRootDomain == undefined ? true : false; + +}; + +SEA3D.DomainManager.prototype = { + constructor: SEA3D.DomainManager, + + onDisposeDomain : function( e ) { + + this.remove( e.domain ); + + if ( this.autoDisposeRootDomain && this.domains.length == 1 ) { + + this.dispose(); + + } + + }, + + add : function( domain ) { + + this._onDisposeDomain = this._onDisposeDomain || this.onDisposeDomain.bind( this ); + + domain.addEvent( "dispose", this._onDisposeDomain ); + + this.domains.push( domain ); + + }, + + remove : function( domain ) { + + domain.removeEvent( "dispose", this._onDisposeDomain ); + + this.domains.splice( this.domains.indexOf( domain ), 1 ); + + }, + + contains : function( domain ) { + + return this.domains.indexOf( domain ) != - 1; + + }, + + dispose : function() { + + var domains = this.domains.concat(), + i = domains.length; + + while ( i -- ) { + + domains[ i ].dispose(); + + } + + } +}; + + +// +// Script +// + +SEA3D.Script = function( domain, root ) { + + domain = domain || new SEA3D.Domain(); + domain.add( this ); + + var events = new SEA3D.EventDispatcher(); + + this.getId = function() { + + return domain.id; + + } + + this.isRoot = function() { + + return root; + + } + + this.addEvent = function( type, listener ) { + + events.addEventListener( type, listener ); + + } + + this.hasEvent = function( type, listener ) { + + return events.hasEventListener( type, listener ); + + } + + this.removeEvent = function( type, listener ) { + + events.removeEventListener( type, listener ); + + } + + this.dispatchEvent = function( event ) { + + event.script = this; + + events.dispatchEvent( event ); + + } + + this.dispose = function() { + + domain.remove( this ); + + if ( root ) domain.dispose(); + + this.dispatchEvent( { type : "dispose" } ); + + } + +}; + +// +// Script Manager +// + +SEA3D.ScriptManager = function() { + + this.scripts = []; + + var onDisposeScript = ( function( e ) { + + this.remove( e.script ); + + } ).bind( this ); + + this.add = function( src ) { + + src.addEvent( "dispose", onDisposeScript ); + + this.scripts.push( src ); + + } + + this.remove = function( src ) { + + src.removeEvent( "dispose", onDisposeScript ); + + this.scripts.splice( this.scripts.indexOf( src ), 1 ); + + } + + this.contains = function( src ) { + + return this.scripts.indexOf( src ) > - 1; + + } + + this.dispatchEvent = function( event ) { + + var scripts = this.scripts.concat(), + i = scripts.length; + + while ( i -- ) { + + scripts[ i ].dispatchEvent( event ); + + } + + } + +}; + +// +// AnimationFrame +// + +SEA3D.AnimationFrame = function() { + + this.data = [ 0, 0, 0, 0 ]; + +}; + +SEA3D.AnimationFrame.prototype.toVector = function() { + + return { x: this.data[ 0 ], y: this.data[ 1 ], z: this.data[ 2 ], w: this.data[ 3 ] }; + +}; + +SEA3D.AnimationFrame.prototype.toAngles = function( d ) { + + var x = this.data[ 0 ], + y = this.data[ 1 ], + z = this.data[ 2 ], + w = this.data[ 3 ]; + + var a = 2 * ( w * y - z * x ); + + if ( a < - 1 ) a = - 1; + else if ( a > 1 ) a = 1; return { x : Math.atan2( 2 * ( w * x + y * z ), 1 - 2 * ( x * x + y * y ) ) * d, @@ -723,67 +1181,67 @@ SEA3D.AnimationFrame.prototype.toAngles = function( d ) { z : Math.atan2( 2 * ( w * z + x * y ), 1 - 2 * ( y * y + z * z ) ) * d } -} +}; SEA3D.AnimationFrame.prototype.toEuler = function() { return this.toAngles( SEA3D.Math.DEGREES ); -} +}; SEA3D.AnimationFrame.prototype.toRadians = function() { return this.toAngles( 1 ); -} +}; SEA3D.AnimationFrame.prototype.setX = function( val ) { this.data[ 0 ] = val; -} +}; SEA3D.AnimationFrame.prototype.getX = function() { return this.data[ 0 ]; -} +}; SEA3D.AnimationFrame.prototype.setY = function( val ) { this.data[ 1 ] = val; -} +}; SEA3D.AnimationFrame.prototype.getY = function() { return this.data[ 1 ]; -} +}; SEA3D.AnimationFrame.prototype.setZ = function( val ) { this.data[ 2 ] = val; -} +}; SEA3D.AnimationFrame.prototype.getZ = function() { return this.data[ 2 ]; -} +}; SEA3D.AnimationFrame.prototype.setW = function( val ) { this.data[ 3 ] = val; -} +}; SEA3D.AnimationFrame.prototype.getW = function() { return this.data[ 3 ]; -} +}; // // AnimationData @@ -793,7 +1251,7 @@ SEA3D.AnimationData = function( kind, dataType, data, offset ) { this.kind = kind; this.type = dataType; - this.blockLength = SEA3D.DataTable.sizeOf( dataType ); + this.blockLength = SEA3D.Stream.sizeOf( dataType ); this.data = data; this.offset = offset == undefined ? 0 : offset; @@ -805,7 +1263,7 @@ SEA3D.AnimationData = function( kind, dataType, data, offset ) { case 4: this.getData = this.getData4x; break; } -} +}; SEA3D.AnimationData.prototype.getData1x = function( frame, data ) { @@ -813,7 +1271,7 @@ SEA3D.AnimationData.prototype.getData1x = function( frame, data ) { data[ 0 ] = this.data[ frame ]; -} +}; SEA3D.AnimationData.prototype.getData2x = function( frame, data ) { @@ -822,7 +1280,7 @@ SEA3D.AnimationData.prototype.getData2x = function( frame, data ) { data[ 0 ] = this.data[ frame ]; data[ 1 ] = this.data[ frame + 1 ]; -} +}; SEA3D.AnimationData.prototype.getData3x = function( frame, data ) { @@ -832,7 +1290,7 @@ SEA3D.AnimationData.prototype.getData3x = function( frame, data ) { data[ 1 ] = this.data[ frame + 1 ]; data[ 2 ] = this.data[ frame + 2 ]; -} +}; SEA3D.AnimationData.prototype.getData4x = function( frame, data ) { @@ -843,7 +1301,7 @@ SEA3D.AnimationData.prototype.getData4x = function( frame, data ) { data[ 2 ] = this.data[ frame + 2 ]; data[ 3 ] = this.data[ frame + 3 ]; -} +}; // // AnimationNode @@ -869,7 +1327,7 @@ SEA3D.AnimationNode = function( name, frameRate, numFrames, repeat, intrpl ) { this.nextFrame = 0; this.frame = 0; -} +}; SEA3D.AnimationNode.prototype.setTime = function( value ) { @@ -877,43 +1335,43 @@ SEA3D.AnimationNode.prototype.setTime = function( value ) { this.time = this.frame * this.frameRate; this.invalidState = true; -} +}; SEA3D.AnimationNode.prototype.getTime = function() { return this.time; -} +}; SEA3D.AnimationNode.prototype.setFrame = function( value ) { this.setTime( value * this.frameMill ); -} +}; SEA3D.AnimationNode.prototype.getRealFrame = function() { return Math.floor( this.frame ); -} +}; SEA3D.AnimationNode.prototype.getFrame = function() { return this.frame; -} +}; SEA3D.AnimationNode.prototype.setPosition = function( value ) { this.setFrame( value * ( this.numFrames - 1 ) ); -} +}; SEA3D.AnimationNode.prototype.getPosition = function() { return this.frame / ( this.numFrames - 1 ); -} +}; SEA3D.AnimationNode.prototype.validFrame = function( value ) { @@ -921,56 +1379,57 @@ SEA3D.AnimationNode.prototype.validFrame = function( value ) { if ( inverse ) value = - value; - if ( value > this.length ) + if ( value > this.length ) { + value = this.repeat ? value % this.length : this.length; + } + if ( inverse ) value = this.length - value; return value; -} +}; SEA3D.AnimationNode.prototype.addData = function( animationData ) { this.dataListId[ animationData.kind ] = animationData; this.dataList[ this.dataList.length ] = animationData; -} +}; SEA3D.AnimationNode.prototype.removeData = function( animationData ) { delete this.dataListId[ animationData.kind ]; this.dataList.splice( this.dataList.indexOf( animationData ), 1 ); -} +}; SEA3D.AnimationNode.prototype.getDataByKind = function( kind ) { return this.dataListId[ kind ]; -} +}; SEA3D.AnimationNode.prototype.getFrameAt = function( frame, id ) { this.dataListId[ id ].getFrameData( frame, this.buffer.data ); return this.buffer; -} +}; SEA3D.AnimationNode.prototype.getFrame = function( id ) { this.dataListId[ id ].getFrameData( this.getRealFrame(), this.buffer.data ); return this.buffer; -} +}; SEA3D.AnimationNode.prototype.getInterpolationFrame = function( animationData, iFunc ) { - if ( this.numFrames == 0 ) - return this.buffer; + if ( this.numFrames == 0 ) return this.buffer; - if ( this.invalidState ) - { + if ( this.invalidState ) { this.prevFrame = this.getRealFrame(); this.nextFrame = this.validFrame( this.prevFrame + 1 ); @@ -981,8 +1440,7 @@ SEA3D.AnimationNode.prototype.getInterpolationFrame = function( animationData, i animationData.getData( this.prevFrame, this.buffer.data ); - if ( this.percent > 0 ) - { + if ( this.percent > 0 ) { animationData.getData( this.nextFrame, SEA3D.AnimationNode.FRAME_BUFFER ); @@ -993,7 +1451,7 @@ SEA3D.AnimationNode.prototype.getInterpolationFrame = function( animationData, i return this.buffer; -} +}; SEA3D.AnimationNode.FRAME_BUFFER = [ 0, 0, 0, 0 ]; @@ -1006,23 +1464,22 @@ SEA3D.AnimationSet = function() { this.animations = []; this.dataCount = - 1; -} +}; SEA3D.AnimationSet.prototype.addAnimation = function( node ) { - if ( this.dataCount == - 1 ) - this.dataCount = node.dataList.length; + if ( this.dataCount == - 1 ) this.dataCount = node.dataList.length; this.animations[ node.name ] = node; this.animations.push( node ); -} +}; SEA3D.AnimationSet.prototype.getAnimationByName = function( name ) { return this.animations[ name ]; -} +}; // // AnimationState @@ -1035,54 +1492,58 @@ SEA3D.AnimationState = function( node ) { this.weight = 0; this.time = 0; -} +}; SEA3D.AnimationState.prototype.setTime = function( val ) { this.node.time = this.time = val; -} +}; SEA3D.AnimationState.prototype.getTime = function() { return this.time; -} +}; SEA3D.AnimationState.prototype.setFrame = function( val ) { this.node.setFrame( val ); + this.time = this.node.time; -} +}; SEA3D.AnimationState.prototype.getFrame = function() { this.update(); + return this.node.getFrame(); -} +}; SEA3D.AnimationState.prototype.setPosition = function( val ) { this.node.setPosition( val ); + this.time = this.node.time; -} +}; SEA3D.AnimationState.prototype.getPosition = function() { this.update(); + return this.node.getPosition(); -} +}; SEA3D.AnimationState.prototype.update = function() { if ( this.node.time != this.time ) this.node.setTime( this.time ); -} +}; // // Animation Handler @@ -1103,7 +1564,7 @@ SEA3D.AnimationHandler = function( animationSet ) { this.updateAllStates = false; this.blendMethod = SEA3D.AnimationBlendMethod.LINEAR; -} +}; SEA3D.AnimationHandler.prototype.update = function( delta ) { @@ -1113,7 +1574,7 @@ SEA3D.AnimationHandler.prototype.update = function( delta ) { this.updateState(); this.updateAnimation(); -} +}; SEA3D.AnimationHandler.prototype.updateState = function() { @@ -1121,28 +1582,35 @@ SEA3D.AnimationHandler.prototype.updateState = function() { this.currentState.node.setTime( this.time - this.currentState.offset ); - if ( this.currentState.weight < 1 && this.crossfade > 0 ) - { + if ( this.currentState.weight < 1 && this.crossfade > 0 ) { var delta = Math.abs( this.delta ) / ( 1000.0 * this.crossfade ); var weight = 1; - if ( this.blendMethod === SEA3D.AnimationBlendMethod.EASING ) + if ( this.blendMethod === SEA3D.AnimationBlendMethod.EASING ) { + delta *= this.easeSpeed; + } + for ( i = 0; i < this.states.length; ++ i ) { state = this.states[ i ]; if ( state !== this.currentState ) { - if ( this.blendMethod === SEA3D.AnimationBlendMethod.LINEAR ) + if ( this.blendMethod === SEA3D.AnimationBlendMethod.LINEAR ) { + state.weight -= delta; - else if ( this.blendMethod === SEA3D.AnimationBlendMethod.EASING ) + + } + else if ( this.blendMethod === SEA3D.AnimationBlendMethod.EASING ) { + state.weight -= state.weight * delta; - if ( state.weight < 0 ) - state.weight = 0; + } + + if ( state.weight < 0 ) state.weight = 0; weight -= state.weight; @@ -1156,8 +1624,7 @@ SEA3D.AnimationHandler.prototype.updateState = function() { } - if ( weight < 0 ) - weight = 0; + if ( weight < 0 ) weight = 0; this.currentState.weight = weight; @@ -1167,8 +1634,7 @@ SEA3D.AnimationHandler.prototype.updateState = function() { state = this.states[ i ]; - if ( state === this.currentState ) - state.weight = 1; + if ( state === this.currentState ) state.weight = 1; else { state.weight = 0; @@ -1185,7 +1651,7 @@ SEA3D.AnimationHandler.prototype.updateState = function() { } -} +}; SEA3D.AnimationHandler.prototype.updateAnimation = function() { @@ -1218,8 +1684,7 @@ SEA3D.AnimationHandler.prototype.updateAnimation = function() { if ( node != currentNode ) { - if ( state.weight > 0 ) - { + if ( state.weight > 0 ) { iFunc( frame.data, @@ -1231,26 +1696,29 @@ SEA3D.AnimationHandler.prototype.updateAnimation = function() { } - if ( this.updateAnimationFrame ) + if ( this.updateAnimationFrame ) { + this.updateAnimationFrame( frame, data.kind ); + } + } } -} +}; SEA3D.AnimationHandler.prototype.getStateByName = function( name ) { return this.states[ name ]; -} +}; SEA3D.AnimationHandler.prototype.getStateNameByIndex = function( index ) { return this.animationSet.animations[ index ].name; -} +}; SEA3D.AnimationHandler.prototype.play = function( name, crossfade, offset ) { @@ -1262,18 +1730,23 @@ SEA3D.AnimationHandler.prototype.play = function( name, crossfade, offset ) { this.crossfade = crossfade; this.currentState.offset = this.time; - if ( offset !== undefined ) + if ( offset !== undefined ) { + this.currentState.time = offset; + } + if ( ! this.playing ) { - // add in animation collector + // Add in animation collector + SEA3D.AnimationHandler.add( this ); + this.playing = true; } -} +}; SEA3D.AnimationHandler.prototype.resume = function() { @@ -1284,7 +1757,7 @@ SEA3D.AnimationHandler.prototype.resume = function() { } -} +}; SEA3D.AnimationHandler.prototype.pause = function() { @@ -1295,26 +1768,27 @@ SEA3D.AnimationHandler.prototype.pause = function() { } -} +}; SEA3D.AnimationHandler.prototype.stop = function() { this.time = 0; + this.pause(); -} +}; SEA3D.AnimationHandler.prototype.setRelative = function( val ) { this.relative = val; -} +}; SEA3D.AnimationHandler.prototype.getRelative = function() { return this.relative; -} +}; // // Manager @@ -1324,13 +1798,13 @@ SEA3D.AnimationHandler.add = function( animation ) { SEA3D.AnimationHandler.animations.push( animation ); -} +}; SEA3D.AnimationHandler.remove = function( animation ) { SEA3D.AnimationHandler.animations.splice( SEA3D.AnimationHandler.animations.indexOf( animation ), 1 ); -} +}; SEA3D.AnimationHandler.stateFromAnimations = function( anms ) { @@ -1342,7 +1816,7 @@ SEA3D.AnimationHandler.stateFromAnimations = function( anms ) { } return states; -} +}; SEA3D.AnimationHandler.update = function( delta ) { @@ -1352,7 +1826,7 @@ SEA3D.AnimationHandler.update = function( delta ) { } -} +}; SEA3D.AnimationHandler.setTime = function( time ) { @@ -1362,7 +1836,7 @@ SEA3D.AnimationHandler.setTime = function( time ) { } -} +}; SEA3D.AnimationHandler.stop = function() { @@ -1372,7 +1846,7 @@ SEA3D.AnimationHandler.stop = function() { } -} +}; SEA3D.AnimationHandler.animations = []; @@ -1387,27 +1861,30 @@ SEA3D.Object = function( name, data, type, sea ) { this.type = type; this.sea = sea; -} +}; // // Geometry Base // -SEA3D.GeometryBase = function( scope ) { +SEA3D.GeometryBase = function( name, data, sea ) { - var data = scope.data; + this.name = name; + this.data = data; + this.sea = sea; - scope.attrib = data.readUShort(); + this.attrib = data.readUShort(); - scope.isBigMesh = ( scope.attrib & 1 ) != 0; + this.isBig = ( this.attrib & 1 ) != 0; // variable uint - data.readVInt = scope.isBigMesh ? data.readUInt : data.readUShort; + data.readVInt = this.isBig ? data.readUInt : data.readUShort; + + this.numVertex = data.readVInt(); - scope.numVertex = data.readVInt(); - scope.length = scope.numVertex * 3; + this.length = this.numVertex * 3; -} +}; // // Geometry @@ -1415,39 +1892,21 @@ SEA3D.GeometryBase = function( scope ) { SEA3D.Geometry = function( name, data, sea ) { - var i, j, vec, len; - - this.name = name; - this.data = data; - this.sea = sea; + SEA3D.GeometryBase.call( this, name, data, sea ); - SEA3D.GeometryBase( this ); + var i, j, vec, len; // NORMAL if ( this.attrib & 4 ) { - this.normal = []; - - i = 0; - while ( i < this.length ) { - - this.normal[ i ++ ] = data.readFloat(); - - } + this.normal = data.readFloatArray( this.length ); } // TANGENT if ( this.attrib & 8 ) { - this.tangent = []; - - i = 0; - while ( i < this.length ) { - - this.tangent[ i ++ ] = data.readFloat(); - - } + this.tangent = data.readFloatArray( this.length ); } @@ -1463,14 +1922,7 @@ SEA3D.Geometry = function( name, data, sea ) { while ( i < this.uv.length ) { // UV VERTEX DATA - this.uv[ i ++ ] = vec = []; - - j = 0; - while ( j < len ) { - - vec[ j ++ ] = data.readFloat(); - - } + this.uv[ i ++ ] = data.readFloatArray( len ); } @@ -1483,121 +1935,164 @@ SEA3D.Geometry = function( name, data, sea ) { var jntLen = this.numVertex * this.jointPerVertex; - this.joint = []; - this.weight = []; + this.joint = data.readUShortArray( jntLen ); + this.weight = data.readFloatArray( jntLen ); - i = 0; - while ( i < jntLen ) { + } + + // VERTEX_COLOR + if ( this.attrib & 128 ) { + + var colorAttrib = data.readUByte(); + + this.numColor = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1; - this.joint[ i ++ ] = data.readUShort(); + this.color = []; + + for ( i = 0, len = colorAttrib & 15; i < len; i ++ ) { + + this.color.push( data.readFloatArray( this.numVertex * this.numColor ) ); } - i = 0; - while ( i < jntLen ) { + } + + // VERTEX + this.vertex = data.readFloatArray( this.length ); - this.weight[ i ++ ] = data.readFloat(); + // SUB-MESHES + var count = data.readUByte(); + + this.groups = []; + + if ( this.attrib & 2 ) { + + // INDEXES + for ( i = 0, len = 0; i < count; i ++ ) { + + this.groups.push( { + start : len, + count : len += ( data.readVInt() * 3 ), + } ); + + } + + this.indexes = this.isBig ? data.readUIntArray( len ) : data.readUShortArray( len ); + + } else { + + // INDEXES + var stride = this.isBig ? 4 : 2, + bytearray = new SEA3D.UByteArray(); + + for ( i = 0, j = 0; i < count; i ++ ) { + + len = data.readVInt() * 3; + + this.groups.push( { + start : j, + count : len, + } ); + + len += j; + + bytearray.add( data.readUByteArray( len * stride ) ); } + this.indexes = this.isBig ? new Uint32Array( bytearray.toBuffer() ) : new Uint16Array( bytearray.toBuffer() ); + } - // VERTEX_COLOR - if ( this.attrib & 128 ) { +}; - var colorAttrib = data.readUByte(), - numColor = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1, - colorCount = this.numVertex * 4; +SEA3D.Geometry.prototype = Object.create( SEA3D.GeometryBase.prototype ); +SEA3D.Geometry.prototype.constructor = SEA3D.Geometry; - this.color = []; - this.color.length = colorAttrib & 15; +SEA3D.Geometry.prototype.type = "geo"; - for ( i = 0; i < this.color.length; i ++ ) - { +// +// Geometry 16 Bit +// - var vColor = []; +SEA3D.Geometry16 = function( name, data, sea ) { - switch ( numColor ) - { - case 1: - j = 0; - while ( j < colorCount ) - { + SEA3D.GeometryBase.call( this, name, data, sea ); - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = 0; - vColor[ j ++ ] = 0; - vColor[ j ++ ] = 1; + var i, len; - } - break; + // NORMAL + if ( this.attrib & 4 ) { - case 2: - j = 0; - while ( j < colorCount ) - { + this.normal = data.readFloatArray( this.length ); - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = 0; - vColor[ j ++ ] = 1; + } - } - break; + // TANGENT + if ( this.attrib & 8 ) { - case 3: - j = 0; - while ( j < colorCount ) - { + this.tangent = data.readFloatArray( this.length ); - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = 1; + } - } - break; + // UV + if ( this.attrib & 32 ) { - case 4: - j = 0; - while ( j < colorCount ) - { + this.uv = []; + this.uv.length = data.readUByte(); - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; - vColor[ j ++ ] = data.readUByte() / 0xFF; + len = this.numVertex * 2; - } - break; - } + i = 0; + while ( i < this.uv.length ) { - this.color[ i ] = vColor; + // UV VERTEX DATA + this.uv[ i ++ ] = data.readFloatArray( len ); } } - // VERTEX - this.vertex = []; + // JOINT-INDEXES / WEIGHTS + if ( this.attrib & 64 ) { - i = 0; - while ( i < this.length ) { + this.jointPerVertex = data.readUByte(); - this.vertex[ i ++ ] = data.readFloat(); + var jntLen = this.numVertex * this.jointPerVertex; + + this.joint = data.readUShortArray( jntLen ); + this.weight = data.readFloatArray( jntLen ); + + } + + // VERTEX_COLOR + if ( this.attrib & 128 ) { + + var colorAttrib = data.readUByte(); + + this.numColor = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1; + + this.color = []; + + for ( i = 0, len = colorAttrib & 15; i < len; i ++ ) { + + this.color.push( data.readFloatArray( this.numVertex * this.numColor ) ); + + } } + // VERTEX + this.vertex = data.readFloatArray( this.length ); + // SUB-MESHES var count = data.readUByte(); - this.indexes = vec = []; + this.indexes = new Uint16Array(); this.groups = []; // INDEXES - j = 0; - for ( i = 0; i < count; i ++ ) - { + for ( i = 0, j = 0; i < count; i ++ ) { len = data.readVInt() * 3; @@ -1607,85 +2102,87 @@ SEA3D.Geometry = function( name, data, sea ) { } ); len += j; - while ( j < len ) { - - vec[ j ++ ] = data.readVInt(); - } + this.indexes = this.isBig ? data.readUIntArray( len ) : data.readUShortArray( len ); } -} +}; -SEA3D.Geometry.prototype.type = "geo"; + +SEA3D.Geometry16.prototype = Object.create( SEA3D.GeometryBase.prototype ); +SEA3D.Geometry16.prototype.constructor = SEA3D.Geometry16; + +SEA3D.Geometry16.prototype.type = "ge16"; // -// Geometry Delta +// Geometry Delta Base // -SEA3D.GeometryDelta = function( name, data, sea ) { - - var i, j, start, delta, len, readNumber, numDiv, vecUint, vec; +SEA3D.GeometryDeltaBase = function( name, data, sea ) { this.name = name; this.data = data; this.sea = sea; this.attrib = data.readUShort(); + this.numVertex = data.readUInteger(); this.length = this.numVertex * 3; - if ( this.attrib & 1 ) - { + if ( this.attrib & 1 ) { - readNumber = function() { + data.readNumber = data.readByte; + this.numDiv = 0xFF / 2; - return data.readByte(); + } + else { - } - numDiv = 0xFF / 2; + data.readNumber = data.readShort; + numDiv = 0xFFFF / 2; } - else - { - readNumber = function() { +}; - return data.readShort(); +// +// Geometry Delta +// - } - numDiv = 0xFFFF / 2; +SEA3D.GeometryDelta = function( name, data, sea ) { - } + SEA3D.GeometryDeltaBase.call( this, name, data, sea ); + + var i, j, start, delta, len, vec; // NORMAL - if ( this.attrib & 4 ) - { + if ( this.attrib & 4 ) { delta = data.readFloat(); - this.normal = []; + + this.normal = new Float32Array( this.length ); i = 0; while ( i < this.length ) { - this.normal[ i ++ ] = ( readNumber() / numDiv ) * delta; + this.normal[ i ++ ] = ( data.readNumber() / this.numDiv ) * delta; } } // TANGENT - if ( this.attrib & 8 ) - { + if ( this.attrib & 8 ) { delta = data.readFloat(); - this.tangent = []; + + this.tangent = new Float32Array( this.length ); i = 0; while ( i < this.length ) { - this.tangent[ i ++ ] = ( readNumber() / numDiv ) * delta; + this.tangent[ i ++ ] = ( data.readNumber() / this.numDiv ) * delta; } @@ -1704,12 +2201,12 @@ SEA3D.GeometryDelta = function( name, data, sea ) { // UV VERTEX DATA delta = data.readFloat(); - this.uv[ i ++ ] = vec = []; + this.uv[ i ++ ] = vec = new Float32Array( uvLen ); j = 0; while ( j < uvLen ) { - vec[ j ++ ] = ( readNumber() / numDiv ) * delta; + vec[ j ++ ] = ( data.readNumber() / this.numDiv ) * delta; } @@ -1724,8 +2221,8 @@ SEA3D.GeometryDelta = function( name, data, sea ) { var jntLen = this.numVertex * this.jointPerVertex; - this.joint = []; - this.weight = []; + this.joint = new Uint16Array( jntLen ); + this.weight = new Float32Array( jntLen ); i = 0; while ( i < jntLen ) { @@ -1737,7 +2234,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { i = 0; while ( i < jntLen ) { - this.weight[ i ++ ] = ( readNumber() / numDiv ) * 1; + this.weight[ i ++ ] = ( data.readNumber() / this.numDiv ) * 1; } @@ -1747,23 +2244,23 @@ SEA3D.GeometryDelta = function( name, data, sea ) { if ( this.attrib & 128 ) { var colorAttrib = data.readUByte(), - numColor = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1, + numColorData = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1, colorCount = this.numVertex * 4; this.color = []; this.color.length = colorAttrib & 15; - for ( i = 0; i < this.color.length; i ++ ) - { + this.numColor = 4; + + for ( i = 0; i < this.color.length; i ++ ) { - var vColor = []; + var vColor = new Float32Array( colorCount ); - switch ( numColor ) + switch ( numColorData ) { case 1: j = 0; - while ( j < colorCount ) - { + while ( j < colorCount ) { vColor[ j ++ ] = data.readUByte() / 0xFF; vColor[ j ++ ] = 0; @@ -1775,8 +2272,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { case 2: j = 0; - while ( j < colorCount ) - { + while ( j < colorCount ) { vColor[ j ++ ] = data.readUByte() / 0xFF; vColor[ j ++ ] = data.readUByte() / 0xFF; @@ -1788,8 +2284,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { case 3: j = 0; - while ( j < colorCount ) - { + while ( j < colorCount ) { vColor[ j ++ ] = data.readUByte() / 0xFF; vColor[ j ++ ] = data.readUByte() / 0xFF; @@ -1801,8 +2296,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { case 4: j = 0; - while ( j < colorCount ) - { + while ( j < colorCount ) { vColor[ j ++ ] = data.readUByte() / 0xFF; vColor[ j ++ ] = data.readUByte() / 0xFF; @@ -1822,12 +2316,12 @@ SEA3D.GeometryDelta = function( name, data, sea ) { // VERTEX delta = data.readFloat(); - this.vertex = []; + this.vertex = new Float32Array( this.length ); i = 0; while ( i < this.length ) { - this.vertex[ i ++ ] = ( readNumber() / numDiv ) * delta; + this.vertex[ i ++ ] = ( data.readNumber() / this.numDiv ) * delta; } @@ -1839,8 +2333,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { // INDEXES j = 0; - for ( i = 0; i < count; i ++ ) - { + for ( i = 0; i < count; i ++ ) { len = data.readVInt() * 3; @@ -1874,8 +2367,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { start = vec.length; - for ( j = 0; j < len; j ++ ) - { + for ( j = 0; j < len; j ++ ) { var a = data.readUInteger(), b = data.readUInteger(), @@ -1910,8 +2402,7 @@ SEA3D.GeometryDelta = function( name, data, sea ) { // TRIANGLE j = 0; - for ( i = 0; i < count; i ++ ) - { + for ( i = 0; i < count; i ++ ) { len = data.readUInteger() * 3; @@ -1931,7 +2422,10 @@ SEA3D.GeometryDelta = function( name, data, sea ) { } -} +}; + +SEA3D.GeometryDeltaBase.prototype = Object.create( SEA3D.GeometryDeltaBase.prototype ); +SEA3D.GeometryDeltaBase.prototype.constructor = SEA3D.GeometryDelta; SEA3D.GeometryDelta.prototype.type = "geDL"; @@ -1939,115 +2433,79 @@ SEA3D.GeometryDelta.prototype.type = "geDL"; // Object3D // -SEA3D.Object3D = -{ - read : function( scope ) { - - var data = scope.data; +SEA3D.Object3D = function( name, data, sea ) { - scope.isStatic = false; + this.name = name; + this.data = data; + this.sea = sea; - scope.attrib = data.readUShort(); - scope.tags = []; + this.isStatic = false; - if ( scope.attrib & 1 ) - scope.parent = scope.sea.getObject( data.readUInt() ); + this.attrib = data.readUShort(); - if ( scope.attrib & 2 ) - scope.animations = SEA3D.Animation.readAnimationList( data, scope.sea ); + if ( this.attrib & 1 ) this.parent = sea.getObject( data.readUInt() ); - if ( scope.attrib & 4 ) - scope.scripts = SEA3D.Script.readScriptList( data, scope.sea ); + if ( this.attrib & 2 ) this.animations = data.readAnimationList( sea ); - if ( scope.attrib & 16 ) - scope.properties = scope.sea.getObject( data.readUInt() ); + if ( this.attrib & 4 ) this.scripts = data.readScriptList( sea ); - if ( scope.attrib & 32 ) { + if ( this.attrib & 16 ) this.properties = sea.getObject( data.readUInt() ); - var objectType = data.readUByte(); - scope.isStatic = objectType & 1; + if ( this.attrib & 32 ) { - } + var objectType = data.readUByte(); + this.isStatic = objectType & 1; } - , readTags : function( scope, callback ) { - - var data = scope.data, - numTag = data.readUByte(); - - for ( var i = 0; i < numTag; ++ i ) { - - var kind = data.readUShort(); - var size = data.readUInt(); - var pos = data.position; - - //not implemented - //readTag(kind, size) - data.position = pos += size; +}; - } +SEA3D.Object3D.prototype.readTag = function( kind, data, size ) { - } -} +}; // // Entity3D // -SEA3D.Entity3D = -{ - read : function( scope ) { +SEA3D.Entity3D = function( name, data, sea ) { - SEA3D.Object3D.read( scope ); + SEA3D.Object3D.call( this, name, data, sea ); - var data = scope.data; + this.castShadows = true; - scope.castShadows = true; - - if ( scope.attrib & 64 ) { + if ( this.attrib & 64 ) { - var lightType = data.readUByte(); - scope.castShadows = ( lightType & 1 ) == 0; + var lightType = data.readUByte(); - } + this.castShadows = ( lightType & 1 ) == 0; } - , readTags : function( scope, callback ) { - SEA3D.Object3D.readTags( scope, callback ); +}; - } -} +SEA3D.Entity3D.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Entity3D.prototype.constructor = SEA3D.Entity3D; // // Sound3D // -SEA3D.Sound3D = -{ - read : function( scope ) { - - SEA3D.Object3D.read( scope ); - - var data = scope.data, - sea = scope.sea; +SEA3D.Sound3D = function( name, data, sea ) { - scope.autoPlay = ( scope.attrib & 64 ) != 0; + SEA3D.Object3D.call( this, name, data, sea ); - if ( scope.attrib & 128 ) - scope.mixer = sea.getObject( data.readUInt() ); + this.autoPlay = ( this.attrib & 64 ) != 0; - scope.sound = sea.getObject( data.readUInt() ); - scope.volume = data.readFloat(); + if ( this.attrib & 128 ) this.mixer = sea.getObject( data.readUInt() ); - } - , readTags : function( scope, callback ) { + this.sound = sea.getObject( data.readUInt() ); + this.volume = data.readFloat(); - SEA3D.Object3D.readTags( scope, callback ); +}; - } -} +SEA3D.Sound3D.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Sound3D.prototype.constructor = SEA3D.Sound3D; // // Sound Point @@ -2055,18 +2513,17 @@ SEA3D.Sound3D = SEA3D.SoundPoint = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Sound3D.read( this ); + SEA3D.Sound3D.call( this, name, data, sea ); this.position = data.readVector3(); this.distance = data.readFloat(); - SEA3D.Sound3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); -} +}; + +SEA3D.SoundPoint.prototype = Object.create( SEA3D.Sound3D.prototype ); +SEA3D.SoundPoint.prototype.constructor = SEA3D.SoundPoint; SEA3D.SoundPoint.prototype.type = "sp"; @@ -2076,17 +2533,16 @@ SEA3D.SoundPoint.prototype.type = "sp"; SEA3D.Container3D = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Object3D.read( this ); + SEA3D.Object3D.call( this, name, data, sea ); this.transform = data.readMatrix(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); + +}; -} +SEA3D.Container3D.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Container3D.prototype.constructor = SEA3D.Container3D; SEA3D.Container3D.prototype.type = "c3d"; @@ -2102,7 +2558,7 @@ SEA3D.TextureURL = function( name, data, sea ) { this.url = data.readUTF( data.length ); -} +}; SEA3D.TextureURL.prototype.type = "urlT"; @@ -2117,7 +2573,7 @@ SEA3D.Actions = function( name, data, sea ) { this.sea = sea; this.count = data.readUInt(); - this.action = []; + this.actions = []; for ( var i = 0; i < this.count; i ++ ) { @@ -2127,11 +2583,10 @@ SEA3D.Actions = function( name, data, sea ) { var size = data.readUShort(); var position = data.position; - var act = this.action[ i ] = { kind: kind }; + var act = this.actions[ i ] = { kind: kind }; // range of animation - if ( flag & 1 ) - { + if ( flag & 1 ) { // start and count in frames act.range = [ data.readUInt(), data.readUInt() ]; @@ -2139,27 +2594,23 @@ SEA3D.Actions = function( name, data, sea ) { } // time - if ( flag & 2 ) - { + if ( flag & 2 ) { act.time = data.readUInt(); } // easing - if ( flag & 4 ) - { + if ( flag & 4 ) { - act.intrpl = SEA3D.DataTable.INTERPOLATION_TABLE[ data.readUByte() ]; + act.intrpl = data.readInterpolation(); - if ( act.intrpl.indexOf( 'back.' ) == 0 ) - { + if ( act.intrpl.indexOf( 'back.' ) == 0 ) { act.intrplParam0 = data.readFloat(); } - else if ( act.intrpl.indexOf( 'elastic.' ) == 0 ) - { + else if ( act.intrpl.indexOf( 'elastic.' ) == 0 ) { act.intrplParam0 = data.readFloat(); act.intrplParam1 = data.readFloat(); @@ -2207,6 +2658,14 @@ SEA3D.Actions = function( name, data, sea ) { act.camera = sea.getObject( data.readUInt() ); break; + case SEA3D.Actions.SCRIPTS: + act.scripts = data.readScriptList( sea ); + break; + + case SEA3D.Actions.CLASS_OF: + act.classof = sea.getObject( data.readUInt() ); + break; + default: console.log( "Action \"" + kind + "\" not found." ); break; @@ -2216,7 +2675,7 @@ SEA3D.Actions = function( name, data, sea ) { } -} +}; SEA3D.Actions.SCENE = 0; SEA3D.Actions.ENVIRONMENT_COLOR = 1; @@ -2228,210 +2687,78 @@ SEA3D.Actions.ANIMATION_AUDIO_SYNC = 6; SEA3D.Actions.LOOK_AT = 7; SEA3D.Actions.RTT_TARGET = 8; SEA3D.Actions.CAMERA = 9; +SEA3D.Actions.SCRIPTS = 10; +SEA3D.Actions.CLASS_OF = 11; SEA3D.Actions.prototype.type = "act"; // -// Script +// Properties // -SEA3D.Script = -{ - DETAILED : false - - , readScriptList : function( data, sea ) { +SEA3D.Properties = function( name, data, sea ) { - var list = [], - count = data.readUByte(); + this.name = name; + this.data = data; + this.sea = sea; - var i = 0; - while ( i < count ) - { + this.tag = data.readProperties( sea ); + this.tag.__name = name; - var attrib = data.readUByte(), - numParams, - script = {}; +}; - script.priority = ( attrib & 1 ) | ( attrib & 2 ); +SEA3D.Properties.prototype.type = "prop"; - if ( attrib & 4 ) - { +// +// File Info +// - var j, name; +SEA3D.FileInfo = function( name, data, sea ) { - numParams = data.readUByte(); + this.name = name; + this.data = data; + this.sea = sea; - if ( SEA3D.Script.DETAILED ) - { + this.tag = data.readProperties( sea ); + this.tag.__name = name; - script.params = []; + sea.info = this.tag; - for ( j = 0; j < numParams; j ++ ) - { +}; - name = data.readUTF8(); - var type = data.readUByte(); +SEA3D.FileInfo.prototype.type = "info"; - script.params[ j ] = - { - name : name, - type : type, - data : SEA3D.DataTable.readToken( type, data, sea ) - }; +// +// Java Script +// - } +SEA3D.JavaScript = function( name, data, sea ) { - } - else - { + this.name = name; + this.data = data; + this.sea = sea; - script.params = {}; + this.src = data.readUTF( data.length ); - for ( j = 0; j < numParams; j ++ ) - { +}; - name = data.readUTF8(); - script.params[ name ] = SEA3D.DataTable.readObject( data, sea ); +SEA3D.JavaScript.prototype.type = "js"; - } +// +// Java Script Method +// - } - - } - - if ( attrib & 8 ) - { - - script.method = data.readUTF8(); - - } - - script.tag = sea.getObject( data.readUInt() ); - - list[ i ++ ] = script; - - } - - return list; - - } -} - -// -// Properties -// - -SEA3D.Properties = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; - - this.tag = SEA3D.Properties.readProperties( data, sea.objects, name ); - -} - -SEA3D.Properties.readProperties = function( data, sea, pname ) { - - var count, i, type, name, attribs; - - if ( SEA3D.Properties.DETAILED ) - { - - count = data.readUByte(); - - props = []; - - for ( i = 0; i < count; i ++ ) - { - - name = data.readUTF8(); - type = data.readUByte(); - - props[ i ] = - { - name : name, - type : type, - value : SEA3D.DataTable.readToken( type, data, sea ) - }; - - } - - } - else - { - - count = data.readUByte(); - - props = {}; - - if ( pname ) - props.__name__ = pname; - - for ( i = 0; i < count; i ++ ) - { - - name = data.readUTF8(); - props[ name ] = SEA3D.DataTable.readObject( data, sea ); - - } - - } - - return props; - -} - -SEA3D.Properties.DETAILED = false; -SEA3D.Properties.prototype.type = "prop"; - -// -// File Info -// - -SEA3D.FileInfo = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; - - sea.info = this.tag = SEA3D.Properties.readProperties( data, sea.objects, name ); - -} - -SEA3D.FileInfo.prototype.type = "info"; - -// -// Java Script -// - -SEA3D.JavaScript = function( name, data, sea ) { +SEA3D.JavaScriptMethod = function( name, data, sea ) { this.name = name; this.data = data; this.sea = sea; - this.src = data.readUTF( data.length ); - -} - -SEA3D.JavaScript.prototype.type = "js"; - -// -// Java Script Method -// - -SEA3D.JavaScriptMethod = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; + var count = data.readUShort(); - this.count = data.readUShort(); this.methods = {}; - for ( var i = 0; i < this.count; i ++ ) - { + for ( var i = 0; i < count; i ++ ) { var flag = data.readUByte(); var method = data.readUTF8(); @@ -2442,7 +2769,7 @@ SEA3D.JavaScriptMethod = function( name, data, sea ) { } -} +}; SEA3D.JavaScriptMethod.prototype.type = "jsm"; @@ -2458,7 +2785,7 @@ SEA3D.GLSL = function( name, data, sea ) { this.src = data.readUTF( data.length ); -} +}; SEA3D.GLSL.prototype.type = "glsl"; @@ -2468,11 +2795,7 @@ SEA3D.GLSL.prototype.type = "glsl"; SEA3D.Dummy = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Object3D.read( this ); + SEA3D.Object3D.call( this, name, data, sea ); this.transform = data.readMatrix(); @@ -2480,9 +2803,12 @@ SEA3D.Dummy = function( name, data, sea ) { this.height = data.readFloat(); this.depth = data.readFloat(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); + +}; -} +SEA3D.Dummy.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Dummy.prototype.constructor = SEA3D.Dummy; SEA3D.Dummy.prototype.type = "dmy"; @@ -2492,11 +2818,7 @@ SEA3D.Dummy.prototype.type = "dmy"; SEA3D.Line = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Object3D.read( this ); + SEA3D.Object3D.call( this, name, data, sea ); this.count = ( this.attrib & 64 ? data.readUInt() : data.readUShort() ) * 3; this.closed = ( this.attrib & 128 ) != 0; @@ -2511,49 +2833,14 @@ SEA3D.Line = function( name, data, sea ) { } - SEA3D.Object3D.readTags( this ); - -} - -SEA3D.Line.prototype.type = "line"; - -// -// Planar Render -// - -SEA3D.PlanarRender = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; - - this.attrib = data.readUByte(); - - this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 ); - this.transform = data.readMatrix(); - -} - -SEA3D.PlanarRender.prototype.type = "rttp"; - -// -// Cube Render -// - -SEA3D.CubeRender = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; - - this.attrib = data.readUByte(); + data.readTags( this.readTag.bind( this ) ); - this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 ); - this.position = data.readVector3(); +}; -} +SEA3D.Line.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Line.prototype.constructor = SEA3D.Line; -SEA3D.CubeRender.prototype.type = "rttc"; +SEA3D.Line.prototype.type = "line"; // // Mesh2D @@ -2561,23 +2848,25 @@ SEA3D.CubeRender.prototype.type = "rttc"; SEA3D.Mesh2D = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; + SEA3D.Object3D.call( this, name, data, sea ); - SEA3D.Object3D.read( this ); + if ( this.attrib & 256 ) { - if ( this.attrib & 256 ) this.material = sea.getObject( data.readUInt() ); + } + this.position = data.readVector3(); this.width = data.readFloat(); this.height = data.readFloat(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); + +}; -} +SEA3D.Mesh2D.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Mesh2D.prototype.constructor = SEA3D.Mesh2D; SEA3D.Mesh2D.prototype.type = "m2d"; @@ -2587,11 +2876,7 @@ SEA3D.Mesh2D.prototype.type = "m2d"; SEA3D.Mesh = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Entity3D.read( this ); + SEA3D.Entity3D.call( this, name, data, sea ); // MATERIAL if ( this.attrib & 256 ) { @@ -2601,14 +2886,13 @@ SEA3D.Mesh = function( name, data, sea ) { var len = data.readUByte(); if ( len == 1 ) this.material[ 0 ] = sea.getObject( data.readUInt() ); - else - { + else { var i = 0; - while ( i < len ) - { + while ( i < len ) { var matIndex = data.readUInt(); + if ( matIndex > 0 ) this.material[ i ++ ] = sea.getObject( matIndex - 1 ); else this.material[ i ++ ] = undefined; @@ -2624,18 +2908,24 @@ SEA3D.Mesh = function( name, data, sea ) { var len = data.readUByte(); - for ( var i = 0; i < len; i ++ ) + for ( var i = 0; i < len; i ++ ) { + this.modifiers[ i ] = sea.getObject( data.readUInt() ); + } + } this.transform = data.readMatrix(); this.geometry = sea.getObject( data.readUInt() ); - SEA3D.Entity3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); + +}; -} +SEA3D.Mesh.prototype = Object.create( SEA3D.Entity3D.prototype ); +SEA3D.Mesh.prototype.constructor = SEA3D.Mesh; SEA3D.Mesh.prototype.type = "m3d"; @@ -2656,14 +2946,14 @@ SEA3D.Skeleton = function( name, data, sea ) { for ( var i = 0; i < length; i ++ ) { this.joint[ i ] = { - name: data.readUTF8(), - parentIndex: data.readUShort() - 1, - inverseBindMatrix: data.readMatrix() - } + name: data.readUTF8(), + parentIndex: data.readUShort() - 1, + inverseBindMatrix: data.readMatrix() + }; } -} +}; SEA3D.Skeleton.prototype.type = "skl"; @@ -2684,22 +2974,22 @@ SEA3D.SkeletonLocal = function( name, data, sea ) { for ( var i = 0; i < length; i ++ ) { this.joint[ i ] = { - name: data.readUTF8(), - parentIndex: data.readUShort() - 1, - // POSITION XYZ - x: data.readFloat(), - y: data.readFloat(), - z: data.readFloat(), - // QUATERNION XYZW - qx: data.readFloat(), - qy: data.readFloat(), - qz: data.readFloat(), - qw: data.readFloat() - } + name: data.readUTF8(), + parentIndex: data.readUShort() - 1, + // POSITION XYZ + x: data.readFloat(), + y: data.readFloat(), + z: data.readFloat(), + // QUATERNION XYZW + qx: data.readFloat(), + qy: data.readFloat(), + qz: data.readFloat(), + qw: data.readFloat() + }; } -} +}; SEA3D.SkeletonLocal.prototype.type = "sklq"; @@ -2707,43 +2997,47 @@ SEA3D.SkeletonLocal.prototype.type = "sklq"; // Animation Base // -SEA3D.AnimationBase = -{ - read : function( scope ) { +SEA3D.AnimationBase = function( name, data, sea ) { - var data = scope.data, flag = data.readUByte(); + this.name = name; + this.data = data; + this.sea = sea; - scope.sequence = []; + var flag = data.readUByte(); - if ( flag & 1 ) { + this.sequence = []; - var count = data.readUShort(); + if ( flag & 1 ) { - for ( var i = 0; i < count; i ++ ) { + var count = data.readUShort(); - flag = data.readUByte(); + for ( var i = 0; i < count; i ++ ) { - scope.sequence[ i ] = { - name: data.readUTF8(), - start: data.readUInt(), - count: data.readUInt(), - repeat: ( flag & 1 ) != 0, - intrpl: ( flag & 2 ) != 0 - } + flag = data.readUByte(); + this.sequence[ i ] = { + name: data.readUTF8(), + start: data.readUInt(), + count: data.readUInt(), + repeat: ( flag & 1 ) != 0, + intrpl: ( flag & 2 ) != 0 } } - scope.frameRate = data.readUByte(); - scope.numFrames = data.readUInt(); + } + + this.frameRate = data.readUByte(); + this.numFrames = data.readUInt(); - // no contains sequence - if ( scope.sequence.length == 0 ) - scope.sequence[ 0 ] = { name: "root", start: 0, count: scope.numFrames, repeat: true, intrpl: true }; + // no contains sequence + if ( this.sequence.length == 0 ) { + + this.sequence[ 0 ] = { name: "root", start: 0, count: this.numFrames, repeat: true, intrpl: true }; } -} + +}; // // Animation @@ -2751,11 +3045,7 @@ SEA3D.AnimationBase = SEA3D.Animation = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.AnimationBase.read( this ); + SEA3D.AnimationBase.call( this, name, data, sea ); this.dataList = []; this.dataList.length = data.readUByte(); @@ -2763,21 +3053,20 @@ SEA3D.Animation = function( name, data, sea ) { for ( var i = 0; i < this.dataList.length; i ++ ) { var kind = data.readUShort(), - type = data.readUByte(), - anmRaw = []; + type = data.readUByte(); - SEA3D.DataTable.readVector( type, data, anmRaw, this.numFrames, 0 ); + var anmRaw = data.readVector( type, this.numFrames, 0 ); this.dataList[ i ] = { - kind: kind, - type: type, - blockSize: SEA3D.DataTable.sizeOf( type ), - data: anmRaw - } + kind: kind, + type: type, + blockSize: SEA3D.Stream.sizeOf( type ), + data: anmRaw + } } -} +}; SEA3D.Animation.POSITION = 0; SEA3D.Animation.ROTATION = 1; @@ -2811,33 +3100,10 @@ SEA3D.Animation.DefaultLerpFuncs = [ SEA3D.Math.lerpAng1x, // ANGLE SEA3D.Math.lerp1x, // ALPHA SEA3D.Math.lerp1x // VOLUME -] - -SEA3D.Animation.readAnimationList = function( data, sea ) { - - var list = [], - count = data.readUByte(); - - var i = 0; - while ( i < count ) { - - var attrib = data.readUByte(), - anm = {}; - - anm.relative = ( attrib & 1 ) != 0; - - if ( attrib & 2 ) - anm.timeScale = data.readFloat(); - - anm.tag = sea.getObject( data.readUInt() ); - - list[ i ++ ] = anm; - - } - - return list; +]; -} +SEA3D.Animation.prototype = Object.create( SEA3D.AnimationBase.prototype ); +SEA3D.Animation.prototype.constructor = SEA3D.Animation; SEA3D.Animation.prototype.type = "anm"; @@ -2847,44 +3113,17 @@ SEA3D.Animation.prototype.type = "anm"; SEA3D.SkeletonAnimation = function( name, data, sea ) { + SEA3D.AnimationBase.call( this, name, data, sea ); + this.name = name; this.data = data; this.sea = sea; - var i, j, count, joint; - - SEA3D.AnimationBase.read( this ); - - count = data.readUShort() - - this.pose = []; - - for ( i = 0; i < this.numFrames; i ++ ) { - - joint = []; - joint.length = count; - - for ( j = 0; j < count; j ++ ) { - - joint[ j ] = { - // POSITION XYZ - x: data.readFloat(), - y: data.readFloat(), - z: data.readFloat(), - // QUATERNION XYZW - qx: data.readFloat(), - qy: data.readFloat(), - qz: data.readFloat(), - qw: data.readFloat() - } - - } - - this.pose[ i ] = joint; + this.numJoints = data.readUShort() - } + this.raw = data.readFloatArray( this.numFrames * this.numJoints * 7 ); -} +}; SEA3D.SkeletonAnimation.prototype.type = "skla"; @@ -2894,11 +3133,7 @@ SEA3D.SkeletonAnimation.prototype.type = "skla"; SEA3D.Morph = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.GeometryBase( this ); + SEA3D.GeometryBase.call( this, name, data, sea ); var useVertex = ( this.attrib & 2 ) != 0; var useNormal = ( this.attrib & 4 ) != 0; @@ -2907,43 +3142,22 @@ SEA3D.Morph = function( name, data, sea ) { this.node = []; - var i, j; - - for ( i = 0; i < nodeCount; i ++ ) { - - var nodeName = data.readUTF8(); - - if ( useVertex ) { - - var verts = []; - - j = 0; - while ( j < this.length ) { - - verts[ j ++ ] = data.readFloat(); - - } - - } - - if ( useNormal ) { - - var norms = []; - - j = 0; - while ( j < this.length ) { - - norms[ j ++ ] = data.readFloat(); + for ( var i = 0; i < nodeCount; i ++ ) { - } + var nodeName = data.readUTF8(), + verts, norms; - } + if ( useVertex ) verts = data.readFloatArray( this.length ); + if ( useNormal ) norms = data.readFloatArray( this.length ); this.node[ i ] = { vertex: verts, normal: norms, name: nodeName } } -} +}; + +SEA3D.Morph.prototype = Object.create( SEA3D.GeometryBase.prototype ); +SEA3D.Morph.prototype.constructor = SEA3D.Morph; SEA3D.Morph.prototype.type = "mph"; @@ -2953,19 +3167,16 @@ SEA3D.Morph.prototype.type = "mph"; SEA3D.VertexAnimation = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.AnimationBase.read( this ); + SEA3D.AnimationBase.call( this, name, data, sea ); var flags = data.readUByte(); - this.isBigMesh = ( flags & 1 ) != 0; + this.isBig = ( flags & 1 ) != 0; - data.readVInt = this.isBigMesh ? data.readUInt : data.readUShort; + data.readVInt = this.isBig ? data.readUInt : data.readUShort; this.numVertex = data.readVInt(); + this.length = this.numVertex * 3; var useVertex = ( flags & 2 ) != 0; @@ -2973,41 +3184,21 @@ SEA3D.VertexAnimation = function( name, data, sea ) { this.frame = []; - var i, j; + var i, verts, norms; for ( i = 0; i < this.numFrames; i ++ ) { - if ( useVertex ) { - - var verts = []; - - j = 0; - while ( j < this.length ) { - - verts[ j ++ ] = data.readFloat(); - - } - - } - - if ( useNormal ) { - - var norms = []; - - j = 0; - while ( j < this.length ) { - - norms[ j ++ ] = data.readFloat(); - - } - - } + if ( useVertex ) verts = data.readFloatArray( this.length ); + if ( useNormal ) norms = data.readFloatArray( this.length ); this.frame[ i ] = { vertex: verts, normal: norms } } -} +}; + +SEA3D.VertexAnimation.prototype = Object.create( SEA3D.AnimationBase.prototype ); +SEA3D.VertexAnimation.prototype.constructor = SEA3D.VertexAnimation; SEA3D.VertexAnimation.prototype.type = "vtxa"; @@ -3017,18 +3208,14 @@ SEA3D.VertexAnimation.prototype.type = "vtxa"; SEA3D.Camera = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Object3D.read( this ); + SEA3D.Object3D.call( this, name, data, sea ); if ( this.attrib & 64 ) { this.dof = { - distance: data.readFloat(), - range: data.readFloat() - } + distance: data.readFloat(), + range: data.readFloat() + }; } @@ -3036,9 +3223,12 @@ SEA3D.Camera = function( name, data, sea ) { this.fov = data.readFloat(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); -} +}; + +SEA3D.Camera.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Camera.prototype.constructor = SEA3D.Camera; SEA3D.Camera.prototype.type = "cam"; @@ -3048,18 +3238,17 @@ SEA3D.Camera.prototype.type = "cam"; SEA3D.JointObject = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Object3D.read( this ); + SEA3D.Object3D.call( this, name, data, sea ); this.target = sea.getObject( data.readUInt() ); this.joint = data.readUShort(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); -} +}; + +SEA3D.JointObject.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.JointObject.prototype.constructor = SEA3D.JointObject; SEA3D.JointObject.prototype.type = "jnt"; @@ -3067,39 +3256,38 @@ SEA3D.JointObject.prototype.type = "jnt"; // Light // -SEA3D.Light = { - read : function( scope ) { +SEA3D.Light = function( name, data, sea ) { - SEA3D.Object3D.read( scope ); + SEA3D.Object3D.call( this, name, data, sea ); - var data = scope.data; + this.attenStart = Number.MAX_VALUE; + this.attenEnd = Number.MAX_VALUE; - scope.attenStart = Number.MAX_VALUE; - scope.attenEnd = Number.MAX_VALUE; + if ( this.attrib & 64 ) { - if ( scope.attrib & 64 ) { + var shadowHeader = data.readUByte(); - var shadowHeader = data.readUByte(); + this.shadow = {} - scope.shadow = {} + this.shadow.opacity = shadowHeader & 1 ? data.readFloat() : 1; + this.shadow.color = shadowHeader & 2 ? data.readUInt24() : 0x000000; - scope.shadow.opacity = shadowHeader & 1 ? data.readFloat() : 1; - scope.shadow.color = shadowHeader & 2 ? data.readUInt24() : 0x000000; + } - } + if ( this.attrib & 512 ) { - if ( scope.attrib & 512 ) { + this.attenStart = data.readFloat(); + this.attenEnd = data.readFloat(); - scope.attenStart = data.readFloat(); - scope.attenEnd = data.readFloat(); + } - } + this.color = data.readUInt24(); + this.multiplier = data.readFloat(); - scope.color = data.readUInt24(); - scope.multiplier = data.readFloat(); +}; - } -} +SEA3D.Light.prototype = Object.create( SEA3D.Object3D.prototype ); +SEA3D.Light.prototype.constructor = SEA3D.Light; // // Point Light @@ -3107,26 +3295,25 @@ SEA3D.Light = { SEA3D.PointLight = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Light.read( this ); + SEA3D.Light.call( this, name, data, sea ); if ( this.attrib & 128 ) { this.attenuation = { - start: data.readFloat(), - end: data.readFloat() - } + start: data.readFloat(), + end: data.readFloat() + } } this.position = data.readVector3(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); -} +}; + +SEA3D.PointLight.prototype = Object.create( SEA3D.Light.prototype ); +SEA3D.PointLight.prototype.constructor = SEA3D.PointLight; SEA3D.PointLight.prototype.type = "plht"; @@ -3136,11 +3323,7 @@ SEA3D.PointLight.prototype.type = "plht"; SEA3D.HemisphereLight = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Light.read( this ); + SEA3D.Light.call( this, name, data, sea ); if ( this.attrib & 128 ) { @@ -3153,9 +3336,12 @@ SEA3D.HemisphereLight = function( name, data, sea ) { this.secondColor = data.readUInt24(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); + +}; -} +SEA3D.HemisphereLight.prototype = Object.create( SEA3D.Light.prototype ); +SEA3D.HemisphereLight.prototype.constructor = SEA3D.HemisphereLight; SEA3D.HemisphereLight.prototype.type = "hlht"; @@ -3165,17 +3351,16 @@ SEA3D.HemisphereLight.prototype.type = "hlht"; SEA3D.DirectionalLight = function( name, data, sea ) { - this.name = name; - this.data = data; - this.sea = sea; - - SEA3D.Light.read( this ); + SEA3D.Light.call( this, name, data, sea ); this.transform = data.readMatrix(); - SEA3D.Object3D.readTags( this ); + data.readTags( this.readTag.bind( this ) ); -} +}; + +SEA3D.DirectionalLight.prototype = Object.create( SEA3D.Light.prototype ); +SEA3D.DirectionalLight.prototype.constructor = SEA3D.DirectionalLight; SEA3D.DirectionalLight.prototype.type = "dlht"; @@ -3212,7 +3397,7 @@ SEA3D.Material = function( name, data, sea ) { this.blendMode = data.readBlendMode(); if ( this.attrib & 128 ) - this.animations = SEA3D.Animation.readAnimationList( data, sea ); + this.animations = data.readAnimationList( sea ); this.depthMask = ( this.attrib & 256 ) == 0; @@ -3228,40 +3413,40 @@ SEA3D.Material = function( name, data, sea ) { switch ( kind ) { case SEA3D.Material.DEFAULT: tech = { - ambientColor: data.readUInt24(), - diffuseColor: data.readUInt24(), - specularColor: data.readUInt24(), + ambientColor: data.readUInt24(), + diffuseColor: data.readUInt24(), + specularColor: data.readUInt24(), - specular: data.readFloat(), - gloss: data.readFloat() - } + specular: data.readFloat(), + gloss: data.readFloat() + }; break; case SEA3D.Material.COMPOSITE_TEXTURE: tech = { - composite: sea.getObject( data.readUInt() ) - } + composite: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.DIFFUSE_MAP: tech = { - texture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.SPECULAR_MAP: tech = { - texture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.NORMAL_MAP: tech = { - texture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.REFLECTION: case SEA3D.Material.FRESNEL_REFLECTION: tech = { - texture: sea.getObject( data.readUInt() ), - alpha: data.readFloat() - } + texture: sea.getObject( data.readUInt() ), + alpha: data.readFloat() + }; if ( kind == SEA3D.Material.FRESNEL_REFLECTION ) { @@ -3272,59 +3457,58 @@ SEA3D.Material = function( name, data, sea ) { break; case SEA3D.Material.REFRACTION: tech = { - texture: sea.getObject( data.readUInt() ), - alpha: data.readFloat(), - ior: data.readFloat() - } + texture: sea.getObject( data.readUInt() ), + alpha: data.readFloat(), + ior: data.readFloat() + }; break; case SEA3D.Material.RIM: tech = { - color: data.readUInt24(), - strength: data.readFloat(), - power: data.readFloat(), - blendMode: data.readBlendMode() - } + color: data.readUInt24(), + strength: data.readFloat(), + power: data.readFloat(), + blendMode: data.readBlendMode() + }; break; case SEA3D.Material.LIGHT_MAP: tech = { - texture: sea.getObject( data.readUInt() ), - channel: data.readUByte(), - blendMode: data.readBlendMode() - } + texture: sea.getObject( data.readUInt() ), + channel: data.readUByte(), + blendMode: data.readBlendMode() + }; break; case SEA3D.Material.DETAIL_MAP: tech = { - texture: sea.getObject( data.readUInt() ), - scale: data.readFloat(), - blendMode: data.readBlendMode() - } + texture: sea.getObject( data.readUInt() ), + scale: data.readFloat(), + blendMode: data.readBlendMode() + }; break; case SEA3D.Material.CEL: tech = { - color: data.readUInt24(), - levels: data.readUByte(), - size: data.readFloat(), - specularCutOff: data.readFloat(), - smoothness: data.readFloat() - } + color: data.readUInt24(), + levels: data.readUByte(), + size: data.readFloat(), + specularCutOff: data.readFloat(), + smoothness: data.readFloat() + }; break; case SEA3D.Material.TRANSLUCENT: tech = { - color: data.readUInt24(), - translucency: data.readFloat(), - scattering: data.readFloat() - } + color: data.readUInt24(), + translucency: data.readFloat(), + scattering: data.readFloat() + }; break; case SEA3D.Material.BLEND_NORMAL_MAP: methodAttrib = data.readUByte(); tech = { - texture: sea.getObject( data.readUInt() ), - secondaryTexture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ), + secondaryTexture: sea.getObject( data.readUInt() ) + }; - if ( methodAttrib & 1 ) - { + if ( methodAttrib & 1 ) { tech.offsetX0 = data.readFloat(); tech.offsetY0 = data.readFloat(); @@ -3333,8 +3517,7 @@ SEA3D.Material = function( name, data, sea ) { tech.offsetY1 = data.readFloat(); } - else - { + else { tech.offsetX0 = tech.offsetY0 = tech.offsetX1 = tech.offsetY1 = 0 @@ -3345,9 +3528,9 @@ SEA3D.Material = function( name, data, sea ) { break; case SEA3D.Material.MIRROR_REFLECTION: tech = { - texture: sea.getObject( data.readUInt() ), - alpha: data.readFloat() - } + texture: sea.getObject( data.readUInt() ), + alpha: data.readFloat() + }; break; case SEA3D.Material.AMBIENT_MAP: @@ -3358,54 +3541,54 @@ SEA3D.Material = function( name, data, sea ) { case SEA3D.Material.ALPHA_MAP: tech = { - texture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.EMISSIVE_MAP: tech = { - texture: sea.getObject( data.readUInt() ) - } + texture: sea.getObject( data.readUInt() ) + }; break; case SEA3D.Material.VERTEX_COLOR: tech = { - blendMode: data.readBlendMode() - } + blendMode: data.readBlendMode() + }; break; case SEA3D.Material.WRAP_LIGHTING: tech = { color: data.readUInt24(), strength: data.readFloat() - } + }; break; case SEA3D.Material.COLOR_REPLACE: methodAttrib = data.readUByte(); tech = { - red: data.readUInt24(), - green: data.readUInt24(), - blue: data.readUInt24() - } + red: data.readUInt24(), + green: data.readUInt24(), + blue: data.readUInt24() + }; - if ( methodAttrib & 1 ) - tech.mask = sea.getObject( data.readUInt() ); + if ( methodAttrib & 1 ) tech.mask = sea.getObject( data.readUInt() ); + + if ( methodAttrib & 2 ) tech.alpha = data.readFloat(); - if ( methodAttrib & 2 ) - tech.alpha = data.readFloat(); break; case SEA3D.Material.REFLECTION_SPHERICAL: tech = { - texture: sea.getObject( data.readUInt() ), - alpha: data.readFloat() - } + texture: sea.getObject( data.readUInt() ), + alpha: data.readFloat() + }; break; default: console.warn( "SEA3D: MaterialTechnique not found:", kind.toString( 16 ) ); + data.position = pos += size; continue; } @@ -3418,7 +3601,7 @@ SEA3D.Material = function( name, data, sea ) { } -} +}; SEA3D.Material.DEFAULT = 0; SEA3D.Material.COMPOSITE_TEXTURE = 1; @@ -3459,299 +3642,480 @@ SEA3D.Composite = function( name, data, sea ) { this.layer = []; - for ( var i = 0; i < layerCount; i ++ ) - this.layer[ i ] = this.readLayer( data, this ); + for ( var i = 0; i < layerCount; i ++ ) { + + this.layer[ i ] = new SEA3D.Composite.prototype.Layer( data, sea ); + + } -} +}; SEA3D.Composite.prototype.getLayerByName = function( name ) { for ( var i = 0; i < this.layer.length; i ++ ) { - if ( this.layer[ i ].name == name ) + if ( this.layer[ i ].name == name ) { + return this.layer[ i ]; + } + } -} +}; + +SEA3D.Composite.prototype.Layer = function( data, sea ) { + + var attrib = data.readUShort(); + + if ( attrib & 1 ) this.texture = new SEA3D.Composite.LayerBitmap( data, sea ); + else this.color = data.readUInt24(); + + if ( attrib & 2 ) { + + this.mask = new SEA3D.Composite.LayerBitmap( data, sea ); + + } -SEA3D.Composite.prototype.readLayer = function( data, scope ) { + if ( attrib & 4 ) { - this.scope = scope; + this.name = data.readUTF8(); - var out = { - blendMode: "normal", - opacity: 1 } + this.blendMode = attrib & 8 ? data.readBlendMode() : "normal"; + + this.opacity = attrib & 16 ? data.readFloat() : 1; + +}; + +SEA3D.Composite.LayerBitmap = function( data, sea ) { + + this.map = sea.getObject( data.readUInt() ); + var attrib = data.readUShort(); - if ( attrib & 1 ) out.texture = this.readLayerBitmap( data, scope ); - else out.color = data.readUInt24(); + this.channel = attrib & 1 ? data.readUByte() : 0; + this.repeat = attrib & 2 == 0; + this.offsetU = attrib & 4 ? data.readFloat() : 0; + this.offsetV = attrib & 8 ? data.readFloat() : 0; + this.scaleU = attrib & 16 ? data.readFloat() : 1; + this.scaleV = attrib & 32 ? data.readFloat() : 1; + this.rotation = attrib & 64 ? data.readFloat() : 0; + + if ( attrib & 128 ) this.animation = data.readAnimationList( sea ); + +}; + +SEA3D.Composite.prototype.type = "ctex"; + +// +// Sphere +// + +SEA3D.Sphere = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.radius = data.readFloat(); + +}; + +SEA3D.Sphere.prototype.type = "sph"; + +// +// Box +// + +SEA3D.Box = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.width = data.readFloat(); + this.height = data.readFloat(); + this.depth = data.readFloat(); + +}; - if ( attrib & 2 ) - out.mask = this.readLayerBitmap( data, scope ); +SEA3D.Box.prototype.type = "box"; - if ( attrib & 4 ) - out.name = data.readUTF8(); +// +// Cone +// + +SEA3D.Cone = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.radius = data.readFloat(); + this.height = data.readFloat(); + +}; + +SEA3D.Cone.prototype.type = "cone"; + +// +// Capsule +// + +SEA3D.Capsule = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.radius = data.readFloat(); + this.height = data.readFloat(); + +}; + +SEA3D.Capsule.prototype.type = "cap"; + +// +// Cylinder +// + +SEA3D.Cylinder = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.radius = data.readFloat(); + this.height = data.readFloat(); + +}; + +SEA3D.Cylinder.prototype.type = "cyl"; + +// +// Geometry Shape +// + +SEA3D.GeometryShape = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; - if ( attrib & 8 ) - out.blendMode = data.readBlendMode(); + this.geometry = sea.getObject( data.readUInt() ); + this.subGeometryIndex = data.readUByte(); + +}; + +SEA3D.GeometryShape.prototype.type = "gs"; + +// +// Static Geometry Shape +// + +SEA3D.StaticGeometryShape = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.geometry = sea.getObject( data.readUInt() ); + this.subGeometryIndex = data.readUByte(); + +}; + +SEA3D.StaticGeometryShape.prototype.type = "sgs"; + +// +// Physics +// + +SEA3D.Physics = function( name, data, sea ) { + + this.name = name; + this.data = data; + this.sea = sea; + + this.attrib = data.readUShort(); + + this.shape = sea.getObject( data.readUInt() ); + + if ( this.attrib & 1 ) this.target = sea.getObject( data.readUInt() ); + else this.transform = data.readMatrix(); + +}; + +SEA3D.Physics.prototype.readTag = function( kind, data, size ) { + +}; + +// +// Rigidy Body Base +// + +SEA3D.RigidBodyBase = function( name, data, sea ) { + + SEA3D.Physics.call( this, name, data, sea ); + + if ( this.attrib & 32 ) { + + this.linearDamping = data.readFloat(); + this.angularDamping = data.readFloat(); + + } else { + + this.linearDamping = 0; + this.angularDamping = 0; + + } + + this.mass = data.readFloat(); + this.friction = data.readFloat(); + this.restitution = data.readFloat(); + +}; + +SEA3D.RigidBodyBase.prototype = Object.create( SEA3D.Physics.prototype ); +SEA3D.RigidBodyBase.prototype.constructor = SEA3D.RigidBodyBase; + +// +// Rigidy Body +// - if ( attrib & 16 ) - out.opacity = data.readFloat(); +SEA3D.RigidBody = function( name, data, sea ) { - return out; + SEA3D.RigidBodyBase.call( this, name, data, sea ); -} + data.readTags( this.readTag.bind( this ) ); -SEA3D.Composite.prototype.readLayerBitmap = function( data, scope ) { +}; - this.scope = scope; +SEA3D.RigidBody.prototype = Object.create( SEA3D.RigidBodyBase.prototype ); +SEA3D.RigidBody.prototype.constructor = SEA3D.RigidBody; - var out = { - channel: 0, - repeat: true, - offsetU: 0, - offsetV: 0, - scaleU: 0, - scaleV: 0, - rotation: 0 - } +SEA3D.RigidBody.prototype.type = "rb"; - out.map = scope.sea.getObject( data.readUInt() ); +// +// Car Controller +// - var attrib = data.readUShort(); +SEA3D.CarController = function( name, data, sea ) { - if ( attrib > 0 ) { + SEA3D.RigidBodyBase.call( this, name, data, sea ); - if ( attrib & 1 ) - out.channel = data.readUByte(); + this.suspensionStiffness = data.readFloat(); + this.suspensionCompression = data.readFloat(); + this.suspensionDamping = data.readFloat(); + this.maxSuspensionTravelCm = data.readFloat(); + this.frictionSlip = data.readFloat(); + this.maxSuspensionForce = data.readFloat(); - if ( attrib & 2 ) - out.repeat = false; + this.dampingCompression = data.readFloat(); + this.dampingRelaxation = data.readFloat(); - if ( attrib & 4 ) - out.offsetU = data.readFloat(); + var count = data.readUByte(); - if ( attrib & 8 ) - out.offsetV = data.readFloat(); + this.wheel = []; - if ( attrib & 16 ) - out.scaleU = data.readFloat(); + for ( var i = 0; i < count; i ++ ) { - if ( attrib & 32 ) - out.scaleV = data.readFloat(); + this.wheel[ i ] = new SEA3D.CarController.Wheel( data, sea ); - if ( attrib & 64 ) - out.rotation = data.readFloat(); + } - if ( attrib & 128 ) - out.animation = SEA3D.Animation.readAnimationList( data, scope.sea ); + data.readTags( this.readTag.bind( this ) ); - } +}; - return out; +SEA3D.CarController.Wheel = function( data, sea ) { -} + this.data = data; + this.sea = sea; -SEA3D.Composite.prototype.type = "ctex"; + var attrib = data.readUShort(); -// -// Sphere -// + this.isFront = ( attrib & 1 ) != 0, -SEA3D.Sphere = function( name, data, sea ) { + this.target = sea.getObject( data.readUInt() ); - this.name = name; - this.data = data; - this.sea = sea; + this.pos = data.readVector3(); + this.dir = data.readVector3(); + this.axle = data.readVector3(); this.radius = data.readFloat(); + this.suspensionRestLength = data.readFloat(); -} +}; -SEA3D.Sphere.prototype.type = "sph"; +SEA3D.CarController.prototype = Object.create( SEA3D.RigidBodyBase.prototype ); +SEA3D.CarController.prototype.constructor = SEA3D.CarController; + +SEA3D.CarController.prototype.type = "carc"; // -// Box +// Constraints // -SEA3D.Box = function( name, data, sea ) { +SEA3D.Constraints = function( name, data, sea ) { this.name = name; this.data = data; this.sea = sea; - this.width = data.readFloat(); - this.height = data.readFloat(); - this.depth = data.readFloat(); - -} - -SEA3D.Box.prototype.type = "box"; + this.attrib = data.readUShort(); -// -// Cone -// + this.disableCollisionsBetweenBodies = this.attrib & 1 != 0; -SEA3D.Cone = function( name, data, sea ) { + this.targetA = sea.getObject( data.readUInt() ); + this.pointA = data.readVector3(); - this.name = name; - this.data = data; - this.sea = sea; + if ( this.attrib & 2 ) { - this.radius = data.readFloat(); - this.height = data.readFloat(); + this.targetB = sea.getObject( data.readUInt() ); + this.pointB = data.readVector3(); -} + } -SEA3D.Cone.prototype.type = "cone"; +}; // -// Capsule +// P2P Constraint // -SEA3D.Capsule = function( name, data, sea ) { +SEA3D.P2PConstraint = function( name, data, sea ) { this.name = name; this.data = data; this.sea = sea; - this.radius = data.readFloat(); - this.height = data.readFloat(); + SEA3D.Constraints.call( this, name, data, sea ); -} +}; -SEA3D.Capsule.prototype.type = "cap"; +SEA3D.P2PConstraint.prototype = Object.create( SEA3D.Constraints.prototype ); +SEA3D.P2PConstraint.prototype.constructor = SEA3D.P2PConstraint; + +SEA3D.P2PConstraint.prototype.type = "p2pc"; // -// Cylinder +// Hinge Constraint // -SEA3D.Cylinder = function( name, data, sea ) { - - this.name = name; - this.data = data; - this.sea = sea; - - this.radius = data.readFloat(); - this.height = data.readFloat(); +SEA3D.HingeConstraint = function( name, data, sea ) { -} + SEA3D.Constraints.call( this, name, data, sea ); -SEA3D.Cylinder.prototype.type = "cyl"; + this.axisA = data.readVector3(); -// -// Geometry Shape -// + if ( this.attrib & 1 ) { -SEA3D.GeometryShape = function( name, data, sea ) { + this.axisB = data.readVector3(); - this.name = name; - this.data = data; - this.sea = sea; + } - this.geometry = sea.getObject( data.readUInt() ); - this.subGeometryIndex = data.readUByte(); + if ( this.attrib & 4 ) { -} + this.limit = { + low : data.readFloat(), + high : data.readFloat(), + softness : data.readFloat(), + biasFactor : data.readFloat(), + relaxationFactor : data.readFloat() + } -SEA3D.GeometryShape.prototype.type = "gs"; + } -// -// Static Geometry Shape -// + if ( this.attrib & 8 ) { -SEA3D.StaticGeometryShape = function( name, data, sea ) { + this.angularMotor = { + velocity : data.readFloat(), + impulse : data.readFloat() + } - this.name = name; - this.data = data; - this.sea = sea; + } - this.geometry = sea.getObject( data.readUInt() ); - this.subGeometryIndex = data.readUByte(); +}; -} +SEA3D.HingeConstraint.prototype = Object.create( SEA3D.Constraints.prototype ); +SEA3D.HingeConstraint.prototype.constructor = SEA3D.HingeConstraint; -SEA3D.StaticGeometryShape.prototype.type = "sgs"; +SEA3D.HingeConstraint.prototype.type = "hnec"; // -// Physics +// Cone Twist Constraint // -SEA3D.Physics = -{ - read : function( scope ) { +SEA3D.ConeTwistConstraint = function( name, data, sea ) { - var data = scope.data, - sea = scope.sea; + SEA3D.Constraints.call( this, name, data, sea ); - scope.attrib = data.readUShort(); + this.axisA = data.readVector3(); - scope.shape = sea.getObject( data.readUInt() ); + if ( this.attrib & 1 ) { - if ( scope.attrib & 1 ) - scope.target = sea.getObject( data.readUInt() ); - else - scope.transform = data.readMatrix(); + this.axisB = data.readVector3(); } - , readTags : function( scope, readTag ) { - var data = scope.data, - numTag = data.readUByte(); - - for ( var i = 0; i < numTag; ++ i ) { - - var kind = data.readUShort(); - var size = data.readUInt(); - var pos = data.position; - - if ( readTag !== undefined ) { + if ( this.attrib & 4 ) { - readTag( kind, data, size ) + this.limit = { + swingSpan1 : data.readFloat(), + swingSpan2 : data.readFloat(), + twistSpan : data.readFloat(), + softness : data.readFloat(), + biasFactor : data.readFloat(), + relaxationFactor : data.readFloat() + }; - } + } - data.position = pos += size; +}; - } +SEA3D.ConeTwistConstraint.prototype = Object.create( SEA3D.Constraints.prototype ); +SEA3D.ConeTwistConstraint.prototype.constructor = SEA3D.ConeTwistConstraint; - } -} +SEA3D.ConeTwistConstraint.prototype.type = "ctwc"; // -// Rigidy Body +// Planar Render // -SEA3D.RigidBody = function( name, data, sea ) { +SEA3D.PlanarRender = function( name, data, sea ) { this.name = name; this.data = data; this.sea = sea; - SEA3D.Physics.read( this ); + this.attrib = data.readUByte(); - if ( this.attrib & 32 ) { + this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 ); + this.transform = data.readMatrix(); - this.linearDamping = data.readFloat(); - this.angularDamping = data.readFloat(); +}; - } else { +SEA3D.PlanarRender.prototype.type = "rttp"; - this.linearDamping = 0; - this.angularDamping = 0; +// +// Cube Render +// - } +SEA3D.CubeRender = function( name, data, sea ) { - this.mass = data.readFloat(); - this.friction = data.readFloat(); - this.restitution = data.readFloat(); + this.name = name; + this.data = data; + this.sea = sea; -} + this.attrib = data.readUByte(); -SEA3D.RigidBody.prototype.type = "rb"; + this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 ); + this.position = data.readVector3(); + +}; + +SEA3D.CubeRender.prototype.type = "rttc"; // // Cube Maps @@ -3772,12 +4136,14 @@ SEA3D.CubeMap = function( name, data, sea ) { for ( var i = 0; i < 6; i ++ ) { var size = data.readUInt(); + this.faces[ i ] = data.concat( data.position, size ); + data.position += size; } -} +}; SEA3D.CubeMap.prototype.type = "cmap"; @@ -3793,7 +4159,7 @@ SEA3D.JPEG = function( name, data, sea ) { this.transparent = false; -} +}; SEA3D.JPEG.prototype.type = "jpg"; @@ -3809,7 +4175,7 @@ SEA3D.JPEG_XR = function( name, data, sea ) { this.transparent = true; -} +}; SEA3D.JPEG_XR.prototype.type = "wdp"; @@ -3825,7 +4191,7 @@ SEA3D.PNG = function( name, data, sea ) { this.transparent = data.buffer[ 25 ] == 0x06; -} +}; SEA3D.PNG.prototype.type = "png"; @@ -3841,7 +4207,7 @@ SEA3D.GIF = function( name, data, sea ) { this.transparent = data.buffer[ 11 ] > 0; -} +}; SEA3D.GIF.prototype.type = "gif"; @@ -3855,7 +4221,7 @@ SEA3D.OGG = function( name, data, sea ) { this.data = data; this.sea = sea; -} +}; SEA3D.OGG.prototype.type = "ogg"; @@ -3869,7 +4235,7 @@ SEA3D.MP3 = function( name, data, sea ) { this.data = data; this.sea = sea; -} +}; SEA3D.MP3.prototype.type = "mp3"; @@ -3881,16 +4247,19 @@ SEA3D.File = function( data ) { this.version = SEA3D.VERSION; this.objects = []; - this.typeClass = {} - this.typeRead = {} + this.typeClass = {}; + this.typeRead = {}; + this.typeUnique = {}; this.position = this.dataPosition = 0; this.scope = this; + this.streaming = true; this.timeLimit = 60; // SEA3D - this.addClass( SEA3D.Geometry ); - this.addClass( SEA3D.GeometryDelta ); + this.addClass( SEA3D.FileInfo, true ); + this.addClass( SEA3D.Geometry, true ); + this.addClass( SEA3D.GeometryDelta, true ); this.addClass( SEA3D.Mesh ); this.addClass( SEA3D.Mesh2D ); this.addClass( SEA3D.Material ); @@ -3898,14 +4267,14 @@ SEA3D.File = function( data ) { this.addClass( SEA3D.PointLight ); this.addClass( SEA3D.DirectionalLight ); this.addClass( SEA3D.HemisphereLight ); - this.addClass( SEA3D.Skeleton ); - this.addClass( SEA3D.SkeletonLocal ); - this.addClass( SEA3D.SkeletonAnimation ); + this.addClass( SEA3D.Skeleton, true ); + this.addClass( SEA3D.SkeletonLocal, true ); + this.addClass( SEA3D.SkeletonAnimation, true ); this.addClass( SEA3D.JointObject ); this.addClass( SEA3D.Camera ); - this.addClass( SEA3D.Morph ); - this.addClass( SEA3D.VertexAnimation ); - this.addClass( SEA3D.CubeMap ); + this.addClass( SEA3D.Morph, true ); + this.addClass( SEA3D.VertexAnimation, true ); + this.addClass( SEA3D.CubeMap, true ); this.addClass( SEA3D.Animation ); this.addClass( SEA3D.Dummy ); this.addClass( SEA3D.Line ); @@ -3913,10 +4282,11 @@ SEA3D.File = function( data ) { this.addClass( SEA3D.PlanarRender ); this.addClass( SEA3D.CubeRender ); this.addClass( SEA3D.Actions ); - this.addClass( SEA3D.TextureURL ); this.addClass( SEA3D.Container3D ); this.addClass( SEA3D.Properties ); - this.addClass( SEA3D.FileInfo ); + + // URL + this.addClass( SEA3D.TextureURL, true ); // PHYSICS this.addClass( SEA3D.Sphere ); @@ -3927,19 +4297,23 @@ SEA3D.File = function( data ) { this.addClass( SEA3D.GeometryShape ); this.addClass( SEA3D.StaticGeometryShape ); this.addClass( SEA3D.RigidBody ); + this.addClass( SEA3D.P2PConstraint ); + this.addClass( SEA3D.HingeConstraint ); + this.addClass( SEA3D.ConeTwistConstraint ); + this.addClass( SEA3D.CarController ); // UNIVERSAL - this.addClass( SEA3D.JPEG ); - this.addClass( SEA3D.JPEG_XR ); - this.addClass( SEA3D.PNG ); - this.addClass( SEA3D.GIF ); - this.addClass( SEA3D.OGG ); - this.addClass( SEA3D.MP3 ); - this.addClass( SEA3D.JavaScript ); - this.addClass( SEA3D.JavaScriptMethod ); - this.addClass( SEA3D.GLSL ); - -} + this.addClass( SEA3D.JPEG, true ); + this.addClass( SEA3D.JPEG_XR, true ); + this.addClass( SEA3D.PNG, true ); + this.addClass( SEA3D.GIF, true ); + this.addClass( SEA3D.OGG, true ); + this.addClass( SEA3D.MP3, true ); + this.addClass( SEA3D.JavaScript, true ); + this.addClass( SEA3D.JavaScriptMethod, true ); + this.addClass( SEA3D.GLSL, true ); + +}; SEA3D.File.CompressionLibs = {}; SEA3D.File.DecompressionMethod = {} @@ -3949,13 +4323,14 @@ SEA3D.File.setDecompressionEngine = function( id, name, method ) { SEA3D.File.CompressionLibs[ id ] = name; SEA3D.File.DecompressionMethod[ id ] = method; -} +}; -SEA3D.File.prototype.addClass = function( clazz ) { +SEA3D.File.prototype.addClass = function( clazz, unique ) { this.typeClass[ clazz.prototype.type ] = clazz; + this.typeUnique[ clazz.prototype.type ] = unique === true; -} +}; SEA3D.File.prototype.readHead = function() { @@ -3971,7 +4346,7 @@ SEA3D.File.prototype.readHead = function() { if ( this.stream.readUByte() != 0 ) { - throw new Error( "Protection algorithm not is compatible." ); + throw new Error( "Protection algorithm not compatible." ); } @@ -3982,7 +4357,7 @@ SEA3D.File.prototype.readHead = function() { if ( this.compressionID > 0 && ! this.decompressionMethod ) { - throw new Error( "Compression algorithm not is compatible." ); + throw new Error( "Compression algorithm not compatible." ); } @@ -4002,13 +4377,13 @@ SEA3D.File.prototype.readHead = function() { return true; -} +}; SEA3D.File.prototype.getObject = function( index ) { return this.objects[ index ]; -} +}; SEA3D.File.prototype.readSEAObject = function() { @@ -4029,17 +4404,20 @@ SEA3D.File.prototype.readSEAObject = function() { compressed = ( flag & 2 ) != 0, streaming = ( flag & 4 ) != 0; - if ( flag & 8 ) - { + if ( flag & 8 ) { var metalen = this.stream.readUShort(); var metabytes = this.stream.concat( this.stream.position, metalen ); + this.stream.position += metalen; - if ( compressed && this.decompressionMethod ) + if ( compressed && this.decompressionMethod ) { + metabytes.set( this.decompressionMethod( metabytes.buffer ) ); - meta = SEA3D.Properties.readProperties( metabytes, this.objects ); + } + + meta = metabytes.readProperties( this ); } @@ -4049,20 +4427,24 @@ SEA3D.File.prototype.readSEAObject = function() { var data = this.stream.concat( position, size ), obj; - if ( this.typeClass[ type ] ) - { + if ( this.typeClass[ type ] ) { + + if ( compressed && this.decompressionMethod ) { - if ( compressed && this.decompressionMethod ) data.buffer = this.decompressionMethod( data.buffer ); + } + obj = new this.typeClass[ type ]( name, data, this ); - if ( streaming && this.typeRead[ type ] ) + if ( this.streaming && streaming && this.typeRead[ type ] ) { + this.typeRead[ type ].call( this.scope, obj ); + } + } - else - { + else { obj = new SEA3D.Object( name, data, type, this ); @@ -4070,6 +4452,7 @@ SEA3D.File.prototype.readSEAObject = function() { } + obj.streaming = streaming; obj.metadata = meta; this.objects.push( this.objects[ obj.type + "/" + obj.name ] = obj ); @@ -4080,7 +4463,7 @@ SEA3D.File.prototype.readSEAObject = function() { return obj; -} +}; SEA3D.File.prototype.readBody = function() { @@ -4106,7 +4489,73 @@ SEA3D.File.prototype.readBody = function() { return true; -} +}; + +SEA3D.File.prototype.parse = function() { + + this.timer = new SEA3D.Timer(); + this.position = 0; + + setTimeout( this.parseObject.bind( this ), 10 ); + +}; + +SEA3D.File.prototype.parseObject = function() { + + this.timer.update(); + + while ( this.position < this.length && this.timer.deltaTime < this.timeLimit ) { + + var obj = this.objects[ this.position ++ ], + type = obj.type; + + if ( ! this.typeUnique[ type ] ) delete obj.tag; + + if ( obj.streaming && this.typeRead[ type ] ) { + + if ( obj.tag == undefined ) { + + this.typeRead[ type ].call( this.scope, obj ); + + } + + } + + } + + if ( this.position == this.length ) { + + var elapsedTime = this.timer.elapsedTime; + var message = elapsedTime + "ms, " + this.objects.length + " objects"; + + if ( this.onParseComplete ) { + + this.onParseComplete( { + file: this, + timeTotal: elapsedTime, + message: message + } ); + + } else console.log( "SEA3D Parse Complete:", message ); + + } else { + + if ( this.onParseProgress ) { + + this.onParseProgress( { + file: this, + loaded: this.position, + total: this.length, + progress: this.position / this.length + } ); + + } + + setTimeout( this.parseObject.bind( this ), 10 ); + + } + +}; SEA3D.File.prototype.readComplete = function() { @@ -4119,7 +4568,7 @@ SEA3D.File.prototype.readComplete = function() { this.dispatchComplete(); -} +}; SEA3D.File.prototype.readState = function() { @@ -4127,12 +4576,12 @@ SEA3D.File.prototype.readState = function() { if ( this.state ) { - window.setTimeout( this.readState.bind( this ), 10 ); + setTimeout( this.readState.bind( this ), 10 ); this.dispatchProgress(); } -} +}; SEA3D.File.prototype.read = function( data ) { @@ -4142,44 +4591,44 @@ SEA3D.File.prototype.read = function( data ) { this.readState(); -} +}; SEA3D.File.prototype.dispatchCompleteObject = function( obj ) { if ( ! this.onCompleteObject ) return; this.onCompleteObject( { - file: this, - object: obj - } ); + file: this, + object: obj + } ); -} +}; SEA3D.File.prototype.dispatchProgress = function() { if ( ! this.onProgress ) return; this.onProgress( { - file: this, - loaded: this.position, - total: this.length, - progress: this.position / this.length - } ); + file: this, + loaded: this.position, + total: this.length, + progress: this.position / this.length + } ); -} +}; SEA3D.File.prototype.dispatchDownloadProgress = function( position, length ) { if ( ! this.onDownloadProgress ) return; this.onDownloadProgress( { - file: this, - loaded: position, - total: length, - progress: position / length - } ); + file: this, + loaded: position, + total: length, + progress: position / length + } ); -} +}; SEA3D.File.prototype.dispatchComplete = function() { @@ -4193,14 +4642,14 @@ SEA3D.File.prototype.dispatchComplete = function() { } ); else console.log( "SEA3D:", message ); -} +}; SEA3D.File.prototype.dispatchError = function( id, message ) { if ( this.onError ) this.onError( { file: this, id: id, message: message } ); else console.error( "SEA3D: #" + id, message ); -} +}; SEA3D.File.prototype.load = function( url ) { @@ -4212,9 +4661,12 @@ SEA3D.File.prototype.load = function( url ) { xhr.onprogress = function( e ) { - if ( e.lengthComputable ) + if ( e.lengthComputable ) { + file.dispatchDownloadProgress( e.loaded, e.total ); + } + } xhr.onreadystatechange = function() { @@ -4242,4 +4694,114 @@ SEA3D.File.prototype.load = function( url ) { xhr.send(); -} +}; + +/** + * EventDispatcher.js + * @author mrdoob / http://mrdoob.com/ + * @sunag sunag / http://www.sunag.com.br/ + */ + +SEA3D.EventDispatcher = function () {} + +SEA3D.EventDispatcher.prototype = { + + constructor: SEA3D.EventDispatcher, + + addEventListener: function ( type, listener ) { + + if ( this._listeners === undefined ) this._listeners = {}; + + var listeners = this._listeners; + + if ( listeners[ type ] === undefined ) { + + listeners[ type ] = []; + + } + + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + + listeners[ type ].push( listener ); + + } + + }, + + hasEventListener: function ( type, listener ) { + + if ( this._listeners === undefined ) return false; + + var listeners = this._listeners; + + if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) { + + return true; + + } + + return false; + + }, + + removeEventListener: function ( type, listener ) { + + if ( this._listeners === undefined ) return; + + var listeners = this._listeners; + var listenerArray = listeners[ type ]; + + if ( listenerArray !== undefined ) { + + var index = listenerArray.indexOf( listener ); + + if ( index !== - 1 ) { + + listenerArray.splice( index, 1 ); + + } + + } + + }, + + dispatchEvent: function ( event ) { + + if ( this._listeners === undefined ) return; + + var listeners = this._listeners; + var listenerArray = listeners[ event.type ]; + + if ( listenerArray !== undefined ) { + + event.target = this; + + var array = []; + var length = listenerArray.length; + + for ( var i = 0; i < length; i ++ ) { + + array[ i ] = listenerArray[ i ]; + + } + + for ( var i = 0; i < length; i ++ ) { + + array[ i ].call( this, event ); + + } + + } + + } + +}; + +SEA3D.EventDispatcher.apply = function ( object ) { + + object.addEventListener = SEA3D.EventDispatcher.prototype.addEvenListener; + object.hasEventListener = SEA3D.EventDispatcher.prototype.hasEventListener; + object.removeEventListener = SEA3D.EventDispatcher.prototype.removeEventListener; + object.dispatchEvent = SEA3D.EventDispatcher.prototype.dispatchEvent; + +}; diff --git a/examples/js/loaders/sea3d/SEA3DLoader.js b/examples/js/loaders/sea3d/SEA3DLoader.js index e8ba8af3300790..747de1a670dc69 100644 --- a/examples/js/loaders/sea3d/SEA3DLoader.js +++ b/examples/js/loaders/sea3d/SEA3DLoader.js @@ -3,6 +3,8 @@ * @author Sunag / http://www.sunag.com.br/ */ +'use strict'; + // // SEA3D // @@ -11,17 +13,17 @@ THREE.SEA3D = function( config ) { this.config = config || {}; - if ( this.config.autoPlay === undefined ) this.config.autoPlay = false; + if ( this.config.script == undefined ) this.config.script = true; + if ( this.config.autoPlay == undefined ) this.config.autoPlay = false; if ( this.config.multiplier == undefined ) this.config.multiplier = 1; if ( this.config.bounding == undefined ) this.config.bounding = true; if ( this.config.standardMaterial == undefined ) this.config.standardMaterial = true; if ( this.config.audioRolloffFactor == undefined ) this.config.audioRolloffFactor = 10; + if ( this.config.timeLimit == undefined ) this.config.timeLimit = 10; + if ( this.config.streaming == undefined ) this.config.streaming = true; + if ( this.config.lights == undefined ) this.config.lights = true; - this.container = this.config.container; - - this.objects = {}; - -} +}; THREE.SEA3D.prototype = { constructor: THREE.SEA3D, @@ -29,8 +31,28 @@ THREE.SEA3D.prototype = { addEventListener: THREE.EventDispatcher.prototype.addEventListener, hasEventListener: THREE.EventDispatcher.prototype.hasEventListener, removeEventListener: THREE.EventDispatcher.prototype.removeEventListener, - dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent -} + dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent, + + set container ( val ) { + + this.config.container = val; + + }, + + get container () { + + return this.config.container; + + } +}; + +// +// Defaults +// + +THREE.SEA3D.BACKGROUND_COLOR = 0x333333; +THREE.SEA3D.HELPER_COLOR = 0x9AB9E5; +THREE.SEA3D.RTT_SIZE = 512; // // Shader @@ -46,9 +68,12 @@ THREE.SEA3D.ShaderLib.replaceCode = function( src, target, replace ) { rep = replace[ i ], index = src.indexOf( tar ); - if ( index > - 1 ) + if ( index > - 1 ) { + src = src.substring( 0, index ) + rep + src.substring( index + tar.length ); + } + } return src; @@ -99,13 +124,13 @@ THREE.SEA3D.StandardMaterial.prototype.__defineSetter__( "__webglShader", functi val.fragmentShader = THREE.SEA3D.ShaderLib.fragStdMtl; this.__webglShader__ = val; -} ); +} ) THREE.SEA3D.StandardMaterial.prototype.__defineGetter__( "__webglShader", function() { return this.__webglShader__; -} ); +} ) // // Container @@ -125,11 +150,37 @@ THREE.SEA3D.Object3D.prototype.constructor = THREE.SEA3D.Object3D; THREE.SEA3D.Object3D.prototype.updateAnimateMatrix = function( force ) { - THREE.Mesh.prototype.updateMatrixWorld.call( this, force ); + if ( this.matrixAutoUpdate === true ) this.updateMatrix(); + + if ( this.matrixWorldNeedsUpdate === true || force === true ) { + + if ( this.parent === null ) { + + this.matrixWorld.copy( this.matrix ); + + } else { + + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + + } + + this.animateMatrix.compose( this.animatePosition, this.animateQuaternion, this.animateScale ); + + this.matrixWorld.multiplyMatrices( this.matrixWorld, this.animateMatrix ); + + this.matrixWorldNeedsUpdate = false; - this.animateMatrix.compose( this.animatePosition, this.animateQuaternion, this.animateScale ); + force = true; - this.matrixWorld.multiplyMatrices( this.matrixWorld, this.animateMatrix ); + } + + // update children + + for ( var i = 0, l = this.children.length; i < l; i ++ ) { + + this.children[ i ].updateMatrixWorld( force ); + + } }; @@ -170,6 +221,42 @@ THREE.SEA3D.Object3D.prototype.getAnimateMatrix = function() { }; +// +// Dummy +// + +THREE.SEA3D.Dummy = function ( width, height, depth ) { + + this.width = width != undefined ? width : 100; + this.height = height != undefined ? height : 100; + this.depth = depth != undefined ? depth : 100; + + var geo = new THREE.BoxGeometry( this.width, this.height, this.depth, 1, 1, 1 ); + + THREE.Mesh.call( this, geo, THREE.SEA3D.Dummy.MATERIAL ); + +}; + +THREE.SEA3D.Dummy.prototype = Object.create( THREE.Mesh.prototype ); +THREE.SEA3D.Dummy.prototype.constructor = THREE.Dummy; + +THREE.SEA3D.Dummy.prototype.setAnimateMatrix = THREE.SEA3D.Object3D.prototype.setAnimateMatrix; +THREE.SEA3D.Dummy.prototype.getAnimateMatrix = THREE.SEA3D.Object3D.prototype.getAnimateMatrix; + +THREE.SEA3D.Dummy.MATERIAL = new THREE.MeshBasicMaterial( { wireframe: true, color: THREE.SEA3D.HELPER_COLOR } ); + +THREE.SEA3D.Dummy.prototype.clone = function ( object ) { + + return new THREE.SEA3D.Dummy( this.width, this.height, this.depth ).copy( this ); + +}; + +THREE.SEA3D.Dummy.prototype.dispose = function () { + + this.geometry.dispose(); + +}; + // // Mesh // @@ -198,17 +285,6 @@ THREE.SEA3D.Mesh.prototype.getWeight = function( name ) { }; -THREE.SEA3D.Mesh.prototype.dispose = function () { - - if ( this.animation ) - this.animation.dispose(); - - delete this.animations; - - THREE.Mesh.prototype.dispose.call( this ); - -}; - THREE.SEA3D.Mesh.prototype.copy = function ( source ) { THREE.Mesh.prototype.copy.call( this, source ); @@ -239,8 +315,8 @@ THREE.SEA3D.SkinnedMesh = function ( geometry, material, useVertexTexture ) { THREE.SEA3D.SkinnedMesh.prototype = Object.create( THREE.SkinnedMesh.prototype ); THREE.SEA3D.SkinnedMesh.prototype.constructor = THREE.SEA3D.SkinnedMesh; -THREE.SEA3D.SkinnedMesh.prototype.setAnimateMatrix = THREE.SEA3D.Mesh.prototype.setAnimateMatrix; -THREE.SEA3D.SkinnedMesh.prototype.getAnimateMatrix = THREE.SEA3D.Mesh.prototype.getAnimateMatrix; +THREE.SEA3D.SkinnedMesh.prototype.setAnimateMatrix = THREE.SEA3D.Object3D.prototype.setAnimateMatrix; +THREE.SEA3D.SkinnedMesh.prototype.getAnimateMatrix = THREE.SEA3D.Object3D.prototype.getAnimateMatrix; THREE.SEA3D.SkinnedMesh.prototype.setWeight = THREE.SEA3D.Mesh.prototype.setWeight; THREE.SEA3D.SkinnedMesh.prototype.getWeight = THREE.SEA3D.Mesh.prototype.getWeight; @@ -252,12 +328,14 @@ THREE.SEA3D.SkinnedMesh.prototype.stop = function() { if ( this.currentAnimation ) { this.currentAnimation.stop(); + delete this.currentAnimation; + this.isPlaying = false; } -} +}; THREE.SEA3D.SkinnedMesh.prototype.pause = function() { @@ -268,7 +346,7 @@ THREE.SEA3D.SkinnedMesh.prototype.pause = function() { } -} +}; THREE.SEA3D.SkinnedMesh.prototype.resume = function() { @@ -279,7 +357,7 @@ THREE.SEA3D.SkinnedMesh.prototype.resume = function() { } -} +}; THREE.SEA3D.SkinnedMesh.prototype.play = function( name, crossfade, offset ) { @@ -304,7 +382,7 @@ THREE.SEA3D.SkinnedMesh.prototype.play = function( name, crossfade, offset ) { this.isPlaying = true; -} +}; THREE.SEA3D.SkinnedMesh.prototype.setAnimations = function( animations ) { @@ -328,7 +406,7 @@ THREE.SEA3D.SkinnedMesh.prototype.setAnimations = function( animations ) { } -} +}; THREE.SEA3D.SkinnedMesh.prototype.boneByName = function( name ) { @@ -341,20 +419,7 @@ THREE.SEA3D.SkinnedMesh.prototype.boneByName = function( name ) { } -} - -THREE.SEA3D.SkinnedMesh.prototype.dispose = function () { - - this.stop(); - - if ( this.animation ) - this.animation.dispose(); - - delete this.animations; - - THREE.SkinnedMesh.prototype.dispose.call( this ); - -} +}; THREE.SEA3D.SkinnedMesh.prototype.copy = function ( source ) { @@ -407,6 +472,7 @@ THREE.SEA3D.VertexAnimationMesh = function ( geometry, material, fps ) { this.animations = geometry.animations; this.isPlaying = false; + this.totalTime = 0; this.playingCallback = this.updateAnimation.bind( this ); @@ -416,46 +482,53 @@ THREE.SEA3D.VertexAnimationMesh = function ( geometry, material, fps ) { THREE.SEA3D.VertexAnimationMesh.prototype = Object.create( THREE.MorphAnimMesh.prototype ); THREE.SEA3D.VertexAnimationMesh.prototype.constructor = THREE.SEA3D.VertexAnimationMesh; +THREE.SEA3D.VertexAnimationMesh.prototype.setAnimateMatrix = THREE.SEA3D.Object3D.prototype.setAnimateMatrix; +THREE.SEA3D.VertexAnimationMesh.prototype.getAnimateMatrix = THREE.SEA3D.Object3D.prototype.getAnimateMatrix; + THREE.SEA3D.VertexAnimationMesh.prototype.play = function( name, offset ) { var animation = this.animations[ name ]; this.setFrameRange( animation.start ? animation.start : 1, animation.end - 1 ); + this.duration = ( animation.end - animation.start ) / this.fps; this.time = offset !== undefined ? offset : this.time; this.resume(); -} +}; THREE.SEA3D.VertexAnimationMesh.prototype.pause = function() { if ( this.isPlaying ) { this.isPlaying = false; + THREE.SEA3D.AnimationHandler.removeUpdate( this.playingCallback ); } -} +}; THREE.SEA3D.VertexAnimationMesh.prototype.resume = function() { if ( ! this.isPlaying ) { this.isPlaying = true; + THREE.SEA3D.AnimationHandler.addUpdate( this.playingCallback ); } -} +}; THREE.SEA3D.VertexAnimationMesh.prototype.stop = function() { this.pause(); + this.time = 0; -} +}; THREE.SEA3D.VertexAnimationMesh.prototype.clone = function ( object ) { @@ -463,6 +536,30 @@ THREE.SEA3D.VertexAnimationMesh.prototype.clone = function ( object ) { }; +// +// Camera +// + +THREE.SEA3D.Camera = function ( fov, aspect, near, far ) { + + THREE.PerspectiveCamera.call( this, fov, aspect, near, far ); + +}; + +THREE.SEA3D.Camera.prototype = Object.create( THREE.PerspectiveCamera.prototype ); +THREE.SEA3D.Camera.prototype.constructor = THREE.SEA3D.Camera; + +THREE.SEA3D.Camera.prototype.setAnimateMatrix = THREE.SEA3D.Object3D.prototype.setAnimateMatrix; +THREE.SEA3D.Camera.prototype.getAnimateMatrix = THREE.SEA3D.Object3D.prototype.getAnimateMatrix; + +THREE.SEA3D.Camera.prototype.copy = function ( source ) { + + THREE.PerspectiveCamera.prototype.copy.call( this, source ); + + return this; + +}; + // // Animation Update // @@ -489,15 +586,14 @@ THREE.SEA3D.AnimationHandler = { mesh.previousAnimation.weight = 0; mesh.currentAnimation.weight = 1; - if ( mesh.onCrossfadeComplete ) - mesh.onCrossfadeComplete( mesh ); + if ( mesh.onCrossfadeComplete ) mesh.onCrossfadeComplete( mesh ); cf.splice( i, 1 ); delete mesh.crossfade; - } else - ++ i; + } + else ++ i; mesh.previousAnimation.weight = 1 - mesh.currentAnimation.weight; @@ -517,9 +613,12 @@ THREE.SEA3D.AnimationHandler = { addCrossfade : function( mesh, crossfade ) { - if ( mesh.crossfade !== undefined ) + if ( mesh.crossfade !== undefined ) { + THREE.SEA3D.AnimationHandler.crossfade.splice( THREE.SEA3D.AnimationHandler.crossfade.indexOf( mesh ), 1 ); + } + mesh.crossfade = crossfade; THREE.SEA3D.AnimationHandler.crossfade.push( mesh ); @@ -536,12 +635,15 @@ THREE.SEA3D.AnimationHandler = { var index = THREE.SEA3D.AnimationHandler.updates.indexOf( func ); - if ( index !== - 1 ) + if ( index !== - 1 ) { + THREE.SEA3D.AnimationHandler.crossfade.splice( THREE.SEA3D.AnimationHandler.updates.indexOf( func ), 1 ); + } + } -} +}; // // Animation Event @@ -558,8 +660,7 @@ THREE.SEA3D.Animation.prototype.constructor = THREE.SEA3D.Animation; THREE.SEA3D.Animation.prototype.stop = function() { - if ( this.onComplete ) - this.onComplete( this ); + if ( this.onComplete ) this.onComplete( this ); THREE.Animation.prototype.stop.call( this ); @@ -567,8 +668,7 @@ THREE.SEA3D.Animation.prototype.stop = function() { THREE.SEA3D.Animation.prototype.reset = function() { - if ( this.onReset ) - this.onReset( this ); + if ( this.onReset ) this.onReset( this ); THREE.Animation.prototype.reset.call( this ); @@ -581,10 +681,6 @@ THREE.SEA3D.Animation.prototype.reset = function() { THREE.SEA3D.MTXBUF = new THREE.Matrix4(); THREE.SEA3D.VECBUF = new THREE.Vector3(); -THREE.SEA3D.BACKGROUND_COLOR = 0x333333; -THREE.SEA3D.HELPER_COLOR = 0x9AB9E5; -THREE.SEA3D.TEXTURE_SIZE = 512; - THREE.SEA3D.prototype.setShadowMap = function( light, opacity ) { light.shadowMapWidth = @@ -593,7 +689,7 @@ THREE.SEA3D.prototype.setShadowMap = function( light, opacity ) { light.castShadow = true; light.shadowDarkness = opacity !== undefined ? opacity : 1; -} +}; // // Output @@ -603,85 +699,85 @@ THREE.SEA3D.prototype.getMesh = function( name ) { return this.objects[ "m3d/" + name ]; -} +}; THREE.SEA3D.prototype.getDummy = function( name ) { return this.objects[ "dmy/" + name ]; -} +}; THREE.SEA3D.prototype.getLine = function( name ) { return this.objects[ "line/" + name ]; -} +}; THREE.SEA3D.prototype.getSound3D = function( name ) { return this.objects[ "sn3d/" + name ]; -} +}; THREE.SEA3D.prototype.getMaterial = function( name ) { return this.objects[ "mat/" + name ]; -} +}; THREE.SEA3D.prototype.getLight = function( name ) { return this.objects[ "lht/" + name ]; -} +}; THREE.SEA3D.prototype.getGLSL = function( name ) { return this.objects[ "glsl/" + name ]; -} +}; THREE.SEA3D.prototype.getCamera = function( name ) { return this.objects[ "cam/" + name ]; -} +}; THREE.SEA3D.prototype.getTexture = function( name ) { return this.objects[ "tex/" + name ]; -} +}; THREE.SEA3D.prototype.getCubeMap = function( name ) { return this.objects[ "cmap/" + name ]; -} +}; THREE.SEA3D.prototype.getJointObject = function( name ) { return this.objects[ "jnt/" + name ]; -} +}; THREE.SEA3D.prototype.getContainer3D = function( name ) { return this.objects[ "c3d/" + name ]; -} +}; THREE.SEA3D.prototype.getSprite = function( name ) { return this.objects[ "m2d/" + name ]; -} +}; THREE.SEA3D.prototype.getProperty = function( name ) { return this.objects[ "prop/" + name ]; -} +}; // // Utils @@ -691,22 +787,20 @@ THREE.SEA3D.prototype.isPowerOfTwo = function( num ) { return num ? ( ( num & - num ) == num ) : false; -} +}; THREE.SEA3D.prototype.nearestPowerOfTwo = function( num ) { return Math.pow( 2, Math.round( Math.log( num ) / Math.LN2 ) ); -} +}; THREE.SEA3D.prototype.updateTransform = function( obj3d, sea ) { var mtx = THREE.SEA3D.MTXBUF, vec = THREE.SEA3D.VECBUF; - if ( sea.transform ) - mtx.elements = sea.transform; - else - mtx.makeTranslation( sea.position.x, sea.position.y, sea.position.z ); + if ( sea.transform ) mtx.elements.set( sea.transform ); + else mtx.makeTranslation( sea.position.x, sea.position.y, sea.position.z ); // matrix @@ -727,13 +821,13 @@ THREE.SEA3D.prototype.updateTransform = function( obj3d, sea ) { } -} +}; THREE.SEA3D.prototype.toVector3 = function( data ) { return new THREE.Vector3( data.x, data.y, data.z ); -} +}; THREE.SEA3D.prototype.scaleColor = function( color, scale ) { @@ -743,7 +837,7 @@ THREE.SEA3D.prototype.scaleColor = function( color, scale ) { return ( r << 16 | g << 8 | b ); -} +}; THREE.SEA3D.prototype.updateScene = function() { @@ -757,26 +851,17 @@ THREE.SEA3D.prototype.updateScene = function() { } -} +}; THREE.SEA3D.prototype.addSceneObject = function( sea ) { var obj3d = sea.tag; - obj3d.props = sea.properties; + obj3d.userData = sea.properties; - if ( sea.scripts ) - { + if ( this.config.script && sea.scripts ) { - for ( var i = 0; i < sea.scripts.length; i ++ ) - { - - var script = sea.scripts[ i ]; - - if ( script.tag.type == SEA3D.JavaScriptMethod.prototype.type ) - this.runJS( obj3d, script ); - - } + this.runJSMList( obj3d, sea.scripts ); } @@ -784,30 +869,28 @@ THREE.SEA3D.prototype.addSceneObject = function( sea ) { sea.parent.tag.add( obj3d ); else if ( this.config.container ) this.config.container.add( obj3d ); - else - this.container.add( obj3d ); -} +}; THREE.SEA3D.prototype.createObjectURL = function( raw, mime ) { return ( window.URL || window.webkitURL ).createObjectURL( new Blob( [ raw ], { type: mime } ) ); -} +}; THREE.SEA3D.prototype.bufferToTexture = function( raw ) { return this.createObjectURL( raw, "image" ); -} +}; THREE.SEA3D.prototype.bufferToSound = function( raw ) { return this.createObjectURL( raw, "audio" ); -} +}; -THREE.SEA3D.prototype.applyDefaultAnimation = function( sea, ANIMATOR_CLASS ) { +THREE.SEA3D.prototype.applyDefaultAnimation = function( sea, animatorClass ) { var obj = sea.tag; @@ -817,19 +900,22 @@ THREE.SEA3D.prototype.applyDefaultAnimation = function( sea, ANIMATOR_CLASS ) { switch ( anm.tag.type ) { case SEA3D.Animation.prototype.type: - obj.animation = new ANIMATOR_CLASS( obj, anm.tag.tag ); + obj.animation = new animatorClass( obj, anm.tag.tag ); obj.animation.setRelative( anm.relative ); - if ( this.config.autoPlay ) + if ( this.config.autoPlay ) { + obj.animation.play( obj.animation.getStateNameByIndex( 0 ) ); + } + return obj.animation; break; } } -} +}; // // Animation @@ -847,6 +933,7 @@ THREE.SEA3D.prototype.readAnimation = function( sea ) { for ( var j = 0; j < sea.dataList.length; j ++ ) { var anmData = sea.dataList[ j ]; + node.addData( new SEA3D.AnimationData( anmData.kind, anmData.type, anmData.data, seq.start * anmData.blockSize ) ); } @@ -855,10 +942,10 @@ THREE.SEA3D.prototype.readAnimation = function( sea ) { } - this.animationSets = this.animationSets || []; + this.domain.animationSets = this.animationSets = this.animationSets || []; this.animationSets.push( this.objects[ sea.name + '.#anm' ] = sea.tag = anmSet ); -} +}; // // Object3D Animator @@ -867,9 +954,10 @@ THREE.SEA3D.prototype.readAnimation = function( sea ) { THREE.SEA3D.Object3DAnimator = function( object3d, animationSet ) { SEA3D.AnimationHandler.call( this, animationSet ); + this.object3d = object3d; -} +}; THREE.SEA3D.Object3DAnimator.prototype = Object.create( SEA3D.AnimationHandler.prototype ); THREE.SEA3D.Object3DAnimator.prototype.constructor = THREE.SEA3D.Object3DAnimator; @@ -886,13 +974,13 @@ THREE.SEA3D.Object3DAnimator.prototype.stop = function() { SEA3D.AnimationHandler.prototype.stop.call( this ); -} +}; THREE.SEA3D.Object3DAnimator.prototype.setRelative = function( val ) { this.object3d.setAnimateMatrix( this.relative = val ); -} +}; THREE.SEA3D.Object3DAnimator.prototype.updateAnimationFrame = function( frame, kind ) { @@ -901,16 +989,19 @@ THREE.SEA3D.Object3DAnimator.prototype.updateAnimationFrame = function( frame, k switch ( kind ) { case SEA3D.Animation.POSITION: var v = frame.toVector(); + this.object3d.animatePosition.set( v.x, v.y, v.z ); break; case SEA3D.Animation.ROTATION: var v = frame.toVector(); + this.object3d.animateQuaternion.set( v.x, v.y, v.z, v.w ); break; case SEA3D.Animation.SCALE: var v = frame.toVector(); + this.object3d.animateScale.set( v.x, v.y, v.z ); break; } @@ -922,23 +1013,26 @@ THREE.SEA3D.Object3DAnimator.prototype.updateAnimationFrame = function( frame, k switch ( kind ) { case SEA3D.Animation.POSITION: var v = frame.toVector(); + this.object3d.position.set( v.x, v.y, v.z ); break; case SEA3D.Animation.ROTATION: var v = frame.toVector(); + this.object3d.quaternion.set( v.x, v.y, v.z, v.w ); break; case SEA3D.Animation.SCALE: var v = frame.toVector(); + this.object3d.scale.set( v.x, v.y, v.z ); break; } } -} +}; // // Camera Animator @@ -948,7 +1042,7 @@ THREE.SEA3D.CameraAnimator = function( object3d, animationSet ) { THREE.SEA3D.Object3DAnimator.call( this, object3d, animationSet ); -} +}; THREE.SEA3D.CameraAnimator.prototype = Object.create( THREE.SEA3D.Object3DAnimator.prototype ); THREE.SEA3D.CameraAnimator.prototype.constructor = THREE.SEA3D.Object3DAnimator; @@ -965,7 +1059,7 @@ THREE.SEA3D.CameraAnimator.prototype.updateAnimationFrame = function( frame, kin break; } -} +}; // // Light Animator @@ -975,7 +1069,7 @@ THREE.SEA3D.LightAnimator = function( object3d, animationSet ) { THREE.SEA3D.Object3DAnimator.call( this, object3d, animationSet ); -} +}; THREE.SEA3D.LightAnimator.prototype = Object.create( THREE.SEA3D.Object3DAnimator.prototype ); THREE.SEA3D.LightAnimator.prototype.constructor = THREE.SEA3D.Object3DAnimator; @@ -996,7 +1090,7 @@ THREE.SEA3D.LightAnimator.prototype.updateAnimationFrame = function( frame, kind break; } -} +}; // // Geometry @@ -1013,27 +1107,27 @@ THREE.SEA3D.prototype.readGeometryBuffer = function( sea ) { } - geo.setIndex( new THREE.BufferAttribute( new Uint16Array( sea.indexes ), 1 ) ); - geo.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( sea.vertex ), 3 ) ); + geo.setIndex( new THREE.BufferAttribute( sea.indexes, 1 ) ); + geo.addAttribute( 'position', new THREE.BufferAttribute( sea.vertex, 3 ) ); if ( sea.uv ) { - geo.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( sea.uv[ 0 ] ), 2 ) ); - if ( sea.uv.length > 1 ) geo.addAttribute( 'uv2', new THREE.BufferAttribute( new Float32Array( sea.uv[ 1 ] ), 2 ) ); + geo.addAttribute( 'uv', new THREE.BufferAttribute( sea.uv[ 0 ], 2 ) ); + if ( sea.uv.length > 1 ) geo.addAttribute( 'uv2', new THREE.BufferAttribute( sea.uv[ 1 ], 2 ) ); } - if ( sea.normal ) geo.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( sea.normal ), 3 ) ); + if ( sea.normal ) geo.addAttribute( 'normal', new THREE.BufferAttribute( sea.normal, 3 ) ); else geo.computeVertexNormals(); - if ( sea.tangent4 ) geo.addAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( sea.tangent4 ), 4 ) ); + if ( sea.tangent4 ) geo.addAttribute( 'tangent', new THREE.BufferAttribute( sea.tangent4, 4 ) ); - if ( sea.color ) geo.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( sea.color ), 4 ) ); + if ( sea.color ) geo.addAttribute( 'color', new THREE.BufferAttribute( sea.color[ 0 ], sea.numColor ) ); if ( sea.joint ) { - geo.addAttribute( 'skinIndex', new THREE.Float32Attribute( new Float32Array( sea.joint ), 4 ) ); - geo.addAttribute( 'skinWeight', new THREE.Float32Attribute( new Float32Array( sea.weight ), 4 ) ); + geo.addAttribute( 'skinIndex', new THREE.Float32Attribute( sea.joint, 4 ) ); + geo.addAttribute( 'skinWeight', new THREE.Float32Attribute( sea.weight, 4 ) ); } @@ -1046,9 +1140,10 @@ THREE.SEA3D.prototype.readGeometryBuffer = function( sea ) { geo.name = sea.name; - sea.tag = geo; + this.domain.geometries = this.geometries = this.geometries || []; + this.geometries.push( this.objects[ "geo/" + sea.name ] = sea.tag = geo ); -} +}; // // Dummy @@ -1056,13 +1151,10 @@ THREE.SEA3D.prototype.readGeometryBuffer = function( sea ) { THREE.SEA3D.prototype.readDummy = function( sea ) { - var geo = new THREE.BoxGeometry( sea.width, sea.height, sea.depth, 1, 1, 1 ); - var mat = new THREE.MeshBasicMaterial( { wireframe: true, color: THREE.SEA3D.HELPER_COLOR } ); - - var dummy = new THREE.Mesh( geo, mat ); + var dummy = new THREE.SEA3D.Dummy( sea.width, sea.height, sea.depth ); dummy.name = sea.name; - this.dummys = this.dummys || []; + this.domain.dummys = this.dummys = this.dummys || []; this.dummys.push( this.objects[ "dmy/" + sea.name ] = sea.tag = dummy ); this.addSceneObject( sea ); @@ -1070,7 +1162,7 @@ THREE.SEA3D.prototype.readDummy = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Line @@ -1096,7 +1188,7 @@ THREE.SEA3D.prototype.readLine = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Container3D @@ -1106,7 +1198,7 @@ THREE.SEA3D.prototype.readContainer3D = function( sea ) { var container = new THREE.SEA3D.Object3D(); - this.containers = this.containers || []; + this.domain.containers = this.containers = this.containers || []; this.containers.push( this.objects[ "c3d/" + sea.name ] = sea.tag = container ); this.addSceneObject( sea ); @@ -1114,7 +1206,7 @@ THREE.SEA3D.prototype.readContainer3D = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Mesh2D | Sprite @@ -1124,11 +1216,9 @@ THREE.SEA3D.prototype.readMesh2D = function( sea ) { var material; - if ( sea.material ) - { + if ( sea.material ) { - if ( ! sea.material.tag.sprite ) - { + if ( ! sea.material.tag.sprite ) { material = sea.material.tag.sprite = new THREE.SpriteMaterial(); @@ -1147,7 +1237,7 @@ THREE.SEA3D.prototype.readMesh2D = function( sea ) { var sprite = new THREE.Sprite( material ); sprite.name = sea.name; - this.sprites = this.sprites || []; + this.domain.sprites = this.sprites = this.sprites || []; this.sprites.push( this.objects[ "m2d/" + sea.name ] = sea.tag = sprite ); this.addSceneObject( sea ); @@ -1155,7 +1245,7 @@ THREE.SEA3D.prototype.readMesh2D = function( sea ) { sprite.scale.set( sea.width, sea.height, 1 ); -} +}; // // Mesh @@ -1170,15 +1260,16 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { var mod = sea.modifiers[ i ]; - switch ( mod.type ) - { + switch ( mod.type ) { case SEA3D.SkeletonLocal.prototype.type: skeleton = mod; + geo.bones = skeleton.tag; break; case SEA3D.Morph.prototype.type: morpher = mod; + geo.morphAttributes = morpher.tag.attribs; geo.morphTargets = morpher.tag.targets; break; @@ -1190,15 +1281,16 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { var anm = sea.animations[ i ]; - switch ( anm.tag.type ) - { + switch ( anm.tag.type ) { case SEA3D.SkeletonAnimation.prototype.type: skeletonAnimation = anm.tag; + geo.animations = this.getSkeletonAnimation( skeletonAnimation, skeleton ); break; case SEA3D.VertexAnimation.prototype.type: vertexAnimation = anm.tag; + geo.morphAttributes = vertexAnimation.tag.attribs; geo.morphTargets = vertexAnimation.tag.targets; geo.animations = vertexAnimation.tag.animations; @@ -1221,6 +1313,7 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { for ( i = 0; i < sea.material.length; i ++ ) { mats[ i ] = sea.material[ i ].tag; + mats[ i ].skinning = skeleton != undefined; mats[ i ].morphTargets = uMorph; mats[ i ].morphNormals = uMorphNormal; @@ -1233,6 +1326,7 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { } else { mat = sea.material[ 0 ].tag; + mat.skinning = skeleton != undefined; mat.morphTargets = uMorph; mat.morphNormals = uMorphNormal; @@ -1250,18 +1344,24 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { mesh.setAnimations( geo.animations ); - if ( this.config.autoPlay ) + if ( this.config.autoPlay ) { + mesh.play( mesh.animations[ 0 ].name ); + } + } } else if ( vertexAnimation ) { mesh = new THREE.SEA3D.VertexAnimationMesh( geo, mat, vertexAnimation.frameRate ); - if ( this.config.autoPlay ) + if ( this.config.autoPlay ) { + mesh.play( mesh.animations[ 0 ].name ); + } + } else { mesh = new THREE.SEA3D.Mesh( geo, mat ); @@ -1273,7 +1373,7 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { mesh.castShadow = sea.castShadows; mesh.receiveShadow = sea.material ? sea.material[ 0 ].receiveShadows : true; - this.meshes = this.meshes || []; + this.domain.meshes = this.meshes = this.meshes || []; this.meshes.push( this.objects[ "m3d/" + sea.name ] = sea.tag = mesh ); this.addSceneObject( sea ); @@ -1281,7 +1381,7 @@ THREE.SEA3D.prototype.readMesh = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Sound Point @@ -1292,7 +1392,12 @@ THREE.SEA3D.prototype.readSoundPoint = function( sea ) { if ( ! this.audioListener ) { this.audioListener = new THREE.AudioListener(); - this.container.add( this.audioListener ); + + if ( this.config.container ) { + + this.config.container.add( this.audioListener ); + + } } @@ -1307,7 +1412,7 @@ THREE.SEA3D.prototype.readSoundPoint = function( sea ) { sound3d.name = sea.name; - this.sounds3d = this.sounds3d || []; + this.domain.sounds3d = this.sounds3d = this.sounds3d || []; this.sounds3d.push( this.objects[ "sn3d/" + sea.name ] = sea.tag = sound3d ); this.addSceneObject( sea ); @@ -1315,7 +1420,7 @@ THREE.SEA3D.prototype.readSoundPoint = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Cube Render @@ -1323,10 +1428,10 @@ THREE.SEA3D.prototype.readSoundPoint = function( sea ) { THREE.SEA3D.prototype.readCubeRender = function( sea ) { - var cube = new THREE.CubeCamera( 0.1, 5000, THREE.SEA3D.TEXTURE_SIZE ); + var cube = new THREE.CubeCamera( 0.1, 5000, THREE.SEA3D.RTT_SIZE ); cube.renderTarget.cubeCamera = cube; - this.cubeRenderers = this.cubeRenderers || []; + this.domain.cubeRenderers = this.cubeRenderers = this.cubeRenderers || []; this.cubeRenderers.push( this.objects[ "rttc/" + sea.name ] = sea.tag = cube.renderTarget ); this.addSceneObject( sea ); @@ -1334,7 +1439,7 @@ THREE.SEA3D.prototype.readCubeRender = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator ); -} +}; // // Images (WDP, JPEG, PNG and GIF) @@ -1351,8 +1456,7 @@ THREE.SEA3D.prototype.readImage = function( sea ) { image.onload = function () { if ( ! scope.isPowerOfTwo( image.width ) || - ! scope.isPowerOfTwo( image.height ) ) - { + ! scope.isPowerOfTwo( image.height ) ) { var width = scope.nearestPowerOfTwo( image.width ), height = scope.nearestPowerOfTwo( image.height ); @@ -1377,10 +1481,10 @@ THREE.SEA3D.prototype.readImage = function( sea ) { image.src = this.bufferToTexture( sea.data.buffer ); - this.textures = this.textures || []; + this.domain.textures = this.textures = this.textures || []; this.textures.push( this.objects[ "tex/" + sea.name ] = sea.tag = texture ); -} +}; // // Cube Map @@ -1393,6 +1497,7 @@ THREE.SEA3D.prototype.readCubeMap = function( sea ) { // xyz(- / +) to xyz(+ / -) sequence var faces = []; + faces[ 0 ] = sea.faces[ 1 ]; faces[ 1 ] = sea.faces[ 0 ]; faces[ 2 ] = sea.faces[ 3 ]; @@ -1409,23 +1514,27 @@ THREE.SEA3D.prototype.readCubeMap = function( sea ) { for ( var i = 0, il = faces.length; i < il; ++ i ) { var cubeImage = new Image(); + images[ i ] = cubeImage; cubeImage.onload = function () { - if ( ++ images.loadedCount == 6 ) + if ( ++ images.loadedCount == 6 ) { + texture.needsUpdate = true; + } + } cubeImage.src = this.bufferToTexture( faces[ i ].buffer ); } - this.cubmaps = this.cubmaps || []; - this.cubmaps.push( this.objects[ "cmap/" + sea.name ] = sea.tag = texture ); + this.domain.cubemaps = this.cubemaps = this.cubemaps || []; + this.cubemaps.push( this.objects[ "cmap/" + sea.name ] = sea.tag = texture ); -} +}; // // Sound (MP3, OGG) @@ -1435,10 +1544,10 @@ THREE.SEA3D.prototype.readSound = function( sea ) { var sound = this.bufferToSound( sea.data.buffer ); - this.sounds = this.sounds || []; + this.domain.sounds = this.sounds = this.sounds || []; this.sounds.push( this.objects[ "snd/" + sea.name ] = sea.tag = sound ); -} +}; // // Texture URL @@ -1452,87 +1561,198 @@ THREE.SEA3D.prototype.readTextureURL = function( sea ) { texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.flipY = false; - this.textures = this.textures || []; + this.domain.textures = this.textures = this.textures || []; this.textures.push( this.objects[ "tex/" + sea.name ] = sea.tag = texture ); -} +}; + +// +// Java Script +// + +THREE.SEA3D.SCRIPT = new SEA3D.ScriptManager(); + +THREE.SEA3D.Domain = function( id, objects, container, extensions ) { + + SEA3D.Domain.call( this, id ); + + this.objects = objects; + this.container = container; + this.extensions = extensions || []; + +}; + +THREE.SEA3D.Domain.prototype = Object.create( SEA3D.Domain.prototype ); +THREE.SEA3D.Domain.prototype.constructor = THREE.SEA3D.Domain; + +THREE.SEA3D.Domain.prototype.disposeExtensions = function() { + + extensions = extensions.concat(); + + var i = list.length; + + while ( i -- ) list[ i ].dispose(); + +}; + +THREE.SEA3D.Domain.prototype.disposeList = function( list ) { + + if ( ! list || ! list.length ) return; + + list = list.concat(); + + var i = list.length; + while ( i -- ) list[ i ].dispose(); + +}; + +THREE.SEA3D.Domain.prototype.dispose = function() { + + SEA3D.Domain.prototype.dispose.call( this ); + + while ( this.container.children.length ) { + + this.container.remove( this.container.children[ 0 ] ); + + } + + var i = this.extensions.length; + while ( i -- ) this.extensions[ i ].dispose.call( this ); + + this.disposeList( this.materials ); + this.disposeList( this.dummys ); + +}; + +SEA3D.Domain.prototype.getMesh = THREE.SEA3D.prototype.getMesh; +SEA3D.Domain.prototype.getDummy = THREE.SEA3D.prototype.getDummy; +SEA3D.Domain.prototype.getLine = THREE.SEA3D.prototype.getLine; +SEA3D.Domain.prototype.getSound3D = THREE.SEA3D.prototype.getSound3D; +SEA3D.Domain.prototype.getMaterial = THREE.SEA3D.prototype.getMaterial; +SEA3D.Domain.prototype.getLight = THREE.SEA3D.prototype.getLight; +SEA3D.Domain.prototype.getGLSL = THREE.SEA3D.prototype.getGLSL; +SEA3D.Domain.prototype.getCamera = THREE.SEA3D.prototype.getCamera; +SEA3D.Domain.prototype.getTexture = THREE.SEA3D.prototype.getTexture; +SEA3D.Domain.prototype.getCubeMap = THREE.SEA3D.prototype.getCubeMap; +SEA3D.Domain.prototype.getJointObject = THREE.SEA3D.prototype.getJointObject; +SEA3D.Domain.prototype.getContainer3D = THREE.SEA3D.prototype.getContainer3D; +SEA3D.Domain.prototype.getSprite = THREE.SEA3D.prototype.getSprite; +SEA3D.Domain.prototype.getProperty = THREE.SEA3D.prototype.getProperty; + +THREE.SEA3D.DomainManager = function( autoDisposeRootDomain ) { + + SEA3D.DomainManager.call( this, autoDisposeRootDomain ); + +}; + +THREE.SEA3D.DomainManager.prototype = Object.create( SEA3D.DomainManager.prototype ); +THREE.SEA3D.DomainManager.prototype.constructor = THREE.SEA3D.DomainManager; + +THREE.SEA3D.DomainManager.prototype.add = function( domain ) { + + SEA3D.DomainManager.prototype.add.call( this, domain ); + + this.textures = this.textures || domain.textures; + this.cubemaps = this.cubemaps || domain.cubemaps; + this.geometries = this.geometries || domain.geometries; + +}; + +THREE.SEA3D.DomainManager.prototype.disposeList = THREE.SEA3D.Domain.prototype.disposeList; + +THREE.SEA3D.DomainManager.prototype.dispose = function() { + + SEA3D.DomainManager.prototype.dispose.call( this ); + + this.disposeList( this.textures ); + this.disposeList( this.cubemaps ); + this.disposeList( this.geometries ); + +}; // -// JavaScript +// Runtime // -SEA3D.GLOBAL = {}; +THREE.SEA3D.prototype.runJSMList = function( target, scripts, root ) { + + for ( var i = 0; i < scripts.length; i ++ ) { -SEA3D.PRINT = function() { + var script = scripts[ i ]; - console.log.apply( console, arguments ); + if ( script.tag.type == SEA3D.JavaScriptMethod.prototype.type ) { - } -SEA3D.WATCH = function() {} + this.runJSM( target, script, root ); -SEA3D.REF = function( ns ) { + } - return eval( ns ); + } - } +}; -THREE.SEA3D.prototype.runJS = function( obj, script ) -{ +THREE.SEA3D.prototype.runJSM = function( target, script, root ) { - if ( obj.local === undefined ) obj.local = {}; + if ( target.local == undefined ) target.local = {}; - var global = - { - print : SEA3D.PRINT, - watch : SEA3D.WATCH, - sea3d : this, - scene : this.container + var include = { + print : this.domain.print, + watch : this.domain.watch, + sea3d : this.domain, + scene : this.config.container, + source : new SEA3D.Script( this.domain, root == true ) }; - try - { + Object.freeze( include.source ); + + THREE.SEA3D.SCRIPT.add( include.source ); + + try { - this.script[ script.method ] - ( - global, - SEA3D.REF, - SEA3D.GLOBAL, - obj.local, - obj, + this.script[ script.method ] ( + include, + this.domain.getReference, + this.domain.global, + target.local, + target, script.params ); } - catch ( e ) - { + catch ( e ) { console.error( 'SEA3D JavaScript: Error running method "' + script.method + '".' ); console.error( e ); } -} +}; THREE.SEA3D.prototype.readJavaScriptMethod = function( sea ) { - try - { + try { var src = '(function() {\n' + 'var $METHOD = {}\n'; var declare = - 'function($GLOBAL, $REF, global, local, $his, $PARAM) {\n' + - 'var watch = $GLOBAL["watch"],\n' + - 'sea3d = $GLOBAL["sea3d"],\n' + - 'scene = $GLOBAL["scene"],\n' + - 'print = $GLOBAL["print"];\n'; + 'function($INC, $REF, global, local, $his, $PARAM) {\n' + + 'var watch = $INC["watch"],\n' + + 'scene = $INC["scene"],\n' + + 'sea3d = $INC["sea3d"],\n' + + 'print = $INC["print"];\n'; + + declare += + 'var $SRC = $INC["source"],\n' + + 'addEvent = $SRC.addEvent.bind( $SRC ),\n' + + 'hasEvent = $SRC.hasEvent.bind( $SRC ),\n' + + 'dispatchEvent = $SRC.dispatchEvent.bind( $SRC ),\n' + + 'removeEvent = $SRC.removeEvent.bind( $SRC ),\n' + + 'dispose = $SRC.dispose.bind( $SRC );\n' for ( var name in sea.methods ) { - var method = sea.methods[ name ]; - src += '$METHOD["' + name + '"] = ' + declare + method.src + '}\n'; + src += '$METHOD["' + name + '"] = ' + declare + sea.methods[ name ].src + '}\n'; } @@ -1541,15 +1761,14 @@ THREE.SEA3D.prototype.readJavaScriptMethod = function( sea ) { this.script = eval( src )(); } - catch ( e ) - { + catch ( e ) { console.error( 'SEA3D JavaScriptMethod: Error running "' + sea.name + '".' ); console.error( e ); } -} +}; // // GLSL @@ -1557,10 +1776,10 @@ THREE.SEA3D.prototype.readJavaScriptMethod = function( sea ) { THREE.SEA3D.prototype.readGLSL = function( sea ) { - this.glsl = this.glsl || []; + this.domain.glsl = this.glsl = this.glsl || []; this.glsl.push( this.objects[ "glsl/" + sea.name ] = sea.tag = sea.src ); -} +}; // // Material @@ -1572,7 +1791,7 @@ THREE.SEA3D.prototype.blendMode = { subtract: THREE.SubtractiveBlending, multiply: THREE.MultiplyBlending, screen: THREE.AdditiveBlending -} +}; THREE.SEA3D.prototype.materialTechnique = ( function() { @@ -1661,7 +1880,8 @@ THREE.SEA3D.prototype.materialTechnique = techniques[ SEA3D.Material.LIGHT_MAP ] = function( tech, mat ) { - mat.lightMap = tech.texture.tag; + if ( tech.blendMode == "multiply" ) mat.aoMap = tech.texture.tag; + else mat.lightMap = tech.texture.tag; } @@ -1678,9 +1898,12 @@ THREE.SEA3D.prototype.readMaterial = function( sea ) { mat.side = sea.bothSides ? THREE.DoubleSide : THREE.FrontSide; mat.shading = sea.smooth ? THREE.SmoothShading : THREE.FlatShading; - if ( sea.blendMode != "normal" && this.blendMode[ sea.blendMode ] ) + if ( sea.blendMode != "normal" && this.blendMode[ sea.blendMode ] ) { + mat.blending = this.blendMode[ sea.blendMode ]; + } + if ( sea.alpha < 1 || mat.blending > THREE.NormalBlending ) { mat.opacity = sea.alpha; @@ -1692,9 +1915,12 @@ THREE.SEA3D.prototype.readMaterial = function( sea ) { var tech = sea.technique[ i ]; - if ( this.materialTechnique[ tech.kind ] ) + if ( this.materialTechnique[ tech.kind ] ) { + this.materialTechnique[ tech.kind ].call( this, tech, mat ); + } + } if ( mat.transparent ) { @@ -1703,10 +1929,10 @@ THREE.SEA3D.prototype.readMaterial = function( sea ) { } - this.materials = this.materials || []; + this.domain.materials = this.materials = this.materials || []; this.materials.push( this.objects[ "mat/" + sea.name ] = sea.tag = mat ); -} +}; // // Point Light @@ -1723,20 +1949,24 @@ THREE.SEA3D.prototype.readPointLight = function( sea ) { } - if ( sea.shadow ) + if ( sea.shadow ) { + this.setShadowMap( light, sea.shadow.opacity ); - this.lights = this.lights || []; + } + + this.domain.lights = this.lights = this.lights || []; this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light ); - this.addSceneObject( sea ); + if ( this.config.lights ) this.addSceneObject( sea ); + this.updateTransform( light, sea ); this.applyDefaultAnimation( sea, THREE.SEA3D.LightAnimator ); this.updateScene(); -} +}; // // Hemisphere Light @@ -1747,16 +1977,16 @@ THREE.SEA3D.prototype.readHemisphereLight = function( sea ) { var light = new THREE.HemisphereLight( sea.color, sea.secondColor, sea.multiplier * this.config.multiplier ); light.name = sea.name; - this.lights = this.lights || []; + this.domain.lights = this.lights = this.lights || []; this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light ); - this.addSceneObject( sea ); + if ( this.config.lights ) this.addSceneObject( sea ); this.applyDefaultAnimation( sea, THREE.SEA3D.LightAnimator ); this.updateScene(); -} +}; // // Directional Light @@ -1767,20 +1997,24 @@ THREE.SEA3D.prototype.readDirectionalLight = function( sea ) { var light = new THREE.DirectionalLight( sea.color, sea.multiplier * this.config.multiplier ); light.name = sea.name; - if ( sea.shadow ) + if ( sea.shadow ) { + this.setShadowMap( light, sea.shadow.opacity ); - this.lights = this.lights || []; + } + + this.domain.lights = this.lights = this.lights || []; this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light ); - this.addSceneObject( sea ); + if ( this.config.lights ) this.addSceneObject( sea ); + this.updateTransform( light, sea ); this.applyDefaultAnimation( sea, THREE.SEA3D.LightAnimator ); this.updateScene(); -} +}; // // Camera @@ -1788,10 +2022,10 @@ THREE.SEA3D.prototype.readDirectionalLight = function( sea ) { THREE.SEA3D.prototype.readCamera = function( sea ) { - var camera = new THREE.PerspectiveCamera( sea.fov ); + var camera = new THREE.SEA3D.Camera( sea.fov ); camera.name = sea.name; - this.cameras = this.camera || []; + this.domain.cameras = this.cameras = this.camera || []; this.cameras.push( this.objects[ "cam/" + sea.name ] = sea.tag = camera ); this.addSceneObject( sea ); @@ -1799,7 +2033,7 @@ THREE.SEA3D.prototype.readCamera = function( sea ) { this.applyDefaultAnimation( sea, THREE.SEA3D.CameraAnimator ); -} +}; // // Skeleton @@ -1814,17 +2048,17 @@ THREE.SEA3D.prototype.readSkeletonLocal = function( sea ) { var bone = sea.joint[ i ]; bones[ i ] = { - name: bone.name, - pos: [ bone.x, bone.y, bone.z ], - rotq: [ bone.qx, bone.qy, bone.qz, bone.qw ], - parent: bone.parentIndex - } + name: bone.name, + pos: [ bone.x, bone.y, bone.z ], + rotq: [ bone.qx, bone.qy, bone.qz, bone.qw ], + parent: bone.parentIndex + }; } sea.tag = bones; -} +}; // // Joint Object @@ -1835,10 +2069,10 @@ THREE.SEA3D.prototype.readJointObject = function( sea ) { var mesh = sea.target.tag, bone = mesh.skeleton.bones[ sea.joint ]; - this.joints = this.joints || []; + this.domain.joints = this.joints = this.joints || []; this.joints.push( this.objects[ "jnt/" + sea.name ] = sea.tag = bone ); -} +}; // // Skeleton Animation @@ -1867,27 +2101,28 @@ THREE.SEA3D.prototype.getSkeletonAnimation = function( sea, skl ) { JIT: 0, length: delta * ( seq.count - 1 ), hierarchy: [] - } + }; - var len = sea.pose[ 0 ].length; + var numJoints = sea.numJoints, + raw = sea.raw; - for ( var j = 0; j < len; j ++ ) { + for ( var j = 0; j < numJoints; j ++ ) { var bone = skl.joint[ j ], node = { parent: bone.parentIndex, keys: [] }, keys = node.keys, time = 0; - for ( var t = start; t < end; t ++ ) { + for ( var frame = start; frame < end; frame ++ ) { - var joint = sea.pose[ t ][ j ]; + var idx = ( frame * numJoints * 7 ) + ( j * 7 ); keys.push( { - time: time, - pos: [ joint.x, joint.y, joint.z ], - rot: [ joint.qx, joint.qy, joint.qz, joint.qw ], - scl: scale - } ); + time: time, + pos: [ raw[ idx ], raw[ idx + 1 ], raw[ idx + 2 ] ], + rot: [ raw[ idx + 3 ], raw[ idx + 4 ], raw[ idx + 5 ], raw[ idx + 6 ] ], + scl: scale + } ); time += delta; @@ -1903,7 +2138,7 @@ THREE.SEA3D.prototype.getSkeletonAnimation = function( sea, skl ) { return sea.tag = animations; -} +}; // // Morpher @@ -1936,9 +2171,9 @@ THREE.SEA3D.prototype.readMorpher = function( sea ) { sea.tag = { attribs : attribs, targets : targets - }; + } -} +}; // // Vertex Animation @@ -1989,7 +2224,31 @@ THREE.SEA3D.prototype.readVertexAnimation = function( sea ) { frameRate : sea.frameRate }; -} +}; + +// +// Actions +// + +THREE.SEA3D.prototype.readActions = function( sea ) { + + for ( var i = 0; i < sea.actions.length; i ++ ) { + + var act = sea.actions[ i ]; + + switch ( act.kind ) { + + case SEA3D.Actions.SCRIPTS: + + this.runJSMList( this.domain, act.scripts, true ); + + break; + + } + + } + +}; // // Events @@ -2000,8 +2259,10 @@ THREE.SEA3D.Event = { DOWNLOAD_PROGRESS: "sea3d_download", COMPLETE: "sea3d_complete", OBJECT_COMPLETE: "sea3d_object", + PARSE_PROGRESS: "parse_progress", + PARSE_COMPLETE: "parse_complete", ERROR: "sea3d_error" -} +}; THREE.SEA3D.prototype.onProgress = undefined; @@ -2010,7 +2271,7 @@ THREE.SEA3D.prototype.onComplete = function( args ) { args.file = this.scope; args.type = THREE.SEA3D.Event.COMPLETE; args.file.dispatchEvent( args ); -} +}; THREE.SEA3D.prototype.onLoadProgress = function( args ) { @@ -2018,7 +2279,7 @@ THREE.SEA3D.prototype.onLoadProgress = function( args ) { args.file.dispatchEvent( args ); if ( args.file.onProgress ) args.file.onProgress( args ); -} +}; THREE.SEA3D.prototype.onDownloadProgress = function( args ) { @@ -2026,58 +2287,142 @@ THREE.SEA3D.prototype.onDownloadProgress = function( args ) { args.file.dispatchEvent( args ); if ( args.file.onProgress ) args.file.onProgress( args ); -} +}; THREE.SEA3D.prototype.onCompleteObject = function( args ) { args.file = this.scope; args.type = THREE.SEA3D.Event.OBJECT_COMPLETE; args.file.dispatchEvent( args ); -} +}; + +THREE.SEA3D.prototype.onParseProgress = function( args ) { + + args.file = this.scope; args.type = THREE.SEA3D.Event.PARSE_PROGRESS; + args.file.dispatchEvent( args ); + +}; + +THREE.SEA3D.prototype.onParseComplete = function( args ) { + + args.file = this.scope; args.type = THREE.SEA3D.Event.PARSE_COMPLETE; + args.file.dispatchEvent( args ); + +}; THREE.SEA3D.prototype.onError = function( args ) { args.file = this.scope; args.type = THREE.SEA3D.Event.ERROR; args.file.dispatchEvent( args ); -} +}; // // Loader // +THREE.SEA3D.prototype.newDomain = function() { + + this.domain = new THREE.SEA3D.Domain( + this.config.id, + this.objects = {}, + this.config.container, + THREE.SEA3D.EXTENSIONS_DOMAIN + ); + +} + +THREE.SEA3D.prototype.parse = function( onParseComplete, onParseProgress ) { + + delete this.cameras; + delete this.containers; + delete this.lights; + delete this.joints; + delete this.meshes; + delete this.materials; + delete this.animationSets; + delete this.sprites; + delete this.sounds3d; + delete this.cubeRenderers; + delete this.sounds; + delete this.glsl; + delete this.dummy; + + delete this.domain; + + this.newDomain(); + + this.file.onParseComplete = ( function( e ) { + + if ( this.config.manager ) this.config.manager.add( this.domain ); + + ( onParseComplete || this.onParseComplete ).call( this.file, e ); + + } ).bind( this ); + + this.file.onParseProgress = onParseProgress || this.onParseProgress; + + // EXTENSIONS + + for ( var i = 0; i < THREE.SEA3D.EXTENSIONS_PARSE.length; i ++ ) { + + THREE.SEA3D.EXTENSIONS_PARSE[ i ].call( this ); + + } + + this.file.parse(); + + return this; + +}; + THREE.SEA3D.prototype.load = function( url ) { this.loadBytes(); this.file.load( url ); -} +}; THREE.SEA3D.prototype.onHead = function( args ) { if ( args.sign != 'TJS' ) { - throw "Sign '" + args.sign + "' not supported! Use SEA3D Studio to export." + throw "Sign '" + args.sign + "' not supported! Use SEA3D Studio to export."; } -} +}; THREE.SEA3D.EXTENSIONS = []; +THREE.SEA3D.EXTENSIONS_PARSE = []; +THREE.SEA3D.EXTENSIONS_DOMAIN = []; THREE.SEA3D.prototype.loadBytes = function( data ) { this.file = new SEA3D.File(); this.file.scope = this; - this.file.onComplete = this.onComplete; + this.file.streaming = this.config.streaming; + this.file.timeLimit = this.config.timeLimit; this.file.onProgress = this.onLoadProgress; this.file.onCompleteObject = this.onCompleteObject; this.file.onDownloadProgress = this.onDownloadProgress; + this.file.onParseProgress = this.onParseProgress; + this.file.onParseComplete = this.onParseComplete; this.file.onError = this.onError; this.file.onHead = this.onHead; + this.file.onComplete = ( function( e ) { + + if ( this.config.manager ) this.config.manager.add( this.domain ); + + this.onComplete.call( this.file, e ); + + } ).bind( this ); + // SEA3D + this.newDomain(); + this.file.typeRead[ SEA3D.Geometry.prototype.type ] = this.file.typeRead[ SEA3D.GeometryDelta.prototype.type ] = this.readGeometryBuffer; this.file.typeRead[ SEA3D.Mesh.prototype.type ] = this.readMesh; @@ -2086,9 +2431,6 @@ THREE.SEA3D.prototype.loadBytes = function( data ) { this.file.typeRead[ SEA3D.Dummy.prototype.type ] = this.readDummy; this.file.typeRead[ SEA3D.Line.prototype.type ] = this.readLine; this.file.typeRead[ SEA3D.Material.prototype.type ] = this.readMaterial; - this.file.typeRead[ SEA3D.PointLight.prototype.type ] = this.readPointLight; - this.file.typeRead[ SEA3D.DirectionalLight.prototype.type ] = this.readDirectionalLight; - this.file.typeRead[ SEA3D.HemisphereLight.prototype.type ] = this.readHemisphereLight; this.file.typeRead[ SEA3D.Camera.prototype.type ] = this.readCamera; this.file.typeRead[ SEA3D.SkeletonLocal.prototype.type ] = this.readSkeletonLocal; this.file.typeRead[ SEA3D.JointObject.prototype.type ] = this.readJointObject; @@ -2099,6 +2441,10 @@ THREE.SEA3D.prototype.loadBytes = function( data ) { this.file.typeRead[ SEA3D.TextureURL.prototype.type ] = this.readTextureURL; this.file.typeRead[ SEA3D.Morph.prototype.type ] = this.readMorpher; this.file.typeRead[ SEA3D.VertexAnimation.prototype.type ] = this.readVertexAnimation; + this.file.typeRead[ SEA3D.PointLight.prototype.type ] = this.readPointLight; + this.file.typeRead[ SEA3D.DirectionalLight.prototype.type ] = this.readDirectionalLight; + this.file.typeRead[ SEA3D.HemisphereLight.prototype.type ] = this.readHemisphereLight; + this.file.typeRead[ SEA3D.Actions.prototype.type ] = this.readActions; // UNIVERSAL @@ -2112,13 +2458,12 @@ THREE.SEA3D.prototype.loadBytes = function( data ) { // EXTENSIONS - for ( var i = 0; i < THREE.SEA3D.EXTENSIONS.length; i ++ ) - { + for ( var i = 0; i < THREE.SEA3D.EXTENSIONS.length; i ++ ) { - THREE.SEA3D.EXTENSIONS[ i ](this); + THREE.SEA3D.EXTENSIONS[ i ].call( this ); } this.file.read( data ); -} +};