JAVAC.JP
HOSHI TETSUYA 星鉄矢
2005/07/26
hossy@javac.jp
http://www.javac.jp
Google
WWW を検索 WWW.JAVAC.JP を検索

2-4 3D描画の基礎機能を持ったクラス

ここで作成するのは、ParamControlクラスとDrawingControlクラスです。
ParamControlクラスは、描画に向けて3Dデータを2Dデータに変換し、また、そのための変数を保持するクラスです。
DrawingControlクラスは、実際に描画するためのメソッド群を保持したクラスです。

まず、ParamControlクラスですが、先に述べた方法を用います。
つまり、視線ベクトルを(0,0,-1)と固定して計算する方法です。
このクラスはgetScreenX,getScreenY,getScreenSizeメソッドを持ち、3Dのパラメータを描画の際の2Dデータに変換します。
視点座標や倍率は現在決め打ちですが、いずれ自由に変更できるように修正します。
ParamControl.as
---
class ParamControl{
    private var cx:Number;
    private var cy:Number;
    private var cz:Number;
    private var screenLength:Number=100;
    private var scale:Number;

    function ParamControl(){
        cx=0;
        cy=0;
        cz=1000;
        scale=10;
    }

    function getScreenX(x:Number,y:Number,z:Number,size:Number):Number{
        return scale*(x-cx)*screenLength/(z-cz);
    }

    function getScreenY(x:Number,y:Number,z:Number,size:Number):Number{
        return scale*(y-cy)*screenLength/(z-cz);
    }

    function getScreenSize(x:Number,y:Number,z:Number,size:Number):Number{
        return Math.abs(scale*size*screenLength/(z-cz));
    }
}

次にDrawingControlクラスです。
主なメソッドとして、drawOvalメソッドとdrawLineメソッドがあります。
これらのメソッドは3D処理を一切行いません。純粋に画面に対応する数値を受け取り画面にそのサイズで描画します。
drawOvalメソッドの実装はattachMovieにて行うものなので、リンケージ名ovalを登録する必要があります。
drawLineメソッドでのエッジの描画では、moveToメソッド、lineToメソッドにて線を描画します。また、一度描いた線を再利用する手もあるのですが(伸縮と回転と移動を複雑に多用する)、ここではエッジの移動のためには、描いた線を消して描き直すことで行っています。
DrawingControl.as
---
class DrawingControl{
    private var path:MovieClip;
    private var ovalBase:MovieClip;
    private var lineBase:MovieClip;
    private var ovalDepth:Number;
    private var lineDepth:Number;
    private var OVAL_BASE_DEPTH:Number=500;
    private var LINE_BASE_DEPTH:Number=300;
    private var OVAL_START_DEPTH:Number=1;
    private var LINE_START_DEPTH:Number=1;

    function DrawingControl(path:MovieClip){
        this.path=path;
        path.createEmptyMovieClip("oval_base",OVAL_BASE_DEPTH);
        ovalBase=path.oval_base;
        path.createEmptyMovieClip("line_base",LINE_BASE_DEPTH);
        lineBase=path.line_base;
        ovalDepth=OVAL_START_DEPTH;
        lineDepth=LINE_START_DEPTH;
    }

    public function drawOval(x:Number,y:Number,size:Number):Void{
        var depth:Number=ovalDepth;
        ovalDepth++;
        var linkage:String="oval";
        var mcname:String="oval"+String(depth);
        ovalBase.attachMovie(linkage,mcname,depth);
        var mc:MovieClip=ovalBase[mcname];
        mc._x=x;
        mc._y=y;
        mc._xscale=size;
        mc._yscale=size;
    }

    public function drawLine(x1:Number,y1:Number,x2:Number,y2:Number):Void{
        var depth:Number=lineDepth;
        lineDepth++;
        var mcname:String="line"+depth;
        lineBase.createEmptyMovieClip(mcname,depth);
        var mc:MovieClip=lineBase[mcname];
        mc.lineStyle(3,0x000000);
        mc.moveTo(x1,y1);
        mc.lineTo(x2,y2);
    }

    public function removeAllOvals():Void{
        ovalBase.removeMovieClip();
        path.createEmptyMovieClip("oval_base",OVAL_BASE_DEPTH);
        ovalBase=path.oval_base;
    }

    public function removeAllLines():Void{
        lineBase.removeMovieClip();
        path.createEmptyMovieClip("line_base",LINE_BASE_DEPTH);
        lineBase=path.line_base;
    }
}
このDrawingクラスの簡便な面として、ノード・エッジの移動の際に『前の画像(MovieClip)を全て消して描き直す』という仕様があります。これは『MovieClipにデータを保持させない』という姿勢の賜物です。
一方で、指定したMovieClipのみを適宜消す、という姿勢も重要なことはFlash講座 - ActionScript 2.0の基礎とGraphの概念の(5-5)エッジの再描画、全体・一部間の比較で述べた通りです。
ですが、3次元回転において、前の画像が残ることはありません。ですので、ただの3次元回転の際には、全消去・全再描画という姿勢で構わないように思います。

また、後に述べますが、CPU負荷を軽くするためにMovieClipの数を抑える、そのためにエッジの描画、つまりlineTo, moveTo、は1つのMovieClipにのみ行う、という実装があります。



BACKTOPNEXT




All Contents Copyright (C) 2005 HOSHI Tetsuya
Home