Отсечение нелицевых граней


Созданные с помощью 3Д редакторов трехмерные выпуклые фигуры, имеют грани, точки которых заносятся по определенному принципу, а именно по часовой стрелке или против, соответственно нормаль будет построена во внутрь фигуры или наружу, когда мы будем смотреть на фигуру, то наш лучь взгляда будет направлен по координате z, естественно знаки нормалей граней которые повернуты к нам передом, будут различаться знаками с направлением z, иными словами нормали невидимых граней выпуклого многоугольника будут при умножении их на вектор z будут с отрицательным знаком, а видимые с положительным. Берем окраэдр, как выпуклый многогранник.
Использовался экспорт в as из 3dmax. Таким образом сделал экспорт низкополигонального октаэдра и немного изменил его под свои нужды.
package 
{
//import away3d.core.mesh.*;

public class MyObject
{
public var v3ds:Vector.<Number>;
public var uvs:Vector.<int>;
public var facs:Vector.<int>;
public var facUvs:Vector.<int>;

private function v(x:Number,y:Number,z:Number):void
{
v3ds.push(x,y,z);
}

private function uv(u:Number,v:Number):void
{
uvs.push(u,v);
}
private function f(vn0:int, vn1:int, vn2:int, uvn0:int, uvn1:int, uvn2:int):void
{
	facs.push(vn0, vn1, vn2);
	facUvs.push(uvn0, uvn1, uvn2);
}

public function MyObject()
{
v3ds = new Vector.<Number>()
uvs = new Vector.<int>();
facs = new Vector.<int>();
facUvs = new Vector.<int>();
build();
}
private function build():void
{
v(0.0,-1.29938e-005,-297.871);
v(266.423,-5.84126e-006,-133.212);
v(82.3294,253.384,-133.212);
v(-215.541,156.6,-133.212);
v(-215.541,-156.6,-133.212);
v(82.3294,-253.384,-133.212);
v(215.541,156.6,133.212);
v(-82.3294,253.384,133.212);
v(-266.423,-1.75238e-005,133.212);
v(-82.3294,-253.384,133.212);
v(215.541,-156.6,133.212);
v(0.0,1.29938e-005,297.871);
uv(0.4,1.0);
uv(0.5,0.647584);
uv(0.7,0.647584);
uv(0.9,0.647584);
uv(0.1,0.647584);
uv(0.3,0.647584);
uv(0.6,0.352416);
uv(0.8,0.352416);
uv(0.0,0.352416);
uv(0.2,0.352416);
uv(0.4,0.352416);
uv(0.5,0.0);
uv(0.6,1.0);
uv(0.8,1.0);
uv(0.0,1.0);
uv(-0.1,0.647584);
uv(0.2,1.0);
uv(-0.1,0.647584);
uv(-0.2,0.352416);
uv(-0.1,0.647584);
uv(0.7,0.0);
uv(-0.1,0.0);
uv(-0.2,0.352416);
uv(0.1,0.0);
uv(0.3,0.0);
f(0,1,2, 12,1,2);
f(0,2,3, 13,2,3);
f(0,3,4, 14,15,4);
f(0,4,5, 16,4,5);
f(0,5,1, 0,5,1);
f(1,10,6, 1,10,6);
f(2,6,7, 2,6,7);
f(3,7,8, 17,18,8);
f(4,8,9, 4,8,9);
f(5,9,10, 5,9,10);
f(6,2,1, 6,2,1);
f(7,3,2, 7,3,2);
f(8,4,3, 8,4,19);
f(9,5,4, 9,5,4);
f(10,1,5, 10,1,5);
f(11,7,6, 20,7,6);
f(11,8,7, 21,8,22);
f(11,9,8, 23,9,8);
f(11,10,9, 24,10,9);
f(11,6,10, 11,6,10);
}
}
}

