package { import flash.display.Graphics; public class animation_ch17_Triangle { private var pointA:animation_ch17_Point3D; private var pointB:animation_ch17_Point3D; private var pointC:animation_ch17_Point3D; private var color:uint; public var light:animation_ch17_Light; public function animation_ch17_Triangle(a:animation_ch17_Point3D, b:animation_ch17_Point3D, c:animation_ch17_Point3D, color:uint) { pointA = a; pointB = b; pointC = c; this.color = color; } //@ draw public function draw(g:Graphics):void { if(isBackFace()) { return; } g.beginFill(getAdjustedColor()); g.moveTo(pointA.screenX, pointA.screenY); g.lineTo(pointB.screenX, pointB.screenY); g.lineTo(pointC.screenX, pointC.screenY); g.lineTo(pointA.screenX, pointA.screenY); g.endFill(); } //@ color(s) private function getAdjustedColor():uint { var red:Number = color >> 16; var green:Number = color >> 8 & 0xff; var blue:Number =color & 0xff; var lightFactor:Number = getLightFactor(); red *= lightFactor; green *= lightFactor; blue *= lightFactor; return red << 16 | green << 8 | blue; } //@ light(s) private function getLightFactor():Number { var ab:Object = new Object(); ab.x = pointA.x - pointB.x; ab.y = pointA.y - pointB.y; ab.z = pointA.z - pointB.z; var bc:Object = new Object(); bc.x = pointB.x - pointC.x; bc.y = pointB.y - pointC.y; bc.z = pointB.z - pointC.z; var norm:Object = new Object(); norm.x = (ab.y * bc.z) - (ab.z * bc.y); norm.y = -((ab.x * bc.z) - (ab.z * bc.x)); norm.z = (ab.x * bc.y) - (ab.y * bc.x); var dotProd:Number = norm.x * light.x + norm.y * light.y + norm.z * light.z; var normMag:Number = Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z); var lightMag:Number = Math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z); return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * light.brightness; } //@ face(s) private function isBackFace():Boolean { // see http://www.jurjans.lv/flash/shape.html var cax:Number = pointC.screenX - pointA.screenX; var cay:Number = pointC.screenY - pointA.screenY; var bcx:Number = pointB.screenX - pointC.screenX; var bcy:Number = pointB.screenY - pointC.screenY; return cax * bcy > cay * bcx; } //@ depth(s) public function get depth():Number { var zpos:Number = Math.min(pointA.z, pointB.z); zpos = Math.min(zpos, pointC.z); return zpos; } } }