PageRenderTime 801ms CodeModel.GetById 121ms app.highlight 520ms RepoModel.GetById 144ms app.codeStats 1ms

/src/away3d/extrusions/LatheExtrude.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 1550 lines | 1179 code | 281 blank | 90 comment | 262 complexity | 2a0d8865febf486421fce403e35cc27e 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.entities.Mesh;
   9	import away3d.materials.MaterialBase;
  10	import away3d.materials.utils.MultipleMaterials;
  11	import away3d.tools.helpers.MeshHelper;
  12	
  13	import flash.geom.Point;
  14	import flash.geom.Vector3D;
  15	
  16	/**
  17	 * Class for generating meshes with axial symmetry such as donuts, pipes, vases etc.
  18	 */
  19	public class LatheExtrude extends Mesh
  20	{
  21		private const EPS:Number = .0001;
  22		private const LIMIT:uint = 196605;
  23		private const MAXRAD:Number = 1.2;
  24		
  25		private var _profile:Vector.<Vector3D>;
  26		private var _lastProfile:Vector.<Vector3D>;
  27		private var _keepLastProfile:Boolean;
  28		private var _axis:String;
  29		private var _revolutions:Number;
  30		private var _subdivision:uint;
  31		private var _offsetRadius:Number;
  32		private var _prevOffsetRadius:Number = 0;
  33		private var _materials:MultipleMaterials;
  34		private var _coverAll:Boolean;
  35		private var _flip:Boolean;
  36		private var _centerMesh:Boolean;
  37		private var _thickness:Number;
  38		private var _preciseThickness:Boolean;
  39		private var _ignoreSides:String;
  40		private var _smoothSurface:Boolean;
  41		private var _tweek:Object;
  42		private var _varr:Vector.<Vector3D>;
  43		private var _varr2:Vector.<Vector3D>;
  44		private var _uvarr:Vector.<UV>;
  45		private var _startRotationOffset:Number = 0;
  46		
  47		private var _geomDirty:Boolean = true;
  48		private var _subGeometry:SubGeometry;
  49		private var _MaterialsSubGeometries:Vector.<SubGeometryList> = new Vector.<SubGeometryList>();
  50		private var _maxIndProfile:uint;
  51		private var _uva:UV;
  52		private var _uvb:UV;
  53		private var _uvc:UV;
  54		private var _uvd:UV;
  55		private var _va:Vector3D;
  56		private var _vb:Vector3D;
  57		private var _vc:Vector3D;
  58		private var _vd:Vector3D;
  59		private var _uvs:Vector.<Number>;
  60		private var _vertices:Vector.<Number>;
  61		private var _indices:Vector.<uint>;
  62		private var _normals:Vector.<Number>;
  63		private var _normalTmp:Vector3D;
  64		private var _normal0:Vector3D;
  65		private var _normal1:Vector3D;
  66		private var _normal2:Vector3D;
  67		
  68		public static const X_AXIS:String = "x";
  69		public static const Y_AXIS:String = "y";
  70		public static const Z_AXIS:String = "z";
  71		
  72		/**
  73		 *  Class LatheExtrude generates circular meshes such as donuts, pipes, pyramids etc.. from a series of Vector3D's
  74		 *
  75		 *@param        material                [optional] MaterialBase. The LatheExtrude (Mesh) material. Optional in constructor, material must be set before LatheExtrude object is render.
  76		 * @param        profile                [optional] Vector.&lt;Vector3D&gt;. A series of Vector3D's representing the profile information to be repeated/rotated around a given axis.
  77		 * @param        axis                    [optional] String. The axis to rotate around: X_AXIS, Y_AXIS or Z_AXIS. Default is LatheExtrude.Y_AXIS.
  78		 * @param        revolutions            [optional] Number. The LatheExtrude object can have less than one revolution, like 0.6 for a piechart or greater than 1 if a tweek object is passed. Minimum is 0.01. Default is 1.
  79		 * @param        subdivision            [optional] uint. Howmany segments will compose the mesh in its rotational construction. Minimum is 3. Default is 10.
  80		 * @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 true.
  81		 * @param        flip                    [optional] Boolean. If the faces must be reversed depending on Vector3D's orientation. Default is false.
  82		 * @param        thickness            [optional] Number. If the shape must simulate a thickness. Default is 0.
  83		 * @param        preciseThickness    [optional] Boolean. If the thickness must be repected along the entire volume profile. Default is true.
  84		 * @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.
  85		 * @param        offsetRadius        [optional] Number. An offset radius if the profile data is not to be updated but the radius expected to be different. Default is 0.
  86		 * @param        materials            [optional] MultipleMaterials. Allows multiple material support when thickness is set higher to 1. Default is null.
  87		 * properties as MaterialBase are: bottom, top, left, right, front and back.
  88		 * @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 "".
  89		 * @param        tweek                [optional] Object. To build springs like shapes, rotation must be higher than 1. Properties of the tweek object are x,y,z, radius and rotation. Default is null.
  90		 * @param        smoothSurface    [optional]    An optional Boolean. Defines if the surface of the mesh must be smoothed or not.
  91		 */
  92		public function LatheExtrude(material:MaterialBase = null, profile:Vector.<Vector3D> = null, axis:String = LatheExtrude.Y_AXIS, revolutions:Number = 1, subdivision:uint = 10, coverall:Boolean = true, centerMesh:Boolean = false, flip:Boolean = false, thickness:Number = 0, preciseThickness:Boolean = true, offsetRadius:Number = 0, materials:MultipleMaterials = null, ignoreSides:String = "", tweek:Object = null, smoothSurface:Boolean = true)
  93		{
  94			var geom:Geometry = new Geometry();
  95			_subGeometry = new SubGeometry();
  96			
  97			if (!material && materials && materials.front)
  98				material = materials.front;
  99			super(geom, material);
 100			
 101			_profile = profile;
 102			_axis = axis;
 103			_revolutions = revolutions;
 104			_subdivision = (subdivision < 3)? 3 : subdivision;
 105			_offsetRadius = offsetRadius;
 106			_materials = materials;
 107			_coverAll = coverall;
 108			_flip = flip;
 109			_centerMesh = centerMesh;
 110			_thickness = Math.abs(thickness);
 111			_preciseThickness = preciseThickness;
 112			_ignoreSides = ignoreSides;
 113			_tweek = tweek;
 114			_smoothSurface = smoothSurface;
 115		}
 116		
 117		/*
 118		 * A Vector.<Vector3D> representing the profile information to be repeated/rotated around a given axis.
 119		 */
 120		public function get profile():Vector.<Vector3D>
 121		{
 122			return _profile;
 123		}
 124		
 125		public function set profile(val:Vector.<Vector3D>):void
 126		{
 127			if (val.length > 1) {
 128				_profile = val;
 129				invalidateGeometry();
 130			} else
 131				throw new Error("LatheExtrude error: the profile Vector.<Vector3D> must hold a mimimun of 2 vector3D's");
 132		}
 133		
 134		/*
 135		 * A Number, to offset the original start angle of the rotation. Default is 0;
 136		 */
 137		public function get startRotationOffset():Number
 138		{
 139			return _startRotationOffset;
 140		}
 141		
 142		public function set startRotationOffset(val:Number):void
 143		{
 144			_startRotationOffset = val;
 145		}
 146		
 147		/**
 148		 * Defines the axis used for the lathe rotation. Defaults to "y".
 149		 */
 150		public function get axis():String
 151		{
 152			return _axis;
 153		}
 154		
 155		public function set axis(val:String):void
 156		{
 157			if (_axis == val)
 158				return;
 159			
 160			_axis = val;
 161			invalidateGeometry();
 162		}
 163		
 164		/**
 165		 * Defines the number of revolutions performed by the lathe extrusion. Defaults to 1.
 166		 */
 167		public function get revolutions():Number
 168		{
 169			return _revolutions;
 170		}
 171		
 172		public function set revolutions(val:Number):void
 173		{
 174			if (_revolutions == val)
 175				return;
 176			_revolutions = (_revolutions > .001)? _revolutions : .001;
 177			_revolutions = val;
 178			invalidateGeometry();
 179		}
 180		
 181		/**
 182		 * Defines the subdivisions created in the mesh for the total number of revolutions. Defaults to 2, minimum 2.
 183		 *
 184		 * @see #revolutions
 185		 */
 186		public function get subdivision():uint
 187		{
 188			return _subdivision;
 189		}
 190		
 191		public function set subdivision(val:uint):void
 192		{
 193			val = (val < 3)? 3 : val;
 194			if (_subdivision == val)
 195				return;
 196			_subdivision = val;
 197			invalidateGeometry();
 198		}
 199		
 200		/**
 201		 * Defines an offset radius applied to the profile. Defaults to 0.
 202		 */
 203		public function get offsetRadius():Number
 204		{
 205			return _offsetRadius;
 206		}
 207		
 208		public function set offsetRadius(val:Number):void
 209		{
 210			if (_offsetRadius == val)
 211				return;
 212			_offsetRadius = val;
 213			invalidateGeometry();
 214		}
 215		
 216		/**
 217		 * An optional object that defines left, right, front, back, top and bottom materials to be set on the resulting lathe extrusion.
 218		 */
 219		public function get materials():MultipleMaterials
 220		{
 221			return _materials;
 222		}
 223		
 224		public function set materials(val:MultipleMaterials):void
 225		{
 226			_materials = val;
 227			
 228			if (_materials.front && this.material != _materials.front)
 229				this.material = _materials.front;
 230			
 231			invalidateGeometry();
 232		}
 233		
 234		/**
 235		 * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to true.
 236		 */
 237		public function get coverAll():Boolean
 238		{
 239			return _coverAll;
 240		}
 241		
 242		public function set coverAll(val:Boolean):void
 243		{
 244			if (_coverAll == val)
 245				return;
 246			
 247			_coverAll = val;
 248			invalidateGeometry();
 249		}
 250		
 251		/**
 252		 * Defines if the generated faces should be inversed. Default false.
 253		 */
 254		public function get flip():Boolean
 255		{
 256			return _flip;
 257		}
 258		
 259		public function set flip(val:Boolean):void
 260		{
 261			if (_flip == val)
 262				return;
 263			
 264			_flip = val;
 265			invalidateGeometry();
 266		}
 267		
 268		/**
 269		 * Defines if the surface of the mesh must be smoothed or not.
 270		 */
 271		public function get smoothSurface():Boolean
 272		{
 273			return _smoothSurface;
 274		}
 275		
 276		public function set smoothSurface(val:Boolean):void
 277		{
 278			if (_smoothSurface == val)
 279				return;
 280			
 281			_smoothSurface = val;
 282			_geomDirty = true;
 283		}
 284		
 285		/**
 286		 * Defines if the last transformed profile values are saved or not. Useful in combo with rotations less than 1, to ease combinations with other extrusions classes such as SkinExtrude.
 287		 */
 288		public function get keepLastProfile():Boolean
 289		{
 290			return _keepLastProfile;
 291		}
 292		
 293		public function set keepLastProfile(val:Boolean):void
 294		{
 295			if (_keepLastProfile == val)
 296				return;
 297			
 298			_keepLastProfile = val;
 299		}
 300		
 301		/**
 302		 * returns the last rotated profile values, if keepLastProfile was true
 303		 */
 304		public function get lastProfile():Vector.<Vector3D>
 305		{
 306			if (keepLastProfile && !_lastProfile)
 307				buildExtrude();
 308			
 309			return _lastProfile;
 310		}
 311		
 312		/**
 313		 * Defines if thickness is greater than 0 if the thickness is equally distributed along the volume. Default is false.
 314		 */
 315		public function get preciseThickness():Boolean
 316		{
 317			return _preciseThickness;
 318		}
 319		
 320		public function set preciseThickness(val:Boolean):void
 321		{
 322			if (_preciseThickness == val)
 323				return;
 324			
 325			_preciseThickness = val;
 326			invalidateGeometry();
 327		}
 328		
 329		/**
 330		 * Defines whether the mesh is recentered of not after generation
 331		 */
 332		public function get centerMesh():Boolean
 333		{
 334			return _centerMesh;
 335		}
 336		
 337		public function set centerMesh(val:Boolean):void
 338		{
 339			if (_centerMesh == val)
 340				return;
 341			
 342			_centerMesh = val;
 343			
 344			if (_centerMesh && _subGeometry.vertexData.length > 0)
 345				MeshHelper.recenter(this);
 346			else
 347				invalidateGeometry();
 348		}
 349		
 350		/**
 351		 * Defines the thickness of the resulting lathed geometry. Defaults to 0 (single face).
 352		 */
 353		public function get thickness():Number
 354		{
 355			return _thickness;
 356		}
 357		
 358		public function set thickness(val:Number):void
 359		{
 360			if (_thickness == val)
 361				return;
 362			
 363			_thickness = (val > 0)? val : _thickness;
 364			invalidateGeometry();
 365		}
 366		
 367		/**
 368		 * Defines if the top, bottom, left, right, front or back of the the extrusion is left open.
 369		 */
 370		public function get ignoreSides():String
 371		{
 372			return _ignoreSides;
 373		}
 374		
 375		public function set ignoreSides(val:String):void
 376		{
 377			_ignoreSides = val;
 378			invalidateGeometry();
 379		}
 380		
 381		/**
 382		 * Allows the building of shapes such as springs. Rotation must be higher than 1 to have significant effect. Properties of the objects are x,y,z,radius and rotation
 383		 */
 384		public function get tweek():Object
 385		{
 386			return _tweek;
 387		}
 388		
 389		public function set tweek(val:Object):void
 390		{
 391			_tweek = val;
 392			invalidateGeometry();
 393		}
 394		
 395		/**
 396		 * @inheritDoc
 397		 */
 398		override public function get bounds():BoundingVolumeBase
 399		{
 400			if (_geomDirty)
 401				buildExtrude();
 402			
 403			return super.bounds;
 404		}
 405		
 406		/**
 407		 * @inheritDoc
 408		 */
 409		override public function get geometry():Geometry
 410		{
 411			if (_geomDirty)
 412				buildExtrude();
 413			
 414			return super.geometry;
 415		}
 416		
 417		/**
 418		 * @inheritDoc
 419		 */
 420		override public function get subMeshes():Vector.<SubMesh>
 421		{
 422			if (_geomDirty)
 423				buildExtrude();
 424			
 425			return super.subMeshes;
 426		}
 427		
 428		private function closeTopBottom(ptLength:int, renderSide:RenderSide):void
 429		{
 430			var va:Vector3D;
 431			var vb:Vector3D;
 432			var vc:Vector3D;
 433			var vd:Vector3D;
 434			
 435			var i:uint;
 436			var j:uint;
 437			var a:Number;
 438			var b:Number;
 439			
 440			var total:uint = _varr.length - ptLength;
 441			
 442			_uva.u = _uvb.u = 0;
 443			_uvc.u = _uvd.u = 1;
 444			
 445			for (i = 0; i < total; i += ptLength) {
 446				
 447				if (i != 0) {
 448					if (_coverAll) {
 449						a = i/total;
 450						b = (i + ptLength)/total;
 451						
 452						_uva.v = a;
 453						_uvb.v = b;
 454						_uvc.v = b;
 455						_uvd.v = a;
 456						
 457					} else {
 458						_uva.v = 0;
 459						_uvb.v = 1;
 460						_uvc.v = 1;
 461						_uvd.v = 0;
 462					}
 463					
 464					if (renderSide.top) {
 465						
 466						va = _varr[i];
 467						vb = _varr[i + ptLength];
 468						vc = _varr2[i + ptLength];
 469						vd = _varr2[i];
 470						
 471						if (_flip) {
 472							addFace(vb, va, vc, _uvb, _uva, _uvc, 4);
 473							addFace(vc, va, vd, _uvc, _uva, _uvd, 4);
 474						} else {
 475							addFace(va, vb, vc, _uva, _uvb, _uvc, 4);
 476							addFace(va, vc, vd, _uva, _uvc, _uvd, 4);
 477						}
 478					}
 479					
 480					if (renderSide.bottom) {
 481						j = i + ptLength - 1;
 482						
 483						va = _varr[j];
 484						vb = _varr[j + ptLength];
 485						vc = _varr2[j + ptLength];
 486						vd = _varr2[j];
 487						
 488						if (_flip) {
 489							addFace(va, vb, vc, _uva, _uvb, _uvc, 5);
 490							addFace(va, vc, vd, _uva, _uvc, _uvd, 5);
 491						} else {
 492							addFace(vb, va, vc, _uvb, _uva, _uvc, 5);
 493							addFace(vc, va, vd, _uvc, _uva, _uvd, 5);
 494						}
 495					}
 496				}
 497			}
 498		}
 499		
 500		private function closeSides(ptLength:uint, renderSide:RenderSide):void
 501		{
 502			var va:Vector3D;
 503			var vb:Vector3D;
 504			var vc:Vector3D;
 505			var vd:Vector3D;
 506			
 507			var total:uint = _varr.length - ptLength;
 508			var i:uint;
 509			var j:uint;
 510			var a:Number;
 511			var b:Number;
 512			
 513			var iter:int = ptLength - 1;
 514			var step:Number = (_preciseThickness && ptLength%2 == 0)? 1/iter : 1/ptLength;
 515			
 516			for (i = 0; i < iter; ++i) {
 517				
 518				if (_coverAll) {
 519					a = i*step;
 520					b = a + step;
 521					
 522					_uva.v = 1 - a;
 523					_uvb.v = 1 - b;
 524					_uvc.v = 1 - b;
 525					_uvd.v = 1 - a;
 526					
 527				} else {
 528					
 529					_uva.v = 0;
 530					_uvb.v = 1;
 531					_uvc.v = 1;
 532					_uvd.v = 0;
 533				}
 534				
 535				if (renderSide.left) {
 536					va = _varr[i + 1];
 537					vb = _varr[i];
 538					vc = _varr2[i];
 539					vd = _varr2[i + 1];
 540					
 541					_uva.u = _uvb.u = 0;
 542					_uvc.u = _uvd.u = 1;
 543					
 544					if (_flip) {
 545						addFace(vb, va, vc, _uvb, _uva, _uvc, 2);
 546						addFace(vc, va, vd, _uvc, _uva, _uvd, 2);
 547					} else {
 548						addFace(va, vb, vc, _uva, _uvb, _uvc, 2);
 549						addFace(va, vc, vd, _uva, _uvc, _uvd, 2);
 550					}
 551				}
 552				
 553				if (renderSide.right) {
 554					j = total + i;
 555					va = _varr[j + 1];
 556					vb = _varr[j ];
 557					vc = _varr2[j];
 558					vd = _varr2[j + 1];
 559					
 560					_uva.u = _uvb.u = 1;
 561					_uvc.u = _uvd.u = 0;
 562					
 563					if (_flip) {
 564						addFace(va, vb, vc, _uva, _uvb, _uvc, 3);
 565						addFace(va, vc, vd, _uva, _uvc, _uvd, 3);
 566					} else {
 567						addFace(vb, va, vc, _uvb, _uva, _uvc, 3);
 568						addFace(vc, va, vd, _uvc, _uva, _uvd, 3);
 569					}
 570				}
 571				
 572			}
 573		}
 574		
 575		private function generate(vectors:Vector.<Vector3D>, axis:String, tweek:Object, render:Boolean = true, id:uint = 0):void
 576		{
 577			// TODO: not used
 578			axis = axis;
 579			
 580			if (!tweek)
 581				tweek = {};
 582			
 583			if (isNaN(tweek[X_AXIS]) || !tweek[X_AXIS])
 584				tweek[X_AXIS] = 0;
 585			if (isNaN(tweek[Y_AXIS]) || !tweek[Y_AXIS])
 586				tweek[Y_AXIS] = 0;
 587			if (isNaN(tweek[Z_AXIS]) || !tweek[Z_AXIS])
 588				tweek[Z_AXIS] = 0;
 589			if (isNaN(tweek["radius"]) || !tweek["radius"])
 590				tweek["radius"] = 0;
 591			
 592			var angle:Number = _startRotationOffset;
 593			var step:Number = 360/_subdivision;
 594			var j:uint;
 595			
 596			var tweekX:Number = 0;
 597			var tweekY:Number = 0;
 598			var tweekZ:Number = 0;
 599			var tweekradius:Number = 0;
 600			var tweekrotation:Number = 0;
 601			
 602			var tmpVecs:Vector.<Vector3D>;
 603			var aRads:Array = [];
 604			
 605			var uvu:Number;
 606			var uvv:Number;
 607			var i:uint;
 608			
 609			if (!_varr)
 610				_varr = new Vector.<Vector3D>();
 611			
 612			for (i = 0; i < vectors.length; ++i) {
 613				_varr.push(new Vector3D(vectors[i].x, vectors[i].y, vectors[i].z));
 614				_uvarr.push(new UV(0, 1%i));
 615			}
 616			
 617			var offsetradius:Number = -_offsetRadius;
 618			offsetradius += _prevOffsetRadius;
 619			var factor:Number = 0;
 620			var stepm:Number = 360*_revolutions;
 621			
 622			var lsub:Number = (_revolutions < 1)? _subdivision : _subdivision*_revolutions;
 623			if (_revolutions < 1)
 624				step *= _revolutions;
 625			
 626			for (i = 0; i <= lsub; ++i) {
 627				
 628				tmpVecs = new Vector.<Vector3D>();
 629				tmpVecs = vectors.concat();
 630				
 631				for (j = 0; j < tmpVecs.length; ++j) {
 632					
 633					factor = ((_revolutions - 1)/(_varr.length + 1));
 634					
 635					if (tweek[X_AXIS] != 0)
 636						tweekX += (tweek[X_AXIS]*factor)/_revolutions;
 637					
 638					if (tweek[Y_AXIS] != 0)
 639						tweekY += (tweek[Y_AXIS]*factor)/_revolutions;
 640					
 641					if (tweek[Z_AXIS] != 0)
 642						tweekZ += (tweek[Z_AXIS]*factor)/_revolutions;
 643					
 644					if (tweek.radius != 0)
 645						tweekradius += (tweek.radius/(_varr.length + 1));
 646					
 647					if (tweek.rotation != 0)
 648						tweekrotation += 360/(tweek.rotation*_subdivision);
 649					
 650					if (_axis == X_AXIS) {
 651						if (i == 0)
 652							aRads[j] = offsetradius - Math.abs(tmpVecs[j].z);
 653						
 654						tmpVecs[j].z = Math.cos(-angle/180*Math.PI)*(aRads[j] + tweekradius );
 655						tmpVecs[j].y = Math.sin(angle/180*Math.PI)*(aRads[j] + tweekradius );
 656						
 657						if (i == 0) {
 658							_varr[j].z += tmpVecs[j].z;
 659							_varr[j].y += tmpVecs[j].y;
 660						}
 661						
 662					} else if (_axis == Y_AXIS) {
 663						
 664						if (i == 0)
 665							aRads[j] = offsetradius - Math.abs(tmpVecs[j].x);
 666						
 667						tmpVecs[j].x = Math.cos(-angle/180*Math.PI)*(aRads[j] + tweekradius );
 668						tmpVecs[j].z = Math.sin(angle/180*Math.PI)*(aRads[j] + tweekradius );
 669						
 670						if (i == 0) {
 671							_varr[j].x = tmpVecs[j].x;
 672							_varr[j].z = tmpVecs[j].z;
 673						}
 674						
 675					} else {
 676						
 677						if (i == 0)
 678							aRads[j] = offsetradius - Math.abs(tmpVecs[j].y);
 679						
 680						tmpVecs[j].x = Math.cos(-angle/180*Math.PI)*(aRads[j] + tweekradius );
 681						tmpVecs[j].y = Math.sin(angle/180*Math.PI)*(aRads[j] + tweekradius );
 682						
 683						if (i == 0) {
 684							_varr[j].x = tmpVecs[j].x;
 685							_varr[j].y = tmpVecs[j].y;
 686						}
 687					}
 688					
 689					tmpVecs[j].x += tweekX;
 690					tmpVecs[j].y += tweekY;
 691					tmpVecs[j].z += tweekZ;
 692					
 693					_varr.push(new Vector3D(tmpVecs[j].x, tmpVecs[j].y, tmpVecs[j].z));
 694					
 695					if (_coverAll)
 696						uvu = angle/stepm;
 697					else
 698						uvu = (i%2 == 0)? 0 : 1;
 699					
 700					uvv = j/(_profile.length - 1);
 701					_uvarr.push(new UV(uvu, uvv));
 702				}
 703				
 704				angle += step;
 705				
 706			}
 707			
 708			_prevOffsetRadius = _offsetRadius;
 709			
 710			if (render) {
 711				
 712				var index:int;
 713				var inc:int = vectors.length;
 714				var loop:int = _varr.length - inc;
 715				
 716				var va:Vector3D;
 717				var vb:Vector3D;
 718				var vc:Vector3D;
 719				var vd:Vector3D;
 720				var uva:UV;
 721				var uvb:UV;
 722				var uvc:UV;
 723				var uvd:UV;
 724				var uvind:uint;
 725				var vind:uint;
 726				var iter:int = inc - 1;
 727				
 728				for (i = 0; i < loop; i += inc) {
 729					index = 0;
 730					for (j = 0; j < iter; ++j) {
 731						
 732						if (i > 0) {
 733							uvind = i + index;
 734							vind = uvind;
 735							
 736							uva = _uvarr[uvind + 1];
 737							uvb = _uvarr[uvind];
 738							uvc = _uvarr[uvind + inc];
 739							uvd = _uvarr[uvind + inc + 1];
 740							
 741							if (_revolutions == 1 && i + inc == loop && _tweek == null) {
 742								va = _varr[vind + 1];
 743								vb = _varr[vind];
 744								vc = _varr[vind + inc];
 745								vd = _varr[vind + inc + 1];
 746								
 747							} else {
 748								va = _varr[vind + 1];
 749								vb = _varr[vind];
 750								vc = _varr[vind + inc];
 751								vd = _varr[vind + inc + 1];
 752							}
 753							
 754							if (_flip) {
 755								if (id == 1) {
 756									_uva.u = 1 - uva.u;
 757									_uva.v = uva.v;
 758									_uvb.u = 1 - uvb.u;
 759									_uvb.v = uvb.v;
 760									_uvc.u = 1 - uvc.u;
 761									_uvc.v = uvc.v;
 762									_uvd.u = 1 - uvd.u;
 763									_uvd.v = uvd.v;
 764									
 765									addFace(va, vb, vc, _uva, _uvb, _uvc, id);
 766									addFace(va, vc, vd, _uva, _uvc, _uvd, id);
 767									
 768								} else {
 769									
 770									addFace(vb, va, vc, uvb, uva, uvc, id);
 771									addFace(vc, va, vd, uvc, uva, uvd, id);
 772								}
 773								
 774							} else {
 775								
 776								if (id == 1) {
 777									_uva.u = uva.u;
 778									_uva.v = 1 - uva.v;
 779									_uvb.u = uvb.u;
 780									_uvb.v = 1 - uvb.v;
 781									_uvc.u = uvc.u;
 782									_uvc.v = 1 - uvc.v;
 783									_uvd.u = uvd.u;
 784									_uvd.v = 1 - uvd.v;
 785									
 786									addFace(vb, va, vc, _uvb, _uva, _uvc, id);
 787									addFace(vc, va, vd, _uvc, _uva, _uvd, id);
 788									
 789								} else {
 790									
 791									addFace(va, vb, vc, uva, uvb, uvc, id);
 792									addFace(va, vc, vd, uva, uvc, uvd, id);
 793								}
 794								
 795							}
 796						}
 797						
 798						index++;
 799					}
 800				}
 801			}
 802		}
 803		
 804		private function buildExtrude():void
 805		{
 806			if (!_profile)
 807				throw new Error("LatheExtrude error: No profile Vector.<Vector3D> set");
 808			_MaterialsSubGeometries = null;
 809			_geomDirty = false;
 810			initHolders();
 811			_maxIndProfile = _profile.length*9;
 812			
 813			if (_profile.length > 1) {
 814				
 815				if (_thickness != 0) {
 816					var i:uint;
 817					var aListsides:Array = ["top", "bottom", "right", "left", "front", "back"];
 818					var renderSide:RenderSide = new RenderSide();
 819					
 820					for (i = 0; i < aListsides.length; ++i)
 821						renderSide[aListsides[i]] = (_ignoreSides.indexOf(aListsides[i]) == -1);
 822					
 823					_varr = new Vector.<Vector3D>();
 824					_varr2 = new Vector.<Vector3D>();
 825					
 826					if (_preciseThickness) {
 827						
 828						var prop1:String;
 829						var prop2:String;
 830						var prop3:String;
 831						
 832						switch (_axis) {
 833							case X_AXIS:
 834								prop1 = X_AXIS;
 835								prop2 = Z_AXIS;
 836								prop3 = Y_AXIS;
 837								break;
 838							
 839							case Y_AXIS:
 840								prop1 = Y_AXIS;
 841								prop2 = X_AXIS;
 842								prop3 = Z_AXIS;
 843								break;
 844							
 845							case Z_AXIS:
 846								prop1 = Z_AXIS;
 847								prop2 = Y_AXIS;
 848								prop3 = X_AXIS;
 849						}
 850						
 851						var lines:Array = buildThicknessPoints(_profile, thickness, prop1, prop2);
 852						var points:FourPoints;
 853						var vector:Vector3D;
 854						var vector2:Vector3D;
 855						var vector3:Vector3D;
 856						var vector4:Vector3D;
 857						var profileFront:Vector.<Vector3D> = new Vector.<Vector3D>();
 858						var profileBack:Vector.<Vector3D> = new Vector.<Vector3D>();
 859						
 860						for (i = 0; i < lines.length; ++i) {
 861							
 862							points = lines[i];
 863							vector = new Vector3D();
 864							vector2 = new Vector3D();
 865							
 866							if (i == 0) {
 867								
 868								vector[prop1] = points.pt2.x;
 869								vector[prop2] = points.pt2.y;
 870								vector[prop3] = _profile[0][prop3];
 871								profileFront.push(vector);
 872								
 873								vector2[prop1] = points.pt1.x;
 874								vector2[prop2] = points.pt1.y;
 875								vector2[prop3] = _profile[0][prop3];
 876								profileBack.push(vector2);
 877								
 878								if (lines.length == 1) {
 879									vector3 = new Vector3D();
 880									vector4 = new Vector3D();
 881									
 882									vector3[prop1] = points.pt4.x;
 883									vector3[prop2] = points.pt4.y;
 884									vector3[prop3] = _profile[0][prop3];
 885									profileFront.push(vector3);
 886									
 887									vector4[prop1] = points.pt3.x;
 888									vector4[prop2] = points.pt3.y;
 889									vector4[prop3] = _profile[0][prop3];
 890									profileBack.push(vector4);
 891								}
 892								
 893							} else if (i == lines.length - 1) {
 894								vector[prop1] = points.pt2.x;
 895								vector[prop2] = points.pt2.y;
 896								vector[prop3] = _profile[i][prop3];
 897								profileFront.push(vector);
 898								
 899								vector2[prop1] = points.pt1.x;
 900								vector2[prop2] = points.pt1.y;
 901								vector2[prop3] = _profile[i][prop3];
 902								profileBack.push(vector2);
 903								
 904								vector3 = new Vector3D();
 905								vector4 = new Vector3D();
 906								
 907								vector3[prop1] = points.pt4.x;
 908								vector3[prop2] = points.pt4.y;
 909								vector3[prop3] = _profile[i][prop3];
 910								profileFront.push(vector3);
 911								
 912								vector4[prop1] = points.pt3.x;
 913								vector4[prop2] = points.pt3.y;
 914								vector4[prop3] = _profile[i][prop3];
 915								profileBack.push(vector4);
 916								
 917							} else {
 918								
 919								vector[prop1] = points.pt2.x;
 920								vector[prop2] = points.pt2.y;
 921								vector[prop3] = _profile[i][prop3];
 922								profileFront.push(vector);
 923								
 924								vector2[prop1] = points.pt1.x;
 925								vector2[prop2] = points.pt1.y;
 926								vector2[prop3] = _profile[i][prop3];
 927								profileBack.push(vector2);
 928								
 929							}
 930						}
 931						
 932						generate(profileFront, _axis, _tweek, renderSide.front, 0);
 933						_varr2 = _varr2.concat(_varr);
 934						_varr = new Vector.<Vector3D>();
 935						generate(profileBack, _axis, _tweek, renderSide.back, 1);
 936						
 937					} else {
 938						// non distributed thickness
 939						var tmprofile1:Vector.<Vector3D> = new Vector.<Vector3D>();
 940						var tmprofile2:Vector.<Vector3D> = new Vector.<Vector3D>();
 941						var halft:Number = _thickness*.5;
 942						var val:Number;
 943						for (i = 0; i < _profile.length; ++i) {
 944							
 945							switch (_axis) {
 946								case X_AXIS:
 947									val = (_profile[i].z < 0)? halft : -halft;
 948									tmprofile1.push(new Vector3D(_profile[i].x, _profile[i].y, _profile[i].z - val));
 949									tmprofile2.push(new Vector3D(_profile[i].x, _profile[i].y, _profile[i].z + val));
 950									break;
 951								
 952								case Y_AXIS:
 953									val = (_profile[i].x < 0)? halft : -halft;
 954									tmprofile1.push(new Vector3D(_profile[i].x - val, _profile[i].y, _profile[i].z));
 955									tmprofile2.push(new Vector3D(_profile[i].x + val, _profile[i].y, _profile[i].z));
 956									break;
 957								
 958								case Z_AXIS:
 959									val = (_profile[i].y < 0)? halft : -halft;
 960									tmprofile1.push(new Vector3D(_profile[i].x, _profile[i].y - val, _profile[i].z));
 961									tmprofile2.push(new Vector3D(_profile[i].x, _profile[i].y + val, _profile[i].z));
 962							}
 963							
 964						}
 965						generate(tmprofile1, _axis, _tweek, renderSide.front, 0);
 966						_varr2 = _varr2.concat(_varr);
 967						_varr = new Vector.<Vector3D>();
 968						generate(tmprofile2, _axis, _tweek, renderSide.back, 1);
 969					}
 970					
 971					closeTopBottom(_profile.length, renderSide);
 972					
 973					if (_revolutions != 1)
 974						closeSides(_profile.length, renderSide);
 975					
 976				} else
 977					generate(_profile, _axis, _tweek);
 978				
 979			} else
 980				throw new Error("LatheExtrude error: the profile Vector.<Vector3D> must hold a mimimun of 2 vector3D's");
 981			
 982			if (_vertices.length > 0) {
 983				_subGeometry.updateVertexData(_vertices);
 984				_subGeometry.updateIndexData(_indices);
 985				_subGeometry.updateUVData(_uvs);
 986				if (_smoothSurface)
 987					_subGeometry.updateVertexNormalData(_normals);
 988				this.geometry.addSubGeometry(_subGeometry);
 989			}
 990			
 991			if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
 992				var sglist:SubGeometryList;
 993				var sg:SubGeometry;
 994				for (i = 1; i < 6; ++i) {
 995					sglist = _MaterialsSubGeometries[i];
 996					sg = sglist.subGeometry;
 997					if (sg && sglist.vertices.length > 0) {
 998						this.geometry.addSubGeometry(sg);
 999						this.subMeshes[this.subMeshes.length - 1].material = sglist.material;
1000						sg.updateVertexData(sglist.vertices);
1001						sg.updateIndexData(sglist.indices);
1002						sg.updateUVData(sglist.uvs);
1003						if (_smoothSurface)
1004							sg.updateVertexNormalData(sglist.normals);
1005					}
1006				}
1007			}
1008			
1009			if (_keepLastProfile)
1010				_lastProfile = _varr.splice(_varr.length - _profile.length, _profile.length);
1011			else
1012				_lastProfile = null;
1013			
1014			_varr = _varr2 = null;
1015			_uvarr = null;
1016			
1017			if (_centerMesh)
1018				MeshHelper.recenter(this);
1019		}
1020		
1021		private function calcNormal(v0:Vector3D, v1:Vector3D, v2:Vector3D):void
1022		{
1023			var dx1:Number = v2.x - v0.x;
1024			var dy1:Number = v2.y - v0.y;
1025			var dz1:Number = v2.z - v0.z;
1026			var dx2:Number = v1.x - v0.x;
1027			var dy2:Number = v1.y - v0.y;
1028			var dz2:Number = v1.z - v0.z;
1029			
1030			var cx:Number = dz1*dy2 - dy1*dz2;
1031			var cy:Number = dx1*dz2 - dz1*dx2;
1032			var cz:Number = dy1*dx2 - dx1*dy2;
1033			var d:Number = 1/Math.sqrt(cx*cx + cy*cy + cz*cz);
1034			
1035			_normal0.x = _normal1.x = _normal2.x = cx*d;
1036			_normal0.y = _normal1.y = _normal2.y = cy*d;
1037			_normal0.z = _normal1.z = _normal2.z = cz*d;
1038		}
1039		
1040		private function addFace(v0:Vector3D, v1:Vector3D, v2:Vector3D, uv0:UV, uv1:UV, uv2:UV, subGeomInd:uint):void
1041		{
1042			var subGeom:SubGeometry;
1043			var uvs:Vector.<Number>;
1044			var normals:Vector.<Number>;
1045			var vertices:Vector.<Number>;
1046			var indices:Vector.<uint>;
1047			
1048			if (subGeomInd > 0 && _MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
1049				subGeom = _MaterialsSubGeometries[subGeomInd].subGeometry;
1050				uvs = _MaterialsSubGeometries[subGeomInd].uvs;
1051				vertices = _MaterialsSubGeometries[subGeomInd].vertices;
1052				indices = _MaterialsSubGeometries[subGeomInd].indices;
1053				normals = _MaterialsSubGeometries[subGeomInd].normals;
1054			} else {
1055				
1056				subGeom = _subGeometry;
1057				uvs = _uvs;
1058				vertices = _vertices;
1059				indices = _indices;
1060				normals = _normals;
1061			}
1062			
1063			if (vertices.length + 9 > LIMIT) {
1064				subGeom.updateVertexData(vertices);
1065				subGeom.updateIndexData(indices);
1066				subGeom.updateUVData(uvs);
1067				if (_smoothSurface)
1068					subGeom.updateVertexNormalData(normals);
1069				this.geometry.addSubGeometry(subGeom);
1070				
1071				if (subGeomInd > 0 && _MaterialsSubGeometries && _MaterialsSubGeometries[subGeomInd].subGeometry)
1072					this.subMeshes[this.subMeshes.length - 1].material = _MaterialsSubGeometries[subGeomInd].material;
1073				
1074				subGeom = new SubGeometry();
1075				subGeom.autoDeriveVertexTangents = true;
1076				
1077				if (_MaterialsSubGeometries && _MaterialsSubGeometries.length > 0) {
1078					_MaterialsSubGeometries[subGeomInd].subGeometry = subGeom;
1079					uvs = new Vector.<Number>();
1080					vertices = new Vector.<Number>();
1081					indices = new Vector.<uint>();
1082					normals = new Vector.<Number>();
1083					_MaterialsSubGeometries[subGeomInd].uvs = uvs;
1084					_MaterialsSubGeometries[subGeomInd].indices = indices;
1085					
1086					if (_smoothSurface)
1087						_MaterialsSubGeometries[subGeomInd].normals = normals;
1088					else
1089						subGeom.autoDeriveVertexNormals = true;
1090					
1091					if (subGeomInd == 0) {
1092						_subGeometry = subGeom;
1093						_uvs = uvs;
1094						_vertices = vertices;
1095						_indices = indices;
1096						_normals = normals;
1097					}
1098					
1099				} else {
1100					_subGeometry = subGeom;
1101					_uvs = new Vector.<Number>();
1102					_vertices = new Vector.<Number>();
1103					_indices = new Vector.<uint>();
1104					_normals = new Vector.<Number>();
1105					uvs = _uvs;
1106					vertices = _vertices;
1107					indices = _indices;
1108					normals = _normals;
1109				}
1110			}
1111			
1112			var bv0:Boolean;
1113			var bv1:Boolean;
1114			var bv2:Boolean;
1115			
1116			var ind0:uint;
1117			var ind1:uint;
1118			var ind2:uint;
1119			
1120			if (_smoothSurface) {
1121				var uvind:uint;
1122				var uvindV:uint;
1123				var vind:uint;
1124				var vindy:uint;
1125				var vindz:uint;
1126				var ind:uint;
1127				var indlength:uint = indices.length;
1128				calcNormal(v0, v1, v2);
1129				var ab:Number;
1130				
1131				if (indlength > 0) {
1132					var back:Number = indlength - _maxIndProfile;
1133					var limitBack:uint = (back < 0)? 0 : back;
1134					
1135					for (var i:uint = indlength - 1; i > limitBack; --i) {
1136						ind = indices[i];
1137						vind = ind*3;
1138						vindy = vind + 1;
1139						vindz = vind + 2;
1140						uvind = ind*2;
1141						uvindV = uvind + 1;
1142						
1143						if (bv0 && bv1 && bv2)
1144							break;
1145						
1146						if (!bv0 && vertices[vind] == v0.x && vertices[vindy] == v0.y && vertices[vindz] == v0.z) {
1147							
1148							_normalTmp.x = normals[vind];
1149							_normalTmp.y = normals[vindy];
1150							_normalTmp.z = normals[vindz];
1151							ab = Vector3D.angleBetween(_normalTmp, _normal0);
1152							
1153							if (ab < MAXRAD) {
1154								_normal0.x = (_normalTmp.x + _normal0.x)*.5;
1155								_normal0.y = (_normalTmp.y + _normal0.y)*.5;
1156								_normal0.z = (_normalTmp.z + _normal0.z)*.5;
1157								
1158								if (uvs[uvind] == uv0.u && uvs[uvindV] == uv0.v) {
1159									bv0 = true;
1160									ind0 = ind;
1161									continue;
1162								}
1163							}
1164						}
1165						
1166						if (!bv1 && vertices[vind] == v1.x && vertices[vindy] == v1.y && vertices[vindz] == v1.z) {
1167							
1168							_normalTmp.x = normals[vind];
1169							_normalTmp.y = normals[vindy];
1170							_normalTmp.z = normals[vindz];
1171							ab = Vector3D.angleBetween(_normalTmp, _normal1);
1172							
1173							if (ab < MAXRAD) {
1174								_normal1.x = (_normalTmp.x + _normal1.x)*.5;
1175								_normal1.y = (_normalTmp.y + _normal1.y)*.5;
1176								_normal1.z = (_normalTmp.z + _normal1.z)*.5;
1177								
1178								if (uvs[uvind] == uv1.u && uvs[uvindV] == uv1.v) {
1179									bv1 = true;
1180									ind1 = ind;
1181									continue;
1182								}
1183							}
1184						}
1185						
1186						if (!bv2 && vertices[vind] == v2.x && vertices[vindy] == v2.y && vertices[vindz] == v2.z) {
1187							
1188							_normalTmp.x = normals[vind];
1189							_normalTmp.y = normals[vindy];
1190							_normalTmp.z = normals[vindz];
1191							ab = Vector3D.angleBetween(_normalTmp, _normal2);
1192							
1193							if (ab < MAXRAD) {
1194								_normal2.x = (_normalTmp.x + _normal2.x)*.5;
1195								_normal2.y = (_normalTmp.y + _normal2.y)*.5;
1196								_normal2.z = (_normalTmp.z + _normal2.z)*.5;
1197								
1198								if (uvs[uvind] == uv2.u && uvs[uvindV] == uv2.v) {
1199									bv2 = true;
1200									ind2 = ind;
1201									continue;
1202								}
1203							}
1204							
1205						}
1206					}
1207				}
1208			}
1209			
1210			if (!bv0) {
1211				ind0 = vertices.length/3;
1212				vertices.push(v0.x, v0.y, v0.z);
1213				uvs.push(uv0.u, uv0.v);
1214				if (_smoothSurface)
1215					normals.push(_normal0.x, _normal0.y, _normal0.z);
1216			}
1217			
1218			if (!bv1) {
1219				ind1 = vertices.length/3;
1220				vertices.push(v1.x, v1.y, v1.z);
1221				uvs.push(uv1.u, uv1.v);
1222				if (_smoothSurface)
1223					normals.push(_normal1.x, _normal1.y, _normal1.z);
1224			}
1225			
1226			if (!bv2) {
1227				ind2 = vertices.length/3;
1228				vertices.push(v2.x, v2.y, v2.z);
1229				uvs.push(uv2.u, uv2.v);
1230				if (_smoothSurface)
1231					normals.push(_normal2.x, _normal2.y, _normal2.z);
1232			}
1233			
1234			indices.push(ind0, ind1, ind2);
1235		}
1236		
1237		private function initHolders():void
1238		{
1239			_uvarr = new Vector.<UV>();
1240			_uva = new UV(0, 0);
1241			_uvb = new UV(0, 0);
1242			_uvc = new UV(0, 0);
1243			_uvd = new UV(0, 0);
1244			_va = new Vector3D(0, 0, 0);
1245			_vb = new Vector3D(0, 0, 0);
1246			_vc = new Vector3D(0, 0, 0);
1247			_vd = new Vector3D(0, 0, 0);
1248			_uvs = new Vector.<Number>();
1249			_vertices = new Vector.<Number>();
1250			_indices = new Vector.<uint>();
1251			_normals = new Vector.<Number>();
1252			
1253			if (_smoothSurface) {
1254				_normal0 = new Vector3D(0.0, 0.0, 0.0);
1255				_normal1 = new Vector3D(0.0, 0.0, 0.0);
1256				_normal2 = new Vector3D(0.0, 0.0, 0.0);
1257				_normalTmp = new Vector3D(0.0, 0.0, 0.0);
1258			} else
1259				_subGeometry.autoDeriveVertexNormals = true;
1260			
1261			_subGeometry.autoDeriveVertexTangents = true;
1262			
1263			if (_materials && _thickness > 0)
1264				initSubGeometryList();
1265		}
1266		
1267		private function buildThicknessPoints(aPoints:Vector.<Vector3D>, thickness:Number, prop1:String, prop2:String):Array
1268		{
1269			var anchors:Array = [];
1270			var lines:Array = [];
1271			var i:int;
1272			
1273			for (i = 0; i < aPoints.length - 1; ++i) {
1274				if (aPoints[i][prop1] == 0 && aPoints[i][prop2] == 0)
1275					aPoints[i][prop1] = EPS;
1276				if (aPoints[i + 1][prop2] != null && aPoints[i][prop2] == aPoints[i + 1][prop2])
1277					aPoints[i + 1][prop2] += EPS;
1278				if (aPoints[i][prop1] != null && aPoints[i][prop1] == aPoints[i + 1][prop1])
1279					aPoints[i + 1][prop1] += EPS;
1280				anchors.push(defineAnchors(aPoints[i], aPoints[i + 1], thickness, prop1, prop2));
1281			}
1282			
1283			var totallength:int = anchors.length;
1284			var pointResult:FourPoints;
1285			
1286			if (totallength > 1) {
1287				
1288				for (i = 0; i < totallength; ++i) {
1289					
1290					if (i < totallength)
1291						pointResult = defineLines(i, anchors[i], anchors[i + 1], lines);
1292					else
1293						pointResult = defineLines(i, anchors[i], anchors[i - 1], lines);
1294					
1295					if (pointResult != null)
1296						lines.push(pointResult);
1297				}
1298				
1299			} else {
1300				
1301				var fourPoints:FourPoints = new FourPoints();
1302				var anchorFP:FourPoints = anchors[0];
1303				fourPoints.pt1 = anchorFP.pt1;
1304				fourPoints.pt2 = anchorFP.pt2;
1305				fourPoints.pt3 = anchorFP.pt3;
1306				fourPoints.pt4 = anchorFP.pt4;
1307				lines = [fourPoints];
1308			}
1309			
1310			return lines;
1311		}
1312		
1313		private function defineLines(index:int, point1:FourPoints, point2:FourPoints = null, lines:Array = null):FourPoints
1314		{
1315			var tmppt:FourPoints;
1316			var fourPoints:FourPoints = new FourPoints();
1317			
1318			if (point2 == null) {
1319				tmppt = lines[index - 1];
1320				fourPoints.pt1 = tmppt.pt3;
1321				fourPoints.pt2 = tmppt.pt4;
1322				fourPoints.pt3 = point1.pt3;
1323				fourPoints.pt4 = point1.pt4;
1324				
1325				return fourPoints;
1326			}
1327			
1328			var line1:Line = buildObjectLine(point1.pt1.x, point1.pt1.y, point1.pt3.x, point1.pt3.y);
1329			var line2:Line = buildObjectLine(point1.pt2.x, point1.pt2.y, point1.pt4.x, point1.pt4.y);
1330			var line3:Line = buildObjectLine(point2.pt1.x, point2.pt1.y, point2.pt3.x, point2.pt3.y);
1331			var line4:Line = buildObjectLine(point2.pt2.x, point2.pt2.y, point2.pt4.x, point2.pt4.y);
1332			
1333			var cross1:Point = lineIntersect(line3, line1);
1334			var cross2:Point = lineIntersect(line2, line4);
1335			
1336			if (cross1 != null && cross2 != null) {
1337				
1338				if (index == 0) {
1339					fourPoints.pt1 = point1.pt1;
1340					fourPoints.pt2 = point1.pt2;
1341					fourPoints.pt3 = cross1;
1342					fourPoints.pt4 = cross2;
1343					
1344					return fourPoints;
1345				}
1346				
1347				tmppt = lines[index - 1];
1348				fourPoints.pt1 = tmppt.pt3;
1349				fourPoints.pt2 = tmppt.pt4;
1350				fourPoints.pt3 = cross1;
1351				fourPoints.pt4 = cross2;
1352				
1353				return fourPoints;
1354				
1355			} else
1356				return null;
1357		}
1358		
1359		private function defineAnchors(base:Vector3D, baseEnd:Vector3D, thickness:Number, prop1:String, prop2:String):FourPoints
1360		{
1361			var angle:Number = (Math.atan2(base[prop2] - baseEnd[prop2], base[prop1] - baseEnd[prop1])*180)/Math.PI;
1362			angle -= 270;
1363			var angle2:Number = angle + 180;
1364			
1365			var fourPoints:FourPoints = new FourPoints();
1366			fourPoints.pt1 = new Point(base[prop1], base[prop2]);
1367			fourPoints.pt2 = new Point(base[prop1], base[prop2]);
1368			fourPoints.pt3 = new Point(baseEnd[prop1], baseEnd[prop2]);
1369			fourPoints.pt4 = new Point(baseEnd[prop1], baseEnd[prop2]);
1370			
1371			var radius:Number = thickness*.5;
1372			
1373			fourPoints.pt1.x = fourPoints.pt1.x + Math.cos(-angle/180*Math.PI)*radius;
1374			fourPoints.pt1.y = fourPoints.pt1.y + Math.sin(angle/180*Math.PI)*radius;
1375			
1376			fourPoints.pt2.x = fourPoints.pt2.x + Math.cos(-angle2/180*Math.PI)*radius;
1377			fourPoints.pt2.y = fourPoints.pt2.y + Math.sin(angle2/180*Math.PI)*radius;
1378			
1379			fourPoints.pt3.x = fourPoints.pt3.x + Math.cos(-angle/180*Math.PI)*radius;
1380			fourPoints.pt3.y = fourPoints.pt3.y + Math.sin(angle/180*Math.PI)*radius;
1381			
1382			fourPoints.pt4.x = fourPoints.pt4.x + Math.cos(-angle2/180*Math.PI)*radius;
1383			fourPoints.pt4.y = fourPoints.pt4.y + Math.sin(angle2/180*Math.PI)*radius;
1384			
1385			return fourPoints;
1386		}
1387		
1388		private function buildObjectLine(origX:Number, origY:Number, endX:Number, endY:Number):Line
1389		{
1390			var line:Line = new Line();
1391			line.ax = origX;
1392			line.ay = origY;
1393			line.bx = endX - origX;
1394			line.by = endY - origY;
1395			
1396			return line;
1397		}
1398		
1399		private function lineIntersect(Line1:Line, Line2:Line):Point
1400		{
1401			Line1.bx = (Line1.bx == 0)? EPS : Line1.bx;
1402			Line2.bx = (Line2.bx == 0)? EPS : Line2.bx;
1403			
1404			var a1:Number = Line1.by/Line1.bx;
1405			var b1:Number = Line1.ay - a1*Line1.ax;
1406			var a2:Number = Line2.by/Line2.bx;
1407			var b2:Number = Line2.ay - a2*Line2.ax;
1408			var nzero:Number = ((a1 - a2) == 0)? EPS : a1 - a2;
1409			var ptx:Number = ( b2 - b1 )/(nzero);
1410			var pty:Number = a1*ptx + b1;
1411			
1412			if (isFinite(ptx) && isFinite(pty))
1413				return new Point(ptx, pty);
1414			else {
1415				trace("infinity");
1416				return null;
1417			}
1418		}
1419		
1420		/**
1421		 * Invalidates the geometry, causing it to be rebuilded when requested.
1422		 */
1423		private function invalidateGeometry():void
1424		{
1425			_geomDirty = true;
1426			invalidateBounds();
1427		}
1428		
1429		private function initSubGeometryList():void
1430		{
1431			var i:uint;
1432			var sglist:SubGeometryList;
1433			
1434			if (!_MaterialsSubGeometries)
1435				_MaterialsSubGeometries = new Vector.<SubGeometryList>();
1436			
1437			for (i = 0; i < 6; ++i) {
1438				sglist = new SubGeometryList();
1439				_MaterialsSubGeometries.push(sglist);
1440				sglist.id = i;
1441				if (i == 0) {
1442					sglist.subGeometry = _subGeometry;
1443					sglist.uvs = _uvs;
1444					sglist.vertices = _vertices;
1445					sglist.indices = _indices;
1446					sglist.normals = _normals;
1447				} else {
1448					sglist.uvs = new Vector.<Number>();
1449					sglist.vertices = new Vector.<Number>();
1450					sglist.indices = new Vector.<uint>();
1451					sglist.normals = new Vector.<Number>();
1452				}
1453			}
1454			
1455			var sg:SubGeometry;
1456			var prop:String;
1457			for (i = 1; i < 6; ++i) {
1458				switch (i) {
1459					case 1:
1460						prop = "back";
1461						break;
1462					case 2:
1463						prop = "left";
1464						break;
1465					case 3:
1466						prop = "right";
1467						break;
1468					case 4:
1469						prop = "top";
1470						break;
1471					case 5:
1472						prop = "bottom";
1473						break;
1474					default:
1475						prop = "front";
1476				}
1477				
1478				if (_materials[prop] && _MaterialsSubGeometries[i].subGeometry == null) {
1479					sglist = _MaterialsSubGeometries[i];
1480					sg = new SubGeometry();
1481					sglist.material = _materials[prop];
1482					sglist.subGeometry = sg;
1483					sg.autoDeriveVertexNormals = true;
1484					sg.autoDeriveVertexTangents = true;
1485					
1486				}
1487			}
1488		
1489		}
1490	}
1491}
1492
1493import away3d.core.base.SubGeometry;
1494import away3d.materials.MaterialBase;
1495
1496import flash.geom.Point;
1497
1498class SubGeometryList
1499{
1500	public var id:uint;
1501	public var uvs:Vector.<Number>;
1502	public var vertices:Vector.<Number>;
1503	public var normals:Vector.<Number>;
1504	public var indices:Vector.<uint>;
1505	public var subGeometry:SubGeometry;
1506	public var material:MaterialBase;
1507	
1508	public function SubGeometryList()
1509	{
1510	}
1511}
1512
1513class RenderSide
1514{
1515	public var top:Boolean;
1516	public var bottom:Boolean;
1517	public var right:Boolean;
1518	public var left:Boolean;
1519	public var front:Boolean;
1520	public var back:Boolean;
1521	
1522	public function RenderSide()
1523	{
1524	}
1525}
1526
1527class Line
1528{
1529	public var ax:Number;
1530	public var ay:Number;
1531	public var bx:Number;
1532	public var by:Number;
1533	
1534	public function Line()
1535	{
1536	}
1537}
1538
1539class FourPoints
1540{
1541	public var pt1:Point;
1542	public var pt2:Point;
1543	public var pt3:Point;
1544	public var pt4:Point;
1545	
1546	public function FourPoints()
1547	{
1548	}
1549}
1550