[Papervision 3d] - framerate problems

Hi everyone,

i have a little question about my actionscript code. It dynamically generates a street with rows of buildings along each side while a camera moves down this street.
the problem is that after a while the framerate starts dropping and the application doesn’t run fluently anymore. FrustumClipping is present, but this doesn’t solve the problem.

so my question is: is this problem due to the structure of my code and is there any way of improving this so that the framerate stays stable.

thanks in advance.

here’s the code:

package {package {
import caurina.transitions.Tweener;

import flash.display.Bitmap;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

import org.papervision3d.cameras.CameraType;
import org.papervision3d.core.clipping.FrustumClipping;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.shaders.PhongShader;
import org.papervision3d.materials.shaders.ShadedMaterial;
import org.papervision3d.materials.shaders.Shader;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.materials.shadematerials.GouraudMaterial;
import org.papervision3d.objects.parsers.Collada;

[SWF(width="580", height="400", backgroundColor="#02f0ff", frameRate="32")]
public class TrafficGameTest extends BasicView
{
    [Embed(source="assets/sidewalktexture.jpg")]
    private var FloorAsset:Class;
    [Embed(source="assets/streettexture.jpg")]
    private var StreetAsset:Class;
    
    [Embed(source="assets/building1.jpg")]
    private var Building1Asset:Class;
    [Embed(source="assets/building2.jpg")]
    private var Building2Asset:Class;
    [Embed(source="assets/building3.jpg")]
    private var Building3Asset:Class;
    
    [Embed(source="assets/building1-wall.jpg")]
    private var Building1WallAsset:Class;
    [Embed(source="assets/building2-wall.jpg")]
    private var Building2WallAsset:Class;
    [Embed(source="assets/building3-wall.jpg")]
    private var Building3WallAsset:Class;
    
    
    private var light:PointLight3D;
    private var streetBlocks:Array;
    private var cameraTargetZPos:Number;
    private var blockCounter:Number=0;
    private var cameraTargetRotation:Number=0;
    private var keyDown:Number=-1;
    //private var testBuilding:Cube;
    
    private var buildingurls:Array;
    private var buildings:Array;
    private var _light:PointLight3D;
    private var building:Collada

    public function TrafficGameTest()
    {
        super(640,480,true,false,CameraType.FREE);
        //super(640,480,true,false,FreeCamera3D.TYPE);
        
        viewport.autoCulling=true;
        
        renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);

        
        streetBlocks=new Array();  

        
        
        for(var i:Number=0;i<6;i++){
            var block:DisplayObject3D=createStreetBlock();
            scene.addChild(block);
            block.z=i*1250;
            streetBlocks.push(block);
            blockCounter++;
        }
        
        camera.y=150;
        camera.x=200; 
        //camera.target.x=200;
        //camera.x=500;
        camera.z=-312;
        //camera.target.y=camera.y;
        //camera.target.z=camera.z+500;
        cameraTargetZPos=-312+1250;
        Tweener.addTween(camera,{z:cameraTargetZPos,transition:"linear",delay:1,time:3,onComplete:moveToNextBlock});
        //camera.lookAt(street);
        //camera.zoom=15;
        //camera.focus=300;
        //camera.zoom=3;
        stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDown_handler);
        stage.addEventListener(KeyboardEvent.KEY_UP,keyUp_handler);
        startRendering();
    }
    private function keyDown_handler(evt:KeyboardEvent):void{
        keyDown=evt.keyCode;
    }
    private function keyUp_handler(evt:KeyboardEvent):void{
        if(evt.keyCode==keyDown){
            keyDown=-1;
        }
    }
    private function moveToNextBlock():void{
        var block:DisplayObject3D=streetBlocks[0] as DisplayObject3D;
        //scene.removeChild(block);
        streetBlocks.splice(0,1);
        var newBlock:DisplayObject3D=block;//createStreetBlock();
        scene.addChild(newBlock);
        newBlock.z=blockCounter*1250;
        blockCounter++;
        streetBlocks.push(newBlock);
        
        cameraTargetZPos+=1250;
        Tweener.addTween(camera,{z:cameraTargetZPos,transition:"linear",time:3,onComplete:moveToNextBlock});

    }
    private function createStreetBlock():DisplayObject3D{
        var temp:DisplayObject3D=new DisplayObject3D();
        //testBuilding=createBuilding(1,true);
        var street:Cube=createStreet();
        temp.addChild(street);
        //street.x=1000;
        street.y=-5;
        //street.z=625;
        var sideStreet:Cube=createSideStreet();
        temp.addChild(sideStreet);
        sideStreet.x=-750;
        sideStreet.y=-5
        sideStreet.z=500;
        
        sideStreet=createSideStreet();
        temp.addChild(sideStreet);
        sideStreet.x=750;
        sideStreet.y=-5
        sideStreet.z=500;
        
        var building1:Collada=createBuilding(Math.floor(Math.random()*3)+1,true);
        temp.addChild(building1);
        building1.x=-480;
        building1.z=-200;
        
        var building2:Collada=createBuilding(Math.floor(Math.random()*3)+1,false);
        temp.addChild(building2);
        building2.x=480;
        building2.z=-700;
        
        var building3:Collada=createBuilding(Math.floor(Math.random()*3)+1,true);
        temp.addChild(building3);
        building3.x=-480;
        building3.z=-700;
        
        var building4:Collada=createBuilding(Math.floor(Math.random()*3)+1,false);
        temp.addChild(building4);
        building4.x=480;
        building4.z=-200;
        
        return temp;
    }
    private function getWallTexture(type:Number):Bitmap{
        switch(type){
            case 1:
                return new Building1WallAsset();
            case 2:
                return new Building2WallAsset();
            case 3:
                return new Building3WallAsset();
        }
        return null;
    }
    private function getBuildingFrontTexture(type:Number):Bitmap{
        switch(type){
            case 1:
                return new Building1Asset();
            case 2:
                return new Building2Asset();
            case 3:
                return new Building3Asset();
        }
        return null;
    }
    private function createBuilding(type:Number, rightSideBuilding:Boolean):Collada{
       var materialsList:MaterialsList = new MaterialsList();
         var wallMaterial:BitmapMaterial=new BitmapMaterial(getWallTexture(type).bitmapData,false);
         //var wallMaterial:ColorMaterial=new ColorMaterial(0xffffff);
         //var wallMaterial:WireframeMaterial=new WireframeMaterial(0x000000);
         wallMaterial.smooth=false;
         var precise:Boolean=true;
        materialsList.addMaterial( wallMaterial, "back");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "bottom");
        materialsList.addMaterial(wallMaterial, "front");
        materialsList.addMaterial(!rightSideBuilding? new BitmapMaterial(getWallTexture(type).bitmapData):new BitmapMaterial(getBuildingFrontTexture(type).bitmapData,precise), "left");
        materialsList.addMaterial(rightSideBuilding? new BitmapMaterial(getWallTexture(type).bitmapData):new BitmapMaterial(getBuildingFrontTexture(type).bitmapData,precise), "right");
        //materialsList.addMaterial(wallMaterial, "left");
        //materialsList.addMaterial(wallMaterial, "right");
        
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "top");
        
        
        return building;
    }
    private function createStreet():Cube{
        var materialsList:MaterialsList = new MaterialsList();
        var street:Cube;
        var streetMat:BitmapMaterial=new BitmapMaterial(new FloorAsset().bitmapData,true);
        streetMat.smooth=false;
        //var streetMat:ColorMaterial=new ColorMaterial(0xcccccc,1);
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "back");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "bottom");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "front");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "left");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "right");
        materialsList.addMaterial(streetMat, "top");
        street = new Cube(materialsList, 1000, 1250,1, 1, 1, 1,0,Cube.ALL-Cube.TOP);
        //street.culled=false;
        return street;
    }
    private function createSideStreet():Cube{
        var materialsList:MaterialsList = new MaterialsList();
        var street:Cube;
        var streetMat:BitmapMaterial=new BitmapMaterial(new StreetAsset().bitmapData,true);
        streetMat.smooth=false;
        //var streetMat:ColorMaterial=new ColorMaterial(0xcccccc,1);
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "back");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "bottom");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "front");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "left");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "right");
        materialsList.addMaterial(streetMat, "top");
        street = new Cube(materialsList, 500, 250, 10, 1, 1, 1,0,Cube.ALL-Cube.TOP);
        return street; 
    }
    private function createShadedMaterial(bitmap:Bitmap):ShadedMaterial
    {
        var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, true);
        var shader:Shader = new PhongShader(light, 0xf7e896, 0x204574, 10, bitmap.bitmapData, null);
        var shadedMaterial:ShadedMaterial = new ShadedMaterial(bitmapMaterial, shader);
        return shadedMaterial;
    }
    override protected function onRenderTick(event:Event=null):void
    {
        if(keyDown==Keyboard.LEFT){
            camera.rotationY+=2;
            if(camera.rotationY>50)
                camera.rotationY=50;
        }else if(keyDown==Keyboard.RIGHT){
            camera.rotationY-=2;
            if(camera.rotationY<-50)
                camera.rotationY=-50;
        }else{
            if(camera.rotationY!=0){
                if(camera.rotationY>0)
                    camera.rotationY-=5;
                if(camera.rotationY<0)
                    camera.rotationY+=5;            
            }
        }            
        renderer.renderScene(scene, camera, viewport);
    }
}

}

