PageRenderTime 29ms CodeModel.GetById 1ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/away3d/entities/SegmentSet.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 644 lines | 478 code | 114 blank | 52 comment | 50 complexity | b10ebdc65b8a94fed950c18562b3f4e2 MD5 | raw file
  1package away3d.entities
  2{
  3	import away3d.arcane;
  4	import away3d.animators.IAnimator;
  5	import away3d.bounds.BoundingSphere;
  6	import away3d.bounds.BoundingVolumeBase;
  7	import away3d.cameras.Camera3D;
  8	import away3d.core.base.IRenderable;
  9	import away3d.core.managers.Stage3DProxy;
 10	import away3d.core.partition.EntityNode;
 11	import away3d.core.partition.RenderableNode;
 12	import away3d.materials.MaterialBase;
 13	import away3d.materials.SegmentMaterial;
 14	import away3d.primitives.LineSegment;
 15	import away3d.primitives.data.Segment;
 16	import away3d.library.assets.AssetType;
 17	
 18	import flash.display3D.Context3D;
 19	import flash.display3D.Context3DVertexBufferFormat;
 20	import flash.display3D.IndexBuffer3D;
 21	import flash.display3D.VertexBuffer3D;
 22	import flash.geom.Matrix;
 23	import flash.geom.Matrix3D;
 24	import flash.geom.Vector3D;
 25	import flash.utils.Dictionary;
 26	
 27	use namespace arcane;
 28	
 29	public class SegmentSet extends Entity implements IRenderable
 30	{
 31		private const LIMIT:uint = 3*0xFFFF;
 32		private var _activeSubSet:SubSet;
 33		private var _subSets:Vector.<SubSet>;
 34		private var _subSetCount:uint;
 35		private var _numIndices:uint;
 36		private var _material:MaterialBase;
 37		private var _animator:IAnimator;
 38		private var _hasData:Boolean;
 39		
 40		protected var _segments:Dictionary;
 41		private var _indexSegments:uint;
 42		
 43		/**
 44		 * Creates a new SegmentSet object.
 45		 */
 46		public function SegmentSet()
 47		{
 48			super();
 49			
 50			_subSetCount = 0;
 51			_subSets = new Vector.<SubSet>();
 52			addSubSet();
 53			
 54			_segments = new Dictionary();
 55			material = new SegmentMaterial();
 56		}
 57		
 58		/**
 59		 * Adds a new segment to the SegmentSet.
 60		 *
 61		 * @param segment  the segment to add
 62		 */
 63		public function addSegment(segment:Segment):void
 64		{
 65			segment.segmentsBase = this;
 66			
 67			_hasData = true;
 68			
 69			var subSetIndex:uint = _subSets.length - 1;
 70			var subSet:SubSet = _subSets[subSetIndex];
 71			
 72			if (subSet.vertices.length + 44 > LIMIT) {
 73				subSet = addSubSet();
 74				subSetIndex++;
 75			}
 76			
 77			segment.index = subSet.vertices.length;
 78			segment.subSetIndex = subSetIndex;
 79			
 80			updateSegment(segment);
 81			
 82			var index:uint = subSet.lineCount << 2;
 83			
 84			subSet.indices.push(index, index + 1, index + 2, index + 3, index + 2, index + 1);
 85			subSet.numVertices = subSet.vertices.length/11;
 86			subSet.numIndices = subSet.indices.length;
 87			subSet.lineCount++;
 88			
 89			var segRef:SegRef = new SegRef();
 90			segRef.index = index;
 91			segRef.subSetIndex = subSetIndex;
 92			segRef.segment = segment;
 93			
 94			_segments[_indexSegments] = segRef;
 95			
 96			_indexSegments++;
 97		}
 98		
 99		/**
100		 * Removes a segment from the SegmentSet by its index in the set.
101		 *
102		 * @param index        The index of the segment to remove
103		 * @param dispose    If the segment must be disposed as well. Default is false;
104		 *
105		 *    Removing a Segment by an index when segment is unknown
106		 *    index of the segment is relative to the order it was added to the segmentSet.
107		 *    If a segment was removed from or added to the segmentSet, a segment index may have changed.
108		 *    The index of each Segment is updated when one is added or removed.
109		 *    If 2 segments are added, segment #1 has index 0, segment #2 has index 1
110		 *    if segment #1 is removed, segment#2 will get index 0 instead of 1.
111		 */
112		public function removeSegmentByIndex(index:uint, dispose:Boolean = false):void
113		{
114			var segRef:SegRef;
115			if (index >= _indexSegments)
116				return;
117			
118			if (_segments[index])
119				segRef = _segments[index];
120			else
121				return;
122			
123			var subSet:SubSet;
124			if (!_subSets[segRef.subSetIndex])
125				return;
126			var subSetIndex:int = segRef.subSetIndex;
127			subSet = _subSets[segRef.subSetIndex];
128			
129			var segment:Segment = segRef.segment;
130			var indices:Vector.<uint> = subSet.indices;
131			
132			var ind:uint = index*6;
133			for (var i:uint = ind; i < indices.length; ++i)
134				indices[i] -= 4;
135			
136			subSet.indices.splice(index*6, 6);
137			subSet.vertices.splice(index*44, 44);
138			subSet.numVertices = subSet.vertices.length/11;
139			subSet.numIndices = indices.length;
140			subSet.vertexBufferDirty = true;
141			subSet.indexBufferDirty = true;
142			subSet.lineCount--;
143			
144			if (dispose) {
145				segment.dispose();
146				segment = null;
147				
148			} else {
149				segment.index = -1;
150				segment.segmentsBase = null;
151			}
152			
153			if (subSet.lineCount == 0) {
154				
155				if (subSetIndex == 0)
156					_hasData = false;
157				
158				else {
159					subSet.dispose();
160					_subSets[subSetIndex] = null;
161					_subSets.splice(subSetIndex, 1);
162				}
163			}
164			
165			reOrderIndices(subSetIndex, index);
166			
167			segRef = null;
168			_segments[_indexSegments] = null;
169			_indexSegments--;
170		}
171		
172		/**
173		 * Removes a segment from the SegmentSet.
174		 *
175		 * @param segment        The segment to remove
176		 * @param dispose        If the segment must be disposed as well. Default is false;
177		 */
178		public function removeSegment(segment:Segment, dispose:Boolean = false):void
179		{
180			if (segment.index == -1)
181				return;
182			removeSegmentByIndex(segment.index/44);
183		}
184		
185		/**
186		 * Empties the segmentSet from all its segments data
187		 */
188		public function removeAllSegments():void
189		{
190			var subSet:SubSet;
191			for (var i:uint = 0; i < _subSetCount; ++i) {
192				subSet = _subSets[i];
193				subSet.vertices = null;
194				subSet.indices = null;
195				if (subSet.vertexBuffer)
196					subSet.vertexBuffer.dispose();
197				if (subSet.indexBuffer)
198					subSet.indexBuffer.dispose();
199				subSet = null;
200			}
201			
202			for each (var segRef:SegRef in _segments)
203				segRef = null;
204			_segments = null;
205			
206			_subSetCount = 0;
207			_activeSubSet = null;
208			_indexSegments = 0;
209			_subSets = new Vector.<SubSet>();
210			_segments = new Dictionary();
211			
212			addSubSet();
213			
214			_hasData = false;
215		}
216		
217		/**
218		 * @returns a segment object from a given index.
219		 */
220		public function getSegment(index:uint):Segment
221		{
222			if (index > _indexSegments - 1)
223				return null;
224			
225			return _segments[index].segment;
226		}
227		
228		/**
229		 * @returns howmany segments are in the SegmentSet
230		 */
231		public function get segmentCount():uint
232		{
233			return _indexSegments;
234		}
235		
236		arcane function get subSetCount():uint
237		{
238			return _subSetCount;
239		}
240		
241		arcane function updateSegment(segment:Segment):void
242		{
243			//to do: add support for curve segment
244			var start:Vector3D = segment._start;
245			var end:Vector3D = segment._end;
246			var startX:Number = start.x, startY:Number = start.y, startZ:Number = start.z;
247			var endX:Number = end.x, endY:Number = end.y, endZ:Number = end.z;
248			var startR:Number = segment._startR, startG:Number = segment._startG, startB:Number = segment._startB;
249			var endR:Number = segment._endR, endG:Number = segment._endG, endB:Number = segment._endB;
250			var index:uint = segment.index;
251			var t:Number = segment.thickness;
252			
253			var subSet:SubSet = _subSets[segment.subSetIndex];
254			var vertices:Vector.<Number> = subSet.vertices;
255			
256			vertices[index++] = startX;
257			vertices[index++] = startY;
258			vertices[index++] = startZ;
259			vertices[index++] = endX;
260			vertices[index++] = endY;
261			vertices[index++] = endZ;
262			vertices[index++] = t;
263			vertices[index++] = startR;
264			vertices[index++] = startG;
265			vertices[index++] = startB;
266			vertices[index++] = 1;
267			
268			vertices[index++] = endX;
269			vertices[index++] = endY;
270			vertices[index++] = endZ;
271			vertices[index++] = startX;
272			vertices[index++] = startY;
273			vertices[index++] = startZ;
274			vertices[index++] = -t;
275			vertices[index++] = endR;
276			vertices[index++] = endG;
277			vertices[index++] = endB;
278			vertices[index++] = 1;
279			
280			vertices[index++] = startX;
281			vertices[index++] = startY;
282			vertices[index++] = startZ;
283			vertices[index++] = endX;
284			vertices[index++] = endY;
285			vertices[index++] = endZ;
286			vertices[index++] = -t;
287			vertices[index++] = startR;
288			vertices[index++] = startG;
289			vertices[index++] = startB;
290			vertices[index++] = 1;
291			
292			vertices[index++] = endX;
293			vertices[index++] = endY;
294			vertices[index++] = endZ;
295			vertices[index++] = startX;
296			vertices[index++] = startY;
297			vertices[index++] = startZ;
298			vertices[index++] = t;
299			vertices[index++] = endR;
300			vertices[index++] = endG;
301			vertices[index++] = endB;
302			vertices[index++] = 1;
303			
304			subSet.vertexBufferDirty = true;
305			
306			invalidateBounds();
307		}
308		
309		arcane function get hasData():Boolean
310		{
311			return _hasData;
312		}
313		
314		public function getIndexBuffer(stage3DProxy:Stage3DProxy):IndexBuffer3D
315		{
316			if (_activeSubSet.indexContext3D != stage3DProxy.context3D || _activeSubSet.indexBufferDirty) {
317				_activeSubSet.indexBuffer = stage3DProxy._context3D.createIndexBuffer(_activeSubSet.numIndices);
318				_activeSubSet.indexBuffer.uploadFromVector(_activeSubSet.indices, 0, _activeSubSet.numIndices);
319				_activeSubSet.indexBufferDirty = false;
320				_activeSubSet.indexContext3D = stage3DProxy.context3D;
321			}
322			
323			return _activeSubSet.indexBuffer;
324		}
325		
326		public function activateVertexBuffer(index:int, stage3DProxy:Stage3DProxy):void
327		{
328			var subSet:SubSet = _subSets[index];
329			
330			_activeSubSet = subSet;
331			_numIndices = subSet.numIndices;
332			
333			if (subSet.vertexContext3D != stage3DProxy.context3D || subSet.vertexBufferDirty) {
334				subSet.vertexBuffer = stage3DProxy._context3D.createVertexBuffer(subSet.numVertices, 11);
335				subSet.vertexBuffer.uploadFromVector(subSet.vertices, 0, subSet.numVertices);
336				vertexBuffer = subSet.vertexBuffer;
337				subSet.vertexBufferDirty = false;
338				subSet.vertexContext3D = stage3DProxy.context3D;
339			}
340			
341			var vertexBuffer:VertexBuffer3D = subSet.vertexBuffer;
342			var context3d:Context3D = stage3DProxy._context3D;
343			
344			context3d.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
345			context3d.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
346			context3d.setVertexBufferAt(2, vertexBuffer, 6, Context3DVertexBufferFormat.FLOAT_1);
347			context3d.setVertexBufferAt(3, vertexBuffer, 7, Context3DVertexBufferFormat.FLOAT_4);
348		}
349		
350		public function activateUVBuffer(index:int, stage3DProxy:Stage3DProxy):void
351		{
352		}
353		
354		public function activateVertexNormalBuffer(index:int, stage3DProxy:Stage3DProxy):void
355		{
356		}
357		
358		public function activateVertexTangentBuffer(index:int, stage3DProxy:Stage3DProxy):void
359		{
360		}
361		
362		public function activateSecondaryUVBuffer(index:int, stage3DProxy:Stage3DProxy):void
363		{
364		}
365		
366		private function reOrderIndices(subSetIndex:uint, index:int):void
367		{
368			var segRef:SegRef;
369			
370			for (var i:uint = index; i < _indexSegments - 1; ++i) {
371				segRef = _segments[i + 1];
372				segRef.index = i;
373				if (segRef.subSetIndex == subSetIndex)
374					segRef.segment.index -= 44;
375				_segments[i] = segRef;
376			}
377		
378		}
379		
380		private function addSubSet():SubSet
381		{
382			var subSet:SubSet = new SubSet();
383			_subSets.push(subSet);
384			
385			subSet.vertices = new Vector.<Number>();
386			subSet.numVertices = 0;
387			subSet.indices = new Vector.<uint>();
388			subSet.numIndices = 0;
389			subSet.vertexBufferDirty = true;
390			subSet.indexBufferDirty = true;
391			subSet.lineCount = 0;
392			
393			_subSetCount++;
394			
395			return subSet;
396		}
397		
398		/**
399		 * @inheritDoc
400		 */
401		override public function dispose():void
402		{
403			super.dispose();
404			removeAllSegments();
405			_segments = null
406			_material = null;
407			var subSet:SubSet = _subSets[0];
408			subSet.vertices = null;
409			subSet.indices = null;
410			_subSets = null;
411		}
412		
413		/**
414		 * @inheritDoc
415		 */
416		override public function get mouseEnabled():Boolean
417		{
418			return false;
419		}
420		
421		/**
422		 * @inheritDoc
423		 */
424		override protected function getDefaultBoundingVolume():BoundingVolumeBase
425		{
426			return new BoundingSphere();
427		}
428		
429		/**
430		 * @inheritDoc
431		 */
432		override protected function updateBounds():void
433		{
434			var subSet:SubSet;
435			var len:uint;
436			var v:Number;
437			var index:uint;
438			
439			var minX:Number = Infinity;
440			var minY:Number = Infinity;
441			var minZ:Number = Infinity;
442			var maxX:Number = -Infinity;
443			var maxY:Number = -Infinity;
444			var maxZ:Number = -Infinity;
445			var vertices:Vector.<Number>;
446			
447			for (var i:uint = 0; i < _subSetCount; ++i) {
448				subSet = _subSets[i];
449				index = 0;
450				vertices = subSet.vertices;
451				len = vertices.length;
452				
453				if (len == 0)
454					continue;
455				
456				while (index < len) {
457					
458					v = vertices[index++];
459					if (v < minX)
460						minX = v;
461					else if (v > maxX)
462						maxX = v;
463					
464					v = vertices[index++];
465					if (v < minY)
466						minY = v;
467					else if (v > maxY)
468						maxY = v;
469					
470					v = vertices[index++];
471					if (v < minZ)
472						minZ = v;
473					else if (v > maxZ)
474						maxZ = v;
475					
476					index += 8;
477				}
478			}
479			
480			if (minX != Infinity)
481				_bounds.fromExtremes(minX, minY, minZ, maxX, maxY, maxZ);
482			
483			else {
484				var min:Number = .5;
485				_bounds.fromExtremes(-min, -min, -min, min, min, min);
486			}
487			
488			_boundsInvalid = false;
489		}
490		
491		/**
492		 * @inheritDoc
493		 */
494		override protected function createEntityPartitionNode():EntityNode
495		{
496			return new RenderableNode(this);
497		}
498		
499		public function get numTriangles():uint
500		{
501			return _numIndices/3;
502		}
503		
504		public function get sourceEntity():Entity
505		{
506			return this;
507		}
508		
509		public function get castsShadows():Boolean
510		{
511			return false;
512		}
513		
514		public function get material():MaterialBase
515		{
516			return _material;
517		}
518		
519		public function get animator():IAnimator
520		{
521			return _animator;
522		}
523		
524		public function set material(value:MaterialBase):void
525		{
526			if (value == _material)
527				return;
528			if (_material)
529				_material.removeOwner(this);
530			_material = value;
531			if (_material)
532				_material.addOwner(this);
533		}
534		
535		public function get uvTransform():Matrix
536		{
537			return null;
538		}
539		
540		public function get vertexData():Vector.<Number>
541		{
542			return null;
543		}
544		
545		public function get indexData():Vector.<uint>
546		{
547			return null;
548		}
549		
550		public function get UVData():Vector.<Number>
551		{
552			return null;
553		}
554		
555		public function get numVertices():uint
556		{
557			return null;
558		}
559		
560		public function get vertexStride():uint
561		{
562			return 11;
563		}
564		
565		public function get vertexNormalData():Vector.<Number>
566		{
567			return null;
568		}
569		
570		public function get vertexTangentData():Vector.<Number>
571		{
572			return null;
573		}
574		
575		public function get vertexOffset():int
576		{
577			return 0;
578		}
579		
580		public function get vertexNormalOffset():int
581		{
582			return 0;
583		}
584		
585		public function get vertexTangentOffset():int
586		{
587			return 0;
588		}
589		
590		override public function get assetType():String
591		{
592			return AssetType.SEGMENT_SET;
593		}
594		
595		public function getRenderSceneTransform(camera:Camera3D):Matrix3D
596		{
597			return _sceneTransform;
598		}
599	}
600}
601
602final class SegRef
603{
604	import away3d.primitives.data.Segment;
605	
606	public var index:uint;
607	public var subSetIndex:uint;
608	public var segment:Segment;
609}
610
611final class SubSet
612{
613	
614	import flash.display3D.Context3D;
615	import flash.display3D.Context3DVertexBufferFormat;
616	import flash.display3D.IndexBuffer3D;
617	import flash.display3D.VertexBuffer3D;
618	
619	public var vertices:Vector.<Number>;
620	public var numVertices:uint;
621	
622	public var indices:Vector.<uint>;
623	public var numIndices:uint;
624	
625	public var vertexBufferDirty:Boolean;
626	public var indexBufferDirty:Boolean;
627	
628	public var vertexContext3D:Context3D;
629	public var indexContext3D:Context3D;
630	
631	public var vertexBuffer:VertexBuffer3D;
632	public var indexBuffer:IndexBuffer3D;
633	public var lineCount:uint;
634	
635	public function dispose():void
636	{
637		vertices = null;
638		if (vertexBuffer)
639			vertexBuffer.dispose();
640		if (indexBuffer)
641			indexBuffer.dispose();
642	}
643}
644