// Flash3D engine // version 2.0 // 11/26/02 // originally developed and coded by Todd Yard // Please contact tyard@27Bobs.com with any questions. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ defaultGray = 0x999999; model = function(coor, type) { this.vertexlist = []; // holds all vertices this.vGroup = []; // holds groups of vertices this.type = type; this.makeFromMesh(coor); this.setRenderMode("solid"); // default renderMode is solid this.setLineStyle(1, 0, 100); // width of 1, alpha of 100 this.x = 0; this.y = 0; this.z = 0; return this; } // adds a vertex to the model (coor:coordinates) model.prototype.addVertex = function(coor) { this.vertexList.push({x:coor[0], y:coor[1], z:coor[2]}); } // adds an array of vertices to model (verts:multidimensional array) model.prototype.addVertices = function(verts) { for (var i = 0; i < verts.length; i++) { this.addVertex(verts[i]); } } // adds a new side to model given the vertices (vert:vertices array) model.prototype.assignSide = function(vert, fillColor, fillAlpha) { this.side.push({points:vert, fillColor:defaultGray, fillAlpha:100}); if (arguments.length > 1) { this.setFill(fillColor, fillAlpha, this.side.length - 1); } } // creates isolated group of vertices (id:name; verts:array of vertices) model.prototype.createVGroup = function(id, verts) { this.vGroup[id] = {points:verts}; } // returns a given side's fill color and alpha (side:which side) model.prototype.getFill = function(side) { if (arguments.length) { return [this.side[side].fillColor, this.side[side].fillAlpha]; } else { return [this.side[0].fillColor, this.side[0].fillAlpha]; } } // returns line width and alpha as array model.prototype.getLineStyle = function() { return [this.lineWidth, this.lineColor, this.lineAlpha]; } // returns current rendering style model.prototype.getRenderMode = function() { return this.renderMode; } // returns vertex list of model model.prototype.getVertexList = function() { return this.vertexList; } // makes new model based on primitive model.prototype.makeFromMesh = function(type) { for (var i = 0; i < type.verts.length; i++) { this.addVertex(type.verts[i]); } this.side = []; for (var i = 0; i < type.sides.length; i++) { this.side[i] = {}; this.side[i].points = type.sides[i].points; this.side[i].fillColor = type.sides[i].fillColor; this.side[i].fillAlpha = type.sides[i].fillAlpha; } } // assigns proper vertices to list model.prototype.makeVertList = function(set) { if (set != undefined) { var vertList = []; for (var i = 0; i < set.points.length; i++) { vertList.push(this.vertexList[set.points[i]]); } } else { var vertList = this.vertexList; } return vertList; } // translates model back to center model.prototype.removeTransform = function() { this.trans = this.transform(); this.translate(-this.trans[0], -this.trans[1], -this.trans[2]); } // rotates a model (xA,yA,zA:angles, world:whether to rotate around world center, set:group of vertices; sin,cos:angles precalculated) model.prototype.rotate = function(xA, yA, zA, world, set, sin, cos) { var toRad = Math.PI/180; if (sin == undefined) { // if angles weren't sent var rads = [xA*toRad, yA*toRad, zA*toRad]; var sin = [Math.sin(rads[0]), Math.sin(rads[1]), Math.sin(rads[2])]; var cos = [Math.cos(rads[0]), Math.cos(rads[1]), Math.cos(rads[2])]; } if (!world) { // translates model to world center before rotating this.removeTransform(); } else if (set == undefined) { if (xA) { var z = cos[0] * this.z - sin[0] * this.y; var y = cos[0] * this.y + sin[0] * this.z; this.z = z; this.y = y; } if (yA) { var x = cos[1] * this.x - sin[1] * this.z; var z = cos[1] * this.z + sin[1] * this.x; this.z = z; this.x = x; } if (zA) { var x = cos[2] * this.x - sin[2] * this.y; var y = cos[2] * this.y + sin[2] * this.x; this.y = y; this.x = x; } } var vertList = this.makeVertList(set); this.rotateVertices(vertList, xA, yA, zA, sin, cos); if (!world) { this.translate(this.trans[0], this.trans[1], this.trans[2]); } } // rotates the vertices (verts:which vertices; sin,cos: precalc'ed angles) model.prototype.rotateVertices = function(verts, xA, yA, zA, sin, cos) { var i = verts.length; while (i--) { var whichVert = verts[i]; if (xA) { var z = cos[0] * whichVert.z - sin[0] * whichVert.y; var y = cos[0] * whichVert.y + sin[0] * whichVert.z; whichVert.z = z; whichVert.y = y; } if (yA) { var x = cos[1] * whichVert.x - sin[1] * whichVert.z; var z = cos[1] * whichVert.z + sin[1] * whichVert.x; whichVert.z = z; whichVert.x = x; } if (zA) { var x = cos[2] * whichVert.x - sin[2] * whichVert.y; var y = cos[2] * whichVert.y + sin[2] * whichVert.x; whichVert.x = x; whichVert.y = y; } } } // scales a model proportionally (amt:percentage; set:which group of vertices) model.prototype.scale = function(amt, set) { this.removeTransform(); var vertList = this.makeVertList(set); var i = vertList.length; while (i--) { var whichVert = vertList[i]; if (typeof amt == "object") { var xAmt = amt[0]; var yAmt = amt[1]; var zAmt = amt[2]; } else { xAmt = yAmt = zAmt = amt; } whichVert.x *= xAmt; whichVert.y *= yAmt; whichVert.z *= zAmt; } this.transform(this.trans[0], this.trans[1], this.trans[2]); } // sets color of model or individual sides (col:color, alp:alpha, side:side#)-- if no side# sent, color is applied to all sides model.prototype.setFill = function(col, alp, side) { if (side != undefined) { this.side[side].fillColor = col; this.side[side].fillAlpha = alp; } else { for (var i = 0; i < this.side.length; i++) { this.side[i].fillColor = col; this.side[i].fillAlpha = alp; } } } // sets line width and alpha (size:lineWidth; col: lineColor; alp:lineAlpha) model.prototype.setLineStyle = function(size, col, alp) { this.lineWidth = size; this.lineColor = col; this.lineAlpha = alp; } // sets rendering style for model (mode:"wire", "solid", "wire2side") model.prototype.setRenderMode = function(mode) { this.culling = (mode != "wire2side"); // no culling (false) for "wire2side" this.renderMode = mode; } // sets coordinates for model (x,y,z:coordinates) model.prototype.transform = function(x, y, z) { if (arguments.length) { this.removeTransform(); this.translate(x, y, z); } return [this.x, this.y, this.z]; } // moves model specified distance (x,y,z:units; set:group of vertices) model.prototype.translate = function(x, y, z, set) { var vertList = this.makeVertList(set); if (set == undefined) { this.x += x; this.y += y; this.z += z; } var i = vertList.length; while (i--) { var whichVert = vertList[i]; whichVert.x += x; whichVert.y += y; whichVert.z += z; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ light = function(x, y, z, brightness) { this.x = x; this.y = y; this.z = z; this.brightness = brightness; this.calcMag(); } // distance from world center light.prototype.calcMag = function() { this.magnitude = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); } // returns brightness light.prototype.getBrightness = function(amt) { return this.brightness; } // rotates light (x,y,z:angles; sin,cos:precalculated angles) --perhaps abstract? light.prototype.rotate = function(x, y, z, sin, cos) { var toRad = Math.PI/180; if (sin == undefined) { // if angles weren't sent var rads = [x*toRad, y*toRad, z*toRad]; var sin = [Math.sin(rads[0]), Math.sin(rads[1]), Math.sin(rads[2])]; var cos = [Math.cos(rads[0]), Math.cos(rads[1]), Math.cos(rads[2])]; } if (x) { var z = cos[0] * this.z - sin[0] * this.y; var y = cos[0] * this.y + sin[0] * this.z; this.z = z; this.y = y; } if (y) { var x = cos[1] * this.x - sin[1] * this.z; var z = cos[1] * this.z + sin[1] * this.x; this.z = z; this.x = x; } if (z) { var x = cos[2] * this.x - sin[2] * this.y; var y = cos[2] * this.y + sin[2] * this.x; this.x = x; this.y = y; } } // sets light brightness (amt:0-100) light.prototype.setBrightness = function(amt) { this.brightness = amt; } // sets or gets absolute coordinates of light (x,y,z:coordinates) light.prototype.transform = function(x, y, z) { if (arguments.length) { this.x = x; this.y = y; this.z = z; } else { return [this.x, this.y, this.z]; } } // moves light (x,y,z:units) perhaps this needs abstraction as models use same thing? light.prototype.translate = function(x, y, z) { this.x += x; this.y += y; this.z += z; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Flash3D = function(xPos, yPos, depth) { this.setCoor([xPos, yPos]); // _x, _y of clip this.depth = depth; // holds reference for name this.par = eval(_target); // timeline calling this function this.par.createEmptyMovieClip("color" + this.depth, this.depth + 5000); // dummy clip to facilitate coloring this.colorChip = new Color(this.par["color" + this.depth]); // color object for dummy clip this.init(); this.lens = 500; // for perspective this.focalLength = 300; // depth of camera (z from center) this.model = {}; // holds reference for each model this.light = new light(-15000, -2000, 5000, 70); } // creates empty mc to hold drawing Flash3D.prototype.init = function() { this.par.createEmptyMovieClip("clip" + this.depth, this.depth); this.clip = this.par["clip" + this.depth]; this.clip._x = this.coordinates[0]; this.clip._y = this.coordinates[1]; } // determines if polygon faces viewer (x,y:arrays containing three vertices' x and y positions) Flash3D.prototype.backface = function(x, y) { var cax = x[2] - x[0]; var cay = y[2] - y[0]; var bcx = x[1] - x[2]; var bcy = y[1] - y[2]; return (cax * bcy - cay * bcx < 0); } // checks to see if side needs to be clipped at z plane (clip:array of Booleans; side:vertices; mod:which model) Flash3D.prototype.checkClip = function(clip, side, mod) { var clipPoints = []; for (var i = 0; i < clip.length; i++) { if (!clip[i]) { clipPoints.push({x:mod.vertexList[side[i]].x, y:mod.vertexList[side[i]].y, z:mod.vertexList[side[i]].z}); // this vertex is visible } else { var prevClip = i-1; if (prevClip < 0) { prevClip = clip.length-1 } var nextClip = i+1; if (nextClip == clip.length) { nextClip = 0 } if (clip[i] && !clip[prevClip]) { // clip edge between these two vertices clipPoints.push(this.clipEdge(mod.vertexList[side[i]], mod.vertexList[side[prevClip]])); } if (clip[i] && !clip[nextClip]) { // clip edge between these two vertices clipPoints.push(this.clipEdge(mod.vertexList[side[i]], mod.vertexList[side[nextClip]])); } } } return clipPoints; // returns amended array of vertices } // finds where edge intersects the z plane (v1,v2: vertices defining edge) Flash3D.prototype.clipEdge = function(v1,v2) { var k = (this.focalLength - v2.z)/(v1.z - v2.z); var x1 = v2.x + k*(v1.x - v2.x); var y1 = v2.y + k*(v1.y - v2.y); return {x:x1, y:y1, z:this.focalLength}; } // removes model from world (mod:model id) Flash3D.prototype.deleteModel = function(mod) { delete this.model[mod]; } // calculates angle of light in relation to angle of face (vertices:3 points on poly) Flash3D.prototype.factorLightAngle = function(vertices) { var U = [(vertices[0].x - vertices[1].x), (vertices[0].y - vertices[1].y), (vertices[0].z - vertices[1].z)]; var V = [(vertices[1].x - vertices[2].x), (vertices[1].y - vertices[2].y), (vertices[1].z - vertices[2].z)]; var p = [((U[1]*V[2]) - (U[2]*V[1])) , -((U[0]*V[2]) - (U[2]*V[0])), ((U[0]*V[1]) - (U[1]*V[0]))]; var magP = Math.sqrt((p[0]*p[0]) + (p[1]*p[1]) + (p[2]*p[2])); var dP = ((p[0] * this.light.x) + (p[1] * this.light.y) + (p[2] * this.light.z)); return (Math.acos(dP/(magP * this.light.magnitude))/Math.PI) * (this.light.brightness/100); } // fills side with color (mod:model; vertices:3D coordinates; fillColor:hex color; fillAlpha:alpha amount; vertices2D:converted coordinates) Flash3D.prototype.fillSide = function(mod, vertices, fillColor, fillAlpha, vertices2D) { if (!this.backface([vertices2D[0][0], vertices2D[1][0], vertices2D[2][0]], [vertices2D[0][1], vertices2D[1][1], vertices2D[2][1]]) || !mod.culling) { if (!this.light.frozen) { fillColor = this.getColor(vertices, fillColor) } this.clip.beginFill(fillColor, fillAlpha); this.clip.lineStyle(mod.lineWidth, mod.lineColor, mod.lineAlpha); this.clip.moveTo(vertices2D[0][0], vertices2D[0][1]); for (var i = 1; i < vertices2D.length; i++) { this.clip.lineTo(vertices2D[i][0], vertices2D[i][1]) } // this.clip.lineTo(vertices2D[0][0], vertices2D[0][1]) this.clip.endFill(); } } // freezes lighted color for each side to prevent further computation Flash3D.prototype.freezeLights = function() { for (var i in this.model) { var whichMod = this.model[i]; for (var j = 0; j < whichMod.side.length; j++) { var whichSide = whichMod.side[j]; var vertices = []; for (var k = 0; k < 3; k++) { var vertexNum = whichSide.points[k]; var whichVert = whichMod.vertexList[vertexNum]; vertices.push({x:whichVert.x, y:whichVert.y, z:whichVert.z}); } this.model[i].side[j].fillColor = this.getColor(vertices, whichSide.fillColor) } } this.light.frozen = true; } // finds proper color (considering light) for side (vertices:3 points on poly; fillColor:hex color) Flash3D.prototype.getColor = function(vertices, fillColor) { // colorChip is dummy clip to facilitate recoloring (would straight conversion of hex to RGB be quicker?) this.colorChip.setRGB(fillColor); var colorParams = this.colorChip.getTransform(); var lightFactor = this.factorLightAngle(vertices); colorParams.rb *= lightFactor; colorParams.gb *= lightFactor; colorParams.bb *= lightFactor; this.colorChip.setTransform(colorParams); // all to return RGB values altered by light factor return this.colorChip.getRGB(); } // returns screen coordinates Flash3D.prototype.getCoor = function() { return [this.coordinates[0], this.coordinates[1]]; } // returns camera distance from center Flash3D.prototype.getFocalLength = function() { return this.focalLength; } // returns lens value Flash3D.prototype.getLens = function() { return this.lens; } // turns a user-defined model into a primitive mesh (model:model name; id:primitive identifier) Flash3D.prototype.makePrimitive = function(model, id) { this.primitive[id] = {}; this.primitive[id].verts = []; this.primitive[id].sides = []; var verts = this.model[model].getVertexList(); for (var i = 0; i < verts.length; i++) { this.primitive[id].verts.push([verts[i].x, verts[i].y, verts[i].z]); } for (var i = 0; i < this.model[model].side.length; i++) { var points = []; for (var j = 0; j < this.model[model].side[i].points.length; j++) { points.push(this.model[model].side[i].points[j]); } this.primitive[id].sides.push({points:points, fillColor:defaultGray, fillAlpha:100}); } } // adds a new model to world (id:model identifier; type:model type) Flash3D.prototype.newModel = function(id, type) { if (this.primitive[type] == undefined) { this.model[id] = new model({verts:[],sides:[]}, type); } else { this.model[id] = new model(this.primitive[type], type); } return this.model[id]; } Flash3D.prototype.primitive = {}; Flash3D.prototype.primitive.cube = { verts:[[-50,-50,-50], [50,-50,-50], [50,50,-50], [-50,50,-50], [-50,-50,50], [50,-50,50], [50,50,50], [-50,50,50]], sides:[{points:[0,1,2,3], fillColor:defaultGray, fillAlpha:100}, {points:[0,3,7,4], fillColor:defaultGray, fillAlpha:100}, {points:[6,5,4,7], fillColor:defaultGray, fillAlpha:100}, {points:[1,5,6,2], fillColor:defaultGray, fillAlpha:100}, {points:[0,4,5,1], fillColor:defaultGray, fillAlpha:100}, {points:[7,3,2,6], fillColor:defaultGray, fillAlpha:100}], top:[4,0,1,5], bottom:[2,3,6,7], front:[4,5,6,7], back:[0,1,2,3], right:[1,2,5,6], left:[0,3,4,7] } Flash3D.prototype.primitive.plane = { verts:[[-50,-50,1],[50,-50,1],[50,50,1],[-50,50,1]], sides:[{points:[3,2,1,0], fillColor:defaultGray, fillAlpha:100}], top:[0,1], bottom:[2,3], right:[1,2], left:[0,3] } Flash3D.prototype.primitive.pyramid = { verts:[[-50,50,50], [-50,50,-50], [50,50,-50], [50,50,50], [0,-50,0]], sides:[{points:[0,1,2,3], fillColor:defaultGray, fillAlpha:100}, {points:[2,4,3], fillColor:defaultGray, fillAlpha:100}, {points:[3,4,0], fillColor:defaultGray, fillAlpha:100}, {points:[0,4,1], fillColor:defaultGray, fillAlpha:100}, {points:[4,2,1], fillColor:defaultGray, fillAlpha:100}], top:[4], bottom:[0,1,2,3], base:[0,1,2,3], front:[0,3], back:[1,2], right:[2,3], left:[0,1] } Flash3D.prototype.primitive.octahedron = { verts:[[-50,0,50], [-50,0,-50], [50,0,-50], [50,0,50], [0,-50,0], [0,50,0]], sides:[{points:[2,4,3], fillColor:defaultGray, fillAlpha:100}, {points:[3,4,0], fillColor:defaultGray, fillAlpha:100}, {points:[0,4,1], fillColor:defaultGray, fillAlpha:100}, {points:[4,2,1], fillColor:defaultGray, fillAlpha:100}, {points:[5,3,0], fillColor:defaultGray, fillAlpha:100}, {points:[5,0,1], fillColor:defaultGray, fillAlpha:100}, {points:[5,1,2], fillColor:defaultGray, fillAlpha:100}, {points:[5,2,3], fillColor:defaultGray, fillAlpha:100}], top:[4], base:[0,1,2,3], bottom:[5], front:[0,3], back:[1,2], right:[2,3], left:[0,1] } // duplicates a specified primitives so that transformations may be performed to one without affecting the other Flash3D.prototype.primitive.duplicate = function(newID, oldID) { this[newID] = {}; this[newID].verts = []; this[newID].sides = []; for (var i = 0; i < this[oldID].sides.length; i++) { this[newID].sides[i] = {}; for (var j in this[oldID].sides[i]) { this[newID].sides[i][j] = this[oldID].sides[i][j] } } for (var i = 0; i < this[oldID].verts.length; i++) { this[newID].verts[i] = []; for (var j = 0; j < this[oldID].verts[i].length; j++) { this[newID].verts[i][j] = this[oldID].verts[i][j] } } this[newID].back = this[oldID].back; this[newID].front = this[oldID].front; } // creates a new mesh resource to make models from (id:mesh name; verts:multidim array; sides:multidim array) Flash3D.prototype.primitive.newMesh = function(id, verts, sides) { this[id] = {verts:verts, sides:[]}; for (var i = 0; i < sides.length; i++) { this[id].sides.push({points:sides[i], fillColor:defaultGray, fillAlpha:100}); } } Flash3D.prototype.primitive.setHeight = function(prim, h) { for (var i = 0; i < this[prim].top.length; i++) { this[prim].verts[this[prim].top[i]][1] = -(h/2); } for (var i = 0; i < this[prim].bottom.length; i++) { this[prim].verts[this[prim].bottom[i]][1] = (h/2); } } Flash3D.prototype.primitive.setLength = function(prim, l) { for (var i = 0; i < this[prim].back.length; i++) { this[prim].verts[this[prim].back[i]][2] = -(l/2); } for (var i = 0; i < this[prim].front.length; i++) { this[prim].verts[this[prim].front[i]][2] = (l/2); } } Flash3D.prototype.primitive.setWidth = function(prim, w) { for (var i = 0; i < this[prim].left.length; i++) { this[prim].verts[this[prim].left[i]][0] = -(w/2); } for (var i = 0; i < this[prim].right.length; i++) { this[prim].verts[this[prim].right[i]][0] = (w/2); } } // called when world needs to be redrawn Flash3D.prototype.render = function() { this.reset(); var zPos = []; // holds z of each SIDE for (var i in this.model) { var whichMod = this.model[i]; for (var j = 0; j < whichMod.side.length; j++) { var zDepth = 0; // helps determine order for drawing sides var clip = []; // array index holds true if edge needs clipping var clipped = 0; // flag for (var k = 0; k < whichMod.side[j].points.length; k++) { var vertexNum = whichMod.side[j].points[k]; var whichVert = whichMod.vertexList[vertexNum]; zDepth += whichVert.z; clip.push(whichVert.z > this.focalLength); // true/false if (whichVert.z > this.focalLength) { clipped = 1; // edge needs clipping } } if (clipped) { clip = this.checkClip(clip, whichMod.side[j].points, whichMod); // creates new array of vertices with added points } else { clip = null; } zPos.push([zDepth, this.model[i], whichMod.side[j], clip]); // places z, model, and side in array } } zPos.sort(function(a, b) { return a[0]-b[0] }); // sorts array according to z // goes through each side sequentially for (var i = 0; i < zPos.length; i++) { var whichMod = zPos[i][1]; var whichSide = zPos[i][2]; var side = []; var vertices = []; // goes through all vertices in side if (zPos[i][3] != null) { var points = zPos[i][3]; //additional vertices because of clipping } else { var points = whichSide.points; } for (var k = 0; k < points.length; k++) { if (zPos[i][3] != null) { var whichVert = points[k]; } else { var vertexNum = points[k]; var whichVert = whichMod.vertexList[vertexNum]; } var vert = this.translate2D(whichVert); // converts 3D coordinates to 2D side.push(vert); var vert3D = {x:whichVert.x, y:whichVert.y, z:whichVert.z}; vertices.push(vert3D); } if (whichMod.renderMode == "wire" || whichMod.renderMode == "wire2side") { var fillAlpha = 0; } else { var fillAlpha = whichSide.fillAlpha; } this.fillSide(whichMod, vertices, whichSide.fillColor, fillAlpha, side); } } Flash3D.prototype.reset = function() { this.clip.clear(); } // rotates each model about world axis (x,y,z:angles) --ABSTRACT?? Flash3D.prototype.rotate = function(x, y, z) { this.rotX += x; this.rotY += y; this.rotZ += z; var rads = [x*Math.PI/180, y*Math.PI/180, z*Math.PI/180]; var sin = [Math.sin(rads[0]), Math.sin(rads[1]), Math.sin(rads[2])]; var cos = [Math.cos(rads[0]), Math.cos(rads[1]), Math.cos(rads[2])]; for (var i in this.model) { this.model[i].rotate(x, y, z, 1, undefined, sin, cos); } this.light.rotate(x, y, z, sin, cos); } // resets screen coordinates (coor:_x,_y) Flash3D.prototype.setCoor = function(coor) { this.coordinates = [coor[0], coor[1]]; } // sets camera distance (dis: z distance from center) Flash3D.prototype.setFocalLength = function(dis) { this.focalLength = dis; } // changes perspective (amt:amount) Flash3D.prototype.setLens = function(amt) { this.lens = amt; } Flash3D.prototype.transform = function() { return [this.x, this.y, this.z, this.rotX, this.rotY, this.rotZ]; } // translates all models (x,y,z:units) Flash3D.prototype.translate = function(x, y, z) { this.x += x; this.y += y; this.z += z; for (var i in this.model) { this.model[i].translate(x, y, z); } // this.light.translate(x, y, z); } // converts 3D points to 2D coordinates Flash3D.prototype.translate2D = function(coor) { var scale = 1/(1 - ((coor.z)/this.lens)); return [(coor.x) * scale, (coor.y) * scale]; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //___________FLASH3D methods______________ /* newModel(); freezeLights(); translate(); transform(); rotate(); getLens(); setLens(); render(); getCoor(); setCoor(); deleteModel(); makePrimitive(); reset(); setFocalLength(); getFocalLength() */ //___________primitive methods______________ /* newMesh(); setHeight(); setWidth(); setLength(); */ //___________Model methods______________ /* addVertex(); addVertices(); assignSide(); getVertexList(); createVGroup(); translate(); rotate(); transform(); scale(); getFill(); setFill(); getRenderMode(); setRenderMode(); getLineStyle(); setLineStyle(); */ //___________Light methods______________ /* translate(); rotate(); transform(); getBrightness(); setBrightness(); */