3Д свет для флеш граней.


Класс для трехмерных расчетов
package  lex
{
	import flash.geom.*;
	import __AS3__.vec.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;
	
	/**
	 * ...
	 * @author http://www.murmadillo.tut.su/
	 */
	public class Lex3D 
	{
		private var matrix:Matrix, bd:BitmapData,rect:Rectangle;
		public function Lex3D() 
		{
			bd = new BitmapData(1, 1, true, 0x00000000);
			matrix = new Matrix;
			rect = new Rectangle(0, 0, 1, 1);
		}




		public function calcNormal(myNum:Vector.<uint> , vec3D:Vector.<Vector3D> ):Vector3D {
			var _v1:Vector3D, _v2:Vector3D, _v3:Vector3D;
			_v1 = vec3D[myNum[0]];
			_v2 = vec3D[myNum[1]];
			_v3 = vec3D[myNum[2]];
			var v:Vector3D = new Vector3D(
			(_v2.y - _v1.y) * (_v3.z - _v1.z) - (_v3.y - _v1.y) * (_v2.z - _v1.z),
			(_v2.x - _v1.x) * (_v3.z - _v1.z) - (_v3.x - _v1.x) * (_v2.z - _v1.z),
			(_v2.x - _v1.x) * (_v3.y - _v1.y) - (_v3.x - _v1.x) * (_v2.y - _v1.y));
			return v;
		}

		public function calcZ(myNum:Vector.<uint> , vec3D:Vector.<Vector3D> ):Number {
			var i:int, len:int, z:Number = 0;
			len = myNum.length;
			for (i = 0; i < len; i++) {
				z += vec3D[myNum[i]].z;
				//trace(vec3D[myNum[i]].z);
			}
			z = z / len;
			return z;
		}

		public function calcLigth(_k:Number, maxColor:uint=0xffffff):uint {
			var rMax:uint = maxColor >> 16 & 0xFF;
			var gMax:uint = maxColor >> 8 & 0xFF;
			var bMax:uint = maxColor & 0xFF;
			
			var r:uint;
			var g:uint;
			var b:uint;
			r = rMax * _k;
			b = bMax * _k;
			g = gMax * _k;
			var color:uint = ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
			return color;
		}

	}
	
}