import caurina.transitions.Tweener;

import flash.display.Bitmap;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

import org.papervision3d.cameras.CameraType;
import org.papervision3d.core.clipping.FrustumClipping;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.shaders.PhongShader;
import org.papervision3d.materials.shaders.ShadedMaterial;
import org.papervision3d.materials.shaders.Shader;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.materials.shadematerials.GouraudMaterial;
import org.papervision3d.objects.parsers.Collada;

[SWF(width="580", height="400", backgroundColor="#02f0ff", frameRate="32")]
public class TrafficGameTest extends BasicView
{
    [Embed(source="assets/sidewalktexture.jpg")]
    private var FloorAsset:Class;
    [Embed(source="assets/streettexture.jpg")]
    private var StreetAsset:Class;
    
    [Embed(source="assets/building1.jpg")]
    private var Building1Asset:Class;
    [Embed(source="assets/building2.jpg")]
    private var Building2Asset:Class;
    [Embed(source="assets/building3.jpg")]
    private var Building3Asset:Class;
    
    [Embed(source="assets/building1-wall.jpg")]
    private var Building1WallAsset:Class;
    [Embed(source="assets/building2-wall.jpg")]
    private var Building2WallAsset:Class;
    [Embed(source="assets/building3-wall.jpg")]
    private var Building3WallAsset:Class;
    
    
    private var light:PointLight3D;
    private var streetBlocks:Array;
    private var cameraTargetZPos:Number;
    private var blockCounter:Number=0;
    private var cameraTargetRotation:Number=0;
    private var keyDown:Number=-1;
    //private var testBuilding:Cube;
    