Теперь собственно документ класс
package  
{
	import flash.display.*;
	
	import flash.geom.*;
	
	import fl.controls.*;
	import fl.events.*;
	
	
	import lex.*;
	/**
	 * ...
	 * @author Alex Lexcuk http://www.murmadillo.tut.su
	 */
	public class DocCube extends Sprite
	{
		private var my3Obj:MyObject = new MyObject();


		private var slider:Slider = new Slider();
		private var cubeSh:Shape;
		private var world:Sprite;
		private var fcom:Vector.<int> = Vector.<int>([1,2,2,2]);
		private var fdat:Vector.<Number> = new Vector.<Number>();
		private var m3d:Matrix3D = new Matrix3D();
		private var dats:Vector.<Number> = new Vector.<Number> ();
		public function DocCube() 
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			addChild(cubeSh = new Shape());
			
			cubeSh.x = 400;
			cubeSh.y = 300;
			
			addChild(slider);
			slider.x = 100;
			slider.y = 550;
			slider.setSize(500, 10);
			slider.maximum = 180;
			slider.minimum = -180;
			slider.tickInterval = 5;
			slider.liveDragging = true;
			drawCube();
			slider.addEventListener(SliderEvent.CHANGE, announceChange);
		}

		private function drawCube():void {
			cubeSh.graphics.clear();
			cubeSh.graphics.lineStyle(1,1);
			
			var i:int;
			var j:int;
			var len:int = my3Obj.facs.length;
			var facs:Vector.<int> = my3Obj.facs;
			var x0:Number;
			var x:Number;
			var y0:Number;
			var y:Number;
			var w:Number;
			var focus:Number = 1000;
			var n:Vector3D;
			var poly:Vector.<Vector3D> = new Vector.<Vector3D>();
			var z:Number;
			var x1:Number;
			var x2:Number;
			var y1:Number;
			var y2:Number;
			var z0:Number, z1:Number, z2:Number;
			m3d.transformVectors(my3Obj.v3ds, dats);
			
			
			
			
			
			w = 1 / ((focus + z) / focus);


			for (i = 0; i < len; i += 3) {
				j = 0;
				z = dats[facs[i] * 3 + 2 ];//z
				
				w = 1 / ((focus + z) / focus);
				
				
				x0 = fdat[j++] = dats[facs[i] * 3 ]*w;//x
				y0 = fdat[j++] = dats[facs[i] * 3 + 1 ]*w;//y
				z0 = dats[facs[i] * 3 + 2 ]*w;//z
				
				z = dats[facs[i+1] * 3 +2];//z
				w = 1 / ((focus + z) / focus);
				
				x1 = fdat[j++] = dats[facs[i+1] * 3 ] * w;//x
				y1 = fdat[j++] = dats[facs[i+1] * 3 + 1 ] * w;//y
				z1 = dats[facs[i+1] * 3 + 2 ] * w;//z
				
				
				z = dats[facs[i+2] * 3 + 2 ];//z
				w = 1 / ((focus + z) / focus);
				
				x2 = fdat[j++] = dats[facs[i+2] * 3 ] * w;//x
				y2 = fdat[j++] = dats[facs[i+2] * 3 + 1 ] * w;//y
				z2 =  dats[facs[i+2] * 3 + 2 ] * w;//z
				
				
				fdat[j++] = x0;
				fdat[j++] = y0;
				
				
				
				poly[0] = new Vector3D( x0, y0, z0);
				poly[1] = new Vector3D( x1, y1, z1);
				poly[2] = new Vector3D( x2, y2, z2);
				
				
				
				LMath.calcNormal(poly[0], poly[1], poly[2], n = new Vector3D);
				
				if (n.dotProduct(Vector3D.Z_AXIS)>0){//тут определяем видимость грани выпуклого многоугольника
				cubeSh.graphics.beginFill(0, 0.5);
				cubeSh.graphics.drawPath(fcom, fdat);
				trace(fdat);
				cubeSh.graphics.endFill();
				trace('рисую');
				}else trace('не рисую');
				

			}
			
		}


		private function announceChange(e:SliderEvent):void {
			m3d.identity();
			m3d.appendRotation(e.target.value, Vector3D.X_AXIS);
			drawCube();
		}

	}

}





Потребуется функция LMath.calcNormal да вот она
		public static function calcNormal(_v1:Vector3D, _v2:Vector3D, _v3:Vector3D,_vOut:Vector3D):void {
			_vOut.x = (_v2.y - _v1.y) * (_v3.z - _v1.z) - (_v3.y - _v1.y) * (_v2.z - _v1.z);
			_vOut.y = (_v2.x - _v1.x) * (_v3.z - _v1.z) - (_v3.x - _v1.x) * (_v2.z - _v1.z);
			_vOut.z = (_v2.x - _v1.x) * (_v3.y - _v1.y) - (_v3.x - _v1.x) * (_v2.y - _v1.y);
		}

Все... Вот такой октаэдр

Крутим слайдер
Чето он немного тормозит, клацните на слайдер и стрелками клавиатуры влево, вправо, так не тормозит.