Flash10で球体の作成
Flash10で球体の作成をしてみました。
こんな感じ。
http://moeten.info/flex/20081016_fp10Test/bin-release/test04.html
参考サイト(っというかそのまま)
Enhanced Drawing API
ソースはこちら
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" width="800" height="600" backgroundGradientColors="[0x000000,0xcccccc]" > <mx:Script> <![CDATA[ //初期化関数 private var globe:Shape; private function init():void{ // 地球作成 globe = new Shape(); globe.x = 275; globe.y = 200; myUI.addChild(globe); //地球データーの作成 setGlobeData(); // 毎フレーム描画 addEventListener(Event.ENTER_FRAME, render ); // マウスダウン・アップイベント addEventListener(MouseEvent.MOUSE_DOWN, toggleStroke); addEventListener(MouseEvent.MOUSE_UP , toggleStroke); } //描画 private function render(event:Event):void { //GraphicsTrianglePathのデーターから3Dへ変換 transformIn3D(triangles, vectors3D, focal, getTimer()/1000); //一旦クリア globe.graphics.clear(); //一気に描画 globe.graphics.drawGraphicsData(globeData); } //マウスイベント private function toggleStroke(event:MouseEvent):void { //マウスダウンでラインのサイズを指定 GraphicsStroke(globeData[0]).thickness = (event.type == MouseEvent.MOUSE_DOWN) ? 1 : NaN; } /***********************************************\ * 球体 \***********************************************/ // グローバル変数 [Embed(source="map.png")]private var Erf:Class;//テクスチャ private var focal:Number = 300;//? private var globeRadius:Number = 100;//半径 private var globeParallels:int = 10;//縦ライン private var globeMeridians:int = 20;//横ライン private var frontFace:BitmapData = Bitmap(new Erf()).bitmapData;//表面用テクスチャ private var backFace:BitmapData = getDarkerBitmap(frontFace, .25);//背面用テクスチャ private var globeData:Vector.<IGraphicsData>; private var triangles:GraphicsTrianglePath; private var vectors3D:Vector.<Vector3D>; private function setGlobeData():void{ triangles = new GraphicsTrianglePath( new Vector.<Number>(), new Vector.<int>(), new Vector.<Number>(), TriangleCulling.NEGATIVE); vectors3D = new Vector.<Vector3D>(); createSphere(triangles, vectors3D, globeRadius, globeParallels, globeMeridians); var trianglesDark:GraphicsTrianglePath = new GraphicsTrianglePath( triangles.vertices, triangles.indices, triangles.uvtData, TriangleCulling.POSITIVE); globeData = Vector.<IGraphicsData>([ new GraphicsStroke(NaN, false, "normal", "none", "round", 3, new GraphicsSolidFill(0xFF0000)), new GraphicsBitmapFill(backFace, null, false, true), trianglesDark, new GraphicsBitmapFill(frontFace, null, false, true), triangles ]); } // 球を作成 private function createSphere(trianglePathOut:GraphicsTrianglePath, vertices3DOut:Vector.<Vector3D>, radius:Number = 100, parallels:int = 5, meridians:int = 10):void { if (parallels < 3) parallels = 3; if (meridians < 3) meridians = 3; meridians++; // テクスチャのエッジtexture edge meridian duplicated var parallelStops:int = parallels-1; // uの決定用 var meridianStops:int = meridians-1; // vの決定用 // ローカル変数 var r:Number; // 半径 var x:Number, y:Number, z:Number; // coordinates var p:int, pi:int, pa:Number; // parallel vars var m:int, mi:int, ma:Number; // meridian vars var u:Number, v:Number; // u, v of uvt var n:int = -1; // 頂点インデックス // 横方向 for (p=0; p<parallels; p++){ v = p/parallelStops; pa = v*Math.PI - Math.PI/2; y = radius*Math.sin(pa); r = radius*Math.cos(pa); // 縦方向 for (m=0; m<meridians; m++){ u = m/meridianStops; ma = u*Math.PI*2; x = r*Math.cos(ma); z = r*Math.sin(ma); // 頂点 vertices3DOut[++n] = new Vector3D(x,y,z); // 三角パスアウト trianglePathOut.vertices.push(x, y); trianglePathOut.uvtData.push(u, v, 1); if (m != 0){ // not first meridian (texture edge) if (p != parallelStops){ // not last parallel (no next parallel to connect) trianglePathOut.indices.push(n, n+meridians, n+meridians-1); trianglePathOut.indices.push(n, n+meridians-1, n-1); } } } } } // コンバーター。GraphicsTrianglePathのデーターから3Dへ private function transformIn3D(trianglePathOut:GraphicsTrianglePath, vertices3DIn:Vector.<Vector3D>, focal:Number, rotationY:Number):void { // Yの回転方向についての角度計算 var ca:Number = Math.cos(rotationY); var sa:Number = Math.sin(rotationY); var t:Number; var i:int, n:int = vertices3DIn.length; for (i=0; i<n; i++){ // Y軸周りのポイント変換 var x:Number = vertices3DIn[i].x*ca - vertices3DIn[i].z*sa; var z:Number = vertices3DIn[i].x*sa + vertices3DIn[i].z*ca; // 3D 奥行き t = focal/(focal + z); // trianglePathOutの設定 trianglePathOut.uvtData[i*3 + 2] = t; // テクスチャ用のperspective trianglePathOut.vertices[i*2] = x * t; // perspective x trianglePathOut.vertices[i*2 + 1] = vertices3DIn[i].y * t; // perspective y } } // 背面用にテクスチャを黒くする private function getDarkerBitmap(source:BitmapData, darkness:Number):BitmapData { var darker:Bitmap = new Bitmap(source); darker.transform.colorTransform = new ColorTransform(darkness, darkness, darkness); var container:Sprite = new Sprite(); container.addChild(darker); var bmp:BitmapData = new BitmapData(source.width, source.height, source.transparent, 0); bmp.draw(container); return bmp; } ]]> </mx:Script> <mx:UIComponent id="myUI" width="100%" height="100%"/> </mx:Application>