    private var buildingurls:Array;
    private var buildings:Array;
    private var _light:PointLight3D;
    private var building:Collada

    public function TrafficGameTest()
    {
        super(640,480,true,false,CameraType.FREE);
        //super(640,480,true,false,FreeCamera3D.TYPE);
        
        viewport.autoCulling=true;
        
        renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);

        
        streetBlocks=new Array();  

        
        
        for(var i:Number=0;i<6;i++){
            var block:DisplayObject3D=createStreetBlock();
            scene.addChild(block);
            block.z=i*1250;
            streetBlocks.push(block);
            blockCounter++;
        }
        
        camera.y=150;
        camera.x=200; 
        //camera.target.x=200;
        //camera.x=500;
        camera.z=-312;
        //camera.target.y=camera.y;
        //camera.target.z=camera.z+500;
        cameraTargetZPos=-312+1250;
        Tweener.addTween(camera,{z:cameraTargetZPos,transition:"linear",delay:1,time:3,onComplete:moveToNextBlock});
        //camera.lookAt(street);
        //camera.zoom=15;
        //camera.focus=300;
        //camera.zoom=3;
        stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDown_handler);
        stage.addEventListener(KeyboardEvent.KEY_UP,keyUp_handler);
        startRendering();
    }
    private function keyDown_handler(evt:KeyboardEvent):void{
        keyDown=evt.keyCode;
    }
    private function keyUp_handler(evt:KeyboardEvent):void{
        if(evt.keyCode==keyDown){
            keyDown=-1;
        }
    }
    private function moveToNextBlock():void{
        var block:DisplayObject3D=streetBlocks[0] as DisplayObject3D;
        //scene.removeChild(block);
        streetBlocks.splice(0,1);
        var newBlock:DisplayObject3D=block;//createStreetBlock();
        scene.addChild(newBlock);
        newBlock.z=blockCounter*1250;
        blockCounter++;
        streetBlocks.push(newBlock);
        
        cameraTargetZPos+=1250;
        Tweener.addTween(camera,{z:cameraTargetZPos,transition:"linear",time:3,onComplete:moveToNextBlock});

    }
    private function createStreetBlock():DisplayObject3D{
        var temp:DisplayObject3D=new DisplayObject3D();
        var street:Cube=createStreet();
        temp.addChild(street);
        street.y=-5;
        var sideStreet:Cube=createSideStreet();
        temp.addChild(sideStreet);
        sideStreet.x=-750;
        sideStreet.y=-5
        sideStreet.z=500;
        
        sideStreet=createSideStreet();
        temp.addChild(sideStreet);
        sideStreet.x=750;
        sideStreet.y=-5
        sideStreet.z=500;
        
        var building1:Collada=createBuilding(Math.floor(Math.random()*3)+1,true);
        temp.addChild(building1);
        building1.x=-480;
        building1.z=-200;
        
        var building2:Collada=createBuilding(Math.floor(Math.random()*3)+1,false);
        temp.addChild(building2);
        building2.x=480;
        building2.z=-700;
        
        var building3:Collada=createBuilding(Math.floor(Math.random()*3)+1,true);
        temp.addChild(building3);
        building3.x=-480;
        building3.z=-700;
        
        var building4:Collada=createBuilding(Math.floor(Math.random()*3)+1,false);
        temp.addChild(building4);
        building4.x=480;
        building4.z=-200;
        
        return temp;
    }
    private function getWallTexture(type:Number):Bitmap{
        switch(type){
            case 1:
                return new Building1WallAsset();
            case 2:
                return new Building2WallAsset();
            case 3:
                return new Building3WallAsset();
        }
        return null;
    }
    private function getBuildingFrontTexture(type:Number):Bitmap{
        switch(type){
            case 1:
                return new Building1Asset();
            case 2:
                return new Building2Asset();
            case 3:
                return new Building3Asset();
        }
        return null;
    }
    private function createBuilding(type:Number, rightSideBuilding:Boolean):Collada{
        if (rightSideBuilding) {
            building = new Collada("assets/buildingModel2.1.dae");
        } else {
            building = new Collada("assets/buildingModel2.2.dae");
        }
        building.scale = 1;
        return building;
    }
    private function createStreet():Cube{
        var materialsList:MaterialsList = new MaterialsList();
        var street:Cube;
        var streetMat:BitmapMaterial=new BitmapMaterial(new FloorAsset().bitmapData,true);
        streetMat.smooth=false;
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "back");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "bottom");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "front");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "left");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "right");
        materialsList.addMaterial(streetMat, "top");
        street = new Cube(materialsList, 1000, 1250,1, 1, 1, 1,0,Cube.ALL-Cube.TOP);
        return street;
    }
    private function createSideStreet():Cube{
        var materialsList:MaterialsList = new MaterialsList();
        var street:Cube;
        var streetMat:BitmapMaterial=new BitmapMaterial(new StreetAsset().bitmapData,true);
        streetMat.smooth=false;
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "back");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "bottom");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "front");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "left");
        materialsList.addMaterial(new ColorMaterial(0x000000,1), "right");
        materialsList.addMaterial(streetMat, "top");
        street = new Cube(materialsList, 500, 250, 10, 1, 1, 1,0,Cube.ALL-Cube.TOP);
        return street; 
    }
    private function createShadedMaterial(bitmap:Bitmap):ShadedMaterial
    {
        var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, true);
        var shader:Shader = new PhongShader(light, 0xf7e896, 0x204574, 10, bitmap.bitmapData, null);
        var shadedMaterial:ShadedMaterial = new ShadedMaterial(bitmapMaterial, shader);
        return shadedMaterial;
    }
    override protected function onRenderTick(event:Event=null):void
    {
        if(keyDown==Keyboard.LEFT){
            camera.rotationY+=2;
            if(camera.rotationY>50)
                camera.rotationY=50;
        }else if(keyDown==Keyboard.RIGHT){
            camera.rotationY-=2;
            if(camera.rotationY<-50)
                camera.rotationY=-50;
        }else{
            if(camera.rotationY!=0){
                if(camera.rotationY>0)
                    camera.rotationY-=5;
                if(camera.rotationY<0)
                    camera.rotationY+=5;            
            }
        }            
        renderer.renderScene(scene, camera, viewport);
    }
}

}