Browse Source

First somehow working version ;).

Just one hardcoded shader for the moment. Everything needs to get cleaned / bugfixed / optimized.
alteredq 14 years ago
parent
commit
f4fe695d9a

+ 5 - 0
src/animation/Animation.js

@@ -156,7 +156,12 @@ THREE.Animation.prototype.update = function( time ) {
 			object.skinMatrix           = JIThierarchy[ h ][ frame ];
 			object.skinMatrix           = JIThierarchy[ h ][ frame ];
 			object.autoUpdateMatrix     = false;
 			object.autoUpdateMatrix     = false;
 			object.matrixNeedsToUpdate  = false;
 			object.matrixNeedsToUpdate  = false;
+			
 			this.root.boneMatrices[ h ] = object.skinMatrix.flatten32;
 			this.root.boneMatrices[ h ] = object.skinMatrix.flatten32;
+			
+			//object.skinMatrix.flattenToArray( this.root.boneMatrices[ h ] );
+			//object.skinMatrix.flattenToArrayOffset( this.root.boneMatrices, h * 16 );
+			
 		}
 		}
 		else {
 		else {
 		
 		

+ 7 - 1
src/cameras/Camera.js

@@ -69,8 +69,12 @@ THREE.Camera.prototype.update = function( parentGlobalMatrix, forceUpdate, scene
 		else
 		else
 			this.globalMatrix.copy( this.localMatrix );
 			this.globalMatrix.copy( this.localMatrix );
 
 
-		THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );	
+		THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
+		
+		//THREE.Matrix4.makeInvertTo( this.globalMatrix, this.inverseMatrix );	
 			
 			
+		//console.log(this.inverseMatrix);
+		
 		forceUpdate = true;
 		forceUpdate = true;
 	
 	
 	} else {
 	} else {
@@ -89,6 +93,8 @@ THREE.Camera.prototype.update = function( parentGlobalMatrix, forceUpdate, scene
 			forceUpdate              = true;
 			forceUpdate              = true;
 
 
 			THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
 			THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
+			
+			//THREE.Matrix4.makeInvertTo( this.globalMatrix, this.inverseMatrix );
 
 
 		}
 		}
 
 

+ 2 - 0
src/core/Geometry.js

@@ -17,6 +17,8 @@ THREE.Geometry = function () {
 	
 	
 	this.skinWeights = [];
 	this.skinWeights = [];
 	this.skinIndices = [];
 	this.skinIndices = [];
+	//this.skinVerticesA = [];
+	//this.skinVerticesB = [];
 
 
 	this.boundingBox = null;
 	this.boundingBox = null;
 	this.boundingSphere = null;
 	this.boundingSphere = null;

+ 101 - 2
src/core/Matrix4.js

@@ -18,6 +18,38 @@ THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33
 	this.flat = new Array( 16 );
 	this.flat = new Array( 16 );
 	this.m33 = new THREE.Matrix3();
 	this.m33 = new THREE.Matrix3();
 
 
+	// WebGL additions - NEEDS TO BE DISCUSSED!
+
+	if( typeof Float32Array !== 'undefined' ) {
+
+		var that = this;		
+		this.float32Array    = new Float32Array( 16 );
+		this.float32Array3x3 = new Float32Array( 9 );
+		
+		this.flatten32 = function() {
+			
+			var flat = that.float32Array;
+			
+			flat[ 0  ] = that.n11; flat[ 1  ] = that.n21; flat[ 2  ] = that.n31; flat[ 3  ] = that.n41;
+			flat[ 4  ] = that.n12; flat[ 5  ] = that.n22; flat[ 6  ] = that.n32; flat[ 7  ] = that.n42;
+			flat[ 8  ] = that.n13; flat[ 9  ] = that.n23; flat[ 10 ] = that.n33; flat[ 11 ] = that.n43;
+			flat[ 12 ] = that.n14; flat[ 13 ] = that.n24; flat[ 14 ] = that.n34; flat[ 15 ] = that.n44;
+	
+			return flat;
+		}
+		
+		this.flatten323x3 = function() {
+			
+			var flat = that.float32Array3x3;
+
+			flat[ 0 ] = that.n11; flat[ 1 ] = that.n21; flat[ 2 ] = that.n31;
+			flat[ 3 ] = that.n12; flat[ 4 ] = that.n22; flat[ 5 ] = that.n32;
+			flat[ 6 ] = that.n13; flat[ 7 ] = that.n23; flat[ 8 ] = that.n33;
+			
+			return flat;
+		}
+	}
+	
 };
 };
 
 
 THREE.Matrix4.prototype = {
 THREE.Matrix4.prototype = {
@@ -389,6 +421,32 @@ THREE.Matrix4.prototype = {
 
 
 	},
 	},
 
 
+	flattenToArrayOffset: function( flat, offset ) {
+		
+		flat[ offset ] 	   = this.n11;
+		flat[ offset + 1 ] = this.n21;
+		flat[ offset + 2 ] = this.n31;
+		flat[ offset + 3 ] = this.n41;
+
+		flat[ offset + 4 ] = this.n12;
+		flat[ offset + 5 ] = this.n22;
+		flat[ offset + 6 ] = this.n32;
+		flat[ offset + 7 ] = this.n42;
+
+		flat[ offset + 8 ]  = this.n13;
+		flat[ offset + 9 ]  = this.n23;
+		flat[ offset + 10 ] = this.n33;
+		flat[ offset + 11 ] = this.n43;
+
+		flat[ offset + 12 ] = this.n14;
+		flat[ offset + 13 ] = this.n24;
+		flat[ offset + 14 ] = this.n34;
+		flat[ offset + 15 ] = this.n44;
+
+		return flat;
+
+	},
+
 	setTranslation: function( x, y, z ) {
 	setTranslation: function( x, y, z ) {
 
 
 		this.set( 1, 0, 0, x,
 		this.set( 1, 0, 0, x,
@@ -626,8 +684,50 @@ THREE.Matrix4.rotationAxisAngleMatrix = function ( axis, angle ) {
 
 
 };
 };
 
 
+THREE.Matrix4.makeInvert = function ( m1, m2 ) {
+
+	// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
+
+	var n11 = m1.n11, n12 = m1.n12, n13 = m1.n13, n14 = m1.n14,
+		n21 = m1.n21, n22 = m1.n22, n23 = m1.n23, n24 = m1.n24,
+		n31 = m1.n31, n32 = m1.n32, n33 = m1.n33, n34 = m1.n34,
+		n41 = m1.n41, n42 = m1.n42, n43 = m1.n43, n44 = m1.n44;
+
+	if( m2 === undefined ) m2 = new THREE.Matrix4();
+
+	m2.n11 = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
+	m2.n12 = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
+	m2.n13 = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;
+	m2.n14 = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;
+	m2.n21 = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;
+	m2.n22 = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;
+	m2.n23 = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;
+	m2.n24 = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;
+	m2.n31 = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;
+	m2.n32 = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;
+	m2.n33 = n13*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;
+	m2.n34 = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;
+	m2.n41 = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;
+	m2.n42 = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;
+	m2.n43 = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;
+	m2.n44 = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;
+	m2.multiplyScalar( 1 / m1.determinant() );
+
+	return m2;
+
+};
+
+/*
 THREE.Matrix4.makeInvert = function ( m1 ) {
 THREE.Matrix4.makeInvert = function ( m1 ) {
 
 
+	var m2 = new THREE.Matrix4();
+	
+	return THREE.Matrix4.makeInvertTo( m1, m2 );
+
+};
+
+THREE.Matrix4.makeInvertTo = function ( m1, m2 ) {
+
 	var n11 = m1.n11, n12 = m1.n12, n13 = m1.n13, n14 = m1.n14,
 	var n11 = m1.n11, n12 = m1.n12, n13 = m1.n13, n14 = m1.n14,
 		n21 = m1.n21, n22 = m1.n22, n23 = m1.n23, n24 = m1.n24,
 		n21 = m1.n21, n22 = m1.n22, n23 = m1.n23, n24 = m1.n24,
 		n31 = m1.n31, n32 = m1.n32, n33 = m1.n33, n34 = m1.n34,
 		n31 = m1.n31, n32 = m1.n32, n33 = m1.n33, n34 = m1.n34,
@@ -635,7 +735,6 @@ THREE.Matrix4.makeInvert = function ( m1 ) {
 
 
 	//TODO: make this more efficient
 	//TODO: make this more efficient
 	//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
 	//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
-	var m2 = new THREE.Matrix4();
 
 
 	m2.n11 = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
 	m2.n11 = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
 	m2.n12 = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
 	m2.n12 = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
@@ -658,7 +757,7 @@ THREE.Matrix4.makeInvert = function ( m1 ) {
 	return m2;
 	return m2;
 
 
 };
 };
-
+*/
 THREE.Matrix4.makeInvert3x3 = function ( m1 ) {
 THREE.Matrix4.makeInvert3x3 = function ( m1 ) {
 
 
 	// input:  THREE.Matrix4, output: THREE.Matrix3
 	// input:  THREE.Matrix4, output: THREE.Matrix3

+ 26 - 4
src/objects/SkinnedMesh.js

@@ -2,6 +2,14 @@
  * @author mikael emtinger / http://gomo.se/
  * @author mikael emtinger / http://gomo.se/
  */
  */
 
 
+// do not crash if somebody includes the file in oldie browser
+
+if ( !window.Float32Array ) {
+
+	window.Float32Array = Array;
+
+}
+
 THREE.SkinnedMesh = function( geometry, materials ) {
 THREE.SkinnedMesh = function( geometry, materials ) {
 	
 	
 	THREE.Mesh.call( this, geometry, materials );
 	THREE.Mesh.call( this, geometry, materials );
@@ -41,6 +49,8 @@ THREE.SkinnedMesh = function( geometry, materials ) {
 			else
 			else
 				this.bones[ this.geometry.bones[ b ].parent ].addChild( this.bones[ b ] );
 				this.bones[ this.geometry.bones[ b ].parent ].addChild( this.bones[ b ] );
 		}
 		}
+
+		//this.boneMatrices = new Float32Array( 16 * this.bones.length );
 		
 		
 		this.pose();
 		this.pose();
 
 
@@ -141,13 +151,25 @@ THREE.SkinnedMesh.prototype.pose = function() {
 
 
 	this.update( undefined, true );
 	this.update( undefined, true );
 
 
-	var boneInverses = [];
+	var bim, bone,
+		boneInverses = [];
 	
 	
 	for( var b = 0; b < this.bones.length; b++ ) {
 	for( var b = 0; b < this.bones.length; b++ ) {
 		
 		
-		boneInverses.push( THREE.Matrix4.makeInvert( this.bones[ b ].skinMatrix, new THREE.Matrix4()));
+		boneInverses.push( THREE.Matrix4.makeInvert( this.bones[ b ].skinMatrix, new THREE.Matrix4() ) );
 		this.boneMatrices.push( this.bones[ b ].skinMatrix.flatten32 );
 		this.boneMatrices.push( this.bones[ b ].skinMatrix.flatten32 );
+		
+/*		
+		bone = this.bones[ b ];
+		
+		boneInverses.push( THREE.Matrix4.makeInvert( bone.skinMatrix ) );
+		
+		bim = new Float32Array( 16 );
+		bone.skinMatrix.flattenToArray( bim );
+		this.boneMatrices.push( bim );
 
 
+		//bone.skinMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
+*/
 	}
 	}
 	
 	
 
 
@@ -168,10 +190,10 @@ THREE.SkinnedMesh.prototype.pose = function() {
 			var indexB = this.geometry.skinIndices[ i ].y;
 			var indexB = this.geometry.skinIndices[ i ].y;
 	
 	
 			vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
 			vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
-			this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ));
+			this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ) );
 	
 	
 			vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
 			vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
-			this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ));
+			this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ) );
 			
 			
 			// todo: add more influences
 			// todo: add more influences
 	
 	

+ 331 - 8
src/renderers/WebGLRenderer.js

@@ -43,6 +43,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	_projScreenMatrix = new THREE.Matrix4(),
 	_projScreenMatrix = new THREE.Matrix4(),
 	_projectionMatrixArray = new Float32Array( 16 ),
 	_projectionMatrixArray = new Float32Array( 16 ),
+	_cameraInverseMatrixArray = new Float32Array( 16 ),
 	
 	
 	_viewMatrixArray = new Float32Array( 16 ),	
 	_viewMatrixArray = new Float32Array( 16 ),	
 
 
@@ -64,7 +65,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	this.domElement = _canvas;
 	this.domElement = _canvas;
 	this.autoClear = true;
 	this.autoClear = true;
-	this.sortObjects = false;
+	this.sortObjects = true;
 
 
 	initGL( antialias, clearColor, clearAlpha );
 	initGL( antialias, clearColor, clearAlpha );
 
 
@@ -210,6 +211,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 		geometryChunk.__webGLUVBuffer = _gl.createBuffer();
 		geometryChunk.__webGLUVBuffer = _gl.createBuffer();
 		geometryChunk.__webGLUV2Buffer = _gl.createBuffer();
 		geometryChunk.__webGLUV2Buffer = _gl.createBuffer();
 		
 		
+		geometryChunk.__webGLSkinVertexABuffer = _gl.createBuffer();
+		geometryChunk.__webGLSkinVertexBBuffer = _gl.createBuffer();
+		geometryChunk.__webGLSkinIndicesBuffer = _gl.createBuffer();
+		geometryChunk.__webGLSkinWeightsBuffer = _gl.createBuffer();
+		
 		geometryChunk.__webGLFaceBuffer = _gl.createBuffer();
 		geometryChunk.__webGLFaceBuffer = _gl.createBuffer();
 		geometryChunk.__webGLLineBuffer = _gl.createBuffer();
 		geometryChunk.__webGLLineBuffer = _gl.createBuffer();
 
 
@@ -275,6 +281,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 		geometryChunk.__uvArray = new Float32Array( nvertices * 2 );
 		geometryChunk.__uvArray = new Float32Array( nvertices * 2 );
 		geometryChunk.__uv2Array = new Float32Array( nvertices * 2 );
 		geometryChunk.__uv2Array = new Float32Array( nvertices * 2 );
 
 
+		geometryChunk.__skinVertexAArray = new Float32Array( nvertices * 4 );
+		geometryChunk.__skinVertexBArray = new Float32Array( nvertices * 4 );
+		geometryChunk.__skinIndexArray = new Float32Array( nvertices * 4 );
+		geometryChunk.__skinWeightArray = new Float32Array( nvertices * 4 );
+		
 		geometryChunk.__faceArray = new Uint16Array( ntris * 3 );
 		geometryChunk.__faceArray = new Uint16Array( ntris * 3 );
 		geometryChunk.__lineArray = new Uint16Array( nlines * 2 );
 		geometryChunk.__lineArray = new Uint16Array( nlines * 2 );
 
 
@@ -290,6 +301,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var f, fl, fi, face, vertexNormals, faceNormal, normal, 
 		var f, fl, fi, face, vertexNormals, faceNormal, normal, 
 			uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, 
 			uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, 
 			c1, c2, c3, c4,
 			c1, c2, c3, c4,
+			sw1, sw2, sw3, sw4,
+			si1, si2, si3, si4,
+			sa1, sa2, sa3, sa4,
+			sb1, sb2, sb3, sb4,
 			m, ml, i,
 			m, ml, i,
 			vn, uvi, uv2i,
 			vn, uvi, uv2i,
 
 
@@ -303,6 +318,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		offset_tangent = 0,
 		offset_tangent = 0,
 		offset_line = 0,
 		offset_line = 0,
 		offset_color = 0,
 		offset_color = 0,
+		offset_skin = 0,
 
 
 		vertexArray = geometryChunk.__vertexArray,
 		vertexArray = geometryChunk.__vertexArray,
 		uvArray = geometryChunk.__uvArray,
 		uvArray = geometryChunk.__uvArray,
@@ -310,6 +326,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 		normalArray = geometryChunk.__normalArray,
 		normalArray = geometryChunk.__normalArray,
 		tangentArray = geometryChunk.__tangentArray,
 		tangentArray = geometryChunk.__tangentArray,
 		colorArray = geometryChunk.__colorArray,
 		colorArray = geometryChunk.__colorArray,
+		
+		skinVertexAArray = geometryChunk.__skinVertexAArray,
+		skinVertexBArray = geometryChunk.__skinVertexBArray,
+		skinIndexArray = geometryChunk.__skinIndexArray,
+		skinWeightArray = geometryChunk.__skinWeightArray,
 
 
 		faceArray = geometryChunk.__faceArray,
 		faceArray = geometryChunk.__faceArray,
 		lineArray = geometryChunk.__lineArray,
 		lineArray = geometryChunk.__lineArray,
@@ -330,7 +351,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 		obj_faces = geometry.faces,
 		obj_faces = geometry.faces,
 		obj_uvs = geometry.uvs,
 		obj_uvs = geometry.uvs,
 		obj_uvs2 = geometry.uvs2,
 		obj_uvs2 = geometry.uvs2,
-		obj_colors = geometry.colors;
+		obj_colors = geometry.colors,
+		
+		obj_skinVerticesA = geometry.skinVerticesA,
+		obj_skinVerticesB = geometry.skinVerticesB,
+		obj_skinIndices = geometry.skinIndices,
+		obj_skinWeights = geometry.skinWeights;
 		
 		
 		for ( f = 0, fl = chunk_faces.length; f < fl; f++ ) {
 		for ( f = 0, fl = chunk_faces.length; f < fl; f++ ) {
 
 
@@ -365,6 +391,96 @@ THREE.WebGLRenderer = function ( parameters ) {
 					offset += 9;
 					offset += 9;
 
 
 				}
 				}
+				
+				if ( obj_skinWeights.length ) {
+
+					// weights
+					
+					sw1 = obj_skinWeights[ face.a ];
+					sw2 = obj_skinWeights[ face.b ];
+					sw3 = obj_skinWeights[ face.c ];
+					
+					skinWeightArray[ offset_skin ]     = sw1.x;
+					skinWeightArray[ offset_skin + 1 ] = sw1.y;
+					skinWeightArray[ offset_skin + 2 ] = sw1.z;
+					skinWeightArray[ offset_skin + 3 ] = sw1.w;
+
+					skinWeightArray[ offset_skin + 4 ] = sw2.x;
+					skinWeightArray[ offset_skin + 5 ] = sw2.y;
+					skinWeightArray[ offset_skin + 6 ] = sw2.z;
+					skinWeightArray[ offset_skin + 7 ] = sw2.w;
+
+					skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+					skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+					skinWeightArray[ offset_skin + 10 ] = sw3.z;
+					skinWeightArray[ offset_skin + 11 ] = sw3.w;
+
+					// indices
+					
+					si1 = obj_skinIndices[ face.a ];
+					si2 = obj_skinIndices[ face.b ];
+					si3 = obj_skinIndices[ face.c ];
+
+					skinIndexArray[ offset_skin ]     = si1.x;
+					skinIndexArray[ offset_skin + 1 ] = si1.y;
+					skinIndexArray[ offset_skin + 2 ] = si1.z;
+					skinIndexArray[ offset_skin + 3 ] = si1.w;
+
+					skinIndexArray[ offset_skin + 4 ] = si2.x;
+					skinIndexArray[ offset_skin + 5 ] = si2.y;
+					skinIndexArray[ offset_skin + 6 ] = si2.z;
+					skinIndexArray[ offset_skin + 7 ] = si2.w;
+
+					skinIndexArray[ offset_skin + 8 ]  = si3.x;
+					skinIndexArray[ offset_skin + 9 ]  = si3.y;
+					skinIndexArray[ offset_skin + 10 ] = si3.z;
+					skinIndexArray[ offset_skin + 11 ] = si3.w;
+
+					// vertices A
+					
+					sa1 = obj_skinVerticesA[ face.a ];
+					sa2 = obj_skinVerticesA[ face.b ];
+					sa3 = obj_skinVerticesA[ face.c ];
+
+					skinVertexAArray[ offset_skin ]     = sa1.x;
+					skinVertexAArray[ offset_skin + 1 ] = sa1.y;
+					skinVertexAArray[ offset_skin + 2 ] = sa1.z;
+					skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
+
+					skinVertexAArray[ offset_skin + 4 ] = sa2.x;
+					skinVertexAArray[ offset_skin + 5 ] = sa2.y;
+					skinVertexAArray[ offset_skin + 6 ] = sa2.z;
+					skinVertexAArray[ offset_skin + 7 ] = 1;
+
+					skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
+					skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
+					skinVertexAArray[ offset_skin + 10 ] = sa3.z;
+					skinVertexAArray[ offset_skin + 11 ] = 1;
+
+					// vertices B
+					
+					sb1 = obj_skinVerticesB[ face.a ];
+					sb2 = obj_skinVerticesB[ face.b ];
+					sb3 = obj_skinVerticesB[ face.c ];
+
+					skinVertexBArray[ offset_skin ]     = sb1.x;
+					skinVertexBArray[ offset_skin + 1 ] = sb1.y;
+					skinVertexBArray[ offset_skin + 2 ] = sb1.z;
+					skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
+
+					skinVertexBArray[ offset_skin + 4 ] = sb2.x;
+					skinVertexBArray[ offset_skin + 5 ] = sb2.y;
+					skinVertexBArray[ offset_skin + 6 ] = sb2.z;
+					skinVertexBArray[ offset_skin + 7 ] = 1;
+
+					skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
+					skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
+					skinVertexBArray[ offset_skin + 10 ] = sb3.z;
+					skinVertexBArray[ offset_skin + 11 ] = 1;
+
+					offset_skin += 12;
+					
+				}
 
 
 				if ( dirtyColors && obj_colors.length ) {
 				if ( dirtyColors && obj_colors.length ) {
 					
 					
@@ -528,6 +644,120 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				}
 				}
 				
 				
+				if ( obj_skinWeights.length ) {
+
+					// weights
+					
+					sw1 = obj_skinWeights[ face.a ];
+					sw2 = obj_skinWeights[ face.b ];
+					sw3 = obj_skinWeights[ face.c ];
+					sw4 = obj_skinWeights[ face.d ];
+					
+					skinWeightArray[ offset_skin ]     = sw1.x;
+					skinWeightArray[ offset_skin + 1 ] = sw1.y;
+					skinWeightArray[ offset_skin + 2 ] = sw1.z;
+					skinWeightArray[ offset_skin + 3 ] = sw1.w;
+
+					skinWeightArray[ offset_skin + 4 ] = sw2.x;
+					skinWeightArray[ offset_skin + 5 ] = sw2.y;
+					skinWeightArray[ offset_skin + 6 ] = sw2.z;
+					skinWeightArray[ offset_skin + 7 ] = sw2.w;
+
+					skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+					skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+					skinWeightArray[ offset_skin + 10 ] = sw3.z;
+					skinWeightArray[ offset_skin + 11 ] = sw3.w;
+
+					skinWeightArray[ offset_skin + 12 ] = sw4.x;
+					skinWeightArray[ offset_skin + 13 ] = sw4.y;
+					skinWeightArray[ offset_skin + 14 ] = sw4.z;
+					skinWeightArray[ offset_skin + 15 ] = sw4.w;
+
+					// indices
+					
+					si1 = obj_skinIndices[ face.a ];
+					si2 = obj_skinIndices[ face.b ];
+					si3 = obj_skinIndices[ face.c ];
+					si4 = obj_skinIndices[ face.d ];
+
+					skinIndexArray[ offset_skin ]     = si1.x;
+					skinIndexArray[ offset_skin + 1 ] = si1.y;
+					skinIndexArray[ offset_skin + 2 ] = si1.z;
+					skinIndexArray[ offset_skin + 3 ] = si1.w;
+
+					skinIndexArray[ offset_skin + 4 ] = si2.x;
+					skinIndexArray[ offset_skin + 5 ] = si2.y;
+					skinIndexArray[ offset_skin + 6 ] = si2.z;
+					skinIndexArray[ offset_skin + 7 ] = si2.w;
+
+					skinIndexArray[ offset_skin + 8 ]  = si3.x;
+					skinIndexArray[ offset_skin + 9 ]  = si3.y;
+					skinIndexArray[ offset_skin + 10 ] = si3.z;
+					skinIndexArray[ offset_skin + 11 ] = si3.w;
+
+					skinIndexArray[ offset_skin + 12 ] = si4.x;
+					skinIndexArray[ offset_skin + 13 ] = si4.y;
+					skinIndexArray[ offset_skin + 14 ] = si4.z;
+					skinIndexArray[ offset_skin + 15 ] = si4.w;
+
+					// vertices A
+					
+					sa1 = obj_skinVerticesA[ face.a ];
+					sa2 = obj_skinVerticesA[ face.b ];
+					sa3 = obj_skinVerticesA[ face.c ];
+					sa4 = obj_skinVerticesA[ face.d ];
+
+					skinVertexAArray[ offset_skin ]     = sa1.x;
+					skinVertexAArray[ offset_skin + 1 ] = sa1.y;
+					skinVertexAArray[ offset_skin + 2 ] = sa1.z;
+					skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
+
+					skinVertexAArray[ offset_skin + 4 ] = sa2.x;
+					skinVertexAArray[ offset_skin + 5 ] = sa2.y;
+					skinVertexAArray[ offset_skin + 6 ] = sa2.z;
+					skinVertexAArray[ offset_skin + 7 ] = 1;
+
+					skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
+					skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
+					skinVertexAArray[ offset_skin + 10 ] = sa3.z;
+					skinVertexAArray[ offset_skin + 11 ] = 1;
+
+					skinVertexAArray[ offset_skin + 12 ] = sa4.x;
+					skinVertexAArray[ offset_skin + 13 ] = sa4.y;
+					skinVertexAArray[ offset_skin + 14 ] = sa4.z;
+					skinVertexAArray[ offset_skin + 15 ] = 1;
+
+					// vertices B
+					
+					sb1 = obj_skinVerticesB[ face.a ];
+					sb2 = obj_skinVerticesB[ face.b ];
+					sb3 = obj_skinVerticesB[ face.c ];
+					sb4 = obj_skinVerticesB[ face.d ];
+
+					skinVertexBArray[ offset_skin ]     = sb1.x;
+					skinVertexBArray[ offset_skin + 1 ] = sb1.y;
+					skinVertexBArray[ offset_skin + 2 ] = sb1.z;
+					skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
+
+					skinVertexBArray[ offset_skin + 4 ] = sb2.x;
+					skinVertexBArray[ offset_skin + 5 ] = sb2.y;
+					skinVertexBArray[ offset_skin + 6 ] = sb2.z;
+					skinVertexBArray[ offset_skin + 7 ] = 1;
+
+					skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
+					skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
+					skinVertexBArray[ offset_skin + 10 ] = sb3.z;
+					skinVertexBArray[ offset_skin + 11 ] = 1;
+
+					skinVertexBArray[ offset_skin + 12 ]  = sb4.x;
+					skinVertexBArray[ offset_skin + 13 ]  = sb4.y;
+					skinVertexBArray[ offset_skin + 14 ] = sb4.z;
+					skinVertexBArray[ offset_skin + 15 ] = 1;
+
+					offset_skin += 16;					
+					
+				}
+				
 				if ( dirtyColors && obj_colors.length ) {
 				if ( dirtyColors && obj_colors.length ) {
 
 
 					c1 = obj_colors[ face.a ];
 					c1 = obj_colors[ face.a ];
@@ -733,6 +963,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
 			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
 
 
 		}
 		}
+		
+		if( offset_skin > 0 ) {
+			
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinVertexABuffer );
+			_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexAArray, hint );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinVertexBBuffer );
+			_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexBArray, hint );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinIndicesBuffer );
+			_gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinWeightsBuffer );
+			_gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
+			
+		}
 
 
 	};
 	};
 
 
