PageRenderTime 319ms CodeModel.GetById 110ms app.highlight 102ms RepoModel.GetById 100ms app.codeStats 0ms

/src/away3d/extrusions/PathDuplicator.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 309 lines | 209 code | 52 blank | 48 comment | 29 complexity | 85cf64505cd1898ce97a50fd9f6b5300 MD5 | raw file
  1package away3d.extrusions
  2{
  3	
  4	import away3d.containers.ObjectContainer3D;
  5	import away3d.containers.Scene3D;
  6	import away3d.entities.Mesh;
  7	import away3d.paths.IPath;
  8	
  9	import flash.geom.Matrix3D;
 10	import flash.geom.Vector3D;
 11	
 12	[Deprecated]
 13	public class PathDuplicator
 14	{
 15		private var _transform:Matrix3D;
 16		private var _upAxis:Vector3D = new Vector3D(0, 1, 0);
 17		private var _path:IPath;
 18		private var _scene:Scene3D;
 19		private var _meshes:Vector.<Mesh>;
 20		private var _clones:Vector.<Mesh>;
 21		private var _repeat:uint;
 22		private var _alignToPath:Boolean;
 23		private var _randomRotationY:Boolean;
 24		private var _segmentSpread:Boolean = false;
 25		private var _mIndex:uint;
 26		private var _count:uint;
 27		private var _container:ObjectContainer3D;
 28		
 29		/**
 30		 * Creates a new <code>PathDuplicator</code>
 31		 * Class replicates and distribute one or more mesh(es) along a path. The offsets are defined by the position of the object. 0,0,0 would place the center of the mesh exactly on Path.
 32		 *
 33		 * @param    path                [optional]    A Path object. The _path definition. either Cubic or Quadratic path
 34		 * @param    meshes                [optional]    Vector.&lt;Mesh&gt;. One or more meshes to repeat along the path.
 35		 * @param    scene                [optional]    Scene3D. The scene where to addchild the meshes if no ObjectContainer3D is provided.
 36		 * @param    repeat                [optional]    uint. How many times a mesh is cloned per PathSegment. Default is 1.
 37		 * @param    alignToPath            [optional]    Boolean. If the alignment of the clones must follow the path. Default is true.
 38		 * @param    segmentSpread        [optional]    Boolean. If more than one Mesh is passed, it defines if the clones alternate themselves per PathSegment or each repeat. Default is false.
 39		 * @param container                [optional]    ObjectContainer3D. If an ObjectContainer3D is provided, the meshes are addChilded to it instead of directly into the scene. The container is NOT addChilded to the scene by default.
 40		 * @param    randomRotationY    [optional]    Boolean. If the clones must have a random rotationY added to them.
 41		 *
 42		 */
 43		function PathDuplicator(path:IPath = null, meshes:Vector.<Mesh> = null, scene:Scene3D = null, repeat:uint = 1, alignToPath:Boolean = true, segmentSpread:Boolean = true, container:ObjectContainer3D = null, randomRotationY:Boolean = false)
 44		{
 45			_path = path;
 46			_meshes = meshes;
 47			_scene = scene;
 48			_repeat = repeat;
 49			_alignToPath = alignToPath;
 50			_segmentSpread = segmentSpread;
 51			_randomRotationY = randomRotationY;
 52			_container = container;
 53		}
 54		
 55		/**
 56		 * The up axis to which duplicated objects' Y axis will be oriented.
 57		 */
 58		public function get upAxis():Vector3D
 59		{
 60			return _upAxis;
 61		}
 62		
 63		public function set upAxis(value:Vector3D):void
 64		{
 65			_upAxis = value;
 66		}
 67		
 68		/**
 69		 * If a container is provided, the meshes are addChilded to it instead of directly into the scene. The container is NOT addChilded to the scene.
 70		 */
 71		public function set container(cont:ObjectContainer3D):void
 72		{
 73			_container = cont;
 74		}
 75		
 76		public function get container():ObjectContainer3D
 77		{
 78			return _container;
 79		}
 80		
 81		/**
 82		 * Defines the resolution between each PathSegments. Default 1, is also minimum.
 83		 */
 84		public function set repeat(val:uint):void
 85		{
 86			_repeat = (val < 1)? 1 : val;
 87		}
 88		
 89		public function get repeat():uint
 90		{
 91			return _repeat;
 92		}
 93		
 94		/**
 95		 * Defines if the profile point array should be orientated on path or not. Default true.
 96		 */
 97		public function set alignToPath(b:Boolean):void
 98		{
 99			_alignToPath = b;
100		}
101		
102		public function get alignToPath():Boolean
103		{
104			return _alignToPath;
105		}
106		
107		/**
108		 * Defines if a clone gets a random rotationY to break visual repetitions, usefull in case of vegetation for instance.
109		 */
110		public function set randomRotationY(b:Boolean):void
111		{
112			_randomRotationY = b;
113		}
114		
115		public function get randomRotationY():Boolean
116		{
117			return _randomRotationY;
118		}
119		
120		/**
121		 * returns a vector with all meshes cloned since last time build method was called. Returns null if build hasn't be called yet.
122		 * Another option to retreive the generated meshes is to pass an ObjectContainer3D to the class
123		 */
124		public function get clones():Vector.<Mesh>
125		{
126			return _clones;
127		}
128		
129		/**
130		 * Sets and defines the Path object. See extrusions.utils package. Required for this class.
131		 */
132		public function set path(p:IPath):void
133		{
134			_path = p;
135		}
136		
137		public function get path():IPath
138		{
139			return _path;
140		}
141		
142		/**
143		 * Defines an optional Vector.&lt;Mesh&gt;. One or more meshes to repeat along the path.
144		 * When the last in the vector is reached, the first in the array will be used, this process go on and on until the last segment.
145		 *
146		 * @param    ms    A Vector.<Mesh>. One or more meshes to repeat along the path. Required for this class.
147		 */
148		public function set meshes(ms:Vector.<Mesh>):void
149		{
150			_meshes = ms;
151		}
152		
153		public function get meshes():Vector.<Mesh>
154		{
155			return _meshes;
156		}
157		
158		public function clearData(destroyCachedMeshes:Boolean):void
159		{
160			if (destroyCachedMeshes) {
161				var i:uint = 0;
162				if (meshes) {
163					for (i = 0; i < meshes.length; ++i)
164						meshes[i] = null;
165				}
166				if (_clones) {
167					for (i; i < _clones.length; ++i)
168						_clones[i] = null;
169				}
170			}
171			_meshes = _clones = null;
172		}
173		
174		/**
175		 * defines if the meshes[index] is repeated per segments or duplicated after each others. default = false.
176		 */
177		public function set segmentSpread(b:Boolean):void
178		{
179			_segmentSpread = b;
180		}
181		
182		public function get segmentSpread():Boolean
183		{
184			return _segmentSpread;
185		}
186		
187		/**
188		 * Triggers the generation
189		 */
190		public function build():void
191		{
192			if (!_path || !_meshes || meshes.length == 0)
193				throw new Error("PathDuplicator error: Missing Path or Meshes data.");
194			if (!_scene && !_container)
195				throw new Error("PathDuplicator error: Missing Scene3D or ObjectContainer3D.");
196			
197			_mIndex = _meshes.length - 1;
198			_count = 0;
199			_clones = new Vector.<Mesh>();
200			
201			var segments:Vector.<Vector.<Vector3D>> = _path.getPointsOnCurvePerSegment(_repeat);
202			var tmppt:Vector3D = new Vector3D();
203			
204			var i:uint;
205			var j:uint;
206			var nextpt:Vector3D;
207			var m:Mesh;
208			var tPosi:Vector3D;
209			
210			for (i = 0; i < segments.length; ++i) {
211				
212				if (!_segmentSpread)
213					_mIndex = (_mIndex + 1 != _meshes.length)? _mIndex + 1 : 0;
214				
215				for (j = 0; j < segments[i].length; ++j) {
216					
217					if (_segmentSpread)
218						_mIndex = (_mIndex + 1 != _meshes.length)? _mIndex + 1 : 0;
219					
220					m = _meshes[_mIndex];
221					tPosi = m.position;
222					
223					if (_alignToPath) {
224						_transform = new Matrix3D();
225						
226						if (i == segments.length - 1 && j == segments[i].length - 1) {
227							nextpt = segments[i][j - 1];
228							orientateAt(segments[i][j], nextpt);
229						} else {
230							nextpt = (j < segments[i].length - 1)? segments[i][j + 1] : segments[i + 1][0];
231							orientateAt(nextpt, segments[i][j]);
232						}
233					}
234					
235					if (_alignToPath) {
236						tmppt.x = tPosi.x*_transform.rawData[0] + tPosi.y*_transform.rawData[4] + tPosi.z*_transform.rawData[8] + _transform.rawData[12];
237						tmppt.y = tPosi.x*_transform.rawData[1] + tPosi.y*_transform.rawData[5] + tPosi.z*_transform.rawData[9] + _transform.rawData[13];
238						tmppt.z = tPosi.x*_transform.rawData[2] + tPosi.y*_transform.rawData[6] + tPosi.z*_transform.rawData[10] + _transform.rawData[14];
239						
240						tmppt.x += segments[i][j].x;
241						tmppt.y += segments[i][j].y;
242						tmppt.z += segments[i][j].z;
243					} else
244						tmppt = new Vector3D(tPosi.x + segments[i][j].x, tPosi.y + segments[i][j].y, tPosi.z + segments[i][j].z);
245					
246					generate(m, tmppt);
247				}
248			}
249			
250			segments = null;
251		}
252		
253		private function orientateAt(target:Vector3D, position:Vector3D):void
254		{
255			var xAxis:Vector3D;
256			var yAxis:Vector3D;
257			var zAxis:Vector3D = target.subtract(position);
258			zAxis.normalize();
259			
260			if (zAxis.length > 0.1) {
261				xAxis = _upAxis.crossProduct(zAxis);
262				xAxis.normalize();
263				
264				yAxis = xAxis.crossProduct(zAxis);
265				yAxis.normalize();
266				
267				var rawData:Vector.<Number> = _transform.rawData;
268				
269				rawData[0] = xAxis.x;
270				rawData[1] = xAxis.y;
271				rawData[2] = xAxis.z;
272				
273				rawData[4] = -yAxis.x;
274				rawData[5] = -yAxis.y;
275				rawData[6] = -yAxis.z;
276				
277				rawData[8] = zAxis.x;
278				rawData[9] = zAxis.y;
279				rawData[10] = zAxis.z;
280				
281				_transform.rawData = rawData;
282			}
283		}
284		
285		private function generate(m:Mesh, position:Vector3D):void
286		{
287			var clone:Mesh = m.clone() as Mesh;
288			
289			if (_alignToPath)
290				clone.transform = _transform;
291			else
292				clone.position = position;
293			
294			clone.name = (m.name != null)? m.name + "_" + _count : "clone_" + _count;
295			_count++;
296			
297			if (_randomRotationY)
298				clone.rotationY = Math.random()*360;
299			
300			if (_container)
301				_container.addChild(clone);
302			else
303				_scene.addChild(clone);
304			
305			_clones.push(clone);
306		}
307	
308	}
309}