瀏覽代碼

new examples and revision

Jean Carlo Deconto 10 年之前
父節點
當前提交
6f11ff0f3a

+ 4 - 0
examples/index.html

@@ -264,6 +264,10 @@
 				"webgl_loader_pdb",
 				"webgl_loader_ply",
 				"webgl_loader_sea3d",
+				"webgl_loader_sea3d_hierarchy",
+				"webgl_loader_sea3d_keyframe",
+				"webgl_loader_sea3d_skinning",
+				"webgl_loader_sea3d_sound",
 				"webgl_loader_scene",
 				"webgl_loader_stl",
 				"webgl_loader_utf8",

+ 53 - 4
examples/js/loaders/sea3d/SEA3D.js

@@ -2280,8 +2280,6 @@ SEA3D.Morph = function(name, data, sea) {
 	var useVertex = (this.attrib & 2) != 0;
 	var useNormal = (this.attrib & 4) != 0;
 	
-	var len = this.numVertex * 3;
-	
 	var nodeCount = data.readUShort();
 	
 	this.node = [];
@@ -2295,7 +2293,7 @@ SEA3D.Morph = function(name, data, sea) {
 			var verts = [];
 			
 			j = 0;
-			while(j < len)
+			while(j < this.length)
 				verts[j++] = data.readFloat();
 		}
 		
@@ -2303,7 +2301,7 @@ SEA3D.Morph = function(name, data, sea) {
 			var norms = [];
 			
 			j = 0;
-			while(j < len)
+			while(j < this.length)
 				norms[j++] = data.readFloat();
 		}
 		
@@ -2313,6 +2311,56 @@ SEA3D.Morph = function(name, data, sea) {
 
 SEA3D.Morph.prototype.type = "mph";
 
+//
+//	Vertex Animation
+//
+
+SEA3D.VertexAnimation = function(name, data, sea) {
+	this.name = name;
+	this.data = data;
+	this.sea = sea;
+	
+	SEA3D.AnimationBase.read(this);
+	
+	var flags = data.readUByte();
+	
+	this.isBigMesh = (flags & 1) != 0;	
+	
+	data.readVInt = this.isBigMesh ? 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, j;
+	
+	for(i = 0; i < this.numFrames; i++) {
+		if (useVertex) {				
+			var verts = [];
+			
+			j = 0;
+			while(j < this.length)
+				verts[j++] = data.readFloat();
+		}
+		
+		if (useNormal) {
+			var norms = [];
+			
+			j = 0;
+			while(j < this.length)
+				norms[j++] = data.readFloat();
+		}
+		
+		this.frame[i] = {vertex:verts, normal:norms}
+	}	
+}
+
+SEA3D.VertexAnimation.prototype.type = "vtxa";
+
 //
 //	Camera
 //
@@ -2942,6 +2990,7 @@ SEA3D.File = function(data) {
 	this.addClass(SEA3D.JointObject);
 	this.addClass(SEA3D.Camera);
 	this.addClass(SEA3D.Morph);
+	this.addClass(SEA3D.VertexAnimation);
 	this.addClass(SEA3D.CubeMap);
 	this.addClass(SEA3D.Animation);	
 	this.addClass(SEA3D.Dummy);

+ 210 - 125
examples/js/loaders/sea3d/SEA3DLoader.js

@@ -25,12 +25,12 @@ THREE.ShaderLib.replaceCode = function(src, target, replace) {
 THREE.ShaderLib['phong'].fragmentShader_StandardMaterial = 
 	THREE.ShaderLib.replaceCode( THREE.ShaderLib['phong'].fragmentShader, [
 		//	Target
-		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) * specular + totalSpecularLight + emissive;', // METAL
-		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) + totalSpecularLight + emissive;'	
+		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) * specular + totalSpecularLight + totalEmissiveLight;', // METAL
+		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) + totalSpecularLight + totalEmissiveLight;'	
 	], [
 		//	Replace To
-		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor + emissive ) * specular + totalSpecularLight;', // METAL
-		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor + emissive ) + totalSpecularLight;'	
+		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight + totalEmissiveLight ) * specular + totalSpecularLight;', // METAL
+		'outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight + totalEmissiveLight ) + totalSpecularLight;'	
 	] );
 
 //