@@ -1029,7 +1275,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 					   maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point };
 					   maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point };
 		material.program = buildProgram( material.fragment_shader, material.vertex_shader, parameters );
 		material.program = buildProgram( material.fragment_shader, material.vertex_shader, parameters );
 
 
-		identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition' ];
+		identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition', 
+						'cameraInverseMatrix', 
+						'uBoneGlobalMatrices[0]', 'uBoneGlobalMatrices[1]', 'uBoneGlobalMatrices[2]', 'uBoneGlobalMatrices[3]', 'uBoneGlobalMatrices[4]',
+					    'uBoneGlobalMatrices[5]', 'uBoneGlobalMatrices[6]', 'uBoneGlobalMatrices[7]', 'uBoneGlobalMatrices[8]', 'uBoneGlobalMatrices[9]',
+					    'uBoneGlobalMatrices[10]', 'uBoneGlobalMatrices[11]', 'uBoneGlobalMatrices[12]', 'uBoneGlobalMatrices[13]', 'uBoneGlobalMatrices[14]'
+						];
 		for( u in material.uniforms ) {
 		for( u in material.uniforms ) {
 
 
 			identifiers.push(u);
 			identifiers.push(u);
@@ -1037,12 +1288,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 		}
 
 
 		cacheUniformLocations( material.program, identifiers );
 		cacheUniformLocations( material.program, identifiers );
-		cacheAttributeLocations( material.program, [ "position", "normal", "uv", "uv2", "tangent", "color" ] );
+		cacheAttributeLocations( material.program, [ "position", "normal", "uv", "uv2", "tangent", "color", 
+													 "skinVertexA", "skinVertexB", "skinIndex", "skinWeight" ] );
 
 
 	};
 	};
 	
 	
 	this.setProgram = function( camera, lights, fog, material, object ) {
 	this.setProgram = function( camera, lights, fog, material, object ) {
 		
 		
+		var skinning = true; // hack for testing
+		
 		if ( !material.program ) this.initMaterial( material, lights, fog );
 		if ( !material.program ) this.initMaterial( material, lights, fog );
 
 
 		var program = material.program, 
 		var program = material.program, 
@@ -1131,7 +1385,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 		}
 		
 		
 		if ( material instanceof THREE.MeshShaderMaterial ||
 		if ( material instanceof THREE.MeshShaderMaterial ||
-			 material.env_map) {
+			 material.env_map ||
+			 skinning ) {
 				 
 				 
 			_gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray );
 			_gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray );
 		
 		
@@ -1139,12 +1394,36 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( material instanceof THREE.MeshPhongMaterial ||
 		if ( material instanceof THREE.MeshPhongMaterial ||
 			 material instanceof THREE.MeshLambertMaterial ||
 			 material instanceof THREE.MeshLambertMaterial ||
-			 material instanceof THREE.MeshShaderMaterial ) {
+			 material instanceof THREE.MeshShaderMaterial ||
+			 skinning ) {
 			 
 			 
 			_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray );
 			_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray );
 			
 			
 		}
 		}
 		
 		
