Показать сообщение отдельно
Старый 23.08.2013, 00:10
Vasya Pupkin вне форума Посмотреть профиль Отправить личное сообщение для Vasya Pupkin Найти все сообщения от Vasya Pupkin
  № 4  
Ответить с цитированием
Vasya Pupkin

Регистрация: Dec 2011
Сообщений: 17
Спасибо за советы, но изменение zNear до 0.1 и zFar до 2000 ни к каким улучшениям не привело. По-прежнему этот проклятый срез присутствует и все остальные проблемные эффекты остались. Какие есть еще предложения. Приведу весь код:
1. PointCloudRender.as
Код AS3:
package
{
	import com.adobe.utils.AGALMiniAssembler;
	import com.adobe.utils.PerspectiveMatrix3D;
 
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display.TriangleCulling;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DCompareMode;
	import flash.display3D.Context3DProfile;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DRenderMode;
	import flash.display3D.Context3DTriangleFace;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.Program3D;
	import flash.display3D.VertexBuffer3D;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.filters.DropShadowFilter;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
 
	[SWF(width=800, height=600, frameRate=30)]
 
 
	public class PointCloudRender extends Sprite
	{
		public function PointCloudRender()
		{
 
			if(stage)
				loadData()
			else
				addEventListener(Event.ADDED_TO_STAGE,loadData);
		}
		private function loadData(e:Event = null):void {
 
			removeEventListener(Event.ADDED_TO_STAGE, loadData);
 
			var urlrequest:URLRequest=new URLRequest("data.pcd");
			var urlloader:URLLoader=new URLLoader();
 
			urlloader.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
			urlloader.addEventListener(Event.COMPLETE,onComplete);
			urlloader.dataFormat= URLLoaderDataFormat.BINARY;
			urlloader.load(urlrequest);
			function onIOError(e:IOErrorEvent):void
			{
				urlloader.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);
				urlloader.removeEventListener(Event.COMPLETE,onComplete);
			}
			function onComplete(e:Event):void
			{
				urlloader.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);
				urlloader.removeEventListener(Event.COMPLETE,onComplete);
				pointCloud=urlloader.data;
				callContext3D();
			}
		}
		private var context3D:Context3D;
 
		private function callContext3D(e:Event=null):void
		{
 
			stage.addEventListener(MouseEvent.MOUSE_WHEEL,onMWheel);
			stage.addEventListener(MouseEvent.MOUSE_DOWN,onMDown);
			stage.addEventListener(MouseEvent.MOUSE_UP,onMUp);
 
 
			removeEventListener(Event.ADDED_TO_STAGE,callContext3D);
			if(!stage)
			{
				log("callContext3D stage == null");
				return;
			}
			if(!stage.stage3Ds)
			{
				log("callContext3D stage3Ds == null");
				return;
			}
			if(stage.stage3Ds.length == 0)
			{
				log("callContext3D stage3Ds length == 0");
				return;
			}
			var stage3D:Stage3D = stage.stage3Ds[0]; 
			if(!stage3D)
			{
				log("callContext3D stage3D == null");
				return;
			}
 
			stage3D.removeEventListener(Event.CONTEXT3D_CREATE,initContext3D);
			stage3D.addEventListener(Event.CONTEXT3D_CREATE,initContext3D);
			stage3D.requestContext3D(Context3DRenderMode.AUTO);
			log("callContext3D OK");
		}
		private var vertexShader:AGALMiniAssembler = new AGALMiniAssembler();
		private var fragmentShader:AGALMiniAssembler = new AGALMiniAssembler();
		private function initContext3D(e:Event):void
		{
			context3D = (e.target as Stage3D).context3D;
 
			//Режим ошибок.
			context3D.enableErrorChecking = true;
 
			//Кюлинг
			context3D.setCulling(Context3DTriangleFace.NONE);
 
			//Не знаю для чего это, но взял от сюда - https://gist.github.com/noonat/847106
			//context3D.setDepthTest(true,Context3DCompareMode.LESS_EQUAL);
 
			//Ширина и высота frameBuffer-а
			var backBufferWidth:uint = stage.stageHeight;
			var backBufferHeight:uint = stage.stageHeight;
 
 
			//AntiAliasing
			var antiAlias:uint = 0//0,2,4,8,16
			log("backBuffer",backBufferWidth,backBufferHeight);
			//Конфигурируем размеры.
			context3D.configureBackBuffer(backBufferWidth,backBufferHeight,antiAlias,true,true);
 
			//Наши шейдеры.
			const VERTEX_SHADER:String = 
				//"mov op, va0 \n" + 
				"m44 op, va0, vc0 \n" +
				"mov v0, va1";
			const FRAGMENT_SHADER:String = 
				"mov oc, v0";
 
			//Наши скомпилированные шейдеры.
			vertexShader.assemble(Context3DProgramType.VERTEX,VERTEX_SHADER);
			fragmentShader.assemble(Context3DProgramType.FRAGMENT,FRAGMENT_SHADER);
 
			//Программа
			var program:Program3D = context3D.createProgram();
			program.upload(vertexShader.agalcode,fragmentShader.agalcode);
			context3D.setProgram(program);
 
//			Создаем спрайты
//			var sprite3D:Sprite3D = new Sprite3D(context3D,Vector.<Number>([
//				//xyz		   rgb
//				-0.3, 0.3, 0.0,  1.0, 0.0, 0.0,
//				
//				 0.3, 0.3, 0.0,  0.0, 0.0, 0.0,
//				 0.0,-0.3, 0.0,  1.0, 1.0, 0.0
//			]),Vector.<uint>([0,1,2]));
//			sprite3Ds.push(sprite3D);
 
 
 
			sprite3Ds = new Vector.<Sprite3D>();
                        //Переводим данные кинекта в треугольники.
			initPointCloud(320,240,1,true);
 
			amountOfSprites = sprite3Ds.length;
			contextChanged = true;
 
 
			//Начинаем рендерить
			removeEventListener(Event.ENTER_FRAME,render);
			addEventListener(Event.ENTER_FRAME,render);
			log("initContext3D OK");
		}
		private var perspective:PerspectiveMatrix3D;
		private var modelMatrix:Matrix3D;
		private var perspectiveMatrix:Matrix3D;
		private var modelPerspectiveMatrix:Matrix3D;
		private var amountOfSprites:uint=0;
		private var sprite3Ds:Vector.<Sprite3D> = new Vector.<Sprite3D>();
		private var contextChanged:Boolean=false;
		private var matrix3D:Matrix3D;
		public function render(e:Event):void
		{
 
			if(!contextChanged)return;
			context3D.clear(0,0,0);
 
 
			if(!matrix3D)
			{
				matrix3D = new Matrix3D();	
			}
			else
			{
				matrix3D.identity();
			}
			matrix3D.appendRotation(rY, Vector3D.Y_AXIS);
			matrix3D.appendRotation(rX, Vector3D.X_AXIS);
			matrix3D.appendRotation(rZ, Vector3D.Z_AXIS);
			matrix3D.appendScale(scale,scale,scale);
			matrix3D.appendTranslation(offsetX, offsetY, offsetZ);
 
 
			if(!perspective)
			{
				perspective = new PerspectiveMatrix3D();
				var aspect:Number = 3/3;
				var zNear:Number = 0.1;
				var zFar:Number = 2000;
				var fov:Number = this.fov*Math.PI/180;
				perspective.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
			}
			matrix3D.append(perspective);
 
 
			for(var i:uint=0;i<amountOfSprites;i++)
			{				
				//Геометрия
				context3D.setVertexBufferAt(0,sprite3Ds[i].vertexBuffer3D,0,Context3DVertexBufferFormat.FLOAT_3);
				context3D.setVertexBufferAt(1,sprite3Ds[i].vertexBuffer3D,3,Context3DVertexBufferFormat.FLOAT_3);
				context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,matrix3D);
 
				//Отрисовка
				context3D.drawTriangles(sprite3Ds[i].indexBuffer3D,0,sprite3Ds[i].numTriangles);
			}
 
			//Окончательный вывод изображения.
			context3D.present();
 
			contextChanged = false;
			log("render OK");
		}
		private var rY:Number=0;
		private var rX:Number=0;
		private var rZ:Number=0;
		private var offsetX:Number=0;
		private var offsetY:Number=0;
		private var offsetZ:Number= 2;
		private var scale:Number= 1;
		private var fov:Number=45;
 
 
		public var press:Boolean=false;
		public var ctrl:Boolean=false;
		public var shift:Boolean=false;
		public var lastMouse:Point;
		public function onMDown(e:MouseEvent):void
		{
			lastMouse=new Point(stage.mouseX,stage.mouseY);
			updateInput();
			removeEventListener(Event.ENTER_FRAME,updateInput);
			addEventListener(Event.ENTER_FRAME,updateInput);
			ctrl=e.ctrlKey;
			shift = e.shiftKey;
		}
		public function onMUp(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME,updateInput);
			ctrl = false;
			shift = false;
		}
 
		public function onMWheel(e:MouseEvent):void
		{			
			contextChanged = true;
 
			if(e.ctrlKey)
			{
				fov -= e.delta;
				perspective = null;
				log2("fov =",fov.toFixed(2));
			}
			else
			{
				rZ -= e.delta;
				log2("rotationZ =",rZ.toFixed(2));
			}
 
 
		}
		private var sZ:Number = 1;
		private function updateInput(e:Event=null):void {
			var currentMouse:Point=new Point(stage.mouseX,stage.mouseY);
			if(ctrl && shift)
			{
				scale += (currentMouse.x-lastMouse.x)*0.01;
				log2("scale =",scale);
			}
			else if(ctrl)
			{	
 
				offsetZ += (currentMouse.x-lastMouse.x);
				log2("offsetZ =",offsetZ);
			}
			else if(shift)
			{
				offsetX += (currentMouse.x-lastMouse.x)*0.01;
				offsetY -= (currentMouse.y-lastMouse.y)*0.01;
				log2("offsetX =",offsetX.toFixed(2),"offsetY =",offsetY.toFixed(2));
			}
			else
			{
				rY-= (currentMouse.x-lastMouse.x);
				rX-= (currentMouse.y-lastMouse.y);
				log2("rotationY =",rY.toFixed(2),"rotationX =",rX.toFixed(2));
 
			}
			lastMouse=currentMouse;
			contextChanged = true;
		} 
 
 
 
 
 
		private var pointCloud:ByteArray;
		public function initPointCloud(width:int=320,height:int=240,density:int=1,includeRGB:Boolean=false):void
		{	
 
			var vertices:Vector.<Number> = new Vector.<Number>();
			var indexes:Vector.<uint> = initIndexes2(width);
 
			var i:uint=0;
			var j:uint=0;
			var offset:Number = 0.5;
			var centerX:Number = width*0.5;
			var centerY:Number = height*0.5;
			pointCloud.position=0;
			if(!includeRGB)
			{
				while(pointCloud.bytesAvailable>0)
				{
					var x:Number = Number(pointCloud.readUnsignedByte());
					x += pointCloud.readUnsignedByte() << 8;
					var y:Number = Number(pointCloud.readUnsignedByte());
					y += pointCloud.readUnsignedByte() << 8;
					var z:Number = Number(pointCloud.readUnsignedByte());
					z += pointCloud.readUnsignedByte() << 8;
 
					vertices.push(x);
					vertices.push(y);
					vertices.push(z*0.01);
					i++;
				}
			}
			else
			{
				while(pointCloud.bytesAvailable>0)
				{	
					//1 байт 0-255
					x = Number(pointCloud.readUnsignedByte());
					//2 байт 255 - 25535
					x += pointCloud.readUnsignedByte() << 8;
					//3 байт
					y = Number(pointCloud.readUnsignedByte());
					//4 байт
					y += pointCloud.readUnsignedByte() << 8;
					//5 байт
					z = Number(pointCloud.readUnsignedByte());
					//6 байт
					z += pointCloud.readUnsignedByte() << 8;
 
					//7 байт - RED 1
					var r:Number = Number(pointCloud.readUnsignedByte());
					//8 байт - RED 2
					pointCloud.readUnsignedByte();
					//9 байт - GREEN 1
					var g:Number = Number(pointCloud.readUnsignedByte());
					//10 байт - GREEN 2
					pointCloud.readUnsignedByte();
					//11 байт - BLUE 1
					var b:Number = Number(pointCloud.readUnsignedByte());
					//12 байт - BLUE 2
					pointCloud.readUnsignedByte();
 
					x-=centerX;
					y-=centerY;
					//z*= 0;
 
					r/=255;
					g/=255;
					b/=255;
 
 
					//Первая вершина треугольника
					vertices.push(x-offset);
					vertices.push(y-offset);
					vertices.push(z);
					vertices.push(r);
					vertices.push(g);
					vertices.push(b);
 
					//Вторая вершина треугольника
					vertices.push(x+offset);
					vertices.push(y-offset);
					vertices.push(z);
					vertices.push(r);
					vertices.push(g);
					vertices.push(b);
 
					//Третья вершина треугольника
					vertices.push(x+offset);
					vertices.push(y+offset);
					vertices.push(z);
					vertices.push(r);
					vertices.push(g);
					vertices.push(b);
 
					//Четвертая вершина треугольника
					vertices.push(x-offset);
					vertices.push(y+offset);
					vertices.push(z);
					vertices.push(r);
					vertices.push(g);
					vertices.push(b);
 
 
 
					i++;
					if(i>=width)
					{					
						var sprite3D:Sprite3D = new Sprite3D(context3D,vertices,indexes);
						sprite3Ds.push(sprite3D);
						vertices = new Vector.<Number>();
						i = 0;
						j++;
					}
 
				}
			}		
 
			log("initPointCloud OK");
			function initIndexes2(triangles:int=320):Vector.<uint>
			{
				var vi:Vector.<uint> = new Vector.<uint>();
				var indexAmount:uint = triangles*4;
				for(var i:uint=0;i<indexAmount;i+=4)
				{
					vi.push(i);
					vi.push(i+1);
					vi.push(i+2);
					vi.push(i);
					vi.push(i+2);
					vi.push(i+3);
				}
				vi.fixed=true;
 
				return vi;
			}
		}
 
		private var tf:TextField;
		public var log:Function=drawText;
		public function clearLog():void
		{
			if(tf)tf.text="";
		}
 
		private var previewText:String;
		private var previewCount:int=1;
		private var previewLength:int=0;
		public function drawText(...args):void
		{
 
			if(!tf)
			{
				tf=new TextField();
				tf.textColor=0x0000ff;
				tf.type=TextFieldType.INPUT;
				tf.addEventListener(Event.CHANGE,posTf);
				tf.multiline=true;
				tf.autoSize="right";
				var tfr:TextFormat = new TextFormat();
				tfr.align ="right";
				tf.defaultTextFormat=tfr;
				tf.setTextFormat(tf.defaultTextFormat);
				tf.filters=[new DropShadowFilter(0,0,0xffffff,1,5,5,3)];
			}
			if(stage)stage.addChild(tf);
			var text:String="";
			for(var i:uint=0;i<args.length;i++)text+=(i==0?"":" ")+String(args[i]);
 
 
			if(previewText==text)
			{
				previewCount++;
				if(previewCount==2)
				{
					var extendedText:String="[ "+previewCount+" ] "+text;
					tf.text=tf.text.substring(0,tf.text.length-text.length)+extendedText;
					previewLength=extendedText.length;
				}
				else
				{
					extendedText="[ "+previewCount+" ] "+text;
					tf.text=tf.text.substring(0,tf.text.length-previewLength)+extendedText;
					previewLength=extendedText.length;
				}
 
			}
			else
			{
				previewCount=1;
				previewLength=0;
				tf.appendText((tf.text==""?"":"\n")+text);
			}
			previewText=text;
			posTf();
			function posTf(e:Event=null):void
			{
				tf.x=stage?stage.stageWidth-tf.width-10:10;
				tf.y=stage?stage.stageHeight-tf.height:300-tf.height;
			}
 
		}
		public var log2:Function = drawText2;
		private var tf2:TextField;
		private var previewText2:String;
		private var previewCount2:int=1;
		private var previewLength2:int=0;
		public function drawText2(...args):void
		{
 
			if(!tf2)
			{
				tf2=new TextField();
				tf2.textColor=0x00ffff;
				tf2.type=TextFieldType.INPUT;
				tf2.addEventListener(Event.CHANGE,posTf);
				tf2.multiline=true;
				tf2.autoSize="right";
				var tfr:TextFormat = new TextFormat();
				tfr.align ="right";
				tf2.defaultTextFormat=tfr;
				tf2.setTextFormat(tf2.defaultTextFormat);
//				tf2.filters=[new DropShadowFilter(0,0,0xffffff,1,5,5,3)];
			}
			tf2.text="";
			if(stage)stage.addChild(tf2);
			var text:String="";
			for(var i:uint=0;i<args.length;i++)text+=(i==0?"":" ")+String(args[i]);
 
 
			if(previewText==text)
			{
				previewCount++;
				if(previewCount==2)
				{
					var extendedText:String="[ "+previewCount2+" ] "+text;
					tf2.text=tf2.text.substring(0,tf2.text.length-text.length)+extendedText;
					previewLength2=extendedText.length;
				}
				else
				{
					extendedText="[ "+previewCount2+" ] "+text;
					tf2.text=tf2.text.substring(0,tf2.text.length-previewLength2)+extendedText;
					previewLength2=extendedText.length;
				}
 
			}
			else
			{
				previewCount2=1;
				previewLength2=0;
				tf2.appendText((tf2.text==""?"":"\n")+text);
			}
			previewText2=text;
			posTf();
			function posTf(e:Event=null):void
			{
				tf2.x=10;
				tf2.y=stage?stage.stageHeight-tf2.height:300-tf2.height;
			}
 
		}
	}
}
2. Sprite3D.as
Код AS3:
package
{
	import flash.display3D.Context3D;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.VertexBuffer3D;
	import flash.utils.ByteArray;
 
	public class Sprite3D
	{
		public function Sprite3D(context:Context3D,vertices:Vector.<Number>,indexes:Vector.<uint>,vertexStride:uint=6)
		{
			_indexBuffer3D = context.createIndexBuffer(indexes.length);
			_indexBuffer3D.uploadFromVector(indexes,0,indexes.length);
			_numVerticies = vertices.length/vertexStride;
			_numTriangles = _numVerticies/2;
			_vertexBuffer3D = context.createVertexBuffer(_numVerticies,vertexStride);
			_vertexBuffer3D.uploadFromVector(vertices,0,_numVerticies);
 
		}
		private var _numVerticies:uint=3;
		public function get numVerticies():uint
		{
			return _numVerticies;
		}
		private var _numTriangles:uint=1;
		public function get numTriangles():uint
		{
			return _numTriangles;
		}
		private var _vertexBuffer3D:VertexBuffer3D;
 
		public function get vertexBuffer3D():VertexBuffer3D
		{
			return _vertexBuffer3D;
		}
 
		private var _indexBuffer3D:IndexBuffer3D;
 
		public function get indexBuffer3D():IndexBuffer3D
		{
			return _indexBuffer3D;
		}
 
 
 
	}
}