mirror of
https://github.com/MapMakersAndProgrammers/Alternativa3D.git
synced 2025-10-26 01:49:07 -07:00
@@ -14,10 +14,14 @@ package alternativa.engine3d.loaders {
|
|||||||
import alternativa.engine3d.core.Light3D;
|
import alternativa.engine3d.core.Light3D;
|
||||||
import alternativa.engine3d.core.Object3D;
|
import alternativa.engine3d.core.Object3D;
|
||||||
import alternativa.engine3d.loaders.collada.DaeDocument;
|
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.DaeMaterial;
|
||||||
import alternativa.engine3d.loaders.collada.DaeNode;
|
import alternativa.engine3d.loaders.collada.DaeNode;
|
||||||
import alternativa.engine3d.loaders.collada.DaeObject;
|
import alternativa.engine3d.loaders.collada.DaeObject;
|
||||||
import alternativa.engine3d.resources.ExternalTextureResource;
|
import alternativa.engine3d.resources.ExternalTextureResource;
|
||||||
|
import flash.utils.getTimer;
|
||||||
|
import flash.utils.setTimeout;
|
||||||
|
|
||||||
use namespace alternativa3d;
|
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 onComplete Callback function accepting ParserCollada object as its argument.
|
||||||
|
* @param data <code>XML</code> data type of collada.
|
||||||
|
* @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(onComplete:Function, data:XML, 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.
|
* Adds components of animated object to lists objects, parents, hierarchy, cameras, animations and to parent container.
|
||||||
*/
|
*/
|
||||||
@@ -176,6 +217,90 @@ 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 j:int = 0; j < queue.length; j++) {
|
||||||
|
if (queue[j].element is DaeNode) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.splice(j, 0, 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 {
|
private function trimPath(path:String):String {
|
||||||
var index:int = path.lastIndexOf("/");
|
var index:int = path.lastIndexOf("/");
|
||||||
return (index < 0) ? path : path.substr(index + 1);
|
return (index < 0) ? path : path.substr(index + 1);
|
||||||
@@ -387,3 +512,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;
|
private var data:XML;
|
||||||
|
|
||||||
// Dictionaries to store matchings id-> DaeElement
|
// Dictionaries to store matchings id-> DaeElement
|
||||||
internal var sources:Object;
|
public var sources:Object;
|
||||||
internal var arrays:Object;
|
internal var arrays:Object;
|
||||||
internal var vertices:Object;
|
internal var vertices:Object;
|
||||||
public var geometries:Object;
|
public var geometries:Object;
|
||||||
@@ -30,9 +30,11 @@ package alternativa.engine3d.loaders.collada {
|
|||||||
internal var lights:Object;
|
internal var lights:Object;
|
||||||
internal var images:Object;
|
internal var images:Object;
|
||||||
internal var effects:Object;
|
internal var effects:Object;
|
||||||
internal var controllers:Object;
|
public var controllers:Object;
|
||||||
internal var samplers:Object;
|
internal var samplers:Object;
|
||||||
|
|
||||||
|
public var channels:Vector.<DaeChannel>;
|
||||||
|
|
||||||
public var materials:Object;
|
public var materials:Object;
|
||||||
|
|
||||||
internal var logger:DaeLogger;
|
internal var logger:DaeLogger;
|
||||||
@@ -186,6 +188,10 @@ package alternativa.engine3d.loaders.collada {
|
|||||||
var node:DaeNode = channel.node;
|
var node:DaeNode = channel.node;
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
node.addChannel(channel);
|
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;
|
use namespace alternativa3d;
|
||||||
|
|
||||||
internal var geometryVertices:Vector.<DaeVertex>;
|
internal var geometryVertices:Vector.<DaeVertex>;
|
||||||
internal var primitives:Vector.<DaePrimitive>;
|
public var primitives:Vector.<DaePrimitive>;
|
||||||
internal var geometry:Geometry;
|
internal var geometry:Geometry;
|
||||||
|
|
||||||
private var vertices:DaeVertices;
|
private var vertices:DaeVertices;
|
||||||
@@ -46,12 +46,13 @@ package alternativa.engine3d.loaders.collada {
|
|||||||
if (verticesXML != null) {
|
if (verticesXML != null) {
|
||||||
vertices = new DaeVertices(verticesXML, document);
|
vertices = new DaeVertices(verticesXML, document);
|
||||||
document.vertices[vertices.id] = vertices;
|
document.vertices[vertices.id] = vertices;
|
||||||
|
// set primitives early for ParserCollada's parseAsync
|
||||||
|
parsePrimitives();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected function parseImplementation():Boolean {
|
override protected function parseImplementation():Boolean {
|
||||||
if (vertices != null) {
|
if (vertices != null) {
|
||||||
parsePrimitives();
|
|
||||||
|
|
||||||
vertices.parse();
|
vertices.parse();
|
||||||
var numVertices:int = vertices.positions.numbers.length/vertices.positions.stride;
|
var numVertices:int = vertices.positions.numbers.length/vertices.positions.stride;
|
||||||
|
|||||||
@@ -28,9 +28,14 @@ package alternativa.engine3d.loaders.collada {
|
|||||||
return data.@source[0];
|
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 {
|
public function get offset():int {
|
||||||
|
if (_offset < 0) {
|
||||||
var attr:XML = data.@offset[0];
|
var attr:XML = data.@offset[0];
|
||||||
return (attr == null) ? 0 : parseInt(attr.toString(), 10);
|
_offset = (attr == null) ? 0 : parseInt(attr.toString(), 10);
|
||||||
|
}
|
||||||
|
return _offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get setNum():int {
|
public function get setNum():int {
|
||||||
|
|||||||
Reference in New Issue
Block a user