In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

CC3DPreview : CCD with Alternativa3D EllipsoidColliders

Sector-based Continuous collision detection/response framework with ellipsoid colliders. NOTE: still rather incomplete atm.
http://github.com/Glidias/CC3D-The-AlternSector
Get Adobe Flash player
by Glidias 23 Oct 2012
/**
 * Copyright Glidias ( http://wonderfl.net/user/Glidias )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/r7WP
 */

package  {
    import alternativ7.engine3d.containers.DistanceSortContainer;
    import alternativ7.engine3d.controllers.SimpleObjectController;
    import alternativ7.engine3d.core.*;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.objects.Mesh;
    import alternativ7.engine3d.primitives.Box;
    import alternativ7.engine3d.primitives.GeoSphere;

    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    import flash.utils.getTimer;
    
    import alternativ7.engine3d.alternativa3d;
    use namespace alternativa3d;

    /**
     * CC3D preview demo. A continous collision detection (CCD) framework
     * for Alternativa3D and (possibly other games).  
     */
    public class CC3DPreviewOnline extends Sprite {
        
        private var rootContainer:Object3DContainer = new DistanceSortContainer();
        
        private var camera:Camera3D;
        private var controller:SimpleObjectController;
        private var _debugField:TextField;
        private var errors:String = "";
        
        
        public static var _GROUPS:CollisionGroups;
        public static var _WORLD:SectorWorld;
        
        
        public function CC3DPreviewOnline() {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            // Camera and view
            // Создание камеры и вьюпорта
            camera = new Camera3D();
            camera.view = new View(stage.stageWidth, stage.stageHeight);

            addChild(camera.view);
            addChild(camera.diagram);
            
            // Initial position
            // Установка начального положения камеры
            camera.rotationX = -130*Math.PI/180;
            camera.rotationZ = -30*Math.PI/180;
            camera.x = -594;
            camera.y = 212;
            camera.z = -127;
            camera.rotationX = -1.2;
            camera.rotationZ = -2;
            controller = new SimpleObjectController(stage, camera, 200);
            rootContainer.addChild(camera);
            rootContainer.name = "Root container!";
            

            // Listeners
            // Подписка на события
            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(Event.RESIZE, onResize);
            
            setupDebugField();
            setupWorld();
            
            _currTime = getTimer();
        }
        
        private function setupWorld():void 
        {
            // World and collision groups
            _WORLD = new SectorWorld();
            _GROUPS = new CollisionGroups();
          
            var ball:TestBall;
            var testSector:Sector;
            
            var container:Object3DContainer = new DistanceSortContainer();
            container.name = "CONTAINER_1";
            container.x = 0;
            container.y = 0;
            container.z = 0;
            var polyhedron:Mesh;
            
            polyhedron = new Box(712, 512, 400, 1, 1, 1, true);
            polyhedron.sorting = 0;
            // jitter vertex hack required because EllipsoidCollider has bug that returns zero-length collision
            // normal for axis-aligned surfaces
            for (var v:Vertex = polyhedron.vertexList; v != null; v = v.next) {
                v.x += Math.random() * 1e-8;
                v.y += Math.random() * 1e-8;
                v.z += Math.random() * 1e-8;
            }
            polyhedron.calculateNormals();
            polyhedron.calculateBounds();
            polyhedron.setMaterialToAllFaces(new FillMaterial(0, 0.2, 1, 0));
            FaceMacros.makeDoubleSided(polyhedron);
            

            testSector = new Sector();
            testSector.container = container;
            testSector.collisionTarget = polyhedron;
            
            container.addChild(polyhedron);
            rootContainer.addChild(container);
        

            ball = getRandomBall(testSector, 50, 0, 0, 1000);
            ball.object.x += 80;
            ball = getRandomBall(testSector, 50, 0, 0, 1000);
            ball.object.x -= 80;
            getRandomBall(testSector, 51, 50, 0, 1000);
            ball.object.y -= 80;
            
        
    //    /*
            polyhedron = new GeoSphere(512, 1, true);
            polyhedron.setMaterialToAllFaces(new FillMaterial(0, .1, 1));
            
            
            container = new DistanceSortContainer();
            container.name = "CONTAINER 2";
            container.x = 1600;
            container.y = 0;
            container.z = 0;
            testSector = new Sector();
            
            testSector.collisionTarget = polyhedron;
            
            
            testSector.container = container;
            container.addChild(polyhedron);
            rootContainer.addChild(container);
            
        
        
            polyhedron.calculateNormals();
            polyhedron.calculateBounds();
            polyhedron.sorting = 0;
            FaceMacros.makeDoubleSided(polyhedron);
        
            ball = getRandomBall(testSector, 20);
            ball.object.x += 210;
            
            ball = getRandomBall(testSector, 50, 50, 20);
            ball.object.y += 220;
            ball = getRandomBall(testSector, 20);
            ball.object.y -= 220;
            ball = getRandomBall(testSector, 20);
            ball.object.z -= 220;
            ball = getRandomBall(testSector, 60);
            ball.object.z += 220;
        //    */
            
            
        }
        
        private function getRandomBall(sector:Sector, radius:Number=20, radiusY:Number=0, radiusZ:Number=0, baseSpeed:Number=1500):TestBall {
            var ball:TestBall = new TestBall(sector, radius, radiusY, radiusZ);
            var cloneSector:Object3D = sector.collisionTarget;
            ball.object.x = cloneSector.x + ( cloneSector.boundMinX + (cloneSector.boundMaxX-cloneSector.boundMinX)*.5);
            ball.object.y = cloneSector.y + ( cloneSector.boundMinY + (cloneSector.boundMaxY-cloneSector.boundMinY)*.5);
            ball.object.z = cloneSector.z + ( cloneSector.boundMinZ + (cloneSector.boundMaxZ - cloneSector.boundMinZ) * .5);
            var dir:Vector3D =new Vector3D(Math.random() * 100, Math.random() * 100, Math.random() * 100);
            dir.normalize();
            dir.scaleBy(baseSpeed);
            ball.cc3D.vx =  dir.x;
            ball.cc3D.vy =   dir.y;
            ball.cc3D.vz =  dir.z;
            sector.container.addChild(ball.object);
            return ball;
        }
        
        private function setupDebugField():void 
        {
            _debugField  = new TextField();
            _debugField.autoSize = "left";
            addChild(_debugField);
        }
        
        private var _currTime:int;
        private function onEnterFrame(e:Event):void {
            var newTime:int = getTimer()
            var timeElapsed:int = 30; // newTime - _currTime;
            _currTime = newTime;
            
            _WORLD.update(timeElapsed);
            
            var errorShow:Error;
            if ( (errorShow= _WORLD.getTraceError()) ) {
                errors +=  "\n" + errorShow.message;
            }
            camera.transformId++;  // timestamp for cam
            _debugField.text = "Updating...::"+ errors;
                
            controller.update();
            camera.render();
        }
        
        private function onResize(e:Event = null):void {
            // Width and height of view
            // Установка ширины и высоты вьюпорта
            camera.view.width = stage.stageWidth;
            camera.view.height = stage.stageHeight;
        }
        
    
        
    }
}

