note.x | Papervision3Dメモ #11 のハイトマップから地形を生成させるとか note.x | [Papervision3D] 富士山 の標高とか見てたら、でこぼこした地形を扱ってみたくなった。

とりあえず、org.papervision3d.objects.Plane クラスを改造して DekoBokoPlane クラスを作ってみた。
奥行き(高さ)データの二次元配列(配列の配列)を指定することで、デコボコした平面オブジェクトを作ることができる。テクスチャも貼れる。

DekoBokoSample.as


package {
 
  import flash.display.*;
  import flash.events.*;
 
  import org.papervision3d.scenes.*;
  import org.papervision3d.objects.*;
  import org.papervision3d.cameras.*;
  import org.papervision3d.materials.*;
 
  [SWF(width="400", height="400", backgroundColor="#000000", frameRate="30")]
 
  // This class is a sample for DekoBokoPlane class.
  public class DekoBokoSample extends Sprite {
 
    private var container : Sprite;
    private var scene     : Scene3D;
    private var camera    : Camera3D;
    private var rootNode  : DisplayObject3D;
 
    private var obj:Array = new Array();
 
    // these parameters for dancing 3d object
    private var valx    : Number = 0;
    private var valy    : Number = 0;
 
    public function DekoBokoSample():void {
 
      stage.addEventListener(Event.RESIZE, onStageResize);
 
      addEventListener(Event.ENTER_FRAME, myLoopEvent);
 
      // for display
      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);
 
      // z parameters (depths)
      var depths:Array = [
        [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,   5,  10,  15,  20,  25,  30,  35,  40,  45],
        [   0,  10,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  15,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  20,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  25,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  30,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  35,   0,   0, -50, -50,   0,   0,   0,   0],
        [   0,  40,   0,   0, -50, -50,   0,   0,   0,   0],
        [   0,  45,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  50,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  55,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  60,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  65,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  70,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  75,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  80,   0,   0,   0,   0,   0,   0,   0,   0],
        [   0,  85,   0,   0,   0,   0,   0,   0,   0, 100],
      ];
 
      obj.push(createWireframePlane(depths));
      obj.push(createColorPlane(depths));
      obj.push(createBitmapPlane(depths));
 
      for(var i:int; i<obj.length; i++){
        rootNode.addChild(obj[i]);
      }
    }
 
    private function createWireframePlane(depths:Array):DisplayObject3D {
 
      var material:WireframeMaterial = new WireframeMaterial();
      material.oneSide = false;
      material.lineColor = 0x00FF00;
      material.lineAlpha = 1;
 
      var planeSize:int = 200;
 
      var plane:DekoBokoPlane = new DekoBokoPlane(
        material, planeSize, planeSize, depths);
      plane.x =  -100;
      plane.y =   100;
      plane.z =      0;
      return plane;
    }
 
    private function createColorPlane(depths:Array):DisplayObject3D {
 
      var material:ColorMaterial =
        new ColorMaterial(0xFF0000, 1);
      material.oneSide = false;
      material.lineColor = 0x0000FF;
      material.lineAlpha = 1;
 
      var planeSize:int = 200;
 
      var plane:DekoBokoPlane = new DekoBokoPlane(
        material, planeSize, planeSize, depths);
      plane.x =   100;
      plane.y =  -100;
      plane.z =     0;
      return plane;
    }
 
    private function createBitmapPlane(depths:Array):DisplayObject3D {
 
      var material:BitmapFileMaterial =
        new BitmapFileMaterial("texture.jpg");
      material.oneSide = false;
      material.lineColor = 0x0000FF;
      material.lineAlpha = 1;
 
      var planeSize:int = 200;
 
      var plane:DekoBokoPlane = new DekoBokoPlane(
        material, planeSize, planeSize, depths);
      plane.x =  0;
      plane.y =  0;
      plane.z =  0;
      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;
    }
    
  }
}

DekoBokoPlane.as


// This source code is based by org.papervision3d.objects.Plane class by Carlos Ulloa Matesanz, noventaynueve.com.
// Copyright 2007 (c) NI-Lab. www.nilab.info
 
/*
 *  PAPER    ON   ERVIS  NPAPER ISION  PE  IS ON  PERVI IO  APER  SI  PA
 *  AP  VI  ONPA  RV  IO PA     SI  PA ER  SI NP PE     ON AP  VI ION AP
 *  PERVI  ON  PE VISIO  APER   IONPA  RV  IO PA  RVIS  NP PE  IS ONPAPE
 *  ER     NPAPER IS     PE     ON  PE  ISIO  AP     IO PA ER  SI NP PER
 *  RV     PA  RV SI     ERVISI NP  ER   IO   PE VISIO  AP  VISI  PA  RV3D
 *  ______________________________________________________________________
 *  papervision3d.org + blog.papervision3d.org + osflash.org/papervision3d
 */
 
