2
0
Эх сурвалжийг харах

Merge pull request #16834 from sunag/dev-sea3d-modules

sea3d modules
Mr.doob 6 жил өмнө
parent
commit
1f3bfcf2f2

+ 212 - 0
examples/jsm/loaders/sea3d/SEA3DDraco.js

@@ -0,0 +1,212 @@
+/**
+ * 	SEA3D - Google Draco
+ * 	@author Sunag / http://www.sunag.com.br/
+ */
+
+import { SEA3D } from "./SEA3DLoader.js";
+
+//
+//	Lossy Compression
+//
+
+function GeometryDraco( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var attrib = data.readUShort(),
+		i;
+
+	this.isBig = ( attrib & 1 ) !== 0;
+
+	data.readVInt = this.isBig ? data.readUInt : data.readUShort;
+
+	this.groups = [];
+
+	if ( attrib & 32 ) {
+
+		this.uv = [];
+		this.uv.length = data.readUByte();
+
+	}
+
+	if ( attrib & 1024 ) {
+
+		var numGroups = data.readUByte(),
+			groupOffset = 0;
+
+		for ( i = 0; i < numGroups; i ++ )		{
+
+			var groupLength = data.readVInt() * 3;
+
+			this.groups.push( {
+				start: groupOffset,
+				count: groupLength,
+			} );
+
+			groupOffset += groupLength;
+
+		}
+
+	}
+
+	var module = GeometryDraco.getModule(),
+		dracoData = new Int8Array( data.concat( data.position, data.bytesAvailable ).buffer );
+
+	var decoder = new module.Decoder();
+
+	var buffer = new module.DecoderBuffer();
+	buffer.Init( dracoData, dracoData.length );
+	
+	var mesh = new module.Mesh();
+
+	var decodingStatus = decoder.DecodeBufferToMesh( buffer, mesh );
+
+	if ( ! decodingStatus.ok() ) {
+
+		data.position += 5; // jump "DRACO" magic string
+		var version = data.readUByte() + '.' + data.readUByte(); // draco version
+
+		console.error( "SEA3D Draco", version, "decoding failed:", decodingStatus.error_msg(), "You may need update 'draco_decoder.js'." );
+
+		// use an empty geometry
+		this.vertex = new Float32Array();
+
+		return;
+
+	}
+
+	var index = 0;
+
+	this.vertex = this.readFloat32Array( module, decoder, mesh, index ++ );
+
+	if ( attrib & 4 ) this.normal = this.readFloat32Array( module, decoder, mesh, index ++ );
+
+	if ( attrib & 32 ) {
+
+		for ( i = 0; i < this.uv.length; i ++ ) {
+
+			this.uv[ i ] = this.readFloat32Array( module, decoder, mesh, index ++ );
+
+		}
+
+	}
+
+	if ( attrib & 64 ) {
+
+		this.jointPerVertex = decoder.GetAttribute( mesh, index ).num_components();
+
+		this.joint = this.readUint16Array( module, decoder, mesh, index ++ );
+		this.weight = this.readFloat32Array( module, decoder, mesh, index ++ );
+
+	}
+
+	this.indexes = this.readIndices( module, decoder, mesh );
+
+	module.destroy( mesh );
+	module.destroy( buffer );
+	module.destroy( decoder );
+
+};
+
+GeometryDraco.getModule = function () {
+
+	if ( ! this.module ) {
+
+		this.module = DracoDecoderModule();
+
+	}
+
+	return this.module;
+
+};
+
+GeometryDraco.prototype.type = "sdrc";
+
+GeometryDraco.prototype.readIndices = function ( module, decoder, mesh ) {
+
+	var numFaces = mesh.num_faces(),
+		numIndices = numFaces * 3,
+		indices = new ( numIndices >= 0xFFFE ? Uint32Array : Uint16Array )( numIndices );
+
+	var ia = new module.DracoInt32Array();
+
+	for ( var i = 0; i < numFaces; ++ i ) {
+
+		  decoder.GetFaceFromMesh( mesh, i, ia );
+
+		  var index = i * 3;
+
+		  indices[ index ] = ia.GetValue( 0 );
+		  indices[ index + 1 ] = ia.GetValue( 1 );
+		  indices[ index + 2 ] = ia.GetValue( 2 );
+
+	}
+
+	module.destroy( ia );
+
+	return indices;
+
+};
+
+GeometryDraco.prototype.readFloat32Array = function ( module, decoder, mesh, attrib ) {
+
+	var attribute = decoder.GetAttribute( mesh, attrib ),
+		numPoints = mesh.num_points();
+
+	var dracoArray = new module.DracoFloat32Array();
+	decoder.GetAttributeFloatForAllPoints( mesh, attribute, dracoArray );
+
+	var size = numPoints * attribute.num_components(),
+		output = new Float32Array( size );
+
+	for ( var i = 0; i < size; ++ i ) {
+
+		output[ i ] = dracoArray.GetValue( i );
+
+	}
+
+	module.destroy( dracoArray );
+
+	return output;
+
+};
+
+GeometryDraco.prototype.readUint16Array = function ( module, decoder, mesh, attrib, type ) {
+
+	var attribute = decoder.GetAttribute( mesh, attrib ),
+		numPoints = mesh.num_points();
+
+	var dracoArray = new module.DracoUInt16Array();
+	decoder.GetAttributeUInt16ForAllPoints( mesh, attribute, dracoArray );
+
+	var size = numPoints * attribute.num_components(),
+		output = new Uint16Array( size );
+
+	for ( var i = 0; i < size; ++ i ) {
+
+		output[ i ] = dracoArray.GetValue( i );
+
+	}
+
+	module.destroy( dracoArray );
+
+	return output;
+
+};
+
+//
+//	Extension
+//
+
+SEA3D.EXTENSIONS_LOADER.push( {
+
+	setTypeRead: function () {
+
+		this.file.addClass( GeometryDraco, true );
+		this.file.typeRead[ GeometryDraco.prototype.type ] = this.readGeometryBuffer;
+
+	}
+
+} );

+ 805 - 0
examples/jsm/loaders/sea3d/SEA3DLZMA.js

@@ -0,0 +1,805 @@
+/*
+Copyright (c) 2011 Juan Mellado
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+References:
+- "LZMA SDK" by Igor Pavlov
+  http://www.7-zip.org/sdk.html
+*/
+
+/**
+ * 	SEA3D LZMA
+ * 	@author Sunag / http://www.sunag.com.br/
+ */
+
+import { SEA3DSDK } from "./SEA3DSDK.js";
+
+var LZMA = {};
+
+LZMA.OutWindow = function () {
+
+	this._windowSize = 0;
+
+};
+
+LZMA.OutWindow.prototype.create = function ( windowSize ) {
+
+	if ( ( ! this._buffer ) || ( this._windowSize !== windowSize ) ) {
+
+		this._buffer = [];
+
+	}
+	this._windowSize = windowSize;
+	this._pos = 0;
+	this._streamPos = 0;
+
+};
+
+LZMA.OutWindow.prototype.flush = function () {
+
+	var size = this._pos - this._streamPos;
+	if ( size !== 0 ) {
+
+		while ( size -- ) {
+
+			this._stream.writeByte( this._buffer[ this._streamPos ++ ] );
+
+		}
+		if ( this._pos >= this._windowSize ) {
+
+			this._pos = 0;
+
+		}
+		this._streamPos = this._pos;
+
+	}
+
+};
+
+LZMA.OutWindow.prototype.releaseStream = function () {
+
+	this.flush();
+	this._stream = null;
+
+};
+
+LZMA.OutWindow.prototype.setStream = function ( stream ) {
+
+	this.releaseStream();
+	this._stream = stream;
+
+};
+
+LZMA.OutWindow.prototype.init = function ( solid ) {
+
+	if ( ! solid ) {
+
+		this._streamPos = 0;
+		this._pos = 0;
+
+	}
+
+};
+
+LZMA.OutWindow.prototype.copyBlock = function ( distance, len ) {
+
+	var pos = this._pos - distance - 1;
+	if ( pos < 0 ) {
+
+		pos += this._windowSize;
+
+	}
+	while ( len -- ) {
+
+		if ( pos >= this._windowSize ) {
+
+			pos = 0;
+
+		}
+		this._buffer[ this._pos ++ ] = this._buffer[ pos ++ ];
+		if ( this._pos >= this._windowSize ) {
+
+			this.flush();
+
+		}
+
+	}
+
+};
+
+LZMA.OutWindow.prototype.putByte = function ( b ) {
+
+	this._buffer[ this._pos ++ ] = b;
+	if ( this._pos >= this._windowSize ) {
+
+		this.flush();
+
+	}
+
+};
+
+LZMA.OutWindow.prototype.getByte = function ( distance ) {
+
+	var pos = this._pos - distance - 1;
+	if ( pos < 0 ) {
+
+		pos += this._windowSize;
+
+	}
+	return this._buffer[ pos ];
+
+};
+
+LZMA.RangeDecoder = function () {
+};
+
+LZMA.RangeDecoder.prototype.setStream = function ( stream ) {
+
+	this._stream = stream;
+
+};
+
+LZMA.RangeDecoder.prototype.releaseStream = function () {
+
+	this._stream = null;
+
+};
+
+LZMA.RangeDecoder.prototype.init = function () {
+
+	var i = 5;
+
+	this._code = 0;
+	this._range = - 1;
+
+	while ( i -- ) {
+
+		this._code = ( this._code << 8 ) | this._stream.readByte();
+
+	}
+
+};
+
+LZMA.RangeDecoder.prototype.decodeDirectBits = function ( numTotalBits ) {
+
+	var result = 0, i = numTotalBits, t;
+
+	while ( i -- ) {
+
+		this._range >>>= 1;
+		t = ( this._code - this._range ) >>> 31;
+		this._code -= this._range & ( t - 1 );
+		result = ( result << 1 ) | ( 1 - t );
+
+		if ( ( this._range & 0xff000000 ) === 0 ) {
+
+			this._code = ( this._code << 8 ) | this._stream.readByte();
+			this._range <<= 8;
+
+		}
+
+	}
+
+	return result;
+
+};
+
+LZMA.RangeDecoder.prototype.decodeBit = function ( probs, index ) {
+
+	var prob = probs[ index ],
+		newBound = ( this._range >>> 11 ) * prob;
+
+	if ( ( this._code ^ 0x80000000 ) < ( newBound ^ 0x80000000 ) ) {
+
+		this._range = newBound;
+		probs[ index ] += ( 2048 - prob ) >>> 5;
+		if ( ( this._range & 0xff000000 ) === 0 ) {
+
+			this._code = ( this._code << 8 ) | this._stream.readByte();
+			this._range <<= 8;
+
+		}
+		return 0;
+
+	}
+
+	this._range -= newBound;
+	this._code -= newBound;
+	probs[ index ] -= prob >>> 5;
+	if ( ( this._range & 0xff000000 ) === 0 ) {
+
+		this._code = ( this._code << 8 ) | this._stream.readByte();
+		this._range <<= 8;
+
+	}
+	return 1;
+
+};
+
+LZMA.initBitModels = function ( probs, len ) {
+
+	while ( len -- ) {
+
+		probs[ len ] = 1024;
+
+	}
+
+};
+
+LZMA.BitTreeDecoder = function ( numBitLevels ) {
+
+	this._models = [];
+	this._numBitLevels = numBitLevels;
+
+};
+
+LZMA.BitTreeDecoder.prototype.init = function () {
+
+	LZMA.initBitModels( this._models, 1 << this._numBitLevels );
+
+};
+
+LZMA.BitTreeDecoder.prototype.decode = function ( rangeDecoder ) {
+
+	var m = 1, i = this._numBitLevels;
+
+	while ( i -- ) {
+
+		m = ( m << 1 ) | rangeDecoder.decodeBit( this._models, m );
+
+	}
+	return m - ( 1 << this._numBitLevels );
+
+};
+
+LZMA.BitTreeDecoder.prototype.reverseDecode = function ( rangeDecoder ) {
+
+	var m = 1, symbol = 0, i = 0, bit;
+
+	for ( ; i < this._numBitLevels; ++ i ) {
+
+		bit = rangeDecoder.decodeBit( this._models, m );
+		m = ( m << 1 ) | bit;
+		symbol |= bit << i;
+
+	}
+	return symbol;
+
+};
+
+LZMA.reverseDecode2 = function ( models, startIndex, rangeDecoder, numBitLevels ) {
+
+	var m = 1, symbol = 0, i = 0, bit;
+
+	for ( ; i < numBitLevels; ++ i ) {
+
+		bit = rangeDecoder.decodeBit( models, startIndex + m );
+		m = ( m << 1 ) | bit;
+		symbol |= bit << i;
+
+	}
+	return symbol;
+
+};
+
+LZMA.LenDecoder = function () {
+
+	this._choice = [];
+	this._lowCoder = [];
+	this._midCoder = [];
+	this._highCoder = new LZMA.BitTreeDecoder( 8 );
+	this._numPosStates = 0;
+
+};
+
+LZMA.LenDecoder.prototype.create = function ( numPosStates ) {
+
+	for ( ; this._numPosStates < numPosStates; ++ this._numPosStates ) {
+
+		this._lowCoder[ this._numPosStates ] = new LZMA.BitTreeDecoder( 3 );
+		this._midCoder[ this._numPosStates ] = new LZMA.BitTreeDecoder( 3 );
+
+	}
+
+};
+
+LZMA.LenDecoder.prototype.init = function () {
+
+	var i = this._numPosStates;
+	LZMA.initBitModels( this._choice, 2 );
+	while ( i -- ) {
+
+		this._lowCoder[ i ].init();
+		this._midCoder[ i ].init();
+
+	}
+	this._highCoder.init();
+
+};
+
+LZMA.LenDecoder.prototype.decode = function ( rangeDecoder, posState ) {
+
+	if ( rangeDecoder.decodeBit( this._choice, 0 ) === 0 ) {
+
+		return this._lowCoder[ posState ].decode( rangeDecoder );
+
+	}
+	if ( rangeDecoder.decodeBit( this._choice, 1 ) === 0 ) {
+
+		return 8 + this._midCoder[ posState ].decode( rangeDecoder );
+
+	}
+	return 16 + this._highCoder.decode( rangeDecoder );
+
+};
+
+LZMA.Decoder2 = function () {
+
+	this._decoders = [];
+
+};
+
+LZMA.Decoder2.prototype.init = function () {
+
+	LZMA.initBitModels( this._decoders, 0x300 );
+
+};
+
+LZMA.Decoder2.prototype.decodeNormal = function ( rangeDecoder ) {
+
+	var symbol = 1;
+
+	do {
+
+		symbol = ( symbol << 1 ) | rangeDecoder.decodeBit( this._decoders, symbol );
+
+	}while ( symbol < 0x100 );
+
+	return symbol & 0xff;
+
+};
+
+LZMA.Decoder2.prototype.decodeWithMatchByte = function ( rangeDecoder, matchByte ) {
+
+	var symbol = 1, matchBit, bit;
+
+	do {
+
+		matchBit = ( matchByte >> 7 ) & 1;
+		matchByte <<= 1;
+		bit = rangeDecoder.decodeBit( this._decoders, ( ( 1 + matchBit ) << 8 ) + symbol );
+		symbol = ( symbol << 1 ) | bit;
+		if ( matchBit !== bit ) {
+
+			while ( symbol < 0x100 ) {
+
+				symbol = ( symbol << 1 ) | rangeDecoder.decodeBit( this._decoders, symbol );
+
+			}
+			break;
+
+		}
+
+	}while ( symbol < 0x100 );
+
+	return symbol & 0xff;
+
+};
+
+LZMA.LiteralDecoder = function () {
+};
+
+LZMA.LiteralDecoder.prototype.create = function ( numPosBits, numPrevBits ) {
+
+	var i;
+
+	if ( this._coders
+		&& ( this._numPrevBits === numPrevBits )
+		&& ( this._numPosBits === numPosBits ) ) {
+
+		return;
+
+	}
+	this._numPosBits = numPosBits;
+	this._posMask = ( 1 << numPosBits ) - 1;
+	this._numPrevBits = numPrevBits;
+
+	this._coders = [];
+
+	i = 1 << ( this._numPrevBits + this._numPosBits );
+	while ( i -- ) {
+
+		this._coders[ i ] = new LZMA.Decoder2();
+
+	}
+
+};
+
+LZMA.LiteralDecoder.prototype.init = function () {
+
+	var i = 1 << ( this._numPrevBits + this._numPosBits );
+	while ( i -- ) {
+
+		this._coders[ i ].init();
+
+	}
+
+};
+
+LZMA.LiteralDecoder.prototype.getDecoder = function ( pos, prevByte ) {
+
+	return this._coders[ ( ( pos & this._posMask ) << this._numPrevBits )
+		+ ( ( prevByte & 0xff ) >>> ( 8 - this._numPrevBits ) ) ];
+
+};
+
+LZMA.Decoder = function () {
+
+	this._outWindow = new LZMA.OutWindow();
+	this._rangeDecoder = new LZMA.RangeDecoder();
+	this._isMatchDecoders = [];
+	this._isRepDecoders = [];
+	this._isRepG0Decoders = [];
+	this._isRepG1Decoders = [];
+	this._isRepG2Decoders = [];
+	this._isRep0LongDecoders = [];
+	this._posSlotDecoder = [];
+	this._posDecoders = [];
+	this._posAlignDecoder = new LZMA.BitTreeDecoder( 4 );
+	this._lenDecoder = new LZMA.LenDecoder();
+	this._repLenDecoder = new LZMA.LenDecoder();
+	this._literalDecoder = new LZMA.LiteralDecoder();
+	this._dictionarySize = - 1;
+	this._dictionarySizeCheck = - 1;
+
+	this._posSlotDecoder[ 0 ] = new LZMA.BitTreeDecoder( 6 );
+	this._posSlotDecoder[ 1 ] = new LZMA.BitTreeDecoder( 6 );
+	this._posSlotDecoder[ 2 ] = new LZMA.BitTreeDecoder( 6 );
+	this._posSlotDecoder[ 3 ] = new LZMA.BitTreeDecoder( 6 );
+
+};
+
+LZMA.Decoder.prototype.setDictionarySize = function ( dictionarySize ) {
+
+	if ( dictionarySize < 0 ) {
+
+		return false;
+
+	}
+	if ( this._dictionarySize !== dictionarySize ) {
+
+		this._dictionarySize = dictionarySize;
+		this._dictionarySizeCheck = Math.max( this._dictionarySize, 1 );
+		this._outWindow.create( Math.max( this._dictionarySizeCheck, 4096 ) );
+
+	}
+	return true;
+
+};
+
+LZMA.Decoder.prototype.setLcLpPb = function ( lc, lp, pb ) {
+
+	var numPosStates = 1 << pb;
+
+	if ( lc > 8 || lp > 4 || pb > 4 ) {
+
+		return false;
+
+	}
+
+	this._literalDecoder.create( lp, lc );
+
+	this._lenDecoder.create( numPosStates );
+	this._repLenDecoder.create( numPosStates );
+	this._posStateMask = numPosStates - 1;
+
+	return true;
+
+};
+
+LZMA.Decoder.prototype.init = function () {
+
+	var i = 4;
+
+	this._outWindow.init( false );
+
+	LZMA.initBitModels( this._isMatchDecoders, 192 );
+	LZMA.initBitModels( this._isRep0LongDecoders, 192 );
+	LZMA.initBitModels( this._isRepDecoders, 12 );
+	LZMA.initBitModels( this._isRepG0Decoders, 12 );
+	LZMA.initBitModels( this._isRepG1Decoders, 12 );
+	LZMA.initBitModels( this._isRepG2Decoders, 12 );
+	LZMA.initBitModels( this._posDecoders, 114 );
+
+	this._literalDecoder.init();
+
+	while ( i -- ) {
+
+		this._posSlotDecoder[ i ].init();
+
+	}
+
+	this._lenDecoder.init();
+	this._repLenDecoder.init();
+	this._posAlignDecoder.init();
+	this._rangeDecoder.init();
+
+};
+
+LZMA.Decoder.prototype.decode = function ( inStream, outStream, outSize ) {
+
+	var state = 0, rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0, nowPos64 = 0, prevByte = 0,
+		posState, decoder2, len, distance, posSlot, numDirectBits;
+
+	this._rangeDecoder.setStream( inStream );
+	this._outWindow.setStream( outStream );
+
+	this.init();
+
+	while ( outSize < 0 || nowPos64 < outSize ) {
+
+		posState = nowPos64 & this._posStateMask;
+
+		if ( this._rangeDecoder.decodeBit( this._isMatchDecoders, ( state << 4 ) + posState ) === 0 ) {
+
+			decoder2 = this._literalDecoder.getDecoder( nowPos64 ++, prevByte );
+
+			if ( state >= 7 ) {
+
+				prevByte = decoder2.decodeWithMatchByte( this._rangeDecoder, this._outWindow.getByte( rep0 ) );
+
+			} else {
+
+				prevByte = decoder2.decodeNormal( this._rangeDecoder );
+
+			}
+			this._outWindow.putByte( prevByte );
+
+			state = state < 4 ? 0 : state - ( state < 10 ? 3 : 6 );
+
+		} else {
+
+			if ( this._rangeDecoder.decodeBit( this._isRepDecoders, state ) === 1 ) {
+
+				len = 0;
+				if ( this._rangeDecoder.decodeBit( this._isRepG0Decoders, state ) === 0 ) {
+
+					if ( this._rangeDecoder.decodeBit( this._isRep0LongDecoders, ( state << 4 ) + posState ) === 0 ) {
+
+						state = state < 7 ? 9 : 11;
+						len = 1;
+
+					}
+
+				} else {
+
+					if ( this._rangeDecoder.decodeBit( this._isRepG1Decoders, state ) === 0 ) {
+
+						distance = rep1;
+
+					} else {
+
+						if ( this._rangeDecoder.decodeBit( this._isRepG2Decoders, state ) === 0 ) {
+
+							distance = rep2;
+
+						} else {
+
+							distance = rep3;
+							rep3 = rep2;
+
+						}
+						rep2 = rep1;
+
+					}
+					rep1 = rep0;
+					rep0 = distance;
+
+				}
+				if ( len === 0 ) {
+
+					len = 2 + this._repLenDecoder.decode( this._rangeDecoder, posState );
+					state = state < 7 ? 8 : 11;
+
+				}
+
+			} else {
+
+				rep3 = rep2;
+				rep2 = rep1;
+				rep1 = rep0;
+
+				len = 2 + this._lenDecoder.decode( this._rangeDecoder, posState );
+				state = state < 7 ? 7 : 10;
+
+				posSlot = this._posSlotDecoder[ len <= 5 ? len - 2 : 3 ].decode( this._rangeDecoder );
+				if ( posSlot >= 4 ) {
+
+					numDirectBits = ( posSlot >> 1 ) - 1;
+					rep0 = ( 2 | ( posSlot & 1 ) ) << numDirectBits;
+
+					if ( posSlot < 14 ) {
+
+						rep0 += LZMA.reverseDecode2( this._posDecoders,
+							rep0 - posSlot - 1, this._rangeDecoder, numDirectBits );
+
+					} else {
+
+						rep0 += this._rangeDecoder.decodeDirectBits( numDirectBits - 4 ) << 4;
+						rep0 += this._posAlignDecoder.reverseDecode( this._rangeDecoder );
+						if ( rep0 < 0 ) {
+
+							if ( rep0 === - 1 ) {
+
+								break;
+
+							}
+							return false;
+
+						}
+
+					}
+
+				} else {
+
+					rep0 = posSlot;
+
+				}
+
+			}
+
+			if ( rep0 >= nowPos64 || rep0 >= this._dictionarySizeCheck ) {
+
+				return false;
+
+			}
+
+			this._outWindow.copyBlock( rep0, len );
+			nowPos64 += len;
+			prevByte = this._outWindow.getByte( 0 );
+
+		}
+
+	}
+
+	this._outWindow.flush();
+	this._outWindow.releaseStream();
+	this._rangeDecoder.releaseStream();
+
+	return true;
+
+};
+
+LZMA.Decoder.prototype.setDecoderProperties = function ( properties ) {
+
+	var value, lc, lp, pb, dictionarySize;
+
+	if ( properties.size < 5 ) {
+
+		return false;
+
+	}
+
+	value = properties.readByte();
+	lc = value % 9;
+	value = ~~ ( value / 9 );
+	lp = value % 5;
+	pb = ~~ ( value / 5 );
+
+	if ( ! this.setLcLpPb( lc, lp, pb ) ) {
+
+		return false;
+
+	}
+
+	dictionarySize = properties.readByte();
+	dictionarySize |= properties.readByte() << 8;
+	dictionarySize |= properties.readByte() << 16;
+	dictionarySize += properties.readByte() * 16777216;
+
+	return this.setDictionarySize( dictionarySize );
+
+};
+
+LZMA.decompress = function ( properties, inStream, outStream, outSize ) {
+
+	var decoder = new LZMA.Decoder();
+
+	if ( ! decoder.setDecoderProperties( properties ) ) {
+
+		throw "Incorrect stream properties";
+
+	}
+
+	if ( ! decoder.decode( inStream, outStream, outSize ) ) {
+
+		throw "Error in data stream";
+
+	}
+
+	return true;
+
+};
+
+LZMA.decompressFile = function ( inStream, outStream ) {
+
+	var decoder = new LZMA.Decoder(), outSize;
+
+	if ( ! decoder.setDecoderProperties( inStream ) ) {
+
+		throw "Incorrect stream properties";
+
+	}
+
+	outSize = inStream.readByte();
+	outSize |= inStream.readByte() << 8;
+	outSize |= inStream.readByte() << 16;
+	outSize += inStream.readByte() * 16777216;
+
+	inStream.readByte();
+	inStream.readByte();
+	inStream.readByte();
+	inStream.readByte();
+
+	if ( ! decoder.decode( inStream, outStream, outSize ) ) {
+
+		throw "Error in data stream";
+
+	}
+
+	return true;
+
+};
+
+SEA3DSDK.File.LZMAUncompress = function ( data ) {
+
+	data = new Uint8Array( data );
+
+	var inStream = {
+		data: data,
+		position: 0,
+		readByte: function () {
+
+			return this.data[ this.position ++ ];
+
+		}
+	};
+
+	var outStream = {
+		data: [],
+		position: 0,
+		writeByte: function ( value ) {
+
+			this.data[ this.position ++ ] = value;
+
+		}
+	};
+
+	LZMA.decompressFile( inStream, outStream );
+
+	return new Uint8Array( outStream.data ).buffer;
+
+};
+
+SEA3DSDK.File.setDecompressionEngine( 2, "lzma", SEA3DSDK.File.LZMAUncompress );
+
+export { LZMA };

+ 3998 - 0
examples/jsm/loaders/sea3d/SEA3DLoader.js

