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


forked from : keim_at_Si's Code based Structure Synth [diff(167)]

embed

FAVORITE BY
:
:
StructureSynth3Dportage structure synth
:
3d
:
:
:
3d3d
:
:
3D
:
Structure Synthをオリジナルで実装。
:
PV3D使っていないんですか!?
:
it's geting better and better
:
かっこいー
:
3dすごい!
:
しゅごーい
FORKED
  1. // forked from keim_at_Si's Regular Solid Structures
  2. // forked from keim_at_Si's Code based Structure Synth
  3. // Code based Structure Synth
  4. //  Structure Synth; http://structuresynth.sourceforge.net/
  5. //------------------------------------------------------------
  6. package {
  7.     import flash.display.*;
  8.     import flash.events.*;
  9.     import flash.geom.*;
  10.     import flash.utils.*;
  11.     import flash.text.*;
  12.     [SWF(width='465', height='465', backgroundColor='#000000', frameRate='30')]
  13.     public class main extends Sprite {
  14.         // 3D renders
  15.         private var _materials:Vector.<Material> = new Vector.<Material>();
  16.         private var _light:Light = new Light(1,1,1);
  17.         private var _screen:BitmapData = new BitmapData(465465false0);
  18.         private var _matscr:Matrix = new Matrix(1001232.5232.5);
  19.         private var _tf:TextField = new TextField();
  20.         private var gl:Render3D = new Render3D(300,1);
  21.         private var ss:StructureSynth = new StructureSynth(gl);
  22.         
  23.         // objects
  24.         private var camera:Vector3D;
  25.         private var structure:Vector.<Mesh> = new Vector.<Mesh>(5true);
  26.         private var structName:Array = ["tetrahedrons","hexahedrons","octahedrons","dodecahedrons","icosahedrons"];
  27.         
  28.         // motions
  29.         private var structNum:int = 0;
  30.         
  31.         // entry point
  32.         function main() {
  33.             var i:int;
  34.             _tf.autoSize = "left";
  35.             camera = new Vector3D(0, -5, -50);
  36.             _materials.push((new Material()).setColor(0xff8080, 641923280),
  37.                             (new Material()).setColor(0xd0d080, 641923280),
  38.                             (new Material()).setColor(0x80ff80, 641923280),
  39.                             (new Material()).setColor(0x80c0c0, 641924880),
  40.                             (new Material()).setColor(0x8080ff, 641926480));
  41.             for (i=0; i<5; i++) structure[i] = new Mesh(_materials);
  42.             addChild(gl).visible = false;
  43.             addChild(new Bitmap(_screen));
  44.             addChild(_tf);
  45.             addEventListener("enterFrame", _onEnterFrame);
  46.             stage.addEventListener("click", _onClick);
  47.             
  48.             // register meshes
  49.             ss.mesh("tetra",  SolidFactory.tetrahedron (new Mesh(), 10));  // 4vertices/4triangles
  50.             ss.mesh("box",    SolidFactory.hexahedron  (new Mesh(), 11false));  // 8vertices/12triangles
  51.             ss.mesh("octa",   SolidFactory.octahedron  (new Mesh(), 12));  // 6vertices/8triangles
  52.             ss.mesh("dodeca", SolidFactory.dodecahedron(new Mesh(), 13));  // 12vertices/36triangles
  53.             ss.mesh("icosa",  SolidFactory.icosahedron (new Mesh(), 14));  // 20vertices/20triangles
  54.            
  55.             // create mesh by Structure Synth
  56.             // structure[0]
  57.             ss.rule("s0r1"function() : void {
  58.                 ss.call("{rz 6 x -2.5} s0r2");
  59.                 ss.call("{ry 60} s0r1");
  60.             }, {md:6});
  61.             ss.rule("s0r2"function() : void {
  62.                 ss.call("{rz -54.73561032 ry 45} tetra");
  63.                 ss.call("{rz 6 x -2.5} s0r2");
  64.             }, {md:28});
  65.             ss.init(structure[0]).call("{y 30} s0r1");
  66.             ss.init(structure[0]).call("{y 0 ry 30} s0r1");
  67.             structure[0].updateFaces();
  68.             // structure[1]
  69.             ss.rule("s1r1"function() : void {
  70.                 ss.call("s1r2");
  71.                 ss.call("{rx 20 z 4} s1r1");
  72.             }, {md:18});
  73.             ss.rule("s1r2"function() : void {
  74.                 ss.call("box");
  75.                 ss.call("{x 2.4 y -1 z -1 s 1 0.94 0.94} s1r2");
  76.             }, {md:32});
  77.             ss.init(structure[1]).call("{x -36 y 11} s1r1");
  78.             structure[1].updateFaces();
  79.             
  80.             // structure[2]
  81.             ss.rule("s2r1"function() : void {
  82.                 ss.call("3 * {y 2 rx 5} octa");
  83.                 ss.call("{y 6 rz 30 ry 45 s 0.8} s2r1"); 
  84.                 ss.call("{y 6 rz -30 ry 45 s 0.8} s2r1");
  85.             });
  86.             ss.rule("s2r1"function() : void {
  87.                 ss.call("3 * {y 2 rx -5} octa");
  88.                 ss.call("{y 6 rz 30 ry 45 s 0.8} s2r1"); 
  89.                 ss.call("{y 6 rz -30 ry 45 s 0.8} s2r1");
  90.             });
  91.             ss.init(structure[2], 8).call("{s 1.5} s2r1");
  92.             structure[2].updateFaces();
  93.             
  94.             // structure[3]
  95.             ss.rule("s3r1"function() : void {
  96.                 ss.call("s3r2");
  97.                 ss.call("{s 1.5} s3r1");
  98.             }, {md:6});
  99.             ss.rule("s3r2"function() : void {
  100.                 ss.call("{y -4} dodeca");
  101.                 ss.call("5 * {ry 72} s3r3");
  102.             });
  103.             ss.rule("s3r3"function() : void {
  104.                 ss.call("{rz 65 y -4} dodeca");
  105.             });
  106.             ss.init(structure[3]).call("s3r1");
  107.             ss.init(structure[3]).call("{rz 180} s3r1");
  108.             structure[3].updateFaces();
  109.             
  110.             // structure[4]
  111.             ss.rule("s4rx"function() : void {
  112.                 ss.call("icosa");
  113.                 ss.call("{z 3 x 3} s4rz");
  114.                 ss.call("{y 3 z 3} s4ry");
  115.                 ss.call("{x 3 y 3} s4rx");
  116.             });
  117.             ss.rule("s4ry"function() : void {
  118.                 ss.call("icosa");
  119.                 ss.call("{z 3 x 3} s4rz");
  120.                 ss.call("{y 3 z 3} s4ry");
  121.             });
  122.             ss.rule("s4rz"function() : void {
  123.                 ss.call("icosa");
  124.                 ss.call("{z 3 x 3} s4rz");
  125.             });
  126.             ss.init(structure[4], 8).call("{x -21.2132 y -21.2132 z -21.2132 s 2} s4rx"); 
  127.             structure[4].updateFaces();
  128.             
  129.             structNum = -1;
  130.             _onClick(null);
  131.         }
  132.         private function _onEnterFrame(e:Event) : void {
  133.             _screen.fillRect(_screen.rect, 0);
  134.             _light.transformBy(gl.id().tv(camera).rx((400-mouseY)*0.25).ry((232-mouseX)*0.75).matrix);
  135.             _screen.draw(gl.push().t(000).project(structure[structNum]).renderSolid(_light).pop(), _matscr);
  136.         }
  137.         
  138.         private function _onClick(e:Event) : void {
  139.             if (++structNum == structure.length) structNum = 0;
  140.             _tf.htmlText = "<font color='#ffffff' face='_typewriter'>Click to change the structure[" + structName[structNum] + "]</font>";
  141.         }
  142.     }
  143. }
  144. import flash.display.*;
  145. import flash.geom.*;
  146. // Solid Factory
  147. //----------------------------------------------------------------------------------------------------
  148. class SolidFactory {
  149.     // regular solids
  150.     //--------------------------------------------------
  151.     static public function tetrahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  152.         mesh.vertices.push(size,size,size, size,-size,-size, -size,size,-size, -size,-size,size);
  153.         mesh.qface(0,2,1,3,mat).qface(1,3,0,2,mat);
  154.         return mesh.updateFaces();
  155.     }
  156.     
  157.     static public function hexahedron(mesh:Mesh, size:Number, mat:int=0, div:Boolean=true) : Mesh {
  158.         for (var i:int=0; i<8; i++) mesh.vertices.push((i&1)?size:-size, ((i>>1)&1)?size:-size, (i>>2)?size:-size);
  159.         mesh.qface(0,1,2,3,mat,div).qface(1,0,5,4,mat,div).qface(0,2,4,6,mat,div);
  160.         mesh.qface(2,3,6,7,mat,div).qface(3,1,7,5,mat,div).qface(5,4,7,6,mat,div);
  161.         return mesh.updateFaces();
  162.     }
  163.     
  164.     static public function octahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  165.         mesh.vertices.push(0,0,-size, -size,0,00,-size,0, size,0,00,size,00,0,size);
  166.         mesh.qface(0,1,2,5,mat).qface(0,2,3,5,mat).qface(0,3,4,5,mat).qface(0,4,1,5,mat);
  167.         return mesh.updateFaces();
  168.     }
  169.     
  170.     static public function dodecahedron(mesh:Mesh, size:Number, mat:int=0, div:Boolean=true) : Mesh {
  171.         var a:Number=size*0.149071198, b:Number=size*0.241202266, c:Number=size*0.283550269
  172.             d:Number=size*0.390273464, e:Number=size*0.458793973, f:Number=size*0.631475730
  173.             g:Number=size*0.742344243;
  174.         mesh.vertices.push(c,f,d, e,f,-a, 0,f,-b-b, -e,f,-a, -c,f,d);
  175.         mesh.vertices.push(e,a,f, g,a,-b, 0,a,-d-d, -g,a,-b, -e,a,f);
  176.         mesh.vertices.push(0,-a,d+d, g,-a,b, e,-a,-f, -e,-a,-f, -g,-a,b);
  177.         mesh.vertices.push(0,-f,b+b, e,-f,a, c,-f,-d, -c,-f,-d, -e,-f,a);
  178.         mesh.qface(0,3,1,2,mat,div).face(0,4,3,mat).qface(4,5,9,10,mat,div).face(4,0,5,mat);
  179.         mesh.qface(0,6,5,11,mat,div).face(0,1,6,mat).qface(1,7,6,12,mat,div).face(1,2,7,mat);
  180.         mesh.qface(2,8,7,13,mat,div).face(2,3,8,mat).qface(3,9,8,14,mat,div).face(3,4,9,mat);
  181.         mesh.qface(17,11,12,6,mat,div).face(17,16,11,mat).qface(16,10,11,5,mat,div).face(16,15,10,mat);
  182.         mesh.qface(15,14,10,9,mat,div).face(15,19,14,mat).qface(19,13,14,8,mat,div).face(19,18,13,mat);
  183.         mesh.qface(18,12,13,7,mat,div).face(18,17,12,mat).qface(16,18,15,19,mat,div).face(16,17,18,mat);
  184.         return mesh.updateFaces();
  185.     }
  186.     
  187.     static public function icosahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  188.         var a:Number=size*0.276393202, b:Number=size*0.447213595, c:Number=size*0.525731112
  189.             d:Number=size*0.723606798, e:Number=size*0.850650808;
  190.         mesh.vertices.push(0,size,00,b,b+b, e,b,a, c,b,-d, -c,b,-d, -e,b,a);
  191.         mesh.vertices.push(e,-b,-a, c,-b,d, -c,-b,d, -e,-b,-a, 0,-b,-b-b, 0,-size,0);
  192.         mesh.qface(0,2,1,7,mat).qface(0,3,2,6,mat).qface(0,4,3,10,mat).qface(0,5,4,9,mat).qface(0,1,5,8,mat);
  193.         mesh.qface(1,7,8,11,mat).qface(2,6,7,11,mat).qface(3,10,6,11,mat).qface(4,9,10,11,mat).qface(5,8,9,11,mat);
  194.         return mesh.updateFaces();
  195.     }
  196. }
  197. // Structure Synth
  198. //----------------------------------------------------------------------------------------------------
  199. class StructureSynth {
  200.     private var _mesh:Mesh;
  201.     private var _functions:* = new Object();
  202.     private var _meshes:* = new Object();
  203.     private var _maxDepth:int;
  204.     private var _depth:int;
  205.     private var _core:Render3D;
  206.     static private var _rexLine:RegExp = /((\d+)\s*\*)?\s*({(.*?)})?\s*([^{}\s]+)/;
  207.     static private var _rexOperate:RegExp = /(r?[x-z]|s)\s*([\-\d.]+)\s*([\-\d.]+)?\s*([\-\d.]+)?/g;
  208.     
  209.     function StructureSynth(core:Render3D) { 
  210.         _core = core;
  211.     }
  212.     
  213.     /** register mesh to call in CFDG.
  214.      *  @param name Mesh name to call.
  215.      *  @param mesh Mesh data.
  216.      */
  217.     public function mesh(name:String, mesh:Mesh) : StructureSynth {
  218.         _meshes[name] = mesh;
  219.         return this;
  220.     }
  221.     
  222.     /** register rule.
  223.      *  @param name Rule name to call.
  224.      *  @param func Function to execute. The type is "function(depth:int) : void".
  225.      *  @param option Option["w"/"weight"] to set weight and the option["md"/"maxdepth"] to set maxdepth.
  226.      */
  227.     public function rule(name:String, func:Function, option:*=null) : StructureSynth {
  228.         if (!(name in _functions)) _functions[name] = new SSFunctionList();
  229.         _functions[name].rule(func, option||new Object());
  230.         return this;
  231.     }
  232.     
  233.     /** initialize to constructing structure */
  234.     public function init(mesh:Mesh, maxDepth:int=512) : StructureSynth {
  235.         for each (var func:SSFunctionList in _functions) func.init();
  236.         _maxDepth = maxDepth;
  237.         _depth = 0;
  238.         _mesh = mesh;
  239.         _core.id();
  240.         return this;
  241.     }
  242.     
  243.     /** command 1 line in CFDG. */
  244.     public function call(line:String) : StructureSynth {
  245.         var i:int, imax:int, res:*;
  246.         res = _rexLine.exec(line);
  247.         if (res) {
  248.             _core.push();
  249.             imax = (res[2]) ? int(res[2]) : 1;
  250.             for (i=0; i<imax; i++) {
  251.                 operate(res[4]);
  252.                 if (res[5in _functions) {
  253.                     if (++_depth <= _maxDepth) _functions[res[5]].call();
  254.                     _depth--;
  255.                 } else 
  256.                 if (res[5in _meshes) {
  257.                     _core.project(_meshes[res[5]]);
  258.                     _mesh.put(_meshes[res[5]]);
  259.                 }
  260.             }
  261.             _core.pop();
  262.         }
  263.         return this;
  264.     }
  265.     
  266.     /** opreate matrix */
  267.     public function operate(ope:String) : void {
  268.         //_rexOperate.lastIndex = 0;
  269.         var res:* = _rexOperate.exec(ope);
  270.         while(res) {
  271.             var n:Number = Number(res[2]);
  272.             switch (res[1]) {
  273.             case 'x':  _core.t(n,0,0); break;
  274.             case 'y':  _core.t(0,n,0); break;
  275.             case 'z':  _core.t(0,0,n); break;
  276.             case 'rx': _core.rx(n);    break;
  277.             case 'ry': _core.ry(n);    break;
  278.             case 'rz': _core.rz(n);    break;
  279.             case 's':
  280.                 if (res[3]) _core.s(n, Number(res[3]), Number(res[4]));
  281.                 else _core.s(n, n, n);
  282.                 break;
  283.             }
  284.             res = _rexOperate.exec(ope);
  285.         }
  286.     }
  287. }
  288. class SSFunctionList {
  289.     private var _totalWeight:Number = 0;
  290.     private var _functions:Vector.<SSFunction> = new Vector.<SSFunction>();
  291.     
  292.     public function rule(func:Function, option:*) : void {
  293.         var ssf:SSFunction = new SSFunction(func, option);
  294.         _functions.push(ssf);
  295.         _totalWeight += ssf.weight;
  296.     }
  297.     public function init() : void {
  298.         for each (var ssf:SSFunction in _functions) ssf.depth = 0;
  299.     }
  300.     
  301.     public function call() : void {
  302.         var w:Number = 0, rand:Number = Math.random() * _totalWeight;
  303.         for each (var ssf:SSFunction in _functions) {
  304.             w += ssf.weight;
  305.             if (rand <= w) {
  306.                 if (++ssf.depth <= ssf.maxdepth) ssf.func();
  307.                 ssf.depth--;
  308.                 return;
  309.             }
  310.         }
  311.     }
  312. }
  313. class SSFunction {
  314.     public var func:Function;
  315.     public var weight:Number;
  316.     public var maxdepth:int;
  317.     public var depth:int = 0;
  318.     
  319.     function SSFunction(func:Function, option:*) {
  320.         this.func = func;
  321.         this.weight = option["w"] || option["weight"] || 1;
  322.         this.maxdepth = option["md"] || option["maxdepth"] || int.MAX_VALUE;
  323.     }
  324. }
  325. // 3D Engine
  326. //----------------------------------------------------------------------------------------------------
  327. /** Core */
  328. class Render3D extends Shape {
  329.     /** model view matrix */
  330.     public var matrix:Matrix3D;
  331.     private var _meshProjected:Mesh = null;                              // projecting mesh
  332.     private var _facesProjected:Vector.<Face> = new Vector.<Face>();     // projecting face
  333.     private var _projectionMatrix:Matrix3D;                              // projection matrix
  334.     private var _matrixStac:Vector.<Matrix3D> = new Vector.<Matrix3D>(); // matrix stac
  335.     private var _cmdTriangle:Vector.<int> = Vector.<int>([1,2,2]);       // commands to draw triangle
  336.     private var _cmdQuadrangle:Vector.<int> = Vector.<int>([1,2,2,2]);   // commands to draw quadrangle
  337.     private var _data:Vector.<Number> = new Vector.<Number>(8true);    // data to draw shape
  338.     private var _clippingZ:Number;                                       // z value of clipping plane
  339.     
  340.     /** constructor */
  341.     function Render3D(focus:Number=300, clippingZ:Number=-0.1) {
  342.         var projector:PerspectiveProjection = new PerspectiveProjection()
  343.         projector.focalLength = focus;
  344.         _projectionMatrix = projector.toMatrix3D();
  345.         _clippingZ = -clippingZ;
  346.         matrix = new Matrix3D();
  347.         _matrixStac.length = 1;
  348.         _matrixStac[0] = matrix;
  349.     }
  350.     // control matrix
  351.     //--------------------------------------------------
  352.     public function clear() : Render3D { matrix = _matrixStac[0]; _matrixStac.length = 1return this; }
  353.     public function push() : Render3D { _matrixStac.push(matrix.clone()); return this; }
  354.     public function pop() : Render3D { matrix = (_matrixStac.length == 1) ? matrix : _matrixStac.pop(); return this; }
  355.     public function id() : Render3D { matrix.identity(); return this; }
  356.     public function t(x:Number, y:Number, z:Number) : Render3D { matrix.prependTranslation(x, y, z); return this; }
  357.     public function tv(v:Vector3D) : Render3D { matrix.prependTranslation(v.x, v.y, v.z); return this; }
  358.     public function s(x:Number, y:Number, z:Number) : Render3D { matrix.prependScale(x, y, z); return this; }
  359.     public function sv(v:Vector3D) : Render3D { matrix.prependScale(v.x, v.y, v.z); return this; }
  360.     public function r(angle:Number, axis:Vector3D) : Render3D { matrix.prependRotation(angle, axis); return this; }
  361.     public function rv(v:Vector3D) : Render3D { matrix.prependRotation(v.w, v); return this; }
  362.     public function rx(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.X_AXIS); return this; }
  363.     public function ry(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.Y_AXIS); return this; }
  364.     public function rz(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.Z_AXIS); return this; }
  365.     
  366.     // projections
  367.     //--------------------------------------------------
  368.     /** project */
  369.     public function project(mesh:Mesh) : Render3D {
  370.         matrix.transformVectors(mesh.vertices, mesh.verticesOnWorld);
  371.         var fn:Point3D, vs:Vector.<Number> = mesh.verticesOnWorld;
  372.         var m:Vector.<Number> = matrix.rawData, 
  373.             m00:Number = m[0], m01:Number = m[1], m02:Number = m[2], 
  374.             m10:Number = m[4], m11:Number = m[5], m12:Number = m[6], 
  375.             m20:Number = m[8], m21:Number = m[9], m22:Number = m[10];
  376.         _facesProjected.length = 0;
  377.         for each (var f:Face in mesh.faces) {
  378.             var i0:int=(f.i0<<1)+f.i0, i1:int=(f.i1<<1)+f.i1, i2:int=(f.i2<<1)+f.i2,
  379.                 x0:Number=vs[i0++], x1:Number=vs[i1++], x2:Number=vs[i2++],
  380.                 y0:Number=vs[i0++], y1:Number=vs[i1++], y2:Number=vs[i2++],
  381.                 z0:Number=vs[i0],   z1:Number=vs[i1],   z2:Number=vs[i2];
  382.             if (z0<_clippingZ && z1<_clippingZ && z2<_clippingZ) {
  383.                 fn = f.normal;
  384.                 fn.world.x = fn.x * m00 + fn.y * m10 + fn.z * m20;
  385.                 fn.world.y = fn.x * m01 + fn.y * m11 + fn.z * m21;
  386.                 fn.world.z = fn.x * m02 + fn.y * m12 + fn.z * m22;
  387.                 if (vs[f.pvi-2]*fn.world.x + vs[f.pvi-1]*fn.world.y + vs[f.pvi]*fn.world.z <= 0) {
  388.                     _facesProjected.push(f);
  389.                 }
  390.             }
  391.         }
  392.         _facesProjected.sort(function(f1:Face, f2:Face):Numberreturn vs[f1.pvi] - vs[f2.pvi]; });
  393.         _meshProjected = mesh;
  394.         return this;
  395.     }
  396.     
  397.     /** project slower than transformVectors() but Vector3D.w considerable. */
  398.     public function projectPoint3D(points:Vector.<Point3D>) : Render3D {
  399.         var m:Vector.<Number> = matrix.rawData, p:Point3D, 
  400.             m00:Number = m[0],  m01:Number = m[1],  m02:Number = m[2], 
  401.             m10:Number = m[4],  m11:Number = m[5],  m12:Number = m[6], 
  402.             m20:Number = m[8],  m21:Number = m[9],  m22:Number = m[10], 
  403.             m30:Number = m[12], m31:Number = m[13], m32:Number = m[14];
  404.         for each (p in points) {
  405.             p.world.x = p.x * m00 + p.y * m10 + p.z * m20 + p.w * m30;
  406.             p.world.y = p.x * m01 + p.y * m11 + p.z * m21 + p.w * m31;
  407.             p.world.z = p.x * m02 + p.y * m12 + p.z * m22 + p.w * m32;
  408.         }
  409.         return this;
  410.     }
  411.     // rendering
  412.     //--------------------------------------------------
  413.     /** render solid */
  414.     public function renderSolid(light:Light) : Render3D {
  415.         var idx:int, mat:Material, materials:Vector.<Material> = _meshProjected.materials,
  416.             vout:Vector.<Number> = _meshProjected.verticesOnScreen;
  417.         Utils3D.projectVectors(_projectionMatrix, _meshProjected.verticesOnWorld, vout, _meshProjected.texCoord);
  418.         graphics.clear();
  419.         for each (var face:Face in _facesProjected) {
  420.             mat = materials[face.mat];
  421.             graphics.beginFill(mat.getColor(light, face.normal.world), mat.alpha);
  422.             idx = face.i0<<1;
  423.             _data[0] = vout[idx]; idx++;
  424.             _data[1] = vout[idx];
  425.             idx = face.i1<<1;
  426.             _data[2] = vout[idx]; idx++;
  427.             _data[3] = vout[idx];
  428.             idx = face.i2<<1;
  429.             _data[4] = vout[idx]; idx++;
  430.             _data[5] = vout[idx];
  431.             if (face.i3 == -1) {
  432.                 graphics.drawPath(_cmdTriangle, _data);
  433.             } else {
  434.                 idx = face.i3<<1;
  435.                 _data[6] = vout[idx]; idx++;
  436.                 _data[7] = vout[idx];
  437.                 graphics.drawPath(_cmdQuadrangle, _data);
  438.             }
  439.             graphics.endFill();
  440.         }
  441.         return this;
  442.     }
  443.     
  444.     /** render with texture */
  445.     private var _indices:Vector.<int> = new Vector.<int>(); // temporary index list
  446.     public function renderTexture(texture:BitmapData) : Render3D {
  447.         var idx:int, mat:Material, indices:Vector.<int> = _indices;
  448.         indices.length = 0;
  449.         for each (var face:Face in _facesProjected) { indices.push(face.i0, face.i1, face.i2); }
  450.         Utils3D.projectVectors(_projectionMatrix, 
  451.                                _meshProjected.verticesOnWorld, 
  452.                                _meshProjected.verticesOnScreen, 
  453.                                _meshProjected.texCoord);
  454.         graphics.clear();
  455.         graphics.beginBitmapFill(texture, nullfalsetrue);
  456.         graphics.drawTriangles(_meshProjected.verticesOnScreen, indices, _meshProjected.texCoord);
  457.         graphics.endFill();
  458.         return this;
  459.     }
  460. }
  461. /** Point3D */
  462. class Point3D extends Vector3D {
  463.     public var world:Vector3D;
  464.     function Point3D(x:Number=0, y:Number=0, z:Number=0, w:Number=1) { super(x,y,z,w); world=clone(); }
  465. }
  466. /** Face */
  467. class Face {
  468.     public var i0:int, i1:int, i2:int, i3:int, pvi:int, mat:int, normal:Point3D;
  469.     static private var _freeList:Vector.<Face> = new Vector.<Face>();
  470.     static public function free(face:Face) : void { _freeList.push(face); }
  471.     static public function alloc(i0:int, i1:int, i2:int, i3:int, mat:int) : Face { 
  472.         var f:Face = _freeList.pop() || new Face();
  473.         f.i0=i0; f.i1=i1; f.i2=i2; f.i3=i3; f.pvi=0; f.mat=mat;
  474.         return f;
  475.     }
  476. }
  477. /** Mesh */
  478. class Mesh {
  479.     public var materials:Vector.<Material>;                 // material list
  480.     public var vertices:Vector.<Number>;                    // vertex
  481.     public var verticesOnWorld:Vector.<Number>;             // vertex on camera coordinate
  482.     public var verticesOnScreen:Vector.<Number>;            // vertex on screen
  483.     public var verticesCount:int;                           // vertex count
  484.     public var texCoord:Vector.<Number>;                    // texture coordinate
  485.     public var faces:Vector.<Face> = new Vector.<Face>();   // face list
  486.     public var vnormals:Vector.<Vector3D>;                  // vertex normal
  487.     
  488.     /** constructor */
  489.     function Mesh(materials:Vector.<Material>=null) {
  490.         this.materials = materials;
  491.         this.vertices = new Vector.<Number>();
  492.         this.texCoord = new Vector.<Number>();
  493.         this.verticesOnWorld = new Vector.<Number>();
  494.         this.verticesOnScreen = new Vector.<Number>();
  495.         this.vnormals = null;
  496.         this.verticesCount = 0;
  497.     }
  498.     
  499.     /** clear all faces */
  500.     public function clear() : Mesh {
  501.         for each (var face:Face in faces) Face.free(face);
  502.         faces.length = 0;
  503.         return this;
  504.     }
  505.     
  506.     /** register face */
  507.     public function face(i0:int, i1:int, i2:int, mat:int=0) : Mesh {
  508.         faces.push(Face.alloc(i0, i1, i2, -1, mat));
  509.         return this;
  510.     }
  511.     
  512.     /** register quadrangle face. set div=true to divide into 2 triangles. */
  513.     public function qface(i0:int, i1:int, i2:int, i3:int, mat:int=0, div:Boolean=true) : Mesh {
  514.         if (div) faces.push(Face.alloc(i0, i1, i2, -1, mat), Face.alloc(i3, i2, i1, -1, mat));
  515.         else     faces.push(Face.alloc(i0, i1, i3, i2, mat));
  516.         return this;
  517.     }
  518.     
  519.     /** put mesh on world coordinate. */
  520.     public function put(src:Mesh, mat:int=-1) : Mesh {
  521.         var i0:int = vertices.length, imax:int, i:int;
  522.         imax = (src.verticesCount<<1) + src.verticesCount;
  523.         vertices.length += imax;
  524.         for (i=0; i<imax; i++) vertices[i0+i] = src.verticesOnWorld[i];
  525.         i0 /= 3;
  526.         for each (var f:Face in src.faces) {
  527.             i = (mat == -1) ? f.mat : mat;
  528.             if (f.i3==-1) face (f.i0+i0, f.i1+i0, f.i2+i0, i);
  529.             else          qface(f.i0+i0, f.i1+i0, f.i3+i0, f.i2+i0, i, false);
  530.         }
  531.         return this;
  532.     }
  533.     
  534.     /** update face gravity point and normal */
  535.     public function updateFaces() : Mesh {
  536.         verticesCount = vertices.length/3;
  537.         var vs:Vector.<Number> = vertices;
  538.         for each (var f:Face in faces) {
  539.             f.pvi = vs.length+2;
  540.             var i0:int=(f.i0<<1)+f.i0, i1:int=(f.i1<<1)+f.i1, i2:int=(f.i2<<1)+f.i2;
  541.             var x01:Number=vs[i1]-vs[i0], x02:Number=vs[i2]-vs[i0];
  542.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  543.             var y01:Number=vs[i1]-vs[i0], y02:Number=vs[i2]-vs[i0];
  544.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  545.             var z01:Number=vs[i1]-vs[i0], z02:Number=vs[i2]-vs[i0];
  546.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  547.             f.normal = new Point3D(y02*z01-y01*z02, z02*x01-z01*x02, x02*y01-x01*y02, 0);
  548.             f.normal.normalize();
  549.             if (f.i3 != -1) {
  550.                 var i3:int = (f.i3<<1)+f.i3;
  551.                 vs[f.pvi-2] = vs[f.pvi-2]*0.75 + vs[i3++]*0.25;
  552.                 vs[f.pvi-1] = vs[f.pvi-1]*0.75 + vs[i3++]*0.25;
  553.                 vs[f.pvi]   = vs[f.pvi]  *0.75 + vs[i3]  *0.25;
  554.             }
  555.         }
  556.         return this;
  557.     }
  558. }
  559. /** Light */
  560. class Light extends Point3D {
  561.     public var halfVector:Vector3D = new Vector3D();
  562.     
  563.     /** constructor (set position) */
  564.     function Light(x:Number=1, y:Number=1, z:Number=1) {
  565.         super(x, y, z, 0);
  566.         normalize();
  567.     }
  568.     /** projection */
  569.     public function transformBy(matrix:Matrix3D) : void {
  570.         world = matrix.deltaTransformVector(this);
  571.         halfVector.x = world.x;
  572.         halfVector.y = world.y;
  573.         halfVector.z = world.z + 1
  574.         halfVector.normalize();
  575.     }
  576. }
  577. /** Material */
  578. class Material extends BitmapData {
  579.     public var alpha:Number = 1;    // The alpha value is available for renderSolid()
  580.     public var doubleSided:int = 0// set doubleSided=-1 if double sided material
  581.     
  582.     /** constructor */
  583.     function Material(dif:int=128, spc:int=128) { super(dif, spc, false); }
  584.     
  585.     /** set color. */
  586.     public function setColor(col:uint, amb:int=64, dif:int=192, spc:int=0,  pow:Number=8) : Material {
  587.         fillRect(rect, col);
  588.         var lmap:LightMap = new LightMap(width, height);
  589.         draw(lmap.diffusion(amb, dif), nullnull"hardlight");
  590.         draw(lmap.specular (spc, pow), nullnull"add");
  591.         lmap.dispose();
  592.         return this;
  593.     }
  594.     
  595.     /** calculate color by light and normal vector. */
  596.     public function getColor(l:Light, n:Vector3D) : uint {
  597.         var dir:Vector3D = l.world, hv:Vector3D = l.halfVector;
  598.         var ln:int = int((dir.x * n.x + dir.y * n.y + dir.z * n.z) * (width-1)),
  599.             hn:int = int((hv.x  * n.x + hv.y  * n.y + hv.z  * n.z) * (height-1));
  600.         if (ln<0) ln = (-ln) & doubleSided;
  601.         if (hn<0) hn = (-hn) & doubleSided;
  602.         return getPixel(ln, hn);
  603.     }
  604. }
  605. class LightMap extends BitmapData {
  606.     function LightMap(dif:int, spc:int) { super(dif, spc, false); }
  607.     
  608.     public function diffusion(amb:int, dif:int) : BitmapData {
  609.         var col:int, rc:Rectangle = new Rectangle(001, height), ipk:Number = 1 / width;
  610.         for (rc.x=0; rc.x<width; rc.x+=1) {
  611.             col = ((rc.x * (dif - amb)) * ipk) + amb;
  612.             fillRect(rc, (col<<16)|(col<<8)|col);
  613.         }
  614.         return this;
  615.     }
  616.     
  617.     public function specular(spc:int, pow:Number) : BitmapData {
  618.         var col:int, rc:Rectangle = new Rectangle(00, width, 1),
  619.             mpk:Number = (pow + 2) * 0.15915494309189534, ipk:Number = 1 / height;
  620.         for (rc.y=0; rc.y<height; rc.y+=1) {
  621.             col = Math.pow(rc.y * ipk, pow) * spc * mpk;
  622.             if (col > 255) col = 255;
  623.             fillRect(rc, (col<<16)|(col<<8)|col);
  624.         }
  625.         return this;
  626.     }
  627. }