@@ -47,7 +47,7 @@ THREE.MeshPhongMaterial.prototype.clone = function() {
 }
 
 THREE.MeshPhongMaterial.prototype.__defineSetter__("__webglShader", function(val){
-	if (this.emissiveToAmbientColor) val.fragmentShader = THREE.ShaderLib['phong'].fragmentShader_StandardMaterial;
+	if (this.emissiveToAmbientColor) val.fragmentShader = THREE.ShaderLib['phong'].fragmentShader_StandardMaterial;	
 	this.__webglShader__ = val;
 });
 THREE.MeshPhongMaterial.prototype.__defineGetter__("__webglShader", function(){
@@ -188,6 +188,16 @@ THREE.SkinnedMesh.prototype.setAnimations = function(animations) {
 	}
 }
 
+THREE.SkinnedMesh.prototype.boneByName = function(name) {
+	var bones = this.bones;
+	
+	for(var i = 0, bl = bones.length; i < bl; i++) {
+		if (name == bones[i].name) {
+			return bones[i];
+		}
+	}
+}
+
 THREE.SkinnedMesh.prototype.DISPOSE = THREE.SkinnedMesh.prototype.dispose;
 THREE.SkinnedMesh.prototype.dispose = function () {	
 	this.stop();
@@ -269,6 +279,15 @@ THREE.AnimationHandler.addCrossfade = function( mesh, crossfade ) {
 	THREE.AnimationHandler.crossfade.push( mesh );
 }
 
+//
+//	KeyFrame
+//
+
+THREE.VertexAnimation = function () {
+
+
+}
+
 //
 //	Animation Event Extension
 //
@@ -367,22 +386,6 @@ THREE.Sound3D.update = function( camera ) {
 	}
 }
 
-//
-//	Bone Extension (Joint Object)
-//
-
-THREE.Bone.fromName = function(mesh, name) {
-	var bones = mesh.bones;
-	
-	for(var i = 0, bl = bones.length; i < bl; i++)
-	{
-		if (name == bones[i].name)
-		{
-			return bones[i];
-		}
-	}
-}
-
 //
 //	SEA3D
 //
@@ -626,6 +629,7 @@ THREE.SEA3D.prototype.updateTransform = function(obj3d, sea) {
 THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 	var buf = THREE.SEA3D.BUFFER2;
 	var anmSet = obj3d.animation.animationSet;
+	var relative = obj3d.animation.relative;
 		
 	if (anmSet.flip)
 		return;
@@ -637,19 +641,19 @@ THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 		var t_anm = [], j;		
 				
 		for (j = 0; j < dataList.length; j++) {
-			var data = dataList[i];	
-			var raw = dataList[i].data;	
+			var data = dataList[j];	
+			var raw = dataList[j].data;	
 			var kind = data.kind;
 			var numFrames = raw.length / data.blockLength;			
 			
 			switch(kind) {
 				case SEA3D.Animation.POSITION:
-				case SEA3D.Animation.ROTATION:
+				case SEA3D.Animation.ROTATION:				
 					t_anm.push( {
 						kind : kind,
 						numFrames : numFrames,
 						raw : raw						
-					} );
+					} );					
 					break;
 			}
 		}
@@ -657,16 +661,23 @@ THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 		if (t_anm.length > 0) {	
 			
 			var numFrames = t_anm[0].numFrames,
-				ct = THREE.SEA3D.CONTAINER;
-			
-			ct.position.set(0, 0, 0);
-			ct.rotation.set(0, 0, 0);
-			ct.scale.set(1, 1, 1);
-						
-			obj3d.add( ct );
+				ct = THREE.SEA3D.CONTAINER,			
+				tar = relative ? obj3d : obj3d.parent;
+
+			if (obj3d.animation.relative) {				
+				ct.position.set(0, 0, 0);
+				ct.rotation.set(0, 0, 0);
+				ct.scale.set(1, 1, 1);
+			} else {
+				ct.position.copy(obj3d.position);
+				ct.rotation.copy(obj3d.rotation);
+				ct.scale.copy(obj3d.scale);
+			}
+
+			tar.add( ct );
 			
-			for (var f = 0, t, c; f < numFrames; f++) {									
-				
+			for (var f = 0, t, c; f < numFrames; f++) {
+								
 				for (t = 0; t < t_anm.length; t++) {				
 					
 					var raw = t_anm[t].raw,
@@ -681,8 +692,8 @@ THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 								raw[c    ], 
 								raw[c + 1], 
 								raw[c + 2]
-							);			
-													
+							);		
+
 							break;
 							
 						case SEA3D.Animation.ROTATION:
@@ -695,10 +706,10 @@ THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 								raw[c + 2],
 								raw[c + 3]
 							);
-
+							
 							break;
-					}					
-				}	
+					}
+				}
 				
 				this.updateMatrix( ct );
 				
@@ -711,28 +722,28 @@ THREE.SEA3D.prototype.updateAnimationSet = function(obj3d) {
 						case SEA3D.Animation.POSITION:
 							
 							c = f * 3;														
-																					
+
 							raw[c    ] = ct.position.x;
 							raw[c + 1] = ct.position.y;
 							raw[c + 2] = ct.position.z;																									
-						
+					
 							break;
 							
 						case SEA3D.Animation.ROTATION:
 							
 							c = f * 4;
 
-							raw[c    ] = ct.quaternion.x;
-							raw[c + 1] = ct.quaternion.y;
-							raw[c + 2] = ct.quaternion.z;
-							raw[c + 3] = ct.quaternion.w;
-							
+							raw[c    ] = ct.quaternion.x;	
+							raw[c + 1] = ct.quaternion.y;	
+							raw[c + 2] = ct.quaternion.z;	
+							raw[c + 3] = ct.quaternion.w;	
+
 							break;
 					}					
 				}
 			}
 
-			obj3d.remove( ct );			
+			tar.remove( ct );			
 		}
 	}
 	
@@ -831,10 +842,10 @@ THREE.SEA3D.prototype.applyDefaultAnimation = function(sea, ANIMATOR_CLASS) {
 		
 				if (this.config.flip)
 					this.updateAnimationSet(obj);
-		
+
 				if (this.config.autoPlay) 
 					obj.animation.play( obj.animation.getStateNameByIndex(0) );
-				
+
 				return obj.animation;
 				break;
 		}
