PageRenderTime 95ms CodeModel.GetById 14ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 1ms

/src/away3d/extrusions/LinearExtrude.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 1081 lines | 819 code | 190 blank | 72 comment | 176 complexity | fcd7ce76979ba7ef26553597aaed61b1 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.materials.utils.MultipleMaterials;
  12	import away3d.tools.helpers.MeshHelper;
  13	
  14	import flash.geom.Point;
  15	import flash.geom.Vector3D;
  16	
  17	public class LinearExtrude extends Mesh
  18	{
  19		public static const X_AXIS:String = "x";
  20		public static const Y_AXIS:String = "y";
  21		public static const Z_AXIS:String = "z";
  22		
  23		private const LIMIT:uint = 196605;
  24		private const EPS:Number = .0001;
  25		
  26		private var _varr:Vector.<Vertex>;
  27		private var _varr2:Vector.<Vertex>;
  28		private var _uvarr:Vector.<UV>;
  29		private var _subdivision:uint;
  30		private var _coverAll:Boolean;
  31		private var _flip:Boolean;
  32		private var _closePath:Boolean;
  33		private var _axis:String;
  34		private var _offset:Number;
  35		private var _materials:MultipleMaterials;
  36		private var _activeMaterial:MaterialBase;
  37		private var _centerMesh:Boolean;
  38		private var _thickness:Number;
  39		private var _thicknessSubdivision:uint;
  40		private var _ignoreSides:String;
  41		
  42		private var _geomDirty:Boolean = true;
  43		private var _subGeometry:SubGeometry;
  44		private var _MaterialsSubGeometries:Vector.<SubGeometryList>;
  45		private var _uva:UV;
  46		private var _uvb:UV;
  47		private var _uvc:UV;
  48		private var _uvd:UV;
  49		// TODO: not used
  50		// private var _va:Vertex;
  51		// private var _vb:Vertex;
  52		// private var _vc:Vertex;
  53		// private var _vd:Vertex;
  54		private var _maxIndProfile:uint;
  55		private var _uvs:Vector.<Number>;
  56		private var _vertices:Vector.<Number>;
  57		private var _indices:Vector.<uint>;
  58		private var _aVectors:Vector.<Vector3D>;
  59		private var _baseMax:Number;
  60		private var _baseMin:Number;
  61		
  62		/**
  63		 *  Class LinearExtrusion generates walls like meshes with or without thickness from a series of Vector3D's
  64		 *
  65		 *@param        material                        [optional] MaterialBase. The LatheExtrude (Mesh) material. Optional in constructor, material must be set before LatheExtrude object is render.
  66		 * @param        vectors                        [optional] Vector.&lt;Vector3D&gt;. A series of Vector3D's representing the profile information to be repeated/rotated around a given axis.
  67		 * @param        axis                            [optional] String. The axis to elevate along: X_AXIS, Y_AXIS or Z_AXIS. Default is LinearExtrusion.Y_AXIS.
  68		 * @param        offset                            [optional] Number. The elevation offset along the defined axis.
  69		 * @param        subdivision                    [optional] uint. The subdivision of the geometry between 2 vector3D. Default is 32.
  70		 * @param        coverAll                        [optional] Boolean. The way the uv mapping is spreaded across the shape. True covers an entire side of the geometry while false covers per segments. Default is false.
  71		 * @param        thickness                    [optional] Number. If the shape must simulate a thickness. Default is 0.
  72		 * @param        thicknessSubdivision    [optional] uint. If thickness is higher than 0. Defines the subdivision of the thickness (top, left, right, bottom). Default is 3;
  73		 * @param        materials                    [optional] MultipleMaterials. Allows multiple material support when thickness is set higher to 1. Default is null.
  74		 * properties as MaterialBase are: bottom, top, left, right, front and back.
  75		 * @param        centerMesh                [optional] Boolean. If the geometry needs to be recentered in its own object space. If the position after generation is set to 0,0,0, the object would be centered in worldspace. Default is false.
  76		 * @param        closePath                    [optional] Boolean. Defines if the last entered vector needs to be linked with the first one to form a closed shape. Default is false.
  77		 * @param        ignoreSides                [optional] String. To prevent the generation of sides if thickness is set higher than 0. To avoid the bottom ignoreSides = "bottom", avoiding both top and bottom: ignoreSides = "bottom, top". Strings options: bottom, top, left, right, front and back. Default is "".
  78		 * @param        flip                            [optional] Boolean. If the faces must be reversed depending on Vector3D's orientation. Default is false.
  79		 */
  80		
  81		public function LinearExtrude(material:MaterialBase = null, vectors:Vector.<Vector3D> = null, axis:String = LinearExtrude.Y_AXIS, offset:Number = 10, subdivision:uint = 3, coverAll:Boolean = false, thickness:Number = 0, thicknessSubdivision:uint = 3, materials:MultipleMaterials = null, centerMesh:Boolean = false, closePath:Boolean = false, ignoreSides:String = "", flip:Boolean = false)
  82		{
  83			var geom:Geometry = new Geometry();
  84			_subGeometry = new SubGeometry();
  85			
  86			if (!material && materials && materials.front)
  87				material = materials.front;
  88			super(geom, material);
  89			
  90			_aVectors = vectors;
  91			_axis = axis;
  92			_offset = offset;
  93			_coverAll = coverAll;
  94			_flip = flip;
  95			_centerMesh = centerMesh;
  96			_thickness = Math.abs(thickness);
  97			this.subdivision = subdivision;
  98			this.thicknessSubdivision = thicknessSubdivision;
  99			_ignoreSides = ignoreSides;
 100			_closePath = closePath;
 101			
 102			if (materials)
 103				this.materials = materials;
 104			if (_closePath && ignoreSides != "")
 105				this.ignoreSides = ignoreSides;
 106		}
 107		
 108		private function buildExtrude():void
 109		{
 110			
 111			if (!_aVectors.length || _aVectors.length < 2)
 112				throw new Error("LinearExtrusion error: at least 2 vector3D required!");
 113			if (_closePath)
 114				_aVectors.push(new Vector3D(_aVectors[0].x, _aVectors[0].y, _aVectors[0].z));
 115			
 116			_maxIndProfile = _aVectors.length*9;
 117			_MaterialsSubGeometries = null;
 118			_geomDirty = false;
 119			initHolders();
 120			
 121			generate();
 122			
 123			if (_vertices.length > 0) {
 124				_subGeometry.updateVertexData(_vertices);
 125				_subGeometry.updateIndexData(_indices);
 126				_subGeometry.updateUVData(_uvs);
 127				this.geometry.addSubGeometry(_subGeometry);
 128			}
 129			
 130			if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
 131				var sglist:SubGeometryList;
 132				var sg:SubGeometry;
 133				for (var i:uint = 1; i < _MaterialsSubGeometries.length; ++i) {
 134					sglist = _MaterialsSubGeometries[i];
 135					sg = sglist.subGeometry;
 136					if (sg && sglist.vertices.length > 0) {
 137						this.geometry.addSubGeometry(sg);
 138						this.subMeshes[this.subMeshes.length - 1].material = sglist.material;
 139						sg.updateVertexData(sglist.vertices);
 140						sg.updateIndexData(sglist.indices);
 141						sg.updateUVData(sglist.uvs);
 142					}
 143				}
 144			}
 145			
 146			if (_centerMesh)
 147				MeshHelper.recenter(this);
 148			
 149			_varr = _varr2 = null;
 150			_uvarr = null;
 151		}
 152		
 153		/**
 154		 * Defines the axis used for the extrusion. Defaults to "y".
 155		 */
 156		public function get axis():String
 157		{
 158			return _axis;
 159		}
 160		
 161		public function set axis(val:String):void
 162		{
 163			if (_axis == val)
 164				return;
 165			
 166			_axis = val;
 167			invalidateGeometry();
 168		}
 169		
 170		/**
 171		 * An optional MultipleMaterials object that defines left, right, front, back, top and bottom materials to be set on the resulting lathe extrusion.
 172		 */
 173		public function get materials():MultipleMaterials
 174		{
 175			return _materials;
 176		}
 177		
 178		public function set materials(val:MultipleMaterials):void
 179		{
 180			_materials = val;
 181			
 182			if (_materials.front && this.material != _materials.front)
 183				this.material = _materials.front;
 184			
 185			invalidateGeometry();
 186		}
 187		
 188		/**
 189		 * Defines the subdivisions created in the mesh for the total number of revolutions. Defaults to 2, minimum 2.
 190		 */
 191		public function get subdivision():uint
 192		{
 193			return _subdivision;
 194		}
 195		
 196		public function set subdivision(val:uint):void
 197		{
 198			val = (val < 3)? 3 : val;
 199			if (_subdivision == val)
 200				return;
 201			_subdivision = val;
 202			invalidateGeometry();
 203		}
 204		
 205		/**
 206		 * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to true.
 207		 */
 208		public function get coverAll():Boolean
 209		{
 210			return _coverAll;
 211		}
 212		
 213		public function set coverAll(val:Boolean):void
 214		{
 215			if (_coverAll == val)
 216				return;
 217			
 218			_coverAll = val;
 219			invalidateGeometry();
 220		}
 221		
 222		/**
 223		 * Defines if the generated faces should be inversed. Default false.
 224		 */
 225		public function get flip():Boolean
 226		{
 227			return _flip;
 228		}
 229		
 230		public function set flip(val:Boolean):void
 231		{
 232			if (_flip == val)
 233				return;
 234			
 235			_flip = val;
 236			invalidateGeometry();
 237		}
 238		
 239		/**
 240		 * Defines whether the mesh is recentered of not after generation
 241		 */
 242		public function get centerMesh():Boolean
 243		{
 244			return _centerMesh;
 245		}
 246		
 247		public function set centerMesh(val:Boolean):void
 248		{
 249			if (_centerMesh == val)
 250				return;
 251			
 252			_centerMesh = val;
 253			
 254			if (_centerMesh && _subGeometry.vertexData.length > 0)
 255				MeshHelper.recenter(this);
 256			else
 257				invalidateGeometry();
 258		}
 259		
 260		/**
 261		 * Defines the _thickness of the resulting lathed geometry. Defaults to 0 (single face).
 262		 */
 263		public function get thickness():Number
 264		{
 265			return _thickness;
 266		}
 267		
 268		public function set thickness(val:Number):void
 269		{
 270			val = Math.abs(val);
 271			if (_thickness == val)
 272				return;
 273			
 274			_thickness = val;
 275			invalidateGeometry();
 276		}
 277		
 278		/**
 279		 * Defines the subdivision for the top, bottom, right and left if thickness is set higher to 0. Defaults to 1.
 280		 */
 281		public function get thicknessSubdivision():uint
 282		{
 283			return _thicknessSubdivision;
 284		}
 285		
 286		public function set thicknessSubdivision(val:uint):void
 287		{
 288			val = (val < 3)? 3 : val;
 289			if (_thicknessSubdivision == val)
 290				return;
 291			
 292			_thicknessSubdivision = val;
 293			invalidateGeometry();
 294		}
 295		
 296		/**
 297		 * Defines if the top, bottom, left, right, front or back of the the extrusion is left open.
 298		 */
 299		public function get ignoreSides():String
 300		{
 301			return _ignoreSides;
 302		}
 303		
 304		public function set ignoreSides(val:String):void
 305		{
 306			_ignoreSides = val;
 307			if (_closePath) {
 308				if (_ignoreSides.indexOf("left") == -1)
 309					_ignoreSides += "left,";
 310				if (_ignoreSides.indexOf("right") == -1)
 311					_ignoreSides += "right";
 312			}
 313			invalidateGeometry();
 314		}
 315		
 316		/**
 317		 * @inheritDoc
 318		 */
 319		override public function get bounds():BoundingVolumeBase
 320		{
 321			if (_geomDirty)
 322				buildExtrude();
 323			
 324			return super.bounds;
 325		}
 326		
 327		/**
 328		 * @inheritDoc
 329		 */
 330		override public function get geometry():Geometry
 331		{
 332			if (_geomDirty)
 333				buildExtrude();
 334			
 335			return super.geometry;
 336		}
 337		
 338		/**
 339		 * @inheritDoc
 340		 */
 341		override public function get subMeshes():Vector.<SubMesh>
 342		{
 343			if (_geomDirty)
 344				buildExtrude();
 345			
 346			return super.subMeshes;
 347		}
 348		
 349		private function addFace(v0:Vertex, v1:Vertex, v2:Vertex, uv0:UV, uv1:UV, uv2:UV, mat:MaterialBase, invertU:Boolean = false):void
 350		{
 351			var subGeom:SubGeometry;
 352			var uvs:Vector.<Number>;
 353			var vertices:Vector.<Number>;
 354			// TODO: not used
 355			// var normals:Vector.<Number>;
 356			var indices:Vector.<uint>;
 357			var sglist:SubGeometryList;
 358			
 359			if (_activeMaterial != mat && _materials) {
 360				sglist = getSubGeometryListFromMaterial(mat);
 361				_subGeometry = subGeom = sglist.subGeometry;
 362				_uvs = uvs = sglist.uvs;
 363				_vertices = vertices = sglist.vertices;
 364				_indices = indices = sglist.indices;
 365			} else {
 366				
 367				subGeom = _subGeometry;
 368				uvs = _uvs;
 369				vertices = _vertices;
 370				indices = _indices;
 371			}
 372			
 373			if (vertices.length + 9 > LIMIT) {
 374				subGeom.updateVertexData(vertices);
 375				subGeom.updateIndexData(indices);
 376				subGeom.updateUVData(uvs);
 377				this.geometry.addSubGeometry(subGeom);
 378				this.subMeshes[this.subMeshes.length - 1].material = mat;
 379				
 380				subGeom = new SubGeometry();
 381				subGeom.autoDeriveVertexTangents = true;
 382				subGeom.autoDeriveVertexNormals = true;
 383				
 384				if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 1) {
 385					sglist = getSubGeometryListFromMaterial(mat);
 386					sglist.subGeometry = _subGeometry = subGeom;
 387					sglist.uvs = _uvs = uvs = new Vector.<Number>();
 388					sglist.vertices = _vertices = vertices = new Vector.<Number>();
 389					sglist.indices = _indices = indices = new Vector.<uint>();
 390					
 391				} else {
 392					
 393					_subGeometry = subGeom;
 394					uvs = _uvs = new Vector.<Number>();
 395					vertices = _vertices = new Vector.<Number>();
 396					indices = _indices = new Vector.<uint>();
 397				}
 398			}
 399			
 400			var ind:uint = vertices.length/3;
 401			
 402			if (invertU)
 403				uvs.push(1 - uv0.u, uv0.v, 1 - uv1.u, uv1.v, 1 - uv2.u, uv2.v);
 404			else
 405				uvs.push(uv0.u, uv0.v, uv1.u, uv1.v, uv2.u, uv2.v);
 406			vertices.push(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
 407			
 408			indices.push(ind, ind + 1, ind + 2);
 409		}
 410		
 411		private function generate():void
 412		{
 413			var i:uint;
 414			var j:uint;
 415			var increase:Number = _offset/_subdivision;
 416			
 417			var baseMaxX:Number = _aVectors[0].x;
 418			var baseMinX:Number = _aVectors[0].x;
 419			var baseMaxY:Number = _aVectors[0].y;
 420			var baseMinY:Number = _aVectors[0].y;
 421			var baseMaxZ:Number = _aVectors[0].z;
 422			var baseMinZ:Number = _aVectors[0].z;
 423			
 424			for (i = 1; i < _aVectors.length; i++) {
 425				baseMaxX = Math.max(_aVectors[i].x, baseMaxX);
 426				baseMinX = Math.min(_aVectors[i].x, baseMinX);
 427				baseMaxY = Math.max(_aVectors[i].y, baseMaxY);
 428				baseMinY = Math.min(_aVectors[i].y, baseMinY);
 429				baseMaxZ = Math.max(_aVectors[i].z, baseMaxZ);
 430				baseMinZ = Math.min(_aVectors[i].z, baseMinZ);
 431			}
 432			
 433			var offset:Number = 0;
 434			
 435			switch (_axis) {
 436				case X_AXIS:
 437					_baseMax = Math.abs(baseMaxX) - Math.abs(baseMinX);
 438					if (baseMinZ > 0 && baseMaxZ > 0) {
 439						_baseMin = baseMaxZ - baseMinZ;
 440						offset = -baseMinZ;
 441					} else if (baseMinZ < 0 && baseMaxZ < 0) {
 442						_baseMin = Math.abs(baseMinZ - baseMaxZ);
 443						offset = -baseMinZ;
 444					} else {
 445						_baseMin = Math.abs(baseMaxZ) + Math.abs(baseMinZ);
 446						offset = Math.abs(baseMinZ) + ((baseMaxZ < 0)? -baseMaxZ : 0);
 447					}
 448					break;
 449				
 450				case Y_AXIS:
 451					_baseMax = Math.abs(baseMaxY) - Math.abs(baseMinY);
 452					if (baseMinX > 0 && baseMaxX > 0) {
 453						_baseMin = baseMaxX - baseMinX;
 454						offset = -baseMinX;
 455					} else if (baseMinX < 0 && baseMaxX < 0) {
 456						_baseMin = Math.abs(baseMinX - baseMaxX);
 457						offset = -baseMinX;
 458					} else {
 459						_baseMin = Math.abs(baseMaxX) + Math.abs(baseMinX);
 460						offset = Math.abs(baseMinX) + ((baseMaxX < 0)? -baseMaxX : 0);
 461					}
 462					break;
 463				
 464				case Z_AXIS:
 465					_baseMax = Math.abs(baseMaxZ) - Math.abs(baseMinZ);
 466					if (baseMinY > 0 && baseMaxY > 0) {
 467						_baseMin = baseMaxY - baseMinY;
 468						offset = -baseMinY;
 469					} else if (baseMinY < 0 && baseMaxY < 0) {
 470						_baseMin = Math.abs(baseMinY - baseMaxY);
 471						offset = -baseMinY;
 472					} else {
 473						_baseMin = Math.abs(baseMaxY) + Math.abs(baseMinY);
 474						offset = Math.abs(baseMinY) + ((baseMaxY < 0)? -baseMaxY : 0);
 475					}
 476					break;
 477			}
 478			
 479			var aLines:Array;
 480			var prop1:String;
 481			var prop2:String;
 482			var prop3:String;
 483			var vector:Vertex = new Vertex();
 484			if (_thickness != 0) {
 485				var aListsides:Array = ["top", "bottom", "right", "left", "front", "back"];
 486				var renderSide:RenderSide = new RenderSide();
 487				
 488				for (i = 0; i < aListsides.length; ++i)
 489					renderSide[aListsides[i]] = (_ignoreSides.indexOf(aListsides[i]) == -1);
 490				
 491				switch (_axis) {
 492					case X_AXIS:
 493						prop1 = Z_AXIS;
 494						prop2 = Y_AXIS;
 495						prop3 = X_AXIS;
 496						break;
 497					
 498					case Y_AXIS:
 499						prop1 = X_AXIS;
 500						prop2 = Z_AXIS;
 501						prop3 = Y_AXIS;
 502						break;
 503					
 504					case Z_AXIS:
 505						prop1 = Y_AXIS;
 506						prop2 = X_AXIS;
 507						prop3 = Z_AXIS;
 508				}
 509				
 510				aLines = buildThicknessPoints(prop1, prop2);
 511				
 512				var points:FourPoints;
 513				
 514				var vector2:Vertex = new Vertex();
 515				var vector3:Vertex = new Vertex();
 516				var vector4:Vertex = new Vertex();
 517				
 518				for (i = 0; i < aLines.length; i++) {
 519					
 520					points = FourPoints(aLines[i]);
 521					
 522					if (i == 0) {
 523						vector[prop1] = points.pt2.x;
 524						vector[prop2] = points.pt2.y;
 525						vector[prop3] = _aVectors[0][prop3];
 526						_varr.push(new Vertex(vector.x, vector.y, vector.z));
 527						
 528						vector2[prop1] = points.pt1.x;
 529						vector2[prop2] = points.pt1.y;
 530						vector2[prop3] = _aVectors[0][prop3];
 531						_varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
 532						
 533						elevate(vector, vector2, increase);
 534						
 535						if (aLines.length == 1) {
 536							
 537							vector3[prop1] = points.pt4.x;
 538							vector3[prop2] = points.pt4.y;
 539							vector3[prop3] = _aVectors[0][prop3];
 540							_varr.push(new Vertex(vector3.x, vector3.y, vector3.z));
 541							
 542							vector4[prop1] = points.pt3.x;
 543							vector4[prop2] = points.pt3.y;
 544							vector4[prop3] = _aVectors[0][prop3];
 545							_varr2.push(new Vertex(vector4.x, vector4.y, vector4.z));
 546							
 547							elevate(vector3, vector4, increase);
 548						}
 549						
 550					} else if (i == aLines.length - 1) {
 551						
 552						vector[prop1] = points.pt2.x;
 553						vector[prop2] = points.pt2.y;
 554						vector[prop3] = _aVectors[i][prop3];
 555						_varr.push(new Vertex(vector.x, vector.y, vector.z));
 556						
 557						vector2[prop1] = points.pt1.x;
 558						vector2[prop2] = points.pt1.y;
 559						vector2[prop3] = _aVectors[i][prop3];
 560						_varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
 561						
 562						elevate(vector, vector2, increase);
 563						
 564						vector3[prop1] = points.pt4.x;
 565						vector3[prop2] = points.pt4.y;
 566						vector3[prop3] = _aVectors[i][prop3];
 567						_varr.push(new Vertex(vector3.x, vector3.y, vector3.z));
 568						
 569						vector4[prop1] = points.pt3.x;
 570						vector4[prop2] = points.pt3.y;
 571						vector4[prop3] = _aVectors[i][prop3];
 572						_varr2.push(new Vertex(vector4.x, vector4.y, vector4.z));
 573						
 574						elevate(vector3, vector4, increase);
 575						
 576					} else {
 577						
 578						vector[prop1] = points.pt2.x;
 579						vector[prop2] = points.pt2.y;
 580						vector[prop3] = _aVectors[i][prop3];
 581						_varr.push(new Vertex(vector.x, vector.y, vector.z));
 582						
 583						vector2[prop1] = points.pt1.x;
 584						vector2[prop2] = points.pt1.y;
 585						vector2[prop3] = _aVectors[i][prop3];
 586						_varr2.push(new Vertex(vector2.x, vector2.y, vector2.z));
 587						
 588						elevate(vector, vector2, increase);
 589					}
 590				}
 591				
 592			} else {
 593				
 594				for (i = 0; i < _aVectors.length; i++) {
 595					vector.x = _aVectors[i].x;
 596					vector.y = _aVectors[i].y;
 597					vector.z = _aVectors[i].z;
 598					_varr.push(new Vertex(vector.x, vector.y, vector.z));
 599					
 600					for (j = 0; j < _subdivision; j++) {
 601						vector[_axis] += increase;
 602						_varr.push(new Vertex(vector.x, vector.y, vector.z));
 603					}
 604				}
 605			}
 606			
 607			var index:uint = 0;
 608			var mat:MaterialBase;
 609			
 610			if (_thickness > 0) {
 611				var v1a:Vertex;
 612				var v1b:Vertex;
 613				var v1c:Vertex;
 614				var v2a:Vertex;
 615				var v2b:Vertex;
 616				var v2c:Vertex;
 617				var v3a:Vertex;
 618				var v3b:Vertex;
 619				var v3c:Vertex;
 620				var v4b:Vertex;
 621				var v4c:Vertex;
 622			}
 623			
 624			var step:Number = 1/(_aVectors.length - 1);
 625			
 626			var vindex:uint;
 627			
 628			for (i = 0; i < _aVectors.length - 1; ++i) {
 629				
 630				if (_coverAll) {
 631					_uva.u = _uvb.u = step*i;
 632					_uvc.u = _uvd.u = _uvb.u + step;
 633				} else {
 634					_uva.u = 0;
 635					_uvb.u = 0;
 636					_uvc.u = 1;
 637					_uvd.u = 1;
 638				}
 639				
 640				for (j = 0; j < _subdivision; ++j) {
 641					
 642					_uva.v = _uvd.v = 1 - (j/_subdivision);
 643					_uvb.v = _uvc.v = 1 - (j + 1)/_subdivision;
 644					
 645					vindex = index + j;
 646					if (_thickness == 0) {
 647						
 648						if (_flip) {
 649							addFace(_varr[ vindex + 1], _varr[vindex], _varr[vindex + _subdivision + 2], _uvb, _uva, _uvc, this.material);
 650							addFace(_varr[ vindex + _subdivision + 2], _varr[vindex], _varr[vindex + _subdivision + 1], _uvc, _uva, _uvd, this.material);
 651						} else {
 652							addFace(_varr[vindex], _varr[vindex + 1], _varr[vindex + _subdivision + 2], _uva, _uvb, _uvc, this.material);
 653							addFace(_varr[vindex], _varr[vindex + _subdivision + 2], _varr[vindex + _subdivision + 1], _uva, _uvc, _uvd, this.material);
 654						}
 655						
 656					} else {
 657						//half side 1
 658						v1a = _varr[vindex];
 659						v1b = _varr[vindex + 1];
 660						v1c = _varr[vindex + _subdivision + 2];
 661						v2a = _varr[vindex];
 662						v2b = _varr[vindex + _subdivision + 2];
 663						v2c = _varr[vindex + _subdivision + 1];
 664						
 665						//half side 2
 666						v3a = _varr2[vindex];
 667						v3b = _varr2[vindex + 1];
 668						v3c = _varr2[vindex + _subdivision + 2];
 669						v4b = _varr2[vindex + _subdivision + 2];
 670						v4c = _varr2[vindex + _subdivision + 1];
 671						
 672						//right
 673						if (renderSide.right) {
 674							mat = (materials && materials.right)? materials.right : this.material;
 675							if (_flip) {
 676								addFace(v1a, v1b, v1c, _uva, _uvb, _uvc, mat);
 677								addFace(v2a, v2b, v2c, _uva, _uvc, _uvd, mat);
 678							} else {
 679								addFace(v1b, v1a, v1c, _uvb, _uva, _uvc, mat);
 680								addFace(v2b, v2a, v2c, _uvc, _uva, _uvd, mat);
 681							}
 682						}
 683						
 684						//left
 685						if (renderSide.left) {
 686							mat = (materials && materials.left)? materials.left : this.material;
 687							if (_flip) {
 688								addFace(v4c, v3b, v3a, _uvd, _uvb, _uva, mat, true);
 689								addFace(v4c, v4b, v3b, _uvd, _uvc, _uvb, mat, true);
 690							} else {
 691								addFace(v3b, v4c, v3a, _uvb, _uvd, _uva, mat, true);
 692								addFace(v4b, v4c, v3b, _uvc, _uvd, _uvb, mat, true);
 693							}
 694						}
 695						
 696						//back
 697						if (i == 0 && renderSide.back) {
 698							mat = (materials && materials.back)? materials.back : this.material;
 699							if (_flip) {
 700								addFace(v3a, v3b, v1b, _uva, _uvb, _uvc, mat);
 701								addFace(v3a, v1b, v1a, _uva, _uvc, _uvd, mat);
 702							} else {
 703								addFace(v3b, v3a, v1b, _uvb, _uva, _uvc, mat);
 704								addFace(v1b, v3a, v1a, _uvc, _uva, _uvd, mat);
 705							}
 706						}
 707						
 708						//bottom
 709						if (j == 0 && renderSide.bottom) {
 710							mat = (materials && materials.bottom)? materials.bottom : this.material;
 711							addThicknessSubdivision([v4c, v3a], [v2c, v1a], _uvd.u, _uvb.u, mat);
 712						}
 713						
 714						//top
 715						if (j == _subdivision - 1 && renderSide.top) {
 716							mat = (materials && materials.top)? materials.top : this.material;
 717							addThicknessSubdivision([v3b, v3c], [v1b, v1c], _uva.u, _uvc.u, mat);
 718						}
 719						
 720						//front 
 721						if (i == _aVectors.length - 2 && renderSide.front) {
 722							mat = (materials && materials.front)? materials.front : this.material;
 723							if (_flip) {
 724								addFace(v2c, v2b, v3c, _uva, _uvb, _uvc, mat);
 725								addFace(v2c, v3c, v4c, _uva, _uvc, _uvd, mat);
 726							} else {
 727								addFace(v2b, v2c, v3c, _uvb, _uva, _uvc, mat);
 728								addFace(v3c, v2c, v4c, _uvc, _uva, _uvd, mat);
 729							}
 730						}
 731						
 732					}
 733				}
 734				
 735				index += _subdivision + 1;
 736			}
 737		}
 738		
 739		private function addThicknessSubdivision(points1:Array, points2:Array, u1:Number, u2:Number, mat:MaterialBase):void
 740		{
 741			var i:uint;
 742			var j:uint;
 743			
 744			var stepx:Number;
 745			var stepy:Number;
 746			var stepz:Number;
 747			
 748			var va:Vertex;
 749			var vb:Vertex;
 750			var vc:Vertex;
 751			var vd:Vertex;
 752			
 753			var index:uint = 0;
 754			var v1:Number = 0;
 755			var v2:Number = 0;
 756			var tmp:Array = [];
 757			
 758			for (i = 0; i < points1.length; ++i) {
 759				stepx = (points2[i].x - points1[i].x)/_thicknessSubdivision;
 760				stepy = (points2[i].y - points1[i].y)/_thicknessSubdivision;
 761				stepz = (points2[i].z - points1[i].z)/_thicknessSubdivision;
 762				
 763				for (j = 0; j < _thicknessSubdivision + 1; ++j)
 764					tmp.push(new Vertex(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j)));
 765				
 766			}
 767			
 768			for (i = 0; i < points1.length - 1; ++i) {
 769				
 770				for (j = 0; j < _thicknessSubdivision; ++j) {
 771					
 772					v1 = j/_thicknessSubdivision;
 773					v2 = (j + 1)/_thicknessSubdivision;
 774					
 775					_uva.u = u1;
 776					_uva.v = v1;
 777					_uvb.u = u1;
 778					_uvb.v = v2;
 779					_uvc.u = u2;
 780					_uvc.v = v2;
 781					_uvd.u = u2;
 782					_uvd.v = v1;
 783					
 784					va = tmp[index + j];
 785					vb = tmp[(index + j) + 1];
 786					vc = tmp[((index + j) + (_thicknessSubdivision + 2))];
 787					vd = tmp[((index + j) + (_thicknessSubdivision + 1))];
 788					
 789					if (!_flip) {
 790						addFace(va, vb, vc, _uva, _uvb, _uvc, mat);
 791						addFace(va, vc, vd, _uva, _uvc, _uvd, mat);
 792					} else {
 793						addFace(vb, va, vc, _uvb, _uva, _uvc, mat);
 794						addFace(vc, va, vd, _uvc, _uva, _uvd, mat);
 795					}
 796				}
 797				index += _subdivision + 1;
 798			}
 799		
 800		}
 801		
 802		private function elevate(v0:Object, v1:Object, increase:Number):void
 803		{
 804			for (var i:uint = 0; i < _subdivision; ++i) {
 805				v0[_axis] += increase;
 806				v1[_axis] += increase;
 807				_varr.push(new Vertex(v0[X_AXIS], v0[Y_AXIS], v0[Z_AXIS]));
 808				_varr2.push(new Vertex(v1[X_AXIS], v1[Y_AXIS], v1[Z_AXIS]));
 809			}
 810		}
 811		
 812		private function buildThicknessPoints(prop1:String, prop2:String):Array
 813		{
 814			var anchors:Array = [];
 815			var lines:Array = [];
 816			
 817			for (var i:uint = 0; i < _aVectors.length - 1; ++i) {
 818				
 819				if (_aVectors[i][prop1] == 0 && _aVectors[i][prop2] == 0)
 820					_aVectors[i][prop1] = EPS;
 821				
 822				if (_aVectors[i + 1][prop2] && _aVectors[i][prop2] == _aVectors[i + 1][prop2])
 823					_aVectors[i + 1][prop2] += EPS;
 824				
 825				if (_aVectors[i][prop1] && _aVectors[i][prop1] == _aVectors[i + 1][prop1])
 826					_aVectors[i + 1][prop1] += EPS;
 827				
 828				anchors.push(defineAnchors(_aVectors[i], _aVectors[i + 1], prop1, prop2));
 829			}
 830			
 831			var totallength:uint = anchors.length;
 832			var pointResult:FourPoints;
 833			
 834			if (totallength > 1) {
 835				
 836				for (i = 0; i < totallength; ++i) {
 837					
 838					if (i < totallength)
 839						pointResult = definelines(i, anchors[i], anchors[i + 1], lines);
 840					else
 841						pointResult = definelines(i, anchors[i], anchors[i - 1], lines);
 842					
 843					if (pointResult != null)
 844						lines.push(pointResult);
 845				}
 846				
 847			} else {
 848				
 849				var fourPoints:FourPoints = new FourPoints();
 850				var anchorFP:FourPoints = anchors[0];
 851				fourPoints.pt1 = anchorFP.pt1;
 852				fourPoints.pt2 = anchorFP.pt2;
 853				fourPoints.pt3 = anchorFP.pt3;
 854				fourPoints.pt4 = anchorFP.pt4;
 855				lines = [fourPoints];
 856			}
 857			
 858			return lines;
 859		}
 860		
 861		private function definelines(index:uint, point1:FourPoints, point2:FourPoints = null, lines:Array = null):FourPoints
 862		{
 863			var tmppt:FourPoints;
 864			var fourPoints:FourPoints = new FourPoints();
 865			
 866			if (point2 == null) {
 867				tmppt = lines[index - 1];
 868				fourPoints.pt1 = tmppt.pt3;
 869				fourPoints.pt2 = tmppt.pt4;
 870				fourPoints.pt3 = point1.pt3;
 871				fourPoints.pt4 = point1.pt4;
 872				
 873				return fourPoints;
 874			}
 875			
 876			var line1:Line = buildObjectLine(point1.pt1.x, point1.pt1.y, point1.pt3.x, point1.pt3.y);
 877			var line2:Line = buildObjectLine(point1.pt2.x, point1.pt2.y, point1.pt4.x, point1.pt4.y);
 878			var line3:Line = buildObjectLine(point2.pt1.x, point2.pt1.y, point2.pt3.x, point2.pt3.y);
 879			var line4:Line = buildObjectLine(point2.pt2.x, point2.pt2.y, point2.pt4.x, point2.pt4.y);
 880			
 881			var cross1:Point = lineIntersect(line3, line1);
 882			var cross2:Point = lineIntersect(line2, line4);
 883			
 884			if (cross1 != null && cross2 != null) {
 885				
 886				if (index == 0) {
 887					fourPoints.pt1 = point1.pt1;
 888					fourPoints.pt2 = point1.pt2;
 889					fourPoints.pt3 = cross1;
 890					fourPoints.pt4 = cross2;
 891					
 892					return fourPoints;
 893				}
 894				
 895				tmppt = lines[index - 1];
 896				fourPoints.pt1 = tmppt.pt3;
 897				fourPoints.pt2 = tmppt.pt4;
 898				fourPoints.pt3 = cross1;
 899				fourPoints.pt4 = cross2;
 900				
 901				return fourPoints;
 902				
 903			} else
 904				return null;
 905		}
 906		
 907		private function defineAnchors(base:Vector3D, baseEnd:Vector3D, prop1:String, prop2:String):FourPoints
 908		{
 909			var angle:Number = (Math.atan2(base[prop2] - baseEnd[prop2], base[prop1] - baseEnd[prop1])*180)/Math.PI;
 910			angle -= 270;
 911			var angle2:Number = angle + 180;
 912			
 913			var fourPoints:FourPoints = new FourPoints();
 914			fourPoints.pt1 = new Point(base[prop1], base[prop2]);
 915			fourPoints.pt2 = new Point(base[prop1], base[prop2]);
 916			fourPoints.pt3 = new Point(baseEnd[prop1], baseEnd[prop2]);
 917			fourPoints.pt4 = new Point(baseEnd[prop1], baseEnd[prop2]);
 918			
 919			var radius:Number = _thickness*.5;
 920			
 921			fourPoints.pt1.x = fourPoints.pt1.x + Math.cos(-angle/180*Math.PI)*radius;
 922			fourPoints.pt1.y = fourPoints.pt1.y + Math.sin(angle/180*Math.PI)*radius;
 923			
 924			fourPoints.pt2.x = fourPoints.pt2.x + Math.cos(-angle2/180*Math.PI)*radius;
 925			fourPoints.pt2.y = fourPoints.pt2.y + Math.sin(angle2/180*Math.PI)*radius;
 926			
 927			fourPoints.pt3.x = fourPoints.pt3.x + Math.cos(-angle/180*Math.PI)*radius;
 928			fourPoints.pt3.y = fourPoints.pt3.y + Math.sin(angle/180*Math.PI)*radius;
 929			
 930			fourPoints.pt4.x = fourPoints.pt4.x + Math.cos(-angle2/180*Math.PI)*radius;
 931			fourPoints.pt4.y = fourPoints.pt4.y + Math.sin(angle2/180*Math.PI)*radius;
 932			
 933			return fourPoints;
 934		}
 935		
 936		private function buildObjectLine(origX:Number, origY:Number, endX:Number, endY:Number):Line
 937		{
 938			var line:Line = new Line();
 939			line.ax = origX;
 940			line.ay = origY;
 941			line.bx = endX - origX;
 942			line.by = endY - origY;
 943			
 944			return line;
 945		}
 946		
 947		private function lineIntersect(Line1:Line, Line2:Line):Point
 948		{
 949			Line1.bx = (Line1.bx == 0)? EPS : Line1.bx;
 950			Line2.bx = (Line2.bx == 0)? EPS : Line2.bx;
 951			
 952			var a1:Number = Line1.by/Line1.bx;
 953			var b1:Number = Line1.ay - a1*Line1.ax;
 954			var a2:Number = Line2.by/Line2.bx;
 955			var b2:Number = Line2.ay - a2*Line2.ax;
 956			var nzero:Number = ((a1 - a2) == 0)? EPS : a1 - a2;
 957			var ptx:Number = ( b2 - b1 )/(nzero);
 958			var pty:Number = a1*ptx + b1;
 959			
 960			if (isFinite(ptx) && isFinite(pty))
 961				return new Point(ptx, pty);
 962			else {
 963				trace("infinity");
 964				return null;
 965			}
 966		}
 967		
 968		private function initHolders():void
 969		{
 970			if (!_uva) {
 971				_uva = new UV(0, 0);
 972				_uvb = new UV(0, 0);
 973				_uvc = new UV(0, 0);
 974				_uvd = new UV(0, 0);
 975			}
 976			
 977			_varr = new Vector.<Vertex>();
 978			_varr2 = new Vector.<Vertex>();
 979			_uvarr = new Vector.<UV>();
 980			_uvs = new Vector.<Number>();
 981			_vertices = new Vector.<Number>();
 982			_indices = new Vector.<uint>();
 983			
 984			if (_materials) {
 985				_MaterialsSubGeometries = new Vector.<SubGeometryList>();
 986				var sglist:SubGeometryList = new SubGeometryList();
 987				_MaterialsSubGeometries.push(sglist);
 988				sglist.subGeometry = new SubGeometry();
 989				_subGeometry = sglist.subGeometry;
 990				
 991				sglist.uvs = _uvs = new Vector.<Number>();
 992				sglist.vertices = _vertices = new Vector.<Number>();
 993				sglist.indices = _indices = new Vector.<uint>();
 994				sglist.material = this.material;
 995				if (sglist.material.name == null)
 996					sglist.material.name = "baseMaterial";
 997				
 998			} else {
 999				_subGeometry.autoDeriveVertexNormals = true;
1000				_subGeometry.autoDeriveVertexTangents = true;
1001			}
1002		}
1003		
1004		private function getSubGeometryListFromMaterial(mat:MaterialBase):SubGeometryList
1005		{
1006			var sglist:SubGeometryList;
1007			
1008			for (var i:uint = 0; i < _MaterialsSubGeometries.length; ++i) {
1009				if (_MaterialsSubGeometries[i].material == mat) {
1010					sglist = _MaterialsSubGeometries[i];
1011					break;
1012				}
1013			}
1014			
1015			if (!sglist) {
1016				sglist = new SubGeometryList();
1017				_MaterialsSubGeometries.push(sglist);
1018				sglist.subGeometry = new SubGeometry();
1019				sglist.uvs = new Vector.<Number>();
1020				sglist.vertices = new Vector.<Number>();
1021				sglist.indices = new Vector.<uint>();
1022				sglist.material = mat;
1023			}
1024			
1025			return sglist;
1026		}
1027		
1028		/**
1029		 * Invalidates the geometry, causing it to be rebuilded when requested.
1030		 */
1031		private function invalidateGeometry():void
1032		{
1033			if (_geomDirty)
1034				return;
1035			_geomDirty = true;
1036			invalidateBounds();
1037		}
1038	
1039	}
1040}
1041
1042import away3d.core.base.SubGeometry;
1043import away3d.materials.MaterialBase;
1044
1045import flash.geom.Point;
1046
1047class SubGeometryList
1048{
1049	public var id:uint;
1050	public var uvs:Vector.<Number>;
1051	public var vertices:Vector.<Number>;
1052	public var indices:Vector.<uint>;
1053	public var subGeometry:SubGeometry;
1054	public var material:MaterialBase;
1055}
1056
1057class RenderSide
1058{
1059	public var top:Boolean;
1060	public var bottom:Boolean;
1061	public var right:Boolean;
1062	public var left:Boolean;
1063	public var front:Boolean;
1064	public var back:Boolean;
1065}
1066
1067class Line
1068{
1069	public var ax:Number;
1070	public var ay:Number;
1071	public var bx:Number;
1072	public var by:Number;
1073}
1074
1075class FourPoints
1076{
1077	public var pt1:Point;
1078	public var pt2:Point;
1079	public var pt3:Point;
1080	public var pt4:Point;
1081}