//package portal 
//{
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.objects.Mesh;

    import flash.geom.Point;
    import flash.geom.Vector3D;
    /**
     * Example bare-bones class in AS3 for Alternativa3D context.
     * 
     * @author Glenn Ko
     */
    //public 
    class Sector 
    {
        public var physics:SectorPhysics;
        public var collisionTarget:Object3D;
        
        public var container:Object3DContainer; // not being used atm
        
        public function Sector() 
        {
            
        
        }

    }

//}



//package cc3dexample.entity 
//{

    
    /**
     * Example collision groups setup for specific applications.
     * @author Glenn Ko
     */
    //public
    class CollisionGroups
    {
        //eg. buffer in 16 BallToWorld collision pairs
        public const BALL:int = CollisionTable.Get().getNewCollisionGroupId(BallToWorld, 16);
        
        // (Not yet available)
        //public const PLAYER:int = CollisionTable.Get().getNewCollisionGroupId(PlayerToWorld);
        //public const PROJECTILES:int = CollisionTable.Get().getNewCollisionGroupId(ProjectileToWorld);
        
        public function CollisionGroups() {
            
            // Setup table and filtering
            var table:CollisionTable = CollisionTable.Get();
        
             // eg. buffer in 8 BallToBall collision pairs
            table.registerCollisionPair(BALL, BALL, BallToBall);
            table.getPool(BALL, BALL).allocate(8); 
            
            // (Not yet available)
            //table.registerCollisionPair(PLAYER, BALL, PlayerToBall);
            //table.registerCollisionPair(PLAYER, PROJECTILES, PlayerToProjectile);
            //table.setFilterMask(PROJECTILES,  PLAYER);
            
            // Finalize table
            table.finalize();
        }
    }

//}


//package cc3dexample.entity 
//{
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.primitives.Sphere;

    import flash.geom.Vector3D;

    /**
     * ...
     * @author Glenn Ko
     */
    //public
    class TestBall
    {
        private var _object:Sphere;
        private var _radius:Number;
        private var _radiusY:Number;
        private var _radiusZ:Number;
        public var cc3D:CC3D;
        public static var COUNT:int = 0;
        
        public function TestBall(sector:Sector, radius:Number, radiusY:Number=0, radiusZ:Number=0) 
        {
            this._radiusZ = radiusZ!= 0 ? radiusZ : radius;
            this._radiusY = radiusY!= 0 ? radiusY : radius;
            this._radius = radius;
            
            
            this._object = new Sphere(radius);
            _object.name = "Ball" + COUNT++;
            
            if (radiusY != 0 || radiusZ != 0) {
                var normScale:Vector3D = new Vector3D(_radius, _radiusY, _radiusZ);
                normScale.normalize();
                _object.scaleX  = 1;
                _object.scaleY  = _radiusY / radius;
                _object.scaleZ  = _radiusZ / radius;
            }
            _object.sorting = 0;
            
            testCC3D(sector);
            _object.setMaterialToAllFaces( new FillMaterial(0xFF0000, 1, 1,0) )
        }
        
        public function testCC3D(sector:Sector):void 
        {
            cc3D =  CC3D.create(_object, this, CC3DPreviewOnline._GROUPS.BALL, 0, 0, 0, _radius, _radiusY, _radiusZ, sector);
        //    cc3D.collider.threshold = 0.0000001
            CC3DPreviewOnline._WORLD.addCC3D(cc3D);
        }
        
        public function get object():Sphere { return _object; }
        
    }

//}



