Papervision3Dのプリミティブオブジェクトや自作のオブジェクトにテクスチャを貼ってみるサンプル。

いろんなオブジェクトのワイヤーフレーム版は、Papervision3D のプリミティブオブジェクトを生成するサンプル by Flex SDK とか Papervision3D で円形とかリングとか表示してみる とか Papervision3D で凸凹平面を扱うクラス DekoBokoPlane にある。

以下、サンプルのソースコード。
コンパイル環境は Flex SDK 2.0.1 と Papervision3D 1.5。

HelloWorld3D.as


package {
 
  import flash.display.*;
  import flash.events.*;
 
  import org.papervision3d.core.proto.*;
  import org.papervision3d.scenes.*;
  import org.papervision3d.objects.*;
  import org.papervision3d.cameras.*;
  import org.papervision3d.materials.*;
 
  public class HelloWorld3D extends Sprite {
 
    private var container : Sprite;
    private var scene     : Scene3D;
    private var camera    : Camera3D;
    private var rootNode  : DisplayObject3D;
 
    private var obj:Array = new Array();
 
    // 3Dオブジェクト踊らせ用パラメータ
    private var valx    : Number = 0;
    private var valy    : Number = 0;
 
    public function HelloWorld3D():void {
 
      // 画面いっぱいに表示(縦横比無視)したいときはコレを使う
      // stage.scaleMode = StageScaleMode.EXACT_FIT;
 
      // リサイズに対応(swfをブラウザで直接ひらいているときとか)
      stage.addEventListener(Event.RESIZE, onStageResize);
 
      // 定期的にイベント発生
      addEventListener(Event.ENTER_FRAME, myLoopEvent);
 
      // 表示用の Sprite オブジェクトを生成
      container = new Sprite();
      container.x = 400 / 2; // at center : swf width  = 400
      container.y = 400 / 2; // at center : swf height = 400
      addChild(container);
 
      // シーンオブジェクトを作る
      scene = new Scene3D(container);
 
      // カメラオブジェクトを作る
      camera = new Camera3D();
      camera.z = -200;
      camera.focus = 500;
      camera.zoom = 1;
 
      // ルートノードを作る
      rootNode = new DisplayObject3D();
      scene.addChild(rootNode);
 
      // いろんな3Dオブジェクトを作ってみて、配列に入れておく
      obj.push(createPlane());
      obj.push(createCube());
      obj.push(createCylinder());
      obj.push(createSphere());
      obj.push(createCone());
      obj.push(createPaperPlane());
      obj.push(createCircle(createMaterial()));
      obj.push(createRing2D(createMaterial()));
      obj.push(createRing3D(createMaterial()));
      obj.push(createDekoBokoPlane());
 
      // 3Dオブジェクトをルートノードに追加
      for(var i:int; i<obj.length; i++){
        rootNode.addChild(obj[i]);
      }
    }
 
    private static function createMaterial():MaterialObject3D {
      var material:BitmapFileMaterial = new BitmapFileMaterial("20071124_texture.jpg");
      material.doubleSided = true;
      return material;
    }
 
    private function createPlane():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var planeSize:int = 100;
      var segment:int = 2;
 
      var plane:Plane = new Plane(
        material, planeSize, planeSize, segment, segment);
      plane.x =  0;
      plane.y =  0;
      plane.z =  0;
      return plane;
    }
 
    private function createCube():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var width:Number  = 50;
      var depth:Number  = 70;
      var height:Number = 90;
      var __segmentsS:Number = 2;
      var __segmentsT:Number = 4;
      var __segmentsH:Number = 8;
      var cube:Cube = new Cube(
        material, width, depth, height,
        __segmentsS, __segmentsT, __segmentsH);
      cube.x =   50;
      cube.y = -100;
      cube.z =  100;
      return cube;
    }
 
    private function createCylinder():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var cylinder:Cylinder = new Cylinder(material);
      cylinder.x =  100;
      cylinder.y =  100;
      cylinder.z =  100;
      return cylinder;
    }
 
    private function createSphere():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var sphere:Sphere = new Sphere(material);
      sphere.x =  -100;
      sphere.y =  -100;
      sphere.z =  -100;
      return sphere;
    }
 
    private function createCone():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var radius:Number = 30;
      var height:Number = 200;
 
      var cone:Cone = new Cone(material, radius, height);
      cone.x =  -50;
      cone.y =  100;
      cone.z =  -50;
      return cone;
    }
 
    private function createPaperPlane():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var pp:PaperPlane = new PaperPlane(material);
      pp.x =    150;
      pp.y =   -100;
      pp.z =      0;
      return pp;
    }
 
    private function createCircle(material:MaterialObject3D):DisplayObject3D {
      var obj:Circle = new Circle(material, 100, 16);
      obj.x =  200;
      obj.y =  150;
      obj.z = -100;
      return obj;
    }
 
    private function createRing2D(material:MaterialObject3D):DisplayObject3D {
      var obj:Ring2D = new Ring2D(material, 80, 100, 32);
      obj.x = -200;
      obj.y = -150;
      obj.z = -100;
      return obj;
    }
 
    private function createRing3D(material:MaterialObject3D):DisplayObject3D {
      var obj:Ring3D = new Ring3D(material, 80, 100, 50, 32);
      obj.x =  200;
      obj.y = -150;
      obj.z = -100;
      return obj;
    }
 
    private function createDekoBokoPlane():DisplayObject3D {
 
      var material:MaterialObject3D = createMaterial();
 
      var planeWidthSize:int = 200;
      var planeHeightSize:int = 100;
 
      // z parameters (depths)
      var depths:Array = [
        [   0,  10,  20,  30,  30,  20,  10,   0,   0,   0],
        [   0,   0,  10,  20,  30,  30,  20,  10,   0,   0],
        [   0,   0,   0,  10,  20,  30,  30,  20,  10,   0],
        [   0,   0,   0, -10, -20, -30, -30, -20, -10,   0],
        [   0,   0, -10, -20, -30, -30, -20, -10,   0,   0],
        [   0, -10, -20, -30, -30, -20, -10,   0,   0,   0],
      ];
 
      var plane:DekoBokoPlane = new DekoBokoPlane(
        material, planeWidthSize, planeHeightSize, depths);
      plane.x = -200;
      plane.y =  150;
      plane.z = -100;
      return plane;
    }
 
    private function myLoopEvent(event:Event):void {
 
      valx += container.mouseX / 50;
      valy += container.mouseY / 50;
 
      for(var i:int; i<obj.length; i++){
        obj[i].rotationY = valx;
        obj[i].rotationX = valy;
      }
 
      scene.renderCamera(camera);
    }
 
    private function onStageResize(event:Event):void {
      container.x = stage.stageWidth  / 2;
      container.y = stage.stageHeight / 2;
    }
    
  }
}