Документ класс
package
{
	import flash.display.*;
	import flash.events.*;
	import flash.filters.ColorMatrixFilter;
	import flash.text.*;


	import flash.geom.*;
	import __AS3__.vec.*;

	import lex.*;

	/**
	 * ...
	 * @author http://www.murmadillo.tut.su/
	 */
	public class DocLightCube extends MovieClip
	{
		private const objRad:uint = 100, focus:int = 1000;
		
		private var vertsVec:Vector.<Vector3D>,
		facesVec:Vector.<Vector.<uint>>,
		comVec:Vector.<int>,
		sp:Sprite, 
		vs:Sprite,
		pointSp:Sprite,
		mat3D:Matrix3D,
		fillSp:Sprite,
		rect:Rectangle,
		projV:Vector.<Vector3D>,
		toolPanel:ToolPanel,
		custRotTr:Boolean,
		rotatorMem:Vector3D,
		dragGeneralOb:Object,
		liCount:int,
		startColor:uint = 0xffffff,
		endColor:uint = 0x0,
		lex3D:Lex3D,
		iMax:ImportMax,
		matPr:Matrix3D,
		vecXY:Vector3D;
		public function DocLightCube() 
		{
			var i:int;
			lex3D = new Lex3D;
			vertsVec = new Vector.<Vector3D>();	
			facesVec = new Vector.<Vector.<uint>>();
			comVec = new Vector.<int>;
			projV = new Vector.<Vector3D>();
			comVec.push(1, 2, 2);
			iMax = new ImportMax;

			iMax.overloadVec(vertsVec);
			iMax.overloadNum(facesVec);


			addChild(fillSp = new Sprite);
			addChild(sp = new Sprite);
			sp.x = 275;
			sp.y = 200;
			addChild(pointSp = new Sprite);

			sp.rotationX = 60;
			addEventListener(Event.ENTER_FRAME, enterFramHandler);


			
			addChild(toolPanel = new ToolPanel)
			toolPanel.setDrag(this);
			toolPanel.addEventListener(LexEvent.TOOL, toolEventFunc);
			dragGeneralOb = new Object;
			rotatorMem = new Vector3D;
			matPr = new Matrix3D;
			matPr.prependRotation(1, new Vector3D(1, 0, 0));
			vecXY = new Vector3D;
			fillSp.x = 250;
			fillSp.y = 200;
			matPr.prependRotation(180, new Vector3D(1, 0, 0));
			sp.rotationX = 0;
			sp.rotationY = 360;
		}


			private function toolEventFunc(evt:LexEvent):void {
			var generalSp:Sprite = sp;
			if (evt.params.value == "color") {
				if (evt.params.type == 'start') startColor = evt.params.color;
				if (evt.params.type == 'end') endColor = evt.params.color;
			}
			if (evt.params.value == "screen") {
				if (evt.params.rotation == 'screenUp') {
					generalSp.rotationX = 360;
					generalSp.rotationY = 0;
					generalSp.rotationZ = 0;
					custRotTr = false;
				}
				if (evt.params.rotation == 'screenDefault') {
					generalSp.rotationX = 0;
					generalSp.rotationY = 360;
					generalSp.rotationZ = 0;
					custRotTr = false;
				}
				if (evt.params.rotation == 'screenCustom') {
					custRotTr = true;
					generalSp.rotationX = rotatorMem.x;
					generalSp.rotationY = rotatorMem.y;
					generalSp.rotationZ = rotatorMem.z;
				}
			}
			
			if (custRotTr == true) if (evt.params.value == "rotation") {
				if (evt.params.type=='x') rotatorMem.x = generalSp.rotationX = evt.params.ang;
				if (evt.params.type=='y') rotatorMem.y = generalSp.rotationY = evt.params.ang;
				if (evt.params.type=='z') rotatorMem.z = generalSp.rotationZ = evt.params.ang;
			}
			
			
			if (evt.params.value == "dragGeneral") {
				if (evt.params.dragGeneral == true) {
				stage.addEventListener(MouseEvent.MOUSE_DOWN, stageDragGeneral);
				stage.addEventListener(MouseEvent.MOUSE_MOVE, stageDragGeneral);
				stage.addEventListener(MouseEvent.MOUSE_UP, stageDragGeneral);
				}
				if (evt.params.dragGeneral == false) {
					if (stage.hasEventListener(MouseEvent.MOUSE_DOWN))
					stage.removeEventListener(MouseEvent.MOUSE_DOWN, stageDragGeneral);
					
					if (stage.hasEventListener(MouseEvent.MOUSE_MOVE))
					stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageDragGeneral);
					
					if (stage.hasEventListener(MouseEvent.MOUSE_UP))
					stage.removeEventListener(MouseEvent.MOUSE_UP, stageDragGeneral);
				}
			}
		}

		private function stageDragGeneral(evt:MouseEvent):void {
			var generalSp:Sprite = sp;
			
			if (evt.type == "mouseDown") {
				dragGeneralOb.drag = true;
				dragGeneralOb.startX = stage.mouseX;
				dragGeneralOb.startY = stage.mouseY;
				dragGeneralOb.genPosX = generalSp.x;
				dragGeneralOb.genPosY = generalSp.y;
			}
			if (evt.type == "mouseMove") if (dragGeneralOb.drag == true) {
				generalSp.x = dragGeneralOb.genPosX + stage.mouseX - dragGeneralOb.startX;
				generalSp.y = dragGeneralOb.genPosY + stage.mouseY - dragGeneralOb.startY;
			}
			if (evt.type == "mouseUp") dragGeneralOb.drag = false;
		}


		private function enterFramHandler(evt:Event):void {
			var i:int;
			var noVisio:Boolean;
			var sh:Shape;
			var ang:Number;
			var color:uint;
			var zArr:Array = [];
			var z:Number;
			var p:Point;
			var coor:Vector.<Number>;
			var j:int;
			var p2d:Vector.<Number> = new Vector.<Number>;//точки двухмерки
			var norm:Vector3D;//нормаль
			
			matPr.prependRotation(3, new Vector3D(sp.rotationX/360, sp.rotationY/360, sp.rotationZ/360));
			pointSp.graphics.clear();
			for (i = 0; i < vertsVec.length; i++) {
				projV[i] = matPr.transformVector(vertsVec[i]);
				vecXY.w = (focus + vecXY.z) / focus;// vs.transform.getRelativeMatrix3D(this).position;
				projV[i].project();
			}
			for (i = 0; i < facesVec.length; i++) {
				z = lex3D.calcZ(facesVec[i], projV);
				zArr[i] = {z:z, fac:facesVec[i]};
			}
			zArr.sortOn("z", Array.NUMERIC );//| Array.DESCENDING номер | наоборот
			fillSp.graphics.clear();
			for (i = 0; i<zArr.length; i++) 
			{
				coor = new Vector.<Number>();
				for (j = 0; j < zArr[i].fac.length; j++) {
					coor.push(projV[zArr[i].fac[j]].x,//x
					projV[zArr[i].fac[j]].y);//y
				}
				norm = lex3D.calcNormal(zArr[i].fac, projV);
				norm.normalize();
				ang = Math.abs(norm.dotProduct(new Vector3D(0,0,-1)));
				color = lex3D.calcLigth(ang,startColor);
				fillSp.graphics.beginFill(color,0.5);
				fillSp.graphics.drawPath(comVec, coor);
				fillSp.graphics.endFill();
			}
		}


	}
}

к сожалению, когда граней много, определение видимой или невидимой грани очень сильно тормозит весь ролик, в данном случае легче нарисовать все грани. Архив, содержит проект расчета освещенности граней (FlashDevelop).