package away3d.extrusions { import away3d.core.math.*; import away3d.containers.*; import away3d.core.base.*; import away3d.materials.*; import away3d.core.utils.*; import flash.geom.Point; public class SegmentsExtrude extends Mesh { private var varr:Array = new Array(); private var varr2:Array = new Array(); private var uvarr:Array = new Array(); public function SegmentsExtrude(aPoints:*, init:Object = null) { if(init.material != null) init.materials = {defaultmaterial:init.material}; if(init.material == null && init.materials != null) init.material = init.materials.defaultmaterial; init = Init.parse(init); super(init); var axis:String = init.getString("axis", "y"); var offset:Number = init.getNumber("offset", 10); var subdivision:int = init.getInt("subdivision", 1, {min:1}); var thickness:Number = Math.abs(init.getNumber("thickness", 0)); var thickness_subdivision:Number = init.getInt("thickness_subdivision", 1, {min:1}); var flip:Boolean = init.getBoolean("flip", false); var scaling:Number = init.getNumber("scaling", 1); var oMat:Object = init.getObject("materials", null); var omit:String = init.getString("omit", ""); var coverall:Boolean = init.getBoolean("coverall", false); var recenter:Boolean = init.getBoolean("recenter", false); var closepath:Boolean = init.getBoolean("closepath", false); if(closepath) omit += "left,right"; if(aPoints[0] is Array){ //in case more extrudes are done in one mesh for(var i:int = 0;i 1){ varr = new Array(); varr2 = new Array(); uvarr = new Array(); generate(aPoints[i], oMat, axis, offset, subdivision, thickness, thickness_subdivision, scaling, omit, coverall, closepath, flip); } else { trace("SegmentsExtrude error: at index "+i+" , at least 2 points are required per extrude!"); } } }else{ if(closepath) aPoints.push(new Number3D(aPoints[0].x, aPoints[0].y, aPoints[0].z)); if(aPoints.length > 1){ generate(aPoints, oMat, axis, offset, subdivision, thickness, thickness_subdivision, scaling, omit, coverall, closepath, flip); } else { trace("SegmentsExtrude error: at least 2 points in an array are required per extrude!"); } } if(recenter) { applyPosition((this.minX+this.maxX)*.5, (this.minY+this.maxY)*.5, (this.minZ+this.maxZ)*.5); } else { var isArr:Boolean = (aPoints[0] is Array); x = (isArr)? aPoints[0][0].x : aPoints[0].x; y = (isArr)? aPoints[0][0].y : aPoints[0].y; z = (isArr)? aPoints[0][0].z : aPoints[0].z; } varr = null; varr2 = null; uvarr = null; type = "SegmentsExtrude"; url = "Extrude"; } private function generate(points:Array, oMat:Object = null, axis:String = "y", origoffset:Number = 0, subdivision:int = 1, thickness:Number = 0, thickness_subdivision:int = 1, scaling:Number = 1, omit:String = "", coverall:Boolean = false, closepath:Boolean = false, flip:Boolean = false):void { var i:int; var j:int; var vector:Object; var vector2:Object; var increase:Number = (subdivision == 1)? origoffset : origoffset/subdivision; var basemaxX:Number = points[0].x; var baseminX:Number = points[0].x; var basemaxY:Number = points[0].y; var baseminY:Number = points[0].y; var basemaxZ:Number = points[0].z; var baseminZ:Number = points[0].z; for (i = 0; i < points.length; i++) { if(scaling != 1){ points[i].x *= scaling; points[i].y *= scaling; points[i].z *= scaling; } basemaxX = Math.max(points[i].x, basemaxX); baseminX = Math.min(points[i].x, baseminX); basemaxY = Math.max(points[i].y, basemaxY); baseminY = Math.min(points[i].y, baseminY); basemaxZ = Math.max(points[i].z, basemaxZ); baseminZ = Math.min(points[i].z, baseminZ); } var basemax:Number; var basemin:Number; var offset:Number = 0; switch(axis){ case "x": basemax = Math.abs(basemaxX) - Math.abs(baseminX); if(baseminZ >0 && basemaxZ >0){ basemin = basemaxZ - baseminZ; offset = -baseminZ; }else if(baseminZ <0 && basemaxZ <0){ basemin = Math.abs(baseminZ - basemaxZ); offset = -baseminZ; }else{ basemin = Math.abs(basemaxZ) + Math.abs(baseminZ); offset = Math.abs(baseminZ)+((basemaxZ<0)? -basemaxZ: 0); } break; case "y": basemax = Math.abs(basemaxY) - Math.abs(baseminY); if(baseminX >0 && basemaxX >0){ basemin = basemaxX - baseminX; offset = -baseminX; }else if(baseminX <0 && basemaxX <0){ basemin = Math.abs(baseminX - basemaxX); offset = -baseminX; }else{ basemin = Math.abs(basemaxX) + Math.abs(baseminX); offset = Math.abs(baseminX)+((basemaxX<0)? -basemaxX: 0); } break; case "z": basemax = Math.abs(basemaxZ) - Math.abs(baseminZ); if(baseminY >0 && basemaxY >0){ basemin = basemaxY - baseminY; offset = -baseminY; }else if(baseminY <0 && basemaxY <0){ basemin = Math.abs(baseminY - basemaxY); offset = -baseminY; }else{ basemin = Math.abs(basemaxY) + Math.abs(baseminY); offset = Math.abs(baseminY)+((basemaxY<0)? -basemaxY: 0); } break; } var Lines:Array; var prop1:String; var prop2:String; var prop3:String; var aListsides:Array = ["top","bottom", "right", "left", "front", "back"]; if(thickness != 0) { var oRenderside:Object = {}; for(i = 0;i1){ for(i = 0;i 2){ Anchors.push(defineAnchors(aPoints[Anchors.length-1], aPoints[0], thickness, prop1, prop2 )); var tmparray:Array = [Anchors[Anchors.length-1], Anchors[0] , Anchors[1], Anchors[2] ]; var tmplines:Array = new Array() for(i = 0;i<2;i++){ oPointResult = defineLines(i, totallength, tmparray[i], tmparray[i+1], tmparray); if(oPointResult != null) tmplines.push(oPointResult); } Lines[0].pt1 = tmplines[0].pt3; Lines[0].pt2 = tmplines[0].pt4; Lines[0].pt3 = tmplines[1].pt1; Lines[0].pt4 = tmplines[1].pt2; Lines[Lines.length-1].pt3 = tmplines[0].pt3; Lines[Lines.length-1].pt4 = tmplines[0].pt4; } } else{ Lines = [{pt1:Anchors[0].pt1, pt2:Anchors[0].pt2, pt3:Anchors[0].pt3, pt4:Anchors[0].pt4}]; } return Lines; } private function defineLines(index:int, maxindex:int, oPoint1:Object, oPoint2:Object = null, Lines:Array = null):Object { var tmppt = Lines[index -1]; if(oPoint2 == null) return {pt1:tmppt.pt3, pt2:tmppt.pt4, pt3:oPoint1.pt3, pt4:oPoint1.pt4}; var oLine1:Object = buildObjectLine(oPoint1.pt1.x,oPoint1.pt1.y,oPoint1.pt3.x,oPoint1.pt3.y); var oLine2:Object = buildObjectLine(oPoint1.pt2.x,oPoint1.pt2.y,oPoint1.pt4.x,oPoint1.pt4.y); var oLine3:Object = buildObjectLine(oPoint2.pt1.x,oPoint2.pt1.y,oPoint2.pt3.x,oPoint2.pt3.y); var oLine4:Object = buildObjectLine(oPoint2.pt2.x,oPoint2.pt2.y,oPoint2.pt4.x,oPoint2.pt4.y); var cross1:Point = lineIntersect (oLine3, oLine1); var cross2:Point = lineIntersect (oLine2, oLine4); if(cross1 != null && cross2 != null){ if(index == 0) return {pt1:oPoint1.pt1, pt2:oPoint1.pt2, pt3:cross1, pt4:cross2}; return {pt1:tmppt.pt3, pt2:tmppt.pt4, pt3:cross1, pt4:cross2}; } else { return null; } } private function defineAnchors(base:Number3D, baseEnd:Number3D, thickness:Number, prop1:String, prop2:String):Object { var angle = (Math.atan2(base[prop2] - baseEnd[prop2], base[prop1] - baseEnd[prop1])* 180)/ Math.PI; angle -=270; var angle2 = angle+180; //origin points var pt1:Point = new Point(base[prop1], base[prop2]); var pt2:Point = new Point(base[prop1], base[prop2]); //dest points var pt3:Point = new Point(baseEnd[prop1], baseEnd[prop2]); var pt4:Point = new Point(baseEnd[prop1], baseEnd[prop2]); var radius:Number = thickness*.5; pt1.x = pt1.x+Math.cos(-angle/180*Math.PI)*radius; pt1.y = pt1.y+Math.sin(angle/180*Math.PI)*radius; pt2.x = pt2.x+Math.cos(-angle2/180*Math.PI)*radius; pt2.y = pt2.y+Math.sin(angle2/180*Math.PI)*radius; pt3.x = pt3.x+Math.cos(-angle/180*Math.PI)*radius; pt3.y = pt3.y+Math.sin(angle/180*Math.PI)*radius; pt4.x = pt4.x+Math.cos(-angle2/180*Math.PI)*radius; pt4.y = pt4.y+Math.sin(angle2/180*Math.PI)*radius; return {pt1:pt1, pt2:pt2, pt3:pt3, pt4:pt4}; } private function buildObjectLine(origX:Number, origY:Number, endX:Number, endY:Number):Object { return {ax:origX, ay:origY, bx:endX - origX, by:endY - origY}; } private function lineIntersect (Line1:Object, Line2:Object):Point { Line1.bx = (Line1.bx == 0)? 0.0001 : Line1.bx; Line2.bx = (Line2.bx == 0)? 0.0001 : Line2.bx; var a1:Number = Line1.by / Line1.bx; var b1:Number = Line1.ay - a1 * Line1.ax; var a2:Number = Line2.by / Line2.bx; var b2:Number = Line2.ay - a2 * Line2.ax; var nzero:Number = ((a1 - a2) == 0)? 0.0001 : a1 - a2; var ptx:Number = ( b2 - b1 )/(nzero); var pty:Number = a1 * ptx + b1; if(isFinite(ptx) && isFinite(pty)){ return new Point(ptx, pty); } else { trace("infinity"); return null; } } } }