package { import flash.display.Graphics; public class Triangle { private var pointA:Point3D; private var pointB:Point3D; private var pointC:Point3D; private var color:uint; public var light:Light;//每个三角形增加一个光源Light public function Triangle(a:Point3D,b:Point3D,c:Point3D,color:uint) { pointA = a; pointB = b; pointC = c; this.color = color; } 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(); } //★★★根据光线得到动态调整后的颜色 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; } //根据光线得到的颜色调整因子(最难理解的的一个函数) 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的坐标值 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); //向量norm与向量light的点积(数量积) var dotProd:Number = norm.x * light.x + norm.y * light.y + norm.z * light.z; //向量norm的模长 var normMag:Number = Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z); //向量light的模长 var lightMag:Number = Math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z); //夹角angle var angle:Number = Math.acos(dotProd / (normMag * lightMag)); return (angle / Math.PI) * light.brightness; //夹角除取值范围最大值PI,将得到一个0到1之间的小数,然后再乘light的亮度值,即得到最终的光线调整因子 } //是否处于背面 private function isBackFace():Boolean { 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; } //z轴深度 public function get depth():Number { var zpos:Number = Math.min(pointA.z,pointB.z); zpos = Math.min(zpos,pointC.z); return zpos; } } }