+		if ( skinning ) {
+			
+			_gl.uniformMatrix4fv( p_uniforms.cameraInverseMatrix, false, _cameraInverseMatrixArray );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[0]"], false, object.boneMatrices[0]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[1]"], false, object.boneMatrices[1]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[2]"], false, object.boneMatrices[2]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[3]"], false, object.boneMatrices[3]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[4]"], false, object.boneMatrices[4]() );
+			
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[5]"], false, object.boneMatrices[5]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[6]"], false, object.boneMatrices[6]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[7]"], false, object.boneMatrices[7]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[8]"], false, object.boneMatrices[8]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[9]"], false, object.boneMatrices[9]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[10]"], false, object.boneMatrices[10]() );
+			
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[11]"], false, object.boneMatrices[11]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[12]"], false, object.boneMatrices[12]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[13]"], false, object.boneMatrices[13]() );
+			_gl.uniformMatrix4fv( p_uniforms["uBoneGlobalMatrices[14]"], false, object.boneMatrices[14]() );
+			
+		}
+		
 		return program;
 		return program;
 		
 		
 	};
 	};
@@ -1229,6 +1508,26 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
+		if ( object instanceof THREE.SkinnedMesh ) {
+			
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinVertexABuffer );
+			_gl.vertexAttribPointer( attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0 );
+			_gl.enableVertexAttribArray( attributes.skinVertexA );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinVertexBBuffer );
+			_gl.vertexAttribPointer( attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0 );
+			_gl.enableVertexAttribArray( attributes.skinVertexB );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinIndicesBuffer );
+			_gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
+			_gl.enableVertexAttribArray( attributes.skinIndex );
+
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLSkinWeightsBuffer );
+			_gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
+			_gl.enableVertexAttribArray( attributes.skinWeight );
+			
+		}
+		
 		// render mesh
 		// render mesh
 
 
 		if ( object instanceof THREE.Mesh ) {
 		if ( object instanceof THREE.Mesh ) {
@@ -1466,10 +1765,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 		
 		
 		camera.globalMatrix.flattenToArray( _viewMatrixArray );
 		camera.globalMatrix.flattenToArray( _viewMatrixArray );
 		camera.projectionMatrix.flattenToArray( _projectionMatrixArray );
 		camera.projectionMatrix.flattenToArray( _projectionMatrixArray );
+		camera.inverseMatrix.flattenToArray( _cameraInverseMatrixArray );
 
 
 		_projScreenMatrix.multiply( camera.projectionMatrix, camera.globalMatrix );
 		_projScreenMatrix.multiply( camera.projectionMatrix, camera.globalMatrix );
 		computeFrustum( _projScreenMatrix );
 		computeFrustum( _projScreenMatrix );
 		
 		
+		if( THREE.AnimationHandler )
+			THREE.AnimationHandler.update();
+		
 		scene.update( undefined, false, camera, this );
 		scene.update( undefined, false, camera, this );
 		
 		
 		this.initWebGLObjects( scene, camera );
 		this.initWebGLObjects( scene, camera );
@@ -2030,11 +2333,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 			"uniform mat4 viewMatrix;",
 			"uniform mat4 viewMatrix;",
 			"uniform mat3 normalMatrix;",
 			"uniform mat3 normalMatrix;",
 			"uniform vec3 cameraPosition;",
 			"uniform vec3 cameraPosition;",
+
+			"uniform mat4 cameraInverseMatrix;",
+
 			"attribute vec3 position;",
 			"attribute vec3 position;",
 			"attribute vec3 normal;",
 			"attribute vec3 normal;",
 			"attribute vec3 color;",
 			"attribute vec3 color;",
 			"attribute vec2 uv;",
 			"attribute vec2 uv;",
 			"attribute vec2 uv2;",
 			"attribute vec2 uv2;",
+			
+			"attribute vec4 skinVertexA;",
+			"attribute vec4 skinVertexB;",
+			"attribute vec4 skinIndex;",
+			"attribute vec4 skinWeight;",
 			""
 			""
 		].join("\n");
 		].join("\n");
 
 
