/* Copyright (c) 2011 EL-EMENT saharan * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation * files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, * modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package { import com.adobe.utils.*; import flash.display.*; import flash.display3D.*; import flash.display3D.textures.*; import flash.events.*; import flash.net.*; import flash.geom.*; import flash.ui.ContextMenu; [SWF(width = "480", height = "480", frameRate = "60")] public class Earth extends Sprite { private var gl:EGraphics; private var earth:EMesh; private var cloud:EMesh; private var c:uint; private var s1:EShader; private var s2:EShader; private var tz:Number; private var rx:Number; private var ry:Number; private var rvx:Number; private var rvy:Number; private var press:Boolean; private var pmouseX:Number; private var pmouseY:Number; [Embed(source="tex.jpg")] private var tex:Class; // 色マップ [Embed(source="nor.jpg")] private var nor:Class; // 法線マップ [Embed(source="spc.jpg")] private var spc:Class; // スペキュラマップ [Embed(source="cld.jpg")] private var cld:Class; // 雲マップ [Embed(source="lgt.jpg")] private var lgt:Class; // 夜景マップ public function Earth() { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null): void { removeEventListener(Event.ADDED_TO_STAGE, init); contextMenu = new ContextMenu(); contextMenu.hideBuiltInItems(); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:Event):void { press = true; }); stage.addEventListener(MouseEvent.MOUSE_UP, function(e:Event):void { press = false; }); tz = 50; rx = 0; ry = 0; rvx = 0; rvy = 0; pmouseX = 0; pmouseY = 0; // gl = new EGraphics(stage.stage3Ds[0], 480, 480, start); } private function createSphere(divV:uint, divH:uint, radius:Number):EMesh { // 球メッシュの作成 var mesh:EMesh = new EMesh(); var theta:Number; var phi:Number; var dTheta:Number = Math.PI * 2 / divV; var dPhi:Number = Math.PI / divH; var numVertices:uint = (divH + 1) * divV - (divV - 1) * 2; mesh.addVertex(0, radius, 0); phi = dPhi; for (var i:int = 1; i < divH; i++) { theta = Math.PI * 2; for (var j:int = 0; j < divV; j++) { var index:int = (i - 1) * divV + j + 1; mesh.addVertex(radius * Math.sin(phi) * Math.cos(theta), radius * Math.cos(phi), radius * Math.sin(phi) * Math.sin(theta)); theta -= dTheta; } phi += dPhi; } mesh.addVertex(0, -radius, 0); var invV:Number = 1 / divV; var invH:Number = 1 / divH; var u:Number = 0; var v:Number = 0; for (i = 0; i < divH; i++) { u = 0; for (j = 0; j < divV; j++) { if (i == 0) { mesh.addFace(0, (j + 1) % divV + 1, j + 1, u + invV * 0.5, v, u, v + invH, u + invV, v + invH); } else if (i == divH - 1) { mesh.addFace(numVertices - 1, (i - 1) * divV + j + 1, (i - 1) * divV + (j + 1) % divV + 1, u + invV * 0.5, v + invH, u + invV, v, u, v); } else { mesh.addFace((i - 1) * divV + j + 1, (i - 1) * divV + (j + 1) % divV + 1, i * divV + (j + 1) % divV + 1, u, v, u + invV, v, u + invV, v + invH); mesh.addFace((i - 1) * divV + j + 1, i * divV + (j + 1) % divV + 1, i * divV + j + 1, u, v, u + invV, v + invH, u, v + invH); } u += invV; } v += invH; } return mesh; } private function start():void { s1 = new EShader(vertexShaderCode, fragmentShaderEarth, gl.context3D); s2 = new EShader(vertexShaderCode, fragmentShaderCloud, gl.context3D); earth = createSphere(64, 32, 2); earth.initVertexBuffer(gl); earth.initIndexBuffer(gl); earth.calcNormals(); earth.updateBuffers(); cloud = createSphere(64, 32, 2.05); cloud.initVertexBuffer(gl); cloud.initIndexBuffer(gl); cloud.calcNormals(); cloud.updateBuffers(); var tex:Texture = gl.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, true); tex.uploadFromBitmapData(new this.tex().bitmapData); gl.context3D.setTextureAt(0, tex); tex = gl.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, true); tex.uploadFromBitmapData(new nor().bitmapData); gl.context3D.setTextureAt(1, tex); tex = gl.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, true); tex.uploadFromBitmapData(new spc().bitmapData); gl.context3D.setTextureAt(2, tex); tex = gl.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, true); tex.uploadFromBitmapData(new cld().bitmapData); gl.context3D.setTextureAt(3, tex); tex = gl.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, true); tex.uploadFromBitmapData(new lgt().bitmapData); gl.context3D.setTextureAt(4, tex); var prj:PerspectiveMatrix3D = new PerspectiveMatrix3D(); prj.perspectiveFieldOfViewRH(60 * Math.PI / 180, 1, 0.01, 100); gl.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 4, prj, true); addEventListener(Event.ENTER_FRAME, frame); } private function frame(e:Event = null): void { c++; tz += (5 - tz) * 0.03125; if (press) { rvx += (mouseY - pmouseY) * 0.0625; rvy += (mouseX - pmouseX) * 0.0625; } pmouseX = mouseX; pmouseY = mouseY; rvx *= 0.9; rvy *= 0.9; rx += rvx; ry += rvy; if (rx > 90) rx += (90 - rx) * 0.5; if (rx < -90) rx += (-90 - rx) * 0.5; var mdl:Matrix3D = new Matrix3D(); mdl.prependTranslation(0, 0, -tz); mdl.prependRotation(rx, Vector3D.X_AXIS); mdl.prependRotation(ry, Vector3D.Y_AXIS); // 座標変換 var lightVec:Vector3D = new Vector3D(Math.cos(c / 500 - 2), 0, Math.sin(c / 500 - 2)); lightVec = mdl.deltaTransformVector(lightVec); // 光源の向きを回転させる gl.context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.([lightVec.x, lightVec.y, lightVec.z, 1])); gl.beginScene(0, 0, 0); gl.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mdl, true); gl.setShader(s1); gl.renderMesh(earth); // 地球の描画 mdl.prependRotation(-c / 30, Vector3D.Y_AXIS); gl.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mdl, true); gl.setShader(s2); gl.renderMesh(cloud); // 雲の描画 gl.endScene(); } } } var vertexShaderCode:String = ; var fragmentShaderEarth:String = ; mov ft0, v1; // normal mov ft1, v3; // tangent mov ft2, v4; // binormal nrm ft0.xyz, ft0.xyz; nrm ft1.xyz, ft1.xyz; nrm ft2.xyz, ft2.xyz; tex ft3, v2, fs1, <2d, linear, repeat>; // normal map sub ft3.xyz, ft3.xyz, fc8.yyy; mul ft3.xyz, ft3.xyz, fc8.www; // bumpmap normal mov ft4.xyz, fc8.xxx; mul ft5.x, ft1.x, ft3.x; mul ft5.y, ft2.x, ft3.y; mul ft5.z, ft0.x, ft3.z; add ft4.x, ft5.x, ft5.y; add ft4.x, ft4.x, ft5.z; mul ft5.x, ft1.y, ft3.x; mul ft5.y, ft2.y, ft3.y; mul ft5.z, ft0.y, ft3.z; add ft4.y, ft5.x, ft5.y; add ft4.y, ft4.y, ft5.z; mul ft5.x, ft1.z, ft3.x; mul ft5.y, ft2.z, ft3.y; mul ft5.z, ft0.z, ft3.z; add ft4.z, ft5.x, ft5.y; add ft4.z, ft4.z, ft5.z; nrm ft4.xyz, ft4.xyz; mov ft1.xyz, fc0.xyz; // light vector mul ft1.xyz, ft1.xyz, fc9.xxx; nrm ft1.xyz, ft1.xyz; dp3 ft7.x, ft4.xyz, ft1.xyz; // calc brightness add ft7.x, ft7.x, fc10.w; sat ft7.x, ft7.x; mov ft2.xyz, v5.xyz; // calc view vector mul ft2.xyz, ft2.xyz, fc9.xxx; nrm ft2.xyz, ft2.xyz; mul ft1.xyz, ft1.xyz, fc9.xxx; // calc refrection vector dp3 ft3.x, ft1.xyz, ft4.xyz; mul ft3.x, ft3.x, fc8.w; mul ft3.xyz, ft4.xyz, ft3.xxx; sub ft3.xyz, ft1.xyz, ft3.xyz; nrm ft3.xyz, ft3.xyz; dp3 ft1.x, ft2.xyz, ft3.xyz; // calc specular sat ft1.x, ft1.x; pow ft7.y, ft1.x, fc9.y; mul ft7.y, ft7.y, fc8.y; tex ft6, v2, fs0, <2d, linear, repeat>; // color map mul ft4.xyz, ft6.xyz, ft7.xxx; // apply light tex ft6, v2, fs4, <2d, linear, repeat>; // night map sub ft7.x, fc8.z, ft7.x; pow ft7.x, ft7.x, fc9.y; mul ft6.xyz, ft6.xyz, ft7.xxx; add ft4.xyz, ft4.xyz, ft6.xyz; tex ft6, v2, fs2, <2d, linear, repeat>; // specular map mul ft7.y, ft7.y, ft6.x; // apply specular map add ft4.xyz, ft4.xyz, ft7.yyy; // add specular sat ft4.xyz, ft4.xyz; // clamp mov ft4.w, fc8.z; mov oc, ft4; ]]>; var fragmentShaderCloud:String = ; tex ft0, v2, fs1, <2d, nearest>; tex ft0, v2, fs2, <2d, nearest>; tex ft0, v2, fs4, <2d, nearest>; tex ft0, v2, fs3, <2d, linear, repeat>; // cloud map mov ft1.xyz, fc0.xyz; mul ft1.xyz, ft1.xyz, fc9.xxx; nrm ft1.xyz, ft1.xyz; mov ft2.xyz, v1.xyz; nrm ft2.xyz, ft2.xyz; dp3 ft1.x, ft1.xyz, ft2.xyz; mov ft0.w, ft0.x; mov ft0.xyz, ft1.xxx; mov oc, ft0; ]]>; import flash.display.*; import flash.events.*; import flash.display3D.*; import flash.display3D.textures.*; import flash.geom.*; import flash.net.*; import flash.system.*; import com.adobe.utils.*; import flash.utils.*; class EGraphics { public static const OFFSET_VERTEX:uint = 0; public static const OFFSET_NORMAL:uint = 3; public static const OFFSET_COLOR:uint = 6; public static const OFFSET_UV:uint = 10; public static const OFFSET_TANGENT:uint = 12; public static const OFFSET_TMP:uint = 15; public static const NUM_DATAS_IN_VERTEX:uint = 18; // private var s3d:Stage3D; private var c3d:Context3D; private var p3d:Program3D; private var callback:Function; private var width:int; private var height:int; // private var modelview:Matrix3D; private var projection:Matrix3D; public function EGraphics(s3d:Stage3D, width:int, height:int, callback:Function) { this.s3d = s3d; this.width = width; this.height = height; this.callback = callback; s3d.addEventListener(Event.CONTEXT3D_CREATE, init); s3d.requestContext3D(Context3DRenderMode.AUTO); } private function init(e:Event):void { c3d = s3d.context3D; c3d.enableErrorChecking = true; c3d.configureBackBuffer(width, height, 0, true); c3d.setBlendFactors(Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA); c3d.setCulling(Context3DTriangleFace.BACK); p3d = c3d.createProgram(); c3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 8, Vector.([0, 0.5, 1, 2])); c3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 9, Vector.([-1, 8, 16, 32])); c3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 10, Vector.([0.03125, 0.0625, 0.125, 0.25])); c3d.setProgram(p3d); callback(); } public function setShader(shader:EShader):void { c3d.setProgram(shader.program3D); } public function renderMesh(mesh:EMesh):void { var vtxbuf:VertexBuffer3D = mesh.vertexBuffer; c3d.setVertexBufferAt(0, vtxbuf, OFFSET_VERTEX, Context3DVertexBufferFormat.FLOAT_3); c3d.setVertexBufferAt(1, vtxbuf, OFFSET_COLOR, Context3DVertexBufferFormat.FLOAT_4); c3d.setVertexBufferAt(2, vtxbuf, OFFSET_NORMAL, Context3DVertexBufferFormat.FLOAT_3); c3d.setVertexBufferAt(3, vtxbuf, OFFSET_UV, Context3DVertexBufferFormat.FLOAT_2); c3d.setVertexBufferAt(4, vtxbuf, OFFSET_TANGENT, Context3DVertexBufferFormat.FLOAT_3); vtxbuf.uploadFromVector(mesh.vertices, 0, mesh.numVertices); var idxbuf:IndexBuffer3D = mesh.indexBuffer; idxbuf.uploadFromVector(mesh.indices, 0, mesh.numIndices); c3d.drawTriangles(idxbuf); } public function createVertexBuffer(numVertices:uint):VertexBuffer3D { return c3d.createVertexBuffer(numVertices, NUM_DATAS_IN_VERTEX); } public function createIndexBuffer(numIndices:uint):IndexBuffer3D { return c3d.createIndexBuffer(numIndices); } public function beginScene(r:Number = 0, g:Number = 0, b:Number = 0):void { c3d.clear(r, g, b, 1); } public function endScene():void { c3d.present(); } public function get stage3D():Stage3D { return s3d; } public function get context3D():Context3D { return c3d; } public function get program3D():Program3D { return p3d; } } class EMesh { private var vertex:Vector.; private var face:Vector.; private var normal:Vector.>; private var color:Vector.>; private var uv:Vector.>; private var tangent:Vector.>; private var vts:Vector.; private var ids:Vector.; // private var vtxbuf:VertexBuffer3D; private var idxbuf:IndexBuffer3D; // private var numvtx:uint; private var numfce:uint; public function EMesh() { vts = new Vector.(); ids = new Vector.(); // vertex = new Vector.(); face = new Vector.(); normal = new Vector.>(); color = new Vector.>(); uv = new Vector.>(); tangent = new Vector.>(); // vtxbuf = null; idxbuf = null; // numvtx = 0; numfce = 0; } public function addVertex(x:Number, y:Number, z:Number):void { var idx:uint = numvtx * 3; vertex[idx++] = x; vertex[idx++] = y; vertex[idx++] = z; numvtx++; } public function addFace(i1:uint, i2:uint, i3:uint, u1:Number = 0, v1:Number = 0, u2:Number = 0, v2:Number = 0, u3:Number = 0, v3:Number = 0, c1:uint = 0xffffffff, c2:uint = 0xffffffff, c3:uint = 0xffffffff):void { var idx:uint = numfce * 3; face[idx++] = i1; face[idx++] = i2; face[idx++] = i3; normal[numfce] = new Vector.(9, true); tangent[numfce] = new Vector.(9, true); uv[numfce] = new Vector.(6, true); uv[numfce][0] = u1; uv[numfce][1] = v1; uv[numfce][2] = u2; uv[numfce][3] = v2; uv[numfce][4] = u3; uv[numfce][5] = v3; color[numfce] = new Vector.(12, true); color[numfce][0] = c1 >>> 24 & 0xff; color[numfce][1] = c1 >> 16 & 0xff; color[numfce][2] = c1 >> 8 & 0xff; color[numfce][3] = c1 & 0xff; color[numfce][4] = c2 >>> 24 & 0xff; color[numfce][5] = c2 >> 16 & 0xff; color[numfce][6] = c2 >> 8 & 0xff; color[numfce][7] = c2 & 0xff; color[numfce][8] = c3 >>> 24 & 0xff; color[numfce][9] = c3 >> 16 & 0xff; color[numfce][10] = c3 >> 8 & 0xff; color[numfce][11] = c3 & 0xff; numfce++; } public function calcNormals():void { // 法線と接線の計算 var idx:uint = 0; var i:uint; var vtxnrm:Vector. = new Vector.(numvtx * 3, true); var vtxtan:Vector. = new Vector.(numvtx * 3, true); for (i = 0; i < numvtx; i++) { idx = i * 3; vtxnrm[idx] = 0; vtxnrm[idx + 1] = 0; vtxnrm[idx + 2] = 0; vtxtan[idx] = 0; vtxtan[idx + 1] = 0; vtxtan[idx + 2] = 0; } var n1:Number; var n2:Number; var n3:Number; var s1:Number; var s2:Number; var s3:Number; var t1:Number; var t2:Number; var t3:Number; idx = 0; for (i = 0; i < numfce; i++) { var i1:uint = face[idx]; var i2:uint = face[idx + 1]; var i3:uint = face[idx + 2]; var v1:uint = i1 * 3; var v2:uint = i2 * 3; var v3:uint = i3 * 3; // var x1:Number = vertex[v2] - vertex[v1]; var y1:Number = vertex[v2 + 1] - vertex[v1 + 1]; var z1:Number = vertex[v2 + 2] - vertex[v1 + 2]; var x2:Number = vertex[v3] - vertex[v1]; var y2:Number = vertex[v3 + 1] - vertex[v1 + 1]; var z2:Number = vertex[v3 + 2] - vertex[v1 + 2]; // v1 = i1 * 2; v2 = i2 * 2; v3 = i3 * 2; s1 = uv[i][2] - uv[i][0]; t1 = uv[i][3] - uv[i][1]; s2 = uv[i][4] - uv[i][0]; t2 = uv[i][5] - uv[i][1]; // var nx:Number = y2 * z1 - z2 * y1; var ny:Number = z2 * x1 - x2 * z1; var nz:Number = x2 * y1 - y2 * x1; var nl:Number = Math.sqrt(nx * nx + ny * ny + nz * nz); if (nl != 0) nl = 1 / nl; nx *= nl; ny *= nl; nz *= nl; // nl = s1 * t2 - t1 * s2; if (nl != 0) nl = 1 / nl; // var sx:Number; var sy:Number; var sz:Number; sx = (t2 * x1 - t1 * x2) * nl; sy = (t2 * y1 - t1 * y2) * nl; sz = (t2 * z1 - t1 * z2) * nl; // var tx:Number; var ty:Number; var tz:Number; tx = (s1 * x2 - s2 * x1) * nl; ty = (s1 * y2 - s2 * y1) * nl; tz = (s1 * z2 - s2 * z1) * nl; // var n:uint = i1 * 3; vtxnrm[n] += nx; vtxnrm[n + 1] += ny; vtxnrm[n + 2] += nz; vtxtan[n] += sx; vtxtan[n + 1] += sy; vtxtan[n + 2] += sz; n = i2 * 3; vtxnrm[n] += nx; vtxnrm[n + 1] += ny; vtxnrm[n + 2] += nz; vtxtan[n] += sx; vtxtan[n + 1] += sy; vtxtan[n + 2] += sz; n = i3 * 3; vtxnrm[n] += nx; vtxnrm[n + 1] += ny; vtxnrm[n + 2] += nz; vtxtan[n] += sx; vtxtan[n + 1] += sy; vtxtan[n + 2] += sz; idx += 3; } idx = 0; for (i = 0; i < numvtx; i++) { n1 = vtxnrm[idx]; n2 = vtxnrm[idx + 1]; n3 = vtxnrm[idx + 2]; s1 = vtxtan[idx]; s2 = vtxtan[idx + 1]; s3 = vtxtan[idx + 2]; var dot:Number = n1 * s1 + n2 * s2 + n3 * s3; vtxtan[idx] = s1 - n1 * dot; vtxtan[idx + 1] = s2 - n2 * dot; vtxtan[idx + 2] = s3 - n3 * dot; idx += 3; } for (i = 0; i < numfce; i++) { i1 = face[i * 3]; i2 = face[i * 3 + 1]; i3 = face[i * 3 + 2]; idx = i1 * 3; normal[i][0] = vtxnrm[idx]; normal[i][1] = vtxnrm[idx + 1]; normal[i][2] = vtxnrm[idx + 2]; tangent[i][0] = vtxtan[idx]; tangent[i][1] = vtxtan[idx + 1]; tangent[i][2] = vtxtan[idx + 2]; idx = i2 * 3; normal[i][3] = vtxnrm[idx]; normal[i][4] = vtxnrm[idx + 1]; normal[i][5] = vtxnrm[idx + 2]; tangent[i][3] = vtxtan[idx]; tangent[i][4] = vtxtan[idx + 1]; tangent[i][5] = vtxtan[idx + 2]; idx = i3 * 3; normal[i][6] = vtxnrm[idx]; normal[i][7] = vtxnrm[idx + 1]; normal[i][8] = vtxnrm[idx + 2]; tangent[i][6] = vtxtan[idx]; tangent[i][7] = vtxtan[idx + 1]; tangent[i][8] = vtxtan[idx + 2]; } } public function updateBuffers():void { // 頂点とインデックスバッファの更新 const numDatasInVertex:uint = EGraphics.NUM_DATAS_IN_VERTEX; const offsetVertex:uint = EGraphics.OFFSET_VERTEX; const offsetNormal:uint = EGraphics.OFFSET_NORMAL; const offsetColor:uint = EGraphics.OFFSET_COLOR; const offsetUV:uint = EGraphics.OFFSET_UV; const offsetTangent:uint = EGraphics.OFFSET_TANGENT; const vertex:Vector. = this.vertex; const face:Vector. = this.face; const normal:Vector.> = this.normal; const color:Vector.> = this.color; const uv:Vector.> = this.uv; const tangent:Vector.> = this.tangent; var idx:uint; var vc:uint = 0; var fidx:uint = 0; for (var i:uint = 0; i < numfce; i++) { var end:uint = vc + numDatasInVertex * 3; for (var j:uint = vc; j < end; j++) vts[j] = 0; const i1:uint = face[fidx] * 3; const i2:uint = face[fidx + 1] * 3; const i3:uint = face[fidx + 2] * 3; idx = vc + offsetVertex; vts[idx++] = vertex[i1]; vts[idx++] = vertex[i1 + 1]; vts[idx++] = vertex[i1 + 2]; idx = vc + offsetNormal; vts[idx++] = normal[i][0]; vts[idx++] = normal[i][1]; vts[idx++] = normal[i][2]; idx = vc + offsetColor; vts[idx++] = color[i][0]; vts[idx++] = color[i][1]; vts[idx++] = color[i][2]; vts[idx++] = color[i][3]; idx = vc + offsetUV; vts[idx++] = uv[i][0]; vts[idx++] = uv[i][1]; idx = vc + offsetTangent; vts[idx++] = tangent[i][0]; vts[idx++] = tangent[i][1]; vts[idx++] = tangent[i][2]; vc += numDatasInVertex; // idx = vc + offsetVertex; vts[idx++] = vertex[i2]; vts[idx++] = vertex[i2 + 1]; vts[idx++] = vertex[i2 + 2]; idx = vc + offsetNormal; vts[idx++] = normal[i][3]; vts[idx++] = normal[i][4]; vts[idx++] = normal[i][5]; idx = vc + offsetColor; vts[idx++] = color[i][4]; vts[idx++] = color[i][5]; vts[idx++] = color[i][6]; vts[idx++] = color[i][7]; idx = vc + offsetUV; vts[idx++] = uv[i][2]; vts[idx++] = uv[i][3]; idx = vc + offsetTangent; vts[idx++] = tangent[i][3]; vts[idx++] = tangent[i][4]; vts[idx++] = tangent[i][5]; vc += numDatasInVertex; // idx = vc + offsetVertex; vts[idx++] = vertex[i3]; vts[idx++] = vertex[i3 + 1]; vts[idx++] = vertex[i3 + 2]; idx = vc + offsetNormal; vts[idx++] = normal[i][6]; vts[idx++] = normal[i][7]; vts[idx++] = normal[i][8]; idx = vc + offsetColor; vts[idx++] = color[i][8]; vts[idx++] = color[i][9]; vts[idx++] = color[i][10]; vts[idx++] = color[i][11]; idx = vc + offsetUV; vts[idx++] = uv[i][4]; vts[idx++] = uv[i][5]; idx = vc + offsetTangent; vts[idx++] = tangent[i][6]; vts[idx++] = tangent[i][7]; vts[idx++] = tangent[i][8]; vc += numDatasInVertex; ids[fidx] = fidx++; ids[fidx] = fidx++; ids[fidx] = fidx++; } } public function initVertexBuffer(g:EGraphics):void { vtxbuf = g.createVertexBuffer(numfce * 3); } public function initIndexBuffer(g:EGraphics):void { idxbuf = g.createIndexBuffer(numfce * 3); } public function get numVertices():uint { return numfce * 3; } public function get numIndices():uint { return numfce * 3; } public function get vertices():Vector. { return vts; } public function get indices():Vector. { return ids; } public function get vertexBuffer():VertexBuffer3D { return vtxbuf; } public function get indexBuffer():IndexBuffer3D { return idxbuf; } } class EShader { private var vtxcode:ByteArray; private var frgcode:ByteArray; private var p3d:Program3D; public function EShader(vertex:String, fragment:String, c3d:Context3D) { var agal:AGALMiniAssembler = new AGALMiniAssembler(); agal.assemble(Context3DProgramType.VERTEX, vertex); vtxcode = agal.agalcode; agal.assemble(Context3DProgramType.FRAGMENT, fragment); frgcode = agal.agalcode; p3d = c3d.createProgram(); p3d.upload(vtxcode, frgcode); } public function get vertexShader():ByteArray { return vtxcode; } public function get fragmentShader():ByteArray { return frgcode; } public function get program3D():Program3D { return p3d; } }