//package alternsector.physics.adaptors.alternativa3d.ccd {

    //public
    class CC3DPair {
        public function CC3DPair() : void {
            null;
        }
        
        public var next : CC3DPair;
        public var pool : CC3DPairPool;
        public var t : Number;
        public var c1 : CC3D;
        public var c2 : CC3D;
        public function _init() : void {
            null;
        }
        
        public function destroy() : void {
            this.c1 = null;
            this.c2 = null;
            this._dispose();
        }
        
        protected function _dispose() : void {
            this.next = this.pool.collector;
            this.pool.collector = this;
        }
        
        public function willCollide(dt : Number) : Boolean {
            return false;
        }
        
        public function resolve() : void {
            null;
        }
        
    }
//}


//package alternsector.physics.adaptors.alternativa3d.ccd {

    //public 
    class CC3DPairPool {
        public function CC3DPairPool() : void {
            null;
        }
        
        public var collector : CC3DPair;
        public var classe : Class;
        public function allocate(amount : int) : void {
            var result : CC3DPair;
            while(--amount > -1) {
                result = new classe();
                result._init();
                result.pool = this;
                result.next = this.collector;
                this.collector = result;
            }
        }
        
        public function create() : CC3DPair {
            var result : CC3DPair;
            if(this.collector != null) {
                result = this.collector;
                result.next = null;
                result.pool = this;
                this.collector = this.collector.next;
            }
            else {
                result = new classe();
                result._init();
                result.pool = this;
            }
            return result;
        }
        
        static protected var EMPTY_PARAMS : Array = [];
        static public function getNewPool(classe : *) : CC3DPairPool {
            var newPool : CC3DPairPool = new CC3DPairPool();
            newPool.classe = classe;
            return newPool;
        }
        
    }
//}


//package cc3dexample.entity.collisions 
//{

    import flash.geom.Vector3D;
    /**
     * Example: 
     * Supports moving ellipsoid to ellipsoid collision detection and resolution.
     * @author Glenn Ko
     */
    //public
    class BallToBall extends CC3DPair
    {
        
        public function BallToBall() 
        {
            
        }
        
        private var ellipsoid_radius:Vector3D = new Vector3D();
        private var ray_travel:Vector3D = new Vector3D();
        private var ray_origin:Vector3D = new Vector3D();
    //    /*
        override public function willCollide(dt:Number):Boolean {
            
            // This is a C1 ray hit test against....
            ray_origin.x = c1.object.x - c2.object.x;
            ray_origin.y = c1.object.y - c2.object.y;
            ray_origin.z = c1.object.z - c2.object.z;
            
            // ...inflated ellipsoid (sum of radii)
            ellipsoid_radius.x = c1.collider.radiusX + c2.collider.radiusX;
            ellipsoid_radius.y = c1.collider.radiusY + c2.collider.radiusY;
            ellipsoid_radius.z = c1.collider.radiusZ + c2.collider.radiusZ;
            
            // ...based on relative velocities of c1/c2.
            ray_travel.x = c1.vx - c2.vx;
            ray_travel.y = c1.vy - c2.vy;
            ray_travel.z = c1.vz - c2.vz;
        
            // Find "d" in normalized unit time. 
            // Quadratic formula (to consider: simplified to 1 solution: b^2-ac. instead)
            var a:Number = ((ray_travel.x*ray_travel.x)/(ellipsoid_radius.x*ellipsoid_radius.x))
                    + ((ray_travel.y*ray_travel.y)/(ellipsoid_radius.y*ellipsoid_radius.y))
                    + ((ray_travel.z*ray_travel.z)/(ellipsoid_radius.z*ellipsoid_radius.z));
                var b:Number = ((2*ray_origin.x*ray_travel.x)/(ellipsoid_radius.x*ellipsoid_radius.x))
                        + ((2*ray_origin.y*ray_travel.y)/(ellipsoid_radius.y*ellipsoid_radius.y))
                        + ((2*ray_origin.z*ray_travel.z)/(ellipsoid_radius.z*ellipsoid_radius.z));
                var c:Number = ((ray_origin.x*ray_origin.x)/(ellipsoid_radius.x*ellipsoid_radius.x))
                        + ((ray_origin.y*ray_origin.y)/(ellipsoid_radius.y*ellipsoid_radius.y))
                        + ((ray_origin.z*ray_origin.z)/(ellipsoid_radius.z*ellipsoid_radius.z))
                        - 1;

                var d:Number = b*b-4*a*c;
                if ( d < 0 ) {  // no real roots
                    return false;
                }
                
                d = Math.sqrt(d);
                
                const multiplier:Number = 1/(2*a);
                var hit:Number = (-b + d)*multiplier;
                var hitsecond:Number = (-b - d)*multiplier;
                d = hit < hitsecond ? hit : hitsecond;  // 2 solutions, bah...
                if (d < 0) {
                    return false;
                }
                
                t = d * dt; 
                
                return t <= dt;   // collision happened within timeframe
        }
        
        override public function resolve():void {

            var cn:Vector3D = c1.collisionNormal;
            cn.x = c2.object.x - c1.object.x;
            cn.y = c2.object.y - c1.object.y;
            cn.z = c2.object.z - c1.object.z;
            cn.normalize();


            //relative velocity
            var dv:Vector3D = new Vector3D(c2.vx - c1.vx, c2.vy - c1.vy, c2.vz - c1.vz); //  p2.v.minus( p1.v );
            
            const p2Mass:Number = 1;
            const p1Mass:Number = 1;
            //const mass:Number = 1;
            
            //perfectly elastic impulse
            dv.x *= -2; dv.y *= -2; dv.z *= -2;
            var cn2:Vector3D = cn.clone();
            cn2.scaleBy( 1 / p1Mass + 1 / p2Mass );
        
            var impulse:Number = cn.dotProduct( dv  ) / cn.dotProduct( cn2);
            var multiplier:Number = -impulse / p1Mass;
            c1.vx += cn.x * multiplier;
            c1.vy += cn.y  * multiplier;
            c1.vz += cn.z * multiplier;
            multiplier = impulse / p2Mass;
            c2.vx += cn.x * multiplier;
            c2.vy += cn.y  * multiplier;
            c2.vz += cn.z * multiplier;
            
        }
        
    }