@@ -0,0 +1,3998 @@
+/**
+ * 	SEA3D for Three.JS
+ * 	@author Sunag / http://www.sunag.com.br/
+ */
+
+import {
+	Matrix4,
+	Vector3,
+	Quaternion,
+	EventDispatcher,
+	AudioLoader,
+	AnimationClip,
+	AnimationMixer,
+	AudioListener,
+	InterpolateLinear,
+	VectorKeyframeTrack,
+	QuaternionKeyframeTrack,
+	LoopRepeat,
+	LoopOnce,
+	Object3D,
+	BoxGeometry,
+	Mesh,
+	MeshBasicMaterial,
+	SkinnedMesh,
+	Skeleton,
+	Bone,
+	PerspectiveCamera,
+	OrthographicCamera,
+	PointLight,
+	PositionalAudio,
+	Math,
+	BufferGeometry,
+	BufferAttribute,
+	Float32BufferAttribute,
+	LineBasicMaterial,
+	Line,
+	SpriteMaterial,
+	Sprite,
+	VertexColors,
+	Color,
+	NoColors,
+	CubeCamera,
+	Texture,
+	CubeTexture,
+	RepeatWrapping,
+	ClampToEdgeWrapping,
+	CubeReflectionMapping,
+	MixOperation,
+	CubeRefractionMapping,
+	SphericalReflectionMapping,
+	RGBFormat,
+	FileLoader,
+	TextureLoader,
+	//PMREMGenerator,
+	//HDRCubeTextureLoader,
+	UnsignedByteType,
+	//PMREMCubeUVPacker,
+	CubeTextureLoader,
+	NormalBlending,
+	MeshPhysicalMaterial,
+	MeshStandardMaterial,
+	MeshPhongMaterial,
+	AdditiveBlending,
+	SubtractiveBlending,
+	MultiplyBlending,
+	CustomBlending,
+	OneFactor,
+	OneMinusSrcColorFactor,
+	AddEquation,
+	DoubleSide,
+	FrontSide,
+	HemisphereLight,
+	AmbientLight,
+	DirectionalLight
+} from "../../../../build/three.module.js";
+
+import { SEA3DSDK } from "./SEA3DSDK.js";
+
+//
+//
+//	SEA3D
+//
+
+function SEA3D( config ) {
+
+	this.config = {
+		id: "",
+		scripts: true,
+		runScripts: true,
+		autoPlay: false,
+		dummys: true,
+		multiplier: 1,
+		bounding: true,
+		audioRolloffFactor: 10,
+		lights: true,
+		useEnvironment: true,
+		useVertexTexture: true,
+		forceStatic: false,
+		streaming: true,
+		async: true,
+		paths: {},
+		timeLimit: 10
+	};
+
+	if ( config ) this.loadConfig( config );
+
+};
+
+//
+//	Config
+//
+
+SEA3D.MTXBUF = new Matrix4();
+SEA3D.VECBUF = new Vector3();
+SEA3D.QUABUF = new Quaternion();
+
+SEA3D.BACKGROUND_COLOR = 0x333333;
+SEA3D.HELPER_COLOR = 0x9AB9E5;
+SEA3D.RTT_SIZE = 512;
+
+SEA3D.identityMatrixScale = function () {
+
+	var scl = new Vector3();
+
+	return function identityMatrixScale( matrix ) {
+
+		scl.setFromMatrixScale( matrix );
+
+		return matrix.scale( scl.set( 1 / scl.x, 1 / scl.y, 1 / scl.z ) );
+
+	};
+
+}();
+
+SEA3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+
+	constructor: SEA3D,
+
+	setShadowMap: function ( light ) {
+
+		light.shadow.mapSize.width = 2048;
+		light.shadow.mapSize.height = 1024;
+
+		light.castShadow = true;
+
+		light.shadow.camera.left = - 200;
+		light.shadow.camera.right = 200;
+		light.shadow.camera.top = 200;
+		light.shadow.camera.bottom = - 200;
+
+		light.shadow.camera.near = 1;
+		light.shadow.camera.far = 3000;
+		light.shadow.camera.fov = 45;
+
+		light.shadow.bias = - 0.001;
+
+	}
+
+} );
+
+Object.defineProperties( SEA3D.prototype, {
+
+	container: {
+
+		set: function ( val ) {
+
+			this.config.container = val;
+
+		},
+
+		get: function () {
+
+			return this.config.container;
+
+		}
+
+	},
+
+	elapsedTime: {
+
+		get: function () {
+
+			return this.file.timer.elapsedTime;
+
+		}
+
+	}
+
+} );
+
+//
+//	Domain
+//
+
+SEA3D.Domain = function ( id, objects, container ) {
+
+	this.id = id;
+	this.objects = objects;
+	this.container = container;
+
+	this.sources = [];
+	this.local = {};
+
+	this.scriptTargets = [];
+
+	this.events = new EventDispatcher();
+
+};
+
+SEA3D.Domain.global = {};
+
+SEA3D.Domain.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+
+	constructor: SEA3D.Domain,
+
+	add: function ( src ) {
+
+		this.sources.push( src );
+
+	},
+
+	remove: function ( src ) {
+
+		this.sources.splice( this.sources.indexOf( src ), 1 );
+
+	},
+
+	contains: function ( src ) {
+
+		return this.sources.indexOf( src ) != - 1;
+
+	},
+
+	addEventListener: function ( type, listener ) {
+
+		this.events.addEventListener( type, listener );
+
+	},
+
+	hasEventListener: function ( type, listener ) {
+
+		return this.events.hasEventListener( type, listener );
+
+	},
+
+	removeEventListener: function ( type, listener ) {
+
+		this.events.removeEventListener( type, listener );
+
+	},
+
+	print: function () {
+
+		console.log.apply( console, arguments );
+
+	},
+
+	watch: function () {
+
+		console.log.apply( console, 'watch:', arguments );
+
+	},
+
+	runScripts: function () {
+
+		for ( var i = 0; i < this.scriptTargets.length; i ++ ) {
+
+			this.runJSMList( this.scriptTargets[ i ] );
+
+		}
+
+	},
+
+	runJSMList: function ( target ) {
+
+		var scripts = target.scripts;
+
+		for ( var i = 0; i < scripts.length; i ++ ) {
+
+			this.runJSM( target, scripts[ i ] );
+
+		}
+
+		return scripts;
+
+	},
+
+	runJSM: function ( target, script ) {
+
+		var include = {
+			print: this.print,
+			watch: this.watch,
+			sea3d: this,
+			scene: this.container,
+			source: new SEA3D.ScriptDomain( this, target instanceof SEA3D.Domain )
+		};
+
+		Object.freeze( include.source );
+
+		SEA3D.ScriptHandler.add( include.source );
+
+		try {
+
+			this.methods[ script.method ](
+				include,
+				this.getReference,
+				SEA3D.Domain.global,
+				this.local,
+				target,
+				script.params
+			);
+
+		} catch ( e ) {
+
+			console.error( 'SEA3D JavaScript: Error running method "' + script.method + '".' );
+			console.error( e );
+
+		}
+
+	},
+
+	getReference: function ( ns ) {
+
+		return eval( ns );
+
+	},
+
+	disposeList: function ( list ) {
+
+		if ( ! list || ! list.length ) return;
+
+		list = list.concat();
+
+		var i = list.length;
+
+		while ( i -- ) {
+
+			list[ i ].dispose();
+
+		}
+
+	},
+
+	dispatchEvent: function ( event ) {
+
+		event.domain = this;
+
+		var sources = this.sources.concat(),
+			i = sources.length;
+
+		while ( i -- ) {
+
+			sources[ i ].dispatchEvent( event );
+
+		}
+
+		this.events.dispatchEvent( event );
+
+	},
+
+	dispose: function () {
+
+		this.disposeList( this.sources );
+
+		while ( this.container.children.length ) {
+
+			this.container.remove( this.container.children[ 0 ] );
+
+		}
+
+		var i = SEA3D.EXTENSIONS_DOMAIN.length;
+
+		while ( i -- ) {
+
+			var domain = SEA3D.EXTENSIONS_DOMAIN[ i ];
+
+			if ( domain.dispose ) domain.dispose.call( this );
+
+		}
+
+		this.disposeList( this.materials );
+		this.disposeList( this.dummys );
+
+		this.dispatchEvent( { type: "dispose" } );
+
+	}
+} );
+
+//
+//	Domain Manager
+//
+
+SEA3D.DomainManager = function ( autoDisposeRootDomain ) {
+
+	this.domains = [];
+	this.autoDisposeRootDomain = autoDisposeRootDomain !== undefined ? autoDisposeRootDomain : true;
+
+};
+
+Object.assign( SEA3D.DomainManager.prototype, {
+
+	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.on( "dispose", this._onDisposeDomain );
+
+		this.domains.push( domain );
+
+		this.textures = this.textures || domain.textures;
+		this.cubemaps = this.cubemaps || domain.cubemaps;
+		this.geometries = this.geometries || domain.geometries;
+
+	},
+
+	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;
+
+	},
+
+	disposeList: function ( list ) {
+
+		if ( ! list || ! list.length ) return;
+
+		list = list.concat();
+
+		var i = list.length;
+
+		while ( i -- ) {
+
+			list[ i ].dispose();
+
+		}
+
+	},
+
+	dispose: function () {
+
+		this.disposeList( this.domains );
+		this.disposeList( this.textures );
+		this.disposeList( this.cubemaps );
+		this.disposeList( this.geometries );
+
+	}
+
+} );
+
+//
+//	Script ( closure for private functions )
+//
+
+SEA3D.ScriptDomain = function ( domain, root ) {
+
+	domain = domain || new SEA3D.Domain();
+	domain.add( this );
+
+	var events = new EventDispatcher();
+
+	this.getId = function () {
+
+		return domain.id;
+
+	};
+
+	this.isRoot = function () {
+
+		return root;
+
+	};
+
+	this.addEventListener = function ( type, listener ) {
+
+		events.addEventListener( type, listener );
+
+	};
+
+	this.hasEventListener = function ( type, listener ) {
+
+		return events.hasEventListener( type, listener );
+
+	};
+
+	this.removeEventListener = 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 ( closure for private functions )
+//
+
+SEA3D.ScriptManager = function () {
+
+	this.scripts = [];
+
+	var onDisposeScript = ( function ( e ) {
+
+		this.remove( e.script );
+
+	} ).bind( this );
+
+	this.add = function ( src ) {
+
+		src.addEventListener( "dispose", onDisposeScript );
+
+		this.scripts.push( src );
+
+	};
+
+	this.remove = function ( src ) {
+
+		src.removeEventListener( "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 );
+
+		}
+
+	};
+
+};
+
+//
+//	Script Handler
+//
+
+SEA3D.ScriptHandler = new SEA3D.ScriptManager();
+
+SEA3D.ScriptHandler.dispatchUpdate = function ( delta ) {
+
+	this.dispatchEvent( {
+		type: "update",
+		delta: delta
+	} );
+
+};
+
+//
+//	Animation Clip
+//
+
+SEA3D.AnimationClip = function ( name, duration, tracks, repeat ) {
+
+	AnimationClip.call( this, name, duration, tracks );
+
+	this.repeat = repeat !== undefined ? repeat : true;
+
+};
+
+SEA3D.AnimationClip.fromClip = function ( clip, repeat ) {
+
+	return new SEA3D.AnimationClip( clip.name, clip.duration, clip.tracks, repeat );
+
+};
+
+SEA3D.AnimationClip.prototype = Object.assign( Object.create( AnimationClip.prototype ), {
+
+	constructor: SEA3D.AnimationClip
+
+} );
+
+//
+//	Animation
+//
+
+SEA3D.Animation = function ( clip, timeScale ) {
+
+	this.clip = clip;
+	this.timeScale = timeScale !== undefined ? timeScale : 1;
+
+};
+
+SEA3D.Animation.COMPLETE = "animationComplete";
+
+SEA3D.Animation.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+
+	constructor: SEA3D.Animation,
+
+	onComplete: function ( scope ) {
+
+		this.dispatchEvent( { type: SEA3D.Animation.COMPLETE, target: this } );
+
+
+	}
+
+} );
+
+Object.defineProperties( SEA3D.Animation.prototype, {
+
+	name: {
+
+		get: function () {
+
+			return this.clip.name;
+
+		}
+
+	},
+
+	repeat: {
+
+		get: function () {
+
+			return this.clip.repeat;
+
+		}
+
+	},
+
+	duration: {
+
+		get: function () {
+
+			return this.clip.duration;
+
+		}
+
+	},
+
+	mixer: {
+
+		set: function ( val ) {
+
+			if ( this.mx ) {
+
+				this.mx.uncacheClip( this.clip );
+				delete this.mx;
+
+			}
+
+			if ( val ) {
+
+				this.mx = val;
+				this.mx.clipAction( this.clip );
+
+			}
+
+		},
+
+		get: function () {
+
+			return this.mx;
+
+		}
+
+	}
+
+} );
+
+//
+//	Animator
+//
+
+SEA3D.Animator = function ( clips, mixer ) {
+
+	this.updateAnimations( clips, mixer );
+
+	this.clone = function ( scope ) {
+
+		return new this.constructor( this.clips, new AnimationMixer( scope ) ).copyFrom( this );
+
+	}.bind( this );
+
+};
+
+Object.assign( SEA3D.Animator.prototype, {
+
+	update: function ( dt ) {
+
+		this.mixer.update( dt || 0 );
+
+		if ( this.currentAnimationAction && this.currentAnimationAction.paused ) {
+
+			this.pause();
+
+			if ( this.currentAnimation ) {
+
+				this.currentAnimation.onComplete( this );
+
+			}
+
+		}
+
+		return this;
+
+	},
+
+	updateAnimations: function ( clips, mixer ) {
+
+		if ( this.playing ) this.stop();
+
+		if ( this.mixer ) SEA3D.AnimationHandler.remove( this );
+
+		this.mixer = mixer;
+
+		this.relative = false;
+		this.playing = false;
+		this.paused = false;
+
+		this.timeScale = 1;
+
+		this.animations = [];
+		this.animation = {};
+
+		this.clips = [];
+
+		if ( clips ) {
+
+			for ( var i = 0; i < clips.length; i ++ ) {
+
+				this.addAnimation( clips[ i ] );
+
+			}
+
+		}
+
+		return this;
+
+	},
+
+	addAnimation: function ( animation ) {
+
+		if ( animation instanceof AnimationClip ) {
+
+			this.clips.push( animation );
+
+			animation = new SEA3D.Animation( animation );
+
+		}
+
+		this.animations.push( animation );
+		this.animation[ animation.name ] = animation;
+
+		animation.mixer = this.mixer;
+
+		return animation;
+
+	},
+
+	removeAnimation: function ( animation ) {
+
+		if ( animation instanceof AnimationClip ) {
+
+			animation = this.getAnimationByClip( animation );
+
+		}
+
+		this.clips.splice( this.clips.indexOf( animation.clip ), 1 );
+
+		delete this.animation[ animation.name ];
+		this.animations.splice( this.animations.indexOf( animation ), 1 );
+
+		animation.mixer = null;
+
+		return animation;
+
+	},
+
+	getAnimationByClip: function ( clip ) {
+
+		for ( var i = 0; i < this.animations.length; i ++ ) {
+
+			if ( this.animations[ i ].clip === clip ) return clip;
+
+		}
+
+	},
+
+	getAnimationByName: function ( name ) {
+
+		return typeof name === "number" ? this.animations[ name ] : this.animation[ name ];
+
+	},
+
+	setAnimationWeight: function ( name, val ) {
+
+		this.mixer.clipAction( this.getAnimationByName( name ).clip ).setEffectiveWeight( val );
+
+	},
+
+	getAnimationWeight: function ( name ) {
+
+		return this.mixer.clipAction( this.getAnimationByName( name ).clip ).getEffectiveWeight();
+
+	},
+
+	pause: function () {
+
+		if ( this.playing && this.currentAnimation ) {
+
+			SEA3D.AnimationHandler.remove( this );
+
+			this.playing = false;
+
+		}
+
+		return this;
+
+	},
+
+	resume: function () {
+
+		if ( ! this.playing && this.currentAnimation ) {
+
+			SEA3D.AnimationHandler.add( this );
+
+			this.playing = true;
+
+		}
+
+		return this;
+
+	},
+
+	setTimeScale: function ( val ) {
+
+		this.timeScale = val;
+
+		if ( this.currentAnimationAction ) this.updateTimeScale();
+
+		return this;
+
+	},
+
+	getTimeScale: function () {
+
+		return this.timeScale;
+
+	},
+
+	updateTimeScale: function () {
+
+		this.currentAnimationAction.setEffectiveTimeScale( this.timeScale * ( this.currentAnimation ? this.currentAnimation.timeScale : 1 ) );
+
+		return this;
+
+	},
+
+	play: function ( name, crossfade, offset, weight ) {
+
+		var animation = this.getAnimationByName( name );
+
+		if ( ! animation ) throw new Error( 'Animation "' + name + '" not found.' );
+
+		if ( animation === this.currentAnimation ) {
+
+			if ( offset !== undefined || ! animation.repeat ) this.currentAnimationAction.time = offset !== undefined ? offset :
+				( this.currentAnimationAction.timeScale >= 0 ? 0 : this.currentAnimation.duration );
+
+			this.currentAnimationAction.setEffectiveWeight( weight !== undefined ? weight : 1 );
+			this.currentAnimationAction.paused = false;
+
+			return this.resume();
+
+		} else {
+
+			this.previousAnimation = this.currentAnimation;
+			this.currentAnimation = animation;
+
+			this.previousAnimationAction = this.currentAnimationAction;
+			this.currentAnimationAction = this.mixer.clipAction( animation.clip ).setLoop( animation.repeat ? LoopRepeat : LoopOnce, Infinity ).reset();
+			this.currentAnimationAction.clampWhenFinished = ! animation.repeat;
+			this.currentAnimationAction.paused = false;
+
+			this.updateTimeScale();
+
+			if ( offset !== undefined || ! animation.repeat ) this.currentAnimationAction.time = offset !== undefined ? offset :
+				( this.currentAnimationAction.timeScale >= 0 ? 0 : this.currentAnimation.duration );
+
+			this.currentAnimationAction.setEffectiveWeight( weight !== undefined ? weight : 1 );
+
+			this.currentAnimationAction.play();
+
+			if ( ! this.playing ) this.mixer.update( 0 );
+
+			this.playing = true;
+
+			if ( this.previousAnimation ) this.previousAnimationAction.crossFadeTo( this.currentAnimationAction, crossfade || 0, false );
+
+			SEA3D.AnimationHandler.add( this );
+
+		}
+
+		return this;
+
+	},
+
+	stop: function () {
+
+		if ( this.playing ) SEA3D.AnimationHandler.remove( this );
+
+		if ( this.currentAnimation ) {
+
+			this.currentAnimationAction.stop();
+
+			this.previousAnimation = this.currentAnimation;
+			this.previousAnimationAction = this.currentAnimationAction;
+
+			delete this.currentAnimationAction;
+			delete this.currentAnimation;
+
+			this.playing = false;
+
+		}
+
+		return this;
+
+	},
+
+	playw: function ( name, weight ) {
+
+		if ( ! this.playing && ! this.paused ) SEA3D.AnimationHandler.add( this );
+
+		var animation = this.getAnimationByName( name );
+
+		this.playing = true;
+
+		var clip = this.mixer.clipAction( animation.clip );
+		clip.setLoop( animation.repeat ? LoopRepeat : LoopOnce, Infinity ).reset();
+		clip.clampWhenFinished = ! animation.repeat;
+		clip.paused = false;
+
+		clip.setEffectiveWeight( weight ).play();
+
+		return clip;
+
+	},
+
+	crossFade: function ( fromAnimName, toAnimName, duration, wrap ) {
+
+		this.mixer.stopAllAction();
+
+		var fromAction = this.playw( fromAnimName, 1 );
+		var toAction = this.playw( toAnimName, 1 );
+
+		fromAction.crossFadeTo( toAction, duration, wrap !== undefined ? wrap : false );
+
+		return this;
+
+	},
+
+	stopAll: function () {
+
+		this.stop().mixer.stopAllAction();
+
+		this.playing = false;
+
+		return this;
+
+	},
+
+	unPauseAll: function () {
+
+		this.mixer.timeScale = 1;
+
+		this.playing = true;
+		this.paused = false;
+
+		return this;
+
+	},
+
+	pauseAll: function () {
+
+		this.mixer.timeScale = 0;
+
+		this.playing = false;
+		this.paused = true;
+
+		return this;
+
+	},
+
+	setRelative: function ( val ) {
+
+		if ( this.relative === val ) return;
+
+		this.stop();
+
+		this.relative = val;
+
+		return this;
+
+	},
+
+	getRelative: function () {
+
+		return this.relative;
+
+	},
+
+	copyFrom: function ( scope ) {
+
+		for ( var i = 0; i < this.animations.length; i ++ ) {
+
+			this.animations[ i ].timeScale = scope.animations[ i ].timeScale;
+
+		}
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Object3D Animator
+//
+
+SEA3D.Object3DAnimator = function ( clips, object3d ) {
+
+	this.object3d = object3d;
+
+	SEA3D.Animator.call( this, clips, new AnimationMixer( object3d ) );
+
+	this.clone = function ( scope ) {
+
+		return new this.constructor( this.clips, scope ).copyFrom( this );
+
+	}.bind( this );
+
+};
+
+SEA3D.Object3DAnimator.prototype = Object.assign( Object.create( SEA3D.Animator.prototype ), {
+
+	constructor: SEA3D.Object3DAnimator,
+
+	stop: function () {
+
+		if ( this.currentAnimation ) {
+
+			var animate = this.object3d.animate;
+
+			if ( animate && this instanceof SEA3D.Object3DAnimator ) {
+
+				animate.position.set( 0, 0, 0 );
+				animate.quaternion.set( 0, 0, 0, 1 );
+				animate.scale.set( 1, 1, 1 );
+
+			}
+
+		}
+
+		SEA3D.Animator.prototype.stop.call( this );
+
+	},
+
+	setRelative: function ( val ) {
+
+		SEA3D.Animator.prototype.setRelative.call( this, val );
+
+		this.object3d.setAnimator( this.relative );
+
+		this.updateAnimations( this.clips, new AnimationMixer( this.relative ? this.object3d.animate : this.object3d ) );
+
+	}
+
+} );
+
+//
+//	Camera Animator
+//
+
+SEA3D.CameraAnimator = function ( clips, object3d ) {
+
+	SEA3D.Object3DAnimator.call( this, clips, object3d );
+
+};
+
+SEA3D.CameraAnimator.prototype = Object.assign( Object.create( SEA3D.Object3DAnimator.prototype ), {
+
+	constructor: SEA3D.CameraAnimator
+
+} );
+
+//
+//	Sound Animator
+//
+
+SEA3D.SoundAnimator = function ( clips, object3d ) {
+
+	SEA3D.Object3DAnimator.call( this, clips, object3d );
+
+};
+
+SEA3D.SoundAnimator.prototype = Object.assign( Object.create( SEA3D.Object3DAnimator.prototype ), {
+
+	constructor: SEA3D.SoundAnimator
+
+} );
+
+//
+//	Light Animator
+//
+
+SEA3D.LightAnimator = function ( clips, object3d ) {
+
+	SEA3D.Object3DAnimator.call( this, clips, object3d );
+
+};
+
+SEA3D.LightAnimator.prototype = Object.assign( Object.create( SEA3D.Object3DAnimator.prototype ), {
+
+	constructor: SEA3D.LightAnimator
+
+} );
+
+//
+//	Container
+//
+
+SEA3D.Object3D = function ( ) {
+
+	Object3D.call( this );
+
+};
+
+SEA3D.Object3D.prototype = Object.assign( Object.create( Object3D.prototype ), {
+
+	constructor: SEA3D.Object3D,
+
+	// Relative Animation Extension ( Only used if relative animation is enabled )
+	// TODO: It can be done with shader
+
+	updateAnimateMatrix: function ( 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.animate.updateMatrix();
+
+			this.matrixWorld.multiplyMatrices( this.matrixWorld, this.animate.matrix );
+
+			this.matrixWorldNeedsUpdate = false;
+
+			force = true;
+
+		}
+
+		// update children
+
+		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+
+			this.children[ i ].updateMatrixWorld( force );
+
+		}
+
+	},
+
+	setAnimator: function ( val ) {
+
+		if ( this.getAnimator() == val )
+			return;
+
+		if ( val ) {
+
+			this.animate = new Object3D();
+
+			this.updateMatrixWorld = SEA3D.Object3D.prototype.updateAnimateMatrix;
+
+		} else {
+
+			delete this.animate;
+
+			this.updateMatrixWorld = Object3D.prototype.updateMatrixWorld;
+
+		}
+
+		this.matrixWorldNeedsUpdate = true;
+
+	},
+
+	getAnimator: function () {
+
+		return this.animate != undefined;
+
+	},
+
+	copy: function ( source ) {
+
+		Object3D.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Dummy
+//
+
+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 BoxGeometry( this.width, this.height, this.depth, 1, 1, 1 );
+
+	geo.computeBoundingBox();
+	geo.computeBoundingSphere();
+
+	Mesh.call( this, geo, SEA3D.Dummy.MATERIAL );
+
+};
+
+SEA3D.Dummy.MATERIAL = new MeshBasicMaterial( { wireframe: true, color: SEA3D.HELPER_COLOR } );
+
+SEA3D.Dummy.prototype = Object.assign( Object.create( Mesh.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.Dummy,
+
+	copy: function ( source ) {
+
+		Mesh.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	},
+
+	dispose: function () {
+
+		this.geometry.dispose();
+
+	}
+
+} );
+
+//
+//	Mesh
+//
+
+SEA3D.Mesh = function ( geometry, material ) {
+
+	Mesh.call( this, geometry, material );
+
+};
+
+SEA3D.Mesh.prototype = Object.assign( Object.create( Mesh.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.Mesh,
+
+	setWeight: function ( name, val ) {
+
+		var index = typeof name === "number" ? name : this.morphTargetDictionary[ name ];
+
+		this.morphTargetInfluences[ index ] = val;
+
+	},
+
+	getWeight: function ( name ) {
+
+		var index = typeof name === "number" ? name : this.morphTargetDictionary[ name ];
+
+		return this.morphTargetInfluences[ index ];
+
+	},
+
+	copy: function ( source ) {
+
+		Mesh.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Skinning
+//
+
+SEA3D.SkinnedMesh = function ( geometry, material ) {
+
+	SkinnedMesh.call( this, geometry, material );
+
+	this.bind( new Skeleton( this.initBones() ), this.matrixWorld );
+
+	this.updateAnimations( geometry.animations, new AnimationMixer( this ) );
+
+};
+
+SEA3D.SkinnedMesh.prototype = Object.assign( Object.create( SkinnedMesh.prototype ), SEA3D.Mesh.prototype, SEA3D.Animator.prototype, {
+
+	constructor: SEA3D.SkinnedMesh,
+
+	initBones: function () {
+
+		var bones = [], bone, gbone;
+		var i, il;
+
+		if ( this.geometry && this.geometry.bones !== undefined ) {
+
+			// first, create array of 'Bone' objects from geometry data
+
+			for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
+
+				gbone = this.geometry.bones[ i ];
+
+				// create new 'Bone' object
+
+				bone = new Bone();
+				bones.push( bone );
+
+				// apply values
+
+				bone.name = gbone.name;
+				bone.position.fromArray( gbone.pos );
+				bone.quaternion.fromArray( gbone.rotq );
+				if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
+
+			}
+
+			// second, create bone hierarchy
+
+			for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
+
+				gbone = this.geometry.bones[ i ];
+
+				if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
+
+					// subsequent bones in the hierarchy
+
+					bones[ gbone.parent ].add( bones[ i ] );
+
+				} else {
+
+					// topmost bone, immediate child of the skinned mesh
+
+					this.add( bones[ i ] );
+
+				}
+
+			}
+
+		}
+
+		// now the bones are part of the scene graph and children of the skinned mesh.
+		// let's update the corresponding matrices
+
+		this.updateMatrixWorld( true );
+
+		return bones;
+
+	},
+
+	boneByName: function ( name ) {
+
+		var bones = this.skeleton.bones;
+
+		for ( var i = 0, bl = bones.length; i < bl; i ++ ) {
+
+			if ( name === bones[ i ].name )
+				return bones[ i ];
+
+		}
+
+	},
+
+	copy: function ( source ) {
+
+		SkinnedMesh.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Vertex Animation
+//
+
+SEA3D.VertexAnimationMesh = function ( geometry, material ) {
+
+	Mesh.call( this, geometry, material );
+
+	this.type = 'MorphAnimMesh';
+
+	this.updateAnimations( geometry.animations, new AnimationMixer( this ) );
+
+};
+
+SEA3D.VertexAnimationMesh.prototype = Object.assign( Object.create( Mesh.prototype ), SEA3D.Mesh.prototype, SEA3D.Animator.prototype, {
+
+	constructor: SEA3D.VertexAnimationMesh,
+
+	copy: function ( source ) {
+
+		Mesh.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Camera
+//
+
+SEA3D.Camera = function ( fov, aspect, near, far ) {
+
+	PerspectiveCamera.call( this, fov, aspect, near, far );
+
+};
+
+SEA3D.Camera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.Camera,
+
+	copy: function ( source ) {
+
+		PerspectiveCamera.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Orthographic Camera
+//
+
+SEA3D.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
+
+	OrthographicCamera.call( this, left, right, top, bottom, near, far );
+
+};
+
+SEA3D.OrthographicCamera.prototype = Object.assign( Object.create( OrthographicCamera.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.OrthographicCamera,
+
+	copy: function ( source ) {
+
+		OrthographicCamera.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	PointLight
+//
+
+SEA3D.PointLight = function ( hex, intensity, distance, decay ) {
+
+	PointLight.call( this, hex, intensity, distance, decay );
+
+};
+
+SEA3D.PointLight.prototype = Object.assign( Object.create( PointLight.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.PointLight,
+
+	copy: function ( source ) {
+
+		PointLight.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Point Sound
+//
+
+SEA3D.PointSound = function ( listener, sound ) {
+
+	PositionalAudio.call( this, listener );
+
+	this.setSound( sound );
+
+};
+
+SEA3D.PointSound.prototype = Object.assign( Object.create( PositionalAudio.prototype ), SEA3D.Object3D.prototype, {
+
+	constructor: SEA3D.PointSound,
+
+	setSound: function ( sound ) {
+
+		this.sound = sound;
+
+		if ( sound ) {
+
+			if ( sound.buffer ) {
+
+				this.setBuffer( sound.buffer );
+
+			} else {
+
+				sound.addEventListener( "complete", function ( e ) {
+
+					this.setBuffer( sound.buffer );
+
+				}.bind( this ) );
+
+			}
+
+		}
+
+		return this;
+
+	},
+
+	copy: function ( source ) {
+
+		PositionalAudio.prototype.copy.call( this, source );
+
+		this.attribs = source.attribs;
+		this.scripts = source.scripts;
+
+		if ( source.animator ) this.animator = source.animator.clone( this );
+
+		return this;
+
+	}
+
+} );
+
+//
+//	Animation Handler
+//
+
+SEA3D.AnimationHandler = {
+
+	animators: [],
+
+	update: function ( dt ) {
+
+		var i = 0;
+
+		while ( i < this.animators.length ) {
+
+			this.animators[ i ++ ].update( dt );
+
+		}
+
+	},
+
+	add: function ( animator ) {
+
+		var index = this.animators.indexOf( animator );
+
+		if ( index === - 1 ) this.animators.push( animator );
+
+	},
+
+	remove: function ( animator ) {
+
+		var index = this.animators.indexOf( animator );
+
+		if ( index !== - 1 ) this.animators.splice( index, 1 );
+
+	}
+
+};
+
+//
+//	Sound
+//
+
+SEA3D.Sound = function ( src ) {
+
+	this.uuid = Math.generateUUID();
+
+	this.src = src;
+
+	new AudioLoader().load( src, function ( buffer ) {
+
+		this.buffer = buffer;
+
+		this.dispatchEvent( { type: "complete" } );
+
+	}.bind( this ) );
+
+};
+
+SEA3D.Sound.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+
+	constructor: SEA3D.Sound
+
+} );
+
+//
+//	Output
+//
+
+SEA3D.Domain.prototype.getMesh = SEA3D.prototype.getMesh = function ( name ) {
+
+	return this.objects[ "m3d/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getDummy = SEA3D.prototype.getDummy = function ( name ) {
+
+	return this.objects[ "dmy/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getLine = SEA3D.prototype.getLine = function ( name ) {
+
+	return this.objects[ "line/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getSound3D = SEA3D.prototype.getSound3D = function ( name ) {
+
+	return this.objects[ "sn3d/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getMaterial = SEA3D.prototype.getMaterial = function ( name ) {
+
+	return this.objects[ "mat/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getLight = SEA3D.prototype.getLight = function ( name ) {
+
+	return this.objects[ "lht/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getGLSL = SEA3D.prototype.getGLSL = function ( name ) {
+
+	return this.objects[ "glsl/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getCamera = SEA3D.prototype.getCamera = function ( name ) {
+
+	return this.objects[ "cam/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getTexture = SEA3D.prototype.getTexture = function ( name ) {
+
+	return this.objects[ "tex/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getCubeMap = SEA3D.prototype.getCubeMap = function ( name ) {
+
+	return this.objects[ "cmap/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getJointObject = SEA3D.prototype.getJointObject = function ( name ) {
+
+	return this.objects[ "jnt/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getContainer3D = SEA3D.prototype.getContainer3D = function ( name ) {
+
+	return this.objects[ "c3d/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getSprite = SEA3D.prototype.getSprite = function ( name ) {
+
+	return this.objects[ "m2d/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getProperties = SEA3D.prototype.getProperties = function ( name ) {
+
+	return this.objects[ "prop/" + name ];
+
+};
+
+//
+//	Utils
+//
+
+SEA3D.prototype.isPowerOfTwo = function ( num ) {
+
+	return num ? ( ( num & - num ) === num ) : false;
+
+};
+
+SEA3D.prototype.nearestPowerOfTwo = function ( num ) {
+
+	return Math.pow( 2, Math.round( Math.log( num ) / Math.LN2 ) );
+
+};
+
+SEA3D.prototype.updateTransform = function ( obj3d, sea ) {
+
+	var mtx = SEA3D.MTXBUF, vec = SEA3D.VECBUF;
+
+	if ( sea.transform ) mtx.fromArray( sea.transform );
+	else mtx.makeTranslation( sea.position.x, sea.position.y, sea.position.z );
+
+	// matrix
+
+	obj3d.position.setFromMatrixPosition( mtx );
+	obj3d.scale.setFromMatrixScale( mtx );
+
+	// ignore rotation scale
+
+	obj3d.quaternion.setFromRotationMatrix( SEA3D.identityMatrixScale( mtx ) );
+
+	// optimize if is static
+
+	if ( this.config.forceStatic || sea.isStatic ) {
+
+		obj3d.updateMatrix();
+		obj3d.matrixAutoUpdate = false;
+
+	}
+
+};
+
+SEA3D.prototype.toVector3 = function ( data ) {
+
+	return new Vector3( data.x, data.y, data.z );
+
+};
+
+SEA3D.prototype.toFaces = function ( faces ) {
+
+	// xyz(- / +) to xyz(+ / -) sequence
+	var f = [];
+
+	f[ 0 ] = faces[ 1 ];
+	f[ 1 ] = faces[ 0 ];
+	f[ 2 ] = faces[ 3 ];
+	f[ 3 ] = faces[ 2 ];
+	f[ 4 ] = faces[ 5 ];
+	f[ 5 ] = faces[ 4 ];
+
+	return f;
+
+};
+
+SEA3D.prototype.updateScene = function () {
+
+	if ( this.materials != undefined ) {
+
+		for ( var i = 0, l = this.materials.length; i < l; ++ i ) {
+
+			this.materials[ i ].needsUpdate = true;
+
+		}
+
+	}
+
+};
+
+SEA3D.prototype.addSceneObject = function ( sea, obj3d ) {
+
+	obj3d = obj3d || sea.tag;
+
+	obj3d.visible = sea.visible;
+
+	if ( sea.parent ) sea.parent.tag.add( obj3d );
+	else if ( this.config.container ) this.config.container.add( obj3d );
+
+	if ( sea.attributes ) obj3d.attribs = sea.attributes.tag;
+
+	if ( sea.scripts ) {
+
+		obj3d.scripts = this.getJSMList( obj3d, sea.scripts );
+
+		if ( this.config.scripts && this.config.runScripts ) this.domain.runJSMList( obj3d );
+
+	}
+
+};
+
+SEA3D.prototype.createObjectURL = function ( raw, mime ) {
+
+	return ( window.URL || window.webkitURL ).createObjectURL( new Blob( [ raw ], { type: mime } ) );
+
+};
+
+SEA3D.prototype.parsePath = function ( url ) {
+
+	var paths = this.config.paths;
+
+	for ( var name in paths ) {
+
+		url = url.replace( new RegExp( "%" + name + "%", "g" ), paths[ name ] );
+
+	}
+
+	return url;
+
+};
+
+SEA3D.prototype.addDefaultAnimation = function ( sea, animatorClass ) {
+
+	var scope = sea.tag;
+
+	for ( var i = 0, count = sea.animations ? sea.animations.length : 0; i < count; i ++ ) {
+
+		var anm = sea.animations[ i ];
+
+		switch ( anm.tag.type ) {
+
+			case SEA3DSDK.Animation.prototype.type:
+
+				var animation = anm.tag.tag || this.getModifier( {
+					sea: anm.tag,
+					scope: scope,
+					relative: anm.relative
+				} );
+
+				scope.animator = new animatorClass( animation, scope );
+				scope.animator.setRelative( anm.relative );
+
+				if ( this.config.autoPlay ) {
+
+					scope.animator.play( 0 );
+
+				}
+
+				return scope.animator;
+
+				break;
+
+		}
+
+	}
+
+};
+
+//
+//	Geometry
+//
+
+SEA3D.prototype.readGeometryBuffer = function ( sea ) {
+
+	var geo = sea.tag || new BufferGeometry();
+
+	for ( var i = 0; i < sea.groups.length; i ++ ) {
+
+		var g = sea.groups[ i ];
+
+		geo.addGroup( g.start, g.count, i );
+
+	}
+
+	// not indexes? use polygon soup
+	if ( sea.indexes ) geo.setIndex( new BufferAttribute( sea.indexes, 1 ) );
+
+	geo.addAttribute( 'position', new BufferAttribute( sea.vertex, 3 ) );
+
+	if ( sea.uv ) {
+
+		geo.addAttribute( 'uv', new BufferAttribute( sea.uv[ 0 ], 2 ) );
+		if ( sea.uv.length > 1 ) geo.addAttribute( 'uv2', new BufferAttribute( sea.uv[ 1 ], 2 ) );
+
+	}
+
+	if ( sea.normal ) geo.addAttribute( 'normal', new BufferAttribute( sea.normal, 3 ) );
+	else geo.computeVertexNormals();
+
+	if ( sea.tangent4 ) geo.addAttribute( 'tangent', new BufferAttribute( sea.tangent4, 4 ) );
+
+	if ( sea.color ) geo.addAttribute( 'color', new BufferAttribute( sea.color[ 0 ], sea.numColor ) );
+
+	if ( sea.joint ) {
+
+		geo.addAttribute( 'skinIndex', new Float32BufferAttribute( sea.joint, sea.jointPerVertex ) );
+		geo.addAttribute( 'skinWeight', new Float32BufferAttribute( sea.weight, sea.jointPerVertex ) );
+
+	}
+
+	if ( this.config.bounding ) {
+
+		geo.computeBoundingBox();
+		geo.computeBoundingSphere();
+
+	}
+
+	geo.name = sea.name;
+
+	this.domain.geometries = this.geometries = this.geometries || [];
+	this.geometries.push( this.objects[ "geo/" + sea.name ] = sea.tag = geo );
+
+};
+
+//
+//	Dummy
+//
+
+SEA3D.prototype.readDummy = function ( sea ) {
+
+	var dummy = new SEA3D.Dummy( sea.width, sea.height, sea.depth );
+	dummy.name = sea.name;
+
+	this.domain.dummys = this.dummys = this.dummys || [];
+	this.dummys.push( this.objects[ "dmy/" + sea.name ] = sea.tag = dummy );
+
+	this.addSceneObject( sea );
+	this.updateTransform( dummy, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.Object3DAnimator );
+
+};
+
+//
+//	Line
+//
+
+SEA3D.prototype.readLine = function ( sea ) {
+
+	var	geo = new BufferGeometry();
+
+	if ( sea.closed )
+		sea.vertex.push( sea.vertex[ 0 ], sea.vertex[ 1 ], sea.vertex[ 2 ] );
+
+	geo.addAttribute( 'position', new Float32BufferAttribute( sea.vertex, 3 ) );
+
+	var line = new Line( geo, new LineBasicMaterial( { color: SEA3D.HELPER_COLOR, linewidth: 3 } ) );
+	line.name = sea.name;
+
+	this.lines = this.lines || [];
+	this.lines.push( this.objects[ "line/" + sea.name ] = sea.tag = line );
+
+	this.addSceneObject( sea );
+	this.updateTransform( line, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.Object3DAnimator );
+
+};
+
+//
+//	Container3D
+//
+
+SEA3D.prototype.readContainer3D = function ( sea ) {
+
+	var container = new SEA3D.Object3D();
+
+	this.domain.containers = this.containers = this.containers || [];
+	this.containers.push( this.objects[ "c3d/" + sea.name ] = sea.tag = container );
+
+	this.addSceneObject( sea );
+	this.updateTransform( container, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.Object3DAnimator );
+
+};
+
+//
+//	Sprite
+//
+
+SEA3D.prototype.readSprite = function ( sea ) {
+
+	var mat;
+
+	if ( sea.material ) {
+
+		if ( ! sea.material.tag.sprite ) {
+
+			mat = sea.material.tag.sprite = new SpriteMaterial();
+
+			this.setBlending( mat, sea.blendMode );
+
+			var map = sea.material.tag.map;
+
+			if ( map ) {
+
+				map.flipY = true;
+				mat.map = map;
+
+			}
+
+			mat.color.set( sea.material.tag.color );
+			mat.opacity = sea.material.tag.opacity;
+			mat.fog = sea.material.receiveFog;
+
+		} else {
+
+			mat = sea.material.tag.sprite;
+
+		}
+
+	}
+
+	var sprite = new Sprite( mat );
+	sprite.name = sea.name;
+
+	this.domain.sprites = this.sprites = this.sprites || [];
+	this.sprites.push( this.objects[ "m2d/" + sea.name ] = sea.tag = sprite );
+
+	this.addSceneObject( sea );
+	this.updateTransform( sprite, sea );
+
+	sprite.scale.set( sea.width, sea.height, 1 );
+
+};
+
+//
+//	Mesh
+//
+
+SEA3D.prototype.readMesh = function ( sea ) {
+
+	var i, count, geo = sea.geometry.tag, mesh, mat, skeleton, morpher, skeletonAnimation, vertexAnimation, uvwAnimationClips, morphAnimation;
+
+	for ( i = 0, count = sea.modifiers ? sea.modifiers.length : 0; i < count; i ++ ) {
+
+		var mod = sea.modifiers[ i ];
+
+		switch ( mod.type ) {
+
+			case SEA3DSDK.Skeleton.prototype.type:
+			case SEA3DSDK.SkeletonLocal.prototype.type:
+
+				skeleton = mod;
+
+				geo.bones = skeleton.tag;
+
+				break;
+
+			case SEA3DSDK.Morph.prototype.type:
+
+				morpher = mod.tag || this.getModifier( {
+					sea: mod,
+					geometry: sea.geometry
+				} );
+
+				geo.morphAttributes = morpher.attribs;
+				geo.morphTargets = morpher.targets;
+
+				break;
+
+		}
+
+	}
+
+	for ( i = 0, count = sea.animations ? sea.animations.length : 0; i < count; i ++ ) {
+
+		var anm = sea.animations[ i ],
+			anmTag = anm.tag;
+
+		switch ( anmTag.type ) {
+
+			case SEA3DSDK.SkeletonAnimation.prototype.type:
+
+				skeletonAnimation = anmTag;
+
+				geo.animations = skeletonAnimation.tag || this.getModifier( {
+					sea: skeletonAnimation,
+					skeleton: skeleton,
+					relative: true
+				} );
+
+				break;
+
+			case SEA3DSDK.VertexAnimation.prototype.type:
+
+				vertexAnimation = anmTag;
+
+				geo.morphAttributes = vertexAnimation.tag.attribs;
+				geo.morphTargets = vertexAnimation.tag.targets;
+				geo.animations = vertexAnimation.tag.animations;
+
+				break;
+
+			case SEA3DSDK.UVWAnimation.prototype.type:
+
+				uvwAnimationClips = anmTag.tag || this.getModifier( {
+					sea: anmTag
+				} );
+
+				break;
+
+			case SEA3DSDK.MorphAnimation.prototype.type:
+
+				morphAnimation = anmTag.tag || this.getModifier( {
+					sea: anmTag
+				} );
+
+				break;
+
+		}
+
+	}
+
+	var uMorph = morpher != undefined || vertexAnimation != undefined,
+		uMorphNormal =
+					( morpher && morpher.attribs.normal != undefined ) ||
+					( vertexAnimation && vertexAnimation.tag.attribs.normal != undefined );
+
+	if ( sea.material ) {
+
+		if ( sea.material.length > 1 ) {
+
+			mat = [];
+
+			for ( i = 0; i < sea.material.length; i ++ ) {
+
+				mat[ i ] = sea.material[ i ].tag;
+
+				mat[ i ].skinning = skeleton != undefined;
+				mat[ i ].morphTargets = uMorph;
+				mat[ i ].morphNormals = uMorphNormal;
+				mat[ i ].vertexColors = sea.geometry.color ? VertexColors : NoColors;
+
+			}
+
+		} else {
+
+			mat = sea.material[ 0 ].tag;
+
+			mat.skinning = skeleton != undefined;
+			mat.morphTargets = uMorph;
+			mat.morphNormals = uMorphNormal;
+			mat.vertexColors = sea.geometry.color ? VertexColors : NoColors;
+
+		}
+
+	}
+
+	if ( skeleton ) {
+
+		mesh = new SEA3D.SkinnedMesh( geo, mat, this.config.useVertexTexture );
+
+		if ( this.config.autoPlay && skeletonAnimation ) {
+
+			mesh.play( 0 );
+
+		}
+
+	} else if ( vertexAnimation ) {
+
+		mesh = new SEA3D.VertexAnimationMesh( geo, mat );
+
+		if ( this.config.autoPlay ) {
+
+			mesh.play( 0 );
+
+		}
+
+	} else {
+
+		mesh = new SEA3D.Mesh( geo, mat );
+
+	}
+
+	if ( uvwAnimationClips ) {
+
+		mesh.uvwAnimator = new SEA3D.Animator( uvwAnimationClips, new AnimationMixer( mat.map ) );
+
+		if ( this.config.autoPlay ) {
+
+			mesh.uvwAnimator.play( 0 );
+
+		}
+
+	}
+
+	if ( morphAnimation ) {
+
+		mesh.morphAnimator = new SEA3D.Animator( morphAnimation, new AnimationMixer( mesh ) );
+
+		if ( this.config.autoPlay ) {
+
+			mesh.morphAnimator.play( 0 );
+
+		}
+
+	}
+
+	mesh.name = sea.name;
+
+	mesh.castShadow = sea.castShadows;
+	mesh.receiveShadow = sea.material ? sea.material[ 0 ].receiveShadows : true;
+
+	this.domain.meshes = this.meshes = this.meshes || [];
+	this.meshes.push( this.objects[ "m3d/" + sea.name ] = sea.tag = mesh );
+
+	this.addSceneObject( sea );
+	this.updateTransform( mesh, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.Object3DAnimator );
+
+};
+
+//
+//	Sound Point
+//
+
+SEA3D.prototype.readSoundPoint = function ( sea ) {
+
+	if ( ! this.audioListener ) {
+
+		 this.audioListener = new AudioListener();
+
+		 if ( this.config.container ) {
+
+			this.config.container.add( this.audioListener );
+
+		}
+
+	}
+
+	var sound3d = new SEA3D.PointSound( this.audioListener );
+	sound3d.autoplay = sea.autoPlay;
+	sound3d.setLoop( sea.autoPlay );
+	sound3d.setVolume( sea.volume );
+	sound3d.setRefDistance( sea.distance );
+	sound3d.setRolloffFactor( this.config.audioRolloffFactor );
+	sound3d.setSound( sea.sound.tag );
+
+	sound3d.name = sea.name;
+
+	this.domain.sounds3d = this.sounds3d = this.sounds3d || [];
+	this.sounds3d.push( this.objects[ "sn3d/" + sea.name ] = sea.tag = sound3d );
+
+	this.addSceneObject( sea );
+	this.updateTransform( sound3d, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.SoundAnimator );
+
+};
+
+//
+//	Cube Render
+//
+
+SEA3D.prototype.readCubeRender = function ( sea ) {
+
+	var cube = new CubeCamera( 0.1, 5000, SEA3D.RTT_SIZE );
+	cube.renderTarget.cubeCamera = cube;
+
+	sea.tag = cube.renderTarget;
+
+	this.domain.cubeRenderers = this.cubeRenderers = this.cubeRenderers || [];
+	this.cubeRenderers.push( this.objects[ "rttc/" + sea.name ] = cube );
+
+	this.addSceneObject( sea, cube );
+	this.updateTransform( cube, sea );
+
+};
+
+//
+//	Texture (WDP, JPEG, PNG and GIF)
+//
+
+SEA3D.prototype.readTexture = function ( sea ) {
+
+	var image = new Image(),
+		texture = new Texture();
+
+	texture.name = sea.name;
+	texture.wrapS = texture.wrapT = RepeatWrapping;
+	texture.flipY = false;
+	texture.image = image;
+
+	if ( this.config.anisotropy !== undefined ) texture.anisotropy = this.config.anisotropy;
+
+	image.onload = function () {
+
+		texture.needsUpdate = true;
+
+	};
+
+	image.src = this.createObjectURL( sea.data.buffer, "image/" + sea.type );
+
+	this.domain.textures = this.textures = this.textures || [];
+	this.textures.push( this.objects[ "tex/" + sea.name ] = sea.tag = texture );
+
+};
+
+//
+//	Cube Map
+//
+
+SEA3D.prototype.readCubeMap = function ( sea ) {
+
+	var faces = this.toFaces( sea.faces ), texture = new CubeTexture( [] );
+
+	var loaded = 0;
+
+	texture.name = sea.name;
+	texture.flipY = false;
+	texture.format = RGBFormat;
+
+	var onLoaded = function () {
+
+		if ( ++ loaded === 6 ) {
+
+			texture.needsUpdate = true;
+
+			if ( ! this.config.async ) this.file.resume = true;
+
+		}
+
+	}.bind( this );
+
+	for ( var i = 0; i < faces.length; ++ i ) {
+
+		var cubeImage = new Image();
+		cubeImage.onload = onLoaded;
+		cubeImage.src = this.createObjectURL( faces[ i ].buffer, "image/" + sea.extension );
+
+		texture.images[ i ] = cubeImage;
+
+	}
+
+	if ( ! this.config.async ) this.file.resume = false;
+
+	this.domain.cubemaps = this.cubemaps = this.cubemaps || [];
+	this.cubemaps.push( this.objects[ "cmap/" + sea.name ] = sea.tag = texture );
+
+};
+
+//
+//	Updaters
+//
+
+SEA3D.prototype.readGeometryUpdate = function ( geometry, bytes, sea ) {
+
+	var Class = sea.sea3d.typeClass[ sea.type ],
+		seaUpdate = new Class( "", bytes, sea.sea3d );
+
+	seaUpdate.tag = geometry;
+
+	this.readGeometryBuffer( seaUpdate );
+
+};
+
+SEA3D.prototype.readTextureUpdate = function ( texture, bytes, type ) {
+
+	var image = new Image();
+
+	image.onload = function () {
+
+		texture.image = image;
+		texture.needsUpdate = true;
+
+	};
+
+	image.src = this.createObjectURL( bytes.buffer, "image/" + type );
+
+};
+
+SEA3D.prototype.readAssetUpdate = function ( sea ) {
+
+	var obj = this.file.objects[ sea.index ],
+		bytes = sea.bytes,
+		tag = obj.tag;
+
+	if (!tag) return;
+	
+	if ( tag.isBufferGeometry ) {
+
+		this.readGeometryUpdate( tag, bytes, obj );
+
+	} else if ( tag.isTexture ) {
+
+		this.readTextureUpdate( tag, bytes, obj.type );
+
+	}
+
+};
+
+//
+//	Sound (MP3, OGG)
+//
+
+SEA3D.prototype.readSound = function ( sea ) {
+
+	var sound = new SEA3D.Sound( this.createObjectURL( sea.data.buffer, "audio/" + sea.type ) );
+	sound.name = sea.name;
+
+	this.domain.sounds = this.sounds = this.sounds || [];
+	this.sounds.push( this.objects[ "snd/" + sea.name ] = sea.tag = sound );
+
+};
+
+//
+//	Script URL
+//
+
+SEA3D.prototype.readScriptURL = function ( sea ) {
+
+	this.file.resume = false;
+
+	var loader = new FileLoader();
+
+	loader.setResponseType( "text" ).load( sea.url, function ( src ) {
+
+		this.file.resume = true;
+
+		this.domain.scripts = this.scripts = this.scripts || [];
+		this.scripts.push( this.objects[ "src/" + sea.name ] = sea.tag = src );
+
+	}.bind( this ) );
+
+};
+
+//
+//	Texture URL
+//
+
+SEA3D.prototype.readTextureURL = function ( sea ) {
+
+	var texture = new TextureLoader().load( this.parsePath( sea.url ) );
+
+	texture.name = sea.name;
+	texture.wrapS = texture.wrapT = RepeatWrapping;
+	texture.flipY = false;
+
+	if ( this.config.anisotropy !== undefined ) texture.anisotropy = this.config.anisotropy;
+
+	this.domain.textures = this.textures = this.textures || [];
+	this.textures.push( this.objects[ "tex/" + sea.name ] = sea.tag = texture );
+
+};
+
+//
+//	CubeMap URL
+//
+
+SEA3D.prototype.readCubeMapURL = function ( sea ) {
+
+	var faces = this.toFaces( sea.faces );
+
+	for ( var i = 0; i < faces.length; i ++ ) {
+
+		faces[ i ] = this.parsePath( faces[ i ] );
+
+	}
+
+	var texture, format = faces[ 0 ].substr( - 3 );
+
+	if ( format === "hdr" ) {
+
+		var usePMREM = PMREMGenerator != null;
+
+		this.file.resume = ! usePMREM;
+
+		texture = new HDRCubeTextureLoader().load( UnsignedByteType, faces, function ( texture ) {
+
+			if ( usePMREM ) {
+
+				var pmremGenerator = new PMREMGenerator( texture );
+				pmremGenerator.update( this.config.renderer );
+
+				var pmremCubeUVPacker = new PMREMCubeUVPacker( pmremGenerator.cubeLods );
+				pmremCubeUVPacker.update( this.config.renderer );
+
+				texture.dispose();
+
+				this.objects[ "cmap/" + sea.name ] = sea.tag = pmremCubeUVPacker.CubeUVRenderTarget.texture;
+
+				this.file.resume = true;
+
+			}
+
+		}.bind( this ) );
+
+	} else {
+
+		texture = new CubeTextureLoader().load( faces );
+
+	}
+
+	texture.name = sea.name;
+	texture.wrapS = texture.wrapT = RepeatWrapping;
+	texture.flipY = false;
+
+	if ( this.config.anisotropy !== undefined ) texture.anisotropy = this.config.anisotropy;
+
+	this.domain.cubemaps = this.cubemaps = this.cubemaps || [];
+	this.cubemaps.push( this.objects[ "cmap/" + sea.name ] = sea.tag = texture );
+
+};
+
+//
+//	Runtime
+//
+
+SEA3D.prototype.getJSMList = function ( target, scripts ) {
+
+	var scriptTarget = [];
+
+	for ( var i = 0; i < scripts.length; i ++ ) {
+
+		var script = scripts[ i ];
+
+		if ( script.tag.type === SEA3DSDK.JavaScriptMethod.prototype.type ) {
+
+			scriptTarget.push( script );
+
+		}
+
+	}
+
+	this.domain.scriptTargets = this.scriptTargets = this.scriptTargets || [];
+	this.scriptTargets.push( target );
+
+	return scriptTarget;
+
+};
+
+SEA3D.prototype.readJavaScriptMethod = function ( sea ) {
+
+	try {
+
+		var src =
+			'(function() {\n' +
+			'var $METHOD = {}\n';
+
+		var declare =
+			'function($INC, $REF, global, local, self, $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' +
+			'addEventListener = $SRC.addEventListener.bind( $SRC ),\n' +
+			'hasEventListener = $SRC.hasEventListener.bind( $SRC ),\n' +
+			'removeEventListener = $SRC.removeEventListener.bind( $SRC ),\n' +
+			'dispatchEvent = $SRC.dispatchEvent.bind( $SRC ),\n' +
+			'dispose = $SRC.dispose.bind( $SRC );\n';
+
+		for ( var name in sea.methods ) {
+
+			src += '$METHOD["' + name + '"] = ' + declare + sea.methods[ name ].src + '}\n';
+
+		}
+
+		src += 'return $METHOD; })';
+
+		this.domain.methods = eval( src )();
+
+	} catch ( e ) {
+
+		console.error( 'SEA3D JavaScriptMethod: Error running "' + sea.name + '".' );
+		console.error( e );
+
+	}
+
+};
+
+//
+//	GLSL
+//
+
+SEA3D.prototype.readGLSL = function ( sea ) {
+
+	this.domain.glsl = this.glsl = this.glsl || [];
+	this.glsl.push( this.objects[ "glsl/" + sea.name ] = sea.tag = sea.src );
+
+};
+
+//
+//	Material
+//
+
+SEA3D.prototype.materialTechnique =
+( function () {
+
+	var techniques = {};
+
+	// FINAL
+	techniques.onComplete = function ( mat, sea ) {
+
+		if ( sea.alpha < 1 || mat.blending > NormalBlending ) {
+
+			mat.opacity = sea.alpha;
+			mat.transparent = true;
+
+		}
+
+	};
+
+	// PHYSICAL
+	techniques[ SEA3DSDK.Material.PHYSICAL ] =
+	function ( mat, tech ) {
+
+		mat.color.setHex( tech.color );
+		mat.roughness = tech.roughness;
+		mat.metalness = tech.metalness;
+
+	};
+
+	// REFLECTIVITY
+	techniques[ SEA3DSDK.Material.REFLECTIVITY ] =
+	function ( mat, tech ) {
+
+		mat.reflectivity = tech.strength;
+
+	};
+
+	// CLEAR_COAT
+	techniques[ SEA3DSDK.Material.CLEAR_COAT ] =
+	function ( mat, tech ) {
+
+		mat.clearCoat = tech.strength;
+		mat.clearCoatRoughness = tech.roughness;
+
+	};
+
+	// PHONG
+	techniques[ SEA3DSDK.Material.PHONG ] =
+	function ( mat, tech ) {
+
+		mat.color.setHex( tech.diffuseColor );
+		mat.specular.setHex( tech.specularColor ).multiplyScalar( tech.specular );
+		mat.shininess = tech.gloss;
+
+	};
+
+	// DIFFUSE_MAP
+	techniques[ SEA3DSDK.Material.DIFFUSE_MAP ] =
+	function ( mat, tech, sea ) {
+
+		mat.map = tech.texture.tag;
+		mat.color.setHex( 0xFFFFFF );
+
+		mat.map.wrapS = mat.map.wrapT = sea.repeat ? RepeatWrapping : ClampToEdgeWrapping;
+
+		if ( tech.texture.transparent ) {
+
+			mat.transparent = true;
+
+		}
+
+	};
+
+	// ROUGHNESS_MAP
+	techniques[ SEA3DSDK.Material.ROUGHNESS_MAP ] =
+	function ( mat, tech ) {
+
+		mat.roughnessMap = tech.texture.tag;
+
+	};
+
+	// METALNESS_MAP
+	techniques[ SEA3DSDK.Material.METALNESS_MAP ] =
+	function ( mat, tech ) {
+
+		mat.metalnessMap = tech.texture.tag;
+
+	};
+
+	// SPECULAR_MAP
+	techniques[ SEA3DSDK.Material.SPECULAR_MAP ] =
+	function ( mat, tech ) {
+
+		if ( mat.specular ) {
+
+			mat.specularMap = tech.texture.tag;
+			mat.specular.setHex( 0xFFFFFF );
+
+		}
+
+	};
+
+	// NORMAL_MAP
+	techniques[ SEA3DSDK.Material.NORMAL_MAP ] =
+	function ( mat, tech ) {
+
+		mat.normalMap = tech.texture.tag;
+
+	};
+
+	// REFLECTION
+	techniques[ SEA3DSDK.Material.REFLECTION ] =
+	techniques[ SEA3DSDK.Material.FRESNEL_REFLECTION ] =
+	function ( mat, tech ) {
+
+		mat.envMap = tech.texture.tag;
+		mat.envMap.mapping = CubeReflectionMapping;
+		mat.combine = MixOperation;
+
+		mat.reflectivity = tech.alpha;
+
+	};
+
+	// REFLECTION_SPHERICAL
+	techniques[ SEA3DSDK.Material.REFLECTION_SPHERICAL ] =
+	function ( mat, tech ) {
+
+		mat.envMap = tech.texture.tag;
+		mat.envMap.mapping = SphericalReflectionMapping;
+		mat.combine = MixOperation;
+
+		mat.reflectivity = tech.alpha;
+
+	};
+
+	// REFRACTION
+	techniques[ SEA3DSDK.Material.REFRACTION_MAP ] =
+	function ( mat, tech ) {
+
+		mat.envMap = tech.texture.tag;
+		mat.envMap.mapping = CubeRefractionMapping;
+
+		mat.refractionRatio = tech.ior;
+		mat.reflectivity = tech.alpha;
+
+	};
+
+	// LIGHT_MAP
+	techniques[ SEA3DSDK.Material.LIGHT_MAP ] =
+	function ( mat, tech ) {
+
+		if ( tech.blendMode === "multiply" ) mat.aoMap = tech.texture.tag;
+		else mat.lightMap = tech.texture.tag;
+
+	};
+
+	// EMISSIVE
+	techniques[ SEA3DSDK.Material.EMISSIVE ] =
+	function ( mat, tech ) {
+
+		mat.emissive.setHex( tech.color );
+
+	};
+
+	// EMISSIVE_MAP
+	techniques[ SEA3DSDK.Material.EMISSIVE_MAP ] =
+	function ( mat, tech ) {
+
+		mat.emissiveMap = tech.texture.tag;
+
+	};
+
+	// ALPHA_MAP
+	techniques[ SEA3DSDK.Material.ALPHA_MAP ] =
+	function ( mat, tech, sea ) {
+
+		mat.alphaMap = tech.texture.tag;
+		mat.transparent = true;
+
+		mat.alphaMap.wrapS = mat.alphaMap.wrapT = sea.repeat ? RepeatWrapping : ClampToEdgeWrapping;
+
+	};
+
+	return techniques;
+
+} )();
+
+SEA3D.prototype.createMaterial = function ( sea ) {
+
+	if ( sea.tecniquesDict[ SEA3DSDK.Material.REFLECTIVITY ] || sea.tecniquesDict[ SEA3DSDK.Material.CLEAR_COAT ] ) {
+
+		return new MeshPhysicalMaterial();
+
+	} else if ( sea.tecniquesDict[ SEA3DSDK.Material.PHYSICAL ] ) {
+
+		return new MeshStandardMaterial();
+
+	}
+
+	return new MeshPhongMaterial();
+
+};
+
+SEA3D.prototype.setBlending = function ( mat, blendMode ) {
+
+	if ( blendMode === "normal" ) return;
+
+	switch ( blendMode ) {
+
+		case "add":
+
+			mat.blending = AdditiveBlending;
+
+			break;
+
+		case "subtract":
+
+			mat.blending = SubtractiveBlending;
+
+			break;
+
+		case "multiply":
+
+			mat.blending = MultiplyBlending;
+
+			break;
+
+		case "screen":
+
+			mat.blending = CustomBlending;
+			mat.blendSrc = OneFactor;
+			mat.blendDst = OneMinusSrcColorFactor;
+			mat.blendEquation = AddEquation;
+
+			break;
+
+	}
+
+	mat.transparent = true;
+
+};
+
+SEA3D.prototype.readMaterial = function ( sea ) {
+
+	var mat = this.createMaterial( sea );
+	mat.name = sea.name;
+
+	mat.lights = sea.receiveLights;
+	mat.fog = sea.receiveFog;
+
+	mat.depthWrite = sea.depthWrite;
+	mat.depthTest = sea.depthTest;
+
+	mat.premultipliedAlpha = sea.premultipliedAlpha;
+
+	mat.side = sea.doubleSided ? DoubleSide : FrontSide;
+
+	this.setBlending( mat, sea.blendMode );
+
+	for ( var i = 0; i < sea.technique.length; i ++ ) {
+
+		var tech = sea.technique[ i ];
+
+		if ( this.materialTechnique[ tech.kind ] ) {
+
+			this.materialTechnique[ tech.kind ].call( this, mat, tech, sea );
+
+		}
+
+	}
+
+	if ( this.materialTechnique.onComplete ) {
+
+		this.materialTechnique.onComplete.call( this, mat, sea );
+
+	}
+
+	this.domain.materials = this.materials = this.materials || [];
+	this.materials.push( this.objects[ "mat/" + sea.name ] = sea.tag = mat );
+
+};
+
+//
+//	Point Light
+//
+
+SEA3D.prototype.readPointLight = function ( sea ) {
+
+	var light = new SEA3D.PointLight( sea.color, sea.multiplier * this.config.multiplier );
+	light.name = sea.name;
+
+	if ( sea.attenuation ) {
+
+		light.distance = sea.attenuation.end;
+
+	}
+
+	if ( sea.shadow ) this.setShadowMap( light );
+
+	this.domain.lights = this.lights = this.lights || [];
+	this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light );
+
+	this.addSceneObject( sea );
+
+	this.updateTransform( light, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.LightAnimator );
+
+	this.updateScene();
+
+};
+
+//
+//	Hemisphere Light
+//
+
+SEA3D.prototype.readHemisphereLight = function ( sea ) {
+
+	var light = new HemisphereLight( sea.color, sea.secondColor, sea.multiplier * this.config.multiplier );
+	light.position.set( 0, 500, 0 );
+	light.name = sea.name;
+
+	this.domain.lights = this.lights = this.lights || [];
+	this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light );
+
+	this.addSceneObject( sea );
+
+	this.addDefaultAnimation( sea, SEA3D.LightAnimator );
+
+	this.updateScene();
+
+};
+
+//
+//	Ambient Light
+//
+
+SEA3D.prototype.readAmbientLight = function ( sea ) {
+
+	var light = new AmbientLight( sea.color, sea.multiplier * this.config.multiplier );
+	light.name = sea.name;
+
+	this.domain.lights = this.lights = this.lights || [];
+	this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light );
+
+	this.addSceneObject( sea );
+
+	this.addDefaultAnimation( sea, SEA3D.LightAnimator );
+
+	this.updateScene();
+
+};
+
+//
+//	Directional Light
+//
+
+SEA3D.prototype.readDirectionalLight = function ( sea ) {
+
+	var light = new DirectionalLight( sea.color, sea.multiplier * this.config.multiplier );
+	light.name = sea.name;
+
+	if ( sea.shadow ) {
+
+		this.setShadowMap( light );
+
+	}
+
+	this.domain.lights = this.lights = this.lights || [];
+	this.lights.push( this.objects[ "lht/" + sea.name ] = sea.tag = light );
+
+	this.addSceneObject( sea );
+
+	this.updateTransform( light, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.LightAnimator );
+
+	this.updateScene();
+
+};
+
+//
+//	Camera
+//
+
+SEA3D.prototype.readCamera = function ( sea ) {
+
+	var camera = new SEA3D.Camera( sea.fov );
+	camera.name = sea.name;
+
+	this.domain.cameras = this.cameras = this.cameras || [];
+	this.cameras.push( this.objects[ "cam/" + sea.name ] = sea.tag = camera );
+
+	this.addSceneObject( sea );
+	this.updateTransform( camera, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.CameraAnimator );
+
+};
+
+//
+//	Orthographic Camera
+//
+
+SEA3D.prototype.readOrthographicCamera = function ( sea ) {
+
+	var aspect, width, height;
+
+	var stageWidth = this.config.stageWidth !== undefined ? this.config.stageWidth : ( window ? window.innerWidth : 1024 );
+	var stageHeight = this.config.stageHeight !== undefined ? this.config.stageHeight : ( window ? window.innerHeight : 1024 );
+
+	if ( stageWidth > stageHeight ) {
+
+		aspect = stageWidth / stageHeight;
+
+		width = sea.height * aspect;
+		height = sea.height;
+
+	} else {
+
+		aspect = stageHeight / stageWidth;
+
+		width = sea.height;
+		height = sea.height * aspect;
+
+	}
+
+	var camera = new SEA3D.OrthographicCamera( - width, width, height, - height );
+	camera.name = sea.name;
+
+	this.domain.cameras = this.cameras = this.cameras || [];
+	this.cameras.push( this.objects[ "cam/" + sea.name ] = sea.tag = camera );
+
+	this.addSceneObject( sea );
+	this.updateTransform( camera, sea );
+
+	this.addDefaultAnimation( sea, SEA3D.CameraAnimator );
+
+};
+
+//
+//	Skeleton
+//
+
+SEA3D.prototype.getSkeletonFromBones = function ( bonesData ) {
+
+	var bones = [], bone, gbone;
+	var i, il;
+
+	for ( i = 0, il = bonesData.length; i < il; i ++ ) {
+
+		gbone = bonesData[ i ];
+
+		bone = new Bone();
+		bones.push( bone );
+
+		bone.name = gbone.name;
+		bone.position.fromArray( gbone.pos );
+		bone.quaternion.fromArray( gbone.rotq );
+
+		if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
+
+	}
+
+	for ( i = 0, il = bonesData.length; i < il; i ++ ) {
+
+		gbone = bonesData[ i ];
+
+		if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
+
+			bones[ gbone.parent ].add( bones[ i ] );
+
+		}
+
+	}
+
+	return new Skeleton( bones );
+
+};
+
+SEA3D.prototype.readSkeletonLocal = function ( sea ) {
+
+	var bones = [];
+
+	for ( var i = 0; i < sea.joint.length; i ++ ) {
+
+		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
+		};
+
+	}
+
+	this.domain.bones = this.bones = this.bones || [];
+	this.bones.push( this.objects[ sea.name + '.sklq' ] = sea.tag = bones );
+
+};
+
+//
+//	Joint Object
+//
+
+SEA3D.prototype.readJointObject = function ( sea ) {
+
+	var mesh = sea.target.tag,
+		bone = mesh.skeleton.bones[ sea.joint ];
+
+	this.domain.joints = this.joints = this.joints || [];
+	this.joints.push( this.objects[ "jnt/" + sea.name ] = sea.tag = bone );
+
+};
+
+//
+//	Morph
+//
+
+SEA3D.prototype.readMorph = function ( sea ) {
+
+	var attribs = { position: [] }, targets = [];
+
+	for ( var i = 0; i < sea.node.length; i ++ ) {
+
+		var node = sea.node[ i ];
+
+		attribs.position[ i ] = new Float32BufferAttribute( node.vertex, 3 );
+		attribs.position[ i ].name = node.name;
+
+		if ( node.normal ) {
+
+			attribs.normal = attribs.normal || [];
+			attribs.normal[ i ] = new Float32BufferAttribute( node.normal, 3 );
+
+		}
+
+		targets[ i ] = { name: node.name };
+
+	}
+
+	sea.tag = {
+		attribs: attribs,
+		targets: targets
+	};
+
+};
+
+//
+//	Animation
+//
+
+SEA3D.prototype.readAnimation = function ( sea ) {
+
+	var animations = [], delta = ( 1000 / sea.frameRate ) / 1000;
+
+	for ( var i = 0; i < sea.sequence.length; i ++ ) {
+
+		var seq = sea.sequence[ i ];
+
+		var tracks = [];
+
+		for ( var j = 0; j < sea.dataList.length; j ++ ) {
+
+			var anm = sea.dataList[ j ],
+				t, k, times, values,
+				data = anm.data,
+				start = seq.start * anm.blockSize,
+				end = start + ( seq.count * anm.blockSize ),
+				intrpl = seq.intrpl ? InterpolateLinear : false,
+				name = null;
+
+			switch ( anm.kind ) {
+
+				case SEA3DSDK.Animation.POSITION:
+
+					name = '.position';
+
+					break;
+
+				case SEA3DSDK.Animation.ROTATION:
+
+					name = '.quaternion';
+
+					break;
+
+				case SEA3DSDK.Animation.SCALE:
+
+					name = '.scale';
+
+					break;
+
+				case SEA3DSDK.Animation.COLOR:
+
+					name = '.color';
+
+					break;
+
+				case SEA3DSDK.Animation.MULTIPLIER:
+
+					name = '.intensity';
+
+					break;
+
+				case SEA3DSDK.Animation.FOV:
+
+					name = '.fov';
+
+					break;
+
+				case SEA3DSDK.Animation.OFFSET_U:
+
+					name = '.offset[x]';
+
+					break;
+
+				case SEA3DSDK.Animation.OFFSET_V:
+
+					name = '.offset[y]';
+
+					break;
+
+				case SEA3DSDK.Animation.SCALE_U:
+
+					name = '.repeat[x]';
+
+					break;
+
+				case SEA3DSDK.Animation.SCALE_V:
+
+					name = '.repeat[y]';
+
+					break;
+
+				case SEA3DSDK.Animation.RADIAN:
+
+					name = '.rotation';
+
+					break;
+
+				case SEA3DSDK.Animation.MORPH:
+
+					name = '.morphTargetInfluences[' + anm.name + ']';
+
+					break;
+
+			}
+
+			if ( ! name ) continue;
+
+			switch ( anm.type ) {
+
+				case SEA3DSDK.Stream.BYTE:
+				case SEA3DSDK.Stream.UBYTE:
+				case SEA3DSDK.Stream.INT:
+				case SEA3DSDK.Stream.UINT:
+				case SEA3DSDK.Stream.FLOAT:
+				case SEA3DSDK.Stream.DOUBLE:
+				case SEA3DSDK.Stream.DECIMAL:
+
+					values = data.subarray( start, end );
+					times = new Float32Array( values.length );
+					t = 0;
+
+					for ( k = 0; k < times.length; k ++ ) {
+
+						times[ k ] = t;
+						t += delta;
+
+					}
+
+					tracks.push( new NumberKeyframeTrack( name, times, values, intrpl ) );
+
+					break;
+
+				case SEA3DSDK.Stream.VECTOR3D:
+
+					values = data.subarray( start, end );
+					times = new Float32Array( values.length / anm.blockSize );
+					t = 0;
+
+					for ( k = 0; k < times.length; k ++ ) {
+
+						times[ k ] = t;
+						t += delta;
+
+					}
+
+					tracks.push( new VectorKeyframeTrack( name, times, values, intrpl ) );
+
+					break;
+
+				case SEA3DSDK.Stream.VECTOR4D:
+
+					values = data.subarray( start, end );
+					times = new Float32Array( values.length / anm.blockSize );
+					t = 0;
+
+					for ( k = 0; k < times.length; k ++ ) {
+
+						times[ k ] = t;
+						t += delta;
+
+					}
+
+					tracks.push( new QuaternionKeyframeTrack( name, times, values, intrpl ) );
+
+					break;
+
+				case SEA3DSDK.Stream.INT24:
+				case SEA3DSDK.Stream.UINT24:
+
+					values = new Float32Array( ( end - start ) * 3 );
+					times = new Float32Array( values.length / 3 );
+					t = 0;
+
+					for ( k = 0; k < times.length; k ++ ) {
+
+						values[ ( k * 3 ) ] = ( ( data[ k ] >> 16 ) & 0xFF ) / 255;
+						values[ ( k * 3 ) + 1 ] = ( ( data[ k ] >> 8 ) & 0xFF ) / 255;
+						values[ ( k * 3 ) + 2 ] = ( data[ k ] & 0xFF ) / 255;
+						times[ k ] = t;
+						t += delta;
+
+					}
+
+					tracks.push( new VectorKeyframeTrack( name, times, values, intrpl ) );//ColorKeyframeTrack
+
+					break;
+
+			}
+
+		}
+
+		animations.push( new SEA3D.AnimationClip( seq.name, - 1, tracks, seq.repeat ) );
+
+	}
+
+	this.domain.clips = this.clips = this.clips || [];
+	this.clips.push( this.objects[ sea.name + '.anm' ] = sea.tag = animations );
+
+};
+
+//
+//	Skeleton Animation
+//
+
+SEA3D.prototype.readSkeletonAnimation = function ( sea, skl ) {
+
+	skl = ! skl && sea.metadata && sea.metadata.skeleton ? sea.metadata.skeleton : skl;
+
+	if ( ! skl || sea.tag ) return sea.tag;
+
+	var animations = [], delta = ( 1000 / sea.frameRate ) / 1000;
+
+	for ( var i = 0; i < sea.sequence.length; i ++ ) {
+
+		var seq = sea.sequence[ i ];
+
+		var start = seq.start;
+		var end = start + seq.count;
+
+		var animation = {
+			name: seq.name,
+			fps: sea.frameRate,
+			length: delta * seq.count,
+			hierarchy: []
+		};
+
+		var numJoints = sea.numJoints,
+			raw = sea.raw;
+
+		for ( var j = 0; j < numJoints; j ++ ) {
+
+			var bone = skl.joint[ j ],
+				node = { parent: bone.parentIndex, keys: [] },
+				keys = node.keys,
+				time = 0;
+
+			for ( var frame = start; frame < end; frame ++ ) {
+
+				var idx = ( frame * numJoints * 7 ) + ( j * 7 );
+
+				keys.push( {
+					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: [ 1, 1, 1 ]
+				} );
+
+				time += delta;
+
+			}
+
+			animation.hierarchy[ j ] = node;
+
+		}
+
+		animations.push( SEA3D.AnimationClip.fromClip( AnimationClip.parseAnimation( animation, skl.tag ), seq.repeat ) );
+
+	}
+
+	this.domain.clips = this.clips = this.clips || [];
+	this.clips.push( this.objects[ sea.name + '.skla' ] = sea.tag = animations );
+
+};
+
+//
+//	Vertex Animation
+//
+
+SEA3D.prototype.readVertexAnimation = function ( sea ) {
+
+	var attribs = { position: [] }, targets = [], animations = [], i, j, l;
+
+	for ( i = 0, l = sea.frame.length; i < l; i ++ ) {
+
+		var frame = sea.frame[ i ];
+
+		attribs.position[ i ] = new Float32BufferAttribute( frame.vertex, 3 );
+
+		if ( frame.normal ) {
+
+			attribs.normal = attribs.normal || [];
+			attribs.normal[ i ] = new Float32BufferAttribute( frame.normal, 3 );
+
+		}
+
+		targets[ i ] = { name: i };
+
+	}
+
+	for ( i = 0; i < sea.sequence.length; i ++ ) {
+
+		var seq = sea.sequence[ i ];
+		var seqTargets = [];
+
+		for ( j = 0; j < seq.count; j ++ ) {
+
+			seqTargets[ j ] = targets[ seq.start + j ];
+
+		}
+
+		animations.push( SEA3D.AnimationClip.fromClip( AnimationClip.CreateFromMorphTargetSequence( seq.name, seqTargets, sea.frameRate, !seq.repeat ), seq.repeat ) );
+
+	}
+
+	sea.tag = {
+		attribs: attribs,
+		targets: targets,
+		animations: animations
+	};
+
+	this.domain.clips = this.clips = this.clips || [];
+	this.clips.push( this.objects[ sea.name + '.vtxa' ] = sea.tag );
+
+};
+
+//
+//	Selector
+//
+
+SEA3D.prototype.getModifier = function ( req ) {
+
+	var sea = req.sea;
+
+	switch ( sea.type ) {
+
+		case SEA3DSDK.SkeletonAnimation.prototype.type:
+
+			this.readSkeletonAnimation( sea, req.skeleton );
+
+			break;
+
+		case SEA3DSDK.Animation.prototype.type:
+		case SEA3DSDK.MorphAnimation.prototype.type:
+		case SEA3DSDK.UVWAnimation.prototype.type:
+
+			this.readAnimation( sea );
+
+			break;
+
+		case SEA3DSDK.Morph.prototype.type:
+
+			this.readMorph( sea, req.geometry );
+
+			break;
+
+	}
+
+	return sea.tag;
+
+};
+
+//
+//	Actions
+//
+
+SEA3D.prototype.applyEnvironment = function ( envMap ) {
+
+	for ( var j = 0, l = this.materials.length; j < l; ++ j ) {
+
+		var mat = this.materials[ j ];
+
+		if ( mat instanceof MeshStandardMaterial ) {
+
+			if ( mat.envMap ) continue;
+
+			mat.envMap = envMap;
+			mat.envMap.mapping = CubeReflectionMapping;
+
+			mat.needsUpdate = true;
+
+		}
+
+	}
+
+};
+
+SEA3D.prototype.readActions = function ( sea ) {
+
+	for ( var i = 0; i < sea.actions.length; i ++ ) {
+
+		var act = sea.actions[ i ];
+
+		switch ( act.kind ) {
+
+			case SEA3DSDK.Actions.ATTRIBUTES:
+
+				this.attribs = this.domain.attribs = act.attributes.tag;
+
+				break;
+
+			case SEA3DSDK.Actions.SCRIPTS:
+
+				this.domain.scripts = this.getJSMList( this.domain, act.scripts );
+
+				if ( this.config.scripts && this.config.runScripts ) this.domain.runJSMList( this.domain );
+
+				break;
+
+			case SEA3DSDK.Actions.CAMERA:
+
+				this.domain.camera = this.camera = act.camera.tag;
+
+				break;
+
+			case SEA3DSDK.Actions.ENVIRONMENT_COLOR:
+
+				this.domain.background = this.background = this.background || {};
+
+				this.background.color = new Color( act.color );
+
+				break;
+
+			case SEA3DSDK.Actions.ENVIRONMENT:
+
+				this.domain.background = this.background = this.background || {};
+
+				this.background.texture = act.texture.tag;
+
+				if ( this.config.useEnvironment && this.materials != undefined ) {
+
+					this.applyEnvironment( act.texture.tag );
+
+				}
+
+				break;
+
+		}
+
+	}
+
+};
+
+//
+//	Properties
+//
+
+SEA3D.prototype.updatePropertiesAssets = function ( sea, props ) {
+
+	for ( var name in props ) {
+
+		switch ( props.__type[ name ] ) {
+
+			case SEA3DSDK.Stream.ASSET:
+
+				if ( ! props.__asset ) props.__asset = {};
+				if ( ! props.__asset[ name ] ) props.__asset[ name ] = props[ name ];
+
+				props[ name ] = props.__asset[ name ].tag;
+
+				break;
+
+			case SEA3DSDK.Stream.GROUP:
+
+				props[ name ] = this.updatePropertiesAssets( sea, props[ name ] );
+
+				break;
+
+		}
+
+	}
+
+	return props;
+
+};
+
+SEA3D.prototype.readProperties = function ( sea ) {
+
+	var props = this.updatePropertiesAssets( sea, sea.props );
+
+	this.domain.properties = this.properties = this.properties || [];
+	this.properties.push( this.objects[ "prop/" + sea.name ] = sea.tag = props );
+
+};
+
+SEA3D.prototype.readFileInfo = function ( sea ) {
+
+	this.domain.info = this.updatePropertiesAssets( sea, sea.info );
+
+};
+
+//
+//	Events
+//
+
+SEA3D.Event = {
+	PROGRESS: "sea3d_progress",
+	LOAD_PROGRESS: "sea3d_load",
+	DOWNLOAD_PROGRESS: "sea3d_download",
+	COMPLETE: "sea3d_complete",
+	OBJECT_COMPLETE: "sea3d_object",
+	PARSE_PROGRESS: "parse_progress",
+	PARSE_COMPLETE: "parse_complete",
+	ERROR: "sea3d_error"
+};
+
+SEA3D.prototype.onProgress = function ( e ) {
+
+	e.status = e.type;
+	e.progress = e.loaded / e.total;
+	e.type = SEA3D.Event.PROGRESS;
+
+	this.dispatchEvent( e );
+
+};
+
+SEA3D.prototype.onLoadProgress = function ( e ) {
+
+	e.type = SEA3D.Event.LOAD_PROGRESS;
+	this.dispatchEvent( e );
+
+	this.onProgress( e );
+
+};
+
+SEA3D.prototype.onDownloadProgress = function ( e ) {
+
+	e.type = SEA3D.Event.DOWNLOAD_PROGRESS;
+	this.dispatchEvent( e );
+
+	this.onProgress( e );
+
+};
+
+SEA3D.prototype.onComplete = function ( e ) {
+
+	e.type = SEA3D.Event.COMPLETE;
+	this.dispatchEvent( e );
+
+};
+
+SEA3D.prototype.onCompleteObject = function ( e ) {
+
+	e.type = SEA3D.Event.OBJECT_COMPLETE;
+	this.dispatchEvent( e );
+
+};
+
+SEA3D.prototype.onParseProgress = function ( e ) {
+
+	e.type = SEA3D.Event.PARSE_PROGRESS;
+	this.dispatchEvent( e );
+
+};
+
+SEA3D.prototype.onParseComplete = function ( e ) {
+
+	e.type = SEA3D.Event.PARSE_COMPLETE;
+	this.dispatchEvent( e );
+
+};
+
+SEA3D.prototype.onError = function ( e ) {
+
+	e.type = SEA3D.Event.ERROR;
+	this.dispatchEvent( e );
+
+};
+
+//
+//	Loader
+//
+
+SEA3D.prototype.createDomain = function () {
+
+	return this.domain = new SEA3D.Domain(
+		this.config.id,
+		this.objects = {},
+		this.config.container
+	);
+
+};
+
+SEA3D.prototype.clone = function ( config, onParseComplete, onParseProgress ) {
+
+	if ( ! this.file.isDone() ) throw new Error( "Previous parse is not completed." );
+
+	this.config.container = config && config.container !== undefined ? config.container : new Object3D();
+
+	if ( config ) this.loadConfig( config );
+
+	var timeLimit = this.config.timeLimit;
+
+	this.config.timeLimit = config && config.timeLimit !== undefined ? config.timeLimit : Infinity;
+
+	this.parse( onParseComplete, onParseProgress );
+
+	this.config.timeLimit = timeLimit;
+
+	return this.domain;
+
+};
+
+SEA3D.prototype.loadConfig = function ( config ) {
+
+	for ( var name in config ) {
+
+		this.config[ name ] = config[ name ];
+
+	}
+
+};
+
+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.sprites;
+	delete this.sounds3d;
+	delete this.cubeRenderers;
+	delete this.sounds;
+	delete this.glsl;
+	delete this.dummy;
+	delete this.camera;
+	delete this.background;
+	delete this.properties;
+	delete this.scriptTargets;
+
+	delete this.domain;
+
+	this.createDomain();
+
+	this.setTypeRead();
+
+	this.file.onParseComplete = ( function ( e ) {
+
+		if ( this.config.manager ) this.config.manager.add( this.domain );
+
+		( onParseComplete || this.onParseComplete ).call( this, e );
+
+	} ).bind( this );
+
+	this.file.onParseProgress = onParseProgress || this.onParseProgress;
+
+	// EXTENSIONS
+
+	var i = SEA3D.EXTENSIONS_LOADER.length;
+
+	while ( i -- ) {
+
+		var loader = SEA3D.EXTENSIONS_LOADER[ i ];
+
+		if ( loader.parse ) loader.parse.call( this );
+
+	}
+
+	this.file.parse();
+
+	return this.domain;
+
+};
+
+SEA3D.prototype.onHead = function ( args ) {
+
+	if ( args.sign != 'TJS' ) {
+
+		throw new Error( "Sign '" + args.sign + "' not supported! Use SEA3D Studio to publish or SEA3DLegacy.js" );
+
+	}
+
+};
+
+SEA3D.EXTENSIONS_LOADER = [];
+SEA3D.EXTENSIONS_DOMAIN = [];
+
+SEA3D.prototype.setTypeRead = function () {
+
+	this.file.typeRead = {};
+
+	this.file.typeRead[ SEA3DSDK.Geometry.prototype.type ] = this.readGeometryBuffer;
+	this.file.typeRead[ SEA3DSDK.Mesh.prototype.type ] = this.readMesh;
+	this.file.typeRead[ SEA3DSDK.Sprite.prototype.type ] = this.readSprite;
+	this.file.typeRead[ SEA3DSDK.Container3D.prototype.type ] = this.readContainer3D;
+	this.file.typeRead[ SEA3DSDK.Line.prototype.type ] = this.readLine;
+	this.file.typeRead[ SEA3DSDK.Material.prototype.type ] = this.readMaterial;
+	this.file.typeRead[ SEA3DSDK.Camera.prototype.type ] = this.readCamera;
+	this.file.typeRead[ SEA3DSDK.OrthographicCamera.prototype.type ] = this.readOrthographicCamera;
+	this.file.typeRead[ SEA3DSDK.SkeletonLocal.prototype.type ] = this.readSkeletonLocal;
+	this.file.typeRead[ SEA3DSDK.SkeletonAnimation.prototype.type ] = this.readSkeletonAnimation;
+	this.file.typeRead[ SEA3DSDK.JointObject.prototype.type ] = this.readJointObject;
+	this.file.typeRead[ SEA3DSDK.CubeMap.prototype.type ] = this.readCubeMap;
+	this.file.typeRead[ SEA3DSDK.CubeRender.prototype.type ] = this.readCubeRender;
+	this.file.typeRead[ SEA3DSDK.Animation.prototype.type ] =
+	this.file.typeRead[ SEA3DSDK.MorphAnimation.prototype.type ] =
+	this.file.typeRead[ SEA3DSDK.UVWAnimation.prototype.type ] = this.readAnimation;
+	this.file.typeRead[ SEA3DSDK.SoundPoint.prototype.type ] = this.readSoundPoint;
+	this.file.typeRead[ SEA3DSDK.TextureURL.prototype.type ] = this.readTextureURL;
+	this.file.typeRead[ SEA3DSDK.CubeMapURL.prototype.type ] = this.readCubeMapURL;
+	this.file.typeRead[ SEA3DSDK.AssetUpdate.prototype.type ] = this.readAssetUpdate;
+	this.file.typeRead[ SEA3DSDK.Morph.prototype.type ] = this.readMorph;
+	this.file.typeRead[ SEA3DSDK.VertexAnimation.prototype.type ] = this.readVertexAnimation;
+	this.file.typeRead[ SEA3DSDK.Actions.prototype.type ] = this.readActions;
+	this.file.typeRead[ SEA3DSDK.FileInfo.prototype.type ] = this.readFileInfo;
+	this.file.typeRead[ SEA3DSDK.Properties.prototype.type ] = this.readProperties;
+
+	if ( this.config.dummys ) {
+
+		this.file.typeRead[ SEA3DSDK.Dummy.prototype.type ] = this.readDummy;
+
+	}
+
+	if ( this.config.scripts ) {
+
+		this.file.typeRead[ SEA3DSDK.ScriptURL.prototype.type ] = this.readScriptURL;
+		this.file.typeRead[ SEA3DSDK.JavaScriptMethod.prototype.type ] = this.readJavaScriptMethod;
+
+	}
+
+	if ( this.config.lights ) {
+
+		this.file.typeRead[ SEA3DSDK.PointLight.prototype.type ] = this.readPointLight;
+		this.file.typeRead[ SEA3DSDK.DirectionalLight.prototype.type ] = this.readDirectionalLight;
+		this.file.typeRead[ SEA3DSDK.HemisphereLight.prototype.type ] = this.readHemisphereLight;
+		this.file.typeRead[ SEA3DSDK.AmbientLight.prototype.type ] = this.readAmbientLight;
+
+	}
+
+	// UNIVERSAL
+
+	this.file.typeRead[ SEA3DSDK.JPEG.prototype.type ] =
+	this.file.typeRead[ SEA3DSDK.JPEG_XR.prototype.type ] =
+	this.file.typeRead[ SEA3DSDK.PNG.prototype.type ] =
+	this.file.typeRead[ SEA3DSDK.GIF.prototype.type ] = this.readTexture;
+	this.file.typeRead[ SEA3DSDK.MP3.prototype.type ] = this.readSound;
+	this.file.typeRead[ SEA3DSDK.GLSL.prototype.type ] = this.readGLSL;
+
+	// EXTENSIONS
+
+	var i = SEA3D.EXTENSIONS_LOADER.length;
+
+	while ( i -- ) {
+
+		var loader = SEA3D.EXTENSIONS_LOADER[ i ];
+
+		if ( loader.setTypeRead ) loader.setTypeRead.call( this );
+
+	}
+
+};
+
+SEA3D.prototype.load = function ( data ) {
+
+	this.file = new SEA3DSDK.File();
+	this.file.scope = this;
+	this.file.config = this.config;
+	this.file.onProgress = this.onLoadProgress.bind( this );
+	this.file.onCompleteObject = this.onCompleteObject.bind( this );
+	this.file.onDownloadProgress = this.onDownloadProgress.bind( this );
+	this.file.onParseProgress = this.onParseProgress.bind( this );
+	this.file.onParseComplete = this.onParseComplete.bind( this );
+	this.file.onError = this.onError.bind( this );
+	this.file.onHead = this.onHead.bind( this );
+
+	this.file.onComplete = ( function ( e ) {
+
+		if ( this.config.manager ) this.config.manager.add( this.domain );
+
+		this.onComplete.call( this, e );
+
+	} ).bind( this );
+
+	// SEA3D
+
+	this.createDomain();
+
+	this.setTypeRead();
+
+	if ( data === undefined ) return;
+
+	if ( typeof data === "string" ) this.file.load( data );
+	else this.file.read( data );
+
+};
+
+export { SEA3D };

+ 3355 - 0
examples/jsm/loaders/sea3d/SEA3DSDK.js

@@ -0,0 +1,3355 @@
+/**
+ * 	SEA3DSDK
+ * 	@author Sunag / http://www.sunag.com.br/
+ */
+
+'use strict';
+
+var SEA3DSDK = { VERSION: 18110 };
+
+SEA3DSDK.getVersion = function () {
+
+	// Max = 16777215 - VV.S.S.BB  | V = Version | S = Subversion | B = Buildversion
+	var v = SEA3DSDK.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 ' + SEA3DSDK.getVersion() );
+
+//
+//	STREAM : STANDARD DATA-IO ( LITTLE-ENDIAN )
+//
+
+SEA3DSDK.Stream = function ( buffer ) {
+
+	this.position = 0;
+	this.buffer = buffer || new ArrayBuffer();
+
+};
+
+SEA3DSDK.Stream.NONE = 0;
+
+// 1D = 0 at 31
+SEA3DSDK.Stream.BOOLEAN = 1;
+
+SEA3DSDK.Stream.BYTE = 2;
+SEA3DSDK.Stream.UBYTE = 3;
+
+SEA3DSDK.Stream.SHORT = 4;
+SEA3DSDK.Stream.USHORT = 5;
+
+SEA3DSDK.Stream.INT24 = 6;
+SEA3DSDK.Stream.UINT24 = 7;
+
+SEA3DSDK.Stream.INT = 8;
+SEA3DSDK.Stream.UINT = 9;
+
+SEA3DSDK.Stream.FLOAT = 10;
+SEA3DSDK.Stream.DOUBLE = 11;
+SEA3DSDK.Stream.DECIMAL = 12;
+
+// 2D = 32 at 63
+
+// 3D = 64 at 95
+SEA3DSDK.Stream.VECTOR3D = 74;
+
+// 4D = 96 at 127
+SEA3DSDK.Stream.VECTOR4D = 106;
+
+// Undefined Size = 128 at 255
+SEA3DSDK.Stream.STRING_TINY = 128;
+SEA3DSDK.Stream.STRING_SHORT = 129;
+SEA3DSDK.Stream.STRING_LONG = 130;
+
+SEA3DSDK.Stream.ASSET = 200;
+SEA3DSDK.Stream.GROUP = 255;
+
+SEA3DSDK.Stream.BLEND_MODE = [
+	"normal", "add", "subtract", "multiply", "dividing", "mix", "alpha", "screen", "darken",
+	"overlay", "colorburn", "linearburn", "lighten", "colordodge", "lineardodge",
+	"softlight", "hardlight", "pinlight", "spotlight", "spotlightblend", "hardmix",
+	"average", "difference", "exclusion", "hue", "saturation", "color", "value",
+	"linearlight", "grainextract", "reflect", "glow", "darkercolor", "lightercolor", "phoenix", "negation"
+];
+
+SEA3DSDK.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"
+];
+
+SEA3DSDK.Stream.sizeOf = function ( kind ) {
+
+	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;
+
+};
+
+SEA3DSDK.Stream.prototype = {
+
+	constructor: SEA3DSDK.Stream,
+
+	set buffer( val ) {
+
+		this.buf = val;
+		this.data = new DataView( val );
+
+	},
+
+	get buffer() {
+
+		return this.buf;
+
+	},
+
+	get bytesAvailable() {
+
+		return this.length - this.position;
+
+	},
+
+	get length() {
+
+		return this.buf.byteLength;
+
+	}
+
+};
+
+SEA3DSDK.Stream.prototype.getByte = function ( pos ) {
+
+	return this.data.getInt8( pos );
+
+};
+
+SEA3DSDK.Stream.prototype.readBytes = function ( len ) {
+
+	var buf = this.buf.slice( this.position, this.position + len );
+	this.position += len;
+	return buf;
+
+};
+
+SEA3DSDK.Stream.prototype.readByte = function () {
+
+	return this.data.getInt8( this.position ++ );
+
+};
+
+SEA3DSDK.Stream.prototype.readUByte = function () {
+
+	return this.data.getUint8( this.position ++ );
+
+};
+
+SEA3DSDK.Stream.prototype.readBool = function () {
+
+	return this.data.getInt8( this.position ++ ) != 0;
+
+};
+
+SEA3DSDK.Stream.prototype.readShort = function () {
+
+	var v = this.data.getInt16( this.position, true );
+	this.position += 2;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUShort = function () {
+
+	var v = this.data.getUint16( this.position, true );
+	this.position += 2;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUInt24 = function () {
+
+	var v = this.data.getUint32( this.position, true ) & 0xFFFFFF;
+	this.position += 3;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUInt24F = function () {
+
+	return this.readUShort() | ( this.readUByte() << 16 );
+
+};
+
+SEA3DSDK.Stream.prototype.readInt = function () {
+
+	var v = this.data.getInt32( this.position, true );
+	this.position += 4;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUInt = function () {
+
+	var v = this.data.getUint32( this.position, true );
+	this.position += 4;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readFloat = function () {
+
+	var v = this.data.getFloat32( this.position, true );
+	this.position += 4;
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUInteger = function () {
+
+	var v = this.readUByte(),
+		r = v & 0x7F;
+
+	if ( ( v & 0x80 ) != 0 ) {
+
+		v = this.readUByte();
+		r |= ( v & 0x7F ) << 7;
+
+		if ( ( v & 0x80 ) != 0 ) {
+
+			v = this.readUByte();
+			r |= ( v & 0x7F ) << 13;
+
+		}
+
+	}
+
+	return r;
+
+};
+
+SEA3DSDK.Stream.prototype.readVector2 = function () {
+
+	return { x: this.readFloat(), y: this.readFloat() };
+
+};
+
+SEA3DSDK.Stream.prototype.readVector3 = function () {
+
+	return { x: this.readFloat(), y: this.readFloat(), z: this.readFloat() };
+
+};
+
+SEA3DSDK.Stream.prototype.readVector4 = function () {
+
+	return { x: this.readFloat(), y: this.readFloat(), z: this.readFloat(), w: this.readFloat() };
+
+};
+
+SEA3DSDK.Stream.prototype.readMatrix = function () {
+
+	var mtx = new Float32Array( 16 );
+
+	mtx[ 0 ] = this.readFloat();
+	mtx[ 1 ] = this.readFloat();
+	mtx[ 2 ] = this.readFloat();
+	mtx[ 3 ] = 0.0;
+	mtx[ 4 ] = this.readFloat();
+	mtx[ 5 ] = this.readFloat();
+	mtx[ 6 ] = this.readFloat();
+	mtx[ 7 ] = 0.0;
+	mtx[ 8 ] = this.readFloat();
+	mtx[ 9 ] = this.readFloat();
+	mtx[ 10 ] = this.readFloat();
+	mtx[ 11 ] = 0.0;
+	mtx[ 12 ] = this.readFloat();
+	mtx[ 13 ] = this.readFloat();
+	mtx[ 14 ] = this.readFloat();
+	mtx[ 15 ] = 1.0;
+
+	return mtx;
+
+};
+
+SEA3DSDK.Stream.prototype.decodeText = function ( array ) {
+
+	if ( typeof TextDecoder !== 'undefined' ) {
+
+		return new TextDecoder().decode( array );
+
+	}
+
+	// Avoid the String.fromCharCode.apply(null, array) shortcut, which
+	// throws a "maximum call stack size exceeded" error for large arrays.
+
+	var s = '';
+
+	for ( var i = 0, il = array.length; i < il; i ++ ) {
+
+		// Implicitly assumes little-endian.
+		s += String.fromCharCode( array[ i ] );
+
+	}
+
+	// Merges multi-byte utf-8 characters.
+	return decodeURIComponent( escape( s ) );
+
+};
+
+SEA3DSDK.Stream.prototype.readUTF8 = function ( len ) {
+
+	var buffer = this.readBytes( len );
+
+	return this.decodeText( new Uint8Array( buffer ) );
+
+};
+
+SEA3DSDK.Stream.prototype.readExt = function () {
+
+	return this.readUTF8( 4 ).replace( /\0/g, "" );
+
+};
+
+SEA3DSDK.Stream.prototype.readUTF8Tiny = function () {
+
+	return this.readUTF8( this.readUByte() );
+
+};
+
+SEA3DSDK.Stream.prototype.readUTF8Short = function () {
+
+	return this.readUTF8( this.readUShort() );
+
+};
+
+SEA3DSDK.Stream.prototype.readUTF8Long = function () {
+
+	return this.readUTF8( this.readUInt() );
+
+};
+
+SEA3DSDK.Stream.prototype.readUByteArray = function ( length ) {
+
+	var v = new Uint8Array( length );
+
+	SEA3DSDK.Stream.memcpy(
+		v.buffer,
+		0,
+		this.buffer,
+		this.position,
+		length
+	);
+
+	this.position += length;
+
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readUShortArray = function ( length ) {
+
+	var v = new Uint16Array( length ),
+		len = length * 2;
+
+	SEA3DSDK.Stream.memcpy(
+		v.buffer,
+		0,
+		this.buffer,
+		this.position,
+		len
+	);
+
+	this.position += len;
+
+	return v;
+
+};
+
+
+SEA3DSDK.Stream.prototype.readUInt24Array = function ( length ) {
+
+	var v = new Uint32Array( length );
+
+	for ( var i = 0; i < length; i ++ ) {
+
+		v[ i ] = this.readUInt24();
+
+	}
+
+	return v;
+
+};
+
+
+SEA3DSDK.Stream.prototype.readUIntArray = function ( length ) {
+
+	var v = new Uint32Array( length ),
+		len = length * 4;
+
+	SEA3DSDK.Stream.memcpy(
+		v.buffer,
+		0,
+		this.buffer,
+		this.position,
+		len
+	);
+
+	this.position += len;
+
+	return v;
+
+};
+
+SEA3DSDK.Stream.prototype.readFloatArray = function ( length ) {
+
+	var v = new Float32Array( length ),
+		len = length * 4;
+
+	SEA3DSDK.Stream.memcpy(
+		v.buffer,
+		0,
+		this.buffer,
+		this.position,
+		len
+	);
+
+	this.position += len;
+
+	return v;
+
+};
+
+
+SEA3DSDK.Stream.prototype.readBlendMode = function () {
+
+	return SEA3DSDK.Stream.BLEND_MODE[ this.readUByte() ];
+
+};
+
+SEA3DSDK.Stream.prototype.readInterpolation = function () {
+
+	return SEA3DSDK.Stream.INTERPOLATION_TABLE[ this.readUByte() ];
+
+};
+
+SEA3DSDK.Stream.prototype.readTags = function ( callback ) {
+
+	var numTag = this.readUByte();
+
+	for ( var i = 0; i < numTag; ++ i ) {
+
+		var kind = this.readUShort();
+		var size = this.readUInt();
+		var pos = this.position;
+
+		callback( kind, this, size );
+
+		this.position = pos += size;
+
+	}
+
+};
+
+SEA3DSDK.Stream.prototype.readProperties = function ( sea3d ) {
+
+	var count = this.readUByte(),
+		props = {}, types = {};
+
+	props.__type = types;
+
+	for ( var i = 0; i < count; i ++ ) {
+
+		var name = this.readUTF8Tiny(),
+			type = this.readUByte();
+
+		types[ name ] = type;
+		props[ name ] = type === SEA3DSDK.Stream.GROUP ? this.readProperties( sea3d ) : this.readToken( type, sea3d );
+
+	}
+
+	return props;
+
+};
+
+SEA3DSDK.Stream.prototype.readAnimationList = function ( sea3d ) {
+
+	var list = [],
+		count = this.readUByte();
+
+	var i = 0;
+	while ( i < count ) {
+
+		var attrib = this.readUByte(),
+			anm = {};
+
+		anm.relative = ( attrib & 1 ) != 0;
+
+		if ( attrib & 2 ) anm.timeScale = this.readFloat();
+
+		anm.tag = sea3d.getObject( this.readUInt() );
+
+		list[ i ++ ] = anm;
+
+	}
+
+	return list;
+
+};
+
+SEA3DSDK.Stream.prototype.readScriptList = function ( sea3d ) {
+
+	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 = this.readUByte();
+
+			script.params = {};
+
+			for ( var j = 0; j < numParams; j ++ ) {
+
+				var name = this.readUTF8Tiny();
+
+				script.params[ name ] = this.readObject( sea3d );
+
+			}
+
+		}
+
+		if ( attrib & 8 ) {
+
+			script.method = this.readUTF8Tiny();
+
+		}
+
+		script.tag = sea3d.getObject( this.readUInt() );
+
+		list[ i ++ ] = script;
+
+	}
+
+	return list;
+
+};
+
+SEA3DSDK.Stream.prototype.readObject = function ( sea3d ) {
+
+	return this.readToken( this.readUByte(), sea3d );
+
+};
+
+SEA3DSDK.Stream.prototype.readToken = function ( type, sea3d ) {
+
+	switch ( type )	{
+
+		// 1D
+		case SEA3DSDK.Stream.BOOLEAN:
+			return this.readBool();
+			break;
+
+		case SEA3DSDK.Stream.UBYTE:
+			return this.readUByte();
+			break;
+
+		case SEA3DSDK.Stream.USHORT:
+			return this.readUShort();
+			break;
+
+		case SEA3DSDK.Stream.UINT24:
+			return this.readUInt24();
+			break;
+
+		case SEA3DSDK.Stream.INT:
+			return this.readInt();
+			break;
+
+		case SEA3DSDK.Stream.UINT:
+			return this.readUInt();
+			break;
+
+		case SEA3DSDK.Stream.FLOAT:
+			return this.readFloat();
+			break;
+
+		// 3D
+		case SEA3DSDK.Stream.VECTOR3D:
+			return this.readVector3();
+			break;
+
+		// 4D
+		case SEA3DSDK.Stream.VECTOR4D:
+			return this.readVector4();
+			break;
+
+		// Undefined Values
+		case SEA3DSDK.Stream.STRING_TINY:
+			return this.readUTF8Tiny();
+			break;
+
+		case SEA3DSDK.Stream.STRING_SHORT:
+			return this.readUTF8Short();
+			break;
+
+		case SEA3DSDK.Stream.STRING_LONG:
+			return this.readUTF8Long();
+			break;
+
+		case SEA3DSDK.Stream.ASSET:
+			var asset = this.readUInt();
+			return asset > 0 ? sea3d.getObject( asset - 1 ) : null;
+			break;
+
+		default:
+			console.error( "DataType not found!" );
+
+	}
+
+	return null;
+
+};
+
+SEA3DSDK.Stream.prototype.readVector = function ( type, length, offset ) {
+
+	var size = SEA3DSDK.Stream.sizeOf( type ),
+		i = offset * size,
+		count = i + ( length * size );
+
+	switch ( type )	{
+
+		// 1D
+		case SEA3DSDK.Stream.BOOLEAN:
+
+			return this.readUByteArray( count );
+
+
+		case SEA3DSDK.Stream.UBYTE:
+
+			return this.readUByteArray( count );
+
+
+		case SEA3DSDK.Stream.USHORT:
+
+			return this.readUShortArray( count );
+
+
+		case SEA3DSDK.Stream.UINT24:
+
+			return this.readUInt24Array( count );
+
+
+		case SEA3DSDK.Stream.UINT:
+
+			return this.readUIntArray( count );
+
+
+		case SEA3DSDK.Stream.FLOAT:
+
+			return this.readFloatArray( count );
+
+
+		// 3D
+		case SEA3DSDK.Stream.VECTOR3D:
+
+			return this.readFloatArray( count );
+
+
+		// 4D
+		case SEA3DSDK.Stream.VECTOR4D:
+
+			return this.readFloatArray( count );
+
+	}
+
+};
+
+SEA3DSDK.Stream.prototype.append = function ( data ) {
+
+	var buffer = new ArrayBuffer( this.data.byteLength + data.byteLength );
+
+	SEA3DSDK.Stream.memcpy( buffer, 0, this.data.buffer, 0, this.data.byteLength );
+	SEA3DSDK.Stream.memcpy( buffer, this.data.byteLength, data, 0, data.byteLength );
+
+	this.buffer = buffer;
+
+};
+
+SEA3DSDK.Stream.prototype.concat = function ( position, length ) {
+
+	return new SEA3DSDK.Stream( this.buffer.slice( position, position + length ) );
+
+};
+
+/**
+ * @author DataStream.js
+ */
+
+SEA3DSDK.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
+//
+
+SEA3DSDK.UByteArray = function () {
+
+	this.ubytes = [];
+	this.length = 0;
+
+};
+
+SEA3DSDK.UByteArray.prototype = {
+
+	constructor: SEA3DSDK.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
+//
+
+SEA3DSDK.Math = {
+	RAD_TO_DEG: 180 / Math.PI,
+	DEG_TO_RAD: Math.PI / 180
+};
+
+SEA3DSDK.Math.angle = function ( val ) {
+
+	var ang = 180,
+		inv = val < 0;
+
+	val = ( inv ? - val : val ) % 360;
+
+	if ( val > ang ) {
+
+		val = - ang + ( val - ang );
+
+	}
+
+	return ( inv ? - val : val );
+
+};
+
+SEA3DSDK.Math.angleDiff = function ( a, b ) {
+
+	a *= this.DEG_TO_RAD;
+	b *= this.DEG_TO_RAD;
+
+	return Math.atan2( Math.sin( a - b ), Math.cos( a - b ) ) * this.RAD_TO_DEG;
+
+};
+
+SEA3DSDK.Math.angleArea = function ( angle, target, area ) {
+
+	return Math.abs( this.angleDiff( angle, target ) ) <= area;
+
+};
+
+SEA3DSDK.Math.direction = function ( x1, y1, x2, y2 ) {
+
+	return Math.atan2( y2 - y1, x2 - x1 );
+
+};
+
+SEA3DSDK.Math.physicalLerp = function ( val, to, deltaTime, duration ) {
+
+	var t = deltaTime / duration;
+
+	if ( t > 1 ) t = 1;
+
+	return val + ( ( to - val ) * t );
+
+};
+
+SEA3DSDK.Math.physicalAngle = function ( val, to, deltaTime, duration ) {
+
+	if ( Math.abs( val - to ) > 180 ) {
+
+		if ( val > to ) {
+
+			to += 360;
+
+		} else {
+
+			to -= 360;
+
+		}
+
+	}
+
+	var t = deltaTime / duration;
+
+	if ( t > 1 ) t = 1;
+
+	return this.angle( val + ( ( to - val ) * t ) );
+
+};
+
+SEA3DSDK.Math.zero = function ( value, precision ) {
+
+	precision = precision || 1.0E-3;
+
+	var pValue = value < 0 ? - value : value;
+
+	if ( pValue - precision < 0 ) value = 0;
+
+	return value;
+
+};
+
+SEA3DSDK.Math.round = function ( value, precision ) {
+
+	precision = Math.pow( 10, precision );
+
+	return Math.round( value * precision ) / precision;
+
+};
+
+SEA3DSDK.Math.lerpAngle = function ( val, tar, t ) {
+
+	if ( Math.abs( val - tar ) > 180 ) {
+
+		if ( val > tar ) {
+
+			tar += 360;
+
+		} else {
+
+			tar -= 360;
+
+		}
+
+	}
+
+	val += ( tar - val ) * t;
+
+	return SEA3DSDK.Math.angle( val );
+
+};
+
+SEA3DSDK.Math.lerpColor = function ( val, tar, t ) {
+
+	var a0 = val >> 24 & 0xff,
+		r0 = val >> 16 & 0xff,
+		g0 = val >> 8 & 0xff,
+		b0 = val & 0xff;
+
+	var a1 = tar >> 24 & 0xff,
+		r1 = tar >> 16 & 0xff,
+		g1 = tar >> 8 & 0xff,
+		b1 = tar & 0xff;
+
+	a0 += ( a1 - a0 ) * t;
+	r0 += ( r1 - r0 ) * t;
+	g0 += ( g1 - g0 ) * t;
+	b0 += ( b1 - b0 ) * t;
+
+	return a0 << 24 | r0 << 16 | g0 << 8 | b0;
+
+};
+
+SEA3DSDK.Math.lerp = function ( val, tar, t ) {
+
+	return val + ( ( tar - val ) * t );
+
+};
+
+//
+//	Timer
+//
+
+SEA3DSDK.Timer = function () {
+
+	this.time = this.start = Date.now();
+
+};
+
+SEA3DSDK.Timer.prototype = {
+
+	constructor: SEA3DSDK.Timer,
+
+	get now() {
+
+		return Date.now();
+
+	},
+
+	get deltaTime() {
+
+		return Date.now() - this.time;
+
+	},
+
+	get elapsedTime() {
+
+		return Date.now() - this.start;
+
+	},
+
+	update: function () {
+
+		this.time = Date.now();
+
+	}
+};
+
+//
+//	Object
+//
+
+SEA3DSDK.Object = function ( name, data, type, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.type = type;
+	this.sea3d = sea3d;
+
+};
+
+//
+//	Geometry Base
+//
+
+SEA3DSDK.GeometryBase = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUShort();
+
+	this.isBig = ( this.attrib & 1 ) != 0;
+
+	// variable uint
+	data.readVInt = this.isBig ? data.readUInt : data.readUShort;
+
+	this.numVertex = data.readVInt();
+
+	this.length = this.numVertex * 3;
+
+};
+
+//
+//	Geometry
+//
+
+SEA3DSDK.Geometry = function ( name, data, sea3d ) {
+
+	SEA3DSDK.GeometryBase.call( this, name, data, sea3d );
+
+	var i, j, len;
+
+	// NORMAL
+	if ( this.attrib & 4 ) {
+
+		this.normal = data.readFloatArray( this.length );
+
+	}
+
+	// TANGENT
+	if ( this.attrib & 8 ) {
+
+		this.tangent = data.readFloatArray( this.length );
+
+	}
+
+	// UV
+	if ( this.attrib & 32 ) {
+
+		var uvCount = data.readUByte();
+
+		if ( uvCount ) {
+
+			this.uv = [];
+
+			len = this.numVertex * 2;
+
+			i = 0;
+			while ( i < uvCount ) {
+
+				// UV VERTEX DATA
+				this.uv[ i ++ ] = data.readFloatArray( len );
+
+			}
+
+		}
+
+	}
+
+	// JOINT-INDEXES / WEIGHTS
+	if ( this.attrib & 64 ) {
+
+		this.jointPerVertex = data.readUByte();
+
+		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();
+
+		var colorCount = data.readUByte();
+
+		if ( colorCount ) {
+
+			this.numColor = ( ( ( colorAttrib & 64 ) >> 6 ) | ( ( colorAttrib & 128 ) >> 6 ) ) + 1;
+
+			this.color = [];
+
+			for ( i = 0 & 15; i < colorCount; i ++ ) {
+
+				this.color.push( data.readFloatArray( this.numVertex * this.numColor ) );
+
+			}
+
+		}
+
+	}
+
+	// VERTEX
+	this.vertex = data.readFloatArray( this.length );
+
+	// SUB-MESHES
+	var count = data.readUByte();
+
+	this.groups = [];
+
+	if ( this.attrib & 1024 ) {
+
+		// INDEXES
+		for ( i = 0, len = 0; i < count; i ++ ) {
+
+			j = data.readVInt() * 3;
+
+			this.groups.push( {
+				start: len,
+				count: j
+			} );
+
+			len += j;
+
+		}
+
+		if ( ! ( this.attrib & 2048 ) ) {
+
+			this.indexes = this.isBig ? data.readUIntArray( len ) : data.readUShortArray( len );
+
+		}
+
+	} else {
+
+		// INDEXES
+		var stride = this.isBig ? 4 : 2,
+			bytearray = new SEA3DSDK.UByteArray();
+
+		for ( i = 0, j = 0; i < count; i ++ ) {
+
+			len = data.readVInt() * 3;
+
+			this.groups.push( {
+				start: j,
+				count: len
+			} );
+
+			j += len;
+
+			bytearray.add( data.readUByteArray( len * stride ) );
+
+		}
+
+		this.indexes = this.isBig ? new Uint32Array( bytearray.toBuffer() ) : new Uint16Array( bytearray.toBuffer() );
+
+	}
+
+};
+
+SEA3DSDK.Geometry.prototype = Object.create( SEA3DSDK.GeometryBase.prototype );
+SEA3DSDK.Geometry.prototype.constructor = SEA3DSDK.Geometry;
+
+SEA3DSDK.Geometry.prototype.type = "geo";
+
+//
+//	Object3D
+//
+
+SEA3DSDK.Object3D = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.isStatic = false;
+	this.visible = true;
+
+	this.attrib = data.readUShort();
+
+	if ( this.attrib & 1 ) this.parent = sea3d.getObject( data.readUInt() );
+
+	if ( this.attrib & 2 ) this.animations = data.readAnimationList( sea3d );
+
+	if ( this.attrib & 4 ) this.scripts = data.readScriptList( sea3d );
+
+	if ( this.attrib & 16 ) this.attributes = sea3d.getObject( data.readUInt() );
+
+	if ( this.attrib & 32 ) {
+
+		var objectType = data.readUByte();
+
+		this.isStatic = ( objectType & 1 ) !== 0;
+		this.visible = ( objectType & 2 ) === 0;
+
+	}
+
+};
+
+SEA3DSDK.Object3D.prototype.readTag = function ( kind, data, size ) {
+
+};
+
+//
+//	Entity3D
+//
+
+SEA3DSDK.Entity3D = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.castShadows = true;
+
+	if ( this.attrib & 64 ) {
+
+		var lightType = data.readUByte();
+
+		this.castShadows = ( lightType & 1 ) === 0;
+
+	}
+
+};
+
+SEA3DSDK.Entity3D.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Entity3D.prototype.constructor = SEA3DSDK.Entity3D;
+
+//
+//	Sound3D
+//
+
+SEA3DSDK.Sound3D = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.autoPlay = ( this.attrib & 64 ) != 0;
+
+	if ( this.attrib & 128 ) this.mixer = sea3d.getObject( data.readUInt() );
+
+	this.sound = sea3d.getObject( data.readUInt() );
+	this.volume = data.readFloat();
+
+};
+
+SEA3DSDK.Sound3D.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Sound3D.prototype.constructor = SEA3DSDK.Sound3D;
+
+//
+//	Sound Point
+//
+
+SEA3DSDK.SoundPoint = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Sound3D.call( this, name, data, sea3d );
+
+	this.position = data.readVector3();
+	this.distance = data.readFloat();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.SoundPoint.prototype = Object.create( SEA3DSDK.Sound3D.prototype );
+SEA3DSDK.SoundPoint.prototype.constructor = SEA3DSDK.SoundPoint;
+
+SEA3DSDK.SoundPoint.prototype.type = "sp";
+
+//
+//	Container3D
+//
+
+SEA3DSDK.Container3D = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.transform = data.readMatrix();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Container3D.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Container3D.prototype.constructor = SEA3DSDK.Container3D;
+
+SEA3DSDK.Container3D.prototype.type = "c3d";
+
+//
+//	Script URL
+//
+
+SEA3DSDK.ScriptURL = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.url = data.readUTF8( data.length );
+
+};
+
+SEA3DSDK.ScriptURL.prototype.type = "src";
+
+//
+//	Texture URL
+//
+
+SEA3DSDK.TextureURL = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.url = sea3d.config.path + data.readUTF8( data.length );
+
+};
+
+SEA3DSDK.TextureURL.prototype.type = "urlT";
+
+//
+//	CubeMap URL
+//
+
+SEA3DSDK.CubeMapURL = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.faces = [];
+
+	for ( var i = 0; i < 6; i ++ ) {
+
+		this.faces[ i ] = data.readUTF8Tiny();
+
+	}
+
+};
+
+SEA3DSDK.CubeMapURL.prototype.type = "cURL";
+
+//
+//	Actions
+//
+
+SEA3DSDK.Actions = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.count = data.readUInt();
+	this.actions = [];
+
+	for ( var i = 0; i < this.count; i ++ ) {
+
+		var flag = data.readUByte();
+		var kind = data.readUShort();
+
+		var size = data.readUShort();
+
+		var position = data.position;
+		var act = this.actions[ i ] = { kind: kind };
+
+		// range of animation
+		if ( flag & 1 ) {
+
+			// start and count in frames
+			act.range = [ data.readUInt(), data.readUInt() ];
+
+		}
+
+		// time
+		if ( flag & 2 ) {
+
+			act.time = data.readUInt();
+
+		}
+
+		// easing
+		if ( flag & 4 ) {
+
+			act.intrpl = data.readInterpolation();
+
+			if ( act.intrpl.indexOf( 'back.' ) === 0 ) {
+
+				act.intrplParam0 = data.readFloat();
+
+			} else if ( act.intrpl.indexOf( 'elastic.' ) === 0 ) {
+
+				act.intrplParam0 = data.readFloat();
+				act.intrplParam1 = data.readFloat();
+
+			}
+
+		}
+
+		switch ( kind ) {
+
+			case SEA3DSDK.Actions.RTT_TARGET:
+				act.source = sea3d.getObject( data.readUInt() );
+				act.target = sea3d.getObject( data.readUInt() );
+				break;
+
+			case SEA3DSDK.Actions.LOOK_AT:
+				act.source = sea3d.getObject( data.readUInt() );
+				act.target = sea3d.getObject( data.readUInt() );
+				break;
+
+			case SEA3DSDK.Actions.PLAY_SOUND:
+				act.sound = sea3d.getObject( data.readUInt() );
+				act.offset = data.readUInt();
+				break;
+
+			case SEA3DSDK.Actions.PLAY_ANIMATION:
+				act.object = sea3d.getObject( data.readUInt() );
+				act.name = data.readUTF8Tiny();
+				break;
+
+			case SEA3DSDK.Actions.FOG:
+				act.color = data.readUInt24();
+				act.min = data.readFloat();
+				act.max = data.readFloat();
+				break;
+
+			case SEA3DSDK.Actions.ENVIRONMENT:
+				act.texture = sea3d.getObject( data.readUInt() );
+				break;
+
+			case SEA3DSDK.Actions.ENVIRONMENT_COLOR:
+				act.color = data.readUInt24F();
+				break;
+
+			case SEA3DSDK.Actions.CAMERA:
+				act.camera = sea3d.getObject( data.readUInt() );
+				break;
+
+			case SEA3DSDK.Actions.SCRIPTS:
+				act.scripts = data.readScriptList( sea3d );
+				break;
+
+			case SEA3DSDK.Actions.CLASS_OF:
+				act.classof = sea3d.getObject( data.readUInt() );
+				break;
+
+			case SEA3DSDK.Actions.ATTRIBUTES:
+				act.attributes = sea3d.getObject( data.readUInt() );
+				break;
+
+			default:
+				console.log( "Action \"" + kind + "\" not found." );
+				break;
+
+		}
+
+		data.position = position + size;
+
+	}
+
+};
+
+SEA3DSDK.Actions.SCENE = 0;
+SEA3DSDK.Actions.ENVIRONMENT_COLOR = 1;
+SEA3DSDK.Actions.ENVIRONMENT = 2;
+SEA3DSDK.Actions.FOG = 3;
+SEA3DSDK.Actions.PLAY_ANIMATION = 4;
+SEA3DSDK.Actions.PLAY_SOUND = 5;
+SEA3DSDK.Actions.ANIMATION_AUDIO_SYNC = 6;
+SEA3DSDK.Actions.LOOK_AT = 7;
+SEA3DSDK.Actions.RTT_TARGET = 8;
+SEA3DSDK.Actions.CAMERA = 9;
+SEA3DSDK.Actions.SCRIPTS = 10;
+SEA3DSDK.Actions.CLASS_OF = 11;
+SEA3DSDK.Actions.ATTRIBUTES = 12;
+
+SEA3DSDK.Actions.prototype.type = "act";
+
+//
+//	Properties
+//
+
+SEA3DSDK.Properties = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.props = data.readProperties( sea3d );
+	this.props.__name = name;
+
+};
+
+SEA3DSDK.Properties.prototype.type = "prop";
+
+//
+//	File Info
+//
+
+SEA3DSDK.FileInfo = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.info = data.readProperties( sea3d );
+	this.info.__name = name;
+
+	sea3d.info = this.info;
+
+};
+
+SEA3DSDK.FileInfo.prototype.type = "info";
+
+//
+//	Java Script
+//
+
+SEA3DSDK.JavaScript = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.src = data.readUTF8( data.length );
+
+};
+
+SEA3DSDK.JavaScript.prototype.type = "js";
+
+//
+//	Java Script Method
+//
+
+SEA3DSDK.JavaScriptMethod = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var count = data.readUShort();
+
+	this.methods = {};
+
+	for ( var i = 0; i < count; i ++ ) {
+
+		var flag = data.readUByte();
+		var method = data.readUTF8Tiny();
+
+		this.methods[ method ] = {
+			src: data.readUTF8Long()
+		};
+
+	}
+
+};
+
+SEA3DSDK.JavaScriptMethod.prototype.type = "jsm";
+
+//
+//	GLSL
+//
+
+SEA3DSDK.GLSL = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.src = data.readUTF8( data.length );
+
+};
+
+SEA3DSDK.GLSL.prototype.type = "glsl";
+
+//
+//	Dummy
+//
+
+SEA3DSDK.Dummy = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.transform = data.readMatrix();
+
+	this.width = data.readFloat();
+	this.height = data.readFloat();
+	this.depth = data.readFloat();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Dummy.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Dummy.prototype.constructor = SEA3DSDK.Dummy;
+
+SEA3DSDK.Dummy.prototype.type = "dmy";
+
+//
+//	Line
+//
+
+SEA3DSDK.Line = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.count = ( this.attrib & 64 ? data.readUInt() : data.readUShort() ) * 3;
+	this.closed = ( this.attrib & 128 ) != 0;
+	this.transform = data.readMatrix();
+
+	this.vertex = [];
+
+	var i = 0;
+	while ( i < this.count ) {
+
+		this.vertex[ i ++ ] = data.readFloat();
+
+	}
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Line.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Line.prototype.constructor = SEA3DSDK.Line;
+
+SEA3DSDK.Line.prototype.type = "line";
+
+//
+//	Sprite
+//
+
+SEA3DSDK.Sprite = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	if ( this.attrib & 256 ) {
+
+		this.material = sea3d.getObject( data.readUInt() );
+
+	}
+
+	this.position = data.readVector3();
+
+	this.width = data.readFloat();
+	this.height = data.readFloat();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Sprite.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Sprite.prototype.constructor = SEA3DSDK.Sprite;
+
+SEA3DSDK.Sprite.prototype.type = "m2d";
+
+//
+//	Mesh
+//
+
+SEA3DSDK.Mesh = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Entity3D.call( this, name, data, sea3d );
+
+	// MATERIAL
+	if ( this.attrib & 256 ) {
+
+		this.material = [];
+
+		var len = data.readUByte();
+
+		if ( len === 1 ) this.material[ 0 ] = sea3d.getObject( data.readUInt() );
+		else {
+
+			var i = 0;
+			while ( i < len ) {
+
+				var matIndex = data.readUInt();
+
+				if ( matIndex > 0 ) this.material[ i ++ ] = sea3d.getObject( matIndex - 1 );
+				else this.material[ i ++ ] = undefined;
+
+			}
+
+		}
+
+	}
+
+	if ( this.attrib & 512 ) {
+
+		this.modifiers = [];
+
+		var len = data.readUByte();
+
+		for ( var i = 0; i < len; i ++ ) {
+
+			this.modifiers[ i ] = sea3d.getObject( data.readUInt() );
+
+		}
+
+	}
+
+	if ( this.attrib & 1024 ) {
+
+		this.reference = {
+			type: data.readUByte(),
+			ref: sea3d.getObject( data.readUInt() )
+		};
+
+	}
+
+	this.transform = data.readMatrix();
+
+	this.geometry = sea3d.getObject( data.readUInt() );
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Mesh.prototype = Object.create( SEA3DSDK.Entity3D.prototype );
+SEA3DSDK.Mesh.prototype.constructor = SEA3DSDK.Mesh;
+
+SEA3DSDK.Mesh.prototype.type = "m3d";
+
+//
+//	Skeleton
+//
+
+SEA3DSDK.Skeleton = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var length = data.readUShort();
+
+	this.joint = [];
+
+	for ( var i = 0; i < length; i ++ ) {
+
+		this.joint[ i ] = {
+			name: data.readUTF8Tiny(),
+			parentIndex: data.readUShort() - 1,
+			inverseBindMatrix: data.readMatrix()
+		};
+
+	}
+
+};
+
+SEA3DSDK.Skeleton.prototype.type = "skl";
+
+//
+//	Skeleton Local
+//
+
+SEA3DSDK.SkeletonLocal = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var length = data.readUShort();
+
+	this.joint = [];
+
+	for ( var i = 0; i < length; i ++ ) {
+
+		this.joint[ i ] = {
+			name: data.readUTF8Tiny(),
+			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()
+		};
+
+	}
+
+};
+
+SEA3DSDK.SkeletonLocal.prototype.type = "sklq";
+
+//
+//	Animation Base
+//
+
+SEA3DSDK.AnimationBase = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var flag = data.readUByte();
+
+	this.sequence = [];
+
+	if ( flag & 1 ) {
+
+		var count = data.readUShort();
+
+		for ( var i = 0; i < count; i ++ ) {
+
+			var seqFlag = data.readUByte();
+
+			this.sequence[ i ] = {
+				name: data.readUTF8Tiny(),
+				start: data.readUInt(),
+				count: data.readUInt(),
+				repeat: ( seqFlag & 1 ) !== 0,
+				intrpl: ( seqFlag & 2 ) === 0
+			};
+
+		}
+
+	}
+
+	this.frameRate = data.readUByte();
+	this.numFrames = data.readUInt();
+
+	// no contains sequence
+	if ( this.sequence.length === 0 ) {
+
+		this.sequence[ 0 ] = { name: "root", start: 0, count: this.numFrames, repeat: true, intrpl: true };
+
+	}
+
+};
+
+//
+//	Animation
+//
+
+SEA3DSDK.Animation = function ( name, data, sea3d ) {
+
+	SEA3DSDK.AnimationBase.call( this, name, data, sea3d );
+
+	this.dataList = [];
+
+	for ( var i = 0, l = data.readUByte(); i < l; i ++ ) {
+
+		var kind = data.readUShort(),
+			type = data.readUByte();
+
+		var anmRaw = data.readVector( type, this.numFrames, 0 );
+
+		this.dataList.push( {
+			kind: kind,
+			type: type,
+			blockSize: SEA3DSDK.Stream.sizeOf( type ),
+			data: anmRaw
+		} );
+
+	}
+
+};
+
+SEA3DSDK.Animation.POSITION = 0;
+SEA3DSDK.Animation.ROTATION = 1;
+SEA3DSDK.Animation.SCALE = 2;
+SEA3DSDK.Animation.COLOR = 3;
+SEA3DSDK.Animation.MULTIPLIER = 4;
+SEA3DSDK.Animation.ATTENUATION_START = 5;
+SEA3DSDK.Animation.ATTENUATION_END = 6;
+SEA3DSDK.Animation.FOV = 7;
+SEA3DSDK.Animation.OFFSET_U = 8;
+SEA3DSDK.Animation.OFFSET_V = 9;
+SEA3DSDK.Animation.SCALE_U = 10;
+SEA3DSDK.Animation.SCALE_V = 11;
+SEA3DSDK.Animation.DEGREE = 12;
+SEA3DSDK.Animation.ALPHA = 13;
+SEA3DSDK.Animation.VOLUME = 14;
+SEA3DSDK.Animation.RADIAN = 15;
+
+SEA3DSDK.Animation.MORPH = 250;
+
+SEA3DSDK.Animation.prototype = Object.create( SEA3DSDK.AnimationBase.prototype );
+SEA3DSDK.Animation.prototype.constructor = SEA3DSDK.Animation;
+
+SEA3DSDK.Animation.prototype.type = "anm";
+
+//
+//	Skeleton Animation
+//
+
+SEA3DSDK.SkeletonAnimation = function ( name, data, sea3d ) {
+
+	SEA3DSDK.AnimationBase.call( this, name, data, sea3d );
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.numJoints = data.readUShort();
+
+	this.raw = data.readFloatArray( this.numFrames * this.numJoints * 7 );
+
+};
+
+SEA3DSDK.SkeletonAnimation.prototype.type = "skla";
+
+//
+//	UVW Animation
+//
+
+SEA3DSDK.UVWAnimation = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Animation.call( this, name, data, sea3d );
+
+};
+
+SEA3DSDK.UVWAnimation.prototype.type = "auvw";
+
+//
+//	Morph
+//
+
+SEA3DSDK.Morph = function ( name, data, sea3d ) {
+
+	SEA3DSDK.GeometryBase.call( this, name, data, sea3d );
+
+	var useVertex = ( this.attrib & 2 ) != 0;
+	var useNormal = ( this.attrib & 4 ) != 0;
+
+	var nodeCount = data.readUShort();
+
+	this.node = [];
+
+	for ( var i = 0; i < nodeCount; i ++ ) {
+
+		var nodeName = data.readUTF8Tiny(),
+			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 };
+
+	}
+
+};
+
+SEA3DSDK.Morph.prototype = Object.create( SEA3DSDK.GeometryBase.prototype );
+SEA3DSDK.Morph.prototype.constructor = SEA3DSDK.Morph;
+
+SEA3DSDK.Morph.prototype.type = "mph";
+
+//
+//	Morph Animation
+//
+
+SEA3DSDK.MorphAnimation = function ( name, data, sea3d ) {
+
+	SEA3DSDK.AnimationBase.call( this, name, data, sea3d );
+
+	this.dataList = [];
+
+	for ( var i = 0, l = data.readUByte(); i < l; i ++ ) {
+
+		this.dataList.push( {
+			kind: SEA3DSDK.Animation.MORPH,
+			type: SEA3DSDK.Stream.FLOAT,
+			name: data.readUTF8Tiny(),
+			blockSize: 1,
+			data: data.readVector( SEA3DSDK.Stream.FLOAT, this.numFrames, 0 )
+		} );
+
+	}
+
+};
+
+SEA3DSDK.MorphAnimation.prototype.type = "mpha";
+
+//
+//	Vertex Animation
+//
+
+SEA3DSDK.VertexAnimation = function ( name, data, sea3d ) {
+
+	SEA3DSDK.AnimationBase.call( this, name, data, sea3d );
+
+	var flags = data.readUByte();
+
+	this.isBig = ( flags & 1 ) != 0;
+
+	data.readVInt = this.isBig ? data.readUInt : data.readUShort;
+
+	this.numVertex = data.readVInt();
+
+	this.length = this.numVertex * 3;
+
+	var useVertex = ( flags & 2 ) != 0;
+	var useNormal = ( flags & 4 ) != 0;
+
+	this.frame = [];
+
+	var i, verts, norms;
+
+	for ( i = 0; i < this.numFrames; i ++ ) {
+
+		if ( useVertex ) verts = data.readFloatArray( this.length );
+		if ( useNormal ) norms = data.readFloatArray( this.length );
+
+		this.frame[ i ] = { vertex: verts, normal: norms };
+
+	}
+
+};
+
+SEA3DSDK.VertexAnimation.prototype = Object.create( SEA3DSDK.AnimationBase.prototype );
+SEA3DSDK.VertexAnimation.prototype.constructor = SEA3DSDK.VertexAnimation;
+
+SEA3DSDK.VertexAnimation.prototype.type = "vtxa";
+
+//
+//	Camera
+//
+
+SEA3DSDK.Camera = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	if ( this.attrib & 64 ) {
+
+		this.dof = {
+			distance: data.readFloat(),
+			range: data.readFloat()
+		};
+
+	}
+
+	this.transform = data.readMatrix();
+
+	this.fov = data.readFloat();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.Camera.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Camera.prototype.constructor = SEA3DSDK.Camera;
+
+SEA3DSDK.Camera.prototype.type = "cam";
+
+//
+//	Orthographic Camera
+//
+
+SEA3DSDK.OrthographicCamera = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.transform = data.readMatrix();
+
+	this.height = data.readFloat();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.OrthographicCamera.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.OrthographicCamera.prototype.constructor = SEA3DSDK.OrthographicCamera;
+
+SEA3DSDK.OrthographicCamera.prototype.type = "camo";
+
+//
+//	Joint Object
+//
+
+SEA3DSDK.JointObject = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.target = sea3d.getObject( data.readUInt() );
+	this.joint = data.readUShort();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.JointObject.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.JointObject.prototype.constructor = SEA3DSDK.JointObject;
+
+SEA3DSDK.JointObject.prototype.type = "jnt";
+
+//
+//	Light
+//
+
+SEA3DSDK.Light = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Object3D.call( this, name, data, sea3d );
+
+	this.attenStart = Number.MAX_VALUE;
+	this.attenEnd = Number.MAX_VALUE;
+
+	if ( this.attrib & 64 ) {
+
+		var shadowHeader = data.readUByte();
+
+		this.shadow = {};
+
+		this.shadow.opacity = shadowHeader & 1 ? data.readFloat() : 1;
+		this.shadow.color = shadowHeader & 2 ? data.readUInt24() : 0x000000;
+
+	}
+
+	if ( this.attrib & 512 ) {
+
+		this.attenStart = data.readFloat();
+		this.attenEnd = data.readFloat();
+
+	}
+
+	this.color = data.readUInt24();
+	this.multiplier = data.readFloat();
+
+};
+
+SEA3DSDK.Light.prototype = Object.create( SEA3DSDK.Object3D.prototype );
+SEA3DSDK.Light.prototype.constructor = SEA3DSDK.Light;
+
+//
+//	Point Light
+//
+
+SEA3DSDK.PointLight = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Light.call( this, name, data, sea3d );
+
+	if ( this.attrib & 128 ) {
+
+		this.attenuation = {
+			start: data.readFloat(),
+			end: data.readFloat()
+		};
+
+	}
+
+	this.position = data.readVector3();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.PointLight.prototype = Object.create( SEA3DSDK.Light.prototype );
+SEA3DSDK.PointLight.prototype.constructor = SEA3DSDK.PointLight;
+
+SEA3DSDK.PointLight.prototype.type = "plht";
+
+//
+//	Hemisphere Light
+//
+
+SEA3DSDK.HemisphereLight = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Light.call( this, name, data, sea3d );
+
+	if ( this.attrib & 128 ) {
+
+		this.attenuation = {
+			start: data.readFloat(),
+			end: data.readFloat()
+		};
+
+	}
+
+	this.secondColor = data.readUInt24();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.HemisphereLight.prototype = Object.create( SEA3DSDK.Light.prototype );
+SEA3DSDK.HemisphereLight.prototype.constructor = SEA3DSDK.HemisphereLight;
+
+SEA3DSDK.HemisphereLight.prototype.type = "hlht";
+
+//
+//	Ambient Light
+//
+
+SEA3DSDK.AmbientLight = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Light.call( this, name, data, sea3d );
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.AmbientLight.prototype = Object.create( SEA3DSDK.Light.prototype );
+SEA3DSDK.AmbientLight.prototype.constructor = SEA3DSDK.AmbientLight;
+
+SEA3DSDK.AmbientLight.prototype.type = "alht";
+
+//
+//	Directional Light
+//
+
+SEA3DSDK.DirectionalLight = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Light.call( this, name, data, sea3d );
+
+	this.transform = data.readMatrix();
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.DirectionalLight.prototype = Object.create( SEA3DSDK.Light.prototype );
+SEA3DSDK.DirectionalLight.prototype.constructor = SEA3DSDK.DirectionalLight;
+
+SEA3DSDK.DirectionalLight.prototype.type = "dlht";
+
+//
+//	Material
+//
+
+SEA3DSDK.Material = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.technique = [];
+	this.tecniquesDict = {};
+
+	this.attrib = data.readUShort();
+
+	this.alpha = 1;
+	this.blendMode = "normal";
+
+	this.doubleSided = ( this.attrib & 1 ) != 0;
+
+	this.receiveLights = ( this.attrib & 2 ) === 0;
+	this.receiveShadows = ( this.attrib & 4 ) === 0;
+	this.receiveFog = ( this.attrib & 8 ) === 0;
+
+	this.repeat = ( this.attrib & 16 ) === 0;
+
+	if ( this.attrib & 32 )
+		this.alpha = data.readFloat();
+
+	if ( this.attrib & 64 )
+		this.blendMode = data.readBlendMode();
+
+	if ( this.attrib & 128 )
+		this.animations = data.readAnimationList( sea3d );
+
+	this.depthWrite = ( this.attrib & 256 ) === 0;
+	this.depthTest = ( this.attrib & 512 ) === 0;
+
+	this.premultipliedAlpha = ( this.attrib & 1024 ) != 0;
+
+	var count = data.readUByte();
+
+	for ( var i = 0; i < count; ++ i ) {
+
+		var kind = data.readUShort();
+		var size = data.readUShort();
+		var pos = data.position;
+		var tech, methodAttrib;
+
+		switch ( kind ) {
+
+			case SEA3DSDK.Material.PHONG:
+			
+				tech = {
+					ambientColor: data.readUInt24(),
+					diffuseColor: data.readUInt24(),
+					specularColor: data.readUInt24(),
+
+					specular: data.readFloat(),
+					gloss: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.PHYSICAL:
+			
+				tech = {
+					color: data.readUInt24(),
+					roughness: data.readFloat(),
+					metalness: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.ANISOTROPIC:
+				break;
+
+			case SEA3DSDK.Material.COMPOSITE_TEXTURE:
+			
+				tech = {
+					composite: sea3d.getObject( data.readUInt() )
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.DIFFUSE_MAP:
+			case SEA3DSDK.Material.SPECULAR_MAP:
+			case SEA3DSDK.Material.NORMAL_MAP:
+			case SEA3DSDK.Material.AMBIENT_MAP:
+			case SEA3DSDK.Material.ALPHA_MAP:
+			case SEA3DSDK.Material.EMISSIVE_MAP:
+			case SEA3DSDK.Material.ROUGHNESS_MAP:
+			case SEA3DSDK.Material.METALNESS_MAP:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() )
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.REFLECTION:
+			case SEA3DSDK.Material.FRESNEL_REFLECTION:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					alpha: data.readFloat()
+				};
+
+				if ( kind === SEA3DSDK.Material.FRESNEL_REFLECTION ) {
+
+					tech.power = data.readFloat();
+					tech.normal = data.readFloat();
+
+				}
+				
+				break;
+
+			case SEA3DSDK.Material.REFRACTION:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					alpha: data.readFloat(),
+					ior: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.RIM:
+			
+				tech = {
+					color: data.readUInt24(),
+					strength: data.readFloat(),
+					power: data.readFloat(),
+					blendMode: data.readBlendMode()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.LIGHT_MAP:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					channel: data.readUByte(),
+					blendMode: data.readBlendMode()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.DETAIL_MAP:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					scale: data.readFloat(),
+					blendMode: data.readBlendMode()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.CEL:
+			
+				tech = {
+					color: data.readUInt24(),
+					levels: data.readUByte(),
+					size: data.readFloat(),
+					specularCutOff: data.readFloat(),
+					smoothness: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.TRANSLUCENT:
+			
+				tech = {
+					translucency: data.readFloat(),
+					scattering: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.BLEND_NORMAL_MAP:
+			
+				methodAttrib = data.readUByte();
+
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					secondaryTexture: sea3d.getObject( data.readUInt() )
+				};
+
+				if ( methodAttrib & 1 ) {
+
+					tech.offsetX0 = data.readFloat();
+					tech.offsetY0 = data.readFloat();
+
+					tech.offsetX1 = data.readFloat();
+					tech.offsetY1 = data.readFloat();
+
+				} else {
+
+					tech.offsetX0 = tech.offsetY0 =
+					tech.offsetX1 = tech.offsetY1 = 0;
+
+				}
+
+				tech.animate = methodAttrib & 2;
+				
+				break;
+
+			case SEA3DSDK.Material.MIRROR_REFLECTION:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					alpha: data.readFloat()
+				};
+				break;
+
+			case SEA3DSDK.Material.EMISSIVE:
+			
+				tech = {
+					color: data.readUInt24F()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.VERTEX_COLOR:
+			
+				tech = {
+					blendMode: data.readBlendMode()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.WRAP_LIGHTING:
+			
+				tech = {
+					color: data.readUInt24(),
+					strength: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.COLOR_REPLACE:
+			
+				methodAttrib = data.readUByte();
+
+				tech = {
+					red: data.readUInt24(),
+					green: data.readUInt24(),
+					blue: data.readUInt24F()
+				};
+
+				if ( methodAttrib & 1 ) tech.mask = sea3d.getObject( data.readUInt() );
+
+				if ( methodAttrib & 2 ) tech.alpha = data.readFloat();
+
+				break;
+
+			case SEA3DSDK.Material.REFLECTION_SPHERICAL:
+			
+				tech = {
+					texture: sea3d.getObject( data.readUInt() ),
+					alpha: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.REFLECTIVITY:
+			
+				methodAttrib = data.readUByte();
+
+				tech = {
+					strength: data.readFloat()
+				};
+
+				if ( methodAttrib & 1 ) tech.mask = sea3d.getObject( data.readUInt() );
+
+				break;
+
+			case SEA3DSDK.Material.CLEAR_COAT:
+			
+				tech = {
+					strength: data.readFloat(),
+					roughness: data.readFloat()
+				};
+				
+				break;
+
+			case SEA3DSDK.Material.FLACCIDITY:
+			
+				methodAttrib = data.readUByte();
+
+				tech = {
+					target: sea3d.getObject( data.readUInt() ),
+					scale: data.readFloat(),
+					spring: data.readFloat(),
+					damping: data.readFloat()
+				};
+
+				if ( methodAttrib & 1 ) tech.mask = sea3d.getObject( data.readUInt() );
+
+				break;
+				
+			default:
+			
+				console.warn( "SEA3D: MaterialTechnique not found:", kind.toString( 16 ) );
+
+				data.position = pos += size;
+				
+				continue;
+
+		}
+
+		tech.kind = kind;
+
+		this.technique.push( tech );
+		this.tecniquesDict[ kind ] = tech;
+
+		data.position = pos += size;
+
+	}
+
+};
+
+SEA3DSDK.Material.PHONG = 0;
+SEA3DSDK.Material.COMPOSITE_TEXTURE = 1;
+SEA3DSDK.Material.DIFFUSE_MAP = 2;
+SEA3DSDK.Material.SPECULAR_MAP = 3;
+SEA3DSDK.Material.REFLECTION = 4;
+SEA3DSDK.Material.REFRACTION = 5;
+SEA3DSDK.Material.NORMAL_MAP = 6;
+SEA3DSDK.Material.FRESNEL_REFLECTION = 7;
+SEA3DSDK.Material.RIM = 8;
+SEA3DSDK.Material.LIGHT_MAP = 9;
+SEA3DSDK.Material.DETAIL_MAP = 10;
+SEA3DSDK.Material.CEL = 11;
+SEA3DSDK.Material.TRANSLUCENT = 12;
+SEA3DSDK.Material.BLEND_NORMAL_MAP = 13;
+SEA3DSDK.Material.MIRROR_REFLECTION = 14;
+SEA3DSDK.Material.AMBIENT_MAP = 15;
+SEA3DSDK.Material.ALPHA_MAP = 16;
+SEA3DSDK.Material.EMISSIVE_MAP = 17;
+SEA3DSDK.Material.VERTEX_COLOR = 18;
+SEA3DSDK.Material.WRAP_LIGHTING = 19;
+SEA3DSDK.Material.COLOR_REPLACE = 20;
+SEA3DSDK.Material.REFLECTION_SPHERICAL = 21;
+SEA3DSDK.Material.ANISOTROPIC = 22;
+SEA3DSDK.Material.EMISSIVE = 23;
+SEA3DSDK.Material.PHYSICAL = 24;
+SEA3DSDK.Material.ROUGHNESS_MAP = 25;
+SEA3DSDK.Material.METALNESS_MAP = 26;
+SEA3DSDK.Material.REFLECTIVITY = 27;
+SEA3DSDK.Material.CLEAR_COAT = 28;
+SEA3DSDK.Material.FLACCIDITY = 29;
+
+SEA3DSDK.Material.prototype.type = "mat";
+
+//
+//	Composite
+//
+
+SEA3DSDK.Composite = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	var layerCount = data.readUByte();
+
+	this.layer = [];
+
+	for ( var i = 0; i < layerCount; i ++ ) {
+
+		this.layer[ i ] = new SEA3DSDK.Composite.prototype.Layer( data, sea3d );
+
+	}
+
+};
+
+SEA3DSDK.Composite.prototype.getLayerByName = function ( name ) {
+
+	for ( var i = 0; i < this.layer.length; i ++ ) {
+
+		if ( this.layer[ i ].name === name ) {
+
+			return this.layer[ i ];
+
+		}
+
+	}
+
+};
+
+SEA3DSDK.Composite.prototype.Layer = function ( data, sea3d ) {
+
+	var attrib = data.readUShort();
+
+	if ( attrib & 1 ) this.texture = new SEA3DSDK.Composite.LayerBitmap( data, sea3d );
+	else this.color = data.readUInt24();
+
+	if ( attrib & 2 ) {
+
+		this.mask = new SEA3DSDK.Composite.LayerBitmap( data, sea3d );
+
+	}
+
+	if ( attrib & 4 ) {
+
+		this.name = data.readUTF8Tiny();
+
+	}
+
+	this.blendMode = attrib & 8 ? data.readBlendMode() : "normal";
+
+	this.opacity = attrib & 16 ? data.readFloat() : 1;
+
+};
+
+SEA3DSDK.Composite.LayerBitmap = function ( data, sea3d ) {
+
+	this.map = sea3d.getObject( data.readUInt() );
+
+	var attrib = data.readUShort();
+
+	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( sea3d );
+
+};
+
+SEA3DSDK.Composite.prototype.type = "ctex";
+
+//
+//	Planar Render
+//
+
+SEA3DSDK.PlanarRender = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUByte();
+
+	this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 );
+	this.transform = data.readMatrix();
+
+};
+
+SEA3DSDK.PlanarRender.prototype.type = "rttp";
+
+//
+//	Cube Render
+//
+
+SEA3DSDK.CubeRender = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUByte();
+
+	this.quality = ( this.attrib & 1 ) | ( this.attrib & 2 );
+	this.position = data.readVector3();
+
+};
+
+SEA3DSDK.CubeRender.prototype.type = "rttc";
+
+//
+//	Cube Maps
+//
+
+SEA3DSDK.CubeMap = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.transparent = false;
+
+	this.extension = data.readExt();
+
+	this.faces = [];
+
+	for ( var i = 0; i < 6; i ++ ) {
+
+		var size = data.readUInt();
+
+		this.faces[ i ] = data.concat( data.position, size );
+
+		data.position += size;
+
+	}
+
+};
+
+SEA3DSDK.CubeMap.prototype.type = "cmap";
+
+//
+//	JPEG
+//
+
+SEA3DSDK.JPEG = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.transparent = false;
+
+};
+
+SEA3DSDK.JPEG.prototype.type = "jpg";
+
+//
+//	JPEG_XR
+//
+
+SEA3DSDK.JPEG_XR = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.transparent = true;
+
+};
+
+SEA3DSDK.JPEG_XR.prototype.type = "wdp";
+
+//
+//	PNG
+//
+
+SEA3DSDK.PNG = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.transparent = data.getByte( 25 ) === 0x06;
+
+};
+
+SEA3DSDK.PNG.prototype.type = "png";
+
+//
+//	GIF
+//
+
+SEA3DSDK.GIF = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.transparent = data.getByte( 11 ) > 0;
+
+};
+
+SEA3DSDK.GIF.prototype.type = "gif";
+
+//
+//	OGG
+//
+
+SEA3DSDK.OGG = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+};
+
+SEA3DSDK.OGG.prototype.type = "ogg";
+
+//
+//	MP3
+//
+
+SEA3DSDK.MP3 = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+};
+
+SEA3DSDK.MP3.prototype.type = "mp3";
+
+//
+//	Asset Update
+//
+
+SEA3DSDK.AssetUpdate = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.index = data.readUInt();
+	this.bytes = data.concat( data.position, data.length - data.position );
+
+};
+
+SEA3DSDK.AssetUpdate.prototype.type = "upDt";
+
+//
+//	FILE FORMAT
+//
+
+SEA3DSDK.File = function ( config ) {
+
+	this.config = {
+		streaming: true,
+		timeLimit: 60,
+		progressive: false
+	};
+
+	if ( config ) {
+
+		if ( config.streaming !== undefined ) this.config.streaming = config.streaming;
+		if ( config.timeLimit !== undefined ) this.config.timeLimit = config.timeLimit;
+		if ( config.progressive !== undefined ) this.config.progressive = config.progressive;
+		if ( config.path !== undefined ) this.config.path = config.path;
+
+	}
+
+	this.version = SEA3DSDK.VERSION;
+	this.objects = [];
+	this.typeClass = {};
+	this.typeRead = {};
+	this.typeUnique = {};
+	this.position =
+	this.dataPosition = 0;
+	this.scope = this;
+
+	// SEA3D
+	this.addClass( SEA3DSDK.FileInfo, true );
+	this.addClass( SEA3DSDK.Geometry, true );
+	this.addClass( SEA3DSDK.Mesh );
+	this.addClass( SEA3DSDK.Sprite );
+	this.addClass( SEA3DSDK.Material );
+	this.addClass( SEA3DSDK.Composite );
+	this.addClass( SEA3DSDK.PointLight );
+	this.addClass( SEA3DSDK.DirectionalLight );
+	this.addClass( SEA3DSDK.HemisphereLight );
+	this.addClass( SEA3DSDK.AmbientLight );
+	this.addClass( SEA3DSDK.Animation, true );
+	this.addClass( SEA3DSDK.Skeleton, true );
+	this.addClass( SEA3DSDK.SkeletonLocal, true );
+	this.addClass( SEA3DSDK.SkeletonAnimation, true );
+	this.addClass( SEA3DSDK.UVWAnimation, true );
+	this.addClass( SEA3DSDK.JointObject );
+	this.addClass( SEA3DSDK.Camera );
+	this.addClass( SEA3DSDK.OrthographicCamera );
+	this.addClass( SEA3DSDK.Morph, true );
+	this.addClass( SEA3DSDK.MorphAnimation, true );
+	this.addClass( SEA3DSDK.VertexAnimation, true );
+	this.addClass( SEA3DSDK.CubeMap, true );
+	this.addClass( SEA3DSDK.Dummy );
+	this.addClass( SEA3DSDK.Line );
+	this.addClass( SEA3DSDK.SoundPoint );
+	this.addClass( SEA3DSDK.PlanarRender );
+	this.addClass( SEA3DSDK.CubeRender );
+	this.addClass( SEA3DSDK.Actions );
+	this.addClass( SEA3DSDK.Container3D );
+	this.addClass( SEA3DSDK.Properties );
+
+	// URL BASED
+	this.addClass( SEA3DSDK.ScriptURL, true );
+	this.addClass( SEA3DSDK.TextureURL, true );
+	this.addClass( SEA3DSDK.CubeMapURL, true );
+
+	// UNIVERSAL
+	this.addClass( SEA3DSDK.JPEG, true );
+	this.addClass( SEA3DSDK.JPEG_XR, true );
+	this.addClass( SEA3DSDK.PNG, true );
+	this.addClass( SEA3DSDK.GIF, true );
+	this.addClass( SEA3DSDK.OGG, true );
+	this.addClass( SEA3DSDK.MP3, true );
+	this.addClass( SEA3DSDK.JavaScript, true );
+	this.addClass( SEA3DSDK.JavaScriptMethod, true );
+	this.addClass( SEA3DSDK.GLSL, true );
+
+	// UPDATER
+	this.addClass( SEA3DSDK.AssetUpdate, true );
+
+	// EXTENSION
+	var i = SEA3DSDK.File.Extensions.length;
+
+	while ( i -- ) {
+
+		SEA3DSDK.File.Extensions[ i ].call( this );
+
+	}
+
+};
+
+SEA3DSDK.File.Extensions = [];
+SEA3DSDK.File.CompressionLibs = {};
+SEA3DSDK.File.DecompressionMethod = {};
+
+SEA3DSDK.File.setExtension = function ( callback ) {
+
+	SEA3DSDK.File.Extensions.push( callback );
+
+};
+
+SEA3DSDK.File.setDecompressionEngine = function ( id, name, method ) {
+
+	SEA3DSDK.File.CompressionLibs[ id ] = name;
+	SEA3DSDK.File.DecompressionMethod[ id ] = method;
+
+};
+
+SEA3DSDK.File.prototype.addClass = function ( clazz, unique ) {
+
+	this.typeClass[ clazz.prototype.type ] = clazz;
+	this.typeUnique[ clazz.prototype.type ] = unique === true;
+
+};
+
+SEA3DSDK.File.prototype.readHead = function () {
+
+	if ( this.stream.bytesAvailable < 16 )
+		return false;
+
+	if ( this.stream.readUTF8( 3 ) != "SEA" )
+		throw new Error( "Invalid SEA3D format." );
+
+	this.sign = this.stream.readUTF8( 3 );
+
+	this.version = this.stream.readUInt24();
+
+	if ( this.stream.readUByte() != 0 ) {
+
+		throw new Error( "Protection algorithm not compatible." );
+
+	}
+
+	this.compressionID = this.stream.readUByte();
+
+	this.compressionAlgorithm = SEA3DSDK.File.CompressionLibs[ this.compressionID ];
+	this.decompressionMethod = SEA3DSDK.File.DecompressionMethod[ this.compressionID ];
+
+	if ( this.compressionID > 0 && ! this.decompressionMethod ) {
+
+		throw new Error( "Compression algorithm not compatible." );
+
+	}
+
+	this.length = this.stream.readUInt();
+
+	this.dataPosition = this.stream.position;
+
+	this.objects.length = 0;
+
+	this.state = this.readBody;
+
+	if ( this.onHead ) {
+
+		this.onHead( {
+			file: this,
+			sign: this.sign
+		} );
+
+	}
+
+	return true;
+
+};
+
+SEA3DSDK.File.prototype.getObject = function ( index ) {
+
+	return this.objects[ index ];
+
+};
+
+SEA3DSDK.File.prototype.getObjectIndex = function ( name ) {
+
+	return this.objects[ name ].index;
+
+};
+
+SEA3DSDK.File.prototype.getObjectByName = function ( name ) {
+
+	return this.getObject( this.getObjectIndex( name ) );
+
+};
+
+SEA3DSDK.File.prototype.readSEAObject = function () {
+
+	if ( this.stream.bytesAvailable < 4 )
+		return null;
+
+	var size = this.stream.readUInt(),
+		position = this.stream.position;
+
+	if ( this.stream.bytesAvailable < size )
+		return null;
+
+	var flag = this.stream.readUByte(),
+		type = this.stream.readExt(),
+		meta = null;
+
+	var name = flag & 1 ? this.stream.readUTF8Tiny() : "",
+		compressed = ( flag & 2 ) != 0,
+		streaming = ( flag & 4 ) != 0;
+
+	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 ) {
+
+			metabytes.buffer = this.decompressionMethod( metabytes.buffer );
+
+		}
+
+		meta = metabytes.readProperties( this );
+
+	}
+
+	size -= this.stream.position - position;
+	position = this.stream.position;
+
+	var data = this.stream.concat( position, size ),
+		obj;
+
+	if ( this.typeClass[ type ] ) {
+
+		if ( compressed && this.decompressionMethod ) {
+
+			data.buffer = this.decompressionMethod( data.buffer );
+
+		}
+
+		obj = new this.typeClass[ type ]( name, data, this );
+
+		if ( ( this.config.streaming && streaming || this.config.forceStreaming ) && this.typeRead[ type ] ) {
+
+			this.typeRead[ type ].call( this.scope, obj );
+
+		}
+
+	} else {
+
+		obj = new SEA3DSDK.Object( name, data, type, this );
+
+		console.warn( "SEA3D: Unknown format \"" + type + "\" of file \"" + name + "\". Add a module referring for this format." );
+
+	}
+
+	obj.index = this.objects.length;
+	obj.streaming = streaming;
+	obj.metadata = meta;
+
+	this.objects.push( this.objects[ obj.name + "." + obj.type ] = obj );
+
+	this.dataPosition = position + size;
+
+	++ this.position;
+
+	return obj;
+
+};
+
+SEA3DSDK.File.prototype.isDone = function () {
+
+	return this.position === this.length;
+
+};
+
+SEA3DSDK.File.prototype.readBody = function () {
+
+	this.timer.update();
+
+	if ( ! this.resume ) return false;
+
+	while ( this.position < this.length ) {
+
+		if ( this.timer.deltaTime < this.config.timeLimit ) {
+
+			this.stream.position = this.dataPosition;
+
+			var sea = this.readSEAObject();
+
+			if ( sea ) this.dispatchCompleteObject( sea );
+			else return false;
+
+		} else return false;
+
+	}
+
+	this.state = this.readComplete;
+
+	return true;
+
+};
+
+SEA3DSDK.File.prototype.initParse = function () {
+
+	this.timer = new SEA3DSDK.Timer();
+	this.position = 0;
+	this.resume = true;
+
+};
+
+SEA3DSDK.File.prototype.parse = function () {
+
+	this.initParse();
+
+	if ( isFinite( this.config.timeLimit ) ) requestAnimationFrame( this.parseObject.bind( this ) );
+	else this.parseObject();
+
+};
+
+SEA3DSDK.File.prototype.parseObject = function () {
+
+	this.timer.update();
+
+	while ( this.position < this.length && this.timer.deltaTime < this.config.timeLimit ) {
+
+		var obj = this.objects[ this.position ++ ],
+			type = obj.type;
+
+		if ( ! this.typeUnique[ type ] ) delete obj.tag;
+
+		if ( ( obj.streaming || this.config.forceStreaming ) && 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
+			} );
+
+		}
+
+		setTimeout( this.parseObject.bind( this ), 10 );
+
+	}
+
+};
+
+SEA3DSDK.File.prototype.readComplete = function () {
+
+	this.stream.position = this.dataPosition;
+
+	if ( this.stream.readUInt24F() != 0x5EA3D1 )
+		console.warn( "SEA3D file is corrupted." );
+
+	delete this.state;
+
+	return false;
+
+};
+
+SEA3DSDK.File.prototype.readState = function () {
+
+	while ( this.state() ) continue;
+
+	if ( this.state ) {
+
+		requestAnimationFrame( this.readState.bind( this ) );
+
+		this.dispatchProgress();
+
+	} else {
+
+		this.dispatchComplete();
+
+	}
+
+};
+
+SEA3DSDK.File.prototype.append = function( buffer ) {
+
+	if (this.state) {
+
+		this.stream.append( buffer );
+
+	} else {
+
+		this.read( buffer );
+
+	}
+
+};
+
+SEA3DSDK.File.prototype.read = function ( buffer ) {
+
+	if ( ! buffer ) throw new Error( "No data found." );
+
+	this.initParse();
+
+	this.stream = new SEA3DSDK.Stream( buffer );
+	this.state = this.readHead;
+
+	this.readState();
+
+};
+
+SEA3DSDK.File.prototype.dispatchCompleteObject = function ( obj ) {
+
+	if ( ! this.onCompleteObject ) return;
+
+	this.onCompleteObject( {
+		file: this,
+		object: obj
+	} );
+
+};
+
+SEA3DSDK.File.prototype.dispatchProgress = function () {
+
+	if ( ! this.onProgress ) return;
+
+	this.onProgress( {
+		file: this,
+		loaded: this.position,
+		total: this.length
+	} );
+
+};
+
+SEA3DSDK.File.prototype.dispatchDownloadProgress = function ( position, length ) {
+
+	if ( ! this.onDownloadProgress ) return;
+
+	this.onDownloadProgress( {
+		file: this,
+		loaded: position,
+		total: length
+	} );
+
+};
+
+SEA3DSDK.File.prototype.dispatchComplete = function () {
+
+	var elapsedTime = this.timer.elapsedTime;
+	var message = elapsedTime + "ms, " + this.objects.length + " objects";
+
+	if ( this.onComplete ) this.onComplete( {
+		file: this,
+		timeTotal: elapsedTime,
+		message: message
+	} );
+	else console.log( "SEA3D:", message );
+
+};
+
+SEA3DSDK.File.prototype.dispatchError = function ( id, message ) {
+
+	if ( this.onError ) this.onError( { file: this, id: id, message: message } );
+	else console.error( "SEA3D: #" + id, message );
+
+};
+
+SEA3DSDK.File.prototype.extractUrlBase = function ( url ) {
+
+	var parts = url.split( '/' );
+
+	if ( parts.length === 1 ) return './';
+
+	parts.pop();
+
+	return parts.join( '/' ) + '/';
+
+};
+
+SEA3DSDK.File.prototype.load = function ( url ) {
+
+	var self = this,
+		xhr = new XMLHttpRequest();
+
+	xhr.open( "GET", url, true );
+
+	if (!this.config.path) {
+
+		this.config.path = this.extractUrlBase( url );
+
+	}
+
+	if ( self.config.progressive ) {
+
+		var position = 0;
+
+		xhr.overrideMimeType( 'text/plain; charset=x-user-defined' );
+
+	} else {
+
+		xhr.responseType = 'arraybuffer';
+
+	}
+
+	xhr.onprogress = function ( e ) {
+
+		if ( self.config.progressive ) {
+
+			var binStr = xhr.responseText.substring( position ),
+				bytes = new Uint8Array( binStr.length );
+
+			for ( var i = 0; i < binStr.length; i ++ ) {
+
+				bytes[ i ] = binStr.charCodeAt( i ) & 0xFF;
+
+			}
+
+			position += binStr.length;
+
+			self.append( bytes.buffer );
+
+		}
+
+		self.dispatchDownloadProgress( e.loaded, e.total );
+
+	};
+
+	if ( ! self.config.progressive ) {
+
+		xhr.onreadystatechange = function () {
+
+			if ( xhr.readyState === 4 ) {
+
+				if ( xhr.status === 200 || xhr.status === 0 ) {
+
+					self.read( this.response );
+
+				} else {
+
+					this.dispatchError( 1001, "Couldn't load [" + url + "] [" + xhr.status + "]" );
+
+				}
+
+			}
+
+		};
+
+	}
+
+	xhr.send();
+
+};
+
+export { SEA3DSDK };

