notice: Flash editor updated! Join the development! Thanks to MiniBuilder


embed

FORKED
  1. // forked from keim_at_Si's Ambient Occlusion Rendering
  2. // Ambient Occlusion Bench Flash10 porting
  3. //   Original version of AO bench was written by Syoyo Fujita.
  4. //     http://lucille.atso-net.jp/aobench/
  5. //   In original Flash10 porting, it takes 7 times slower than the Proce55ing.
  6. //   (refer from http://lucille.atso-net.jp/blog/?p=638).
  7. //   And now, it seems to be same speed as the Proce55ing does.
  8. //----------------------------------------------------------------------
  9. package {
  10.     import flash.display.*;
  11.     import flash.text.*;
  12.     import flash.events.*;
  13.     
  14.     [SWF(frameRate = "1000", backgroundColor = "#808080")]
  15.     public class main extends Sprite {
  16.         private var _tf:TextField = new TextField();
  17.         private var _screen:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0xffffff);
  18.         private var _renderY:int;
  19.         
  20.         function main() { 
  21.             _tf.autoSize = 'left';
  22.             _tf.htmlText = "<font color='#ffffff'>Rendering...</font>";
  23.             addChild(_tf);
  24.             with(addChild(new Bitmap(_screen))){ x = y = 104.5; }
  25.             
  26.             _renderY = 0;
  27.             
  28.             addEventListener("enterFrame", _startRender);
  29.         }
  30.         
  31.         private function _startRender(e:Event) : void {
  32.             // rendering
  33.             render.rasterRendering(_renderY);
  34.             
  35.             // copy pixels
  36.             _screen.lock();
  37.             for (var x:int=0; x<WIDTH; x++) _screen.setPixel(x, _renderY, render.output[x]);
  38.             _screen.unlock();
  39.             
  40.             // increment
  41.             _renderY++;
  42.             if (_renderY == 256) {
  43.                 // finish rendering
  44.                 _tf.htmlText = "<font color='#ffffff'>Rendering time : " + String(render.renderingTime/1000) + "[sec]</font>";
  45.                 removeEventListener("enterFrame", _startRender);
  46.             }
  47.         }
  48.     }
  49. }
  50. import flash.display.*;
  51. import flash.geom.*;
  52. import flash.utils.getTimer;
  53. // global variables
  54. //--------------------------------------------------------------------------------
  55. const WIDTH :int = 256;
  56. const HEIGHT:int = 256;
  57. const NSUBSAMPLES:int = 2;
  58. const NAO_SAMPLES:int = 2;
  59. var render:Render = new Render();
  60. // structures
  61. //--------------------------------------------------------------------------------
  62. class Isect {
  63.     public var t:Number = 0;
  64.     public var p:Vector3D = new Vector3D();
  65.     public var n:Vector3D = new Vector3D();
  66.     public var hit:int = 0;
  67. }
  68. class Ray {
  69.     public var org:Vector3D = new Vector3D();
  70.     public var dir:Vector3D = new Vector3D();
  71. }
  72. class Sphere {
  73.     public var center:Vector3D;
  74.     public var radius2:Number;
  75.     function Sphere(center:Vector3D, radius:Number) {
  76.         this.center = center;
  77.         this.radius2 = radius*radius;
  78.     }
  79. }
  80. class Plane {
  81.     public var p:Vector3D;
  82.     public var n:Vector3D;
  83.     public var pn:Number;
  84.     function Plane(p:Vector3D, n:Vector3D) {
  85.         this.p = p;
  86.         this.n = n;
  87.         this.pn = n.x*p.x + n.y*p.y + n.z*p.z;
  88.     }
  89. }
  90. // render
  91. //--------------------------------------------------------------------------------
  92. class Render {
  93. // variables
  94. //--------------------------------------------------
  95.     public var output:Vector.<uint>;
  96.     public var renderingTime:int;
  97.     private var spheres:Vector.<Sphere> = new Vector.<Sphere>(3true);
  98.     private var plane:Plane;
  99.     
  100.     
  101. // constructor
  102. //--------------------------------------------------
  103.     function Render() {
  104.         _initScene();
  105.         renderingTime = 0;
  106.         output = new Vector.<uint>(WIDTH, true);
  107.     }
  108.     
  109.     
  110. // rendering
  111. //--------------------------------------------------
  112.     public function rasterRendering(y:int) : void {
  113.         var t:int = getTimer();
  114.         _render(output, WIDTH, HEIGHT, y);
  115.         renderingTime += getTimer() - t;
  116.     }
  117.     
  118. // privates
  119. //--------------------------------------------------
  120.     // initialize scene
  121.     private function _initScene() : void {
  122.         spheres[0] = new Sphere(new Vector3D(-2.00.0, -3.5), 0.5);
  123.         spheres[1] = new Sphere(new Vector3D(-0.50.0, -3.0), 0.5);
  124.         spheres[2] = new Sphere(new Vector3D( 1.00.0, -2.2), 0.5);
  125.         plane      = new Plane(new Vector3D(0.0, -0.50.0), new Vector3D(0.01.00.0));
  126.     }
  127.     
  128.     
  129.     // render
  130.     private var ray:Ray = new Ray();
  131.     private var isect:Isect = new Isect();
  132.     private function _render(line:Vector.<uint>, w:int, h:int, y:int) : void {
  133.         var idx:int, x:int, u:int, v:int, du:Number, dv:Number, pixel:uint, ao:Vector3D, 
  134.             hw :Number = w*0.5, hh :Number = h*0.5
  135.             ihw:Number = 1/hw,  ihh:Number = 1/hh,
  136.             step:Number = 1/NSUBSAMPLES, 
  137.             occlusionPerPixel:Number = 1/(NSUBSAMPLES*NSUBSAMPLES),
  138.             color:Vector3D = new Vector3D();
  139.         // scan all pixels
  140.         idx = 0;
  141.         for (x = 0; x < w; x++) {
  142.             // initialize pixel color
  143.             color.x = 0;
  144.             color.y = 0;
  145.             color.z = 0;
  146.             
  147.             // sub samplings
  148.             for (v = 0, dv = 0; v < NSUBSAMPLES; v++, dv += step) {
  149.                 for (u = 0, du = 0; u < NSUBSAMPLES; u++, du += step) {
  150.                     // initialize ray vectors
  151.                     ray.org.x = 0.0;
  152.                     ray.org.y = 0.0;
  153.                     ray.org.z = 0.0;
  154.                     ray.dir.x =  (x + du - hw) * ihw;
  155.                     ray.dir.y = -(y + dv - hh) * ihh;
  156.                     ray.dir.z = -1.0;
  157.                     ray.dir.normalize();
  158.                     // check ray intersections
  159.                     isect.p.x = isect.p.y = isect.p.z = 0.0;
  160.                     isect.n.x = isect.n.y = isect.n.z = 0.0;
  161.                     isect.t   = 1.0e+17;
  162.                     isect.hit = 0;
  163.                     _intersectBySphere(isect, ray, spheres[0]);
  164.                     _intersectBySphere(isect, ray, spheres[1]);
  165.                     _intersectBySphere(isect, ray, spheres[2]);
  166.                     _intersectByPlane (isect, ray, plane);
  167.                     // when the ray is intersected, calculate ambient occlusion color.
  168.                     if (isect.hit) {
  169.                         color.incrementBy(_ambientOcclusion(isect));
  170.                     }
  171.                 }
  172.             }
  173.             
  174.             // calculate gray scale
  175.             color.scaleBy(occlusionPerPixel);
  176.             pixel = 0xff000000;
  177.             pixel |=  (color.x >= 1) ? 255 : (color.x <= 0) ? 0 : int(color.x * 255);
  178.             pixel |= ((color.y >= 1) ? 255 : (color.y <= 0) ? 0 : int(color.x * 255)) << 8;
  179.             pixel |= ((color.z >= 1) ? 255 : (color.z <= 0) ? 0 : int(color.x * 255)) << 16;
  180.             output[idx] = pixel;
  181.             
  182.             // increment index
  183.             idx++;
  184.         }
  185.     }
  186.     
  187.     
  188.     // calculate ambient occlusion
  189.     private var aoRay:Ray = new Ray();
  190.     private var aoIsect:Isect = new Isect();
  191.     private var aoColor:Vector3D = new Vector3D();
  192.     private var basis0:Vector3D = new Vector3D();
  193.     private var basis1:Vector3D = new Vector3D();
  194.     private var basis2:Vector3D = new Vector3D();
  195.     private function _ambientOcclusion(isect:Isect) : Vector3D {
  196.         var i:int, j:int, th:Number, ph:Number,
  197.             x:Number,  y:Number,  z:Number,
  198.             rx:Number, ry:Number, rz:Number,
  199.             ntheta:int = NAO_SAMPLES,
  200.             nphi:int   = NAO_SAMPLES,
  201.             occlusionPerSample:Number = 1 / (ntheta*nphi),
  202.             eps:Number = 0.0001,
  203.             occlusion:Number = 1.0;
  204.         
  205.         // calculate transform matrix from local to global.
  206.         // the "local" coordinate is based on the normal vector at intersected point.
  207.         basis2 = isect.n;
  208.         basis1.x = 0.0;
  209.         basis1.y = 0.0;
  210.         basis1.z = 0.0;
  211.              if ((isect.n.x < 0.6) && (isect.n.x > -0.6)) basis1.x = 1.0;
  212.         else if ((isect.n.y < 0.6) && (isect.n.y > -0.6)) basis1.y = 1.0;
  213.         else if ((isect.n.z < 0.6) && (isect.n.z > -0.6)) basis1.z = 1.0;
  214.         else                                              basis1.x = 1.0;
  215.         vcross(basis0, basis1, basis2).normalize();
  216.         vcross(basis1, basis2, basis0).normalize();
  217.         // calculate the origin of the second ray
  218.         aoRay.org.x = isect.p.x + eps * isect.n.x;
  219.         aoRay.org.y = isect.p.y + eps * isect.n.y;
  220.         aoRay.org.z = isect.p.z + eps * isect.n.z;
  221.         
  222.         // calculate the ambient occlusion at intersected point
  223.         for (j = 0; j < ntheta; j++) {
  224.             for (i = 0; i < nphi; i++) {
  225.                 // calculate the direction of the second ray
  226.                 th = Math.sqrt(Math.random());
  227.                 ph = 6.283185307179586 * Math.random();
  228.                 x = Math.cos(ph) * th;
  229.                 y = Math.sin(ph) * th;
  230.                 z = Math.sqrt(1.0 - th * th);
  231.                 // transform second ray vector from local to global
  232.                 aoRay.dir.x = x * basis0.x + y * basis1.x + z * basis2.x;
  233.                 aoRay.dir.y = x * basis0.y + y * basis1.y + z * basis2.y;
  234.                 aoRay.dir.z = x * basis0.z + y * basis1.z + z * basis2.z;
  235.                 // check second ray intersections 
  236.                 aoIsect.p.x = aoIsect.p.y = aoIsect.p.z = 0.0;
  237.                 aoIsect.n.x = aoIsect.n.y = aoIsect.n.z = 0.0;
  238.                 aoIsect.t   = 1.0e+17;
  239.                 aoIsect.hit = 0;
  240.                 _intersectBySphere(aoIsect, aoRay, spheres[0]);
  241.                 _intersectBySphere(aoIsect, aoRay, spheres[1]);
  242.                 _intersectBySphere(aoIsect, aoRay, spheres[2]);
  243.                 _intersectByPlane (aoIsect, aoRay, plane);
  244.                 // when the second ray is intersected, increase the occlusion.
  245.                 if (aoIsect.hit) occlusion -= occlusionPerSample;
  246.             }
  247.         }
  248.         // return result
  249.         aoColor.x = occlusion;
  250.         aoColor.y = occlusion;
  251.         aoColor.z = occlusion;
  252.         return aoColor;
  253.         
  254.         // cross product
  255.         function vcross(c:Vector3D, v0:Vector3D, v1:Vector3D) : Vector3D {
  256.             c.x = v0.y * v1.z - v0.z * v1.y;
  257.             c.y = v0.z * v1.x - v0.x * v1.z;
  258.             c.z = v0.x * v1.y - v0.y * v1.x;
  259.             return c;
  260.         }
  261.     }
  262.     
  263.     
  264.     // check ray intersection by sphere
  265.     private function _intersectBySphere(isect:Isect, ray:Ray, sph:Sphere) : void {
  266.         var rsx:Number = ray.org.x - sph.center.x,
  267.             rsy:Number = ray.org.y - sph.center.y,
  268.             rsz:Number = ray.org.z - sph.center.z,
  269.             B:Number = rsx*ray.dir.x + rsy*ray.dir.y + rsz*ray.dir.z,
  270.             C:Number = rsx*rsx + rsy*rsy + rsz*rsz - sph.radius2,
  271.             D:Number = B * B - C;
  272.         // when the ray is intersected by the sphere,
  273.         if (D > 0.0) {
  274.             var t:Number = -B - Math.sqrt(D);
  275.             
  276.             if ((t > 0.0) && (t < isect.t)) {
  277.                 // calculate cross point and normal vector.
  278.                 isect.t = t;
  279.                 isect.hit = 1;
  280.                 
  281.                 isect.p.x = ray.org.x + ray.dir.x * t;
  282.                 isect.p.y = ray.org.y + ray.dir.y * t;
  283.                 isect.p.z = ray.org.z + ray.dir.z * t;
  284.                 isect.n.x = isect.p.x - sph.center.x;
  285.                 isect.n.y = isect.p.y - sph.center.y;
  286.                 isect.n.z = isect.p.z - sph.center.z;
  287.                 isect.n.normalize();
  288.             }
  289.         }
  290.     }
  291.     
  292.     // check ray intersection by plane
  293.     private function _intersectByPlane(isect:Isect, ray:Ray, pln:Plane) : void {
  294.         var v:Number = pln.n.x*ray.dir.x + pln.n.y*ray.dir.y + pln.n.z*ray.dir.z;
  295.         
  296.         // when parallel with plane
  297.         if (v>-1.0e-17 && v<1.0e-17return;
  298.         
  299.         var t:Number = -(pln.n.x*ray.org.x + pln.n.y*ray.org.y + pln.n.z*ray.org.z - pln.pn) / v;
  300.         // when the ray is intersected by the plane,
  301.         if ((t > 0.0) && (t < isect.t)) {
  302.             // calculate cross point and normal vector.
  303.             isect.t = t;
  304.             isect.hit = 1;
  305.             
  306.             isect.p.x = ray.org.x + ray.dir.x * t;
  307.             isect.p.y = ray.org.y + ray.dir.y * t;
  308.             isect.p.z = ray.org.z + ray.dir.z * t;
  309.             isect.n.x = pln.n.x;
  310.             isect.n.y = pln.n.y;
  311.             isect.n.z = pln.n.z;
  312.         }
  313.     }
  314. }
noswf
  1. // forked from keim_at_Si's Ambient Occlusion Rendering
  2. // Ambient Occlusion Bench Flash10 porting
  3. //   Original version of AO bench was written by Syoyo Fujita.
  4. //     http://lucille.atso-net.jp/aobench/
  5. //   In original Flash10 porting, it takes 7 times slower than the Proce55ing.
  6. //   (refer from http://lucille.atso-net.jp/blog/?p=638).
  7. //   And now, it seems to be same speed as the Proce55ing does.
  8. //----------------------------------------------------------------------
  9. package {
  10.     import flash.display.*;
  11.     import flash.text.*;
  12.     import flash.events.*;
  13.     
  14.     [SWF(frameRate = "1000", backgroundColor = "#808080")]
  15.     public class main extends Sprite {
  16.         private var _tf:TextField = new TextField();
  17.         private var _screen:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0xffffff);
  18.         private var _renderY:int;
  19.         
  20.         function main() { 
  21.             _tf.autoSize = 'left';
  22.             _tf.htmlText = "<font color='#ffffff'>Rendering...</font>";
  23.             addChild(_tf);
  24.             with(addChild(new Bitmap(_screen))){ x = y = 104.5; }
  25.             
  26.             _renderY = 0;
  27.             
  28.             addEventListener("enterFrame", _startRender);
  29.         }
  30.         
  31.         private function _startRender(e:Event) : void {
  32.             // rendering
  33.             render.rasterRendering(_renderY);
  34.             
  35.             // copy pixels
  36.             _screen.lock();
  37.             for (var x:int=0; x<WIDTH; x++) _screen.setPixel(x, _renderY, render.output[x]);
  38.             _screen.unlock();
  39.             
  40.             // increment
  41.             _renderY++;
  42.             if (_renderY == 256) {
  43.                 // finish rendering
  44.                 _tf.htmlText = "<font color='#ffffff'>Rendering time : " + String(render.renderingTime/1000) + "[sec]</font>";
  45.                 removeEventListener("enterFrame", _startRender);
  46.             }
  47.         }
  48.     }
  49. }
  50. import flash.display.*;
  51. import flash.geom.*;
  52. import flash.utils.getTimer;
  53. // global variables
  54. //--------------------------------------------------------------------------------
  55. const WIDTH :int = 256;
  56. const HEIGHT:int = 256;
  57. const NSUBSAMPLES:int = 2;
  58. const NAO_SAMPLES:int = 8;
  59. var render:Render = new Render();
  60. // structures
  61. //--------------------------------------------------------------------------------
  62. class Isect {
  63.     public var t:Number = 0;
  64.     public var p:Vector3D = new Vector3D();
  65.     public var n:Vector3D = new Vector3D();
  66.     public var hit:int = 0;
  67. }
  68. class Ray {
  69.     public var org:Vector3D = new Vector3D();
  70.     public var dir:Vector3D = new Vector3D();
  71. }
  72. class Sphere {
  73.     public var center:Vector3D;
  74.     public var radius2:Number;
  75.     function Sphere(center:Vector3D, radius:Number) {
  76.         this.center = center;
  77.         this.radius2 = radius*radius;
  78.     }
  79. }
  80. class Plane {
  81.     public var p:Vector3D;
  82.     public var n:Vector3D;
  83.     public var pn:Number;
  84.     function Plane(p:Vector3D, n:Vector3D) {
  85.         this.p = p;
  86.         this.n = n;
  87.         this.pn = n.x*p.x + n.y*p.y + n.z*p.z;
  88.     }
  89. }
  90. // render
  91. //--------------------------------------------------------------------------------
  92. class Render {
  93. // variables
  94. //--------------------------------------------------
  95.     public var output:Vector.<uint>;
  96.     public var renderingTime:int;
  97.     private var spheres:Vector.<Sphere> = new Vector.<Sphere>(3true);
  98.     private var plane:Plane;
  99.     
  100.     
  101. // constructor
  102. //--------------------------------------------------
  103.     function Render() {
  104.         _initScene();
  105.         renderingTime = 0;
  106.         output = new Vector.<uint>(WIDTH, true);
  107.     }
  108.     
  109.     
  110. // rendering
  111. //--------------------------------------------------
  112.     public function rasterRendering(y:int) : void {
  113.         var t:int = getTimer();
  114.         _render(output, WIDTH, HEIGHT, y);
  115.         renderingTime += getTimer() - t;
  116.     }
  117.     
  118. // privates
  119. //--------------------------------------------------
  120.     // initialize scene
  121.     private function _initScene() : void {
  122.         spheres[0] = new Sphere(new Vector3D(-2.00.0, -3.5), 0.5);
  123.         spheres[1] = new Sphere(new Vector3D(-0.50.0, -3.0), 0.5);
  124.         spheres[2] = new Sphere(new Vector3D( 1.00.0, -2.2), 0.5);
  125.         plane      = new Plane(new Vector3D(0.0, -0.50.0), new Vector3D(0.01.00.0));
  126.     }
  127.     
  128.     
  129.     // render
  130.     private var ray:Ray = new Ray();
  131.     private var isect:Isect = new Isect();
  132.     private function _render(line:Vector.<uint>, w:int, h:int, y:int) : void {
  133.         var idx:int, x:int, u:int, v:int, du:Number, dv:Number, pixel:uint, ao:Vector3D, 
  134.             hw :Number = w*0.5, hh :Number = h*0.5
  135.             ihw:Number = 1/hw,  ihh:Number = 1/hh,
  136.             step:Number = 1/NSUBSAMPLES, 
  137.             occlusionPerPixel:Number = 1/(NSUBSAMPLES*NSUBSAMPLES),
  138.             color:Vector3D = new Vector3D();
  139.         // scan all pixels
  140.         idx = 0;
  141.         for (x = 0; x < w; x++) {
  142.             // initialize pixel color
  143.             color.x = 0;
  144.             color.y = 0;
  145.             color.z = 0;
  146.             
  147.             // sub samplings
  148.             for (v = 0, dv = 0; v < NSUBSAMPLES; v++, dv += step) {
  149.                 for (u = 0, du = 0; u < NSUBSAMPLES; u++, du += step) {
  150.                     // initialize ray vectors
  151.                     ray.org.x = 0.0;
  152.                     ray.org.y = 0.0;
  153.                     ray.org.z = 0.0;
  154.                     ray.dir.x =  (x + du - hw) * ihw;
  155.                     ray.dir.y = -(y + dv - hh) * ihh;
  156.                     ray.dir.z = -1.0;
  157.                     ray.dir.normalize();
  158.                     // check ray intersections
  159.                     isect.p.x = isect.p.y = isect.p.z = 0.0;
  160.                     isect.n.x = isect.n.y = isect.n.z = 0.0;
  161.                     isect.t   = 1.0e+17;
  162.                     isect.hit = 0;
  163.                     _intersectBySphere(isect, ray, spheres[0]);
  164.                     _intersectBySphere(isect, ray, spheres[1]);
  165.                     _intersectBySphere(isect, ray, spheres[2]);
  166.                     _intersectByPlane (isect, ray, plane);
  167.                     // when the ray is intersected, calculate ambient occlusion color.
  168.                     if (isect.hit) {
  169.                         color.incrementBy(_ambientOcclusion(isect));
  170.                     }
  171.                 }
  172.             }
  173.             
  174.             // calculate gray scale
  175.             color.scaleBy(occlusionPerPixel);
  176.             pixel = 0xff000000;
  177.             pixel |=  (color.x >= 1) ? 255 : (color.x <= 0) ? 0 : int(color.x * 255);
  178.             pixel |= ((color.y >= 1) ? 255 : (color.y <= 0) ? 0 : int(color.x * 255)) << 8;
  179.             pixel |= ((color.z >= 1) ? 255 : (color.z <= 0) ? 0 : int(color.x * 255)) << 16;
  180.             output[idx] = pixel;
  181.             
  182.             // increment index
  183.             idx++;
  184.         }
  185.     }
  186.     
  187.     
  188.     // calculate ambient occlusion
  189.     private var aoRay:Ray = new Ray();
  190.     private var aoIsect:Isect = new Isect();
  191.     private var aoColor:Vector3D = new Vector3D();
  192.     private var basis0:Vector3D = new Vector3D();
  193.     private var basis1:Vector3D = new Vector3D();
  194.     private var basis2:Vector3D = new Vector3D();
  195.     private function _ambientOcclusion(isect:Isect) : Vector3D {
  196.         var i:int, j:int, th:Number, ph:Number,
  197.             x:Number,  y:Number,  z:Number,
  198.             rx:Number, ry:Number, rz:Number,
  199.             ntheta:int = NAO_SAMPLES,
  200.             nphi:int   = NAO_SAMPLES,
  201.             occlusionPerSample:Number = 1 / (ntheta*nphi),
  202.             eps:Number = 0.0001,
  203.             occlusion:Number = 1.0;
  204.         
  205.         // calculate transform matrix from local to global.
  206.         // the "local" coordinate is based on the normal vector at intersected point.
  207.         basis2 = isect.n;
  208.         basis1.x = 0.0;
  209.         basis1.y = 0.0;
  210.         basis1.z = 0.0;
  211.              if ((isect.n.x < 0.6) && (isect.n.x > -0.6)) basis1.x = 1.0;
  212.         else if ((isect.n.y < 0.6) && (isect.n.y > -0.6)) basis1.y = 1.0;
  213.         else if ((isect.n.z < 0.6) && (isect.n.z > -0.6)) basis1.z = 1.0;
  214.         else                                              basis1.x = 1.0;
  215.         vcross(basis0, basis1, basis2).normalize();
  216.         vcross(basis1, basis2, basis0).normalize();
  217.         // calculate the origin of the second ray
  218.         aoRay.org.x = isect.p.x + eps * isect.n.x;
  219.         aoRay.org.y = isect.p.y + eps * isect.n.y;
  220.         aoRay.org.z = isect.p.z + eps * isect.n.z;
  221.         
  222.         // calculate the ambient occlusion at intersected point
  223.         for (j = 0; j < ntheta; j++) {
  224.             for (i = 0; i < nphi; i++) {
  225.                 // calculate the direction of the second ray
  226.                 th = Math.sqrt(Math.random());
  227.                 ph = 6.283185307179586 * Math.random();
  228.                 x = Math.cos(ph) * th;
  229.                 y = Math.sin(ph) * th;
  230.                 z = Math.sqrt(1.0 - th * th);
  231.                 // transform second ray vector from local to global
  232.                 aoRay.dir.x = x * basis0.x + y * basis1.x + z * basis2.x;
  233.                 aoRay.dir.y = x * basis0.y + y * basis1.y + z * basis2.y;
  234.                 aoRay.dir.z = x * basis0.z + y * basis1.z + z * basis2.z;
  235.                 // check second ray intersections 
  236.                 aoIsect.p.x = aoIsect.p.y = aoIsect.p.z = 0.0;
  237.                 aoIsect.n.x = aoIsect.n.y = aoIsect.n.z = 0.0;
  238.                 aoIsect.t   = 1.0e+17;
  239.                 aoIsect.hit = 0;
  240.                 _intersectBySphere(aoIsect, aoRay, spheres[0]);
  241.                 _intersectBySphere(aoIsect, aoRay, spheres[1]);
  242.                 _intersectBySphere(aoIsect, aoRay, spheres[2]);
  243.                 _intersectByPlane (aoIsect, aoRay, plane);
  244.                 // when the second ray is intersected, increase the occlusion.
  245.                 if (aoIsect.hit) occlusion -= occlusionPerSample;
  246.             }
  247.         }
  248.         // return result
  249.         aoColor.x = occlusion;
  250.         aoColor.y = occlusion;
  251.         aoColor.z = occlusion;
  252.         return aoColor;
  253.         
  254.         // cross product
  255.         function vcross(c:Vector3D, v0:Vector3D, v1:Vector3D) : Vector3D {
  256.             c.x = v0.y * v1.z - v0.z * v1.y;
  257.             c.y = v0.z * v1.x - v0.x * v1.z;
  258.             c.z = v0.x * v1.y - v0.y * v1.x;
  259.             return c;
  260.         }
  261.     }
  262.     
  263.     
  264.     // check ray intersection by sphere
  265.     private function _intersectBySphere(isect:Isect, ray:Ray, sph:Sphere) : void {
  266.         var rsx:Number = ray.org.x - sph.center.x,
  267.             rsy:Number = ray.org.y - sph.center.y,
  268.             rsz:Number = ray.org.z - sph.center.z,
  269.             B:Number = rsx*ray.dir.x + rsy*ray.dir.y + rsz*ray.dir.z,
  270.             C:Number = rsx*rsx + rsy*rsy + rsz*rsz - sph.radius2,
  271.             D:Number = B * B - C;
  272.         // when the ray is intersected by the sphere,
  273.         if (D > 0.0) {
  274.             var t:Number = -B - Math.sqrt(D);
  275.             
  276.             if ((t > 0.0) && (t < isect.t)) {
  277.                 // calculate cross point and normal vector.
  278.                 isect.t = t;
  279.                 isect.hit = 1;
  280.                 
  281.                 isect.p.x = ray.org.x + ray.dir.x * t;
  282.                 isect.p.y = ray.org.y + ray.dir.y * t;
  283.                 isect.p.z = ray.org.z + ray.dir.z * t;
  284.                 isect.n.x = isect.p.x - sph.center.x;
  285.                 isect.n.y = isect.p.y - sph.center.y;
  286.                 isect.n.z = isect.p.z - sph.center.z;
  287.                 isect.n.normalize();
  288.             }
  289.         }
  290.     }
  291.     
  292.     // check ray intersection by plane
  293.     private function _intersectByPlane(isect:Isect, ray:Ray, pln:Plane) : void {
  294.         var v:Number = pln.n.x*ray.dir.x + pln.n.y*ray.dir.y + pln.n.z*ray.dir.z;
  295.         
  296.         // when parallel with plane
  297.         if (v>-1.0e-17 && v<1.0e-17return;
  298.         
  299.         var t:Number = -(pln.n.x*ray.org.x + pln.n.y*ray.org.y + pln.n.z*ray.org.z - pln.pn) / v;
  300.         // when the ray is intersected by the plane,
  301.         if ((t > 0.0) && (t < isect.t)) {
  302.             // calculate cross point and normal vector.
  303.             isect.t = t;
  304.             isect.hit = 1;
  305.             
  306.             isect.p.x = ray.org.x + ray.dir.x * t;
  307.             isect.p.y = ray.org.y + ray.dir.y * t;
  308.             isect.p.z = ray.org.z + ray.dir.z * t;
  309.             isect.n.x = pln.n.x;
  310.             isect.n.y = pln.n.y;
  311.             isect.n.z = pln.n.z;
  312.         }
  313.     }
  314. }
noswf
  1. // forked from keim_at_Si's Ambient Occlusion Rendering
  2. // Ambient Occlusion Bench Flash10 porting
  3. //   Original version of AO bench was written by Syoyo Fujita.
  4. //     http://lucille.atso-net.jp/aobench/
  5. //   In original Flash10 porting, it takes 7 times slower than the Proce55ing.
  6. //   (refer from http://lucille.atso-net.jp/blog/?p=638).
  7. //   And now, it seems to be same speed as the Proce55ing does.
  8. //----------------------------------------------------------------------
  9. package {
  10.     import flash.display.*;
  11.     import flash.text.*;
  12.     import flash.events.*;
  13.     
  14.     [SWF(frameRate = "1000", backgroundColor = "#808080")]
  15.     public class main extends Sprite {
  16.         private var _tf:TextField = new TextField();
  17.         private var _screen:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0xffffff);
  18.         private var _renderY:int;
  19.         
  20.         function main() { 
  21.             _tf.autoSize = 'left';
  22.             _tf.htmlText = "<font color='#ffffff'>Rendering...</font>";
  23.             addChild(_tf);
  24.             with(addChild(new Bitmap(_screen))){ x = y = 104.5; }
  25.             
  26.             _renderY = 0;
  27.             
  28.             addEventListener("enterFrame", _startRender);
  29.         }
  30.         
  31.         private function _startRender(e:Event) : void {
  32.             // rendering
  33.             render.rasterRendering(_renderY);
  34.             
  35.             // copy pixels
  36.             _screen.lock();
  37.             for (var x:int=0; x<WIDTH; x++) _screen.setPixel(x, _renderY, render.output[x]);
  38.             _screen.unlock();
  39.             
  40.             // increment
  41.             _renderY++;
  42.             if (_renderY == 256) {
  43.                 // finish rendering
  44.                 _tf.htmlText = "<font color='#ffffff'>Rendering time : " + String(render.renderingTime/1000) + "[sec]</font>";
  45.                 removeEventListener("enterFrame", _startRender);
  46.             }
  47.         }
  48.     }
  49. }
  50. import flash.display.*;
  51. import flash.geom.*;
  52. import flash.utils.getTimer;
  53. // global variables
  54. //--------------------------------------------------------------------------------
  55. const WIDTH :int = 256;
  56. const HEIGHT:int = 256;
  57. const NSUBSAMPLES:int = 2
  58. const NAO_SAMPLES:int = 8;
  59. var render:Render = new Render();
  60. // structures
  61. //--------------------------------------------------------------------------------
  62. class Isect {
  63.     public var t:Number = 0;
  64.     public var p:Vector3D = new Vector3D();
  65.     public var n:Vector3D = new Vector3D();
  66.     public var hit:int = 0;
  67. }
  68. class Ray {
  69.     public var org:Vector3D = new Vector3D();
  70.     public var dir:Vector3D = new Vector3D();
  71. }
  72. class Sphere {
  73.     public var center:Vector3D;
  74.     public var radius2:Number;
  75.     function Sphere(center:Vector3D, radius:Number) {
  76.         this.center = center;
  77.         this.radius2 = radius*radius;
  78.     }
  79. }
  80. class Plane {
  81.     public var p:Vector3D;
  82.     public var n:Vector3D;
  83.     public var pn:Number;
  84.     function Plane(p:Vector3D, n:Vector3D) {
  85.         this.p = p;
  86.         this.n = n;
  87.         this.pn = n.x*p.x + n.y*p.y + n.z*p.z;
  88.     }
  89. }
  90. // render
  91. //--------------------------------------------------------------------------------
  92. class Render {
  93. // variables
  94. //--------------------------------------------------
  95.     public var output:Vector.<uint>;
  96.     public var renderingTime:int;
  97.     private var spheres:Vector.<Sphere> = new Vector.<Sphere>(3true);
  98.     private var plane:Plane;
  99.     
  100.     
  101. // constructor
  102. //--------------------------------------------------
  103.     function Render() {
  104.         _initScene();
  105.         renderingTime = 0;
  106.         output = new Vector.<uint>(WIDTH, true);
  107.     }
  108.     
  109.     
  110. // rendering
  111. //--------------------------------------------------
  112.     public function rasterRendering(y:int) : void {
  113.         var t:int = getTimer();
  114.         _render(output, WIDTH, HEIGHT, y);
  115.         renderingTime += getTimer() - t;
  116.     }
  117.     
  118. // privates
  119. //--------------------------------------------------
  120.     // initialize scene
  121.     private function _initScene() : void {
  122.           spheres[0] = new Sphere(new Vector3D(-2.00.0, -3.5), 0.5);
  123.          spheres[1] = new Sphere(new Vector3D(-0.40.0, -3.0), 1.1);
  124.         spheres[2] = new Sphere(new Vector3D( 1.00.0, -2.2), 0.5);
  125.         
  126.         plane      = new Plane(new Vector3D(0.0, -0.50.0), new Vector3D(0.01.00.0));
  127.     }
  128.     
  129.     
  130.     // render
  131.     private var ray:Ray = new Ray();
  132.     private var isect:Isect = new Isect();
  133.     private function _render(line:Vector.<uint>, w:int, h:int, y:int) : void {
  134.         var idx:int, x:int, u:int, v:int, du:Number, dv:Number, pixel:uint, ao:Vector3D, 
  135.             hw :Number = w*0.5, hh :Number = h*0.5
  136.             ihw:Number = 1/hw,  ihh:Number = 1/hh,
  137.             step:Number = 1/NSUBSAMPLES, 
  138.             occlusionPerPixel:Number = 1/(NSUBSAMPLES*NSUBSAMPLES),
  139.             color:Vector3D = new Vector3D();
  140.         // scan all pixels
  141.         idx = 0;
  142.         for (x = 0; x < w; x++) {
  143.             // initialize pixel color
  144.             color.x = 0;
  145.             color.y = 0;
  146.             color.z = 0;
  147.             
  148.             // sub samplings
  149.             for (v = 0, dv = 0; v < NSUBSAMPLES; v++, dv += step) {
  150.                 for (u = 0, du = 0; u < NSUBSAMPLES; u++, du += step) {
  151.                     // initialize ray vectors
  152.                     ray.org.x = 0.0;
  153.                     ray.org.y = 0.0;
  154.                     ray.org.z = 0.0;
  155.                     ray.dir.x =  (x + du - hw) * ihw;
  156.                     ray.dir.y = -(y + dv - hh) * ihh;
  157.                     ray.dir.z = -1.0;
  158.                     ray.dir.normalize();
  159.                     // check ray intersections
  160.                     isect.p.x = isect.p.y = isect.p.z = 0.0;
  161.                     isect.n.x = isect.n.y = isect.n.z = 0.0;
  162.                     isect.t   = 1.0e+17;
  163.                     isect.hit = 0;
  164.                     _intersectBySphere(isect, ray, spheres[0]);
  165.                    // _intersectBySphere(isect, ray, spheres[1]);
  166.                     //_intersectBySphere(isect, ray, spheres[2]);
  167.                     _intersectByPlane (isect, ray, plane);
  168.                     // when the ray is intersected, calculate ambient occlusion color.
  169.                     if (isect.hit) {
  170.                         color.incrementBy(_ambientOcclusion(isect));
  171.                     }
  172.                 }
  173.             }
  174.             
  175.             // calculate gray scale
  176.             color.scaleBy(occlusionPerPixel);
  177.             pixel = 0xff000000;
  178.             pixel |=  (color.x >= 1) ? 255 : (color.x <= 0) ? 0 : int(color.x * 255);
  179.             pixel |= ((color.y >= 1) ? 255 : (color.y <= 0) ? 0 : int(color.x * 255)) << 8;
  180.             pixel |= ((color.z >= 1) ? 255 : (color.z <= 0) ? 0 : int(color.x * 255)) << 16;
  181.             output[idx] = pixel;
  182.             
  183.             // increment index
  184.             idx++;
  185.         }
  186.     }
  187.     
  188.     
  189.     // calculate ambient occlusion
  190.     private var aoRay:Ray = new Ray();
  191.     private var aoIsect:Isect = new Isect();
  192.     private var aoColor:Vector3D = new Vector3D();
  193.     private var basis0:Vector3D = new Vector3D();
  194.     private var basis1:Vector3D = new Vector3D();
  195.     private var basis2:Vector3D = new Vector3D();
  196.     private function _ambientOcclusion(isect:Isect) : Vector3D {
  197.         var i:int, j:int, th:Number, ph:Number,
  198.             x:Number,  y:Number,  z:Number,
  199.             rx:Number, ry:Number, rz:Number,
  200.             ntheta:int = NAO_SAMPLES,
  201.             nphi:int   = NAO_SAMPLES,
  202.             occlusionPerSample:Number = 1 / (ntheta*nphi),
  203.             eps:Number = 0.0001,
  204.             occlusion:Number = 1.0;
  205.         
  206.         // calculate transform matrix from local to global.
  207.         // the "local" coordinate is based on the normal vector at intersected point.
  208.         basis2 = isect.n;
  209.         basis1.x = 0.0;
  210.         basis1.y = 0.0;
  211.         basis1.z = 0.0;
  212.              if ((isect.n.x < 0.6) && (isect.n.x > -0.6)) basis1.x = 1.0;
  213.         else if ((isect.n.y < 0.6) && (isect.n.y > -0.6)) basis1.y = 1.0;
  214.         else if ((isect.n.z < 0.6) && (isect.n.z > -0.6)) basis1.z = 1.0;
  215.         else                                              basis1.x = 1.0;
  216.         vcross(basis0, basis1, basis2).normalize();
  217.         vcross(basis1, basis2, basis0).normalize();
  218.         // calculate the origin of the second ray
  219.         aoRay.org.x = isect.p.x + eps * isect.n.x;
  220.         aoRay.org.y = isect.p.y + eps * isect.n.y;
  221.         aoRay.org.z = isect.p.z + eps * isect.n.z;
  222.         
  223.         // calculate the ambient occlusion at intersected point
  224.         for (j = 0; j < ntheta; j++) {
  225.             for (i = 0; i < nphi; i++) {
  226.                 // calculate the direction of the second ray
  227.                 th = Math.sqrt(Math.random());
  228.                 ph = 6.283185307179586 * Math.random();
  229.                 x = Math.cos(ph) * th;
  230.                 y = Math.sin(ph) * th;
  231.                 z = Math.sqrt(1.0 - th * th);
  232.                 // transform second ray vector from local to global
  233.                 aoRay.dir.x = x * basis0.x + y * basis1.x + z * basis2.x;
  234.                 aoRay.dir.y = x * basis0.y + y * basis1.y + z * basis2.y;
  235.                 aoRay.dir.z = x * basis0.z + y * basis1.z + z * basis2.z;
  236.                 // check second ray intersections 
  237.                 aoIsect.p.x = aoIsect.p.y = aoIsect.p.z = 0.0;
  238.                 aoIsect.n.x = aoIsect.n.y = aoIsect.n.z = 0.0;
  239.                 aoIsect.t   = 1.0e+17;
  240.                 aoIsect.hit = 0;
  241.                 _intersectBySphere(aoIsect, aoRay, spheres[0]);
  242.               //  _intersectBySphere(aoIsect, aoRay, spheres[1]);
  243.                // _intersectBySphere(aoIsect, aoRay, spheres[2]);
  244.                 _intersectByPlane (aoIsect, aoRay, plane);
  245.                 // when the second ray is intersected, increase the occlusion.
  246.                 if (aoIsect.hit) occlusion -= occlusionPerSample;
  247.             }
  248.         }
  249.         // return result
  250.         aoColor.x = occlusion;
  251.         aoColor.y = occlusion;
  252.         aoColor.z = occlusion;
  253.         return aoColor;
  254.         
  255.         // cross product
  256.         function vcross(c:Vector3D, v0:Vector3D, v1:Vector3D) : Vector3D {
  257.             c.x = v0.y * v1.z - v0.z * v1.y;
  258.             c.y = v0.z * v1.x - v0.x * v1.z;
  259.             c.z = v0.x * v1.y - v0.y * v1.x;
  260.             return c;
  261.         }
  262.     }
  263.     
  264.     
  265.     // check ray intersection by sphere
  266.     private function _intersectBySphere(isect:Isect, ray:Ray, sph:Sphere) : void {
  267.         var R:Number = sph.radius2 / 2;
  268.         var rsx:Number = ray.org.x - sph.center.x,
  269.             rsy:Number = ray.org.y - sph.center.y,
  270.             rsz:Number = ray.org.z - sph.center.z,
  271.             B:Number = rsx*rsx*rsx*rsx + rsy*rsy*rsy*rsy + rsz*rsz*rsz*rsz,
  272.             C:Number =  rsx*rsx*rsx*rsx + rsy*rsy*rsy*rsy + rsz*rsz*rsz*rsz - 10 * R * R * (rsx*rsx + rsy*rsy + rsz*rsz) + 10 * Math.pow(R,4), 
  273.             D:Number = B * B - C;
  274. //x^4 + y^4 + z^4 - 10*R^2*(x^2 + y^2 + z^2) + 40 * R^4
  275.         // when the ray is intersected by the sphere,
  276.         if (D > 0.0) {
  277.             var t:Number = C//Math.sqrt(D);
  278.             
  279.             if ((t > 0.0) && (t < isect.t)) {
  280.                 // calculate cross point and normal vector.
  281.                 isect.t = t;
  282.                 isect.hit = 1;
  283.                 
  284.                 isect.p.x = ray.org.x + ray.dir.x * t;
  285.                 isect.p.y = ray.org.y + ray.dir.y * t;
  286.                 isect.p.z = ray.org.z + ray.dir.z * t;
  287.                 isect.n.x = isect.p.x - sph.center.x;
  288.                 isect.n.y = isect.p.y - sph.center.y;
  289.                 isect.n.z = isect.p.z - sph.center.z;
  290.                 isect.n.normalize();
  291.             }
  292.         }
  293.     }
  294.     
  295.     // check ray intersection by plane
  296.     private function _intersectByPlane(isect:Isect, ray:Ray, pln:Plane) : void {
  297.         var v:Number = pln.n.x*ray.dir.x + pln.n.y*ray.dir.y + pln.n.z*ray.dir.z;
  298.         
  299.         // when parallel with plane
  300.         if (v>-1.0e-17 && v<1.0e-17return;
  301.         
  302.         var t:Number = -(pln.n.x*ray.org.x + pln.n.y*ray.org.y + pln.n.z*ray.org.z - pln.pn) / v;
  303.         // when the ray is intersected by the plane,
  304.         if ((t > 0.0) && (t < isect.t)) {
  305.             // calculate cross point and normal vector.
  306.             isect.t = t;
  307.             isect.hit = 1;
  308.             
  309.             isect.p.x = ray.org.x + ray.dir.x * t;
  310.             isect.p.y = ray.org.y + ray.dir.y * t;
  311.             isect.p.z = ray.org.z + ray.dir.z * t;
  312.             isect.n.x = pln.n.x;
  313.             isect.n.y = pln.n.y;
  314.             isect.n.z = pln.n.z;
  315.         }
  316.     }
  317. }
noswf
  1. // forked from keim_at_Si's Ambient Occlusion Rendering
  2. // Ambient Occlusion Bench Flash10 porting
  3. //   Original version of AO bench was written by Syoyo Fujita.
  4. //     http://lucille.atso-net.jp/aobench/
  5. //   In original Flash10 porting, it takes 7 times slower than the Proce55ing.
  6. //   (refer from http://lucille.atso-net.jp/blog/?p=638).
  7. //   And now, it seems to be same speed as the Proce55ing does.
  8. //----------------------------------------------------------------------
  9. package {
  10.     import flash.display.*;
  11.     import flash.text.*;
  12.     import flash.events.*;
  13.     
  14.     [SWF(frameRate = "1000", backgroundColor = "#808080")]
  15.     public class main extends Sprite {
  16.         private var _tf:TextField = new TextField();
  17.         private var _screen:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0xffffff);
  18.         private var _renderY:int;
  19.         
  20.         function main() { 
  21.             _tf.autoSize = 'left';
  22.             _tf.htmlText = "<font color='#ffffff'>Rendering...</font>";
  23.             addChild(_tf);
  24.             with(addChild(new Bitmap(_screen))){ x = y = 104.5; }
  25.             
  26.             _renderY = 0;
  27.             
  28.             addEventListener("enterFrame", _startRender);
  29.         }
  30.         
  31.         private function _startRender(e:Event) : void {
  32.             // rendering
  33.             render.rasterRendering(_renderY);
  34.             
  35.             // copy pixels
  36.             _screen.lock();
  37.             for (var x:int=0; x<WIDTH; x++) _screen.setPixel(x, _renderY, render.output[x]);
  38.             _screen.unlock();
  39.             
  40.             // increment
  41.             _renderY++;
  42.             if (_renderY == 256) {
  43.                 // finish rendering
  44.                 _tf.htmlText = "<font color='#ffffff'>Rendering time : " + String(render.renderingTime/1000) + "[sec]</font>";
  45.                 removeEventListener("enterFrame", _startRender);
  46.             }
  47.         }
  48.     }
  49. }
  50. import flash.display.*;
  51. import flash.geom.*;
  52. import flash.utils.getTimer;
  53. // global variables
  54. //--------------------------------------------------------------------------------
  55. const WIDTH :int = 256;
  56. const HEIGHT:int = 256;
  57. const NSUBSAMPLES:int = 2;
  58. const NAO_SAMPLES:int = 8;
  59. var render:Render = new Render();
  60. // structures
  61. //--------------------------------------------------------------------------------
  62. class Isect {
  63.     public var t:Number = 0;
  64.     public var p:Vector3D = new Vector3D();
  65.     public var n:Vector3D = new Vector3D();
  66.     public var hit:int = 0;
  67. }
  68. class Ray {
  69.     public var org:Vector3D = new Vector3D();
  70.     public var dir:Vector3D = new Vector3D();
  71. }
  72. class Sphere {
  73.     public var center:Vector3D;
  74.     public var radius2:Number;
  75.     function Sphere(center:Vector3D, radius:Number) {
  76.         this.center = center;
  77.         this.radius2 = radius*radius;
  78.     }
  79. }
  80. class Plane {
  81.     public var p:Vector3D;
  82.     public var n:Vector3D;
  83.     public var pn:Number;
  84.     function Plane(p:Vector3D, n:Vector3D) {
  85.         this.p = p;
  86.         this.n = n;
  87.         this.pn = n.x*p.x + n.y*p.y + n.z*p.z;
  88.     }
  89. }
  90. // render
  91. //--------------------------------------------------------------------------------
  92. class Render {
  93. // variables
  94. //--------------------------------------------------
  95.     public var output:Vector.<uint>;
  96.     public var renderingTime:int;
  97.     private var spheres:Vector.<Sphere> = new Vector.<Sphere>(3true);
  98.     private var plane:Plane;
  99.     
  100.     
  101. // constructor
  102. //--------------------------------------------------
  103.     function Render() {
  104.         _initScene();
  105.         renderingTime = 0;
  106.         output = new Vector.<uint>(WIDTH, true);
  107.     }
  108.     
  109.     
  110. // rendering
  111. //--------------------------------------------------
  112.     public function rasterRendering(y:int) : void {
  113.         var t:int = getTimer();
  114.         _render(output, WIDTH, HEIGHT, y);
  115.         renderingTime += getTimer() - t;
  116.     }
  117.     
  118. // privates
  119. //--------------------------------------------------
  120.     // initialize scene
  121.     private function _initScene() : void {
  122.         spheres[0] = new Sphere(new Vector3D(-2.00.0, -3.5), 0.5);
  123.         spheres[1] = new Sphere(new Vector3D(-0.50.0, -3.0), 0.5);
  124.         spheres[2] = new Sphere(new Vector3D( 1.00.0, -2.2), 0.5);
  125.         plane      = new Plane(new Vector3D(0.0, -0.50.0), new Vector3D(0.01.00.0));
  126.     }
  127.     
  128.     
  129.     // render
  130.     private var ray:Ray = new Ray();
  131.     private var isect:Isect = new Isect();
  132.     private function _render(line:Vector.<uint>, w:int, h:int, y:int) : void {
  133.         var idx:int, x:int, u:int, v:int, du:Number, dv:Number, pixel:uint, ao:Vector3D, 
  134.             hw :Number = w*0.5, hh :Number = h*0.5
  135.             ihw:Number = 1/hw,  ihh:Number = 1/hh,
  136.             step:Number = 1/NSUBSAMPLES, 
  137.             occlusionPerPixel:Number = 1/(NSUBSAMPLES*NSUBSAMPLES),
  138.             color:Vector3D = new Vector3D();
  139.         // scan all pixels
  140.         idx = 0;
  141.         for (x = 0; x < w; x++) {
  142.             // initialize pixel color
  143.             color.x = 0;
  144.             color.y = 0;
  145.             color.z = 0;
  146.             
  147.             // sub samplings
  148.             for (v = 0, dv = 0; v < NSUBSAMPLES; v++, dv += step) {
  149.                 for (u = 0, du = 0; u < NSUBSAMPLES; u++, du += step) {
  150.                     // initialize ray vectors
  151.                     ray.org.x = 0.0;
  152.                     ray.org.y = 0.0;
  153.                     ray.org.z = 0.0;
  154.                     ray.dir.x =  (x + du - hw) * ihw;
  155.                     ray.dir.y = -(y + dv - hh) * ihh;
  156.                     ray.dir.z = -1.0;
  157.                     ray.dir.normalize();
  158.                     // check ray intersections
  159.                     isect.p.x = isect.p.y = isect.p.z = 0.0;
  160.                     isect.n.x = isect.n.y = isect.n.z = 0.0;
  161.                     isect.t   = 1.0e+17;
  162.                     isect.hit = 0;
  163.                     _intersectBySphere(isect, ray, spheres[0]);
  164.                     _intersectBySphere(isect, ray, spheres[1]);
  165.                     _intersectBySphere(isect, ray, spheres[2]);
  166.                     _intersectByPlane (isect, ray, plane);
  167.                     // when the ray is intersected, calculate ambient occlusion color.
  168.                     if (isect.hit) {
  169.                         color.incrementBy(_ambientOcclusion(isect));
  170.                     }
  171.                 }
  172.             }
  173.             
  174.             // calculate gray scale
  175.             color.scaleBy(occlusionPerPixel);
  176.             pixel = 0xff000000;
  177.             pixel |=  (color.x >= 1) ? 255 : (color.x <= 0) ? 0 : int(color.x * 255);
  178.             pixel |= ((color.y >= 1) ? 255 : (color.y <= 0) ? 0 : int(color.x * 255)) << 8;
  179.             pixel |= ((color.z >= 1) ? 255 : (color.z <= 0) ? 0 : int(color.x * 255)) << 16;
  180.             output[idx] = pixel;
  181.             
  182.             // increment index
  183.             idx++;
  184.         }
  185.     }
  186.     
  187.     
  188.     // calculate ambient occlusion
  189.     private var aoRay:Ray = new Ray();
  190.     private var aoIsect:Isect = new Isect();
  191.     private var aoColor:Vector3D = new Vector3D();
  192.     private var basis0:Vector3D = new Vector3D();
  193.     private var basis1:Vector3D = new Vector3D();
  194.     private var basis2:Vector3D = new Vector3D();
  195.     private function _ambientOcclusion(isect:Isect) : Vector3D {
  196.         var i:int, j:int, th:Number, ph:Number,
  197.             x:Number,  y:Number,  z:Number,
  198.             rx:Number, ry:Number, rz:Number,
  199.             ntheta:int = NAO_SAMPLES,
  200.             nphi:int   = NAO_SAMPLES,
  201.             occlusionPerSample:Number = 1 / (ntheta*nphi),
  202.             eps:Number = 0.0001,
  203.             occlusion:Number = 1.0;
  204.         
  205.         // calculate transform matrix from local to global.
  206.         // the "local" coordinate is based on the normal vector at intersected point.
  207.         basis2 = isect.n;
  208.         basis1.x = 0.0;
  209.         basis1.y = 0.0;
  210.         basis1.z = 0.0;
  211.              if ((isect.n.x < 0.6) && (isect.n.x > -0.6)) basis1.x = 1.0;
  212.         else if ((isect.n.y < 0.6) && (isect.n.y > -0.6)) basis1.y = 1.0;
  213.         else if ((isect.n.z < 0.6) && (isect.n.z > -0.6)) basis1.z = 1.0;
  214.         else                                              basis1.x = 1.0;
  215.         vcross(basis0, basis1, basis2).normalize();
  216.         vcross(basis1, basis2, basis0).normalize();
  217.         // calculate the origin of the second ray
  218.         aoRay.org.x = isect.p.x + eps * isect.n.x;
  219.         aoRay.org.y = isect.p.y + eps * isect.n.y;
  220.         aoRay.org.z = isect.p.z + eps * isect.n.z;
  221.         
  222.         // calculate the ambient occlusion at intersected point
  223.         for (j = 0; j < ntheta; j++) {
  224.             for (i = 0; i < nphi; i++) {
  225.                 // calculate the direction of the second ray
  226.                 th = Math.sqrt(Math.random());
  227.                 ph = 6.283185307179586 * Math.random();
  228.                 x = Math.cos(ph) * th;
  229.                 y = Math.sin(ph) * th;
  230.                 z = Math.sqrt(1.0 - th * th);
  231.                 // transform second ray vector from local to global
  232.                 aoRay.dir.x = x * basis0.x + y * basis1.x + z * basis2.x;
  233.                 aoRay.dir.y = x * basis0.y + y * basis1.y + z * basis2.y;
  234.                 aoRay.dir.z = x * basis0.z + y * basis1.z + z * basis2.z;
  235.                 // check second ray intersections 
  236.                 aoIsect.p.x = aoIsect.p.y = aoIsect.p.z = 0.0;
  237.                 aoIsect.n.x = aoIsect.n.y = aoIsect.n.z = 0.0;
  238.                 aoIsect.t   = 1.0e+17;
  239.                 aoIsect.hit = 0;
  240.                 _intersectBySphere(aoIsect, aoRay, spheres[0]);
  241.                 _intersectBySphere(aoIsect, aoRay, spheres[1]);
  242.                 _intersectBySphere(aoIsect, aoRay, spheres[2]);
  243.                 _intersectByPlane (aoIsect, aoRay, plane);
  244.                 // when the second ray is intersected, increase the occlusion.
  245.                 if (aoIsect.hit) occlusion -= occlusionPerSample;
  246.             }
  247.         }
  248.         // return result
  249.         aoColor.x = occlusion;
  250.         aoColor.y = occlusion;
  251.         aoColor.z = occlusion;
  252.         return aoColor;
  253.         
  254.         // cross product
  255.         function vcross(c:Vector3D, v0:Vector3D, v1:Vector3D) : Vector3D {
  256.             c.x = v0.y * v1.z - v0.z * v1.y;
  257.             c.y = v0.z * v1.x - v0.x * v1.z;
  258.             c.z = v0.x * v1.y - v0.y * v1.x;
  259.             return c;
  260.         }
  261.     }
  262.     
  263.     
  264.     // check ray intersection by sphere
  265.     private function _intersectBySphere(isect:Isect, ray:Ray, sph:Sphere) : void {
  266.         var rsx:Number = ray.org.x - sph.center.x,
  267.             rsy:Number = ray.org.y - sph.center.y,
  268.             rsz:Number = ray.org.z - sph.center.z,
  269.             B:Number = rsx*ray.dir.x + rsy*ray.dir.y + rsz*ray.dir.z,
  270.             C:Number = rsx*rsx + rsy*rsy + rsz*rsz - sph.radius2,
  271.             D:Number = B * B - C;
  272.         // when the ray is intersected by the sphere,
  273.         if (D > 0.0) {
  274.             var t:Number = -B - Math.sqrt(D);
  275.             
  276.             if ((t > 0.0) && (t < isect.t)) {
  277.                 // calculate cross point and normal vector.
  278.                 isect.t = t;
  279.                 isect.hit = 1;
  280.                 
  281.                 isect.p.x = ray.org.x + ray.dir.x * t;
  282.                 isect.p.y = ray.org.y + ray.dir.y * t;
  283.                 isect.p.z = ray.org.z + ray.dir.z * t;
  284.                 isect.n.x = isect.p.x - sph.center.x;
  285.                 isect.n.y = isect.p.y - sph.center.y;
  286.                 isect.n.z = isect.p.z - sph.center.z;
  287.                 isect.n.normalize();
  288.             }
  289.         }
  290.     }
  291.     
  292.     // check ray intersection by plane
  293.     private function _intersectByPlane(isect:Isect, ray:Ray, pln:Plane) : void {
  294.         var v:Number = pln.n.x*ray.dir.x + pln.n.y*ray.dir.y + pln.n.z*ray.dir.z;
  295.         
  296.         // when parallel with plane
  297.         if (v>-1.0e-17 && v<1.0e-17return;
  298.         
  299.         var t:Number = -(pln.n.x*ray.org.x + pln.n.y*ray.org.y + pln.n.z*ray.org.z - pln.pn) / v;
  300.         // when the ray is intersected by the plane,
  301.         if ((t > 0.0) && (t < isect.t)) {
  302.             // calculate cross point and normal vector.
  303.             isect.t = t;
  304.             isect.hit = 1;
  305.             
  306.             isect.p.x = ray.org.x + ray.dir.x * t;
  307.             isect.p.y = ray.org.y + ray.dir.y * t;
  308.             isect.p.z = ray.org.z + ray.dir.z * t;
  309.             isect.n.x = pln.n.x;
  310.             isect.n.y = pln.n.y;
  311.             isect.n.z = pln.n.z;
  312.         }
  313.     }
  314. }
noswf
  1. // forked from keim_at_Si's Ambient Occlusion Rendering
  2. // Ambient Occlusion Bench Flash10 porting
  3. //   Original version of AO bench was written by Syoyo Fujita.
  4. //     http://lucille.atso-net.jp/aobench/
  5. //   In original Flash10 porting, it takes 7 times slower than the Proce55ing.
  6. //   (refer from http://lucille.atso-net.jp/blog/?p=638).
  7. //   And now, it seems to be same speed as the Proce55ing does.
  8. //----------------------------------------------------------------------
  9. package {
  10.     import flash.display.*;
  11.     import flash.text.*;
  12.     import flash.events.*;
  13.     
  14.     [SWF(frameRate = "1000", backgroundColor = "#808080")]
  15.     public class main extends Sprite {
  16.         private var _tf:TextField = new TextField();
  17.         private var _screen:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0xffffff);
  18.         private var _renderY:int;
  19.         
  20.         function main() { 
  21.             _tf.autoSize = 'left';
  22.             _tf.htmlText = "<font color='#ffffff'>Rendering...</font>";
  23.             addChild(_tf);
  24.             with(addChild(new Bitmap(_screen))){ x = y = 104.5; }
  25.             
  26.             _renderY = 0;
  27.             
  28.             addEventListener("enterFrame", _startRender);
  29.         }
  30.         
  31.         private function _startRender(e:Event) : void {
  32.             // rendering
  33.             render.rasterRendering(_renderY);
  34.             
  35.             // copy pixels
  36.             _screen.lock();
  37.             for (var x:int=0; x<WIDTH; x++) _screen.setPixel(x, _renderY, render.output[x]);
  38.             _screen.unlock();
  39.             
  40.             // increment
  41.             _renderY++;
  42.             if (_renderY == 256) {
  43.                 // finish rendering
  44.                 _tf.htmlText = "<font color='#ffffff'>Rendering time : " + String(render.renderingTime/1000) + "[sec]</font>";
  45.                 removeEventListener("enterFrame", _startRender);
  46.             }
  47.         }
  48.     }
  49. }
  50. import flash.display.*;
  51. import flash.geom.*;
  52. import flash.utils.getTimer;
  53. // global variables
  54. //--------------------------------------------------------------------------------
  55. const WIDTH :int = 256;
  56. const HEIGHT:int = 256;
  57. const NSUBSAMPLES:int = 2;
  58. const NAO_SAMPLES:int = 8;
  59. var render:Render = new Render();
  60. // structures
  61. //--------------------------------------------------------------------------------
  62. class Isect {
  63.     public var t:Number = 0;
  64.     public var p:Vector3D = new Vector3D();
  65.     public var n:Vector3D = new Vector3D();
  66.     public var hit:int = 0;
  67. }
  68. class Ray {
  69.     public var org:Vector3D = new Vector3D();
  70.     public var dir:Vector3D = new Vector3D();
  71. }
  72. class Sphere {
  73.     public var center:Vector3D;
  74.     public var radius2:Number;
  75.     function Sphere(center:Vector3D, radius:Number) {
  76.         this.center = center;
  77.         this.radius2 = radius*radius;
  78.     }
  79. }
  80. class Plane {
  81.     public var p:Vector3D;
  82.     public var n:Vector3D;
  83.     public var pn:Number;
  84.     function Plane(p:Vector3D, n:Vector3D) {
  85.         this.p = p;
  86.         this.n = n;
  87.         this.pn = n.x*p.x + n.y*p.y + n.z*p.z;
  88.     }
  89. }
  90. // render
  91. //--------------------------------------------------------------------------------
  92. class Render {
  93. // variables
  94. //--------------------------------------------------
  95.     public var output:Vector.<uint>;
  96.     public var renderingTime:int;
  97.     private var spheres:Vector.<Sphere> = new Vector.<Sphere>(3true);
  98.     private var plane:Plane;
  99.     
  100.     
  101. // constructor
  102. //--------------------------------------------------
  103.     function Render() {
  104.         _initScene();
  105.         renderingTime = 0;
  106.         output = new Vector.<uint>(WIDTH, true);
  107.     }
  108.     
  109.     
  110. // rendering
  111. //--------------------------------------------------
  112.     public function rasterRendering(y:int) : void {
  113.         var t:int = getTimer();
  114.         _render(output, WIDTH, HEIGHT, y);
  115.         renderingTime += getTimer() - t;
  116.     }
  117.     
  118. // privates
  119. //--------------------------------------------------
  120.     // initialize scene
  121.     private function _initScene() : void {
  122.         spheres[0] = new Sphere(new Vector3D(-2.00.0, -3.5), 0.5);
  123.         spheres[1] = new Sphere(new Vector3D(-0.50.0, -3.0), 0.5);
  124.         spheres[2] = new Sphere(new Vector3D( 1.00.0, -2.2), 0.5);
  125.         plane      = new Plane(new Vector3D(0.0, -0.50.0), new Vector3D(0.01.00.0));
  126.     }
  127.     
  128.     
  129.     // render
  130.     private var ray:Ray = new Ray();
  131.     private var isect:Isect = new Isect();
  132.     private function _render(line:Vector.<uint>, w:int, h:int, y:int) : void {
  133.         var idx:int, x:int, u:int, v:int, du:Number, dv:Number, pixel:uint, ao:Vector3D, 
  134.             hw :Number = w*0.5, hh :Number = h*0.5
  135.             ihw:Number = 1/hw,  ihh:Number = 1/hh,
  136.             step:Number = 1/NSUBSAMPLES, 
  137.             occlusionPerPixel:Number = 1/(NSUBSAMPLES*NSUBSAMPLES),
  138.             color:Vector3D = new Vector3D();
  139.             
  140.         var rayOrg:Vector3D = ray.org;
  141.         var rayDir:Vector3D = ray.dir;
  142.         
  143.         // scan all pixels
  144.         idx = 0;
  145.         for (x = 0; x < w; x++) {
  146.             // initialize pixel color
  147.             color.x = 0;
  148.             color.y = 0;
  149.             color.z = 0;
  150.             
  151.             // sub samplings
  152.             for (v = 0, dv = 0; v < NSUBSAMPLES; v++, dv += step) {
  153.                 for (u = 0, du = 0; u < NSUBSAMPLES; u++, du += step) {
  154.                     // initialize ray vectors
  155.                     rayOrg.x = 0.0;
  156.                     rayOrg.y = 0.0;
  157.                     rayOrg.z = 0.0;
  158.                     rayDir.x =  (x + du - hw) * ihw;
  159.                     rayDir.y = -(y + dv - hh) * ihh;
  160.                     rayDir.z = -1.0;
  161.                     rayDir.normalize();
  162.                     // check ray intersections
  163.                     isect.p.x = isect.p.y = isect.p.z = 0.0;
  164.                     isect.n.x = isect.n.y = isect.n.z = 0.0;
  165.                     isect.t   = 1.0e+17;
  166.                     isect.hit = 0;
  167.                     _intersectBySphere(isect, ray, spheres[0]);
  168.                     _intersectBySphere(isect, ray, spheres[1]);
  169.                     _intersectBySphere(isect, ray, spheres[2]);
  170.                     _intersectByPlane (isect, ray, plane);
  171.                     // when the ray is intersected, calculate ambient occlusion color.
  172.                     if (isect.hit) {
  173.                         color.incrementBy(_ambientOcclusion(isect));
  174.                     }
  175.                 }
  176.             }
  177.             
  178.             // calculate gray scale
  179.             color.scaleBy(occlusionPerPixel);
  180.             pixel = 0xff000000;
  181.             pixel |=  (color.x >= 1) ? 255 : (color.x <= 0) ? 0 : int(color.x * 255);
  182.             pixel |= ((color.y >= 1) ? 255 : (color.y <= 0) ? 0 : int(color.x * 255)) << 8;
  183.             pixel |= ((color.z >= 1) ? 255 : (color.z <= 0) ? 0 : int(color.x * 255)) << 16;
  184.             output[idx] = pixel;
  185.             
  186.             // increment index
  187.             idx++;
  188.         }
  189.     }
  190.     
  191.     
  192.     // calculate ambient occlusion
  193.     private var aoRay:Ray = new Ray();
  194.     private var aoIsect:Isect = new Isect();
  195.     private var aoColor:Vector3D = new Vector3D();
  196.     private var basis0:Vector3D = new Vector3D();
  197.     private var basis1:Vector3D = new Vector3D();
  198.     private var basis2:Vector3D = new Vector3D();
  199.     private function _ambientOcclusion(isect:Isect) : Vector3D {
  200.         var i:int, j:int, th:Number, ph:Number,
  201.             x:Number,  y:Number,  z:Number,
  202.             rx:Number, ry:Number, rz:Number,
  203.             ntheta:int = NAO_SAMPLES,
  204.             nphi:int   = NAO_SAMPLES,
  205.             occlusionPerSample:Number = 1 / (ntheta*nphi),
  206.             eps:Number = 0.0001,
  207.             occlusion:Number = 1.0;
  208.         
  209.         // calculate transform matrix from local to global.
  210.         // the "local" coordinate is based on the normal vector at intersected point.
  211.         basis2 = isect.n;
  212.         basis1.x = 0.0;
  213.         basis1.y = 0.0;
  214.         basis1.z = 0.0;
  215.              if ((isect.n.x < 0.6) && (isect.n.x > -0.6)) basis1.x = 1.0;
  216.         else if ((isect.n.y < 0.6) && (isect.n.y > -0.6)) basis1.y = 1.0;
  217.         else if ((isect.n.z < 0.6) && (isect.n.z > -0.6)) basis1.z = 1.0;
  218.         else                                              basis1.x = 1.0;
  219.         
  220.         
  221.         basis0.x = basis1.y * basis2.z - basis1.z * basis2.y;
  222.         basis0.y = basis1.z * basis2.x - basis1.x * basis2.z;
  223.         basis0.z = basis1.x * basis2.y - basis1.y * basis2.x;
  224.         basis0.normalize();
  225.         
  226.         basis1.x = basis2.y * basis0.z - basis2.z * basis0.y;
  227.         basis1.y = basis2.z * basis0.x - basis2.x * basis0.z;
  228.         basis1.z = basis2.x * basis0.y - basis2.y * basis0.x;
  229.         basis1.normalize();
  230.             
  231.         // calculate the origin of the second ray
  232.         aoRay.org.x = isect.p.x + eps * isect.n.x;
  233.         aoRay.org.y = isect.p.y + eps * isect.n.y;
  234.         aoRay.org.z = isect.p.z + eps * isect.n.z;
  235.         
  236.         var mc:Function = Math.cos;
  237.         var ms:Function = Math.sin;
  238.         var mq:Function = Math.sqrt;
  239.         // calculate the ambient occlusion at intersected point
  240.         for (j = 0; j < ntheta; j++) {
  241.             for (i = 0; i < nphi; i++) {
  242.                 // calculate the direction of the second ray
  243.                 th = Math.sqrt(Math.random());
  244.                 ph = 6.283185307179586 * Math.random();
  245.                 x = mc(ph) * th;
  246.                 y = ms(ph) * th;
  247.                 z = mq(1.0 - th * th);
  248.                 // transform second ray vector from local to global
  249.                 aoRay.dir.x = x * basis0.x + y * basis1.x + z * basis2.x;
  250.                 aoRay.dir.y = x * basis0.y + y * basis1.y + z * basis2.y;
  251.                 aoRay.dir.z = x * basis0.z + y * basis1.z + z * basis2.z;
  252.                 // check second ray intersections 
  253.                 aoIsect.p.x = aoIsect.p.y = aoIsect.p.z = 0.0;
  254.                 aoIsect.n.x = aoIsect.n.y = aoIsect.n.z = 0.0;
  255.                 aoIsect.t   = 1.0e+17;
  256.                 aoIsect.hit = 0;
  257.                 _intersectBySphere(aoIsect, aoRay, spheres[0]);
  258.                 _intersectBySphere(aoIsect, aoRay, spheres[1]);
  259.                 _intersectBySphere(aoIsect, aoRay, spheres[2]);
  260.                 _intersectByPlane (aoIsect, aoRay, plane);
  261.                 // when the second ray is intersected, increase the occlusion.
  262.                 if (aoIsect.hit) occlusion -= occlusionPerSample;
  263.             }
  264.         }
  265.         // return result
  266.         aoColor.x = occlusion;
  267.         aoColor.y = occlusion;
  268.         aoColor.z = occlusion;
  269.         return aoColor;
  270.         
  271.         // cross product
  272.         function vcross(c:Vector3D, v0:Vector3D, v1:Vector3D) : Vector3D {
  273.             c.x = v0.y * v1.z - v0.z * v1.y;
  274.             c.y = v0.z * v1.x - v0.x * v1.z;
  275.             c.z = v0.x * v1.y - v0.y * v1.x;
  276.             return c;
  277.         }
  278.     }
  279.     
  280.     
  281.     // check ray intersection by sphere
  282.     private function _intersectBySphere(isect:Isect, ray:Ray, sph:Sphere) : void {
  283.         var rayOrg:Vector3D = ray.org;
  284.         var rayDir:Vector3D = ray.dir;
  285.         var sphCenter:Vector3D = sph.center;
  286.         
  287.         var rsx:Number = rayOrg.x - sphCenter.x,
  288.             rsy:Number = rayOrg.y - sphCenter.y,
  289.             rsz:Number = rayOrg.z - sphCenter.z,
  290.             B:Number = rsx*rayDir.x + rsy*rayDir.y + rsz*rayDir.z,
  291.             C:Number = rsx*rsx + rsy*rsy + rsz*rsz - sph.radius2,
  292.             D:Number = B * B - C;
  293.         // when the ray is intersected by the sphere,
  294.         if (D > 0.0) {
  295.             var t:Number = -B - Math.sqrt(D);
  296.             
  297.             if ((t > 0.0) && (t < isect.t)) {
  298.                 // calculate cross point and normal vector.
  299.                 isect.t = t;
  300.                 isect.hit = 1;
  301.                 
  302.                 isect.p.x = rayOrg.x + rayDir.x * t;
  303.                 isect.p.y = rayOrg.y + rayDir.y * t;
  304.                 isect.p.z = rayOrg.z + rayDir.z * t;
  305.                 isect.n.x = isect.p.x - sphCenter.x;
  306.                 isect.n.y = isect.p.y - sphCenter.y;
  307.                 isect.n.z = isect.p.z - sphCenter.z;
  308.                 isect.n.normalize();
  309.             }
  310.         }
  311.     }
  312.     
  313.     // check ray intersection by plane
  314.     private function _intersectByPlane(isect:Isect, ray:Ray, pln:Plane) : void {
  315.         var v:Number = pln.n.x*ray.dir.x + pln.n.y*ray.dir.y + pln.n.z*ray.dir.z;
  316.         
  317.         // when parallel with plane
  318.         if (v>-1.0e-17 && v<1.0e-17return;
  319.         
  320.         var t:Number = -(pln.n.x*ray.org.x + pln.n.y*ray.org.y + pln.n.z*ray.org.z - pln.pn) / v;
  321.         // when the ray is intersected by the plane,
  322.         if ((t > 0.0) && (t < isect.t)) {
  323.             // calculate cross point and normal vector.
  324.             isect.t = t;
  325.             isect.hit = 1;
  326.             
  327.             isect.p.x = ray.org.x + ray.dir.x * t;
  328.             isect.p.y = ray.org.y + ray.dir.y * t;
  329.             isect.p.z = ray.org.z + ray.dir.z * t;
  330.             isect.n.x = pln.n.x;
  331.             isect.n.y = pln.n.y;
  332.             isect.n.z = pln.n.z;
  333.         }
  334.     }
  335. }
noswf
Get Adobe Flash Player