//}





//package cc3dexample.entity.collisions
//{
    import alternativ7.engine3d.core.EllipsoidCollider;
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.RayIntersectionData;
    import alternativ7.engine3d.materials.FillMaterial;

    import flash.geom.Vector3D;
    
    /**
     * Example:
     * Original implementation: http://wonderfl.net/c/8RNL 
     * generalrelativity's Elastic Collision
     * 
     * @author Glenn Ko
     */
    //public 
    class BallToWorld extends CC3DPair
    {
        
        public function BallToWorld() 
        {
        
        }

        
        override public function resolve():void 
        {
             var cn:Vector3D = c1.collisionNormal.clone();        
            
            //relative velocity
            var dv:Vector3D = new Vector3D(c1.vx, c1.vy, c1.vz);
            
            //perfectly elastic
            const mass:Number = 1;

            var impulse:Number = cn.dotProduct( Vector3DUtils.getNewScaledVector(dv,  -2 ) ) / ( 1 / mass );
            var scalar:Number =  impulse / mass;
            cn.scaleBy( scalar);
            dv.incrementBy( cn );
            c1.vx = dv.x;
            c1.vy = dv.y;
            c1.vz = dv.z;
        }
        
    }

//}



//package cc3dexample 
//{
    import alternativ7.engine3d.core.Face;
    import alternativ7.engine3d.alternativa3d;
    import alternativ7.engine3d.core.Wrapper;
    import alternativ7.engine3d.objects.Mesh;
    use namespace alternativa3d;
    /**
     * ...
     * @author Glenn Ko
     */
    //public
    class FaceMacros
    {
        
        public static function makeDoubleSided(mesh:Mesh):void {
              // Create new list of faces and combine them together
               var tailNewFace:Face;
               var newFace:Face;
               var headNewFace:Face;
               var lastFace:Face;
               for (var face:Face = mesh.faceList; face!=null; face= face.next) {
                    newFace = cloneFace(face);
                    flipFaces(newFace);
                    if (tailNewFace !=  null) tailNewFace.next = newFace
                    else headNewFace = newFace
                    tailNewFace = newFace;
                    lastFace = face;
               }
               // combine lists with new
               lastFace.next = headNewFace;
        }
        
        public static function cloneFace(face:Face):Face  
        {
            // Prepare cloned face 
            var clipFace:Face = face.create();
            clipFace.material = face.material;
            clipFace.offset = face.offset;
            clipFace.normalX = face.normalX;
            clipFace.normalY = face.normalY;
            clipFace.normalZ = face.normalZ;
            
            // deepCloneWrapper() inline
            var wrapper:Wrapper = face.wrapper;
            var wrapperClone:Wrapper = wrapper.create();
            wrapperClone.vertex = wrapper.vertex;

            var w:Wrapper = wrapper.next;
            var tailWrapper:Wrapper = wrapperClone;
            var wClone:Wrapper;
            while (w != null) {
                wClone = w.create();
                wClone.vertex = w.vertex;
                tailWrapper.next = wClone;
                tailWrapper = wClone;
                w = w.next;
            }
            
        
            clipFace.wrapper =  wrapperClone;
            return clipFace;
        }
        
        public static function flipFaces(list:Face):void {
            
            for (var f:Face = list; f != null; f = f.next) {
                // Flip normal/offset values
                f.normalX = -f.normalX;
                f.normalY = -f.normalY;
                f.normalZ = -f.normalZ;
                f.offset = -f.offset;
                
                // Reverse vertex order
                var nextWrapper:Wrapper;
                var headerWrapper:Wrapper = null;
                for (var w:Wrapper = f.wrapper; w != null; w = nextWrapper) {
                    nextWrapper = w.next;
                    w.next = headerWrapper;
                    headerWrapper = w;
                }
                f.wrapper = headerWrapper;
            }
            
        }
        
    }

//}


// -- CORE Framework code below (haxe-as3-output). Can ignore...

// CC3D Framework

