※現在、「wonderfl build flash online」求人コンテンツ制作に関してのアンケートを実施中です!みなさまのお力添えを頂いて、続々とアンケート結果が集まっていますが、まだまだ募集しております。ご協力のほど、どうぞよろしくお願いいたします!

wonderfl運営事務局
→アンケートページ(※ログインしてからお答えいただけるようになっています。)

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


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