Circle.as

Papervision3D で円形とかリングとか表示してみる の Circle.as だとテクスチャがうまく貼れないので projectTexture の部分を修正。


package {
  import org.papervision3d.core.proto.*;
  import org.papervision3d.core.geom.*;
 
  // 円オブジェクト
  public class Circle extends Mesh3D {
 
    public function Circle(
      material:MaterialObject3D = null,
      radius:Number = 100,
      segments:int = 8,
      initObject:Object = null){
 
      super(material, new Array(), new Array(), null, initObject);
      buildCircle(radius, segments);
    }
 
    private function buildCircle(s:Number, segments:int):void {
 
      const density:int = segments + 2;
      const rad:Number = degree2radian(360.0 / density);
 
      var i:int;
 
      var vertices:Array = new Array();
      for(i=0; i<density; i++){
        var x:Number = Math.cos(rad * i) * s;
        var y:Number = Math.sin(rad * i) * s;
        vertices.push(new Vertex3D(x, y, 0));
      }
 
      // vertices に無い頂点を含む Face3D を入れるとエラーになる
      var faces:Array = new Array();
      for(i=1; i<vertices.length-1; i++){
        //var v:Array = new Array();
        //v.push(vertices[0]);
        //v.push(vertices[i]);
        //v.push(vertices[i+1]);
        //faces.push(new Face3D(v));
        faces.push(new Face3D([vertices[0], vertices[i], vertices[i+1]]));
      }
 
      this.geometry.vertices = vertices;
      this.geometry.faces = faces;
      this.projectTexture("x", "y");
      this.geometry.ready = true;
    }
 
    private static function degree2radian(degree:Number):Number{
      return degree / 180.0 * Math.PI;
    }
 
  }
}

Ring2D.as

Papervision3D で円形とかリングとか表示してみる の Ring2D.as をテクスチャのために projectTexture の部分を修正。あまりうまくいってないけど。


