views:

177

answers:

0

package designLab.events { import flash.display.BlendMode; import flash.display.Sprite; import flash.events.Event; import flash.filters.BlurFilter;

// Import designLab
import designLab.layer.IntroLayer;
import designLab.shadow.ShadowCaster;
import designLab.utils.LayerConstant;

// Import Papervision3D
import org.papervision3d.cameras.*;
import org.papervision3d.scenes.*;
import org.papervision3d.objects.*;
import org.papervision3d.objects.special.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.materials.shaders.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.lights.*;
import org.papervision3d.render.*;
import org.papervision3d.view.*;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.events.*;
import org.papervision3d.core.utils.*;
import org.papervision3d.core.geom.renderables.Vertex3D;

public class CoreEnging extends Sprite {    
    public var viewport         :BasicView;         // Create BasicView         
    public var displayObject    :DisplayObject3D;   // Create DisplayObject
    public var shadowCaster     :ShadowCaster;      // Create ShadowCaster
    private var light           :PointLight3D;      // Create PointLight
    private var shadowPlane     :Plane;             // Create Plane     

    private var layer           :LayerConstant;     // Create constant resource layer 
    private static var instance :CoreEnging;        // Create CoreEnging class static instance  

    // CoreEnging class static instance mathod function
    public static function getinstance() {          
        if (instance != null)
        return instance;
        else {
            instance = new CoreEnging();
            return instance;
        }
    }

    // CoreEnging constrictor
    public function CoreEnging () {
        trace("INFO: Design Lab Application : Core Enging v0.1");

        layer = new LayerConstant();

        viewport = new BasicView(900, 600, true, true, CameraType.FREE); // pass the width, height, scaleToStage, interactive, cameraType to BasicView
        viewport.camera.zoom = 100; // Define the zoom level of camera
        addChild(viewport);

        createFloor(); // Create the floor 

        displayObject = new DisplayObject3D();  // Create new instance of DisplayObject 
        viewport.scene.addChild(displayObject); // Add the DisplayObject to the BasicView 

        light = new PointLight3D();  // Create new instance of PointLight
        light.z = -50; // Position the Z of create instance  
        light.x = 0; //Position the X of create instance
        light.rotationZ = 45; //Position the rotation angel of the Z of create instance
        light.y = 500; //Position the Y of create instance

        shadowCaster = new ShadowCaster("shadow", 0x000000, BlendMode.MULTIPLY, .1, [new BlurFilter(20, 20, 1)]); // pass shadowcaster name, color, blend mode, alpha and filters
        shadowCaster.setType(ShadowCaster.SPOTLIGHT); // Define the shadow type

        addEventListener(Event.ENTER_FRAME, onRenderEvent); // Add frame render event
    }   

    // Start create floor
    public function createFloor() {
        var spr:Sprite = new Sprite(); // Create Sprite
        spr.graphics.beginFill(0xFFFFFF); // Define the fill color for sprite
        spr.graphics.drawRect(0, 0, 600, 600);  // Define the X, Y, width, height of the sprite 

        var sprMaterial:MovieMaterial = new MovieMaterial(spr, true, true, true); //Create a texture from an existing sprite instance

        shadowPlane = new Plane(sprMaterial, 2000, 2000, 1, 1); // create new instance of the Plane and pass the texture material, width, height, segmentsW and segmentsH
        shadowPlane.rotationX = 80; //Position the rotation angel of the X of Plane
        shadowPlane.y = -200; //Position the Y of Plane
        viewport.scene.addChild(shadowPlane); // Add the Plane to the BasicView         
    }

    // switch method function of the page layer control 
    public function addLayer(type:String) {
        switch (type) {
            case layer.INTRO:
            var intro:IntroLayer = new IntroLayer();
            break;
        }           
    }

    // Create get mathod function for DisplayObject  
    public function getDisplayObject():DisplayObject3D {
        return displayObject;
    }

    // Create get mathod function for BasicView
    public function getViewport():BasicView {
        return viewport;
    }

    // Rendering function
    protected function onRenderEvent(event:Event):void {    
        var rotY: Number = (mouseY-(stage.stageHeight/2))/(900/2)*(1200);
        var rotX: Number = (mouseX-(stage.stageWidth/2))/(600/2)*(-1200);
        displayObject.rotationY = viewport.camera.x + (rotX - viewport.camera.x) / 50;
        displayObject.rotationX = viewport.camera.y + (rotY - viewport.camera.y) / 30;

        // Remove the shadow
        shadowCaster.invalidate();

        // create new shadow on DisplayObject move
        shadowCaster.castModel(displayObject, light, shadowPlane);

        viewport.singleRender();
    }
}   

}