//package alternsector.physics.adaptors.alternativa3d.ccd {
    
    import flash.geom.Vector3D;
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.EllipsoidCollider;

    //public 
    class CC3D {
        public function CC3D() : void {
            null;
        }
        
        public var object : alternativa.engine3d.core.Object3D;
        public var collider : alternativa.engine3d.core.EllipsoidCollider;
        public var vx : Number;
        public var vy : Number;
        public var vz : Number;
        public var entity : *;
        public var collisionGroupId : int;
        public var sleep : Boolean;
        public var staticCollision : CC3DPair;
        public var collisionPoint : flash.geom.Vector3D;
        public var collisionNormal : flash.geom.Vector3D;
        public var position : flash.geom.Vector3D;
        public var displacement : flash.geom.Vector3D;
        public var typeA : Boolean;
        public var sector : Sector;
        public var id : int;
        public var _parent : CC3DList;
        public var prev : CC3D;
        public var next : CC3D;
        public var boundMaxX : Number;
        public var boundMaxY : Number;
        public var boundMaxZ : Number;
        public var boundMinX : Number;
        public var boundMinY : Number;
        public var boundMinZ : Number;
        public var mass : Number;
        public function _integrate(dt : Number) : void {
            this.object.x += this.vx * dt;
            this.object.y += this.vy * dt;
            this.object.z += this.vz * dt;
        }
        
        public function _updateAABB(dt : Number) : void {
            var dest : Number = this.object.x + this.vx * dt;
            this.boundMinX = PMath.minF(this.object.x,dest) - this.collider.radiusX;
            this.boundMaxX = PMath.maxF(this.object.x,dest) + this.collider.radiusX;
            dest = this.object.y + this.vy * dt;
            this.boundMinY = PMath.minF(this.object.y,dest) - this.collider.radiusY;
            this.boundMaxY = PMath.maxF(this.object.y,dest) + this.collider.radiusY;
            dest = this.object.z + this.vz * dt;
            this.boundMinZ = PMath.minF(this.object.z,dest) - this.collider.radiusZ;
            this.boundMaxZ = PMath.maxF(this.object.z,dest) + this.collider.radiusZ;
        }
        
        public function isAABBOverlapping(sibling : CC3D) : Boolean {
            return !(this.boundMinX > sibling.boundMaxX || this.boundMinY > sibling.boundMaxY || this.boundMinZ > sibling.boundMaxZ || this.boundMaxX < sibling.boundMinX || this.boundMaxY < sibling.boundMinY || this.boundMaxZ < sibling.boundMinZ);
        }
        
        public function collidesWithWorld(dt : Number) : Boolean {
            this._updateVectors(dt);
            return this._gotCollideWithWorld(dt);
        }
        
        public function _updateVectors(dt : Number) : void {
            this.position.x = this.object.x;
            this.position.y = this.object.y;
            this.position.z = this.object.z;
            this.displacement.x = this.vx * dt;
            this.displacement.y = this.vy * dt;
            this.displacement.z = this.vz * dt;
        }
        
        public function _gotCollideWithWorld(dt : Number) : Boolean {
            return this.collider.getCollision(this.position,this.displacement,this.collisionPoint,this.collisionNormal,this.sector.collisionTarget);
        }
        
        public function _removeFromParent() : void {
            null;
        }
        
        public function _dispose() : void {
            null;
        }
        
        static public var collector : CC3D;
        static public function create(obj : alternativa.engine3d.core.Object3D,entity : *,collisionGroupId : int,vx : Number,vy : Number,vz : Number,radiusX : Number,radiusY : Number,radiusZ : Number,sector : Sector) : CC3D {
            var result : CC3D;
            if(CC3D.collector != null) {
                result = collector;
                result.collider.radiusX = radiusX;
                result.collider.radiusY = radiusY;
                result.collider.radiusZ = radiusZ;
                CC3D.collector = collector.next;
            }
            else {
                result = new CC3D();
                result.collider = new alternativa.engine3d.core.EllipsoidCollider(radiusX,radiusY,radiusZ);
                result.collisionNormal = new flash.geom.Vector3D();
                result.collisionPoint = new flash.geom.Vector3D();
                result.position = new flash.geom.Vector3D();
                result.displacement = new flash.geom.Vector3D();
            }
            result.next = null;
            result.sleep = false;
            result.sector = sector;
            result.mass = 1;
            result.typeA = true;
            result.object = obj;
            result.vx = vx;
            result.vy = vy;
            result.vz = vz;
            result.entity = entity;
            result.collisionGroupId = collisionGroupId;
            return result;
        }
        
        static public function createStatic(obj : alternativa.engine3d.core.Object3D) : void {
            var result : CC3D;
            if(CC3D.collector != null) {
                result = collector;
                CC3D.collector = collector.next;
            }
            else result = new CC3D();
            result.next = null;
            result.object = obj;
        }
        
    }
//}


//package alternsector.physics.adaptors.alternativa3d.ccd {

    //public 
    class CC3DList {
        public function CC3DList() : void {
            null;
        }
        
        public var head : CC3D;
        public function _integrate(dt : Number) : void {
            var h : CC3D = this.head;
            while(h != null) {
                h._integrate(dt);
                h = h.next;
            }
        }
        
        public function prepend(cc : CC3D) : void {
            if(this.head != null) null;
            cc.next = this.head;
            this.head = cc;
        }
        
    }
//}






