 package aerys.minko.scene.controller.mesh.skinning
 {
+	import flash.geom.Matrix3D;
+	import flash.utils.ByteArray;
+	import flash.utils.Dictionary;
+	
 	import aerys.minko.render.geometry.Geometry;
 	import aerys.minko.render.geometry.stream.IVertexStream;
 	import aerys.minko.render.geometry.stream.StreamUsage;

			var format				: VertexFormat;
			var dataLength			: uint;
			var bytesPerVertex		: uint;
			var positionStride		: uint;
			var normalStride		: uint;
			var numInfluences		: uint;
			
			for (var streamId : uint = 0; streamId < numStreams; ++streamId)
			{
				var realStream			: VertexStream	= VertexStream(realGeometry.getVertexStream(streamId));
				var fakeStream			: VertexStream	= VertexStream(fakeGeometry.getVertexStream(streamId));
				var realData			: ByteArray		= realStream.lock();
				var fakeData			: ByteArray		= fakeStream.lock();
				
				if (streamId == 0)
				{
					format				= realStream.format;
					dataLength			= realData.length;
					bytesPerVertex		= format.numBytesPerVertex;
					positionStride		= format.getBytesOffsetForComponent(VertexComponent.XYZ);
					normalStride		= format.getBytesOffsetForComponent(VertexComponent.NORMAL);
					getInfluenceStrides(format, TMP_VECTOR);
					numInfluences		= influenceStrides.length;
				}
				
				for (var offset : uint = 0; offset < dataLength; offset += bytesPerVertex)
				{
					var positionOffset	: uint		= offset + positionStride;
					realData.position = positionOffset;
					var inX				: Number	= realData.readFloat();
					var inY				: Number	= realData.readFloat();
					var inZ				: Number	= realData.readFloat();
					
					var normalOffset	: uint		= offset + normalStride;
					realData.position = normalOffset;
					var inNx			: Number	= realData.readFloat();
					var inNy			: Number	= realData.readFloat();
					var inNz			: Number	= realData.readFloat();
					
					var outX			: Number	= 0;
					var outY			: Number	= 0;
					var outZ			: Number	= 0;
					var outNx			: Number	= 0;
					var outNy			: Number	= 0;
					var outNz			: Number	= 0;
					
					for (var influenceId : uint = 0; influenceId < numInfluences; ++influenceId)
					{
						realData.position = offset + influenceStrides[influenceId];
						
						var jointId			: Number	= realData.readFloat();
						var jointWeight		: Number	= realData.readFloat();
						var matrixOffset	: uint		= 16 * jointId;
						
						if (jointWeight != 0)

								+ inY * _matrices[uint(matrixOffset + 9)]
								+ inZ * _matrices[uint(matrixOffset + 10)]
								+ _matrices[uint(matrixOffset + 11)]);
						}
					}
										
					fakeDataXYZ.position = positionOffset;
					fakeDataXYZ.writeFloat(outX);
					fakeDataXYZ.writeFloat(outY);
					fakeDataXYZ.writeFloat(outZ);
				}
				
				
				if (streamId == 0)
				{
					format				= realStreamNormal.format;
					dataLength			= realDataNormal.length;
					bytesPerVertex		= format.numBytesPerVertex;
					stride				= format.getBytesOffsetForComponent(VertexComponent.NORMAL);
					getInfluenceStrides(format, TMP_VECTOR);
					numInfluences		= influenceStrides.length;
				}
				
				for (offset = 0; offset < dataLength; offset += bytesPerVertex)
				{
					var normalOffset	: uint		= offset + stride;
					realDataNormal.position = normalOffset;
					var inNx			: Number	= realDataNormal.readFloat();
					var inNy			: Number	= realDataNormal.readFloat();
					var inNz			: Number	= realDataNormal.readFloat();
					
					var outNx			: Number	= 0;
					var outNy			: Number	= 0;
					var outNz			: Number	= 0;
					
					for (influenceId = 0; influenceId < numInfluences; ++influenceId)
					{
						realDataNormal.position = offset + influenceStrides[influenceId];
						
						jointId			= realDataNormal.readFloat();
						jointWeight		= realDataNormal.readFloat();
						matrixOffset	= 16 * jointId;
						
						if (jointWeight != 0)
						{							
							outNx += jointWeight * (inNx * _matrices[uint(matrixOffset + 0)]
								+ inNy * _matrices[uint(matrixOffset + 1)]
								+ inNz * _matrices[uint(matrixOffset + 2)]);