@@ -3124,7 +3435,7 @@ THREE.ShaderLib = {
 			"uniform vec3 diffuse;",
 			"uniform vec3 diffuse;",
 			"uniform float opacity;",
 			"uniform float opacity;",
 
 
-			"varying vec3 vLightWeighting;",
+			"varying vec3 vLightWeighting;",		
 
 
 			THREE.Snippets[ "color_pars_fragment" ],
 			THREE.Snippets[ "color_pars_fragment" ],
 			THREE.Snippets[ "map_pars_fragment" ],
 			THREE.Snippets[ "map_pars_fragment" ],
@@ -3157,6 +3468,8 @@ THREE.ShaderLib = {
 			THREE.Snippets[ "lights_pars_vertex" ],
 			THREE.Snippets[ "lights_pars_vertex" ],
 			THREE.Snippets[ "color_pars_vertex" ],
 			THREE.Snippets[ "color_pars_vertex" ],
 
 
+			"uniform mat4 uBoneGlobalMatrices[20];",
+
 			"void main() {",
 			"void main() {",
 
 
 				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
 				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
@@ -3170,7 +3483,17 @@ THREE.ShaderLib = {
 
 
 				THREE.Snippets[ "lights_vertex" ],
 				THREE.Snippets[ "lights_vertex" ],
 
 
-				"gl_Position = projectionMatrix * mvPosition;",
+				//"gl_Position = projectionMatrix * mvPosition;",
+				
+				// skinning
+
+				"gl_Position  = ( uBoneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;",
+				"gl_Position += ( uBoneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;",
+				
+				// this doesn't work, no idea why
+				//"gl_Position  = projectionMatrix * cameraInverseMatrix * objectMatrix * gl_Position;",
+				
+				"gl_Position  = projectionMatrix * viewMatrix * objectMatrix * gl_Position;",
 
 
 			"}"
 			"}"