//package alternsector.physics.adaptors.alternativa3d.ccd {

    //public 
    class CollisionTable {
        public function CollisionTable() : void { 
            this.reset();
        }
        
        protected var _COUNT : int;
        public function getNewCollisionGroupId(staticPairClasse : * = null,staticAllocate : int = 0) : int {
            var row : Vector.<CC3DPairPool> = new Vector.<CC3DPairPool>(this._COUNT);
            this._poolTable.push(row);
            var newPool : CC3DPairPool;
            {
                var _g1 : int = 0, _g : int = this._COUNT + 1;
                while(_g1 < _g) {
                    var i : int = _g1++;
                    newPool = new CC3DPairPool();
                    newPool.classe = CC3DPairPool;
                    row[i] = newPool;
                }
            }
            if(staticPairClasse != null) this.registerStaticCollisionPair(this._COUNT,staticPairClasse,staticAllocate);
            else this.registerStaticCollisionPair(this._COUNT,CC3DPair,0);
            return this._COUNT++;
        }
        
        public function setFilterMask(groupId : int,groupMask : int) : void {
            null;
        }
        
        public function registerStaticCollisionPair(groupId : int,classe : *,staticAmount : int = 0) : void {
            var newPool : CC3DPairPool = new CC3DPairPool();
            newPool.classe = classe;
            this._staticPoolTable[groupId] = newPool;
            if(staticAmount != 0) {
                newPool.allocate(staticAmount);
            }
        }
        
        protected var _poolTable : Vector.<Vector.<CC3DPairPool>>;
        protected var _staticPoolTable : Vector.<CC3DPairPool>;
        public function reset() : void {
            this._poolTable = new Vector.<Vector.<CC3DPairPool>>();
            this._staticPoolTable = new Vector.<CC3DPairPool>();
            this._COUNT = 0;
        }
        
        public function getPair(groupId1 : int,groupId2 : int) : CC3DPair {
            var pairPool : CC3DPairPool = this._poolTable[groupId1][groupId2];
            return pairPool.create();
        }
        
        public function getStaticPair(groupId1 : int) : CC3DPair {
            var pairPool : CC3DPairPool = this._staticPoolTable[groupId1];
            return pairPool.create();
        }
        
        public function registerCollisionPair(groupId : int,groupId2 : int,classe : *,allocateAmount : int = 0) : void {
            var pairPool : CC3DPairPool = new CC3DPairPool();
            pairPool.classe = classe;
            this._poolTable[groupId][groupId2] = pairPool;
            this._poolTable[groupId2][groupId] = pairPool;
            if(allocateAmount > 0) {
                pairPool.allocate(allocateAmount);
            }
        }
        
        public function finalize() : void {
            this._poolTable.fixed = true;
            {
                var _g1 : int = 0, _g : int = this._COUNT;
                while(_g1 < _g) {
                    var i : int = _g1++;
                    this._poolTable[i].fixed = true;
                }
            }
            this._staticPoolTable.fixed = true;
        }
        
        public function getStaticPool(id : int) : CC3DPairPool {
            return this._staticPoolTable[id];
        }
        
        public function getPool(id1 : int,id2 : int) : CC3DPairPool {
            return this._poolTable[id1][id2];
        }
        
        static protected var _instance : CollisionTable = new CollisionTable();
        static public function Get() : CollisionTable {
            return _instance;
        }
        
    }
//}

//package alternsector.physics.adaptors.alternativa3d.ccd {
    //public
    interface ICC3DWorld {
        function update(dtms : int) : void ;
    }
//}


