/src/away3d/entities/SegmentSet.as
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