mirror of
				https://github.com/MapMakersAndProgrammers/Alternativa3D.git
				synced 2025-10-27 18:39:07 -07:00 
			
		
		
		
	async dae parsing
This commit is contained in:
		| @@ -14,10 +14,14 @@ package alternativa.engine3d.loaders { | ||||
| 	import alternativa.engine3d.core.Light3D; | ||||
| 	import alternativa.engine3d.core.Object3D; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeDocument; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeElement; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeGeometry; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeMaterial; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeNode; | ||||
| 	import alternativa.engine3d.loaders.collada.DaeObject; | ||||
| 	import alternativa.engine3d.resources.ExternalTextureResource; | ||||
| 	import flash.utils.getTimer; | ||||
| 	import flash.utils.setTimeout; | ||||
|  | ||||
| 	use namespace alternativa3d; | ||||
|  | ||||
| @@ -79,6 +83,43 @@ package alternativa.engine3d.loaders { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|         /** | ||||
|          * Method parses <code>xml</code> of collada asynchronously and fills arrays <code>objects</code>,  <code>hierarchy</code>, <code>materials</code>, <code>animations</code> | ||||
|          * It is slower than <code>parse</code> but does not lock the thread. | ||||
| 		 * If you need to download textures, use class <code>TexturesLoader</code>. | ||||
|          * <p>Path to collada file should match with  <code>URI</code> specification. E.g., <code>file:///C:/test.dae</code> or <code>/C:/test.dae</code> for the full paths and  <code>test.dae</code>, <code>./test.dae</code>  in case of relative.</p> | ||||
|          * | ||||
|          * @param data <code>XML</code> data type of collada. | ||||
| 		 * @param onComplete Callback function accepting ParserCollada object as its argument. | ||||
|          * @param baseURL Path to  textures relative to swf-file (Or file name only in case of <code>trimPaths=true</code>). | ||||
|          * @param trimPaths Use  file names only, without paths. | ||||
|          * | ||||
|          * @see alternativa.engine3d.loaders.TexturesLoader | ||||
|          * @see #objects | ||||
|          * @see #hierarchy | ||||
|          * @see #materials | ||||
|          */ | ||||
| 		public function parseAsync(data:XML, onComplete:Function, baseURL:String = null, trimPaths:Boolean = false):void { | ||||
| 			init(); | ||||
|  | ||||
| 			var document:DaeDocument = new DaeDocument(data, 0); | ||||
| 			if (document.scene != null) { | ||||
| 				parseMaterials(document.materials, baseURL, trimPaths); | ||||
| 				addNodesToQueue(document.scene.nodes, null, false); | ||||
| 				 | ||||
| 				// parse nodes internal sttructures ahead of time to avoid congestion | ||||
| 				addElementsToQueue(document.controllers); | ||||
| 				addElementsToQueue(document.channels); | ||||
| 				addElementsToQueue(document.geometries); | ||||
| 				for each (var geom:DaeGeometry in document.geometries) { | ||||
| 					addElementsToQueue (geom.primitives); | ||||
| 				} | ||||
| 				addElementsToQueue(document.sources); | ||||
| 				 | ||||
| 				parseQueuedElements(onComplete); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * Adds components of animated object to lists objects, parents, hierarchy, cameras, animations  and to parent container. | ||||
| 		 */ | ||||
| @@ -176,6 +217,85 @@ package alternativa.engine3d.loaders { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private var queue:Vector.<QueueElement> = new Vector.<QueueElement> (); | ||||
|  | ||||
| 		private function addNodesToQueue(nodes:Vector.<DaeNode>, parent:Object3D, skinsOnly:Boolean):void { | ||||
| 			for (var i:int = nodes.length; i > 0; i--) { | ||||
| 				var args:QueueElement = new QueueElement; | ||||
| 				args.element = nodes[i - 1]; | ||||
| 				args.parent = parent; | ||||
| 				args.skinsOnly = skinsOnly; | ||||
| 				queue.unshift(args); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private function addElementsToQueue(elements:Object):void { | ||||
| 			for each (var element:DaeElement in elements) { | ||||
| 				var args:QueueElement = new QueueElement; | ||||
| 				args.element = element; | ||||
| 				queue.unshift(args); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private const ASYNC_LIMIT:int = 50; | ||||
| 		private const ASYNC_TIMEOUT:int = 1; | ||||
|  | ||||
| 		private function parseQueuedElements(onComplete:Function):void { | ||||
| 			var t:int = getTimer (); | ||||
| 			do { | ||||
| 				if (queue.length == 0) { | ||||
| 					// make sure onComplete is called after parseAsync exits | ||||
| 					setTimeout (onComplete, ASYNC_TIMEOUT, this); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				var args:QueueElement = queue.shift(); | ||||
| 				args.element.parse(); | ||||
|  | ||||
| 				if (args.element is DaeNode) { | ||||
| 					var node:DaeNode = args.element as DaeNode; | ||||
| 					var parent:Object3D = args.parent; | ||||
| 					var skinsOnly:Boolean = args.skinsOnly; | ||||
|  | ||||
| 					// Object to which child objects will be added. | ||||
| 					var container:Object3D = null; | ||||
| 					if (node.skins != null) { | ||||
| 						// Main joint of skin | ||||
| 						container = addObjects(node.skins, parent, node.layer); | ||||
| 					} else { | ||||
| 						if (!skinsOnly && !node.skinOrTopmostJoint) { | ||||
| 							if (node.objects != null) { | ||||
| 								container = addObjects(node.objects, parent, node.layer); | ||||
| 							} else { | ||||
| 								// Empty Object3D | ||||
| 								container = new Object3D(); | ||||
| 								container.name = node.cloneString(node.name); | ||||
| 								addObject(node.applyAnimation(node.applyTransformations(container)), parent, node.layer); | ||||
| 								container.calculateBoundBox(); | ||||
| 							} | ||||
| 						} else { | ||||
| 							// Object or its parent is a skin or joint | ||||
| 							// Create an object  only if there are a child skins | ||||
| 							if (hasSkinsInChildren(node)) { | ||||
| 								container = new Object3D(); | ||||
| 								container.name = node.cloneString(node.name); | ||||
| 								addObject(node.applyAnimation(node.applyTransformations(container)), parent, node.layer); | ||||
| 								addNodesToQueue(node.nodes, container, skinsOnly || node.skinOrTopmostJoint); | ||||
| 								container.calculateBoundBox(); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 					// Parse children | ||||
| 					if (container != null) { | ||||
| 						addNodesToQueue(node.nodes, container, skinsOnly || node.skinOrTopmostJoint); | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 			} while (getTimer () - t < ASYNC_LIMIT); | ||||
|  | ||||
| 			setTimeout (parseQueuedElements, ASYNC_TIMEOUT, onComplete); | ||||
| 		} | ||||
|  | ||||
| 		private function trimPath(path:String):String { | ||||
| 			var index:int = path.lastIndexOf("/"); | ||||
| 			return (index < 0) ? path : path.substr(index + 1); | ||||
| @@ -387,3 +507,11 @@ package alternativa.engine3d.loaders { | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| import alternativa.engine3d.core.Object3D; | ||||
| import alternativa.engine3d.loaders.collada.DaeElement; | ||||
| class QueueElement { | ||||
| 	public var element:DaeElement; | ||||
| 	public var parent:Object3D; | ||||
| 	public var skinsOnly:Boolean; | ||||
| } | ||||
| @@ -22,7 +22,7 @@ package alternativa.engine3d.loaders.collada { | ||||
| 		private var data:XML; | ||||
|  | ||||
| 		// Dictionaries to store matchings id-> DaeElement | ||||
| 		internal var sources:Object; | ||||
| 		public var sources:Object; | ||||
| 		internal var arrays:Object; | ||||
| 		internal var vertices:Object; | ||||
| 		public var geometries:Object; | ||||
| @@ -30,9 +30,11 @@ package alternativa.engine3d.loaders.collada { | ||||
| 		internal var lights:Object; | ||||
| 		internal var images:Object; | ||||
| 		internal var effects:Object; | ||||
| 		internal var controllers:Object; | ||||
| 		public var controllers:Object; | ||||
| 		internal var samplers:Object; | ||||
|  | ||||
| 		public var channels:Vector.<DaeChannel>; | ||||
|  | ||||
| 		public var materials:Object; | ||||
|  | ||||
| 		internal var logger:DaeLogger; | ||||
| @@ -186,6 +188,10 @@ package alternativa.engine3d.loaders.collada { | ||||
| 				var node:DaeNode = channel.node; | ||||
| 				if (node != null) { | ||||
| 					node.addChannel(channel); | ||||
| 					if (channels == null) { | ||||
| 						channels = new Vector.<DaeChannel>; | ||||
| 					} | ||||
| 					channels.push (channel); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -26,7 +26,7 @@ package alternativa.engine3d.loaders.collada { | ||||
| 		use namespace alternativa3d; | ||||
|  | ||||
| 		internal var geometryVertices:Vector.<DaeVertex>; | ||||
| 		internal var primitives:Vector.<DaePrimitive>; | ||||
| 		public var primitives:Vector.<DaePrimitive>; | ||||
| 		internal var geometry:Geometry; | ||||
| 		 | ||||
| 		private var vertices:DaeVertices; | ||||
| @@ -46,12 +46,13 @@ package alternativa.engine3d.loaders.collada { | ||||
| 			if (verticesXML != null) { | ||||
| 				vertices = new DaeVertices(verticesXML, document); | ||||
| 				document.vertices[vertices.id] = vertices; | ||||
| 				// set primitives early for ParserCollada's parseAsync | ||||
| 				parsePrimitives(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		override protected function parseImplementation():Boolean { | ||||
| 			if (vertices != null) { | ||||
| 				parsePrimitives(); | ||||
|  | ||||
| 				vertices.parse(); | ||||
| 				var numVertices:int = vertices.positions.numbers.length/vertices.positions.stride; | ||||
|   | ||||
| @@ -28,9 +28,14 @@ package alternativa.engine3d.loaders.collada { | ||||
| 			return data.@source[0]; | ||||
| 		} | ||||
| 	 | ||||
| 		// todo: profiler shows that offset getter is seriously abused in DaePrimitive's fillGeometry | ||||
| 		private var _offset:int = -1; | ||||
| 		public function get offset():int { | ||||
| 			var attr:XML = data.@offset[0]; | ||||
| 			return (attr == null) ? 0 : parseInt(attr.toString(), 10); | ||||
| 			if (_offset < 0) { | ||||
| 				var attr:XML = data.@offset[0]; | ||||
| 				_offset = (attr == null) ? 0 : parseInt(attr.toString(), 10); | ||||
| 			} | ||||
| 			return _offset; | ||||
| 		} | ||||
| 	 | ||||
| 		public function get setNum():int { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 makc
					makc