PageRenderTime 39ms CodeModel.GetById 28ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/src/away3d/lights/shadowmaps/DirectionalShadowMapper.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 196 lines | 161 code | 29 blank | 6 comment | 10 complexity | 91ad64aae505d55d65cff7424fd21a8c MD5 | raw file
  1package away3d.lights.shadowmaps
  2{
  3	import away3d.arcane;
  4	import away3d.cameras.Camera3D;
  5	import away3d.cameras.lenses.FreeMatrixLens;
  6	import away3d.containers.Scene3D;
  7	import away3d.core.math.Matrix3DUtils;
  8	import away3d.core.math.Plane3D;
  9	import away3d.core.render.DepthRenderer;
 10	import away3d.lights.DirectionalLight;
 11	
 12	import flash.display3D.textures.TextureBase;
 13	import flash.geom.Matrix3D;
 14	import flash.geom.Vector3D;
 15	
 16	use namespace arcane;
 17	
 18	public class DirectionalShadowMapper extends ShadowMapperBase
 19	{
 20		protected var _overallDepthCamera:Camera3D;
 21		protected var _localFrustum:Vector.<Number>;
 22		
 23		protected var _lightOffset:Number = 10000;
 24		protected var _matrix:Matrix3D;
 25		protected var _overallDepthLens:FreeMatrixLens;
 26		protected var _snap:Number = 64;
 27		
 28		protected var _cullPlanes:Vector.<Plane3D>;
 29		protected var _minZ:Number;
 30		protected var _maxZ:Number;
 31		
 32		public function DirectionalShadowMapper()
 33		{
 34			super();
 35			_cullPlanes = new Vector.<Plane3D>();
 36			_overallDepthLens = new FreeMatrixLens();
 37			_overallDepthCamera = new Camera3D(_overallDepthLens);
 38			_localFrustum = new Vector.<Number>(8*3);
 39			_matrix = new Matrix3D();
 40		}
 41		
 42		public function get snap():Number
 43		{
 44			return _snap;
 45		}
 46		
 47		public function set snap(value:Number):void
 48		{
 49			_snap = value;
 50		}
 51		
 52		public function get lightOffset():Number
 53		{
 54			return _lightOffset;
 55		}
 56		
 57		public function set lightOffset(value:Number):void
 58		{
 59			_lightOffset = value;
 60		}
 61		
 62		/**
 63		 * Depth projection matrix that projects from scene space to depth map.
 64		 */
 65		arcane function get depthProjection():Matrix3D
 66		{
 67			return _overallDepthCamera.viewProjection;
 68		}
 69		
 70		/**
 71		 * Depth projection matrix that projects from scene space to depth map.
 72		 */
 73		arcane function get depth():Number
 74		{
 75			return _maxZ - _minZ;
 76		}
 77		
 78		override protected function drawDepthMap(target:TextureBase, scene:Scene3D, renderer:DepthRenderer):void
 79		{
 80			_casterCollector.camera = _overallDepthCamera;
 81			_casterCollector.cullPlanes = _cullPlanes;
 82			_casterCollector.clear();
 83			scene.traversePartitions(_casterCollector);
 84			renderer.render(_casterCollector, target);
 85			_casterCollector.cleanUp();
 86		}
 87		
 88		protected function updateCullPlanes(viewCamera:Camera3D):void
 89		{
 90			var lightFrustumPlanes:Vector.<Plane3D> = _overallDepthCamera.frustumPlanes;
 91			var viewFrustumPlanes:Vector.<Plane3D> = viewCamera.frustumPlanes;
 92			_cullPlanes.length = 4;
 93			
 94			_cullPlanes[0] = lightFrustumPlanes[0];
 95			_cullPlanes[1] = lightFrustumPlanes[1];
 96			_cullPlanes[2] = lightFrustumPlanes[2];
 97			_cullPlanes[3] = lightFrustumPlanes[3];
 98			
 99			var dir:Vector3D = DirectionalLight(_light).sceneDirection;
100			var dirX:Number = dir.x;
101			var dirY:Number = dir.y;
102			var dirZ:Number = dir.z;
103			var j:int = 4;
104			for (var i:int = 0; i < 6; ++i) {
105				var plane:Plane3D = viewFrustumPlanes[i];
106				if (plane.a*dirX + plane.b*dirY + plane.c*dirZ < 0)
107					_cullPlanes[j++] = plane;
108			}
109		}
110		
111		override protected function updateDepthProjection(viewCamera:Camera3D):void
112		{
113			updateProjectionFromFrustumCorners(viewCamera, viewCamera.lens.frustumCorners, _matrix);
114			_overallDepthLens.matrix = _matrix;
115			updateCullPlanes(viewCamera);
116		}
117		
118		protected function updateProjectionFromFrustumCorners(viewCamera:Camera3D, corners:Vector.<Number>, matrix:Matrix3D):void
119		{
120			var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
121			var dir:Vector3D;
122			var x:Number, y:Number, z:Number;
123			var minX:Number, minY:Number;
124			var maxX:Number, maxY:Number;
125			var i:uint;
126			
127			dir = DirectionalLight(_light).sceneDirection;
128			_overallDepthCamera.transform = _light.sceneTransform;
129			x = int((viewCamera.x - dir.x*_lightOffset)/_snap)*_snap;
130			y = int((viewCamera.y - dir.y*_lightOffset)/_snap)*_snap;
131			z = int((viewCamera.z - dir.z*_lightOffset)/_snap)*_snap;
132			_overallDepthCamera.x = x;
133			_overallDepthCamera.y = y;
134			_overallDepthCamera.z = z;
135			
136			_matrix.copyFrom(_overallDepthCamera.inverseSceneTransform);
137			_matrix.prepend(viewCamera.sceneTransform);
138			_matrix.transformVectors(corners, _localFrustum);
139			
140			minX = maxX = _localFrustum[0];
141			minY = maxY = _localFrustum[1];
142			_maxZ = _localFrustum[2];
143			
144			i = 3;
145			while (i < 24) {
146				x = _localFrustum[i];
147				y = _localFrustum[uint(i + 1)];
148				z = _localFrustum[uint(i + 2)];
149				if (x < minX)
150					minX = x;
151				if (x > maxX)
152					maxX = x;
153				if (y < minY)
154					minY = y;
155				if (y > maxY)
156					maxY = y;
157				if (z > _maxZ)
158					_maxZ = z;
159				i += 3;
160			}
161			_minZ = 1;
162			
163			var w:Number = maxX - minX;
164			var h:Number = maxY - minY;
165			var d:Number = 1/(_maxZ - _minZ);
166			
167			if (minX < 0)
168				minX -= _snap; // because int() rounds up for < 0
169			if (minY < 0)
170				minY -= _snap;
171			minX = int(minX/_snap)*_snap;
172			minY = int(minY/_snap)*_snap;
173			
174			var snap2:Number = 2*_snap;
175			w = int(w/snap2 + 2)*snap2;
176			h = int(h/snap2 + 2)*snap2;
177			
178			maxX = minX + w;
179			maxY = minY + h;
180			
181			w = 1/w;
182			h = 1/h;
183			
184			raw[0] = 2*w;
185			raw[5] = 2*h;
186			raw[10] = d;
187			raw[12] = -(maxX + minX)*w;
188			raw[13] = -(maxY + minY)*h;
189			raw[14] = -_minZ*d;
190			raw[15] = 1;
191			raw[1] = raw[2] = raw[3] = raw[4] = raw[6] = raw[7] = raw[8] = raw[9] = raw[11] = 0;
192			
193			matrix.copyRawDataFrom(raw);
194		}
195	}
196}