/* ActionScript 3 Tutorials by Doug Ensley and Barbara Kaskosz. www.flashandmath.com Last modified: September 23, 2007. */ /* In this part of the tutorial, we draw a partially open sphere. We incorporate the same ideas as in the previous parts. The main difference is that instead of a collection of vertices and faces we use a two-dimensional array of vertices, tilesArray. Each element, tilesArray[i][j], represents a vertex. To each vertex (except when i or j are at their maximum) there corresponds a face whose vertices are tilesArray[i][j], tilesArray[i+1][j], tilesArray[i][j+1], tilesArray[i+1][j+1]. This way, it is sufficient to remember the array of vertices and the faces are already defined. Each face corresponds to an i,j vertex. i and j range from 0 to a fixed integer stored in the variable nMesh below. For parametric surfaces, x=x(t,s), y=y(t,s), z=z(t,s), i and j correspond to consecutive values of the parameters t and s. Below we comment only on the portions of the code that are new to this part of the tutorial. */ var fLen:Number=2000; var spBoard:Sprite=new Sprite(); this.addChild(spBoard); spBoard.x=200; spBoard.y=190; var shBack:Shape=new Shape(); spBoard.addChild(shBack); drawBack(); var shCube:Shape=new Shape(); spBoard.addChild(shCube); var doRotate:Boolean=false; var prevX:Number; var prevY:Number; var curTheta:Number=-10; var curPhi:Number=60; /* The size of tilesArray is stored in nMesh. We choose 30 by 30 which is usually enough to produce a smooth surface. */ var nMesh:Number=30; //The array of vertices. var tilesArray:Array=[]; //A Boolean variable that locks coloring after renderView runs once. var firstRun:Boolean=true; /* The next array stores colors for our faces. You can be very creative changing this array. */ var tilesColors:Array=[]; function drawBack():void { shBack.graphics.lineStyle(1,0x000000); shBack.graphics.beginFill(0x000000); shBack.graphics.drawRect(-160,-160,320,320); shBack.graphics.endFill(); } /* setTilesArray function called here and defined below defines the vertices for our surface. The renderView function is very similar as before. */ setTilesArray(); renderView(curTheta,curPhi); /* In setTilesArray we define vertices that correspond to a parametrized sphere with radius 90. i and j serve as sample values for the parameters. i changes between 0 and 7/4*pi to keep the sphere open, j from 0 to pi. (Of course i and j correspond to the parametrization of the sphere by spherical coordinates theta and phi.) */ function setTilesArray():void { var i:int; var j:int; var istep:Number; var jstep:Number; istep=(7/4)*Math.PI/nMesh; jstep=Math.PI/nMesh; for(i=0;i<=nMesh;i++){ tilesArray[i]=[]; for(j=0;j<=nMesh;j++){ tilesArray[i][j]=[90*Math.cos(istep*i)*Math.sin(jstep*j),90*Math.sin(istep*i)*Math.sin(jstep*j),90*Math.cos(jstep*j)]; } } } /* The changes in renderView function correspond to the fact that tilesArray is two-dimensional as well as dispArray. Thus, there are two indices i and j in every loop. distArray keeps track of the distances from the observer of all nMesh*nMesh midpoints. Each element of distArray is the form [dist,i,j]. After sorting the distArray, we know which face corresponding to a vertex i,j is behind and which is in front. After renderView runs once firstRun variable is set to false so tiles colors assignment will happen only once. */ function renderView(t:Number,p:Number):void { var i:int; var j:int; var n:int; var distArray=[]; var dispArray=[]; var tilesNewArray=[]; var midPoint:Array=[]; var dist:Number; var depLen:Number; var coloFactor=1.2; t=t*Math.PI/180; p=p*Math.PI/180; shCube.graphics.clear(); for(i=0;i<=nMesh;i++){ tilesNewArray[i]=[]; for(j=0;j<=nMesh;j++){ tilesNewArray[i][j]=pointNewView(tilesArray[i][j],t,p); } } for(i=0;iw[0]){ return -1; } else if (v[0]255){red=255;} if(green>255){green=255;} if(blue>255){blue=255;} if(red<0){red=0;} if(green<0){green=0;} if(blue<0){blue=0;} RGB=(red<<16) | (green<<8) | blue; return RGB; } spBoard.addEventListener(MouseEvent.ROLL_OUT,boardOut); spBoard.addEventListener(MouseEvent.MOUSE_MOVE,boardMove); spBoard.addEventListener(MouseEvent.MOUSE_DOWN,boardDown); spBoard.addEventListener(MouseEvent.MOUSE_UP,boardUp); function boardOut(e:MouseEvent):void { doRotate=false; } function boardDown(e:MouseEvent):void { prevX=spBoard.mouseX; prevY=spBoard.mouseY; doRotate=true; } function boardUp(e:MouseEvent):void { doRotate=false; } function boardMove(e:MouseEvent):void { var locX:Number=prevX; var locY:Number=prevY; if(doRotate){ prevX=spBoard.mouseX; prevY=spBoard.mouseY; curTheta+=(prevX-locX); curPhi+=(prevY-locY); renderView(curTheta,curPhi); e.updateAfterEvent(); } }