todo: Convex Mesh cutting by plane and Dismemberment

by Glidias
♥0 | Line 129 | Modified 2012-10-23 16:11:48 | MIT License
play

ActionScript3 source code

/**
 * Copyright Glidias ( http://wonderfl.net/user/Glidias )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/oi2s
 */

package
{
    import alternativ7.engine3d.containers.ConflictContainer;
    import alternativ7.engine3d.controllers.SimpleObjectController;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.Face;
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.core.Vertex;
    import alternativ7.engine3d.core.View;
    import alternativ7.engine3d.core.Wrapper;
    import alternativ7.engine3d.materials.AverageLightMaterial;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.materials.Material;
    import alternativ7.engine3d.objects.BSP;
    import alternativ7.engine3d.objects.Mesh;
    import alternativ7.engine3d.primitives.Box;
    import alternativ7.engine3d.primitives.GeoSphere;
    import alternativ7.engine3d.primitives.Plane;
    import alternativ7.engine3d.primitives.Sphere;
    import flash.display.BitmapData;

    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.geom.Vector3D;
    
    
    import alternativ7.engine3d.alternativa3d;
    use namespace alternativa3d;
    
    [SWF(backgroundColor=0)]
    public class MeshSplitTest extends Sprite
    {
        /*/////////////////////////////////
        * public variables
        /*/////////////////////////////////
        

        //ビュー
        public var view:View;
        
        public var camera:Camera3D;
        
        public var cameraController:SimpleObjectController;
        
        public var isRendering:Boolean = false;
        static public const GROUND_SIZE:Number  = 300;
        static public const GROUND_HEIGHT:Number  = 140;
        static public const SEGMENT:int = 8;
        
          /*/////////////////////////////////
        * private variables
        /*/////////////////////////////////
        
        private var _root:Object3DContainer;
        private var _cc:Object3DContainer;
        
        
        /*/////////////////////////////////
        * public methods
        /*/////////////////////////////////
        
        //Constractor
        public function MeshSplitTest()
        {
            if( stage ){ _init(); }
            else{ addEventListener( Event.ADDED_TO_STAGE, _init ); }
        }
        
        
        /*/////////////////////////////////
        * private methods
        /*/////////////////////////////////
        
        protected function _init( e:Event = null ):void
        {
            removeEventListener( Event.ADDED_TO_STAGE, _init );
            
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
          
            view = new View( stage.stageWidth, stage.stageHeight );
            addChild( view );
             _root = new Object3DContainer();
             
            camera = new Camera3D();
            camera.view = view;
            _root.addChild( camera );
            
            camera.x = -500;
            camera.y = 0;
            camera.z = 0;
           
            
           
            _cc = new ConflictContainer();
            _root.addChild( _cc );

            
            var box:Mesh =  new GeoSphere(100, 2,false);//new Box(200, 200, 200);
            _cc.addChild( box );
            box.setMaterialToAllFaces( new FillMaterial(0xFF0000, 1, 1, 0xFFFFFF) );
            
            // CLIP PLANE
            var plane:Plane = new Plane(400, 400, 1,1);
            //plane.sorting = 2;
            //_cc.addChild(plane);
        
            var boxMat:FillMaterial  = new FillMaterial(0xFF0000, 1, 1, 0xFFFFFF);
            var innerBoxMat:FillMaterial  = new FillMaterial(0x0000FF, 1, 1, 0xFFFFFF);
            plane.setMaterialToAllFaces( boxMat );
            var verts:Vector.<Vertex> = plane.faceList.vertices;
            
            var v:Vertex;
            var f:Face; var w:Wrapper;
            box.weldVertices(0,1);
            // Identity original vertices that belong to original box
            for (v = box.vertexList; v != null; v = v.next) {
                v.id = box; 
            }
    
            var threshold:Number = 0.01;
            
            // Mesh.split( a, b, c, threshold) - a b c are probably transformed vertex positions of clipping plane in local coordinate space in order to get the necessary clip plane normal with cross product and clip offset with dot product. 
            ///*
            var a:Vector3D = new Vector3D(verts[0].x, verts[0].y, verts[0].z);
            var b:Vector3D = new Vector3D(verts[1].x, verts[1].y, verts[1].z);
            var c:Vector3D = new Vector3D(verts[2].x, verts[2].y, verts[2].z);
            var boxes:Vector.<Object3D> = box.split(a, b, c, threshold);
            _cc.addChild( boxes[0] );
            _cc.addChild( boxes[1] );
            //*/
            
            boxes[1].z -= 20;
            
            
            
            // Do filling up of inner cross-section polygon vertices in anti-clockwise order (NEED help on this, how to arrange vertices in anti-clockwise order from a given plane?)  
           /*
            var clipPlaneNorm:Vector3D = b.subtract(a).crossProduct(c.subtract(a));
            clipPlaneNorm.normalize();
            var clipPlaneOffset:Number =  a.dotProduct(clipPlaneNorm);
            
            var vertices:Vector.<Vertex> = new Vector.<Vertex>();
            var offset:Number
            
            // #1
            box = boxes[0] as Mesh;
            vertices.length = 0;
            for (v = box.vertexList; v != null; v = v.next) {
                offset = new Vector3D(v.x, v.y, v.z).dotProduct(clipPlaneNorm);
                if ( v.id == null && offset >= clipPlaneOffset - threshold && offset <= clipPlaneOffset + threshold) {
                    vertices.push(v);
                }
            }
           // vertices = getWeldedVerts(vertices, box);
            f = box.addFace(vertices, innerBoxMat);
            f.normalX = clipPlaneNorm.x;
            f.normalY = clipPlaneNorm.y;
            f.normalZ = clipPlaneNorm.z;
            f.offset = clipPlaneOffset;
            
            //throw new Error(f.vertices);
            
            // #2
            clipPlaneNorm = new Vector3D( -clipPlaneNorm.x, -clipPlaneNorm.y, -clipPlaneNorm.z);
            clipPlaneOffset = -clipPlaneOffset;
        
            box = boxes[1] as Mesh;
            vertices.length = 0;
            for (v = box.vertexList; v != null; v = v.next) {
                offset = new Vector3D(v.x, v.y, v.z).dotProduct(clipPlaneNorm);
                if ( v.id == null && offset >= clipPlaneOffset - threshold && offset <= clipPlaneOffset + threshold) {
                    vertices.push(v);
                }
            }
           // vertices = getWeldedVerts(vertices, box);
            f = box.addFace(vertices, innerBoxMat);
            f.normalX = clipPlaneNorm.x;
            f.normalY = clipPlaneNorm.y;
            f.normalZ = clipPlaneNorm.z;
            f.offset = clipPlaneOffset;
      //  */
            
        //    throw new Error(f.vertices.length);
            
            cameraController = new SimpleObjectController( stage, camera, 200);
            cameraController.lookAt(box);
            
            startRender();
        }
        
       
        private function getWeldedVerts(verts:Vector.<Vertex>, ider:*):Vector.<Vertex> {
            var len:int = verts.length;
            var testA:Vector3D = new Vector3D();
            var testB:Vector3D = new Vector3D();
            var newList:Vector.<Vertex> = new Vector.<Vertex>();
            for (var i:int = 0; i < len; i++) {
                var thisVert:Vertex = verts[i];
                if (thisVert.id == null) {
                    testA.x = thisVert.x;
                    testA.y = thisVert.y;
                    testA.z = thisVert.z;
                    newList.push(thisVert);
                    thisVert.id = ider;    
                }
                else continue;
                
                for (var u:int = i + 1; u < len; u++) {
                    var otherVert:Vertex = verts[u];
                    if (otherVert.id === ider) continue;
                    testB.x = otherVert.x;
                    testB.y = otherVert.y;
                    testB.z = otherVert.z;
                    if (testA.equals(testB)) otherVert.id = ider;
                }
            }
            return newList;
        }

        
        
        public function startRender():void
        {
            isRendering = true;
            addEventListener( Event.ENTER_FRAME, _enterFrameHandler );
        }
        
        
        public function stopRender():void
        {
            removeEventListener( Event.ENTER_FRAME, _enterFrameHandler );
            isRendering = false;
        }
        
        public function update():void
        {
   
            cameraController.update();
         
            camera.render();
            
           
        }
        
        protected function _enterFrameHandler( e:Event ):void
        {
            update();
        }
        
        


        
    }
}