PaperVision3Dでカメラからの距離によってポリゴン数が変化

カメラからの距離によってポリゴン数が変化するっていうとってもエコ?なクラスを使ってみました。
こないだのAutoDeskイベント3Decemberでちょびっと紹介してたので気になり、PaperVision3Dでもないかなぁって調べたらあったので実験してみました。
こんな感じ
http://moeten.info/flex/20081206_papervision3DLOD/bin-release/main.html

簡単な説明

事前に距離によって変化するオブジェクトを作成して配列に入れてLOD(Level of Detail)に登録

for(var i:int=4;i<16;i++){
    objects.unshift(new Sphere(wf, 100, i, i-1));
}
simple = new SimpleLevelOfDetail(objects, 100, 1000, distances);
scene.addChild(simple);

あとはレンダリングするときに変化させる。

renderer.renderScene(scene , camera , viewport );
simple.updateLoD();

参考リンク

ソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute" creationComplete="init3D()" width="640" height="480"
    backgroundGradientColors="[0x999999,0x000000]"
     viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
/* **********************************
            PV3D
********************************** */
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.special.SimpleLevelOfDetail;
import org.papervision3d.materials.BitmapFileMaterial;
private var scene    : Scene3D;
private var viewport : Viewport3D;
private var renderer : BasicRenderEngine;
private var camera   : Camera3D;
private var cameraTarget : DisplayObject3D;
//初期化
private function init3D():void{
    setupScene();
    setupCamera();
    setupSphere();
    setupListeners();
}
//シーンの作成
private function setupScene():void{
    viewport = new Viewport3D( myUI.width , myUI.height , true , false , true , true );
    myUI.addChildAt(viewport , 0);
    renderer = new BasicRenderEngine();
    scene    = new Scene3D();
}
//カメラ設定
private function setupCamera():void{
    cameraTarget = new DisplayObject3D();
    camera = new Camera3D();
    camera.z = - 300;
    camera.y = 10;
}
//イベントリスナー設定
private function setupListeners():void{
    this.addEventListener(Event.ENTER_FRAME , onRenderTick );
}
private var simple:SimpleLevelOfDetail;
private function setupSphere():void{
    var objects:Array = new Array();
    var distances:Array = null;
    //var bMat:BitmapFileMaterial = new BitmapFileMaterial("05.gif");
    var wf:WireframeMaterial = new WireframeMaterial(0xff0000);
    //UNCOMMENT TO USE A DISTANCE BASED ARRAY TO CONTROL RANGES
    //distances = [1000, 1500, 1600, 3000];
    //あらかじめポリゴン数の違う物体を順に用意しておく
     for(var i:int=4;i<16;i++){
        //objects.unshift(new Sphere(bMat, 100, i, i-1));
        objects.unshift(new Sphere(wf, 100, i, i-1));
    }
    simple = new SimpleLevelOfDetail(objects, 100, 1000, distances);
    scene.addChild(simple);
}
//レンダリング+マウス操作
private var theta:Number = 0;
protected function onRenderTick(e:Event):void {
    var reach:Number = 0.01;
    var ease:Number = 0.1;
    var cameraDistance:Number = 100;
    camera.x += (Math.sin(mouseX * reach) *   cameraDistance - camera.x) * ease;
    camera.y += (Math.sin(mouseY * reach) *   cameraDistance - camera.y) * ease;
    theta+=0.03;
    simple.z = Math.cos(theta)*500+300;
    renderer.renderScene(scene , camera , viewport );
    simple.updateLoD();
}
//リサイズイベント
private function onResize(e : Event) : void {
}
]]>
</mx:Script>
<mx:UIComponent id="myUI" width="100%" height="100%" />
</mx:Application>