package {
  import org.papervision3d.core.proto.*;
  import org.papervision3d.core.geom.*;
 
  // 輪オブジェクト平面版
  public class Ring2D extends Mesh3D {
 
    public function Ring2D(
      material:MaterialObject3D = null,
      inRadius:Number =  80,
      exRadius:Number = 100,
      segments:int = 8,
      initObject:Object = null){
 
      super(material, new Array(), new Array(), null, initObject);
      buildRing2D(inRadius, exRadius, segments);
    }
 
    private function buildRing2D(inRadius:Number, exRadius:Number, segments:int):void {
 
      const density:int = segments;
      const rad :Number = degree2radian(360.0 / density);
      const half:Number = degree2radian(360.0 / density / 2.0);
 
      // internal circle
      var inVertices:Array = createVertices(density, rad,  0, inRadius);
 
      // external circle
      var exVertices:Array = createVertices(density, rad, half, exRadius);
 
      var faces:Array = new Array();
      for(var i:int=0; i<density; i++){
        // clockwise
        faces.push(new Face3D([get(inVertices, i), get(exVertices, i), get(inVertices, i+1)]));
        faces.push(new Face3D([get(exVertices, i), get(exVertices, i+1), get(inVertices, i+1)]));
      }
 
      this.geometry.vertices = inVertices.concat(exVertices);
      this.geometry.faces = faces;
      this.projectTexture("x", "y");
      this.geometry.ready = true;
    }
 
    private static function get(a:Array, i:int):Object{
      if(a.length <= i){
        i = i % a.length;
      }
      return a[i];
    }
 
    private static function createVertices(density:int, rad:Number, offsetRad:Number, radius:Number):Array{
 
      var v:Array = new Array();
      for(var i:int=0; i<density; i++){
        var angle:Number = (rad * i) + offsetRad;
        var x:Number = Math.cos(angle) * radius;
        var y:Number = Math.sin(angle) * radius;
        v.push(new Vertex3D(x, y, 0));
      }
 
      return v;
    }
 
    private static function degree2radian(degree:Number):Number{
      return degree / 180.0 * Math.PI;
    }
 
  }
}

Ring3D.as


package {
  import org.papervision3d.core.proto.*;
  import org.papervision3d.core.geom.*;
 
  // 輪オブジェクト立体版
  public class Ring3D extends Mesh3D {
 
    public function Ring3D(
      material:MaterialObject3D = null,
      inRadius:Number   =  80,
      exRadius:Number   = 100,
      depth:Number    =  50,
      segments:int    =   8,
      initObject:Object = null){
 
      super(material, new Array(), new Array(), null, initObject);
      buildRing3D(inRadius, exRadius, depth, segments);
    }
 
    private function buildRing3D(inRadius:Number, exRadius:Number, depth:Number, segments:int):void {
 
      const density:int = segments;
      const rad :Number = degree2radian(360.0 / density);
      const half:Number = degree2radian(360.0 / density / 2.0);
 
      // near side internal circle
      var nsInVertices:Array = createVertices(density, rad,  0, inRadius, depth / -2.0);
 
      // near side external circle
      var nsExVertices:Array = createVertices(density, rad, half, exRadius, depth / -2.0);
 
      // far side internal circle
      var fsInVertices:Array = createVertices(density, rad,  0, inRadius, depth /  2.0);
 
      // far side external circle
      var fsExVertices:Array = createVertices(density, rad, half, exRadius, depth /  2.0);
 
      var faces:Array = new Array();
      for(var i:int=0; i<density; i++){
        // clockwise(時計回りの表側がオブジェクトの表側)
        // near side Ring2D
        faces.push(new Face3D([get(nsInVertices, i), get(nsExVertices, i),   get(nsInVertices, i+1)]));
        faces.push(new Face3D([get(nsExVertices, i), get(nsExVertices, i+1), get(nsInVertices, i+1)]));
        // far side Ring2D
        faces.push(new Face3D([get(fsInVertices, i+1), get(fsExVertices, i), get(fsInVertices, i)]));
        faces.push(new Face3D([get(fsInVertices, i+1), get(fsExVertices, i+1), get(fsExVertices, i)]));
        // connection internal circles for far and near
        faces.push(new Face3D([get(fsInVertices, i), get(nsInVertices, i),   get(fsInVertices, i+1)]));
        faces.push(new Face3D([get(nsInVertices, i), get(nsInVertices, i+1), get(fsInVertices, i+1)]));
        // connection external circles for far and near
        faces.push(new Face3D([get(nsExVertices, i), get(fsExVertices, i),   get(nsExVertices, i+1)]));
        faces.push(new Face3D([get(fsExVertices, i), get(fsExVertices, i+1), get(nsExVertices, i+1)]));
      }
 
      this.geometry.vertices = nsInVertices.concat(nsExVertices, fsInVertices, fsExVertices);
      this.geometry.faces = faces;
      this.projectTexture("x", "z");
      this.geometry.ready = true;
    }
 
    private static function get(a:Array, i:int):Object{
      if(a.length <= i){
        i = i % a.length;
      }
      return a[i];
    }
 
    private static function createVertices(density:int, rad:Number, offsetRad:Number, radius:Number, depth:Number):Array{
 
      var v:Array = new Array();
      for(var i:int=0; i<density; i++){
        var angle:Number = (rad * i) + offsetRad;
        var x:Number = Math.cos(angle) * radius;
        var y:Number = Math.sin(angle) * radius;
        v.push(new Vertex3D(x, y, depth));
      }
 
      return v;
    }
 
    private static function degree2radian(degree:Number):Number{
      return degree / 180.0 * Math.PI;
    }
 
  }
}

DeokoBokoPlahe は Papervision3D で凸凹平面を扱うクラス DekoBokoPlane のコードをそのまま流用。

tags: zlashdot Flash Flash Flex Papervision3D

Posted by NI-Lab. (@nilab)