/*
 * Copyright 2006 (c) Carlos Ulloa Matesanz, noventaynueve.com.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
 
package {
import org.papervision3d.core.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.core.geom.*;
 
import flash.display.BitmapData;
 
/**
* The DekoBokoPlane class lets you create and display dekoboko rectangle objects.
* 
*/
public class DekoBokoPlane extends Mesh3D
{
    public var segmentsW :Number;
    public var segmentsH :Number;
    static public var DEFAULT_SIZE :Number = 500;
    static public var DEFAULT_SCALE :Number = 1;
    //static public var DEFAULT_SEGMENTS :Number = 1;
 
    public function DekoBokoPlane(
        material:MaterialObject3D=null,
        width:Number=0,
        height:Number=0,
        depths:Array=null,
        initObject:Object=null)
    {
        super( material, new Array(), new Array(), null, initObject );
 
        // for dekoboko
        if(depths == null || depths.length < 2 || depths[0].length < 2){
            depths = [ [0,0], [0,0] ];
        }
        this.segmentsW = depths[0].length - 1;
        this.segmentsH = depths.length - 1;
 
        var scale :Number = DEFAULT_SCALE;
 
        if( ! height )
        {
            if( width )
                scale = width;
 
            if( material && material.bitmap )
            {
                width  = material.bitmap.width  * scale;
                height = material.bitmap.height * scale;
            }
            else
            {
                width  = DEFAULT_SIZE * scale;
                height = DEFAULT_SIZE * scale;
            }
        }
 
        buildPlane( width, height, depths );
    }
 
    private function buildPlane( width:Number, height:Number, depths:Array ):void
    {
        var gridX    :Number = this.segmentsW;
        var gridY    :Number = this.segmentsH;
        var gridX1   :Number = gridX + 1;
        var gridY1   :Number = gridY + 1;
 
        var vertices :Array  = this.geometry.vertices;
        var faces    :Array  = this.geometry.faces;
 
        var textureX :Number = width /2;
        var textureY :Number = height /2;
 
        var iW       :Number = width / gridX;
        var iH       :Number = height / gridY;
 
        // Vertices
        for( var ix:int = 0; ix < gridX + 1; ix++ )
        {
            for( var iy:int = 0; iy < gridY1; iy++ )
            {
                var x :Number = ix * iW - textureX;
                var y :Number = iy * iH - textureY;
                
                // for dekoboko
                var z:Number = depths[depths.length - 1 - iy][ix];
 
                //vertices.push( new Vertex3D( x, y, 0 ) );
                vertices.push( new Vertex3D( x, y, z ) ); // for dekoboko
            }
        }
 
        // Faces
        var uvA :NumberUV;
        var uvC :NumberUV;
        var uvB :NumberUV;
 
        for(  ix = 0; ix < gridX; ix++ )
        {
            for(  iy= 0; iy < gridY; iy++ )
            {
                // Triangle A
                var a:Vertex3D = vertices[ ix     * gridY1 + iy     ];
                var c:Vertex3D = vertices[ ix     * gridY1 + (iy+1) ];
                var b:Vertex3D = vertices[ (ix+1) * gridY1 + iy     ];
 
                uvA =  new NumberUV( ix     / gridX, iy     / gridY );
                uvC =  new NumberUV( ix     / gridX, (iy+1) / gridY );
                uvB =  new NumberUV( (ix+1) / gridX, iy     / gridY );
 
                faces.push( new Face3D( [ a, b, c ], null, [ uvA, uvB, uvC ] ) );
 
                // Triangle B
                a = vertices[ (ix+1) * gridY1 + (iy+1) ];
                c = vertices[ (ix+1) * gridY1 + iy     ];
                b = vertices[ ix     * gridY1 + (iy+1) ];
 
                uvA =  new NumberUV( (ix+1) / gridX, (iy+1) / gridY );
                uvC =  new NumberUV( (ix+1) / gridX, iy      / gridY );
                uvB =  new NumberUV( ix      / gridX, (iy+1) / gridY );
 
                faces.push( new Face3D( [ a, b, c ], null, [ uvA, uvB, uvC ] ) );
            }
        }
 
        this.geometry.ready = true;
    }
}
}

DekoBokoSample-config.xml


<flex-config>
  <output>DekoBokoSample.swf</output>
  <default-size>
    <width>400</width>
    <height>400</height>
  </default-size>
  <default-frame-rate>30</default-frame-rate>
  <default-background-color>0x000000</default-background-color>
  <use-network>true</use-network>
  <benchmark>true</benchmark>
  <compiler>
    <incremental>true</incremental>
    <source-path>
      <path-element>../libs/</path-element>
    </source-path>
  </compiler>
</flex-config>

../libs/ 以下に Papervision3D 1.5 のソースコードを設置。

コンパイル風景

Flex 2.0.1 にてコンパイル。


mxmlc DekoBokoSample.as

DekoBokoSample.swf が生成される。

Ref. Papervision3D : Flash/ActionScriptによる3D描画ライブラリ

tags: zlashdot Flash Flash Flex Papervision3D

Posted by NI-Lab. (@nilab)