package { import flash.display.GraphicsTrianglePath; import flash.display.Sprite; import flash.display.TriangleCulling; import flash.events.Event; import flash.geom.Vector3D; /** * @author:Gaara * 2012-3-14 * **/ [SWF(width="800", height="600" ,frameRate="30", backgroundColor="#FFFFFF")] public class DrawBall extends Sprite { private const D:int = 300; //定义路径类 private var triangPath:GraphicsTrianglePath; private var sprite:Sprite = new Sprite; private var indices:Vector.<int> = new Vector.<int>; private var uvtData:Vector.<Number> = new Vector.<Number>; private var vertices:Vector.<Vector3D> = new Vector.<Vector3D>; private var angel:int = 0; private const RADIUS:int = 100;//半径 private var cols:int = 20;//分成多少份 private var rows:int = 20; private var radian:Number = 2 * Math.PI / cols;//弧度 public function DrawBall() { sprite.x = this.stage.stageWidth / 2; sprite.y = this.stage.stageHeight /2; addChild(sprite); for (var i:int = 0;i < rows; i++) { for (var i2:int = 0; i2 < cols; i2++) { var angel2:Number = i2 * Math.PI / cols - Math.PI/2; var before:Vector3D = new Vector3D( Math.cos(radian * i) * RADIUS * Math.cos(angel2), Math.sin(angel2) * RADIUS, Math.sin(radian * i) * RADIUS * Math.cos(angel2)); vertices.push(before); uvtData.push(i2/cols,i/rows,1); } } for (var j:int = 0;j < rows; j++) { for (var k:int = 0; k < cols; k++) { //前面的点 if(j<rows-1 && k < cols-1){ indices.push(j*cols+k,j*cols+k+1,(j+1)*cols+k); indices.push(j*cols+k+1,(j+1)*cols+k+1,(j+1)*cols+k); } } } addEventListener(Event.ENTER_FRAME,onEnterFrame); } protected function onEnterFrame(event:Event):void { angel++; var radianx:Number = mouseX /180*Math.PI; var radiany:Number = mouseY /180*Math.PI; var newVertices:Vector.<Number> = new Vector.<Number>; for (var i:int = 0; i < vertices.length; i++) { var vec3d:Vector3D = vertices[i] var newX:Number = Math.cos(radianx) * vec3d.x - Math.sin(radianx) * vec3d.z; var newZ:Number = Math.cos(radianx) * vec3d.z + Math.sin(radianx) * vec3d.x; var newX2:Number = Math.cos(radiany) * newX - Math.sin(radiany) * vec3d.y; var newY:Number = Math.cos(radiany) * vec3d.y + Math.sin(radiany) * newX; var scale:Number = D/(D+newZ); uvtData[i*3+2] = scale; newVertices.push(scale * newX2); newVertices.push(scale * newY); } sprite.graphics.clear(); sprite.graphics.beginBitmapFill(ResConfig.myLpBmp.bitmapData); sprite.graphics.drawTriangles(newVertices,indices,uvtData,TriangleCulling.POSITIVE); sprite.graphics.endFill(); } } }
仔细观察发现还有不少问题。最后一列没有接上。然后绘制成网格观察。
最后加上接边的代码,调整网格大小后,终于成形。
package { import flash.display.GraphicsTrianglePath; import flash.display.Sprite; import flash.display.TriangleCulling; import flash.events.Event; import flash.geom.Vector3D; /** * @author:Gaara * 2012-3-14 * **/ [SWF(width="800", height="600" ,frameRate="30", backgroundColor="#000000")] public class DrawBall extends Sprite { private const D:int = 300; //定义路径类 private var triangPath:GraphicsTrianglePath; private var sprite:Sprite = new Sprite; private var indices:Vector.<int> = new Vector.<int>; private var uvtData:Vector.<Number> = new Vector.<Number>; private var vertices:Vector.<Vector3D> = new Vector.<Vector3D>; private var angel:int = 0; private const RADIUS:int = 100;//半径 private var cols:int = 40;//分成多少份 private var rows:int = 40; private var radian:Number = 2 * Math.PI / cols;//弧度 public function DrawBall() { sprite.x = this.stage.stageWidth / 2; sprite.y = this.stage.stageHeight /2; addChild(sprite); for (var i:int = 0;i < rows; i++) { var newRadian:Number = Math.PI / (cols -1) * i - Math.PI / 2; var x1:Number = Math.cos(newRadian) * RADIUS ;//减去90度。从最上面开始,计算出圆环的半径 for (var i2:int = 0; i2 < cols; i2++) { var angel2:Number = i2 * radian; var before:Vector3D = new Vector3D( x1* Math.cos(angel2), Math.sin(newRadian) * RADIUS, x1 * Math.sin(angel2)); vertices.push(before); trace(" y:"+before.y + "x:"+ before.x + "z:"+before.z); uvtData.push(i2/cols,i/rows,1); } } for (var j:int = 0;j < rows; j++) { for (var k:int = 0; k < cols; k++) { //前面的点 if(j<(rows - 1) && k <(cols - 1)){ indices.push(j*cols+k,(j+1)*cols+k+1,(j+1)*cols+k); indices.push(j*cols+k,j*cols+k+1,(j+1)*cols+k+1); } else if(k == (cols -1)){ indices.push(j*cols+k,(j+1)*cols,(j+1)*cols+k); indices.push(j*cols+k,j*cols,(j+1)*cols); } } } addEventListener(Event.ENTER_FRAME,onEnterFrame); } protected function onEnterFrame(event:Event):void { angel++; var radianx:Number = mouseX /180*Math.PI; var radiany:Number = mouseY /180*Math.PI; var newVertices:Vector.<Number> = new Vector.<Number>; for (var i:int = 0; i < vertices.length; i++) { var vec3d:Vector3D = vertices[i] var newX:Number = Math.cos(radianx) * vec3d.x - Math.sin(radianx) * vec3d.z; var newZ:Number = Math.cos(radianx) * vec3d.z + Math.sin(radianx) * vec3d.x; var newX2:Number = Math.cos(radiany) * newX - Math.sin(radiany) * vec3d.y; var newY:Number = Math.cos(radiany) * vec3d.y + Math.sin(radiany) * newX; var scale:Number = D/(D+newZ); uvtData[i*3+2] = scale; newVertices.push(scale * newX2); newVertices.push(scale * newY); } sprite.graphics.clear(); sprite.graphics.beginBitmapFill(ResConfig.myLpBmp.bitmapData); // sprite.graphics.lineStyle(1,0xFF0000); sprite.graphics.drawTriangles(newVertices,indices,uvtData,TriangleCulling.NEGATIVE); sprite.graphics.endFill(); } } }
绘制方法
先将球形横切n刀,然后使用公式
var newRadian:Number = Math.PI / (cols -1) * i - Math.PI / 2;
计算出从最上方的点到最下方的点的弧度,切出来的面每个点的y坐标都相等。Math.sin(newRadian) * RADIUS,
然后再计算圆上的坐标确定x,z;这部分以及索引以绘制圆筒相同。