//package alternsector.physics.adaptors.alternativa3d.ccd {

    import flash.geom.Vector3D;

    //public 
    class SectorPhysics {
        public function SectorPhysics() : void {
            null;
        }
        
        public var sector : Sector;
        public var wakeA : CC3DList;
        public var wakeB : CC3DList;
        public var sleepA : CC3DList;
        public var sleepB : CC3DList;
        public var sleepId : int;
        public var ccCount : int;
        public var staticPairList : CC3DPair;
        public var minPair : CC3DPair;
        public var pairList : CC3DPair;
        protected var _lastPair : CC3DPair;
        public var next : SectorPhysics;
        protected var _deltaTime : Number;
        public var _remainingTime : Number;
        protected var _collisionTable : CollisionTable;
        public function findClosestPair() : void {
            var pair : CC3DPair;
            var minT : Number = this._remainingTime;
            this.minPair = null;
            pair = this.staticPairList;
            while(pair != null) {
                if(pair.t < minT) {
                    this.minPair = pair;
                    minT = pair.t;
                }
                pair = pair.next;
            }
            pair = this.pairList;
            while(pair != null) {
                if(pair.willCollide(this._remainingTime) && pair.t < minT) {
                    this.minPair = pair;
                    minT = pair.t;
                }
                this._lastPair = pair;
                pair = pair.next;
            }
            this._deltaTime = minT;
        }
        
        protected function _init(sec : Sector) : void {
            this.wakeA = new CC3DList();
            this.wakeB = new CC3DList();
            this.sleepA = new CC3DList();
            this.sleepB = new CC3DList();
            this._reset();
            this.sector = sec;
            this._collisionTable = CollisionTable.Get();
            sec.physics = this;
        }
        
        protected function _reset() : void {
            this._deltaTime = 0;
            this.ccCount = 0;
            this.sleepId = -1;
        }
        
        public function integrateResolve() : void {
            if(this.minPair != null) {
                this.minPair.c1.staticCollision = null;
            }
            var deferedCollection : CC3DPair = this._integrate();
            if(this.minPair != null) {
                this.minPair.resolve();
            }
            var nextPair : CC3DPair;
            if(this._lastPair != null) {
                this._lastPair.next = deferedCollection;
                deferedCollection = this.pairList;
            }
            while(deferedCollection != null) {
                nextPair = deferedCollection.next;
                deferedCollection.destroy();
                deferedCollection = nextPair;
            }
            this._lastPair = null;
            this.pairList = null;
        }
        
        protected function _integrate() : CC3DPair {
            var pair : CC3DPair = this.staticPairList;
            this._remainingTime -= this._deltaTime;
            var nextPair : CC3DPair;
            var deferedCollection : CC3DPair = null;
            var lastPair : CC3DPair = null;
            while(pair != null) {
                nextPair = pair.next;
                if(pair.c1.staticCollision == null) {
                    if(lastPair != null) lastPair.next = nextPair;
                    else {
                        this.staticPairList = nextPair;
                    }
                    pair.next = deferedCollection;
                    deferedCollection = pair;
                    pair = nextPair;
                    continue;
                }
                pair.t -= this._deltaTime;
                lastPair = pair;
                pair = nextPair;
            }
            var dt : Number = this._deltaTime - 1e-8;
            this.wakeA._integrate(dt);
            this.wakeB._integrate(dt);
            this.sleepA._integrate(dt);
            this.sleepB._integrate(dt);
            return deferedCollection;
        }
        
        public function _notifyWake(remainingTime : Number) : void {
            this._remainingTime = remainingTime;
            this._deltaTime = remainingTime;
        }
        
        public function doCoarsePhase() : void {
            this._updateList(this.wakeA);
            this._collectMovingCollisionPairs();
        }
        
        protected function _collectMovingCollisionPairs() : void {
            var h : CC3D = this.wakeA.head;
            var v : CC3D;
            while(h != null) {
                v = h.next;
                while(v != null) {
                    if(h.isAABBOverlapping(v)) {
                        var pair : CC3DPair = this._getCollisionPairFor(h,v);
                        pair.next = this.pairList;
                        this.pairList = pair;
                    }
                    v = v.next;
                }
                h = h.next;
            }
        }
        
        protected function _updateList(list : CC3DList) : void {
            var h : CC3D = list.head;
            while(h != null) {
                h._updateAABB(this._remainingTime);
                h._updateVectors(this._remainingTime);
                if(h.staticCollision == null) {
                    var staticPair : CC3DPair = (h._gotCollideWithWorld(this._remainingTime)?this._getStaticCollisionFor(h):null);
                    if(staticPair != null) {
                        var collDisplacement : flash.geom.Vector3D = h.collisionPoint.subtract(h.position);
                        var dirNorm : flash.geom.Vector3D = collDisplacement.clone();
                        dirNorm.normalize();
                        dirNorm.scaleBy(-(h.collider.radiusX));
                        collDisplacement.x = collDisplacement.x + dirNorm.x;
                        collDisplacement.y = collDisplacement.y + dirNorm.y;
                        collDisplacement.z = collDisplacement.z + dirNorm.z;
                        var lengther : Number = (Vector3DUtils.lengthOf(collDisplacement));
                        var t : Number = lengther / Vector3DUtils.lengthOf(h.displacement) * this._remainingTime;
                        if(PMath.isNaN(t)) {
                            throw new Error("IT nAN!:" + this._remainingTime + " , " + t) + ", " + Vector3DUtils.lengthOf(collDisplacement) + ", " + collDisplacement;
                            t = 0;
                        }
                        if(t < 0) {
                            t = 0;
                            throw new Error("Delta time is lower than zero!");
                        }
                        staticPair.next = this.staticPairList;
                        this.staticPairList = staticPair;
                        staticPair.c1 = h;
                        staticPair.t = t;
                        h.staticCollision = staticPair;
                    }
                }
                h = h.next;
            }
        }
        
        protected function _getStaticCollisionFor(h : CC3D) : CC3DPair {
            var pair : CC3DPair = this._collisionTable.getStaticPair(h.collisionGroupId);
            pair.c1 = h;
            return pair;
        }
        
        protected function _getCollisionPairFor(h : CC3D,v : CC3D) : CC3DPair {
            var pair : CC3DPair = this._collisionTable.getPair(h.collisionGroupId,v.collisionGroupId);
            pair.c1 = h;
            pair.c2 = v;
            return pair;
        }
        
        public function addChild(cc : CC3D) : void {
            this.ccCount++;
            var list : CC3DList = (cc.sleep?(cc.typeA?this.sleepA:this.sleepB):(cc.typeA?this.wakeA:this.wakeB));
            list.prepend(cc);
        }
        
        public function removeChild(cc : CC3D) : void {
            cc._removeFromParent();
            cc._dispose();
            this.ccCount--;
        }
        
        public function dispose() : void {
            this.sector.physics = null;
            this.sector = null;
            this.minPair = null;
            this.next = collector;
            SectorPhysics.collector = this;
        }
        
        public function getDeltaTime() : Number {
            return this._deltaTime;
        }
        
        static public var EPSILON : Number = 1e-8;
        static public var collector : SectorPhysics;
        static public function Create(sec : Sector) : SectorPhysics {
            var result : SectorPhysics;
            if(SectorPhysics.collector != null) {
                result = collector;
                result.sector = sec;
                result._reset();
                sec.physics = result;
                SectorPhysics.collector = collector.next;
            }
            else {
                result = new SectorPhysics();
                result._init(sec);
            }
            return result;
        }
        
    }
//}



