[AS3] 3Dはテクスチャが命?

2009/08/6

こんばんは。きんくまです。

この間この本を買いました。

>> Papervision3Dではじめる Flash 3Dアニメーション

なんだかんだで書籍はいいですね。まとまった情報が見られるところがいいです。

それで、今回作ったやつです。

 
見ての通り、球2つに板3枚のみです。
ですが、なんかすごく見えます。で、テクスチャを凝ったものにするとモデリングそのものを凝ったものにしなくてもわりと見栄えのいいものができるんじゃないかと思いました。

今回のテクスチャは地球と月はwebから。板はPhotoshopで自作しました。といってもPhotoshopもブラシをダウンロードしてきただけなんですけど…。
みなさまありがとうございます。

地球と月
>> [Away3D] THE WORLD OF TRADITIONAL COLORS(note.x)
>> Learn how to geocode with Papervision3D and Adobe Flex
>> Texture maps of Earth and Planets

Photoshopブラシ
>> Abstract Brushset XIV

PV3Dはちゃんとしたやつを作ったことがないんでもう少しつっこんでいきたいです。
今回は時間がかかりました。

今回のソースです。

package
{
  import flash.display.MovieClip;
  import flash.display.Shader;
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageQuality;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.ui.Mouse;
  import flash.ui.MouseCursor;
  import org.papervision3d.cameras.Camera3D;
  import org.papervision3d.events.InteractiveScene3DEvent;
  import org.papervision3d.lights.PointLight3D;
  import org.papervision3d.materials.BitmapAssetMaterial;
  import org.papervision3d.materials.BitmapFileMaterial;
  import org.papervision3d.materials.ColorMaterial;
  import org.papervision3d.materials.shadematerials.CellMaterial;
  import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
  import org.papervision3d.materials.shaders.FlatShader;
  import org.papervision3d.materials.shaders.ShadedMaterial;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.primitives.Cylinder;
  import org.papervision3d.objects.primitives.Plane;
  import org.papervision3d.objects.primitives.Sphere;
  import org.papervision3d.render.BasicRenderEngine;
  import org.papervision3d.scenes.Scene3D;
  import org.papervision3d.view.Viewport3D;

  public class Sample extends Sprite
  {
    public var scene:Scene3D;
    public var camera:Camera3D;
    public var viewport:Viewport3D;
    public var renderer:BasicRenderEngine;
    public var vpX:Number;
    public var vpY:Number;

    public var plane:Plane;
    public var cyl:Cylinder;

    public var light:PointLight3D;
    public var mainbg:MovieClip;
    public var wrapper:DisplayObject3D;

    public var isDragging:Boolean = false;
    public var moon:Sphere;
    public var earth:Sphere;
    public var moonwrapper:DisplayObject3D;

    public var cntRad:Number = 0;

    public var startBtn:MovieClip;

    public function Sample()
    {
      initStage();
      initScene();
      initCamera();
      enterframeHD();
      startBtn.addEventListener(MouseEvent.CLICK, init);
      setChildIndex(startBtn, numChildren - 1);
    }

    public function init(e:MouseEvent):void
    {
      startBtn.visible = false;
      startBtn.removeEventListener(MouseEvent.CLICK, init);
      addEventListener(Event.ENTER_FRAME, enterframeHD);

    }

    private function mouseUpHD(e:MouseEvent):void
    {
      Mouse.cursor = MouseCursor.ARROW;
      isDragging = false;
      stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHD);
    }

    private function mouseDownHD(e:InteractiveScene3DEvent):void
    {
      Mouse.cursor = MouseCursor.BUTTON;
      isDragging = true;
      stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHD);
    }

    private function initStage():void
    {
      stage.quality = StageQuality.LOW;
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      vpX = stage.stageWidth / 2;
      vpY = stage.stageHeight / 2;
    }

    private function initScene():void
    {
      scene = new Scene3D();
      renderer = new BasicRenderEngine();
      viewport = new Viewport3D(0, 0, true, true);
      addChild(viewport);

      light = new PointLight3D(true);
      light.x = 300;
      light.y = 300;
      light.z = -300;

      var flats:FlatShader = new FlatShader(light, 0xffffff, 0x000000, 100);
      var shade:ShadedMaterial;

      var mat:BitmapAssetMaterial = new BitmapAssetMaterial("earthmap1k.jpg");
      mat.interactive = true;
      shade = new ShadedMaterial(mat, flats);

      earth = new Sphere(mat, 320, 24, 20);
      wrapper = new DisplayObject3D();
      scene.addChild(wrapper);
      wrapper.addChild(earth);

      var mat3:BitmapAssetMaterial = new BitmapAssetMaterial("MoonMap_2500x1250_s.jpg");
      moon = new Sphere(mat3, 30, 20, 20);
      moonwrapper = new DisplayObject3D();
      scene.addChild(moonwrapper);
      moonwrapper.addChild(moon);
      moon.x = 500;

      wrapper.z = 500;

      var mat2:BitmapAssetMaterial = new BitmapAssetMaterial("main_bg.jpg");
      mat2.doubleSided = true;

      shade = new ShadedMaterial(mat2, flats);
      plane = new Plane(mat2, 1600, 1400, 10, 10);

      plane.y = 200;
      plane.x = -690;
      plane.z = 1000;
      plane.rotationY = -30;
      scene.addChild(plane);
      var plane2:Plane = new Plane(mat2, 1600, 1400, 10, 10);
      plane2.rotationY = 30;
      plane2.y = 200;
      plane2.x = 690;
      plane2.z = 1000;


      var plane3:Plane = new Plane(mat2, 3200, 2400, 10, 10);
      plane3.rotationX = 90;
      plane3.rotationY = 45;
      scene.addChild(plane3);
      plane3.y = -600;
      plane3.z = 1000;
      scene.addChild(plane2);
    }

    private function initCamera():void
    {
      camera = new Camera3D();
      camera.z = -1800;
      camera.zoom = 30;
      camera.focus = 30;
      camera.target = DisplayObject3D.ZERO;
    }

    private function enterframeHD(e:Event = null):void
    {
      var radX:Number = (2 * vpY - mouseY) / 2 / vpY * Math.PI;
      var radY:Number = (2 * vpX - mouseX) / 2 / vpX * Math.PI;
      wrapper.rotationX += (90 * Math.cos(radX) - wrapper.rotationX) * 0.04;
      wrapper.rotationY += (90 * Math.cos(radY) - wrapper.rotationY) * 0.04;


      camera.x += (-Math.cos(radY) * 200 - camera.x) * 0.03;
      camera.y += (Math.cos(radX) * 200 + 300 - camera.y) * 0.03;


      cntRad += 0.03;
      if (cntRad > Math.PI * 2) {
        cntRad -= Math.PI * 2;
      }
      moon.x = Math.cos(cntRad) * 500;
      moon.z = Math.sin(cntRad) * 500;
      moon.rotationY = -cntRad / Math.PI * 180;
      moonwrapper.rotationZ += 0.1;
      if (moonwrapper.rotationZ > 360) {
        moonwrapper.rotationZ -= 360;
      }
      earth.rotationY -= 0.5;
      if (earth.rotationY < -360) {
        earth.rotationY += 360;
      }

      renderer.renderScene(scene, camera, viewport);
    }
  }

}

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

ページトップへ戻る