noswf

Regular Solid Structures Depth buffer test [diff(351)]

  1. // forked from keim_at_Si's Regular Solid Structures
  2. // forked from keim_at_Si's Code based Structure Synth
  3. // Code based Structure Synth
  4. //  Structure Synth; http://structuresynth.sourceforge.net/
  5. //------------------------------------------------------------
  6. package {
  7.     import flash.display.*;
  8.     import flash.events.*;
  9.     import flash.geom.*;
  10.     import flash.utils.*;
  11.     import flash.text.*;
  12.     [SWF(width='465', height='465', backgroundColor='#000000', frameRate='30')]
  13.     public class main extends Sprite {
  14.         // 3D renders
  15.         private var _materials:Vector.<Material> = new Vector.<Material>();
  16.         private var _light:Light = new Light(1,0.5,0.25);
  17.         private var _screen:BitmapData = new BitmapData(400400false0);
  18.         private var _matbuf:Matrix = new Matrix(1001200200);
  19.         private var _tf:TextField = new TextField();
  20.         private var gl:Render3D = new Render3D(300,1);
  21.         private var ss:StructureSynth = new StructureSynth();
  22.         // objects
  23.         private var camera:Vector3D;
  24.         private var struct:Vector.<Mesh> = new Vector.<Mesh>(5true);
  25.         private var projected:Vector.<ProjectionMesh> = new Vector.<ProjectionMesh>(5true);
  26.         
  27.         private var _depth:BitmapData;
  28.         private var _mask :BitmapData;
  29.         private var depthBuffer:Vector.<BitmapData> = new Vector.<BitmapData>(2true);
  30.         private var pixelBuffer:Vector.<BitmapData> = new Vector.<BitmapData>(2true);
  31.         
  32.         // motions
  33.         private var clicked:Boolean = false;
  34.         private var frame:int = 0;
  35.         
  36.         // entry point
  37.         function main() {
  38.             stage.quality = "low";
  39.             
  40.             var i:int;
  41.             _tf.autoSize = "left";
  42.             _tf.htmlText = "<font color='#ffffff' face='_typewriter'>Click to view depth buffer.</font>"
  43.             camera = new Vector3D(0, -5, -50);
  44.             _materials.push((new Material()).setColor(0xff8080, 641923280),
  45.                             (new Material()).setColor(0xd0d080, 641923280),
  46.                             (new Material()).setColor(0x80ff80, 641923280),
  47.                             (new Material()).setColor(0x80c0c0, 641924880),
  48.                             (new Material()).setColor(0x8080ff, 641926480));
  49.             for (i=0; i<5; i++) struct[i] = new Mesh(_materials);
  50.             addChild(gl).visible = false;
  51.             with(addChild(new Bitmap(_screen))) { x = y = 32; }
  52.             addChild(_tf);
  53.             addEventListener("enterFrame", _onEnterFrame);
  54.             stage.addEventListener("click", _onClick);
  55.             
  56.             // register meshes
  57.             ss.mesh("tetra",  SolidFactory.tetrahedron (new Mesh(), 10));  // 4vertices/4triangles
  58.             ss.mesh("box",    SolidFactory.hexahedron  (new Mesh(), 11));  // 8vertices/12triangles
  59.             ss.mesh("octa",   SolidFactory.octahedron  (new Mesh(), 12));  // 6vertices/8triangles
  60.             ss.mesh("dodeca", SolidFactory.dodecahedron(new Mesh(), 13));  // 12vertices/36triangles
  61.             ss.mesh("icosa",  SolidFactory.icosahedron (new Mesh(), 14));  // 20vertices/20triangles
  62.            
  63.             for (i=0; i<depthBuffer.length; i++) {
  64.                 depthBuffer[i] = new BitmapData(400400false);
  65.                 pixelBuffer[i] = new BitmapData(400400true);
  66.             }
  67.             _depth= new BitmapData(400400false0);
  68.             _mask = new BitmapData(400400false0);
  69.             
  70.             // create mesh by Structure Synth
  71.             // struct[0]
  72.             ss.rule("r00"function():void{
  73.                 ss.call("2{x6}2{y6}3{z3}box{y9z-3}2{x6}2{z6}box{x9z-3}2{y6}2{z6}box");
  74.             });
  75.             ss.init(struct[0]).call("{s4}{x-9y-9z-6}r00");
  76.             projected[0] = new ProjectionMesh(struct[0].updateFaces());
  77.             // struct[1]
  78.             ss.rule("r10"function():void {
  79.                 ss.call("octa{x-6}2{x4}dodeca{y-6}2{y4}dodeca{z-6}2{z4}dodeca");
  80.             });
  81.             ss.init(struct[1]).call("{s4}{s2.5}r10");
  82.             projected[1] = new ProjectionMesh(struct[1].updateFaces());
  83.         }
  84.         private function _onEnterFrame(e:Event) : void {
  85.             frame++;
  86.             _screen.fillRect(_screen.rect, 0);
  87.             _light.transformBy(gl.id().tv(camera).rx((400-mouseY)*0.25).ry((232-mouseX)*0.75).matrix);
  88.             gl.push().rx(frame).project(projected[0]).pop();
  89.             gl.push().ry(frame*2).project(projected[1]).pop();
  90.             depthTest();
  91.         }
  92.         
  93.         private function _onClick(e:Event) : void { clicked = !clicked; }
  94.         
  95.         private function depthTest() : void {
  96.             var i:int, depthClear:int=0, operation:String="lighten";
  97.             
  98.             // clear buffers
  99.             for (i=0; i<depthBuffer.length; i++) {
  100.                 pixelBuffer[i].fillRect(pixelBuffer[i].rect, 0);
  101.                 depthBuffer[i].fillRect(depthBuffer[i].rect, 0);
  102.             }
  103.             _depth.fillRect(_depth.rect, depthClear);
  104.             
  105.             // render pixel buffer
  106.             pixelBuffer[0].draw(gl.renderSolid(projected[0], _light), _matbuf);
  107.             pixelBuffer[1].draw(gl.renderSolid(projected[1], _light), _matbuf);
  108.             
  109.             // render depth buffer
  110.             var nearZ:Number = -Number.MAX_VALUE, farZ:Number = 0;
  111.             for (i=0; i<2; i++) {
  112.                 if (nearZ < projected[i].nearZ) nearZ = projected[i].nearZ;
  113.                 if (farZ  > projected[i].farZ)  farZ  = projected[i].farZ;
  114.             }
  115.             for (i=0; i<2; i++) {
  116.                 projected[i].nearZ = nearZ+0.001;
  117.                 projected[i].farZ  = farZ-0.001;
  118.                 depthBuffer[i].draw(gl.renderDepth(projected[i]), _matbuf);
  119.                 _depth.draw(depthBuffer[i], nullnull, operation);
  120.             }
  121.             if (clicked) {
  122.                 _screen.draw(_depth);
  123.             } else {
  124.                 for (i=0; i<2; i++) {
  125.                     depthBuffer[i].draw(_depth, nullnull"difference");
  126.                     _mask.fillRect(_mask.rect, 0);
  127.                     _mask.threshold(depthBuffer[i], _mask.rect, _mask.rect.topLeft, "=="0, 0xff0000ff, 0xff);
  128.                     pixelBuffer[i].copyChannel(_mask, _mask.rect, _mask.rect.topLeft, 48);
  129.                     _screen.draw(pixelBuffer[i]);
  130.                 }
  131.             }
  132.         }
  133.     }
  134. }
  135. import flash.display.*;
  136. import flash.geom.*;
  137. // Solid Factory
  138. //----------------------------------------------------------------------------------------------------
  139. class SolidFactory {
  140.     // regular solids
  141.     //--------------------------------------------------
  142.     static public function tetrahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  143.         mesh.vertices.push(size,size,size, size,-size,-size, -size,size,-size, -size,-size,size);
  144.         mesh.qface(0,2,1,3,mat).qface(1,3,0,2,mat);
  145.         return mesh.updateFaces();
  146.     }
  147.     
  148.     static public function hexahedron(mesh:Mesh, size:Number, mat:int=0, div:Boolean=true) : Mesh {
  149.         for (var i:int=0; i<8; i++) mesh.vertices.push((i&1)?size:-size, ((i>>1)&1)?size:-size, (i>>2)?size:-size);
  150.         mesh.qface(0,1,2,3,mat,div).qface(1,0,5,4,mat,div).qface(0,2,4,6,mat,div);
  151.         mesh.qface(2,3,6,7,mat,div).qface(3,1,7,5,mat,div).qface(5,4,7,6,mat,div);
  152.         return mesh.updateFaces();
  153.     }
  154.     
  155.     static public function octahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  156.         mesh.vertices.push(0,0,-size, -size,0,00,-size,0, size,0,00,size,00,0,size);
  157.         mesh.qface(0,1,2,5,mat).qface(0,2,3,5,mat).qface(0,3,4,5,mat).qface(0,4,1,5,mat);
  158.         return mesh.updateFaces();
  159.     }
  160.     
  161.     static public function dodecahedron(mesh:Mesh, size:Number, mat:int=0, div:Boolean=true) : Mesh {
  162.         var a:Number=size*0.149071198, b:Number=size*0.241202266, c:Number=size*0.283550269
  163.             d:Number=size*0.390273464, e:Number=size*0.458793973, f:Number=size*0.631475730
  164.             g:Number=size*0.742344243;
  165.         mesh.vertices.push(c,f,d, e,f,-a, 0,f,-b-b, -e,f,-a, -c,f,d);
  166.         mesh.vertices.push(e,a,f, g,a,-b, 0,a,-d-d, -g,a,-b, -e,a,f);
  167.         mesh.vertices.push(0,-a,d+d, g,-a,b, e,-a,-f, -e,-a,-f, -g,-a,b);
  168.         mesh.vertices.push(0,-f,b+b, e,-f,a, c,-f,-d, -c,-f,-d, -e,-f,a);
  169.         mesh.qface(0,3,1,2,mat,div).face(0,4,3,mat).qface(4,5,9,10,mat,div).face(4,0,5,mat);
  170.         mesh.qface(0,6,5,11,mat,div).face(0,1,6,mat).qface(1,7,6,12,mat,div).face(1,2,7,mat);
  171.         mesh.qface(2,8,7,13,mat,div).face(2,3,8,mat).qface(3,9,8,14,mat,div).face(3,4,9,mat);
  172.         mesh.qface(17,11,12,6,mat,div).face(17,16,11,mat).qface(16,10,11,5,mat,div).face(16,15,10,mat);
  173.         mesh.qface(15,14,10,9,mat,div).face(15,19,14,mat).qface(19,13,14,8,mat,div).face(19,18,13,mat);
  174.         mesh.qface(18,12,13,7,mat,div).face(18,17,12,mat).qface(16,18,15,19,mat,div).face(16,17,18,mat);
  175.         return mesh.updateFaces();
  176.     }
  177.     
  178.     static public function icosahedron(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  179.         var a:Number=size*0.276393202, b:Number=size*0.447213595, c:Number=size*0.525731112
  180.             d:Number=size*0.723606798, e:Number=size*0.850650808;
  181.         mesh.vertices.push(0,size,00,b,b+b, e,b,a, c,b,-d, -c,b,-d, -e,b,a);
  182.         mesh.vertices.push(e,-b,-a, c,-b,d, -c,-b,d, -e,-b,-a, 0,-b,-b-b, 0,-size,0);
  183.         mesh.qface(0,2,1,7,mat).qface(0,3,2,6,mat).qface(0,4,3,10,mat).qface(0,5,4,9,mat).qface(0,1,5,8,mat);
  184.         mesh.qface(1,7,8,11,mat).qface(2,6,7,11,mat).qface(3,10,6,11,mat).qface(4,9,10,11,mat).qface(5,8,9,11,mat);
  185.         return mesh.updateFaces();
  186.     }
  187.     
  188.     static public function sphere(mesh:Mesh, size:Number, mat:int=0) : Mesh {
  189.         return icosahedron(mesh, size, mat);
  190.     }
  191. }
  192. // Structure Synth
  193. //----------------------------------------------------------------------------------------------------
  194. class StructureSynth {
  195.     private var _mesh:Mesh;
  196.     private var _functions:* = new Object(), _meshes:* = new Object();
  197.     private var _maxDepth:int, _depth:int;
  198.     private var _core:Render3D = new Render3D();
  199.     static private var _rexLine   :RegExp = /((\d+)[\s*]*)?\{(.*?)\}\s*|([^{}\s]+)\s*/g;
  200.     static private var _rexOperate:RegExp = /(r?[x-z]|s)\s*([\-\d.]+)\s*([\-\d.]+)?\s*([\-\d.]+)?/g;
  201.     
  202.     /** constructor. do nothing */
  203.     function StructureSynth() {}
  204.     
  205.     /** register mesh to call in CFDG.
  206.      *  @param name Mesh name to call.
  207.      *  @param mesh Mesh data.
  208.      */
  209.     public function mesh(name:String, mesh:Mesh) : StructureSynth {
  210.         _meshes[name] = new ProjectionMesh(mesh);
  211.         return this;
  212.     }
  213.     
  214.     /** register rule.
  215.      *  @param name Rule name to call.
  216.      *  @param func Function to execute. The type is "function() : void".
  217.      *  @param option Option["w"/"weight"] to set weight and the option["md"/"maxdepth"] to set maxdepth.
  218.      */
  219.     public function rule(name:String, func:Function, option:*=null) : StructureSynth {
  220.         if (!(name in _functions)) _functions[name] = new SSFunctionList();
  221.         _functions[name].rule(func, option||new Object());
  222.         return this;
  223.     }
  224.     
  225.     /** initialize to constructing structure */
  226.     public function init(mesh:Mesh, maxDepth:int=512) : StructureSynth {
  227.         for each (var func:SSFunctionList in _functions) func.init();
  228.         _maxDepth = maxDepth;
  229.         _depth = 0;
  230.         _mesh = mesh;
  231.         _core.id();
  232.         return this;
  233.     }
  234.     
  235.     /** command 1 line in CFDG. */
  236.     public function call(line:String) : StructureSynth {
  237.         var res:*, opeList:Array = [], i:int;
  238.         res = _rexLine.exec(line);
  239.         while (res) {
  240.             if (res[3]) opeList.unshift({imax:res[2]||1, mat:calcMatrix(res[3])});
  241.             else if (res[4]) opeList.unshift({imax:0, name:res[4]});
  242.             res = _rexLine.exec(line);
  243.         }
  244.         for (i=opeList.length-1; i>0; i--) i = _repeat(opeList, i);
  245.         return this;
  246.     }
  247.     
  248.     /** opreate matrix */
  249.     public function operate(ope:String) : StructureSynth {
  250.         var res:* = _rexOperate.exec(ope);
  251.         while(res) {
  252.             var n:Number = Number(res[2]);
  253.             switch (res[1]) {
  254.             case 'x':  _core.t(n,0,0); break;
  255.             case 'y':  _core.t(0,n,0); break;
  256.             case 'z':  _core.t(0,0,n); break;
  257.             case 'rx': _core.rx(n);    break;
  258.             case 'ry': _core.ry(n);    break;
  259.             case 'rz': _core.rz(n);    break;
  260.             case 's':
  261.                 if (res[3]) _core.s(n, Number(res[3]), Number(res[4]));
  262.                 else _core.s(n, n, n);
  263.                 break;
  264.             }
  265.             res = _rexOperate.exec(ope);
  266.         }
  267.         return this;
  268.     }
  269.     
  270.     /** calculate opreation matrix */
  271.     public function calcMatrix(ope:String) : Matrix3D {
  272.         _core.push().id();
  273.         operate(ope);
  274.         var mat:Matrix3D = _core.matrix;
  275.         _core.pop();
  276.         return mat;
  277.     }
  278.     
  279.     private function _repeat(opeList:Array, index:int) : int {
  280.         var imax:int = opeList[index].imax, lastIndex:int = index;
  281.         if (imax == 0) {
  282.             var name:String = opeList[index].name;
  283.             if (name in _functions) {
  284.                 if (++_depth <= _maxDepth) _functions[name].call();
  285.                 _depth--;
  286.             } else 
  287.             if (name in _meshes) {
  288.                 _core.project(_meshes[name]);
  289.                 _mesh.put(_meshes[name]);
  290.             }
  291.         } else {
  292.             var i:int, mat:Matrix3D=opeList[index].mat;
  293.             _core.push();
  294.             for (i=0; i<imax; i++) {
  295.                 _core.mult(mat);
  296.                 lastIndex = _repeat(opeList, index-1);
  297.             }
  298.             _core.pop();
  299.         }
  300.         return lastIndex;
  301.     }
  302. }
  303. class SSFunctionList {
  304.     private var _totalWeight:Number = 0;
  305.     private var _functions:Vector.<SSFunction> = new Vector.<SSFunction>();
  306.     
  307.     public function rule(func:Function, option:*) : void {
  308.         var ssf:SSFunction = new SSFunction(func, option);
  309.         _functions.push(ssf);
  310.         _totalWeight += ssf.weight;
  311.     }
  312.     public function init() : void {
  313.         for each (var ssf:SSFunction in _functions) ssf.depth = 0;
  314.     }
  315.     
  316.     public function call() : void {
  317.         var w:Number = 0, rand:Number = Math.random() * _totalWeight;
  318.         for each (var ssf:SSFunction in _functions) {
  319.             w += ssf.weight;
  320.             if (rand <= w) {
  321.                 if (++ssf.depth <= ssf.maxdepth) ssf.func();
  322.                 else ssf.finalFunc();
  323.                 ssf.depth--;
  324.                 return;
  325.             }
  326.         }
  327.     }
  328. }
  329. class SSFunction {
  330.     public var func:Function;
  331.     public var finalFunc:Function;
  332.     public var weight:Number;
  333.     public var maxdepth:int;
  334.     public var depth:int = 0;
  335.     
  336.     function SSFunction(func:Function, option:*) {
  337.         this.func = func;
  338.         this.weight = option["w"] || option["weight"] || 1;
  339.         this.maxdepth = option["md"] || option["maxdepth"] || int.MAX_VALUE;
  340.         this.finalFunc = option["ff"] || option["final"] || function():void{};
  341.     }
  342. }
  343. // 3D Engine
  344. //----------------------------------------------------------------------------------------------------
  345. /** Core */
  346. class Render3D extends Shape {
  347.     /** model view matrix */
  348.     public var matrix:Matrix3D;
  349.     private var _projectionMatrix:Matrix3D;                              // projection matrix
  350.     private var _matrixStac:Vector.<Matrix3D> = new Vector.<Matrix3D>(); // matrix stac
  351.     private var _cmdTriangle:Vector.<int> = Vector.<int>([1,2,2]);       // commands to draw triangle
  352.     private var _cmdQuadrangle:Vector.<int> = Vector.<int>([1,2,2,2]);   // commands to draw quadrangle
  353.     private var _data:Vector.<Number> = new Vector.<Number>(8true);    // data to draw shape
  354.     private var _clippingZ:Number;                                       // clipping z value
  355.     private var _depthMap:BitmapData = new BitmapData(256256false);  // texture for depth buffer rendering
  356.     
  357.     /** constructor */
  358.     function Render3D(focus:Number=300, clippingZ:Number=-0.1) {
  359.         var projector:PerspectiveProjection = new PerspectiveProjection()
  360.         projector.focalLength = focus;
  361.         _projectionMatrix = projector.toMatrix3D();
  362.         _clippingZ = -clippingZ;
  363.         matrix = new Matrix3D();
  364.         _matrixStac.length = 1;
  365.         _matrixStac[0] = matrix;
  366.         var u:int, v:int;
  367.         for (v=0; v<256; v++) 
  368.             for (u=0; u<256; u++) 
  369.                 //_depthMap.setPixel(255-u, 255-v, (v<<8)|u);
  370.                 _depthMap.setPixel(255-u, 255-v, (u<<16)|(u<<8)|u);
  371.     }
  372.     // control matrix
  373.     //--------------------------------------------------
  374.     public function clear() : Render3D { matrix = _matrixStac[0]; _matrixStac.length = 1return this; }
  375.     public function push() : Render3D { _matrixStac.push(matrix.clone()); return this; }
  376.     public function pop() : Render3D { matrix = (_matrixStac.length == 1) ? matrix : _matrixStac.pop(); return this; }
  377.     public function id() : Render3D { matrix.identity(); return this; }
  378.     public function t(x:Number, y:Number, z:Number) : Render3D { matrix.prependTranslation(x, y, z); return this; }
  379.     public function tv(v:Vector3D) : Render3D { matrix.prependTranslation(v.x, v.y, v.z); return this; }
  380.     public function s(x:Number, y:Number, z:Number) : Render3D { matrix.prependScale(x, y, z); return this; }
  381.     public function sv(v:Vector3D) : Render3D { matrix.prependScale(v.x, v.y, v.z); return this; }
  382.     public function r(angle:Number, axis:Vector3D) : Render3D { matrix.prependRotation(angle, axis); return this; }
  383.     public function rv(v:Vector3D) : Render3D { matrix.prependRotation(v.w, v); return this; }
  384.     public function rx(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.X_AXIS); return this; }
  385.     public function ry(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.Y_AXIS); return this; }
  386.     public function rz(angle:Number) : Render3D { matrix.prependRotation(angle, Vector3D.Z_AXIS); return this; }
  387.     public function mult(mat:Matrix3D) : Render3D { matrix.prepend(mat); return this; }
  388.     
  389.     // projections
  390.     //--------------------------------------------------
  391.     /** project */
  392.     public function project(mesh:ProjectionMesh) : Render3D {
  393.         matrix.transformVectors(mesh.base.vertices, mesh.verticesOnWorld);
  394.         var fn:Vector3D, fnw:Vector3D, vs:Vector.<Number> = mesh.verticesOnWorld,
  395.             nearZ:Number = -Number.MAX_VALUE, farZ:Number = _clippingZ,
  396.             flist:Vector.<Face> = mesh.base.faces;
  397.         var m:Vector.<Number> = matrix.rawData, 
  398.             m00:Number = m[0], m01:Number = m[1], m02:Number = m[2], 
  399.             m10:Number = m[4], m11:Number = m[5], m12:Number = m[6], 
  400.             m20:Number = m[8], m21:Number = m[9], m22:Number = m[10];
  401.         mesh.facesProjected.length = 0;
  402.         for each (var f:Face in flist) {
  403.             var i0:int=(f.i0<<1)+f.i0, i1:int=(f.i1<<1)+f.i1, i2:int=(f.i2<<1)+f.i2,
  404.                 x0:Number=vs[i0++], x1:Number=vs[i1++], x2:Number=vs[i2++],
  405.                 y0:Number=vs[i0++], y1:Number=vs[i1++], y2:Number=vs[i2++],
  406.                 z0:Number=vs[i0],   z1:Number=vs[i1],   z2:Number=vs[i2];
  407.             if (z0<_clippingZ && z1<_clippingZ && z2<_clippingZ) {
  408.                 fn  = f.normal;
  409.                 fnw = mesh.normalsProjected[f.index];
  410.                 fnw.x = fn.x * m00 + fn.y * m10 + fn.z * m20;
  411.                 fnw.y = fn.x * m01 + fn.y * m11 + fn.z * m21;
  412.                 fnw.z = fn.x * m02 + fn.y * m12 + fn.z * m22;
  413.                 if (vs[f.gpi-2]*fnw.x + vs[f.gpi-1]*fnw.y + vs[f.gpi]*fnw.z <= 0) {
  414.                     if (nearZ < z0) nearZ = z0;
  415.                     if (nearZ < z1) nearZ = z1;
  416.                     if (nearZ < z2) nearZ = z2;
  417.                     if (farZ  > z0) farZ  = z0;
  418.                     if (farZ  > z1) farZ  = z1;
  419.                     if (farZ  > z2) farZ  = z2;
  420.                     mesh.facesProjected.push(f);
  421.                 }
  422.             }
  423.         }
  424.         mesh.nearZ = nearZ;
  425.         mesh.farZ  = farZ;
  426.         mesh.facesProjected.sort(function(f1:Face, f2:Face):Numberreturn vs[f1.gpi] - vs[f2.gpi]; });
  427.         mesh.indexDirty = true;
  428.         return this;
  429.     }
  430.     
  431.     /** project slower than transformVectors() but Vector3D.w considerable. */
  432.     public function projectPoint3D(points:Vector.<Point3D>) : Render3D {
  433.         var m:Vector.<Number> = matrix.rawData, p:Point3D, 
  434.             m00:Number = m[0],  m01:Number = m[1],  m02:Number = m[2], 
  435.             m10:Number = m[4],  m11:Number = m[5],  m12:Number = m[6], 
  436.             m20:Number = m[8],  m21:Number = m[9],  m22:Number = m[10], 
  437.             m30:Number = m[12], m31:Number = m[13], m32:Number = m[14];
  438.         for each (p in points) {
  439.             p.world.x = p.x * m00 + p.y * m10 + p.z * m20 + p.w * m30;
  440.             p.world.y = p.x * m01 + p.y * m11 + p.z * m21 + p.w * m31;
  441.             p.world.z = p.x * m02 + p.y * m12 + p.z * m22 + p.w * m32;
  442.         }
  443.         return this;
  444.     }
  445.     // rendering
  446.     //--------------------------------------------------
  447.     /** render solid */
  448.     public function renderSolid(mesh:ProjectionMesh, light:Light) : Render3D {
  449.         var idx:int, mat:Material, materials:Vector.<Material> = mesh.base.materials,
  450.             vout:Vector.<Number> = mesh.verticesOnScreen;
  451.         Utils3D.projectVectors(_projectionMatrix, mesh.verticesOnWorld, vout, mesh.base.texCoord);
  452.         graphics.clear();
  453.         for each (var face:Face in mesh.facesProjected) {
  454.             mat = materials[face.mat];
  455.             graphics.beginFill(mat.getColor(light, mesh.normalsProjected[face.index]), mat.alpha);
  456.             idx = face.i0<<1;
  457.             _data[0] = vout[idx]; idx++;
  458.             _data[1] = vout[idx];
  459.             idx = face.i1<<1;
  460.             _data[2] = vout[idx]; idx++;
  461.             _data[3] = vout[idx];
  462.             idx = face.i2<<1;
  463.             _data[4] = vout[idx]; idx++;
  464.             _data[5] = vout[idx];
  465.             if (face.i3 == -1) {
  466.                 graphics.drawPath(_cmdTriangle, _data);
  467.             } else {
  468.                 idx = face.i3<<1;
  469.                 _data[6] = vout[idx]; idx++;
  470.                 _data[7] = vout[idx];
  471.                 graphics.drawPath(_cmdQuadrangle, _data);
  472.             }
  473.             graphics.endFill();
  474.         }
  475.         return this;
  476.     }
  477.     
  478.     /** render with texture */
  479.     public function renderTexture(mesh:ProjectionMesh, texture:BitmapData) : Render3D {
  480.         Utils3D.projectVectors(_projectionMatrix, 
  481.                                mesh.verticesOnWorld, 
  482.                                mesh.verticesOnScreen, 
  483.                                mesh.base.texCoord);
  484.         graphics.clear();
  485.         graphics.beginBitmapFill(texture, nullfalsetrue);
  486.         graphics.drawTriangles(mesh.verticesOnScreen, mesh.indicesProjected, mesh.base.texCoord);
  487.         graphics.endFill();
  488.         return this;
  489.     }
  490.     /** render depth buffer */
  491.     public function renderDepth(mesh:ProjectionMesh) : Render3D {
  492.         var i:int, imax:int = mesh.vertexImax, 
  493.             nearZ:Number = (_clippingZ < mesh.nearZ) ? _clippingZ : mesh.nearZ,
  494.             r:Number=1/(mesh.farZ - nearZ),
  495.             duvt:Vector.<Number> = _depthUVT;
  496.         duvt.length = 0;
  497.         for (i=2; i<imax; i+=3) duvt.push((mesh.verticesOnWorld[i]-nearZ)*r, 00);
  498.         Utils3D.projectVectors(_projectionMatrix, mesh.verticesOnWorld, mesh.verticesOnScreen, duvt);
  499.         graphics.clear();
  500.         graphics.beginBitmapFill(_depthMap, nullfalsetrue);
  501.         graphics.drawTriangles(mesh.verticesOnScreen, mesh.indicesProjected, duvt);
  502.         graphics.endFill();
  503.         return this;
  504.     }
  505.     private var _depthUVT:Vector.<Number> = new Vector.<Number>();
  506. }
  507. /** Point3D */
  508. class Point3D extends Vector3D {
  509.     public var world:Vector3D;
  510.     function Point3D(x:Number=0, y:Number=0, z:Number=0, w:Number=1) { super(x,y,z,w); world=clone(); }
  511. }
  512. /** Face */
  513. class Face {
  514.     public var index:int, i0:int, i1:int, i2:int, i3:int, gpi:int, mat:int, normal:Vector3D;
  515.     static private var _freeList:Vector.<Face> = new Vector.<Face>();
  516.     static public function free(face:Face) : void { _freeList.push(face); }
  517.     static public function alloc(index:int, i0:int, i1:int, i2:int, i3:int, mat:int) : Face { 
  518.         var f:Face = _freeList.pop() || new Face();
  519.         f.index=index; f.i0=i0; f.i1=i1; f.i2=i2; f.i3=i3; f.gpi=0; f.mat=mat;
  520.         return f;
  521.     }
  522. }
  523. /** Mesh */
  524. class Mesh {
  525.     public var materials:Vector.<Material>;                 // material list
  526.     public var vertices:Vector.<Number>;                    // vertex
  527.     public var verticesCount:int;                           // vertex count
  528.     public var texCoord:Vector.<Number>;                    // texture coordinate
  529.     public var faces:Vector.<Face> = new Vector.<Face>();   // face list
  530.     
  531.     /** constructor */
  532.     function Mesh(materials:Vector.<Material>=null) {
  533.         this.materials = materials;
  534.         this.vertices = new Vector.<Number>();
  535.         this.texCoord = new Vector.<Number>();
  536.         this.verticesCount = 0;
  537.     }
  538.     
  539.     /** clear all faces */
  540.     public function clear() : Mesh {
  541.         for each (var face:Face in faces) Face.free(face);
  542.         faces.length = 0;
  543.         return this;
  544.     }
  545.     
  546.     /** register face */
  547.     public function face(i0:int, i1:int, i2:int, mat:int=0) : Mesh {
  548.         faces.push(Face.alloc(faces.length, i0, i1, i2, -1, mat));
  549.         return this;
  550.     }
  551.     
  552.     /** register quadrangle face. set div=true to divide into 2 triangles. */
  553.     public function qface(i0:int, i1:int, i2:int, i3:int, mat:int=0, div:Boolean=true) : Mesh {
  554.         if (div) {
  555.             faces.push(Face.alloc(faces.length,   i0, i1, i2, -1, mat), 
  556.                        Face.alloc(faces.length+1, i3, i2, i1, -1, mat));
  557.         }
  558.         else faces.push(Face.alloc(faces.length, i0, i1, i3, i2, mat));
  559.         return this;
  560.     }
  561.     
  562.     /** put mesh on world coordinate. */
  563.     public function put(src:ProjectionMesh, mat:int=-1) : Mesh {
  564.         var i0:int=vertices.length, imax:int=src.vertexImax, flist:Vector.<Face>=src.base.faces;
  565.         vertices.length += imax;
  566.         for (var i:int=0; i<imax; i++) vertices[i0+i] = src.verticesOnWorld[i];
  567.         i0 /= 3;
  568.         for each (var f:Face in flist) {
  569.             i = (mat == -1) ? f.mat : mat;
  570.             if (f.i3==-1) face (f.i0+i0, f.i1+i0, f.i2+i0, i);
  571.             else          qface(f.i0+i0, f.i1+i0, f.i3+i0, f.i2+i0, i, false);
  572.         }
  573.         return this;
  574.     }
  575.     
  576.     /** update face gravity point and normal */
  577.     public function updateFaces() : Mesh {
  578.         verticesCount = vertices.length/3;
  579.         var vs:Vector.<Number> = vertices;
  580.         for each (var f:Face in faces) {
  581.             f.gpi = vs.length+2;
  582.             var i0:int=(f.i0<<1)+f.i0, i1:int=(f.i1<<1)+f.i1, i2:int=(f.i2<<1)+f.i2;
  583.             var x01:Number=vs[i1]-vs[i0], x02:Number=vs[i2]-vs[i0];
  584.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  585.             var y01:Number=vs[i1]-vs[i0], y02:Number=vs[i2]-vs[i0];
  586.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  587.             var z01:Number=vs[i1]-vs[i0], z02:Number=vs[i2]-vs[i0];
  588.             vs.push((vs[i0++] + vs[i1++] + vs[i2++]) * 0.333333333333);
  589.             f.normal = new Point3D(y02*z01-y01*z02, z02*x01-z01*x02, x02*y01-x01*y02, 0);
  590.             f.normal.normalize();
  591.             if (f.i3 != -1) {
  592.                 var i3:int = (f.i3<<1)+f.i3;
  593.                 vs[f.gpi-2] = vs[f.gpi-2]*0.75 + vs[i3++]*0.25;
  594.                 vs[f.gpi-1] = vs[f.gpi-1]*0.75 + vs[i3++]*0.25;
  595.                 vs[f.gpi]   = vs[f.gpi]  *0.75 + vs[i3]  *0.25;
  596.             }
  597.         }
  598.         return this;
  599.     }
  600. }
  601. /** mesh for projection */
  602. class ProjectionMesh {
  603.     public var verticesOnWorld:Vector.<Number>;     // vertex on camera coordinate
  604.     public var verticesOnScreen:Vector.<Number>;    // vertex on screen
  605.     public var facesProjected:Vector.<Face>;        // projected face
  606.     public var normalsProjected:Vector.<Vector3D>;  // projected normals
  607.     public var vnormals:Vector.<Vector3D>;          // vertex normal
  608.     public var nearZ:Number, farZ:Number;           // z buffer range
  609.     private var _projectedFaceIndices:Vector.<int> = new Vector.<int>();
  610.     private var _base:Mesh;
  611.     
  612.     /** indices of projected faces */
  613.     public function get indicesProjected() : Vector.<int> {
  614.         var idx:Vector.<int> = _projectedFaceIndices;
  615.         if (idx.length == 0for each (var f:Face in facesProjected) idx.push(f.i0, f.i1, f.i2);
  616.         return idx;
  617.     }
  618.     
  619.     public function set indexDirty(b:Boolean) : void {
  620.         if (b) _projectedFaceIndices.length = 0;
  621.     }
  622.     public function get base() : Mesh { return _base; }
  623.     public function set base(m:Mesh) : void {
  624.         if (m && normalsProjected.length < m.faces.length) {
  625.             var i:int = normalsProjected.length, imax:int = m.faces.length;
  626.             normalsProjected.length = imax;
  627.             for (; i<imax; i++) normalsProjected[i] = new Vector3D();
  628.         }
  629.         _base = m;
  630.     }
  631.     
  632.     public function get vertexImax() : int { return (_base.verticesCount<<1) + _base.verticesCount; }
  633.     
  634.     /** constructor */
  635.     function ProjectionMesh(m:Mesh=null) {
  636.         this.verticesOnWorld = new Vector.<Number>();
  637.         this.verticesOnScreen = new Vector.<Number>();
  638.         this.facesProjected = new Vector.<Face>();
  639.         this.normalsProjected= new Vector.<Vector3D>();
  640.         this.vnormals = null;
  641.         this.base = m;
  642.     }
  643. }
  644. /** Light */
  645. class Light extends Point3D {
  646.     public var halfVector:Vector3D = new Vector3D();
  647.     
  648.     /** constructor (set position) */
  649.     function Light(x:Number=1, y:Number=1, z:Number=1) {
  650.         super(x, y, z, 0);
  651.         normalize();
  652.     }
  653.     /** projection */
  654.     public function transformBy(matrix:Matrix3D) : void {
  655.         world = matrix.deltaTransformVector(this);
  656.         halfVector.x = world.x;
  657.         halfVector.y = world.y;
  658.         halfVector.z = world.z + 1
  659.         halfVector.normalize();
  660.     }
  661. }
  662. /** Material */
  663. class Material extends BitmapData {
  664.     public var alpha:Number = 1;    // The alpha value is available for renderSolid()
  665.     public var doubleSided:int = 0// set doubleSided=-1 if double sided material
  666.     
  667.     /** constructor */
  668.     function Material(dif:int=128, spc:int=128) { super(dif, spc, false); }
  669.     
  670.     /** set color. */
  671.     public function setColor(col:uint, amb:int=64, dif:int=192, spc:int=0,  pow:Number=8) : Material {
  672.         fillRect(rect, col);
  673.         var lmap:LightMap = new LightMap(width, height);
  674.         draw(lmap.diffusion(amb, dif), nullnull"hardlight");
  675.         draw(lmap.specular (spc, pow), nullnull"add");
  676.         lmap.dispose();
  677.         return this;
  678.     }
  679.     
  680.     /** calculate color by light and normal vector. */
  681.     public function getColor(l:Light, n:Vector3D) : uint {
  682.         var dir:Vector3D = l.world, hv:Vector3D = l.halfVector;
  683.         var ln:int = int((dir.x * n.x + dir.y * n.y + dir.z * n.z) * (width-1)),
  684.             hn:int = int((hv.x  * n.x + hv.y  * n.y + hv.z  * n.z) * (height-1));
  685.         if (ln<0) ln = (-ln) & doubleSided;
  686.         if (hn<0) hn = (-hn) & doubleSided;
  687.         return getPixel(ln, hn);
  688.     }
  689. }
  690. class LightMap extends BitmapData {
  691.     function LightMap(dif:int, spc:int) { super(dif, spc, false); }
  692.     
  693.     public function diffusion(amb:int, dif:int) : BitmapData {
  694.         var col:int, rc:Rectangle = new Rectangle(001, height), ipk:Number = 1 / width;
  695.         for (rc.x=0; rc.x<width; rc.x+=1) {
  696.             col = ((rc.x * (dif - amb)) * ipk) + amb;
  697.             fillRect(rc, (col<<16)|(col<<8)|col);
  698.         }
  699.         return this;
  700.     }
  701.     
  702.     public function specular(spc:int, pow:Number) : BitmapData {
  703.         var col:int, rc:Rectangle = new Rectangle(00, width, 1),
  704.             mpk:Number = (pow + 2) * 0.15915494309189534, ipk:Number = 1 / height;
  705.         for (rc.y=0; rc.y<height; rc.y+=1) {
  706.             col = Math.pow(rc.y * ipk, pow) * spc * mpk;
  707.             if (col > 255) col = 255;
  708.             fillRect(rc, (col<<16)|(col<<8)|col);
  709.         }
  710.         return this;
  711.     }
  712. }
noswf
Get Adobe Flash Player