package designLab.layer { import flash.display.Sprite; import flash.events.Event;

// Import designLab
import designLab.materials.iBusinessCard;   
import designLab.events.CoreEnging;

// Import Papervision3D
import org.papervision3d.objects.primitives.Cube;   
import org.papervision3d.materials.ColorMaterial;   
import org.papervision3d.materials.MovieMaterial;

public class IntroLayer 
{       
    // IntroLayer constrictor
    public function IntroLayer() 
    {
        trace("INFO: Load Intro layer");            

        var indexDP:DP_index = new DP_index(); //Create the library MovieClip
        var blackMaterial:MovieMaterial = new MovieMaterial(indexDP, true); //Create a texture from an existing library MovieClip instance
        blackMaterial.smooth = true;
        blackMaterial.doubleSided = false;          

        var mycolor:ColorMaterial = new ColorMaterial(0x000000); //Create solid color material

        var mycard:iBusinessCard = new iBusinessCard(blackMaterial, blackMaterial, mycolor, 372, 10, 207); // Create custom 3D cube object to pass the Front, Back, All, CubeWidth, CubeDepth and CubeHeight
        CoreEnging.getinstance().getDisplayObject().addChild(mycard.create3DCube()); // Add the custom 3D cube to the DisplayObject         
    }   
}   

}

package designLab.materials { import flash.display.; import flash.events.;

// Import Papervision3D
import org.papervision3d.materials.*;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;   

public class iBusinessCard extends Sprite
{       
    private var materialsList   :MaterialsList;
    private var cube            :Cube;      
    private var Front           :MovieMaterial = new MovieMaterial();
    private var Back            :MovieMaterial = new MovieMaterial();
    private var All             :ColorMaterial = new ColorMaterial();
    private var CubeWidth       :Number;
    private var CubeDepth       :Number;
    private var CubeHeight      :Number;        

    public function iBusinessCard(Front:MovieMaterial, Back:MovieMaterial, All:ColorMaterial, CubeWidth:Number, CubeDepth:Number, CubeHeight:Number) 
    {
        setFront(Front);
        setBack(Back);
        setAll(All);
        setCubeWidth(CubeWidth);
        setCubeDepth(CubeDepth);
        setCubeHeight(CubeHeight);          
    }   
    public function create3DCube():Cube {
        materialsList = new MaterialsList();
        materialsList.addMaterial(Front, "front");
        materialsList.addMaterial(Back, "back");
        materialsList.addMaterial(All, "left");
        materialsList.addMaterial(All, "right");
        materialsList.addMaterial(All, "top");
        materialsList.addMaterial(All, "bottom");

        cube = new Cube(materialsList, CubeWidth, CubeDepth, CubeHeight);
        cube.x = 0;
        cube.y = 0;
        cube.z = 0;
        cube.rotationY = 180;

        return cube;
    }
    public function setFront(Front:MovieMaterial) {
        this.Front = Front;         
    }
    public function getFront():MovieMaterial {
        return Front;
    }
    public function setBack(Back:MovieMaterial) {
        this.Back = Back;           
    }
    public function getBack():MovieMaterial {
        return Back;
    }
    public function setAll(All:ColorMaterial) {
        this.All = All;         
    }
    public function getAll():ColorMaterial {
        return All;
    }
    public function setCubeWidth(CubeWidth:Number) {
        this.CubeWidth = CubeWidth;         
    }
    public function getCubeWidth():Number {
        return CubeWidth;
    }
    public function setCubeDepth(CubeDepth:Number) {
        this.CubeDepth = CubeDepth;         
    }
    public function getCubeDepth():Number {
        return CubeDepth;
    }
    public function setCubeHeight(CubeHeight:Number) {
        this.CubeHeight = CubeHeight;           
    }
    public function getCubeHeight():Number {
        return CubeHeight;
    }
}   

}