+ 1006 - 0
examples/jsm/loaders/sea3d/physics/SEA3DAmmoLoader.js

@@ -0,0 +1,1006 @@
+/**   _     _   _         _____  __   _______  ______
+*    | |___| |_| |__    /__  |  |  |     |  _  | * *
+*    | / _ \  _|    |    __\    |  |  \  |  _  |  U _
+*    |_\___/\__|_||_| _ |____/____ |__ \_|_  |_|_____|
+*
+*    @author LoTh / http://3dflashlo.wordpress.com/
+*    @author SUNAG / http://www.sunag.com.br/
+*    @author Ammo.lab / https://github.com/lo-th/Ammo.lab/
+*/
+
+import {
+	Vector3,
+	Quaternion,
+	Matrix4
+} from "../../../../../build/three.module.js";
+
+import { SEA3DSDK } from '../SEA3DSDK.js';
+import { SEA3D } from '../SEA3DLoader.js';
+
+var AMMO = {
+
+	world: null,
+
+	rigidBodies: [],
+	rigidBodiesTarget: [],
+	rigidBodiesEnabled: [],
+
+	constraints: [],
+
+	vehicles: [],
+	vehiclesWheels: [],
+
+	ACTIVE: 1,
+	ISLAND_SLEEPING: 2,
+	WANTS_DEACTIVATION: 3,
+	DISABLE_DEACTIVATION: 4,
+	DISABLE_SIMULATION: 5,
+	VERSION: 0.8,
+
+	init: function ( gravity, worldScale, broadphase ) {
+
+		gravity = gravity !== undefined ? gravity : - 90.8;
+
+		this.worldScale = worldScale == undefined ? 1 : worldScale;
+		this.broadphase = broadphase == undefined ? 'bvt' : broadphase;
+
+		this.solver = new Ammo.btSequentialImpulseConstraintSolver();
+		this.collisionConfig = new Ammo.btDefaultCollisionConfiguration();
+		this.dispatcher = new Ammo.btCollisionDispatcher( this.collisionConfig );
+
+		switch ( this.broadphase ) {
+
+			case 'bvt':
+
+				this.broadphase = new Ammo.btDbvtBroadphase();
+
+				break;
+
+			case 'sap':
+
+				this.broadphase = new Ammo.btAxisSweep3(
+					new Ammo.btVector3( - this.worldScale, - this.worldScale, - this.worldScale ),
+					new Ammo.btVector3( this.worldScale, this.worldScale, this.worldScale ),
+					4096
+				);
+
+				break;
+
+			case 'simple':
+
+				this.broadphase = new Ammo.btSimpleBroadphase();
+
+				break;
+
+		}
+
+		this.world = new Ammo.btDiscreteDynamicsWorld( this.dispatcher, this.broadphase, this.solver, this.collisionConfig );
+
+		this.setGravity( gravity );
+
+		console.log( "SEA3D.AMMO " + this.VERSION );
+
+	},
+
+	setGravity: function ( gravity ) {
+
+		this.gravity = gravity;
+
+		this.world.setGravity( new Ammo.btVector3( 0, gravity, 0 ) );
+
+		return this;
+
+	},
+	getGravity: function () {
+
+		return this.gravity;
+
+	},
+
+	setEnabledRigidBody: function ( rb, enabled ) {
+
+		var index = this.rigidBodies.indexOf( rb );
+
+		if ( this.rigidBodiesEnabled[ index ] == enabled ) return;
+
+		if ( enabled ) this.world.addRigidBody( rb );
+		else this.world.removeRigidBody( rb );
+
+		this.rigidBodiesEnabled[ index ] = true;
+
+		return this;
+
+	},
+	getEnabledRigidBody: function ( rb ) {
+
+		return this.rigidBodiesEnabled[ this.rigidBodies.indexOf( rb ) ];
+
+	},
+	addRigidBody: function ( rb, target, enabled ) {
+
+		enabled = enabled !== undefined ? enabled : true;
+
+		this.rigidBodies.push( rb );
+		this.rigidBodiesTarget.push( target );
+		this.rigidBodiesEnabled.push( false );
+
+		this.setEnabledRigidBody( rb, enabled );
+
+		return this;
+
+	},
+	removeRigidBody: function ( rb, destroy ) {
+
+		var index = this.rigidBodies.indexOf( rb );
+
+		this.setEnabledRigidBody( rb, false );
+
+		this.rigidBodies.splice( index, 1 );
+		this.rigidBodiesTarget.splice( index, 1 );
+		this.rigidBodiesEnabled.splice( index, 1 );
+
+		if ( destroy ) Ammo.destroy( rb );
+
+		return this;
+
+	},
+	containsRigidBody: function ( rb ) {
+
+		return this.rigidBodies.indexOf( rb ) > - 1;
+
+	},
+
+	addConstraint: function ( ctrt, disableCollisionsBetweenBodies ) {
+
+		disableCollisionsBetweenBodies = disableCollisionsBetweenBodies == undefined ? true : disableCollisionsBetweenBodies;
+
+		this.constraints.push( ctrt );
+		this.world.addConstraint( ctrt, disableCollisionsBetweenBodies );
+
+		return this;
+
+	},
+	removeConstraint: function ( ctrt, destroy ) {
+
+		this.constraints.splice( this.constraints.indexOf( ctrt ), 1 );
+		this.world.removeConstraint( ctrt );
+
+		if ( destroy ) Ammo.destroy( ctrt );
+
+		return this;
+
+	},
+	containsConstraint: function ( ctrt ) {
+
+		return this.constraints.indexOf( rb ) > - 1;
+
+	},
+
+	addVehicle: function ( vehicle, wheels ) {
+
+		this.vehicles.push( vehicle );
+		this.vehiclesWheels.push( wheels != undefined ? wheels : [] );
+
+		this.world.addAction( vehicle );
+
+		return this;
+
+	},
+	removeVehicle: function ( vehicle, destroy ) {
+
+		var index = this.vehicles.indexOf( vehicle );
+
+		this.vehicles.splice( index, 1 );
+		this.vehiclesWheels.splice( index, 1 );
+
+		this.world.removeAction( vehicle );
+
+		if ( destroy ) Ammo.destroy( vehicle );
+
+		return this;
+
+	},
+	containsVehicle: function ( vehicle ) {
+
+		return this.vehicles.indexOf( vehicle ) > - 1;
+
+	},
+
+	createTriangleMesh: function ( geometry, index, removeDuplicateVertices ) {
+
+		index = index == undefined ? - 1 : index;
+		removeDuplicateVertices = removeDuplicateVertices == undefined ? false : removeDuplicateVertices;
+
+		var mTriMesh = new Ammo.btTriangleMesh();
+
+		var v0 = new Ammo.btVector3( 0, 0, 0 );
+		var v1 = new Ammo.btVector3( 0, 0, 0 );
+		var v2 = new Ammo.btVector3( 0, 0, 0 );
+
+		var vertex = geometry.getAttribute( 'position' ).array;
+		var indexes = geometry.getIndex().array;
+
+		var group = index >= 0 ? geometry.groups[ index ] : undefined,
+			start = group ? group.start : 0,
+			count = group ? group.count : indexes.length;
+
+		var scale = 1 / this.worldScale;
+
+		for ( var idx = start; idx < count; idx += 3 ) {
+
+			var vx1 = indexes[ idx ] * 3,
+				vx2 = indexes[ idx + 1 ] * 3,
+				vx3 = indexes[ idx + 2 ] * 3;
+
+			v0.setValue( vertex[ vx1 ] * scale, vertex[ vx1 + 1 ] * scale, vertex[ vx1 + 2 ] * scale );
+			v1.setValue( vertex[ vx2 ] * scale, vertex[ vx2 + 1 ] * scale, vertex[ vx2 + 2 ] * scale );
+			v2.setValue( vertex[ vx3 ] * scale, vertex[ vx3 + 1 ] * scale, vertex[ vx3 + 2 ] * scale );
+
+			mTriMesh.addTriangle( v0, v1, v2, removeDuplicateVertices );
+
+		}
+
+		return mTriMesh;
+
+	},
+	createConvexHull: function ( geometry, index ) {
+
+		index = index == undefined ? - 1 : index;
+
+		var mConvexHull = new Ammo.btConvexHullShape();
+
+		var v0 = new Ammo.btVector3( 0, 0, 0 );
+
+		var vertex = geometry.getAttribute( 'position' ).array;
+		var indexes = geometry.getIndex().array;
+
+		var group = index >= 0 ? geometry.groups[ index ] : undefined,
+			start = group ? group.start : 0,
+			count = group ? group.count : indexes.length;
+
+		var scale = 1 / this.worldScale;
+
+		for ( var idx = start; idx < count; idx += 3 ) {
+
+			var vx1 = indexes[ idx ] * 3;
+
+			var point = new Ammo.btVector3(
+				vertex[ vx1 ] * scale, vertex[ vx1 + 1 ] * scale, vertex[ vx1 + 2 ] * scale
+			);
+
+			mConvexHull.addPoint( point );
+
+		}
+
+		return mConvexHull;
+
+	},
+
+	getTargetByRigidBody: function ( rb ) {
+
+		return this.rigidBodiesTarget[ this.rigidBodies.indexOf( rb ) ];
+
+	},
+	getRigidBodyByTarget: function ( target ) {
+
+		return this.rigidBodies[ this.rigidBodiesTarget.indexOf( target ) ];
+
+	},
+	getTransformFromMatrix: function ( mtx ) {
+
+		var transform = new Ammo.btTransform();
+
+		var pos = SEA3D.VECBUF.setFromMatrixPosition( mtx );
+		transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
+
+		var scl = SEA3D.VECBUF.setFromMatrixScale( mtx );
+		mtx.scale( scl.set( 1 / scl.x, 1 / scl.y, 1 / scl.z ) );
+
+		var quat = new Quaternion().setFromRotationMatrix( mtx );
+
+		var q = new Ammo.btQuaternion();
+		q.setValue( quat.x, quat.y, quat.z, quat.w );
+		transform.setRotation( q );
+
+		Ammo.destroy( q );
+
+		return transform;
+
+	},
+	getMatrixFromTransform: function ( transform ) {
+
+		var position = new Vector3();
+		var quaternion = new Quaternion();
+		var scale = new Vector3( 1, 1, 1 );
+
+		return function ( transform, matrix ) {
+
+			matrix = matrix || new Matrix4();
+
+			var pos = transform.getOrigin(),
+				quat = transform.getRotation();
+
+			position.set( pos.x(), pos.y(), pos.z() );
+			quaternion.set( quat.x(), quat.y(), quat.z(), quat.w() );
+
+			matrix.compose( position, quaternion, scale );
+
+			return matrix;
+
+		};
+
+	}(),
+
+	updateTargetTransform: function () {
+
+		var matrix = new Matrix4();
+
+		var position = new Vector3();
+		var quaternion = new Quaternion();
+		var scale = new Vector3( 1, 1, 1 );
+
+		return function ( obj3d, transform, offset ) {
+
+			var pos = transform.getOrigin(),
+				quat = transform.getRotation();
+
+			if ( offset ) {
+
+				position.set( pos.x(), pos.y(), pos.z() );
+				quaternion.set( quat.x(), quat.y(), quat.z(), quat.w() );
+
+				matrix.compose( position, quaternion, scale );
+
+				matrix.multiplyMatrices( matrix, offset );
+
+				obj3d.position.setFromMatrixPosition( matrix );
+				obj3d.quaternion.setFromRotationMatrix( matrix );
+
+			} else {
+
+				obj3d.position.set( pos.x(), pos.y(), pos.z() );
+				obj3d.quaternion.set( quat.x(), quat.y(), quat.z(), quat.w() );
+
+			}
+
+			return this;
+
+		};
+
+	}(),
+	update: function ( delta, iteration, fixedDelta ) {
+
+		this.world.stepSimulation( delta, iteration || 0, fixedDelta || ( 60 / 1000 ) );
+
+		var i, j;
+
+		for ( i = 0; i < this.vehicles.length; i ++ ) {
+
+			var vehicle = this.vehicles[ i ],
+				numWheels = vehicle.getNumWheels(),
+				wheels = this.vehiclesWheels[ i ];
+
+			for ( j = 0; j < numWheels; j ++ ) {
+
+				vehicle.updateWheelTransform( j, true );
+
+				var wheelsTransform = vehicle.getWheelTransformWS( j ),
+					wheelTarget = wheels[ j ];
+
+				if ( wheelTarget ) {
+
+					this.updateTargetTransform( wheelTarget, wheelsTransform, wheelTarget.physics ? wheelTarget.physics.offset : null );
+
+				}
+
+			}
+
+		}
+
+		for ( i = 0; i < this.rigidBodies.length; i ++ ) {
+
+			var rb = this.rigidBodies[ i ],
+				target = this.rigidBodiesTarget[ i ];
+
+			if ( target && rb.isActive() ) {
+
+				this.updateTargetTransform( target, rb.getWorldTransform(), target.physics ? target.physics.offset : null );
+
+			}
+
+		}
+
+		return this;
+
+	}
+};
+
+//
+//	Utils
+//
+
+SEA3D.prototype.toAmmoVec3 = function ( v ) {
+
+	return new Ammo.btVector3( v.x, v.y, v.z );
+
+};
+
+//
+//	Sphere
+//
+
+SEA3D.prototype.readSphere = function ( sea ) {
+
+	var shape = new Ammo.btSphereShape( sea.radius );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Box
+//
+
+SEA3D.prototype.readBox = function ( sea ) {
+
+	var shape = new Ammo.btBoxShape( new Ammo.btVector3( sea.width * .5, sea.height * .5, sea.depth * .5 ) );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Cone
+//
+
+SEA3D.prototype.readCone = function ( sea ) {
+
+	var shape = new Ammo.btConeShape( sea.radius, sea.height );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Cylinder
+//
+
+SEA3D.prototype.readCylinder = function ( sea ) {
+
+	var shape = new Ammo.btCylinderShape( new Ammo.btVector3( sea.height, sea.radius, sea.radius ) );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Capsule
+//
+
+SEA3D.prototype.readCapsule = function ( sea ) {
+
+	var shape = new Ammo.btCapsuleShape( sea.radius, sea.height );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Convex Geometry
+//
+
+SEA3D.prototype.readConvexGeometry = function ( sea ) {
+
+	if ( this.config.convexHull ) {
+
+		var shape = AMMO.createConvexHull( sea.geometry.tag, sea.subGeometryIndex );
+
+	} else {
+
+		var triMesh = AMMO.createTriangleMesh( sea.geometry.tag, sea.subGeometryIndex );
+
+		var shape = new Ammo.btConvexTriangleMeshShape( triMesh, true );
+
+	}
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Triangle Geometry
+//
+
+SEA3D.prototype.readTriangleGeometry = function ( sea ) {
+
+	var triMesh = AMMO.createTriangleMesh( sea.geometry.tag, sea.subGeometryIndex );
+
+	var shape = new Ammo.btBvhTriangleMeshShape( triMesh, true, true );
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Compound
+//
+
+SEA3D.prototype.readCompound = function ( sea ) {
+
+	var shape = new Ammo.btCompoundShape();
+
+	for ( var i = 0; i < sea.compounds.length; i ++ ) {
+
+		var compound = sea.compounds[ i ];
+
+		SEA3D.MTXBUF.elements = compound.transform;
+
+		var transform = AMMO.getTransformFromMatrix( SEA3D.MTXBUF );
+
+		shape.addChildShape( transform, compound.shape.tag );
+
+	}
+
+	this.domain.shapes = this.shapes = this.shapes || [];
+	this.shapes.push( this.objects[ "shpe/" + sea.name ] = sea.tag = shape );
+
+};
+
+//
+//	Rigid Body Base
+//
+
+SEA3D.prototype.readRigidBodyBase = function ( sea ) {
+
+	var shape = sea.shape.tag,
+		transform, target;
+
+	if ( sea.target ) {
+
+		target = sea.target.tag;
+
+		target.physics = { enabled: true };
+		target.updateMatrix();
+
+		transform = AMMO.getTransformFromMatrix( sea.target.tag.matrix );
+
+	} else {
+
+		SEA3D.MTXBUF.fromArray( sea.transform );
+
+		transform = AMMO.getTransformFromMatrix( SEA3D.MTXBUF );
+
+	}
+
+	var motionState = new Ammo.btDefaultMotionState( transform );
+	var localInertia = new Ammo.btVector3( 0, 0, 0 );
+
+	shape.calculateLocalInertia( sea.mass, localInertia );
+
+	var info = new Ammo.btRigidBodyConstructionInfo( sea.mass, motionState, shape, localInertia );
+	info.set_m_friction( sea.friction );
+	info.set_m_restitution( sea.restitution );
+	info.set_m_linearDamping( sea.linearDamping );
+	info.set_m_angularDamping( sea.angularDamping );
+
+	var rb = new Ammo.btRigidBody( info );
+
+	if ( target ) {
+
+		target.physics.rigidBody = rb;
+
+		if ( sea.offset ) {
+
+			var offset = new Matrix4();
+			offset.fromArray( sea.offset );
+
+			target.physics.offset = offset;
+
+		}
+
+	}
+
+	Ammo.destroy( info );
+
+	this.domain.rigidBodies = this.rigidBodies = this.rigidBodies || [];
+	this.rigidBodies.push( this.objects[ "rb/" + sea.name ] = sea.tag = rb );
+
+	return rb;
+
+};
+
+//
+//	Rigid Body
+//
+
+SEA3D.prototype.readRigidBody = function ( sea ) {
+
+	var rb = this.readRigidBodyBase( sea );
+
+	AMMO.addRigidBody( rb, sea.target ? sea.target.tag : undefined, this.config.enabledPhysics );
+
+};
+
+//
+//	Car Controller
+//
+
+SEA3D.prototype.readCarController = function ( sea ) {
+
+	var body = this.readRigidBodyBase( sea );
+
+	body.setActivationState( AMMO.DISABLE_DEACTIVATION );
+
+	// Car
+
+	var vehicleRayCaster = new Ammo.btDefaultVehicleRaycaster( AMMO.world );
+
+	var tuning = new Ammo.btVehicleTuning();
+
+	tuning.set_m_suspensionStiffness( sea.suspensionStiffness );
+	tuning.set_m_suspensionDamping( sea.suspensionDamping );
+	tuning.set_m_suspensionCompression( sea.suspensionCompression );
+	tuning.set_m_maxSuspensionTravelCm( sea.maxSuspensionTravelCm );
+	tuning.set_m_maxSuspensionForce( sea.maxSuspensionForce );
+	tuning.set_m_frictionSlip( sea.frictionSlip );
+
+	var vehicle = new Ammo.btRaycastVehicle( tuning, body, vehicleRayCaster ),
+		wheels = [];
+
+	vehicle.setCoordinateSystem( 0, 1, 2 );
+
+	for ( var i = 0; i < sea.wheel.length; i ++ ) {
+
+		var wheel = sea.wheel[ i ];
+
+		var wheelInfo = vehicle.addWheel(
+			this.toAmmoVec3( wheel.pos ),
+			this.toAmmoVec3( wheel.dir ),
+			this.toAmmoVec3( wheel.axle ),
+			wheel.suspensionRestLength,
+			wheel.radius,
+			tuning,
+			wheel.isFront
+		);
+
+		var target = wheels[ i ] = wheel.target ? wheel.target.tag : undefined;
+
+		if ( target ) {
+
+			target.physics = { enabled: true, rigidBody: wheelInfo };
+
+			if ( wheel.offset ) {
+
+				var offset = new Matrix4();
+				offset.fromArray( wheel.offset );
+
+				target.physics.offset = offset;
+
+			}
+
+			if ( target.parent ) {
+
+				target.parent.remove( target );
+
+			}
+
+			if ( this.container ) {
+
+				this.container.add( target );
+
+			}
+
+		}
+
+		wheelInfo.set_m_suspensionStiffness( sea.suspensionStiffness );
+		wheelInfo.set_m_wheelsDampingRelaxation( sea.dampingRelaxation );
+		wheelInfo.set_m_wheelsDampingCompression( sea.dampingCompression );
+		wheelInfo.set_m_frictionSlip( sea.frictionSlip );
+
+	}
+
+	AMMO.addVehicle( vehicle, wheels );
+	AMMO.addRigidBody( body, sea.target ? sea.target.tag : undefined, this.config.enabledPhysics );
+
+	this.domain.vehicles = this.vehicles = this.vehicles || [];
+	this.vehicles.push( this.objects[ "vhc/" + sea.name ] = sea.tag = vehicle );
+
+};
+
+//
+//	P2P Constraint
+//
+
+SEA3D.prototype.readP2PConstraint = function ( sea ) {
+
+	var ctrt;
+
+	if ( sea.targetB ) {
+
+		ctrt = new Ammo.btPoint2PointConstraint(
+			sea.targetA.tag,
+			sea.targetB.tag,
+			this.toAmmoVec3( sea.pointA ),
+			this.toAmmoVec3( sea.pointB )
+		);
+
+	} else {
+
+		ctrt = new Ammo.btPoint2PointConstraint(
+			sea.targetA.tag,
+			this.toAmmoVec3( sea.pointA )
+		);
+
+	}
+
+	AMMO.addConstraint( ctrt );
+
+	this.domain.constraints = this.constraints = this.constraints || [];
+	this.constraints.push( this.objects[ "ctnt/" + sea.name ] = sea.tag = ctrt );
+
+};
+
+//
+//	Hinge Constraint
+//
+
+SEA3D.prototype.readHingeConstraint = function ( sea ) {
+
+	var ctrt;
+
+	if ( sea.targetB ) {
+
+		ctrt = new Ammo.btHingeConstraint(
+			sea.targetA.tag,
+			sea.targetB.tag,
+			this.toAmmoVec3( sea.pointA ),
+			this.toAmmoVec3( sea.pointB ),
+			this.toAmmoVec3( sea.axisA ),
+			this.toAmmoVec3( sea.axisB ),
+			false
+		);
+
+	} else {
+
+		ctrt = new Ammo.btHingeConstraint(
+			sea.targetA.tag,
+			this.toAmmoVec3( sea.pointA ),
+			this.toAmmoVec3( sea.axisA ),
+			false
+		);
+
+	}
+
+	if ( sea.limit ) {
+
+		ctrt.setLimit( sea.limit.low, sea.limit.high, sea.limit.softness, sea.limit.biasFactor, sea.limit.relaxationFactor );
+
+	}
+
+	if ( sea.angularMotor ) {
+
+		ctrt.enableAngularMotor( true, sea.angularMotor.velocity, sea.angularMotor.impulse );
+
+	}
+
+	AMMO.addConstraint( ctrt );
+
+	this.domain.constraints = this.constraints = this.constraints || [];
+	this.constraints.push( this.objects[ "ctnt/" + sea.name ] = sea.tag = ctrt );
+
+};
+
+//
+//	Cone Twist Constraint
+//
+
+SEA3D.prototype.readConeTwistConstraint = function ( sea ) {
+
+	var ctrt;
+
+	if ( sea.targetB ) {
+
+		ctrt = new Ammo.btConeTwistConstraint(
+			sea.targetA.tag,
+			sea.targetB.tag,
+			this.toAmmoVec3( sea.pointA ),
+			this.toAmmoVec3( sea.pointB ),
+			false
+		);
+
+	} else {
+
+		ctrt = new Ammo.btConeTwistConstraint(
+			sea.targetA.tag,
+			this.toAmmoVec3( sea.pointA ),
+			false
+		);
+
+	}
+
+	AMMO.addConstraint( ctrt );
+
+	this.domain.constraints = this.constraints = this.constraints || [];
+	this.constraints.push( this.objects[ "ctnt/" + sea.name ] = sea.tag = ctrt );
+
+};
+
+//
+//	Domain
+//
+
+SEA3D.Domain.prototype.enabledPhysics = function ( enabled ) {
+
+	var i = this.rigidBodies ? this.rigidBodies.length : 0;
+
+	while ( i -- ) {
+
+		AMMO.setEnabledRigidBody( this.rigidBodies[ i ], enabled );
+
+	}
+
+};
+
+SEA3D.Domain.prototype.applyContainerTransform = function () {
+
+	this.container.updateMatrix();
+
+	var matrix = this.container.matrix.clone();
+
+	this.container.position.set( 0, 0, 0 );
+	this.container.quaternion.set( 0, 0, 0, 1 );
+	this.container.scale.set( 1, 1, 1 );
+
+	this.applyTransform( matrix );
+
+};
+
+SEA3D.Domain.prototype.applyTransform = function ( matrix ) {
+
+	var mtx = SEA3D.MTXBUF, vec = SEA3D.VECBUF;
+
+	var i = this.rigidBodies ? this.rigidBodies.length : 0,
+		childs = this.container ? this.container.children : [],
+		targets = [];
+
+	while ( i -- ) {
+
+		var rb = this.rigidBodies[ i ],
+			target = AMMO.getTargetByRigidBody( rb ),
+			transform = rb.getWorldTransform(),
+			transformMatrix = AMMO.getMatrixFromTransform( transform );
+
+		transformMatrix.multiplyMatrices( transformMatrix, matrix );
+
+		transform = AMMO.getTransformFromMatrix( transformMatrix );
+
+		rb.setWorldTransform( transform );
+
+		if ( target ) targets.push( target );
+
+	}
+
+	for ( i = 0; i < childs.length; i ++ ) {
+
+		var obj3d = childs[ i ];
+
+		if ( targets.indexOf( obj3d ) > - 1 ) continue;
+
+		obj3d.updateMatrix();
+
+		mtx.copy( obj3d.matrix );
+
+		mtx.multiplyMatrices( matrix, mtx );
+
+		obj3d.position.setFromMatrixPosition( mtx );
+		obj3d.scale.setFromMatrixScale( mtx );
+
+		// ignore rotation scale
+
+		mtx.scale( vec.set( 1 / obj3d.scale.x, 1 / obj3d.scale.y, 1 / obj3d.scale.z ) );
+		obj3d.quaternion.setFromRotationMatrix( mtx );
+
+	}
+
+};
+
+//
+//	Extension
+//
+
+SEA3D.Domain.prototype.getShape = SEA3D.prototype.getShape = function ( name ) {
+
+	return this.objects[ "shpe/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getRigidBody = SEA3D.prototype.getRigidBody = function ( name ) {
+
+	return this.objects[ "rb/" + name ];
+
+};
+
+SEA3D.Domain.prototype.getConstraint = SEA3D.prototype.getConstraint = function ( name ) {
+
+	return this.objects[ "ctnt/" + name ];
+
+};
+
+SEA3D.EXTENSIONS_LOADER.push( {
+
+	parse: function () {
+
+		delete this.shapes;
+		delete this.rigidBodies;
+		delete this.vehicles;
+		delete this.constraints;
+
+	},
+
+	setTypeRead: function () {
+
+		// CONFIG
+
+		this.config.physics = this.config.physics !== undefined ? this.config.physics : true;
+		this.config.convexHull = this.config.convexHull !== undefined ? this.config.convexHull : true;
+		this.config.enabledPhysics = this.config.enabledPhysics !== undefined ? this.config.enabledPhysics : true;
+
+		if ( this.config.physics ) {
+
+			// SHAPES
+
+			this.file.typeRead[ SEA3DSDK.Sphere.prototype.type ] = this.readSphere;
+			this.file.typeRead[ SEA3DSDK.Box.prototype.type ] = this.readBox;
+			this.file.typeRead[ SEA3DSDK.Capsule.prototype.type ] = this.readCapsule;
+			this.file.typeRead[ SEA3DSDK.Cone.prototype.type ] = this.readCone;
+			this.file.typeRead[ SEA3DSDK.Cylinder.prototype.type ] = this.readCylinder;
+			this.file.typeRead[ SEA3DSDK.ConvexGeometry.prototype.type ] = this.readConvexGeometry;
+			this.file.typeRead[ SEA3DSDK.TriangleGeometry.prototype.type ] = this.readTriangleGeometry;
+			this.file.typeRead[ SEA3DSDK.Compound.prototype.type ] = this.readCompound;
+
+			// CONSTRAINTS
+
+			this.file.typeRead[ SEA3DSDK.P2PConstraint.prototype.type ] = this.readP2PConstraint;
+			this.file.typeRead[ SEA3DSDK.HingeConstraint.prototype.type ] = this.readHingeConstraint;
+			this.file.typeRead[ SEA3DSDK.ConeTwistConstraint.prototype.type ] = this.readConeTwistConstraint;
+
+			// PHYSICS
+
+			this.file.typeRead[ SEA3DSDK.RigidBody.prototype.type ] = this.readRigidBody;
+			this.file.typeRead[ SEA3DSDK.CarController.prototype.type ] = this.readCarController;
+
+		}
+
+	}
+} );
+
+SEA3D.EXTENSIONS_DOMAIN.push( {
+
+	dispose: function () {
+
+		var i;
+
+		i = this.rigidBodies ? this.rigidBodies.length : 0;
+		while ( i -- ) AMMO.removeRigidBody( this.rigidBodies[ i ], true );
+
+		i = this.vehicles ? this.vehicles.length : 0;
+		while ( i -- ) AMMO.removeVehicle( this.vehicles[ i ], true );
+
+		i = this.constraints ? this.constraints.length : 0;
+		while ( i -- ) AMMO.removeConstraint( this.constraints[ i ], true );
+
+		i = this.shapes ? this.shapes.length : 0;
+		while ( i -- ) Ammo.destroy( this.shapes[ i ] );
+
+	}
+
+} );
+
+export { AMMO };

+ 442 - 0
examples/jsm/loaders/sea3d/physics/SEA3DSDKRigidBody.js

@@ -0,0 +1,442 @@
+/**
+ * 	SEA3D - Rigid Body
+ * 	@author Sunag / http://www.sunag.com.br/
+ */
+
+import { SEA3DSDK } from "../SEA3DSDK.js";
+
+//
+//	Sphere
+//
+
+SEA3DSDK.Sphere = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.radius = data.readFloat();
+
+};
+
+SEA3DSDK.Sphere.prototype.type = "sph";
+
+//
+//	Box
+//
+
+SEA3DSDK.Box = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.width = data.readFloat();
+	this.height = data.readFloat();
+	this.depth = data.readFloat();
+
+};
+
+SEA3DSDK.Box.prototype.type = "box";
+
+//
+//	Cone
+//
+
+SEA3DSDK.Cone = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.radius = data.readFloat();
+	this.height = data.readFloat();
+
+};
+
+SEA3DSDK.Cone.prototype.type = "cone";
+
+//
+//	Capsule
+//
+
+SEA3DSDK.Capsule = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.radius = data.readFloat();
+	this.height = data.readFloat();
+
+};
+
+SEA3DSDK.Capsule.prototype.type = "cap";
+
+//
+//	Cylinder
+//
+
+SEA3DSDK.Cylinder = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.radius = data.readFloat();
+	this.height = data.readFloat();
+
+};
+
+SEA3DSDK.Cylinder.prototype.type = "cyl";
+
+//
+//	Convex Geometry
+//
+
+SEA3DSDK.ConvexGeometry = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.geometry = sea3d.getObject( data.readUInt() );
+	this.subGeometryIndex = data.readUByte();
+
+};
+
+SEA3DSDK.ConvexGeometry.prototype.type = "gs";
+
+//
+//	Triangle Geometry
+//
+
+SEA3DSDK.TriangleGeometry = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.geometry = sea3d.getObject( data.readUInt() );
+	this.subGeometryIndex = data.readUByte();
+
+};
+
+SEA3DSDK.TriangleGeometry.prototype.type = "sgs";
+
+//
+//	Compound
+//
+
+SEA3DSDK.Compound = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.compounds = [];
+
+	var count = data.readUByte();
+
+	for ( var i = 0; i < count; i ++ ) {
+
+		this.compounds.push( {
+			shape: sea3d.getObject( data.readUInt() ),
+			transform: data.readMatrix()
+		} );
+
+	}
+
+};
+
+SEA3DSDK.Compound.prototype.type = "cmps";
+
+//
+//	Physics
+//
+
+SEA3DSDK.Physics = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUShort();
+
+	this.shape = sea3d.getObject( data.readUInt() );
+
+	if ( this.attrib & 1 ) this.target = sea3d.getObject( data.readUInt() );
+	else this.transform = data.readMatrix();
+
+	if ( this.attrib & 2 ) this.offset = data.readMatrix();
+
+	if ( this.attrib & 4 ) this.scripts = data.readScriptList( sea3d );
+
+	if ( this.attrib & 16 ) this.attributes = sea3d.getObject( data.readUInt() );
+
+};
+
+SEA3DSDK.Physics.prototype.readTag = function ( kind, data, size ) {
+
+};
+
+//
+//	Rigidy Body Base
+//
+
+SEA3DSDK.RigidBodyBase = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Physics.call( this, name, data, sea3d );
+
+	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();
+
+};
+
+SEA3DSDK.RigidBodyBase.prototype = Object.create( SEA3DSDK.Physics.prototype );
+SEA3DSDK.RigidBodyBase.prototype.constructor = SEA3DSDK.RigidBodyBase;
+
+//
+//	Rigidy Body
+//
+
+SEA3DSDK.RigidBody = function ( name, data, sea3d ) {
+
+	SEA3DSDK.RigidBodyBase.call( this, name, data, sea3d );
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.RigidBody.prototype = Object.create( SEA3DSDK.RigidBodyBase.prototype );
+SEA3DSDK.RigidBody.prototype.constructor = SEA3DSDK.RigidBody;
+
+SEA3DSDK.RigidBody.prototype.type = "rb";
+
+//
+//	Car Controller
+//
+
+SEA3DSDK.CarController = function ( name, data, sea3d ) {
+
+	SEA3DSDK.RigidBodyBase.call( this, name, data, sea3d );
+
+	this.suspensionStiffness = data.readFloat();
+	this.suspensionCompression = data.readFloat();
+	this.suspensionDamping = data.readFloat();
+	this.maxSuspensionTravelCm = data.readFloat();
+	this.frictionSlip = data.readFloat();
+	this.maxSuspensionForce = data.readFloat();
+
+	this.dampingCompression = data.readFloat();
+	this.dampingRelaxation = data.readFloat();
+
+	var count = data.readUByte();
+
+	this.wheel = [];
+
+	for ( var i = 0; i < count; i ++ ) {
+
+		this.wheel[ i ] = new SEA3DSDK.CarController.Wheel( data, sea3d );
+
+	}
+
+	data.readTags( this.readTag.bind( this ) );
+
+};
+
+SEA3DSDK.CarController.Wheel = function ( data, sea3d ) {
+
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUShort();
+
+	this.isFront = ( this.attrib & 1 ) != 0;
+
+	if ( this.attrib & 2 ) {
+
+		this.target = sea3d.getObject( data.readUInt() );
+
+	}
+
+	if ( this.attrib & 4 ) {
+
+		this.offset = data.readMatrix();
+
+	}
+
+	this.pos = data.readVector3();
+	this.dir = data.readVector3();
+	this.axle = data.readVector3();
+
+	this.radius = data.readFloat();
+	this.suspensionRestLength = data.readFloat();
+
+};
+
+SEA3DSDK.CarController.prototype = Object.create( SEA3DSDK.RigidBodyBase.prototype );
+SEA3DSDK.CarController.prototype.constructor = SEA3DSDK.CarController;
+
+SEA3DSDK.CarController.prototype.type = "carc";
+
+//
+//	Constraints
+//
+
+SEA3DSDK.Constraints = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	this.attrib = data.readUShort();
+
+	this.disableCollisionsBetweenBodies = this.attrib & 1 != 0;
+
+	this.targetA = sea3d.getObject( data.readUInt() );
+	this.pointA = data.readVector3();
+
+	if ( this.attrib & 2 ) {
+
+		this.targetB = sea3d.getObject( data.readUInt() );
+		this.pointB = data.readVector3();
+
+	}
+
+};
+
+//
+//	P2P Constraint
+//
+
+SEA3DSDK.P2PConstraint = function ( name, data, sea3d ) {
+
+	this.name = name;
+	this.data = data;
+	this.sea3d = sea3d;
+
+	SEA3DSDK.Constraints.call( this, name, data, sea3d );
+
+};
+
+SEA3DSDK.P2PConstraint.prototype = Object.create( SEA3DSDK.Constraints.prototype );
+SEA3DSDK.P2PConstraint.prototype.constructor = SEA3DSDK.P2PConstraint;
+
+SEA3DSDK.P2PConstraint.prototype.type = "p2pc";
+
+//
+//	Hinge Constraint
+//
+
+SEA3DSDK.HingeConstraint = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Constraints.call( this, name, data, sea3d );
+
+	this.axisA = data.readVector3();
+
+	if ( this.attrib & 1 ) {
+
+		this.axisB = data.readVector3();
+
+	}
+
+	if ( this.attrib & 4 ) {
+
+		this.limit = {
+			low: data.readFloat(),
+			high: data.readFloat(),
+			softness: data.readFloat(),
+			biasFactor: data.readFloat(),
+			relaxationFactor: data.readFloat()
+		};
+
+	}
+
+	if ( this.attrib & 8 ) {
+
+		this.angularMotor = {
+			velocity: data.readFloat(),
+			impulse: data.readFloat()
+		};
+
+	}
+
+};
+
+SEA3DSDK.HingeConstraint.prototype = Object.create( SEA3DSDK.Constraints.prototype );
+SEA3DSDK.HingeConstraint.prototype.constructor = SEA3DSDK.HingeConstraint;
+
+SEA3DSDK.HingeConstraint.prototype.type = "hnec";
+
+//
+//	Cone Twist Constraint
+//
+
+SEA3DSDK.ConeTwistConstraint = function ( name, data, sea3d ) {
+
+	SEA3DSDK.Constraints.call( this, name, data, sea3d );
+
+	this.axisA = data.readVector3();
+
+	if ( this.attrib & 1 ) {
+
+		this.axisB = data.readVector3();
+
+	}
+
+	if ( this.attrib & 4 ) {
+
+		this.limit = {
+			swingSpan1: data.readFloat(),
+			swingSpan2: data.readFloat(),
+			twistSpan: data.readFloat(),
+			softness: data.readFloat(),
+			biasFactor: data.readFloat(),
+			relaxationFactor: data.readFloat()
+		};
+
+	}
+
+};
+
+SEA3DSDK.ConeTwistConstraint.prototype = Object.create( SEA3DSDK.Constraints.prototype );
+SEA3DSDK.ConeTwistConstraint.prototype.constructor = SEA3DSDK.ConeTwistConstraint;
+
+SEA3DSDK.ConeTwistConstraint.prototype.type = "ctwc";
+
+//
+//	Extension
+//
+
+SEA3DSDK.File.setExtension( function () {
+
+	// PHYSICS
+	this.addClass( SEA3DSDK.Sphere );
+	this.addClass( SEA3DSDK.Box );
+	this.addClass( SEA3DSDK.Cone );
+	this.addClass( SEA3DSDK.Capsule );
+	this.addClass( SEA3DSDK.Cylinder );
+	this.addClass( SEA3DSDK.ConvexGeometry );
+	this.addClass( SEA3DSDK.TriangleGeometry );
+	this.addClass( SEA3DSDK.Compound );
+	this.addClass( SEA3DSDK.RigidBody );
+	this.addClass( SEA3DSDK.P2PConstraint );
+	this.addClass( SEA3DSDK.HingeConstraint );
+	this.addClass( SEA3DSDK.ConeTwistConstraint );
+	this.addClass( SEA3DSDK.CarController );
+
+} );

