/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

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