@@ -918,7 +929,7 @@ THREE.SEA3D.Object3DAnimator.prototype.updateAnimationFrame = function(frame, ki
 				break;
 				
 			case SEA3D.Animation.ROTATION:		
-				var v = frame.toVector();				
+				var v = frame.toVector();	
 				this.object3d.quaternion.set(v.x, v.y, v.z, v.w);
 				break;	
 				
@@ -987,14 +998,10 @@ THREE.SEA3D.LightAnimator.prototype.$updateAnimationFrame = THREE.SEA3D.Object3D
 //
 
 THREE.SEA3D.prototype.readGeometrySwitch = function(sea) {
-	if (sea.numVertex < 0xFFFE && !sea.joint && (!sea.uv || sea.uv.length === 1) && sea.indexes.length === 1)
-	{
-		this.readGeometryBuffer(sea);
-	}
+	if (sea.indexes.length === 1)	
+		this.readGeometryBuffer(sea);	
 	else
-	{
-		this.readGeometry(sea);
-	}
+		this.readGeometry(sea);	
 }
 
 THREE.SEA3D.prototype.readGeometryBuffer = function(sea) {
@@ -1002,60 +1009,37 @@ THREE.SEA3D.prototype.readGeometryBuffer = function(sea) {
 		count = index.length,
 		geo = new THREE.BufferGeometry();
 	
-	var indices, position, normals, uv, colors;
-			
-	geo.attributes = {
-		
-		index : {
-			itemSize: 1,
-			array: indices = new Uint16Array( count )
-		},
-		
-		position : {
-			itemSize: 3,
-			array: position = new Float32Array( count * 3 )
-		},
-			
-		uv : {
-			itemSize: 2,
-			array: uv = new Float32Array( count * 2 )
-		}
-	}
+	var indices, position, normals, tangents, uv, uv2, colors, skinIndex, skinWeight;
+	
+	indices = new Uint16Array( count );
+	position = new Float32Array( count * 3 );
 	
 	var a, b, c,
 		v = sea.vertex,
 		n = sea.normal,
 		t = sea.tangent,
-		u = sea.uv ? sea.uv[0] : undefined;
-	var vc = sea.color ? sea.color[0] : undefined;
-	
-	if (n)
-	{
-		geo.attributes.normal = {
-			itemSize: 3,
-			array: normals = new Float32Array( count * 3 )
-		}
-	}
-	
-	if (t)
-	{
-		geo.attributes.tangent = {
-			itemSize: 3,
-			array: normals = new Float32Array( count * 3 )
-		}
-	}
-	
-	if (vc)
-	{
-		geo.attributes.color = {
-			itemSize: 3,
-			array: colors = new Float32Array( count * 3 )
-		}
+		u = sea.uv ? sea.uv[0] : undefined,
+		u2 = sea.uv && sea.uv.length > 1 ? sea.uv[1] : undefined,
+		vc = sea.color ? sea.color[0] : undefined,
+		sI = sea.joint,
+		sW = sea.weight;
+	
+	if (n) normals = new Float32Array( count * 3 );	
+	if (t) tangents = new Float32Array( count * 3 );	
+	if (u) uv = new Float32Array( count * 2 );		
+	if (u2) uv2 = new Float32Array( count * 2 );	
+	if (vc) colors = new Float32Array( count * 3 );	
+	if (sI) {
+		skinIndex = new Float32Array( count * 4 );	
+		skinWeight = new Float32Array( count * 4 );	
+		
+		var jointPerVertex = Math.min( sea.jointPerVertex, 4 );
+		var compJointPerVertex = sea.jointPerVertex.length > 4;
 	}
 	
 	var flip = this.config.flip ? -1 : 1;
 	
-	for (var f = 0, vt = 0, vu=0; f < count; f+=3, vt+=9, vu+=6) {
+	for (var f = 0, vt = 0, vu=0, jt=0; f < count; f+=3, vt+=9, vu+=6, jt+=12) {
 	
 		// index
 	
@@ -1098,17 +1082,20 @@ THREE.SEA3D.prototype.readGeometryBuffer = function(sea) {
 		
 		if (t)
 		{
-			tangent[ vt     ] = t[ a     ];
-			tangent[ vt + 1 ] = t[ a + 1 ];
-			tangent[ vt + 2 ] = t[ a + 2 ] * flip;
+			tangents[ vt     ] = t[ a     ];
+			tangents[ vt + 1 ] = t[ a + 1 ];
+			tangents[ vt + 2 ] = t[ a + 2 ] * flip;
+			tangents[ vt + 3 ] = handleVertex(tangents, vt);
 			
-			tangent[ vt + 3 ] = t[ b     ];
-			tangent[ vt + 4 ] = t[ b + 1 ];
-			tangent[ vt + 5 ] = t[ b + 2 ] * flip;
+			tangents[ vt + 4 ] = t[ b     ];
+			tangents[ vt + 5 ] = t[ b + 1 ];
+			tangents[ vt + 6 ] = t[ b + 2 ] * flip;
+			tangents[ vt + 7 ] = handleVertex(tangents + 5, vt);
 			
-			tangent[ vt + 6 ] = t[ c     ];
-			tangent[ vt + 7 ] = t[ c + 1 ];
-			tangent[ vt + 8 ] = t[ c + 2 ] * flip;
+			tangents[ vt + 8 ] = t[ c     ];
+			tangents[ vt + 9 ] = t[ c + 1 ];
+			tangents[ vt + 10 ] = t[ c + 2 ] * flip;
+			tangents[ vt + 11 ] = handleVertex(tangents + 8, vt);
 		}
 		
 		// uv		
@@ -1140,6 +1127,24 @@ THREE.SEA3D.prototype.readGeometryBuffer = function(sea) {
 			uv[ vu + 5 ] = 1;
 		}
 		
+		// uv2
+		
+		if (u2)
+		{
+			a = index[ f     ] * 2;
+			b = index[ f + 2 ] * 2;
+			c = index[ f + 1 ] * 2;
+			
+			uv2[ vu     ] = u2[ a     ];
+			uv2[ vu + 1 ] = u2[ a + 1 ];
+		
+			uv2[ vu + 2 ] = u2[ b     ];
+			uv2[ vu + 3 ] = u2[ b + 1 ];
+			
+			uv2[ vu + 4 ] = u2[ c     ];
+			uv2[ vu + 5 ] = u2[ c + 1 ];
+		}
+		
 		// colors
 		
 		if (vc)
@@ -1161,24 +1166,65 @@ THREE.SEA3D.prototype.readGeometryBuffer = function(sea) {
 			colors[ vt + 8 ] = vc[ c + 2 ];
 		}
 		
+		// skin
+		
+		if (sI)
+		{
+			var i = 0, totalA = 0, totalB = 0, totalC = 0;
+			
+			a = index[ f     ] * sea.jointPerVertex;
+			b = index[ f + 2 ] * sea.jointPerVertex;
+			c = index[ f + 1 ] * sea.jointPerVertex;
+			
+			i = 0;
+			while ( i < jointPerVertex )
+			{
+				skinIndex[ jt + i ] = sI[ a + i ];				
+				totalA += skinWeight[ jt + i ] = sW[ a + i ];	
+				
+				skinIndex[ jt + i + 4 ] = sI[ b + i ];				
+				totalB += skinWeight[ jt + i + 4 ] = sW[ b + i ];	
+				
+				skinIndex[ jt + i + 8 ] = sI[ c + i ];				
+				totalC += skinWeight[ jt + i + 8 ] = sW[ c + i ];	
+				
+				++i;
+			}
+			
+			skinWeight[ jt ] += 1 - totalA;
+			skinWeight[ jt + 4 ] += 1 - totalB;
+			skinWeight[ jt + 8 ] += 1 - totalC;
+		}
+		
 		// indices
 		
 		indices[ f     ] = f;
 		indices[ f + 1 ] = f + 1;
 		indices[ f + 2 ] = f + 2;
-	}	
-		
-	if (sea.numVertex >= 0xFFFE) {
-		console.warn( "SEA3D: Big Mesh is not compatible with geometry buffer." );
-		//geo.computeOffsets();
-	}	
+	}
+	
+	geo.addAttribute( 'position', new THREE.BufferAttribute( position, 3 ) );
+	geo.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+	
+	if (normals) geo.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+	if (tangents) geo.addAttribute( 'tangent', new THREE.BufferAttribute( tangents, 4 ) );
+	if (uv) geo.addAttribute( 'uv', new THREE.BufferAttribute( uv, 2 ) );
+	if (uv2) geo.addAttribute( 'uv2', new THREE.BufferAttribute( uv2, 2 ) );		
+	if (colors) geo.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+	if (skinIndex) {
+		geo.addAttribute( 'skinIndex', new THREE.Float32Attribute( skinIndex, 4 ) );		
+		geo.addAttribute( 'skinWeight', new THREE.Float32Attribute( skinWeight, 4 ) );		
+	}
+	
+	if (sea.numVertex >= 0xFFFE)	
+		geo.computeOffsets();	
 	
 	if (!n)	
 		geo.computeVertexNormals();	
 	
 	if (this.config.tangent && !sea.tangent)
 		geo.computeTangents();
-		
+	
 	if (this.config.bounding)
 	{
 		geo.computeBoundingBox();
@@ -1445,8 +1491,8 @@ THREE.SEA3D.prototype.readMesh2D = function(sea) {
 
 THREE.SEA3D.prototype.readMesh = function(sea) {
 	var geo = sea.geometry.tag,
-		mesh, mat, skeleton, skeletonAnimation, morpher;
-		
+		mesh, mat, skeleton, skeletonAnimation, morpher, vtxAnm;
+	
 	for(var i = 0, count = sea.modifiers ? sea.modifiers.length : 0; i < count; i++) {
 		var mod = sea.modifiers[i];
 		
@@ -1458,7 +1504,7 @@ THREE.SEA3D.prototype.readMesh = function(sea) {
 				break;
 		
 			case SEA3D.Morph.prototype.type:
-				morpher = mod;
+				morpher = mod;				
 				break;
 		}
 	}
@@ -1472,6 +1518,10 @@ THREE.SEA3D.prototype.readMesh = function(sea) {
 				skeletonAnimation = anm.tag;
 				geo.animations = this.getSkeletonAnimation( skeletonAnimation, skeleton );	
 				break;
+				
+			case SEA3D.VertexAnimation.prototype.type:
+				vtxAnm = anm.tag;								
+				break;
 		}
 	}
 	
@@ -1509,6 +1559,9 @@ THREE.SEA3D.prototype.readMesh = function(sea) {
 		}
 	} else {
 		mesh = new THREE.Mesh( geo, mat );
+		
+		if (vtxAnm)
+			geo.morphTargets = this.getVertexAnimation( vtxAnm );
 	}
 	
 	mesh.name = sea.name;
@@ -1519,10 +1572,10 @@ THREE.SEA3D.prototype.readMesh = function(sea) {
 	this.meshes = this.meshes || [];
 	this.meshes.push( this.objects["m3d/" + sea.name] = sea.tag = mesh );
 	
-	this.addSceneObject( sea );
-	this.updateTransform(mesh, sea);
+	this.addSceneObject( sea );		
+	this.updateTransform(mesh, sea);		
 	
-	this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator );		
+	this.applyDefaultAnimation( sea, THREE.SEA3D.Object3DAnimator );
 }
 
 //
@@ -1869,7 +1922,11 @@ THREE.SEA3D.prototype.readMaterial = function(sea) {
 THREE.SEA3D.prototype.readPointLight = function(sea) {	
 	var light = new THREE.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, sea.shadow.opacity);		
 	
@@ -2151,6 +2208,34 @@ THREE.SEA3D.prototype.getMorpher = function(sea, geo) {
 	return morphs;
 }
 
+//
+//	Vertex Animation
+//
+
+THREE.SEA3D.prototype.getVertexAnimation = function(sea) {	
+	var vtxAnms = [],
+		flip = this.config.flip ? -1 : 1;
+	
+	for(var i = 0; i < sea.frame.length; i++) {
+		var frame = sea.frame[i],
+			vertex = [];
+		
+		var j = 0, k = 0;
+		while(j < frame.vertex.length)
+			vertex[k++] = new THREE.Vector3(
+				frame.vertex[j++], 
+				frame.vertex[j++], 
+				frame.vertex[j++] * flip
+			);
+		
+		vtxAnms[i] = {
+			vertices:vertex			
+		}
+	}
+	
+	return vtxAnms;
+}
+
 //
 //	Events
 //

二進制
examples/models/sea3d/flag.sea


二進制
examples/models/sea3d/keyframe.sea


二進制
examples/models/sea3d/morph.sea


二進制
examples/models/sea3d/robot.sea


二進制
examples/models/sea3d/skin.sea


二進制
examples/models/sea3d/sound.sea


+ 1 - 4
examples/webgl_loader_sea3d.html

@@ -72,7 +72,7 @@
 
 				autoPlay : true, // Auto play animations
 				container : scene, // Container to add models
-				parser : THREE.SEA3D.DEFAULT, // THREE.SEA3D.BUFFER to THREE.GeometryBuffer
+				parser : THREE.SEA3D.AUTO, // Auto choose THREE.BufferGeometry and THREE.Geometry
 				multiplier : 1 // Light multiplier
 
 			} );
@@ -184,9 +184,6 @@
 
 				THREE.AnimationHandler.update( delta );
 
-				// SEA3D Keyframe Update		
-				SEA3D.AnimationHandler.update( delta ); 
-
 				//renderer.render( scene, camera );
 				composer.render( delta );
 

+ 202 - 0
examples/webgl_loader_sea3d_hierarchy.html

@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - sea3d</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+
+			}
+
+			a { color: white }
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - model by <a href="https://github.com/sunag/sea3d" style="color:#FFFFF" target="_blank">sea3d</a>
+		</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/controls/TrackballControls.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/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer, composer, controls;
+
+			var loader;
+
+			// Initialize Three.JS
+
+			init(); 
+
+			//
+			// SEA3D Loader
+			//
+
+			loader = new THREE.SEA3D( {
+				
+				autoPlay : false, // Auto play animations
+				container : scene, // Container to add models
+				parser : THREE.SEA3D.BUFFER, // THREE.BufferGeometry
+				multiplier : 1 // Light multiplier
+
+			} );
+
+			loader.onComplete = function( e ) {
+
+				// reset global time
+				SEA3D.AnimationHandler.setTime( 0 );
+
+				// play all animations
+				for(var i = 0; i < loader.meshes.length; i++) {
+					if (loader.meshes[i].animation)
+						loader.meshes[i].animation.play("root");
+				}
+			
+				// Get the first camera from 3ds Max
+				// use loader.get... to get others objects
+
+				var cam = loader.cameras[0];
+				camera.position.copy( cam.position );
+				camera.rotation.copy( cam.rotation );
+
+				animate();
+
+			};
+
+			loader.load( './models/sea3d/robot.sea' );
+
+			//
+
+			function init() {
+
+				scene = new THREE.Scene();
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.set( 1000, - 300, 1000 );
+
+				controls = new THREE.TrackballControls( camera, document );
+				controls.noZoom = true;
+				controls.noPan = true;
+				controls.dynamicDampingFactor = 0.05;
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setClearColor( 0x333333, 1 );
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				// post-processing
+
+				composer = new THREE.EffectComposer( renderer );
+
+				var renderPass = new THREE.RenderPass( scene, camera );
+				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				composer.addPass( renderPass );
+
+				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 );
+				composer.addPass( colorCorrectionPass );
+
+				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				vignettePass.uniforms[ "darkness" ].value = 1.0;
+				composer.addPass( vignettePass );
+
+				composer.addPass( copyPass );
+				copyPass.renderToScreen = true;
+
+				// events
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				controls.update();
+
+				render();
+
+				stats.update();
+
+			}
+
+			var clock = new THREE.Clock();
+
+			function render() {
+
+				var delta = clock.getDelta();
+
+				THREE.AnimationHandler.update( delta );
+
+				// SEA3D Keyframe Update		
+				SEA3D.AnimationHandler.update( delta ); 
+				
+				//renderer.render( scene, camera );
+				composer.render( delta );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 312 - 0
examples/webgl_loader_sea3d_keyframe.html

@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - sea3d / keyframe</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+
+			}
+
+			a { color: white }
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - model by <a href="https://github.com/sunag/sea3d" style="color:#FFFFF" target="_blank">sea3d</a>
+			<div id="description">Click to play</div>
+		</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/controls/TrackballControls.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/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer, composer, controls, demoAt = -1;
+
+			var loader;
+
+			// Initialize Three.JS
+
+			init(); 
+
+			//
+			// SEA3D Loader
+			//
+
+			loader = new THREE.SEA3D( {
+
+				autoPlay : false, // Manual play animations
+				container : scene, // Container to add models
+				parser : THREE.SEA3D.BUFFER, // THREE.SEA3D.BUFFER to THREE.BufferGeometry
+				multiplier : 1 // Light multiplier
+
+			} );
+
+			loader.onComplete = function( e ) {
+
+				// Get the first camera from 3ds Max
+				// use loader.get... to get others objects
+
+				var cam = loader.cameras[0];
+				camera.position.copy( cam.position );
+				camera.rotation.copy( cam.rotation );
+
+				// reset global animation time
+				SEA3D.AnimationHandler.setTime( 0 );
+				
+				// events
+				
+				window.addEventListener('click', onMouseClick, false);
+				
+				animate();
+
+			};
+
+			loader.load( './models/sea3d/keyframe.sea' );
+
+			//
+			//	Animation Functions
+			//
+
+			function playAll(name, crossfade, offset) {
+
+				// reset global time
+				SEA3D.AnimationHandler.setTime( 0 );
+
+				// play all animations
+				for(var i = 0; i < loader.meshes.length; i++) {
+					if (loader.meshes[i].animation)
+						loader.meshes[i].animation.play(name, crossfade, offset);
+				}
+
+			}
+			
+			function setTimeScale( timeScale ) {		
+			
+				// set in all active animations
+				for(var i in SEA3D.AnimationHandler.animations) {		
+					SEA3D.AnimationHandler.animations[i].timeScale = timeScale;
+				}
+
+			}
+			
+			function stopAll() {
+
+				// reset global time
+				SEA3D.AnimationHandler.setTime( 0 );
+				
+				// stop all active animations
+				SEA3D.AnimationHandler.stop();
+				
+			}
+			
+			//
+
+			function init() {
+
+				scene = new THREE.Scene();
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.set( 1000, - 300, 1000 );
+
+				controls = new THREE.TrackballControls( camera, document );
+				controls.noZoom = true;
+				controls.noPan = true;
+				controls.dynamicDampingFactor = 0.05;
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setClearColor( 0x333333, 1 );
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				// post-processing
+
+				composer = new THREE.EffectComposer( renderer );
+
+				var renderPass = new THREE.RenderPass( scene, camera );
+				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				composer.addPass( renderPass );
+
+				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 );
+				composer.addPass( colorCorrectionPass );
+
+				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				vignettePass.uniforms[ "darkness" ].value = 1.0;
+				composer.addPass( vignettePass );
+
+				composer.addPass( copyPass );
+				copyPass.renderToScreen = true;
+
+				// extra lights
+
+				scene.add( new THREE.AmbientLight( 0x333333 ) );
+
+				// events
+				
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function description(msg) {
+
+				document.getElementById('description').innerHTML = (demoAt + 1) + " - " + msg;
+
+			}
+			
+			function onMouseClick( e ) {
+
+				// 0 at 3 demos
+
+				switch( demoAt = ++demoAt % 4 ) {				
+
+					// play all animation to sequence "crash#1"
+
+					case 0:
+
+						playAll("crash#1", .5);	
+						setTimeScale(1);
+
+						description("crash#1 - crossfade 0.5 seconds");
+
+						break;
+
+					// play all animation to sequence "crash#2"
+
+					case 1:
+
+						playAll("crash#2", .5);	
+						
+						description("crash#2 - crossfade 0.5 seconds");
+
+						break;		
+
+					// play animation in single object
+
+					case 2:
+
+						stopAll();
+
+						var fracture99 = loader.getMesh("Object099");
+
+						//fracture99.animation.time = 0;
+						//fracture99.animation.timeScale = 1;						
+						//fracture99.animation.playing								
+						//fracture99.animation.states ...	
+						//fracture99.animation.currentState ...						
+
+						//fracture99.animation.node ...
+						//fracture99.animation.node.duration
+
+						fracture99.animation.play("crash#2", .5, 0);
+						//fracture99.animation.pause();
+						//fracture99.animation.stop();						
+
+						description("crash#2 in single object - crossfade 0.5 seconds");
+
+						break;
+
+					// set time scale
+
+					case 3:
+
+						playAll("crash#2", .5);
+						setTimeScale(.1);	
+
+						description("time scale / 10 - crossfade 0.5 seconds");
+
+						break;							
+				}
+			}
+			
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				controls.update();
+
+				render();
+
+				stats.update();
+
+			}
+
+			var clock = new THREE.Clock();
+
+			function render() {
+
+				var delta = clock.getDelta();
+
+				THREE.AnimationHandler.update( delta );
+
+				// SEA3D Keyframe Update		
+				SEA3D.AnimationHandler.update( delta ); 
+
+				//renderer.render( scene, camera );
+				composer.render( delta );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 225 - 0
examples/webgl_loader_sea3d_skinning.html

@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - sea3d / skin</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+
+			}
+
+			a { color: white }
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - model by <a href="https://github.com/sunag/sea3d" style="color:#FFFFF" target="_blank">sea3d</a>
+			<br/>BoneObject: Object3D attached in a Bone
+			<br/>Click to hidden/show the hat - Right click to run
+		</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/controls/TrackballControls.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/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer, composer, controls, player, hat;
+
+			var loader;
+
+			// Initialize Three.JS
+
+			init(); 
+
+			//
+			// SEA3D Loader
+			//
+
+			loader = new THREE.SEA3D( {
+
+				autoPlay : true, // Auto play animations
+				container : scene, // Container to add models
+				parser : THREE.SEA3D.AUTO, // Auto choose THREE.BufferGeometry and THREE.Geometry
+				multiplier : 1 // Light multiplier
+
+			} );
+
+			loader.onComplete = function( e ) {
+
+				// Get the first camera from 3ds Max
+				// use loader.get... to get others objects
+
+				var cam = loader.cameras[0];
+				camera.position.copy( cam.position );
+				camera.rotation.copy( cam.rotation );
+
+				// get meshes
+				player = loader.getMesh("Player");
+				hat = loader.getMesh("Hat");
+				
+				// events
+				
+				window.addEventListener( 'click', onMouseClick, false );
+				window.addEventListener( 'contextmenu', onRightClick, false );
+				
+				animate();
+
+			};
+
+			loader.load( './models/sea3d/skin.sea' );
+
+			//
+
+			function init() {
+
+				scene = new THREE.Scene();
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.set( 1000, - 300, 1000 );
+
+				controls = new THREE.TrackballControls( camera, document );
+				controls.noZoom = true;
+				controls.noPan = true;
+				controls.dynamicDampingFactor = 0.05;
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setClearColor( 0x333333, 1 );
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				// post-processing
+
+				composer = new THREE.EffectComposer( renderer );
+
+				var renderPass = new THREE.RenderPass( scene, camera );
+				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				composer.addPass( renderPass );
+
+				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 );
+				composer.addPass( colorCorrectionPass );
+
+				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				vignettePass.uniforms[ "darkness" ].value = 1.0;
+				composer.addPass( vignettePass );
+
+				composer.addPass( copyPass );
+				copyPass.renderToScreen = true;
+
+				// extra lights
+
+				scene.add( new THREE.AmbientLight( 0x333333 ) );
+
+				// events
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onRightClick( e ) {
+
+				// play character animation
+				if (player.currentAnimation.name == "idle")
+					player.play("run", .5);
+				else
+					player.play("idle", .5);
+
+				e.preventDefault();
+
+			}
+			
+			function onMouseClick( e ) {
+
+				if (e.button != 0) return;
+
+				var hat = loader.getMesh("Hat");
+				hat.visible = !hat.visible;
+
+			}
+			
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				controls.update();
+
+				render();
+
+				stats.update();
+
+			}
+
+			var clock = new THREE.Clock();
+
+			function render() {
+
+				var delta = clock.getDelta();
+
+				THREE.AnimationHandler.update( delta );
+
+				//renderer.render( scene, camera );
+				composer.render( delta );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 423 - 0
examples/webgl_loader_sea3d_sound.html

@@ -0,0 +1,423 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - sea3d</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+
+			}
+			
+			#blocker {
+
+				position: absolute;
+
+				width: 100%;
+				height: 100%;
+
+				background-color: rgba(0,0,0,0.5);
+
+			}
+
+			#instructions {
+
+				width: 100%;
+				height: 100%;
+
+				display: -webkit-box;
+				display: -moz-box;
+				display: box;
+
+				-webkit-box-orient: horizontal;
+				-moz-box-orient: horizontal;
+				box-orient: horizontal;
+
+				-webkit-box-pack: center;
+				-moz-box-pack: center;
+				box-pack: center;
+
+				-webkit-box-align: center;
+				-moz-box-align: center;
+				box-align: center;
+
+				color: #ffffff;
+				text-align: center;
+
+				cursor: pointer;
+
+			}
+
+			a { color: white }
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - model by <a href="https://github.com/sunag/sea3d" style="color:#FFFFF" target="_blank">sea3d</a>
+		</div>
+
+		<div id="blocker">
+
+			<div id="instructions">
+				<span style="font-size:40px">Click to play</span>
+				<br />
+				(W, A, S, D = Move, MOUSE = Look around)
+			</div>
+
+		</div>
+		
+		<script src="../build/three.min.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/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer, composer, controls, velocity;
+			var blocker, instructions;
+			var moveLeft, moveForward, moveBackward, moveRight;
+
+			initKeyDown
+			
+			var loader;
+
+			// Initialize Three.JS
+
+			initPointerLock();
+			initKeyDown();
+			init(); 
+
+			//
+			// SEA3D Loader
+			//
+
+			loader = new THREE.SEA3D( {
+
+				autoPlay : true, // Auto play animations
+				container : scene, // Container to add models
+				parser : THREE.SEA3D.AUTO, // Auto choose THREE.BufferGeometry and THREE.Geometry
+				multiplier : 1 // Light multiplier
+
+			} );
+
+			loader.onComplete = function( e ) {
+				
+				animate();
+
+			};
+
+			loader.load( './models/sea3d/sound.sea' );
+
+			//
+
+			function initPointerLock() {
+
+				blocker = document.getElementById( 'blocker' );
+				instructions = document.getElementById( 'instructions' );
+			
+				// http://www.html5rocks.com/en/tutorials/pointerlock/intro/
+
+				var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
+
+				if ( havePointerLock ) {
+
+					var element = document.body;
+
+					var pointerlockchange = function ( event ) {
+
+						if ( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element ) {
+
+							controlsEnabled = true;
+							controls.enabled = true;
+
+							blocker.style.display = 'none';
+
+						} else {
+
+							controls.enabled = false;
+
+							blocker.style.display = '-webkit-box';
+							blocker.style.display = '-moz-box';
+							blocker.style.display = 'box';
+
+							instructions.style.display = '';
+
+						}
+
+					};
+
+					var pointerlockerror = function ( event ) {
+
+						instructions.style.display = '';
+
+					};
+
+					// Hook pointer lock state change events
+					document.addEventListener( 'pointerlockchange', pointerlockchange, false );
+					document.addEventListener( 'mozpointerlockchange', pointerlockchange, false );
+					document.addEventListener( 'webkitpointerlockchange', pointerlockchange, false );
+
+					document.addEventListener( 'pointerlockerror', pointerlockerror, false );
+					document.addEventListener( 'mozpointerlockerror', pointerlockerror, false );
+					document.addEventListener( 'webkitpointerlockerror', pointerlockerror, false );
+
+					instructions.addEventListener( 'click', function ( event ) {
+
+						instructions.style.display = 'none';
+
+						// Ask the browser to lock the pointer
+						element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
+
+						if ( /Firefox/i.test( navigator.userAgent ) ) {
+
+							var fullscreenchange = function ( event ) {
+
+								if ( document.fullscreenElement === element || document.mozFullscreenElement === element || document.mozFullScreenElement === element ) {
+
+									document.removeEventListener( 'fullscreenchange', fullscreenchange );
+									document.removeEventListener( 'mozfullscreenchange', fullscreenchange );
+
+									element.requestPointerLock();
+								}
+
+							};
+
+							document.addEventListener( 'fullscreenchange', fullscreenchange, false );
+							document.addEventListener( 'mozfullscreenchange', fullscreenchange, false );
+
+							element.requestFullscreen = element.requestFullscreen || element.mozRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen;
+
+							element.requestFullscreen();
+
+						} else {
+
+							element.requestPointerLock();
+
+						}
+
+					}, false );
+
+				} else {
+
+					instructions.innerHTML = 'Your browser doesn\'t seem to support Pointer Lock API';
+
+				}
+
+			}
+			
+			function initKeyDown() {
+
+				var onKeyDown = function ( event ) {
+
+					switch ( event.keyCode ) {
+
+						case 38: // up
+						case 87: // w
+							moveForward = true;
+							break;
+
+						case 37: // left
+						case 65: // a
+							moveLeft = true; 
+							break;
+
+						case 40: // down
+						case 83: // s
+							moveBackward = true;
+							break;
+
+						case 39: // right
+						case 68: // d
+							moveRight = true;
+							break;
+
+					}
+
+				};
+
+				var onKeyUp = function ( event ) {
+
+					switch( event.keyCode ) {
+
+						case 38: // up
+						case 87: // w
+							moveForward = false;
+							break;
+
+						case 37: // left
+						case 65: // a
+							moveLeft = false;
+							break;
+
+						case 40: // down
+						case 83: // s
+							moveBackward = false;
+							break;
+
+						case 39: // right
+						case 68: // d
+							moveRight = false;
+							break;
+
+					}
+
+				};
+
+				document.addEventListener( 'keydown', onKeyDown, false );
+				document.addEventListener( 'keyup', onKeyUp, false );
+			
+			}
+			
+			function init() {
+
+				scene = new THREE.Scene();
+				velocity = new THREE.Vector3();
+				
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );				
+				
+				controls = new THREE.PointerLockControls( camera );
+				scene.add( controls.getObject() );
+				
+				controls.getObject().translateX( 250 );				
+				controls.getObject().translateZ( 250 );
+				
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setClearColor( 0x333333, 1 );
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				// post-processing
+
+				composer = new THREE.EffectComposer( renderer );
+
+				var renderPass = new THREE.RenderPass( scene, camera );
+				var copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				composer.addPass( renderPass );
+
+				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 );
+				composer.addPass( colorCorrectionPass );
+
+				var vignettePass = new THREE.ShaderPass( THREE.VignetteShader );
+				vignettePass.uniforms[ "darkness" ].value = 1.0;
+				composer.addPass( vignettePass );
+
+				composer.addPass( copyPass );
+				copyPass.renderToScreen = true;
+
+				// events
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animateCamera( delta ) {
+				
+				var scale = 1400;
+
+				velocity.x -= velocity.x * 10.0 * delta;
+				velocity.z -= velocity.z * 10.0 * delta;
+
+				velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
+
+				if ( moveForward ) velocity.z -= scale * delta;
+				if ( moveBackward ) velocity.z += scale * delta;
+
+				if ( moveLeft ) velocity.x -= scale * delta;
+				if ( moveRight ) velocity.x += scale * delta;
+
+				controls.getObject().translateX( velocity.x * delta );				
+				controls.getObject().translateZ( velocity.z * delta );
+
+			}
+			
+			function animate() {
+
+				var delta = clock.getDelta();
+				
+				animateCamera( delta );
+				
+				render( delta );
+
+				stats.update();
+				
+				requestAnimationFrame( animate );
+
+			}
+
+			var clock = new THREE.Clock();
+
+			function render( delta ) {
+
+				THREE.AnimationHandler.update( delta );
+
+				// SEA3D Keyframe Update		
+				SEA3D.AnimationHandler.update( delta ); 
+
+				// Sound Update
+				THREE.Sound3D.update( camera );
+
+				//renderer.render( scene, camera );
+				composer.render( delta );
+
+			}
+
+		</script>
+	</body>
+</html>