BIN
examples/models/sea3d/mascot.o3dgc.tjs.sea


BIN
examples/models/sea3d/robot.tjs.sea


+ 37 - 38
examples/webgl_loader_sea3d.html

@@ -13,35 +13,34 @@
 			Geometry Compression with <a href="https://github.com/google/draco" target="_blank" rel="noopener">Google Draco</a> and content with LZMA using <a href="http://sunag.github.io/sea3d/IO/index.html" style="color:#FFFFFF" target="_blank">SEA3D I.O.</a> Tools<br>
 			Geometry Compression with <a href="https://github.com/google/draco" target="_blank" rel="noopener">Google Draco</a> and content with LZMA using <a href="http://sunag.github.io/sea3d/IO/index.html" style="color:#FFFFFF" target="_blank">SEA3D I.O.</a> Tools<br>
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
-
-		<script src="js/controls/OrbitControls.js"></script>
-
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
-
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
-
 		<script src="js/libs/draco/draco_decoder.js"></script>
 		<script src="js/libs/draco/draco_decoder.js"></script>
-		<script src="js/loaders/sea3d/SEA3DDraco.js"></script>
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+		<script type="module">
 
 
-		<script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-			if ( WEBGL.isWebGLAvailable() === false ) {
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-			}
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
+			import './jsm/loaders/sea3d/SEA3DDraco.js'; // sea3d draco extension
+
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -59,7 +58,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: true, // Auto play animations
 				autoPlay: true, // Auto play animations
 				container: scene, // Container to add models
 				container: scene, // Container to add models
