/src/aerys/minko/scene/node/light/PointLight.as
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}