PageRenderTime 608ms CodeModel.GetById 321ms app.highlight 109ms RepoModel.GetById 173ms app.codeStats 0ms

/src/away3d/extrusions/SkinExtrude.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 376 lines | 273 code | 65 blank | 38 comment | 32 complexity | a86fbfdc480b1771fafbc4092ee1810f MD5 | raw file
  1package away3d.extrusions
  2{
  3	import away3d.bounds.BoundingVolumeBase;
  4	import away3d.core.base.Geometry;
  5	import away3d.core.base.SubGeometry;
  6	import away3d.core.base.SubMesh;
  7	import away3d.core.base.data.UV;
  8	import away3d.core.base.data.Vertex;
  9	import away3d.entities.Mesh;
 10	import away3d.materials.MaterialBase;
 11	import away3d.tools.helpers.MeshHelper;
 12	
 13	import flash.geom.Vector3D;
 14	
 15	public class SkinExtrude extends Mesh
 16	{
 17		private const LIMIT:uint = 196605;
 18		private var _tmpVectors:Vector.<Number>;
 19		private var _subGeometry:SubGeometry;
 20		private var _indice:uint;
 21		private var _uva:UV;
 22		private var _uvb:UV;
 23		private var _uvc:UV;
 24		private var _uvd:UV;
 25		private var _va:Vertex;
 26		private var _vb:Vertex;
 27		private var _vc:Vertex;
 28		private var _vd:Vertex;
 29		private var _uvs:Vector.<Number>;
 30		private var _vertices:Vector.<Number>;
 31		private var _indices:Vector.<uint>;
 32		private var _geomDirty:Boolean = true;
 33		
 34		private var _profiles:Vector.<Vector.<Vector3D>>;
 35		private var _subdivision:uint;
 36		private var _centerMesh:Boolean;
 37		private var _closeShape:Boolean;
 38		private var _coverAll:Boolean;
 39		private var _flip:Boolean;
 40		
 41		/*
 42		 * Class SkinExtrude generates (and becomes) a mesh from a multidimentional vector of vector3D's . <code>SkinExtrude</code>
 43		 *@param	material			MaterialBase. The SkinExtrude (Mesh) material
 44		 *@param	profiles			Vector.&;t;Vector.&lt;Vector3D&gt;&gt; Multidimentional vector of vectors holding the vector3d's defining the shape. &lt; &lt;va0, va1&gt;, &lt;vb0, vb1&gt; &gt;
 45		 *@param	subdivision		[optional] uint. The _subdivision between vectors. Default is 1.
 46		 *@param	centerMesh	[optional] Boolean. If the final mesh must be _centerMeshed. Default is false.
 47		 *@param	closeShape		[optional] Boolean. If the last vector must be linked to the first vector. Default is false.
 48		 *@param	coverAll			[optional] Boolean. If the mapping is stretched over the entire mesh or from vector to vector. Default is false.
 49		 *@param	flip				[optional] Boolean. If the faces need to be inverted. Default is false.
 50		 */
 51		public function SkinExtrude(material:MaterialBase, profiles:Vector.<Vector.<Vector3D>>, subdivision:uint = 1, centerMesh:Boolean = false, closeShape:Boolean = false, coverAll:Boolean = false, flip:Boolean = false)
 52		{
 53			var geom:Geometry = new Geometry();
 54			_subGeometry = new SubGeometry();
 55			geom.addSubGeometry(_subGeometry);
 56			super(geom, material);
 57			
 58			_profiles = profiles;
 59			_subdivision = subdivision;
 60			_centerMesh = centerMesh;
 61			_closeShape = closeShape;
 62			_coverAll = coverAll;
 63			_flip = flip;
 64		}
 65		
 66		/**
 67		 * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
 68		 */
 69		public function get profiles():Vector.<Vector.<Vector3D>>
 70		{
 71			return _profiles;
 72		}
 73		
 74		public function set profiles(val:Vector.<Vector.<Vector3D>>):void
 75		{
 76			_profiles = val;
 77			invalidateGeometry();
 78		}
 79		
 80		/**
 81		 * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to false.
 82		 */
 83		public function get coverAll():Boolean
 84		{
 85			return _coverAll;
 86		}
 87		
 88		public function set coverAll(val:Boolean):void
 89		{
 90			if (_coverAll == val)
 91				return;
 92			
 93			_coverAll = val;
 94			invalidateGeometry();
 95		}
 96		
 97		/**
 98		 * Defines if the last vector of Vector3D are joined to the first one, closing the shape. works from 3 vector.&lt;Vector3D&gt; entered.
 99		 */
100		public function get closeShape():Boolean
101		{
102			return _closeShape;
103		}
104		
105		public function set closeShape(val:Boolean):void
106		{
107			if (_closeShape == val)
108				return;
109			
110			_closeShape = val;
111			invalidateGeometry();
112		}
113		
114		/**
115		 * Defines if the face orientatio needs to be inverted
116		 */
117		public function get flip():Boolean
118		{
119			return _flip;
120		}
121		
122		public function set flip(val:Boolean):void
123		{
124			if (_flip == val)
125				return;
126			
127			_flip = val;
128			invalidateGeometry();
129		}
130		
131		/**
132		 * Defines whether the mesh is _centerMeshed of not after generation
133		 */
134		public function get centerMesh():Boolean
135		{
136			return _centerMesh;
137		}
138		
139		public function set centerMesh(val:Boolean):void
140		{
141			if (_centerMesh == val)
142				return;
143			
144			_centerMesh = val;
145			
146			if (_centerMesh && _subGeometry.vertexData.length > 0)
147				MeshHelper.applyPosition(this, (this.minX + this.maxX)*.5, (this.minY + this.maxY)*.5, (this.minZ + this.maxZ)*.5);
148			else
149				invalidateGeometry();
150		}
151		
152		public function get subdivision():Number
153		{
154			return _subdivision;
155		}
156		
157		public function set subdivision(val:Number):void
158		{
159			if (_subdivision == val)
160				return;
161			
162			_subdivision = val;
163			invalidateGeometry();
164		}
165		
166		// building
167		private function buildExtrude():void
168		{
169			_geomDirty = false;
170			if (_profiles.length > 1 && _profiles[0].length > 1 && _profiles[1].length > 1) {
171				initHolders();
172				if (_closeShape && _profiles.length < 3)
173					_closeShape = false;
174				generate();
175			} else
176				throw new Error("SkinExtrude: 1 multidimentional Vector.<Vector.<Vector3D>> with minimum 2 children Vector.<Vector3D>. Each child Vector must hold at least 2 Vector3D.");
177			
178			if (_centerMesh)
179				MeshHelper.recenter(this);
180			
181			_tmpVectors = null;
182		}
183		
184		private function generate():void
185		{
186			var uvlength:int = (_closeShape)? _profiles.length : _profiles.length - 1;
187			for (var i:int = 0; i < _profiles.length - 1; ++i) {
188				_tmpVectors = new Vector.<Number>();
189				extrude(_profiles[i], _profiles[i + 1], (1/uvlength)*i, uvlength);
190			}
191			
192			if (_closeShape) {
193				_tmpVectors = new Vector.<Number>();
194				extrude(_profiles[_profiles.length - 1], _profiles[0], (1/uvlength)*i, uvlength);
195			}
196			
197			_subGeometry.updateVertexData(_vertices);
198			_subGeometry.updateIndexData(_indices);
199			_subGeometry.updateUVData(_uvs);
200			_uva = _uvb = _uvc = _uvd = null;
201			_va = _vb = _vc = _vd = null;
202			_uvs = _vertices = null;
203			_indices = null;
204		}
205		
206		private function extrude(vectsA:Vector.<Vector3D>, vectsB:Vector.<Vector3D>, vscale:Number, indexv:int):void
207		{
208			var i:int;
209			var j:int;
210			var k:int;
211			var stepx:Number;
212			var stepy:Number;
213			var stepz:Number;
214			
215			var u1:Number;
216			var u2:Number;
217			var index:int = 0;
218			var vertIndice:uint;
219			
220			var bu:Number = 0;
221			var bincu:Number = 1/(vectsA.length - 1);
222			var v1:Number = 0;
223			var v2:Number = 0;
224			
225			for (i = 0; i < vectsA.length; ++i) {
226				stepx = (vectsB[i].x - vectsA[i].x)/_subdivision;
227				stepy = (vectsB[i].y - vectsA[i].y)/_subdivision;
228				stepz = (vectsB[i].z - vectsA[i].z)/_subdivision;
229				
230				for (j = 0; j < _subdivision + 1; ++j)
231					_tmpVectors.push(vectsA[i].x + (stepx*j), vectsA[i].y + (stepy*j), vectsA[i].z + (stepz*j));
232				
233			}
234			
235			for (i = 0; i < vectsA.length - 1; ++i) {
236				
237				u1 = bu;
238				bu += bincu;
239				u2 = bu;
240				
241				for (j = 0; j < _subdivision; ++j) {
242					
243					v1 = (_coverAll)? vscale + ((j/_subdivision)/indexv) : j/_subdivision;
244					v2 = (_coverAll)? vscale + (( (j + 1)/_subdivision)/indexv) : (j + 1)/_subdivision;
245					
246					_uva.v = u1;
247					_uva.u = v1;
248					_uvb.v = u1;
249					_uvb.u = v2;
250					_uvc.v = u2;
251					_uvc.u = v2;
252					_uvd.v = u2;
253					_uvd.u = v1;
254					
255					_va.x = _tmpVectors[vertIndice = (index + j)*3];
256					_va.y = _tmpVectors[vertIndice + 1];
257					_va.z = _tmpVectors[vertIndice + 2];
258					
259					_vb.x = _tmpVectors[vertIndice = (index + j + 1)*3];
260					_vb.y = _tmpVectors[vertIndice + 1];
261					_vb.z = _tmpVectors[vertIndice + 2];
262					
263					_vc.x = _tmpVectors[vertIndice = (index + j + _subdivision + 2 )*3];
264					_vc.y = _tmpVectors[vertIndice + 1];
265					_vc.z = _tmpVectors[vertIndice + 2];
266					
267					_vd.x = _tmpVectors[vertIndice = (index + j + _subdivision + 1 )*3];
268					_vd.y = _tmpVectors[vertIndice + 1];
269					_vd.z = _tmpVectors[vertIndice + 2];
270					
271					if (_vertices.length == LIMIT) {
272						_subGeometry.updateVertexData(_vertices);
273						_subGeometry.updateIndexData(_indices);
274						_subGeometry.updateUVData(_uvs);
275						
276						_subGeometry = new SubGeometry();
277						this.geometry.addSubGeometry(_subGeometry);
278						_subGeometry.autoDeriveVertexNormals = true;
279						_subGeometry.autoDeriveVertexTangents = true;
280						_uvs = new Vector.<Number>();
281						_vertices = new Vector.<Number>();
282						_indices = new Vector.<uint>();
283						_indice = 0;
284					}
285					
286					if (_flip) {
287						
288						_vertices.push(_va.x, _va.y, _va.z, _vb.x, _vb.y, _vb.z, _vc.x, _vc.y, _vc.z);
289						_uvs.push(_uva.u, _uva.v, _uvb.u, _uvb.v, _uvc.u, _uvc.v);
290						
291						_vertices.push(_va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z, _vd.x, _vd.y, _vd.z);
292						_uvs.push(_uva.u, _uva.v, _uvc.u, _uvc.v, _uvd.u, _uvd.v);
293						
294					} else {
295						
296						_vertices.push(_vb.x, _vb.y, _vb.z, _va.x, _va.y, _va.z, _vc.x, _vc.y, _vc.z);
297						_uvs.push(_uvb.u, _uvb.v, _uva.u, _uva.v, _uvc.u, _uvc.v);
298						
299						_vertices.push(_vc.x, _vc.y, _vc.z, _va.x, _va.y, _va.z, _vd.x, _vd.y, _vd.z);
300						_uvs.push(_uvc.u, _uvc.v, _uva.u, _uva.v, _uvd.u, _uvd.v);
301					}
302					
303					for (k = 0; k < 6; ++k) {
304						_indices[_indice] = _indice;
305						_indice++;
306					}
307					
308				}
309				
310				index += _subdivision + 1;
311			}
312		}
313		
314		private function initHolders():void
315		{
316			_indice = 0;
317			_uva = new UV(0, 0);
318			_uvb = new UV(0, 0);
319			_uvc = new UV(0, 0);
320			_uvd = new UV(0, 0);
321			_va = new Vertex(0, 0, 0);
322			_vb = new Vertex(0, 0, 0);
323			_vc = new Vertex(0, 0, 0);
324			_vd = new Vertex(0, 0, 0);
325			_uvs = new Vector.<Number>();
326			_vertices = new Vector.<Number>();
327			_indices = new Vector.<uint>();
328			
329			_subGeometry.autoDeriveVertexNormals = true;
330			_subGeometry.autoDeriveVertexTangents = true;
331		}
332		
333		/**
334		 * @inheritDoc
335		 */
336		override public function get bounds():BoundingVolumeBase
337		{
338			if (_geomDirty)
339				buildExtrude();
340			
341			return super.bounds;
342		}
343		
344		/**
345		 * @inheritDoc
346		 */
347		override public function get geometry():Geometry
348		{
349			if (_geomDirty)
350				buildExtrude();
351			
352			return super.geometry;
353		}
354		
355		/**
356		 * @inheritDoc
357		 */
358		override public function get subMeshes():Vector.<SubMesh>
359		{
360			if (_geomDirty)
361				buildExtrude();
362			
363			return super.subMeshes;
364		}
365		
366		/**
367		 * Invalidates the geometry, causing it to be rebuillded when requested.
368		 */
369		private function invalidateGeometry():void
370		{
371			_geomDirty = true;
372			invalidateBounds();
373		}
374	
375	}
376}