//package alternsector.physics.adaptors.alternativa3d.ccd {

    //public 
    class SectorWorld implements ICC3DWorld{
        public function SectorWorld(sleepBufferSize : int = 64) : void { 
            this._sleepCount = 0;
            this._sleepingSectors = new Vector.<SectorPhysics>(sleepBufferSize,true);
        }
        
        protected var _awakeSectors : SectorPhysics;
        protected var _sleepingSectors : Vector.<SectorPhysics>;
        protected var _sleepCount : int;
        protected var _traceError : Error;
        public function getTraceError() : Error {
            var err : Error = this._traceError;
            if(this._traceError != null) this._traceError = null;
            return err;
        }
        
        public function update(dtms : int) : void {
            var doSleep : Boolean;
            var doDispose : Boolean;
            var elapsed : Number = dtms * (1 / 1000);
            var iteration : int = 0;
            var sector : SectorPhysics;
            var nextSector : SectorPhysics;
            var tailSector : SectorPhysics;
            while(this._sleepCount > 0) {
                sector = this._sleepingSectors[--this._sleepCount];
                if(sector.sleepId < 0) throw new Error("ALREADY waken!");
                sector.sleepId = -1;
                sector.next = this._awakeSectors;
                this._awakeSectors = sector;
            }
            sector = this._awakeSectors;
            while(sector != null) {
                sector._notifyWake(elapsed);
                sector = sector.next;
            }
            while(this._awakeSectors != null) {
                sector = this._awakeSectors;
                while(sector != null) {
                    sector.doCoarsePhase();
                    sector = sector.next;
                }
                sector = this._awakeSectors;
                tailSector = null;
                while(sector != null) {
                    nextSector = sector.next;
                    sector.findClosestPair();
                    sector.integrateResolve();
                    doSleep = false;
                    doDispose = false;
                    if(doSleep = sector._remainingTime <= 0) {
                        if(tailSector != null) {
                            tailSector.next = nextSector;
                        }
                        else {
                            this._awakeSectors = nextSector;
                        }
                        if(doSleep) {
                            this.sleepSector(sector);
                            sector.next = null;
                        }
                        else {
                            throw new Error("THIs should not happen as of yet!");
                            sector.dispose();
                        }
                        sector = nextSector;
                        continue;
                    }
                    tailSector = sector;
                    sector = nextSector;
                }
                iteration++;
                if(iteration > 100) {
                    this._traceError = new Error("ERROR: MAx iterations reached!:" + tailSector._remainingTime + " left from: " + elapsed + ", +=" + tailSector.getDeltaTime());
                    break;
                }
            }
        }
        
        public function addCC3D(cc : CC3D) : void {
            var sector : Sector = cc.sector;
            var sectorPhysics : SectorPhysics;
            if(sector.physics != null) {
                sectorPhysics = sector.physics;
            }
            else {
                sectorPhysics = SectorPhysics.Create(sector);
                sectorPhysics.next = this._awakeSectors;
                this._awakeSectors = sectorPhysics;
            }
            sectorPhysics.addChild(cc);
        }
        
        protected function _wakeSector(sectorPhysics : SectorPhysics) : void {
            var tailIndex : int = this._sleepCount - 1;
            if(sectorPhysics.sleepId < 0) throw new Error("Sector isn't sleeping!");
            var secPhysics2 : SectorPhysics;
            if(sectorPhysics.sleepId != tailIndex) {
                secPhysics2 = this._sleepingSectors[tailIndex];
                secPhysics2.sleepId = sectorPhysics.sleepId;
                this._sleepingSectors[secPhysics2.sleepId] = secPhysics2;
                this._sleepingSectors[tailIndex] = null;
            }
            else {
                this._sleepingSectors[sectorPhysics.sleepId] = null;
            }
            this._sleepCount--;
            sectorPhysics.sleepId = -1;
            sectorPhysics.next = this._awakeSectors;
            this._awakeSectors = sectorPhysics;
        }
        
        protected function sleepSector(sectorPhysics : SectorPhysics) : void {
            sectorPhysics.sleepId = this._sleepCount;
            this._sleepingSectors[this._sleepCount++] = sectorPhysics;
        }
        
        public function removeCC3D(cc : CC3D) : void {
            var sectorNode : SectorPhysics = cc.sector.physics;
            sectorNode.removeChild(cc);
            if(sectorNode.ccCount == 0) {
                sectorNode.dispose();
            }
        }
        
        static protected var MAX_ITERATIONS : int = 100;
        static protected var MS : Number = 1 / 1000;
    }
//}


// -- Vector3DUtils

//package alternsector.physics.adaptors.utils {
    import flash.geom.Vector3D;
    //public 
    class Vector3DUtils {
        static public function distanceBetween(p1 : flash.geom.Vector3D,p2 : flash.geom.Vector3D) : Number {
            var dx : Number = p2.x - p1.x;
            var dy : Number = p2.y - p1.y;
            var dz : Number = p2.z - p1.z;
            return Math.sqrt(dx * dx + dy * dy + dz * dz);
        }
        
        static public function lengthOf(vec : flash.geom.Vector3D) : Number {
            return Math.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
        }
        
        static public function getNewScaledVector(src : flash.geom.Vector3D,scalar : Number) : flash.geom.Vector3D {
            return new flash.geom.Vector3D(src.x * scalar,src.y * scalar,src.z * scalar);
        }
        
    }
//}

//package alternsector.math {
    //public
    class PMath {
        static public function isNaN(val : Number) : Boolean {
            return val != val;
        }
        
        static public function min(x : int,y : int) : int {
            return (x < y?x:y);
        }
        
        static public function minF(x : Number,y : Number) : Number {
            return (x < y?x:y);
        }
        
        static public function max(x : int,y : int) : int {
            return (x > y?x:y);
        }
        
        static public function maxF(x : Number,y : Number) : Number {
            return (x > y?x:y);
        }

    }
//}