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

Raytracing Voxel Demo with 3D Bresenham's line algorithm

A simple demo using Ray Tracing and 3D Bresenham's line algorithm to render Voxels.
Details:http://bruce-lab.blogspot.com/2011/08/simple-ray-tracing-voxel-demo.html
Get Adobe Flash player
by Bruce_Jawn 27 Nov 2011
/**
 * Copyright Bruce_Jawn ( http://wonderfl.net/user/Bruce_Jawn )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gUA8
 */

/**
*Simple Raytracing Voxel Demo with 3D DDA/Bresenham's line algorithm
*November 27, 2011
*Bruce Jawn
*http://bruce-lab.blogspot.com
*
*Copyright (c) <2011> <Bruce Jawn>
*This software is released under the MIT License
*<http://www.opensource.org/licenses/mit-license.php>
**/
package {
    import flash.display.*;
    import flash.events.*;
    [SWF(backgroundColor = 0x0, width = 256, height = 256, frameRate = 30)]
    public class RaytracingVoxel3DDDA extends Sprite {

        var eyeX:int=128;
        var eyeY:int=128;
        var eyeZ:int=-300;

        var rayX:Number;
        var rayY:Number;
        var rayZ:Number;
        var rayLen:Number;

        var color:uint;

        var xx:int=0;
        var yy:int=0;
        var zz:int=0;

        var voxelData:Array=[];

        private var ScreenData:BitmapData=new BitmapData(256,256,false,0xffff00);
        private var Screen:Bitmap=new Bitmap(ScreenData);

        public function RaytracingVoxel3DDDA():void {
            createVoxel();
            addChild(Screen);
            addEventListener(Event.ENTER_FRAME,render);
        }//end of RaytracingVoxel

        private function createVoxel():void {
            //bounding box
            for (var i:int=0; i<256; i++) {
                for (var j:int=0; j<256; j++) {
                    color=0xffffff;
                    voxelData[i<<16|j<<8|255]=color;
                    voxelData[i<<16|255<<8|j]=color;
                    voxelData[255<<16|i<<8|j]=color;
                    voxelData[i<<16|0<<8|j]=color;
                    voxelData[0<<16|i<<8|j]=color;
                }
            }
            //bounding box outline
            for each(var i in [0,1,2,255,254,253]){
                for (var j:int=0; j<256; j++) {
                    color=0xff0000;
                    voxelData[i<<16|j<<8|255]=color;
                    voxelData[i<<16|255<<8|j]=color;
                    voxelData[255<<16|i<<8|j]=color;
                    voxelData[i<<16|0<<8|j]=color;
                    voxelData[0<<16|i<<8|j]=color;
                }
            }
            for (var i:int=0; i<256; i++){
                for each(var j in [0,1,2,255,254,253]){
                    color=0xff0000;
                    voxelData[i<<16|j<<8|255]=color;
                    voxelData[i<<16|255<<8|j]=color;
                    voxelData[255<<16|i<<8|j]=color;
                    voxelData[i<<16|0<<8|j]=color;
                    voxelData[0<<16|i<<8|j]=color;
                }
            }
            
            //cube
            for (var i:int=2; i<64; i++) {
                for (var j:int=2; j<64; j++) {
                    color=0xff;
                    voxelData[i<<16|63<<8|j]=color;
                    voxelData[63<<16|i<<8|j]=color;
                    voxelData[i<<16|2<<8|j]=color;
                    voxelData[2<<16|i<<8|j]=color;
                    voxelData[i<<16|j<<8|2]=color;
                }
            }
            //cube outline
            for each(var i in [2,3,63,62]){
                for (var j:int=2; j<64; j++) {
                    color=0xff0000;
                    voxelData[i<<16|63<<8|j]=color;
                    voxelData[63<<16|i<<8|j]=color;
                    voxelData[i<<16|2<<8|j]=color;
                    voxelData[2<<16|i<<8|j]=color;
                    voxelData[i<<16|j<<8|2]=color;
                }
            }
            for (var i:int=2; i<64; i++){
                for each(var j in [2,3,63,62]){
                    color=0xff0000;
                    voxelData[i<<16|63<<8|j]=color;
                    voxelData[63<<16|i<<8|j]=color;
                    voxelData[i<<16|2<<8|j]=color;
                    voxelData[2<<16|i<<8|j]=color;
                    voxelData[i<<16|j<<8|2]=color;
                }
            }
            
            //sphere
            for (var i:int=-64; i<64; i++) {
                for (var j:int=-64; j<64; j++) {
                    for (var k:int=-64; k<64; k++) {
                        if (i*i+j*j+k*k<64*64) {
                            voxelData[(i+128)<<16|(j+128)<<8|(k+64)]=0xff00;
                        }
                    }
                }
            }

        }//end of createVoxel

        private function render(event:Event):void {
            ScreenData.lock();
            
            for (var yy:int =0; yy<256; yy++) {
                rayX=xx-eyeX;
                rayY=yy-eyeY;
                rayZ=- eyeZ;

                rayLen=Math.sqrt(rayX*rayX+rayY*rayY+rayZ*rayZ);
                rayX/=rayLen;
                rayY/=rayLen;
                rayZ/=rayLen;
                color=0xffffff;
                
                //Bresenham's line algorithm in 3D, ported from: [http://www.cobrabytes.com/index.php?topic=1150.0]
                var nx:int, x0:int, x1:int, delta_x:int, step_x:int;//:integer
                var ny:int, y0:int, y1:int, delta_y:int, step_y:int;//:integer
                var nz:int, z0:int, z1:int, delta_z:int, step_z:int;//:integer
                var swap_xy:int, swap_xz:int;//:boolean
                var drift_xy:int, drift_xz:int;//:integer
                var cx:int, cy:int, cz:int;//:integer  
                swap_xy=swap_xz=0;
                x0=xx;y0=yy;z0=0;
                x1=x0+600*rayX;y1=y0+600*rayY;z1=z0+600*rayZ;
                //'steep' xy Line, make longest delta x plane 
                if(Math.abs(y1-y0)>Math.abs(x1-x0))
                {
                    var temp:int=x0;
                    x0=y0;
                    y0=temp;
                    temp=x1;
                    x1=y1;
                    y1=temp;
                    swap_xy=1;
                } 
                if(Math.abs(z1-z0)>Math.abs(x1-x0))
                {
                    var temp:int=x0;
                    x0=z0;
                    z0=temp;
                    temp=x1;
                    x1=z1;
                    z1=temp;
                    swap_xz=1;
                }
                
                //delta is Length in each plane
                delta_x = Math.abs(x1 - x0);
                delta_y = Math.abs(y1 - y0);
                delta_z = Math.abs(z1 - z0);
                
                //drift controls when to step in 'shallow' planes
                //starting value keeps Line centred
                drift_xy = (delta_x / 2);
                drift_xz = (delta_x / 2);
                
                //direction of line
                step_x = 1;  if (x0 > x1) step_x = -1;
                step_y = 1;  if (y0 > y1) step_y = -1;
                step_z = 1;  if (z0 > z1) step_z = -1;

                //starting point
                ny = y0;
                nz = z0;

                //step through longest delta (which we have swapped to x)
                for (nx = x0; nx!= x1; nx+=step_x)
                {    
                    //copy position
                    cx = nx;    cy = ny;    cz = nz;

                    //unswap (in reverse)
                    if (swap_xz) //then Swap(cx, cz)
                    {
                        var temp:int=cx;
                        cx=cz;
                        cz=temp;
                    }
                    if (swap_xy) //then Swap(cx, cy)
                    {
                        var temp:int=cx;
                        cx=cy;
                        cy=temp;
                    }
                    
                    //passes through this point
                    //debugmsg(":" + cx + ", " + cy + ", " + cz)
                    //trace(":" + cx + ", " + cy + ", " + cz);

                    //update progress in other planes
                    drift_xy = drift_xy - delta_y;
                    drift_xz = drift_xz - delta_z;

                    //step in y plane
                    if (drift_xy < 0 )
                    {
                        ny = ny + step_y;
                        drift_xy = drift_xy + delta_x;
                    }  
                    
                    //same in z
                    if (drift_xz < 0 )
                    {
                        nz = nz + step_z;
                        drift_xz = drift_xz + delta_x;
                    }

                    if ((x>256)||(y>256)||(z>256)) {
                        break;
                    }
                    if (voxelData[cx<<16|cy<<8|cz]>0) {
                        color=voxelData[cx<<16|cy<<8|cz];
                        break;
                    }

                }//end of for nx
                ScreenData.setPixel(xx,yy,color);
            }//end of for yy
            
            ScreenData.unlock();
            xx++;
            if (xx>256) {
                removeEventListener(Event.ENTER_FRAME,render);
                //(new SavingBitmap(ScreenData)).save("trace.png");
            }
        }

    }//end of class
}//end of package