package designLab.shadow { import flash.display.Sprite; import flash.filters.BlurFilter; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.Dictionary;

import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.BoundingSphere;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Plane3D;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Plane;

public class ShadowCaster
{
    private var vertexRefs:Dictionary;
    private var numberRefs:Dictionary;
    private var lightRay:Number3D = new Number3D()
    private var p3d:Plane3D = new Plane3D();
    public var color:uint = 0;
    public var alpha:Number = 0;
    public var blend:String = "";
    public var filters:Array;
    public var uid:String;
    private var _type:String = "point";
    private var dir:Number3D;
    private var planeBounds:Dictionary;
    private var targetBounds:Dictionary;
    private var models:Dictionary;      

    public static var DIRECTIONAL:String = "dir";
    public static var SPOTLIGHT:String = "spot";        

    public function ShadowCaster(uid:String, color:uint = 0, blend:String = "multiply", alpha:Number = 1, filters:Array=null)
    {
        this.uid = uid;
        this.color = color;
        this.alpha = alpha;
        this.blend = blend; 
        this.filters = filters ? filters : [new BlurFilter()];
        numberRefs = new Dictionary(true);
        targetBounds = new Dictionary(true);
        planeBounds = new Dictionary(true);
        models = new Dictionary(true);
    }

    public function castModel(model:DisplayObject3D, light:PointLight3D, plane:Plane, faces:Boolean = true, cull:Boolean = false):void{

        var ar:Array;
        if(models[model])
        {
            ar = models[model];
        }else{
            ar = new Array();
            getChildMesh(model, ar);
            models[model] = ar;
        }           

        var reset:Boolean = true;

        for each(var t:TriangleMesh3D in ar){
            if(faces)
                castFaces(light, t, plane, cull, reset);
            else
                castBoundingSphere(light, t, plane, 0.75, reset);
            reset = false;
        }

    }

    private function getChildMesh(do3d:DisplayObject3D, ar):void{
        if(do3d is TriangleMesh3D)
            ar.push(do3d);

        for each(var d:DisplayObject3D in do3d.children)
            getChildMesh(d, ar);
    }

    public function setType(type:String="point"):void{
        _type = type;
    }
    public function getType():String{
        return _type;
    }

    public function castBoundingSphere(light:PointLight3D, target:TriangleMesh3D, plane:Plane, scaleRadius:Number=0.8, clear:Boolean = true):void{
        var planeVertices:Array = plane.geometry.vertices;

        //convert to target space?
        var world:Matrix3D = plane.world;
        var inv:Matrix3D = Matrix3D.inverse(plane.transform);

        var lp:Number3D = new Number3D(light.x, light.y, light.z);
        Matrix3D.multiplyVector(inv, lp);

        p3d.setNormalAndPoint(plane.geometry.faces[0].faceNormal, new Number3D());

        var b:BoundingSphere = target.geometry.boundingSphere;


        var bounds:Object = planeBounds[plane];
        if(!bounds){
            bounds = plane.boundingBox();
            planeBounds[plane] = bounds;
        }


        var tbounds:Object = targetBounds[target];
        if(!tbounds){
            tbounds = target.boundingBox();
            targetBounds[target] = tbounds;
        }


        var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
        var movieSize:Point = new Point(planeMovie.width, planeMovie.height);

        var castClip:Sprite = getCastClip(plane);
            castClip.blendMode = this.blend;
            castClip.filters = this.filters;
            castClip.alpha = this.alpha;

        if(clear)
            castClip.graphics.clear();

        vertexRefs = new Dictionary(true);

        var tlp:Number3D = new Number3D(light.x, light.y, light.z);
        Matrix3D.multiplyVector(Matrix3D.inverse(target.world), tlp);

        var center:Number3D = new Number3D(tbounds.min.x+tbounds.size.x*0.5, tbounds.min.y+tbounds.size.y*0.5, tbounds.min.z+tbounds.size.z*0.5);


        var dif:Number3D = Number3D.sub(lp, center);
        dif.normalize();

        var other:Number3D = new Number3D();
        other.x = -dif.y;
        other.y = dif.x;
        other.z = 0;

        other.normalize();


        var cross:Number3D = Number3D.cross(new Number3D(plane.transform.n12, plane.transform.n22, plane.transform.n32), p3d.normal);
        cross.normalize();

        //cross = new Number3D(-dif.y, dif.x, 0);
        //cross.normalize();

        cross.multiplyEq(b.radius*scaleRadius);


        if(_type == DIRECTIONAL){
            var oPos:Number3D = new Number3D(target.x, target.y, target.z);
            Matrix3D.multiplyVector(target.world, oPos);
            Matrix3D.multiplyVector(inv, oPos);
            dir = new Number3D(oPos.x-lp.x, oPos.y-lp.y, oPos.z-lp.z);
        }

        //numberRefs = new Dictionary(true);
        var pos:Number3D;           
        var c2d:Point;
        var r2d:Point;

        //_type = SPOTLIGHT;
        pos = projectVertex(new Vertex3D(center.x, center.y, center.z), lp, inv, target.world);
        c2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);

        pos = projectVertex(new Vertex3D(center.x+cross.x, center.y+cross.y, center.z+cross.z), lp, inv, target.world);
        r2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);

        var dx:Number = r2d.x-c2d.x;
        var dy:Number = r2d.y-c2d.y;
        var rad:Number = Math.sqrt(dx*dx+dy*dy);

        castClip.graphics.beginFill(color);
        castClip.graphics.moveTo(c2d.x, c2d.y);
        castClip.graphics.drawCircle(c2d.x, c2d.y, rad);
        castClip.graphics.endFill();



    }

    public function getCastClip(plane:Plane):Sprite{

        var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
        var movieSize:Point = new Point(planeMovie.width, planeMovie.height);
        var castClip:Sprite;// = new Sprite();
        if(planeMovie.getChildByName("castClip"+uid))
            return Sprite(planeMovie.getChildByName("castClip"+uid));
        else{
            castClip = new Sprite();
            castClip.name = "castClip"+uid;
            castClip.scrollRect = new Rectangle(0, 0, movieSize.x, movieSize.y);
            //castClip.alpha = 0.4;
            planeMovie.addChild(castClip);
            return castClip;
        }
    }

    public function castFaces(light:PointLight3D, target:TriangleMesh3D, plane:Plane, cull:Boolean=false, clear:Boolean = true):void{


        var planeVertices:Array = plane.geometry.vertices;

        //convert to target space?
        var world:Matrix3D = plane.world;
        var inv:Matrix3D = Matrix3D.inverse(plane.transform);

        var lp:Number3D = new Number3D(light.x, light.y, light.z);
        Matrix3D.multiplyVector(inv, lp);

        var tlp:Number3D;
        if(cull){
            tlp = new Number3D(light.x, light.y, light.z);
            Matrix3D.multiplyVector(Matrix3D.inverse(target.world), tlp);
        }
        //Matrix3D.multiplyVector(Matrix3D.inverse(target.transform), tlp);

        //p3d.setThreePoints(planeVertices[0].getPosition(), planeVertices[1].getPosition(), planeVertices[2].getPosition());
        p3d.setNormalAndPoint(plane.geometry.faces[0].faceNormal, new Number3D());

        if(_type == DIRECTIONAL){
            var oPos:Number3D = new Number3D(target.x, target.y, target.z);
            Matrix3D.multiplyVector(target.world, oPos);
            Matrix3D.multiplyVector(inv, oPos);
            dir = new Number3D(oPos.x-lp.x, oPos.y-lp.y, oPos.z-lp.z);
        }

        var bounds:Object = planeBounds[plane];
        if(!bounds){
            bounds = plane.boundingBox();
            planeBounds[plane] = bounds;
        }

        var castClip:Sprite = getCastClip(plane);   
            castClip.blendMode = this.blend;
            castClip.filters = this.filters;
            castClip.alpha = this.alpha;


        var planeMovie:Sprite = Sprite(MovieMaterial(plane.material).movie);
        var movieSize:Point = new Point(planeMovie.width, planeMovie.height);

        if(clear)
            castClip.graphics.clear();

        vertexRefs = new Dictionary(true);
        //numberRefs = new Dictionary(true);
        var pos:Number3D;           
        var p2d:Point;
        var s2d:Point;
        var hitVert:Number3D = new Number3D();

        for each(var t:Triangle3D in target.geometry.faces){

            if( cull){

                hitVert.x = t.v0.x;
                hitVert.y = t.v0.y;
                hitVert.z = t.v0.z;

                if(Number3D.dot(t.faceNormal, Number3D.sub(tlp, hitVert)) <= 0)
                    continue;
            }

            castClip.graphics.beginFill(color);
            pos = projectVertex(t.v0, lp, inv, target.world);
            s2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
            castClip.graphics.moveTo(s2d.x, s2d.y);

            pos = projectVertex(t.v1, lp, inv, target.world);
            p2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
            castClip.graphics.lineTo(p2d.x, p2d.y); 

            pos = projectVertex(t.v2, lp, inv, target.world);
            p2d = get2dPoint(pos, bounds.min, bounds.size, movieSize);
            castClip.graphics.lineTo(p2d.x, p2d.y);

            castClip.graphics.lineTo(s2d.x, s2d.y);

            castClip.graphics.endFill();


        }

    }

    public function invalidate():void{
        invalidateModels();
        invalidatePlanes();
    }

    public function invalidatePlanes():void{
        planeBounds = new Dictionary(true);
    }
    public function invalidateTargets():void{
        numberRefs = new Dictionary(true);
        targetBounds = new Dictionary(true);
    }

    public function invalidateModels():void{
        models = new Dictionary(true);
        invalidateTargets();
    }

    private function get2dPoint(pos3D:Number3D, min3D:Number3D, size3D:Number3D, movieSize:Point):Point{
        return new Point((pos3D.x-min3D.x)/size3D.x*movieSize.x, ((-pos3D.y-min3D.y)/size3D.y*movieSize.y));
    }

    private function projectVertex(v:Vertex3D, light:Number3D, invMat:Matrix3D, world:Matrix3D):Number3D{

        var pos:Number3D = vertexRefs[v];
        if(pos)
            return pos;

        var n:Number3D = numberRefs[v];

        if(!n){
            n = new Number3D(v.x, v.y, v.z);
            Matrix3D.multiplyVector(world, n);
            Matrix3D.multiplyVector(invMat, n);
            numberRefs[v] = n;
        }


        if(_type == SPOTLIGHT){

            lightRay.x = light.x;
            lightRay.y = light.y;
            lightRay.z = light.z;  

        }else{
            lightRay.x = n.x-dir.x;
            lightRay.y = n.y-dir.y;
            lightRay.z = n.z-dir.z;
        }

        pos = p3d.getIntersectionLineNumbers(lightRay, n);
        vertexRefs[v] = pos;
        return pos;
    }

}

}