package away3d.extrusions{ import away3d.core.math.Number3D; import away3d.core.base.*; import away3d.arcane; import away3d.materials.*; import away3d.core.utils.Init; import away3d.core.math.MatrixAway3D; import away3d.animators.data.Path; import away3d.animators.utils.PathUtils; import away3d.animators.data.CurveSegment; use namespace arcane; public class PathExtrude extends Mesh { private var varr:Array; private var xAxis:Number3D = new Number3D(); private var yAxis:Number3D = new Number3D(); private var zAxis:Number3D = new Number3D(); private var _worldAxis:Number3D = new Number3D(0,1,0); private var _transform:MatrixAway3D = new MatrixAway3D(); private var _path:Path; private var _points:Array; private var _scales:Array; private var _rotations:Array; private var _subdivision:int = 2; private var _scaling:Number = 1; private var _coverall:Boolean = true; private var _recenter:Boolean = false; private var _flip:Boolean = false; private var _closepath:Boolean = false; private var _aligntopath:Boolean = true; private var _smoothscale:Boolean = true; private var _isClosedProfile:Boolean = false; private var _doubles:Array = []; private function orientateAt(target:Number3D, position:Number3D):void { zAxis.sub(target, position); zAxis.normalize(); if (zAxis.modulo > 0.1) { xAxis.cross(zAxis, _worldAxis); xAxis.normalize(); yAxis.cross(zAxis, xAxis); yAxis.normalize(); _transform.sxx = xAxis.x; _transform.syx = xAxis.y; _transform.szx = xAxis.z; _transform.sxy = -yAxis.x; _transform.syy = -yAxis.y; _transform.szy = -yAxis.z; _transform.sxz = zAxis.x; _transform.syz = zAxis.y; _transform.szz = zAxis.z; } } private function generate(points:Array, coverall:Boolean = false, closepath:Boolean = false, flip:Boolean = false):void { var uvlength:int = points.length-1; for(var i:int = 0;i< points.length-1;++i){ varr = new Array(); extrudePoints( points[i], points[i+1], 1, coverall, (1/uvlength)*i, uvlength, flip); if(i ==0 && _isClosedProfile){ _doubles = varr.concat(); } } varr = null; _doubles = null; } private function extrudePoints(points1:Array, points2:Array, subdivision:int, coverall:Boolean, vscale:Number, indexv:int, flip:Boolean):void { var i:int; var j:int; var stepx:Number; var stepy:Number; var stepz:Number; var uva:UV; var uvb:UV; var uvc:UV; var uvd:UV; var va:Vertex; var vb:Vertex; var vc:Vertex; var vd:Vertex; var u1:Number; var u2:Number; var index:int = 0; var bu:Number = 0; var bincu = 1/(points1.length-1); var v1:Number = 0; var v2:Number = 0; function getDouble(x:Number, y:Number, z:Number ):Vertex { for(var i:int = 0;i<_doubles.length; ++i){ if( _doubles[i].x == x && _doubles[i].y == y && _doubles[i].z == z){ return _doubles[i]; } } return new Vertex( x, y, z); } for( i = 0; i < points1.length; ++i){ stepx = (points2[i].x - points1[i].x) / subdivision; stepy = (points2[i].y - points1[i].y) / subdivision; stepz = (points2[i].z - points1[i].z) / subdivision; for( j = 0; j < subdivision+1; ++j){ if(_isClosedProfile && _doubles.length > 0){ varr.push( getDouble(points1[i].x+(stepx*j) , points1[i].y+(stepy*j), points1[i].z+(stepz*j) ) ); } else { varr.push( new Vertex( points1[i].x+(stepx*j) , points1[i].y+(stepy*j), points1[i].z+(stepz*j)) ); } } } for( i = 0; i < points1.length-1; ++i){ u1 = bu; bu += bincu; u2 = bu; for( j = 0; j < subdivision; ++j){ v1 = (coverall)? vscale+((j/subdivision)/indexv) : j/subdivision; v2 = (coverall)? vscale+(( (j+1)/subdivision)/indexv) : (j+1)/subdivision; uva = new UV( u1 , v1); uvb = new UV( u1 , v2 ); uvc = new UV( u2 , v2 ); uvd = new UV( u2 , v1 ); va = varr[index+j]; vb = varr[(index+j) + 1]; vc = varr[((index+j) + (subdivision + 2))]; vd = varr[((index+j) + (subdivision + 1))]; if(flip){ addFace(new Face(vb,va,vc, null, uvb, uva, uvc )); addFace(new Face(vc,va,vd, null, uvc, uva, uvd)); }else{ addFace(new Face(va,vb,vc, null, uva, uvb, uvc )); addFace(new Face(va,vc,vd, null, uva, uvc, uvd)); } } index += subdivision +1; } } /** * Creates a new PathExtrude * * @param path A Path object. The _path definition. * @param points An array containing a series of Number3D's. Defines the profile to extrude on the _path definition. * @param scales [optional] An array containing a series of Number3D [Number3D(1,1,1)]. Defines the scale per segment. Init object smoothscale true smooth the scale across the segments, set to false the scale is applied equally to the whole segment, default is true. * @param rotations [optional] An array containing a series of Number3D [Number3D(0,0,0)]. Defines the rotation per segment. Default is null. Note that last value entered is reused for the next segment. * @param init [optional] An initialisation object for specifying default instance properties. * */ function PathExtrude(path:Path=null, points:Array=null, scales:Array=null, rotations:Array=null, init:Object = null) { _path = path; _points = points; _scales = scales; _rotations = rotations; init = Init.parse(init); super(init); _subdivision = init.getInt("subdivision", 2, {min:2}); _scaling = init.getNumber("scaling", 1); _coverall = init.getBoolean("coverall", true); _recenter = init.getBoolean("recenter", false); _flip = init.getBoolean("flip", false); _closepath = init.getBoolean("closepath", false); _aligntopath = init.getBoolean("aligntopath", true); _smoothscale = init.getBoolean("smoothscale", true); if(_points!= null){ _isClosedProfile = (points[0].x == points[points.length-1].x && points[0].y == points[points.length-1].y && points[0].z == points[points.length-1].z); } if(_path != null && _points!= null) build(); } /** * Builds the PathExtrude object. */ public function build():void { if(_path.length != 0 && _points.length >=2){ _worldAxis = _path.worldAxis; if(_closepath){ var ref:CurveSegment = _path.array[_path.array.length-1]; var vc:Number3D = new Number3D( (_path.array[0].vc.x+ref.vc.x)*.5, (_path.array[0].vc.y+ref.vc.y)*.5, (_path.array[0].vc.z+ref.vc.z)*.5 ); _path.add( new CurveSegment( _path.array[0].v1, vc, _path.array[0].v0 ) ); if(_path.smoothed){ var tpv1:Number3D = new Number3D((_path.array[0].v0.x+_path.array[_path.length-1].v0.x)*.5, (_path.array[0].v0.y+_path.array[_path.length-1].v0.y)*.5, (_path.array[0].v0.z+_path.array[_path.length-1].v0.z)*.5); var tpv2:Number3D = new Number3D((_path.array[0].v0.x+_path.array[0].v1.x)*.5, (_path.array[0].v0.y+_path.array[0].v1.y)*.5, (_path.array[0].v0.z+_path.array[0].v1.z)*.5); _path.array[_path.length-1].vc.x = tpv1.x; _path.array[_path.length-1].vc.y = tpv1.y; _path.array[_path.length-1].vc.z = tpv1.z; _path.array[_path.length-1].v1.x = (_path.array[0].v0.x+_path.array[0].v1.x)*.5; _path.array[_path.length-1].v1.y = (_path.array[0].v0.y+_path.array[0].v1.y)*.5; _path.array[_path.length-1].v1.z = (_path.array[0].v0.z+_path.array[0].v1.z)*.5; _path.array[0].v0.x = _path.array[_path.length-1].vc.x; _path.array[0].v0.y = _path.array[_path.length-1].vc.y; _path.array[0].v0.z = _path.array[_path.length-1].vc.z; _path.array[0].vc.x = tpv2.x; _path.array[0].vc.y = tpv2.y; _path.array[0].vc.z = tpv2.z; tpv1 = null; tpv2 = null; } } var aSegPoints:Array = PathUtils.getPointsOnCurve(_path, _subdivision); var aPointlist:Array = []; var aSegresult:Array = []; var atmp:Array; var tmppt:Number3D = new Number3D(0,0,0); var i:int; var j:int; var k:int; var nextpt:Number3D; var lastscale:Number3D = new Number3D(1, 1, 1); var rescale:Boolean = (_scales != null); var rotate:Boolean = (_rotations != null); if(rotate && _rotations.length > 0){ var lastrotate:Number3D = _rotations[0] ; var nextrotate:Number3D; var aRotates:Array = []; var tweenrot:Number3D; } if(_smoothscale && rescale){ var nextscale:Number3D = new Number3D(1, 1, 1); var aScales:Array = []; } for (i = 0; i