[AS3] 東京タワーおじさん (drawTrianglesでポリゴン)

2009/08/27

こんにちは。きんくまです。

3Dまわりで自分でポリゴン作ってテクスチャ貼ってみました。

 
いろいろと調べたらできたのですが、Zバッファーができていないため、おじさんやタワーの配置がおかしいです。
一番苦労したのは、パースのついた投影変換の部分

Utils3D.projectVectors(proj, tVerts, drawVerts, uvts);

この部分ですね。これが最初全然わからなくて、3Dにはなっているんだけど平行投影のみであんまり感じがでなかったんです。
わかったのは下記サイトのおかげ。Thanksです。
>> 3D Bezier

あとUVTの指定はアドビのヘルプを見るとよいです。
>> UV マッピング

テクスチャは一枚でUVで指定してます。
こんな感じ↓

texture_in

これでZバッファーを実装できればそれらしく見えるんだけどなあ。

※追記
そういえば昨日wonderflにうん〇みたいなのを投下しました。
ぐるぐるとまわります。

ぐるぐるまわる – wonderfl build flash online

 

以下今回のソース。 今回は固めたデータ一式も用意しました。CS4用です。
>> tokyotoweruncle

package
{
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Graphics;
  import flash.display.MovieClip;
  import flash.display.Sprite;
  import flash.display.TriangleCulling;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Matrix3D;
  import flash.geom.PerspectiveProjection;
  import flash.geom.Utils3D;
  import flash.geom.Vector3D;
  import flash.text.TextField;
  import flash.utils.getDefinitionByName;
  import fl.controls.Slider;
  import fl.controls.CheckBox;

  public class Main extends MovieClip
  {
    public var s1:Slider;
    public var s1_txt:TextField;
    public var cullingChk:CheckBox;

    public var texture:BitmapData;
    public var sideVerts:Vector.<Number>;
    public var manVerts:Vector.<Number>;
    public var yAxisDeg:Number = 0;
    public var uvts:Vector.<Number>;
    public var manuvts:Vector.<Number>;
    public var fl:Number = 180;

    public var canvas:Sprite;
    public var proj:Matrix3D;
    public var stratBtn:MovieClip;

    public function Main()
    {
      stratBtn.addEventListener(MouseEvent.CLICK, init);
    }

    public function init(e:Event):void
    {
      stratBtn.removeEventListener(MouseEvent.CLICK, init);
      stratBtn.visible = false;

      var TextureC:Class = getDefinitionByName("Texture") as Class;
      texture = new TextureC(0,0);

      canvas = new Sprite();
      canvas.x = stage.stageWidth / 2;
      canvas.y = stage.stageHeight / 2;
      addChildAt(canvas, 0);

      setVerts();
      addEventListener(Event.ENTER_FRAME, render);
    }

    private function setVerts():void
    {
      //tower
      sideVerts = new Vector.<Number> ;

      var i:int;
      var mat:Matrix3D = new Matrix3D();
      var verts:Vector.<Number>;
      var terts:Vector.<Number>;
      for (i = 0; i < 4; i++) {
        verts = new Vector.<Number>();
        terts = new Vector.<Number>();
        verts.push(
          0, -160, 0,
          80, 160, -80,
          -80, 160, -80
          );
        mat.appendRotation(90 * i, Vector3D.Y_AXIS); //90度ずつ回転
        mat.transformVectors(verts, terts);
        sideVerts = sideVerts.concat(terts);
      }

      //man
      manVerts = new Vector.<Number>();
      manVerts.push(
        -150, 0, 0,
        -70, 0, 0,
        -150, 160, 0,

        -70, 0, 0,
        -70, 160, 0,
        -150, 160, 0
      );
    }

    private function setUVTs():void
    {
      //tower
      uvts = new Vector.<Number>();
      var tz1:Number;
      var tz2:Number;
      var tz3:Number;
      var i:int;
      var cnt:int = 1;
      for (i = 0; i < 4; i++) {
        tz1 = sideVerts[cnt * 3 -1];
        tz2 = sideVerts[(cnt + 1) * 3 -1];
        tz3 = sideVerts[(cnt + 2) * 3 -1];
        cnt++;
        uvts.push(
          0.1 + 0.2 * i, 0, fl / (fl + tz1),
          0.2 + 0.2 * i, 1.0, fl / (fl + tz2),
          0.2 * i, 1.0, fl / (fl + tz3)
        );
      }

      //man
      manuvts = new Vector.<Number>();
      cnt = 1;
      for (i = 0; i < 2; i++) {
        tz1 = manVerts[cnt * 3 -1];
        tz2 = manVerts[(cnt + 1) * 3 -1];
        tz3 = manVerts[(cnt + 2) * 3 -1];
        cnt++;
        if (i == 0) {
          manuvts.push(
            0.8, 0, fl / (fl + tz1),
            1, 0, fl / (fl + tz2),
            0.8, 1.0, fl / (fl + tz3)
          );
        }else{
          manuvts.push(
            1, 0, fl / (fl + tz1),
            1, 1, fl / (fl + tz2),
            0.8, 1.0, fl / (fl + tz3)
          );
        }
      }
    }


    private function render(e:Event):void
    {
      fl = s1.value;
      s1_txt.text = "focalLength: " + s1.value;

      setUVTs();
      var transe:Matrix3D = new Matrix3D();
      var drawVerts:Vector.<Number> = new Vector.<Number>();
      var tVerts:Vector.<Number> = new Vector.<Number>();
      var manDrawVerts:Vector.<Number> = new Vector.<Number>();
      var manTVerts:Vector.<Number> = new Vector.<Number>();

      var perse:PerspectiveProjection = new PerspectiveProjection();
      perse.focalLength = fl;
      proj = perse.toMatrix3D();

      transe.appendRotation(yAxisDeg, Vector3D.Y_AXIS);
      transe.appendRotation(30, Vector3D.X_AXIS);
      transe.appendTranslation(0, 0, 1.1 * fl);
      transe.transformVectors(sideVerts, tVerts);
      transe.transformVectors(manVerts, manTVerts);

      Utils3D.projectVectors(proj, tVerts, drawVerts, uvts);
      Utils3D.projectVectors(proj, manTVerts, manDrawVerts, manuvts);
      yAxisDeg += 1;

      var towerCulling:String = cullingChk.selected ? TriangleCulling.NEGATIVE : TriangleCulling.NONE;

      var g:Graphics = canvas.graphics;
      g.clear();
      g.beginBitmapFill(texture, null, false, true);
      g.drawTriangles(drawVerts, null, uvts, towerCulling);
      g.drawTriangles(manDrawVerts, null, manuvts, TriangleCulling.NONE);
      g.endFill();
    }
  }

}
LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る