PageRenderTime 28ms CodeModel.GetById 13ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/aerys/minko/scene/node/light/PointLight.as

https://bitbucket.org/HopeSky/mars_nd2d
ActionScript | 241 lines | 195 code | 44 blank | 2 comment | 25 complexity | 0a697a58513afe3a007d5ca2b1c03262 MD5 | raw file
  1package aerys.minko.scene.node.light
  2{
  3	import aerys.minko.ns.minko_scene;
  4	import aerys.minko.render.resource.texture.CubeTextureResource;
  5	import aerys.minko.render.resource.texture.ITextureResource;
  6	import aerys.minko.render.resource.texture.TextureResource;
  7	import aerys.minko.scene.node.AbstractSceneNode;
  8	import aerys.minko.scene.node.ISceneNode;
  9	import aerys.minko.scene.node.Scene;
 10	import aerys.minko.type.binding.DataBindings;
 11	import aerys.minko.type.enum.ShadowMappingType;
 12	import aerys.minko.type.math.Matrix4x4;
 13	import aerys.minko.type.math.Vector4;
 14
 15	use namespace minko_scene;
 16	
 17	public class PointLight extends AbstractLight
 18	{
 19		public static const TYPE : uint = 2;
 20		
 21		private static const MAP_NAMES : Vector.<String> = new <String>[
 22			'shadowMapCube',
 23			'shadowMapDPFront',
 24			'shadowMapDPBack'
 25		];
 26		
 27		private static const TMP_VECTOR		: Vector4 = new Vector4();
 28		
 29		private static const FRUSTUM_POINTS	: Vector.<Vector4>	= new <Vector4>[
 30			new Vector4(-1, -1, 0, 1),
 31			new Vector4(-1, -1, 1, 1),
 32			new Vector4(-1, +1, 0, 1),
 33			new Vector4(-1, +1, 1, 1),
 34			new Vector4(+1, -1, 0, 1),
 35			new Vector4(+1, -1, 1, 1),
 36			new Vector4(+1, +1, 0, 1),
 37			new Vector4(+1, +1, 1, 1)
 38		];
 39		
 40		private var _worldPosition	: Vector4;
 41		private var _projection		: Matrix4x4;
 42		private var _shadowMapSize	: uint;
 43		
 44		public function get diffuse() : Number
 45		{
 46			return getProperty('diffuse') as Number;
 47		}
 48		
 49		public function get specular() : Number
 50		{
 51			return getProperty('specular') as Number;
 52		}
 53		
 54		public function get shininess() : Number
 55		{
 56			return getProperty('shininess') as Number;
 57		}
 58		
 59		public function get attenuationDistance() : Number
 60		{
 61			return getProperty('attenuationDistance') as Number;
 62		}
 63		
 64		public function get shadowMapSize() : uint
 65		{
 66			return _shadowMapSize;
 67		}
 68		
 69		public function get shadowMapZNear() : Number
 70		{
 71			return getProperty('zNear');
 72		}
 73		
 74		public function get shadowMapZFar() : Number
 75		{
 76			return getProperty('zFar');
 77		}
 78		
 79		public function set diffuse(v : Number)	: void
 80		{
 81			setProperty('diffuse', v);
 82			
 83			if (getProperty('diffuseEnabled') != (v != 0))
 84				setProperty('diffuseEnabled', v != 0);
 85		}
 86		
 87		public function set specular(v : Number) : void
 88		{
 89			setProperty('specular', v);
 90			
 91			if (getProperty('specularEnabled') != (v != 0))
 92				setProperty('specularEnabled', v != 0);
 93		}
 94		
 95		public function set shininess(v : Number) : void
 96		{
 97			setProperty('shininess', v);
 98		}
 99		
100		public function set attenuationDistance(v : Number) : void
101		{
102			setProperty('attenuationDistance', v);
103			
104			if (getProperty('attenuationEnabled') != (v != 0))
105				setProperty('attenuationEnabled', v != 0);
106		}
107		
108		public function set shadowMapSize(v : uint) : void
109		{
110			_shadowMapSize = v;
111			
112			this.shadowCastingType = this.shadowCastingType
113		}
114		
115		public function set shadowMapZNear(v : Number) : void
116		{
117			setProperty('zNear', v);
118			updateProjectionMatrix();
119		}
120		
121		public function set shadowMapZFar(v : Number) : void
122		{
123			setProperty('zFar', v);
124			updateProjectionMatrix();
125		}
126		
127		override public function set shadowCastingType(v : uint) : void
128		{
129			var shadowMap : ITextureResource;
130			
131			// start by clearing current shadow maps.
132			for each (var mapName : String in MAP_NAMES)
133			{
134				shadowMap = getProperty(mapName) as ITextureResource;
135				if (shadowMap !== null)
136				{
137					shadowMap.dispose();
138					removeProperty(mapName);
139				}
140			}
141			
142			switch (v)
143			{
144				case ShadowMappingType.NONE:
145					setProperty('shadowCastingType', ShadowMappingType.NONE);
146					break;
147				
148				case ShadowMappingType.DUAL_PARABOLOID:
149					if (!((_shadowMapSize & (~_shadowMapSize + 1)) == _shadowMapSize
150						&& _shadowMapSize <= 2048))
151						throw new Error(_shadowMapSize + ' is an invalid size for dual paraboloid shadow maps');
152					
153					// set textures and shadowmaptype
154					shadowMap = new TextureResource(_shadowMapSize, _shadowMapSize);
155					setProperty('shadowMapDPFront', shadowMap);
156					shadowMap = new TextureResource(_shadowMapSize, _shadowMapSize);
157					setProperty('shadowMapDPBack', shadowMap);
158					setProperty('shadowCastingType', ShadowMappingType.DUAL_PARABOLOID);
159					break;
160				
161				case ShadowMappingType.CUBE:
162					if (!((_shadowMapSize & (~_shadowMapSize + 1)) == _shadowMapSize
163						&& _shadowMapSize <= 1024))
164						throw new Error(_shadowMapSize + ' is an invalid size for cubic shadow maps');
165					
166					shadowMap = new CubeTextureResource(_shadowMapSize);
167					setProperty('shadowMapCube', shadowMap);
168					setProperty('shadowCastingType', ShadowMappingType.CUBE);
169					break;
170				
171				default: 
172					throw new ArgumentError('Invalid shadow casting type.');
173			}
174		}
175		
176		public function PointLight(color				: uint		= 0xFFFFFFFF,
177								   diffuse				: Number	= .6,
178								   specular				: Number	= .8,
179								   shininess			: Number	= 64,
180								   attenuationDistance	: Number	= 0,
181								   emissionMask			: uint		= 0x1,
182								   shadowCastingType	: uint		= 0,
183								   shadowMapSize		: uint		= 512,
184								   shadowMapZNear		: Number	= 0.1,
185								   shadowMapZFar		: Number	= 1000)
186		{
187			_worldPosition				= new Vector4();
188			_projection					= new Matrix4x4();				
189			_shadowMapSize				= shadowMapSize;
190			
191			super(color, emissionMask, shadowCastingType, TYPE); 
192			
193			this.diffuse				= diffuse;
194			this.specular				= specular;
195			this.shininess				= shininess;
196			this.attenuationDistance	= attenuationDistance;
197			this.shadowMapZNear			= shadowMapZNear;
198			this.shadowMapZFar			= shadowMapZFar;
199			
200			setProperty('worldPosition', _worldPosition);
201			setProperty('projection', _projection);
202			
203			if ([ShadowMappingType.NONE,
204				 ShadowMappingType.DUAL_PARABOLOID,
205				 ShadowMappingType.CUBE].indexOf(shadowCastingType) == -1)
206				throw new Error('Invalid ShadowMappingType.');
207		}
208		
209		override protected function transformChangedHandler(transform : Matrix4x4) : void
210		{
211			super.transformChangedHandler(transform);
212			
213			localToWorld.getTranslation(_worldPosition);
214		}
215		
216		private function updateProjectionMatrix() : void
217		{
218			var zNear	: Number = this.shadowMapZNear;
219			var zFar	: Number = this.shadowMapZFar;
220			var fd		: Number = 1. / Math.tan(Math.PI / 4);
221			var m33		: Number = 1. / (zFar - zNear);
222			var m43		: Number = -zNear / (zFar - zNear);
223			
224			_projection.initialize(fd, 0, 0, 0, 0, fd, 0, 0, 0, 0, m33, 1, 0, 0, m43, 0);
225		}
226		
227		override minko_scene function cloneNode() : AbstractSceneNode
228		{
229			var light : PointLight = new PointLight(
230				color, diffuse, specular, shininess, 
231				attenuationDistance, emissionMask, 
232				shadowCastingType, shadowMapSize
233			);		
234			
235			light.name = this.name;
236			light.transform.copyFrom(this.transform);
237			
238			return light;
239		}
240	}
241}