@@ -86,42 +85,42 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
 				camera.position.set( 1000, 1000, 1000 );
 				camera.position.set( 1000, 1000, 1000 );
 				camera.lookAt( 0, 0, 0 );
 				camera.lookAt( 0, 0, 0 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 
-				controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls = new OrbitControls( camera, renderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
 				container.appendChild( stats.dom );
 				container.appendChild( stats.dom );
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -146,7 +145,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -155,7 +154,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 73 - 66
examples/webgl_loader_sea3d_bvh.html

@@ -12,35 +12,42 @@
 			Runtime convertion of BVH Animation to SEA3D Skeleton Animation
 			Runtime convertion of BVH Animation to SEA3D Skeleton Animation
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
-
-		<script src="js/controls/OrbitControls.js"></script>
-
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
-
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
-
-		<script src="js/loaders/BVHLoader.js"></script>
-		<script src="js/utils/SkeletonUtils.js"></script>
-
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+		<script type="module">
+
+			import {
+				Vector3,
+				Color,
+				Matrix4,
+				Euler,
+				Math,
+				Clock,
+				Group,
+				Object3D,
+				AnimationMixer,
+				SkeletonHelper,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
+
+			import { BVHLoader } from './jsm/loaders/BVHLoader.js';
+
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
+
+			import { SkeletonUtils } from './jsm/utils/SkeletonUtils.js';
+
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -60,7 +67,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: true, // Auto play animations
 				autoPlay: true, // Auto play animations
 				container: scene, // Container to add models
 				container: scene, // Container to add models
@@ -77,7 +84,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				new THREE.OrbitControls( camera, renderer.domElement );
+				new OrbitControls( camera, renderer.domElement );
 
 
 				// get meshes
 				// get meshes
 				player = loader.getMesh( "Player" );
 				player = loader.getMesh( "Player" );
@@ -128,49 +135,49 @@
 				};
 				};
 
 
 				// Automatic offset: get offsets when it is in T-Pose
 				// Automatic offset: get offsets when it is in T-Pose
-				options.offsets = THREE.SkeletonUtils.getSkeletonOffsets( player, bvhSkeletonHelper, options );
+				options.offsets = SkeletonUtils.getSkeletonOffsets( player, bvhSkeletonHelper, options );
 
 
 				/*
 				/*
 				// Manual offsets: compensates the difference in skeletons ( T-Pose )
 				// Manual offsets: compensates the difference in skeletons ( T-Pose )
 				options.offsets = {
 				options.offsets = {
-					"lShldr": new THREE.Matrix4().makeRotationFromEuler(
-						new THREE.Euler(
+					"lShldr": new Matrix4().makeRotationFromEuler(
+						new Euler(
 							0,
 							0,
-							THREE.Math.degToRad( - 45 ),
-							THREE.Math.degToRad( - 80 )
+							Math.degToRad( - 45 ),
+							Math.degToRad( - 80 )
 						)
 						)
 					),
 					),
-					"rShldr": new THREE.Matrix4().makeRotationFromEuler(
-						new THREE.Euler(
+					"rShldr": new Matrix4().makeRotationFromEuler(
+						new Euler(
 							0,
 							0,
-							THREE.Math.degToRad( 45 ),
-							THREE.Math.degToRad( 80 )
+							Math.degToRad( 45 ),
+							Math.degToRad( 80 )
 						)
 						)
 					),
 					),
-					"lFoot": new THREE.Matrix4().makeRotationFromEuler(
-						new THREE.Euler(
+					"lFoot": new Matrix4().makeRotationFromEuler(
+						new Euler(
 							0,
 							0,
-							THREE.Math.degToRad( 15 ),
+							Math.degToRad( 15 ),
 							0
 							0
 						)
 						)
 					),
 					),
-					"rFoot": new THREE.Matrix4().makeRotationFromEuler(
-						new THREE.Euler(
+					"rFoot": new Matrix4().makeRotationFromEuler(
+						new Euler(
 							0,
 							0,
-							THREE.Math.degToRad( 15 ),
+							Math.degToRad( 15 ),
 							0
 							0
 						)
 						)
 					)
 					)
 				};
 				};
 				*/
 				*/
 
 
-				var clip = THREE.SkeletonUtils.retargetClip( player, result.skeleton, result.clip, options );
+				var clip = SkeletonUtils.retargetClip( player, result.skeleton, result.clip, options );
 
 
 				clip.name = "dance";
 				clip.name = "dance";
 
 
-				clip = THREE.SEA3D.AnimationClip.fromClip( clip );
+				clip = SEA3D.AnimationClip.fromClip( clip );
 
 
-				player.addAnimation( new THREE.SEA3D.Animation( clip ) );
+				player.addAnimation( new SEA3D.Animation( clip ) );
 
 
 				player.play( "dance" );
 				player.play( "dance" );
 
 
@@ -179,13 +186,13 @@
 
 
 			function loadBVH() {
 			function loadBVH() {
 
 
-				var loader = new THREE.BVHLoader();
+				var loader = new BVHLoader();
 				loader.load( "models/bvh/pirouette.bvh", function ( result ) {
 				loader.load( "models/bvh/pirouette.bvh", function ( result ) {
 
 
-					bvhSkeletonHelper = new THREE.SkeletonHelper( result.skeleton.bones[ 0 ] );
+					bvhSkeletonHelper = new SkeletonHelper( result.skeleton.bones[ 0 ] );
 					bvhSkeletonHelper.skeleton = result.skeleton; // allow animation mixer to bind to SkeletonHelper directly
 					bvhSkeletonHelper.skeleton = result.skeleton; // allow animation mixer to bind to SkeletonHelper directly
 
 
-					var boneContainer = new THREE.Group();
+					var boneContainer = new Group();
 					boneContainer.add( result.skeleton.bones[ 0 ] );
 					boneContainer.add( result.skeleton.bones[ 0 ] );
 					boneContainer.position.y = - 100;
 					boneContainer.position.y = - 100;
 
 
@@ -193,7 +200,7 @@
 					scene.add( boneContainer );
 					scene.add( boneContainer );
 
 
 					// play animation
 					// play animation
-					bvhMixer = new THREE.AnimationMixer( bvhSkeletonHelper );
+					bvhMixer = new AnimationMixer( bvhSkeletonHelper );
 					bvhMixer.clipAction( result.clip ).setEffectiveWeight( 1.0 ).play();
 					bvhMixer.clipAction( result.clip ).setEffectiveWeight( 1.0 ).play();
 
 
 					bvhToSEA3D( result );
 					bvhToSEA3D( result );
@@ -204,16 +211,16 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
 				camera.position.set( 1000, - 300, 1000 );
 				camera.position.set( 1000, - 300, 1000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -223,20 +230,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -260,7 +267,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -269,7 +276,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				if ( bvhMixer ) bvhMixer.update( delta );
 				if ( bvhMixer ) bvhMixer.update( delta );
 
 

+ 47 - 43
examples/webgl_loader_sea3d_bvh_retarget.html

@@ -12,35 +12,39 @@
 			Runtime retarget of BVH Animation to SEA3D Skeleton
 			Runtime retarget of BVH Animation to SEA3D Skeleton
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
+		<script type="module">
 
 
-		<script src="js/controls/OrbitControls.js"></script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				Group,
+				Object3D,
+				AnimationMixer,
+				SkeletonHelper,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-		<script src="js/loaders/BVHLoader.js"></script>
-		<script src="js/utils/SkeletonUtils.js"></script>
+			import { BVHLoader } from './jsm/loaders/BVHLoader.js';
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
 
 
-		<script>
+			import { SkeletonUtils } from './jsm/utils/SkeletonUtils.js';
 
 
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -60,7 +64,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: false, // Auto play animations
 				autoPlay: false, // Auto play animations
 				container: scene, // Container to add models
 				container: scene, // Container to add models
@@ -77,7 +81,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				new THREE.OrbitControls( camera, renderer.domElement );
+				new OrbitControls( camera, renderer.domElement );
 
 
 				// get meshes
 				// get meshes
 				player = loader.getMesh( "Player" );
 				player = loader.getMesh( "Player" );
@@ -126,13 +130,13 @@
 
 
 			function loadBVH() {
 			function loadBVH() {
 
 
-				var loader = new THREE.BVHLoader();
+				var loader = new BVHLoader();
 				loader.load( "models/bvh/pirouette.bvh", function ( result ) {
 				loader.load( "models/bvh/pirouette.bvh", function ( result ) {
 
 
-					bvhSkeletonHelper = new THREE.SkeletonHelper( result.skeleton.bones[ 0 ] );
+					bvhSkeletonHelper = new SkeletonHelper( result.skeleton.bones[ 0 ] );
 					bvhSkeletonHelper.skeleton = result.skeleton; // allow animation mixer to bind to SkeletonHelper directly
 					bvhSkeletonHelper.skeleton = result.skeleton; // allow animation mixer to bind to SkeletonHelper directly
 
 
-					var boneContainer = new THREE.Group();
+					var boneContainer = new Group();
 					boneContainer.add( result.skeleton.bones[ 0 ] );
 					boneContainer.add( result.skeleton.bones[ 0 ] );
 					boneContainer.position.z = - 100;
 					boneContainer.position.z = - 100;
 					boneContainer.position.y = - 100;
 					boneContainer.position.y = - 100;
@@ -141,10 +145,10 @@
 					scene.add( boneContainer );
 					scene.add( boneContainer );
 
 
 					// get offsets when it is in T-Pose
 					// get offsets when it is in T-Pose
-					options.offsets = THREE.SkeletonUtils.getSkeletonOffsets( player, bvhSkeletonHelper, options );
+					options.offsets = SkeletonUtils.getSkeletonOffsets( player, bvhSkeletonHelper, options );
 
 
 					// play animation
 					// play animation
-					bvhMixer = new THREE.AnimationMixer( bvhSkeletonHelper );
+					bvhMixer = new AnimationMixer( bvhSkeletonHelper );
 					bvhMixer.clipAction( result.clip ).setEffectiveWeight( 1.0 ).play();
 					bvhMixer.clipAction( result.clip ).setEffectiveWeight( 1.0 ).play();
 
 
 				} );
 				} );
@@ -153,16 +157,16 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
 				camera.position.set( 1000, - 300, 1000 );
 				camera.position.set( 1000, - 300, 1000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -172,20 +176,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -209,7 +213,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -218,13 +222,13 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				if ( bvhMixer ) {
 				if ( bvhMixer ) {
 
 
 					bvhMixer.update( delta );
 					bvhMixer.update( delta );
 
 
-					THREE.SkeletonUtils.retarget( player, bvhSkeletonHelper, options );
+					SkeletonUtils.retarget( player, bvhSkeletonHelper, options );
 
 
 				}
 				}
 
 

+ 38 - 41
examples/webgl_loader_sea3d_hierarchy.html

@@ -9,38 +9,35 @@
 	<body>
 	<body>
 		<div id="info">
 		<div id="info">
 			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Exported by <a href="https://github.com/sunag/sea3d" target="_blank" rel="noopener">SEA3D Exporter</a> and edited by <a href="https://github.com/sunag/sea3d" target="_blank" rel="noopener">SEA3D Studio</a>.<br/>Asset by <a href="http://vhalldez.cgsociety.org/" target="_blank" rel="noopener">Valdez Araujo</a>.
 			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Exported by <a href="https://github.com/sunag/sea3d" target="_blank" rel="noopener">SEA3D Exporter</a> and edited by <a href="https://github.com/sunag/sea3d" target="_blank" rel="noopener">SEA3D Studio</a>.<br/>Asset by <a href="http://vhalldez.cgsociety.org/" target="_blank" rel="noopener">Valdez Araujo</a>.
-			High geometry compression with <a href="https://github.com/amd/rest3d/tree/master/server/o3dgc" target="_blank" rel="noopener">Open3DGC</a> and LZMA.
+			Geometry compression lossless with LZMA.
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
+		<script type="module">
 
 
-		<script src="js/controls/OrbitControls.js"></script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				PerspectiveCamera,
+				PCFSoftShadowMap,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-		<script src="js/libs/o3dgc.js"></script>
-		<script src="js/loaders/sea3d/o3dgc/SEA3DGC.js"></script>
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -58,7 +55,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: false, // Auto play animations
 				autoPlay: false, // Auto play animations
 				container: scene // Container to add models
 				container: scene // Container to add models
@@ -83,7 +80,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				new THREE.OrbitControls( camera, renderer.domElement );
+				new OrbitControls( camera, renderer.domElement );
 
 
 				animate();
 				animate();
 
 
@@ -96,19 +93,19 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.shadowMap.enabled = true;
 				renderer.shadowMap.enabled = true;
-				renderer.shadowMap.type = THREE.PCFSoftShadowMap;
+				renderer.shadowMap.type = PCFSoftShadowMap;
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
@@ -116,23 +113,23 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
+				var renderPass = new RenderPass( scene, camera );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( copyPass );
 				composer.addPass( copyPass );
 
 
 				// events
 				// events
@@ -154,7 +151,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -163,7 +160,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 35 - 36
examples/webgl_loader_sea3d_keyframe.html

@@ -12,32 +12,31 @@
 			<div id="description">Click to play</div>
 			<div id="description">Click to play</div>
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
+		<script type="module">
 
 
-		<script src="js/controls/OrbitControls.js"></script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
 
 
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -55,7 +54,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: false, // Manual play animations
 				autoPlay: false, // Manual play animations
 				container: scene // Container to add models
 				container: scene // Container to add models
@@ -71,7 +70,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				new THREE.OrbitControls( camera, renderer.domElement );
+				new OrbitControls( camera, renderer.domElement );
 
 
 				// events
 				// events
 
 
@@ -126,16 +125,16 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
 				camera.position.set( 1000, - 300, 1000 );
 				camera.position.set( 1000, - 300, 1000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -145,20 +144,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -255,7 +254,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -264,7 +263,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 35 - 36
examples/webgl_loader_sea3d_morph.html

@@ -12,32 +12,31 @@
 			<div id="description">Flag is Vertex Animation / Teapot is Morpher</div>
 			<div id="description">Flag is Vertex Animation / Teapot is Morpher</div>
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
+		<script type="module">
 
 
-		<script src="js/controls/OrbitControls.js"></script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
 
 
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -55,7 +54,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: true, // Auto play animations
 				autoPlay: true, // Auto play animations
 				scripts: false, // Disable embed scripts
 				scripts: false, // Disable embed scripts
@@ -72,7 +71,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				new THREE.OrbitControls( camera, renderer.domElement );
+				new OrbitControls( camera, renderer.domElement );
 
 
 				// get mesh
 				// get mesh
 
 
@@ -92,16 +91,16 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
 				camera.position.set( 1000, - 300, 1000 );
 				camera.position.set( 1000, - 300, 1000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -111,20 +110,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -160,7 +159,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -169,7 +168,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 42 - 45
examples/webgl_loader_sea3d_physics.html

@@ -13,37 +13,35 @@
 			<div id="description">Right click to clone</div>
 			<div id="description">Right click to clone</div>
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
-
-		<script src="js/controls/OrbitControls.js"></script>
-
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
-
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
-
 		<script src="js/libs/ammo.js"></script>
 		<script src="js/libs/ammo.js"></script>
-		<script src="js/loaders/sea3d/physics/SEA3DRigidBody.js"></script>
-		<script src="js/loaders/sea3d/physics/SEA3DAmmo.js"></script>
-		<script src="js/loaders/sea3d/physics/SEA3DAmmoLoader.js"></script>
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+		<script type="module">
 
 
-		<script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-			if ( WEBGL.isWebGLAvailable() === false ) {
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-			}
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import { AMMO } from './jsm/loaders/sea3d/physics/SEA3DAmmoLoader.js'; // sea3d ammo.js extension
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
+			import './jsm/loaders/sea3d/physics/SEA3DSDKRigidBody.js'; // sea3d physics extension
+
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -62,13 +60,13 @@
 				// Initialize Physics Engine
 				// Initialize Physics Engine
 
 
 				Ammo = AmmoLib;
 				Ammo = AmmoLib;
-				SEA3D.AMMO.init();
+				AMMO.init();
 
 
 				//
 				//
 				// SEA3D Loader
 				// SEA3D Loader
 				//
 				//
 
 
-				loader = new THREE.SEA3D( {
+				loader = new SEA3D( {
 
 
 					container: scene // Container to add models
 					container: scene // Container to add models
 
 
@@ -76,7 +74,7 @@
 
 
 				loader.onComplete = function () {
 				loader.onComplete = function () {
 
 
-					new THREE.OrbitControls( camera, renderer.domElement );
+					new OrbitControls( camera, renderer.domElement );
 
 
 					// events
 					// events
 
 
@@ -104,7 +102,7 @@
 
 
 					return function () {
 					return function () {
 
 
-						var domain = this.loader.clone( { lights: false, runScripts: false, autoPlay: false, enabledPhysics: false } );
+						var domain = loader.clone( { lights: false, runScripts: false, autoPlay: false, enabledPhysics: false } );
 
 
 						offset -= 180;
 						offset -= 180;
 
 
@@ -113,29 +111,28 @@
 						domain.enabledPhysics( true );
 						domain.enabledPhysics( true );
 						domain.runScripts();
 						domain.runScripts();
 
 
-						this.scene.add( domain.container );
+						scene.add( domain.container );
 
 
 					};
 					};
 
 
 				}();
 				}();
 
 
-
 			} );
 			} );
 
 
 			//
 			//
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 15000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 15000 );
 				camera.position.set( 300, 200, - 300 );
 				camera.position.set( 300, 200, - 300 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -145,20 +142,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -182,7 +179,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -192,11 +189,11 @@
 
 
 				// Update Physics Engine ( fix delta-time in 60fps for more stability )
 				// Update Physics Engine ( fix delta-time in 60fps for more stability )
 
 
-				SEA3D.AMMO.update( 1 / 60 );
+				AMMO.update( 1 / 60 );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
 
 
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 38 - 38
examples/webgl_loader_sea3d_skinning.html

@@ -14,32 +14,32 @@
 			<div id="playercount"></div>
 			<div id="playercount"></div>
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
+		<script type="module">
 
 
-		<script src="js/controls/OrbitControls.js"></script>
+			import {
+				Vector3,
+				Color,
+				Clock,
+				Object3D,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
 
 
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 
 
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
 
 
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
 
 
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -57,7 +57,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: true, // Auto play animations
 				autoPlay: true, // Auto play animations
 				container: scene, // Container to add models
 				container: scene, // Container to add models
@@ -74,7 +74,7 @@
 				camera.position.copy( cam.position );
 				camera.position.copy( cam.position );
 				camera.rotation.copy( cam.rotation );
 				camera.rotation.copy( cam.rotation );
 
 
-				var controls = new THREE.OrbitControls( camera, renderer.domElement );
+				var controls = new OrbitControls( camera, renderer.domElement );
 
 
 				// get meshes
 				// get meshes
 				player = loader.getMesh( "Player" );
 				player = loader.getMesh( "Player" );
@@ -86,7 +86,7 @@
 
 
 				// or
 				// or
 
 
-				player.animation[ 'pass#1' ].addEventListener( THREE.SEA3D.Animation.COMPLETE, function ( e ) {
+				player.animation[ 'pass#1' ].addEventListener( SEA3D.Animation.COMPLETE, function ( e ) {
 
 
 					console.log( "Animation completed!", e );
 					console.log( "Animation completed!", e );
 
 
@@ -122,7 +122,7 @@
 					var PHI = Math.PI * 2 * ( Math.sqrt( 5 ) + 1 ) / 2; // golden ratio
 					var PHI = Math.PI * 2 * ( Math.sqrt( 5 ) + 1 ) / 2; // golden ratio
 					var angle = PHI * count ++;
 					var angle = PHI * count ++;
 
 
-					var container = new THREE.Object3D();
+					var container = new Object3D();
 					container.position.z = ( size * count ) * Math.cos( angle );
 					container.position.z = ( size * count ) * Math.cos( angle );
 					container.position.x = ( size * count ) * Math.sin( angle );
 					container.position.x = ( size * count ) * Math.sin( angle );
 
 
@@ -140,16 +140,16 @@
 
 
 			function init() {
 			function init() {
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 );
 				camera.position.set( 1000, - 300, 1000 );
 				camera.position.set( 1000, - 300, 1000 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -159,20 +159,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -222,7 +222,7 @@
 
 
 			//
 			//
 
 
-			var clock = new THREE.Clock();
+			var clock = new Clock();
 
 
 			function animate() {
 			function animate() {
 
 
@@ -231,7 +231,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );
 
 

+ 51 - 48
examples/webgl_loader_sea3d_sound.html

@@ -57,32 +57,35 @@
 
 
 		</div>
 		</div>
 
 
-		<script src="../build/three.js"></script>
-
-		<script src="js/controls/PointerLockControls.js"></script>
-
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-		<script src="js/shaders/ColorCorrectionShader.js"></script>
-		<script src="js/shaders/VignetteShader.js"></script>
-
-		<script src="js/loaders/sea3d/SEA3D.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLZMA.js"></script>
-		<script src="js/loaders/sea3d/SEA3DLoader.js"></script>
-
-		<script src="js/WebGL.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
-		<script>
-
-			if ( WEBGL.isWebGLAvailable() === false ) {
-
-				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
-
-			}
+		<script type="module">
+
+			import {
+				Vector3,
+				Color,
+				Euler,
+				Clock,
+				AudioAnalyser,
+				AudioLoader,
+				Raycaster,
+				PerspectiveCamera,
+				Scene,
+				WebGLRenderer
+			} from "../build/three.module.js";
+
+			import { PointerLockControls } from './jsm/controls/PointerLockControls.js';
+
+			import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
+			import { RenderPass } from './jsm/postprocessing/RenderPass.js';
+			import { ShaderPass } from './jsm/postprocessing/ShaderPass.js';
+			import { MaskPass } from './jsm/postprocessing/MaskPass.js';
+			import { CopyShader } from './jsm/shaders/CopyShader.js';
+			import { ColorCorrectionShader } from './jsm/shaders/ColorCorrectionShader.js';
+			import { VignetteShader } from './jsm/shaders/VignetteShader.js';
+
+			import { SEA3D } from './jsm/loaders/sea3d/SEA3DLoader.js';
+			import './jsm/loaders/sea3d/SEA3DLZMA.js'; // sea3d lzma extension
+
+			import Stats from './jsm/libs/stats.module.js';
 
 
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 			console.log( "Visit https://github.com/sunag/sea3d to all codes and builds under development." );
 
 
@@ -105,7 +108,7 @@
 			// SEA3D Loader
 			// SEA3D Loader
 			//
 			//
 
 
-			loader = new THREE.SEA3D( {
+			loader = new SEA3D( {
 
 
 				autoPlay: true, // Auto play animations
 				autoPlay: true, // Auto play animations
 				container: scene // Container to add models
 				container: scene // Container to add models
@@ -128,14 +131,14 @@
 				lightOutside = loader.getLight( "Light1" );
 				lightOutside = loader.getLight( "Light1" );
 
 
 				var soundOutside = loader.getSound3D( "Point001" );
 				var soundOutside = loader.getSound3D( "Point001" );
-				soundOutsideAnalyser = new THREE.AudioAnalyser( soundOutside, 32 );
+				soundOutsideAnalyser = new AudioAnalyser( soundOutside, 32 );
 
 
 				// sound asset 2 + area
 				// sound asset 2 + area
 
 
 				lightArea = loader.getLight( "Light2" );
 				lightArea = loader.getLight( "Light2" );
 
 
 				soundArea = loader.getSound3D( "Point002" );
 				soundArea = loader.getSound3D( "Point002" );
-				soundAreaAnalyser = new THREE.AudioAnalyser( soundArea, 512 );
+				soundAreaAnalyser = new AudioAnalyser( soundArea, 512 );
 
 
 				collisionArea = loader.getMesh( "Torus003" );
 				collisionArea = loader.getMesh( "Torus003" );
 
 
@@ -280,25 +283,25 @@
 
 
 			function init() {
 			function init() {
 
 
-				raycaster = new THREE.Raycaster();
+				raycaster = new Raycaster();
 
 
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x333333 );
+				scene = new Scene();
+				scene.background = new Color( 0x333333 );
 
 
-				velocity = new THREE.Vector3();
+				velocity = new Vector3();
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
 
 
-				controls = new THREE.PointerLockControls( camera );
+				controls = new PointerLockControls( camera );
 				scene.add( controls.getObject() );
 				scene.add( controls.getObject() );
 
 
 				controls.getObject().translateX( 250 );
 				controls.getObject().translateX( 250 );
 				controls.getObject().translateZ( 250 );
 				controls.getObject().translateZ( 250 );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -308,20 +311,20 @@
 
 
 				// post-processing
 				// post-processing
 
 
-				composer = new THREE.EffectComposer( renderer );
+				composer = new EffectComposer( renderer );
 
 
-				var renderPass = new THREE.RenderPass( scene, camera );
-				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				var renderPass = new RenderPass( scene, camera );
+				var copyPass = new ShaderPass( CopyShader );
 				composer.addPass( renderPass );
 				composer.addPass( renderPass );
 
 
 				var vh = 1.4, vl = 1.2;
 				var vh = 1.4, vl = 1.2;
 
 
-				var colorCorrectionPass = new THREE.ShaderPass( THREE.ColorCorrectionShader );
-				colorCorrectionPass.uniforms[ "powRGB" ].value = new THREE.Vector3( vh, vh, vh );
-				colorCorrectionPass.uniforms[ "mulRGB" ].value = new THREE.Vector3( vl, vl, vl );
+				var colorCorrectionPass = new ShaderPass( ColorCorrectionShader );
+				colorCorrectionPass.uniforms[ "powRGB" ].value = new Vector3( vh, vh, vh );
+				colorCorrectionPass.uniforms[ "mulRGB" ].value = new Vector3( vl, vl, vl );
 				composer.addPass( colorCorrectionPass );
 				composer.addPass( colorCorrectionPass );
 
 
-				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				var vignettePass = new ShaderPass( VignetteShader );
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				vignettePass.uniforms[ "darkness" ].value = 1.0;
 				composer.addPass( vignettePass );
 				composer.addPass( vignettePass );
 
 
@@ -366,14 +369,14 @@
 
 
 			}
 			}
 
 
-			var clock = new THREE.Clock();
-			var audioPos = new THREE.Vector3();
-			var audioRot = new THREE.Euler();
+			var clock = new Clock();
+			var audioPos = new Vector3();
+			var audioRot = new Euler();
 
 
 			function updateSoundFilter() {
 			function updateSoundFilter() {
 
 
 				// difference position between sound and listener
 				// difference position between sound and listener
-				var difPos = new THREE.Vector3().setFromMatrixPosition( soundArea.matrixWorld ).sub( audioPos );
+				var difPos = new Vector3().setFromMatrixPosition( soundArea.matrixWorld ).sub( audioPos );
 				var length = difPos.length();
 				var length = difPos.length();
 
 
 				// pick a vector from camera to sound
 				// pick a vector from camera to sound
@@ -412,7 +415,7 @@
 				lightArea.intensity = soundAreaAnalyser.getAverageFrequency() / 50;
 				lightArea.intensity = soundAreaAnalyser.getAverageFrequency() / 50;
 
 
 				// Update SEA3D Animations
 				// Update SEA3D Animations
-				THREE.SEA3D.AnimationHandler.update( delta );
+				SEA3D.AnimationHandler.update( delta );
 
 
 				render( delta );
 				render( delta );