Add mostly deobfuscated package, class and function name source

This commit is contained in:
Pyogenics
2025-05-09 17:55:37 +01:00
parent bbf438a33f
commit f8ac96858f
1034 changed files with 48614 additions and 40522 deletions

View File

@@ -0,0 +1,39 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeArray extends DaeElement
{
public var array:Array;
public function DaeArray(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get type() : String
{
return String(data.localName());
}
override protected function parseImplementation() : Boolean
{
var count:int = 0;
this.array = parseStringArray(data);
var countXML:XML = data.@count[0];
if(countXML != null)
{
count = int(parseInt(countXML.toString(),10));
if(this.array.length < count)
{
document.logger.logNotEnoughDataError(data.@count[0]);
return false;
}
this.array.length = count;
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,232 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.animation.keys.NumberKey;
import alternativa.engine3d.animation.keys.§_-Np§;
import alternativa.engine3d.animation.keys.§_-kB§;
use namespace alternativa3d;
public class DaeChannel extends DaeElement
{
public static const PARAM_UNDEFINED:String = "undefined";
public static const PARAM_TRANSLATE_X:String = "x";
public static const PARAM_TRANSLATE_Y:String = "y";
public static const PARAM_TRANSLATE_Z:String = "z";
public static const PARAM_SCALE_X:String = "scaleX";
public static const PARAM_SCALE_Y:String = "scaleY";
public static const PARAM_SCALE_Z:String = "scaleZ";
public static const PARAM_ROTATION_X:String = "rotationX";
public static const PARAM_ROTATION_Y:String = "rotationY";
public static const PARAM_ROTATION_Z:String = "rotationZ";
public static const PARAM_TRANSLATE:String = "translate";
public static const PARAM_SCALE:String = "scale";
public static const PARAM_MATRIX:String = "matrix";
public var tracks:Vector.<§_-Np§>;
public var §_-dS§:String = "undefined";
public var animName:String;
public function DaeChannel(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get node() : DaeNode
{
var targetParts:Array = null;
var node:DaeNode = null;
var i:int = 0;
var count:int = 0;
var sid:String = null;
var targetXML:XML = data.@target[0];
if(targetXML != null)
{
targetParts = targetXML.toString().split("/");
node = document.findNodeByID(targetParts[0]);
if(node != null)
{
targetParts.pop();
for(i = 1,count = int(targetParts.length); i < count; )
{
sid = targetParts[i];
node = node.getNodeBySid(sid);
if(node == null)
{
return null;
}
i++;
}
return node;
}
}
return null;
}
override protected function parseImplementation() : Boolean
{
this.parseTransformationType();
this.parseSampler();
return true;
}
private function parseTransformationType() : void
{
var transformationXML:XML = null;
var child:XML = null;
var attr:XML = null;
var componentName:String = null;
var axis:Array = null;
var targetXML:XML = data.@target[0];
if(targetXML == null)
{
return;
}
var targetParts:Array = targetXML.toString().split("/");
var sid:String = targetParts.pop();
var sidParts:Array = sid.split(".");
var sidPartsCount:int = int(sidParts.length);
var node:DaeNode = this.node;
if(node == null)
{
return;
}
this.animName = node.animName;
var children:XMLList = node.data.children();
for(var i:int = 0,var count:int = int(children.length()); i < count; )
{
child = children[i];
attr = child.@sid[0];
if(attr != null && attr.toString() == sidParts[0])
{
transformationXML = child;
break;
}
i++;
}
var transformationName:String = transformationXML != null ? transformationXML.localName() as String : null;
if(sidPartsCount > 1)
{
componentName = sidParts[1];
loop1:
switch(transformationName)
{
case "translate":
switch(componentName)
{
case "X":
this.§_-dS§ = PARAM_TRANSLATE_X;
break loop1;
case "Y":
this.§_-dS§ = PARAM_TRANSLATE_Y;
break loop1;
case "Z":
this.§_-dS§ = PARAM_TRANSLATE_Z;
}
break;
case "rotate":
axis = parseNumbersArray(transformationXML);
switch(axis.indexOf(1))
{
case 0:
this.§_-dS§ = PARAM_ROTATION_X;
break loop1;
case 1:
this.§_-dS§ = PARAM_ROTATION_Y;
break loop1;
case 2:
this.§_-dS§ = PARAM_ROTATION_Z;
}
break;
case "scale":
switch(componentName)
{
case "X":
this.§_-dS§ = PARAM_SCALE_X;
break loop1;
case "Y":
this.§_-dS§ = PARAM_SCALE_Y;
break loop1;
case "Z":
this.§_-dS§ = PARAM_SCALE_Z;
}
}
}
else
{
switch(transformationName)
{
case "translate":
this.§_-dS§ = PARAM_TRANSLATE;
break;
case "scale":
this.§_-dS§ = PARAM_SCALE;
break;
case "matrix":
this.§_-dS§ = PARAM_MATRIX;
}
}
}
private function parseSampler() : void
{
var track:§_-kB§ = null;
var toRad:Number = NaN;
var key:NumberKey = null;
var sampler:DaeSampler = document.findSampler(data.@source[0]);
if(sampler != null)
{
sampler.parse();
if(this.§_-dS§ == PARAM_MATRIX)
{
this.tracks = Vector.<§_-Np§>([sampler.parseTransformationTrack(this.animName)]);
return;
}
if(this.§_-dS§ == PARAM_TRANSLATE)
{
this.tracks = sampler.parsePointsTracks(this.animName,"x","y","z");
return;
}
if(this.§_-dS§ == PARAM_SCALE)
{
this.tracks = sampler.parsePointsTracks(this.animName,"scaleX","scaleY","scaleZ");
return;
}
if(this.§_-dS§ == PARAM_ROTATION_X || this.§_-dS§ == PARAM_ROTATION_Y || this.§_-dS§ == PARAM_ROTATION_Z)
{
track = sampler.parseNumbersTrack(this.animName,this.§_-dS§);
toRad = Math.PI / 180;
for(key = track.alternativa3d::_-ku; key != null; key = key.alternativa3d::next)
{
key.alternativa3d::_-4O *= toRad;
}
this.tracks = Vector.<§_-Np§>([track]);
return;
}
if(this.§_-dS§ == PARAM_TRANSLATE_X || this.§_-dS§ == PARAM_TRANSLATE_Y || this.§_-dS§ == PARAM_TRANSLATE_Z || this.§_-dS§ == PARAM_SCALE_X || this.§_-dS§ == PARAM_SCALE_Y || this.§_-dS§ == PARAM_SCALE_Z)
{
this.tracks = Vector.<§_-Np§>([sampler.parseNumbersTrack(this.animName,this.§_-dS§)]);
}
}
else
{
document.logger.logNotFoundError(data.@source[0]);
}
}
}
}

View File

@@ -0,0 +1,634 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.*;
import alternativa.engine3d.animation.§_-FA§;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.core.VertexAttributes;
import alternativa.engine3d.loaders.ParserMaterial;
import alternativa.engine3d.objects.Joint;
import alternativa.engine3d.objects.Skin;
import alternativa.engine3d.resources.Geometry;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Endian;
use namespace collada;
use namespace alternativa3d;
public class DaeController extends DaeElement
{
private var §_-A6§:Vector.<Vector.<Number>>;
private var §_-2j§:Array;
private var indices:Array;
private var §_-4h§:DaeInput;
private var §_-NK§:DaeInput;
private var §_-5O§:int;
private var geometry:Geometry;
private var primitives:Vector.<DaePrimitive>;
private var §_-1U§:int = 0;
private var §_-I§:Vector.<Number>;
public function DaeController(data:XML, document:DaeDocument)
{
super(data,document);
}
private function get daeGeometry() : DaeGeometry
{
var geom:DaeGeometry = document.findGeometry(data.skin.@source[0]);
if(geom == null)
{
document.logger.logNotFoundError(data.@source[0]);
}
return geom;
}
override protected function parseImplementation() : Boolean
{
var i:int = 0;
var j:int = 0;
var count:int = 0;
var vertices:Vector.<DaeVertex> = null;
var source:Geometry = null;
var localMaxJointsPerVertex:int = 0;
var attributes:Array = null;
var numSourceAttributes:int = 0;
var index:int = 0;
var numMappings:int = 0;
var sourceData:ByteArray = null;
var data:ByteArray = null;
var byteArray:ByteArray = null;
var attribute:int = 0;
var vertexWeightsXML:XML = this.data.skin.vertex_weights[0];
if(vertexWeightsXML == null)
{
return false;
}
var vcountsXML:XML = vertexWeightsXML.vcount[0];
if(vcountsXML == null)
{
return false;
}
this.§_-2j§ = parseIntsArray(vcountsXML);
var indicesXML:XML = vertexWeightsXML.v[0];
if(indicesXML == null)
{
return false;
}
this.indices = parseIntsArray(indicesXML);
this.parseInputs();
this.parseJointsBindMatrices();
for(i = 0; i < this.§_-2j§.length; )
{
count = int(this.§_-2j§[i]);
if(this.§_-1U§ < count)
{
this.§_-1U§ = count;
}
i++;
}
var geom:DaeGeometry = this.daeGeometry;
this.§_-I§ = this.getBindShapeMatrix();
if(geom != null)
{
geom.parse();
vertices = geom.§_-FV§;
source = geom.geometry;
localMaxJointsPerVertex = this.§_-1U§ % 2 != 0 ? this.§_-1U§ + 1 : this.§_-1U§;
this.geometry = new Geometry();
this.geometry.alternativa3d::_indices = source.alternativa3d::_indices.slice();
attributes = source.getVertexStreamAttributes(0);
numSourceAttributes = int(attributes.length);
index = numSourceAttributes;
for(i = 0; i < localMaxJointsPerVertex; i += 2)
{
attribute = int(VertexAttributes.JOINTS[int(i / 2)]);
attributes[int(index++)] = attribute;
attributes[int(index++)] = attribute;
attributes[int(index++)] = attribute;
attributes[int(index++)] = attribute;
}
numMappings = int(attributes.length);
sourceData = source.alternativa3d::_vertexStreams[0].data;
data = new ByteArray();
data.endian = Endian.LITTLE_ENDIAN;
data.length = 4 * numMappings * source.alternativa3d::_numVertices;
sourceData.position = 0;
for(i = 0; i < source.alternativa3d::_numVertices; i++)
{
data.position = 4 * numMappings * i;
for(j = 0; j < numSourceAttributes; j++)
{
data.writeFloat(sourceData.readFloat());
}
}
byteArray = this.createVertexBuffer(vertices,localMaxJointsPerVertex);
byteArray.position = 0;
for(i = 0; i < source.alternativa3d::_numVertices; i++)
{
data.position = 4 * (numMappings * i + numSourceAttributes);
for(j = 0; j < localMaxJointsPerVertex; j++)
{
data.writeFloat(byteArray.readFloat());
data.writeFloat(byteArray.readFloat());
}
}
this.geometry.addVertexStream(attributes);
this.geometry.alternativa3d::_vertexStreams[0].data = data;
this.geometry.alternativa3d::_numVertices = source.alternativa3d::_numVertices;
this.transformVertices(this.geometry);
this.primitives = geom.primitives;
}
return true;
}
private function transformVertices(geometry:Geometry) : void
{
var x:Number = NaN;
var y:Number = NaN;
var z:Number = NaN;
var data:ByteArray = geometry.alternativa3d::_vertexStreams[0].data;
var numMappings:int = int(geometry.alternativa3d::_vertexStreams[0].attributes.length);
for(var i:int = 0; i < geometry.alternativa3d::_numVertices; i++)
{
data.position = 4 * numMappings * i;
x = Number(data.readFloat());
y = Number(data.readFloat());
z = Number(data.readFloat());
data.position -= 12;
data.writeFloat(x * this.§_-I§[0] + y * this.§_-I§[1] + z * this.§_-I§[2] + this.§_-I§[3]);
data.writeFloat(x * this.§_-I§[4] + y * this.§_-I§[5] + z * this.§_-I§[6] + this.§_-I§[7]);
data.writeFloat(x * this.§_-I§[8] + y * this.§_-I§[9] + z * this.§_-I§[10] + this.§_-I§[11]);
}
}
private function createVertexBuffer(vertices:Vector.<DaeVertex>, localMaxJointsPerVertex:int) : ByteArray
{
var i:int = 0;
var count:int = 0;
var vertexOutIndices:Vector.<uint> = null;
var vertex:DaeVertex = null;
var vec:Vector.<uint> = null;
var jointsPerVertex:int = 0;
var j:int = 0;
var k:int = 0;
var index:int = 0;
var jointIndex:int = 0;
var weightIndex:int = 0;
var jointsOffset:int = this.§_-4h§.offset;
var weightsOffset:int = this.§_-NK§.offset;
var weightsSource:DaeSource = this.§_-NK§.prepareSource(1);
var weights:Vector.<Number> = weightsSource.numbers;
var weightsStride:int = weightsSource.stride;
var verticesDict:Dictionary = new Dictionary();
var byteArray:ByteArray = new ByteArray();
byteArray.length = vertices.length * localMaxJointsPerVertex * 8;
byteArray.endian = Endian.LITTLE_ENDIAN;
for(i = 0,count = int(vertices.length); i < count; i++)
{
vertex = vertices[i];
if(vertex != null)
{
vec = verticesDict[vertex.§_-Eq§];
if(vec == null)
{
vec = verticesDict[vertex.§_-Eq§] = new Vector.<uint>();
}
vec.push(vertex.§_-AR§);
}
}
var vertexIndex:int = 0;
for(i = 0,count = int(this.§_-2j§.length); i < count; i++)
{
jointsPerVertex = int(this.§_-2j§[i]);
vertexOutIndices = verticesDict[i];
for(j = 0; j < vertexOutIndices.length; j++)
{
byteArray.position = vertexOutIndices[j] * localMaxJointsPerVertex * 8;
for(k = 0; k < jointsPerVertex; k++)
{
index = this.§_-5O§ * (vertexIndex + k);
jointIndex = int(this.indices[int(index + jointsOffset)]);
if(jointIndex >= 0)
{
byteArray.writeFloat(jointIndex * 3);
weightIndex = int(this.indices[int(index + weightsOffset)]);
byteArray.writeFloat(weights[int(weightsStride * weightIndex)]);
}
else
{
byteArray.position += 8;
}
}
}
vertexIndex += jointsPerVertex;
}
byteArray.position = 0;
return byteArray;
}
private function parseInputs() : void
{
var input:DaeInput = null;
var semantic:String = null;
var offset:int = 0;
var inputsList:XMLList = data.skin.vertex_weights.input;
var maxInputOffset:int = 0;
for(var i:int = 0,var count:int = int(inputsList.length()); i < count; offset = input.offset,maxInputOffset = offset > maxInputOffset ? offset : maxInputOffset,i++)
{
input = new DaeInput(inputsList[i],document);
semantic = input.semantic;
if(semantic == null)
{
continue;
}
switch(semantic)
{
case "JOINT":
if(this.§_-4h§ == null)
{
this.§_-4h§ = input;
}
break;
case "WEIGHT":
if(this.§_-NK§ == null)
{
this.§_-NK§ = input;
}
break;
}
}
this.§_-5O§ = maxInputOffset + 1;
}
private function parseJointsBindMatrices() : void
{
var jointsXML:XML = null;
var jointsSource:DaeSource = null;
var stride:int = 0;
var count:int = 0;
var i:int = 0;
var index:int = 0;
var matrix:Vector.<Number> = null;
var j:int = 0;
jointsXML = data.skin.joints.input.(@semantic == "INV_BIND_MATRIX")[0];
if(jointsXML != null)
{
jointsSource = document.findSource(jointsXML.@source[0]);
if(jointsSource != null)
{
if(jointsSource.parse() && jointsSource.numbers != null && jointsSource.stride >= 16)
{
stride = jointsSource.stride;
count = jointsSource.numbers.length / stride;
this.§_-A6§ = new Vector.<Vector.<Number>>(count);
for(i = 0; i < count; i++)
{
index = stride * i;
matrix = new Vector.<Number>(16);
this.§_-A6§[i] = matrix;
for(j = 0; j < 16; j++)
{
matrix[j] = jointsSource.numbers[int(index + j)];
}
}
}
}
else
{
document.logger.logNotFoundError(jointsXML.@source[0]);
}
}
}
public function parseSkin(materials:Object, topmostJoints:Vector.<DaeNode>, skeletons:Vector.<DaeNode>) : DaeObject
{
var numJoints:int = 0;
var skin:Skin = null;
var joints:Vector.<DaeObject> = null;
var i:int = 0;
var p:DaePrimitive = null;
var instanceMaterial:DaeInstanceMaterial = null;
var material:ParserMaterial = null;
var daeMaterial:DaeMaterial = null;
var skinXML:XML = data.skin[0];
if(skinXML != null)
{
this.§_-I§ = this.getBindShapeMatrix();
numJoints = int(this.§_-A6§.length);
skin = new Skin(this.§_-1U§,numJoints);
skin.geometry = this.geometry;
joints = this.addJointsToSkin(skin,topmostJoints,this.findNodes(skeletons));
this.setJointsBindMatrices(joints);
skin.§_-WA§ = this.collectRenderedJoints(joints,numJoints);
if(this.primitives != null)
{
for(i = 0; i < this.primitives.length; i++)
{
p = this.primitives[i];
instanceMaterial = materials[p.materialSymbol];
if(instanceMaterial != null)
{
daeMaterial = instanceMaterial.material;
if(daeMaterial != null)
{
daeMaterial.parse();
material = daeMaterial.material;
daeMaterial.used = true;
}
}
skin.addSurface(material,p.indexBegin,p.numTriangles);
}
}
return new DaeObject(skin,this.mergeJointsClips(skin,joints));
}
return null;
}
private function collectRenderedJoints(joints:Vector.<DaeObject>, numJoints:int) : Vector.<Joint>
{
var result:Vector.<Joint> = new Vector.<Joint>();
for(var i:int = 0; i < numJoints; i++)
{
result[i] = Joint(joints[i].object);
}
return result;
}
private function mergeJointsClips(skin:Skin, joints:Vector.<DaeObject>) : §_-FA§
{
var animatedObject:DaeObject = null;
var clip:§_-FA§ = null;
var object:Object3D = null;
var t:int = 0;
if(!this.hasJointsAnimation(joints))
{
return null;
}
var result:§_-FA§ = new §_-FA§();
var resultObjects:Array = [skin];
for(var i:int = 0,var count:int = int(joints.length); i < count; i++)
{
animatedObject = joints[i];
clip = animatedObject.animation;
if(clip != null)
{
for(t = 0; t < clip.numTracks; t++)
{
result.§_-nn§(clip.§_-QA§(t));
}
}
else
{
result.§_-nn§(animatedObject.jointNode.createStaticTransformTrack());
}
object = animatedObject.object;
object.name = animatedObject.jointNode.animName;
resultObjects.push(object);
}
result.alternativa3d::_-Kq = resultObjects;
return result;
}
private function hasJointsAnimation(joints:Vector.<DaeObject>) : Boolean
{
var object:DaeObject = null;
for(var i:int = 0,var count:int = int(joints.length); i < count; )
{
object = joints[i];
if(object.animation != null)
{
return true;
}
i++;
}
return false;
}
private function setJointsBindMatrices(animatedJoints:Vector.<DaeObject>) : void
{
var animatedJoint:DaeObject = null;
var bindMatrix:Vector.<Number> = null;
for(var i:int = 0,var count:int = int(this.§_-A6§.length); i < count; i++)
{
animatedJoint = animatedJoints[i];
bindMatrix = this.§_-A6§[i];
Joint(animatedJoint.object).alternativa3d::setBindPoseMatrix(bindMatrix);
}
}
private function addJointsToSkin(skin:Skin, topmostJoints:Vector.<DaeNode>, nodes:Vector.<DaeNode>) : Vector.<DaeObject>
{
var i:int = 0;
var topmostJoint:DaeNode = null;
var animatedJoint:DaeObject = null;
var nodesDictionary:Dictionary = new Dictionary();
var count:int = int(nodes.length);
for(i = 0; i < count; i++)
{
nodesDictionary[nodes[i]] = i;
}
var animatedJoints:Vector.<DaeObject> = new Vector.<DaeObject>(count);
var numTopmostJoints:int = int(topmostJoints.length);
for(i = 0; i < numTopmostJoints; i++)
{
topmostJoint = topmostJoints[i];
animatedJoint = this.addRootJointToSkin(skin,topmostJoint,animatedJoints,nodesDictionary);
this.addJointChildren(Joint(animatedJoint.object),animatedJoints,topmostJoint,nodesDictionary);
}
return animatedJoints;
}
private function addRootJointToSkin(skin:Skin, node:DaeNode, animatedJoints:Vector.<DaeObject>, nodes:Dictionary) : DaeObject
{
var joint:Joint = new Joint();
joint.name = cloneString(node.name);
skin.addChild(joint);
var animatedJoint:DaeObject = node.applyAnimation(node.applyTransformations(joint));
animatedJoint.jointNode = node;
if(node in nodes)
{
animatedJoints[nodes[node]] = animatedJoint;
}
else
{
animatedJoints.push(animatedJoint);
}
return animatedJoint;
}
private function addJointChildren(parent:Joint, animatedJoints:Vector.<DaeObject>, parentNode:DaeNode, nodes:Dictionary) : void
{
var object:DaeObject = null;
var child:DaeNode = null;
var joint:Joint = null;
var children:Vector.<DaeNode> = parentNode.nodes;
for(var i:int = 0,var count:int = int(children.length); i < count; )
{
child = children[i];
if(child in nodes)
{
joint = new Joint();
joint.name = cloneString(child.name);
object = child.applyAnimation(child.applyTransformations(joint));
object.jointNode = child;
animatedJoints[nodes[child]] = object;
parent.addChild(joint);
this.addJointChildren(joint,animatedJoints,child,nodes);
}
else if(this.hasJointInDescendants(child,nodes))
{
joint = new Joint();
joint.name = cloneString(child.name);
object = child.applyAnimation(child.applyTransformations(joint));
object.jointNode = child;
animatedJoints.push(object);
parent.addChild(joint);
this.addJointChildren(joint,animatedJoints,child,nodes);
}
i++;
}
}
private function hasJointInDescendants(parentNode:DaeNode, nodes:Dictionary) : Boolean
{
var child:DaeNode = null;
var children:Vector.<DaeNode> = parentNode.nodes;
for(var i:int = 0,var count:int = int(children.length); i < count; )
{
child = children[i];
if(child in nodes || this.hasJointInDescendants(child,nodes))
{
return true;
}
i++;
}
return false;
}
private function getBindShapeMatrix() : Vector.<Number>
{
var matrix:Array = null;
var i:int = 0;
var matrixXML:XML = data.skin.bind_shape_matrix[0];
var res:Vector.<Number> = new Vector.<Number>(16,true);
if(matrixXML != null)
{
matrix = parseStringArray(matrixXML);
for(i = 0; i < matrix.length; i++)
{
res[i] = Number(matrix[i]);
}
}
return res;
}
private function isRootJointNode(node:DaeNode, nodes:Dictionary) : Boolean
{
for(var parent:DaeNode = node.parent; parent != null; )
{
if(parent in nodes)
{
return false;
}
parent = parent.parent;
}
return true;
}
public function findRootJointNodes(skeletons:Vector.<DaeNode>) : Vector.<DaeNode>
{
var nodesDictionary:Dictionary = null;
var rootNodes:Vector.<DaeNode> = null;
var node:DaeNode = null;
var nodes:Vector.<DaeNode> = this.findNodes(skeletons);
var i:int = 0;
var count:int = int(nodes.length);
if(count > 0)
{
nodesDictionary = new Dictionary();
for(i = 0; i < count; i++)
{
nodesDictionary[nodes[i]] = i;
}
rootNodes = new Vector.<DaeNode>();
for(i = 0; i < count; )
{
node = nodes[i];
if(this.isRootJointNode(node,nodesDictionary))
{
rootNodes.push(node);
}
i++;
}
return rootNodes;
}
return null;
}
private function findNode(nodeName:String, skeletons:Vector.<DaeNode>) : DaeNode
{
var node:DaeNode = null;
var count:int = int(skeletons.length);
for(var i:int = 0; i < count; )
{
node = skeletons[i].getNodeBySid(nodeName);
if(node != null)
{
return node;
}
i++;
}
return null;
}
private function findNodes(skeletons:Vector.<DaeNode>) : Vector.<DaeNode>
{
var jointsXML:XML = null;
var jointsSource:DaeSource = null;
var stride:int = 0;
var count:int = 0;
var nodes:Vector.<DaeNode> = null;
var i:int = 0;
var node:DaeNode = null;
jointsXML = data.skin.joints.input.(@semantic == "JOINT")[0];
if(jointsXML != null)
{
jointsSource = document.findSource(jointsXML.@source[0]);
if(jointsSource != null)
{
if(jointsSource.parse() && jointsSource.names != null)
{
stride = jointsSource.stride;
count = jointsSource.names.length / stride;
nodes = new Vector.<DaeNode>(count);
for(i = 0; i < count; i++)
{
node = this.findNode(jointsSource.names[int(stride * i)],skeletons);
if(node == null)
{
}
nodes[i] = node;
}
return nodes;
}
}
else
{
document.logger.logNotFoundError(jointsXML.@source[0]);
}
}
return null;
}
}
}

View File

@@ -0,0 +1,287 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeDocument
{
public var scene:DaeVisualScene;
private var data:XML;
internal var §_-DR§:Object;
internal var arrays:Object;
internal var vertices:Object;
public var geometries:Object;
internal var nodes:Object;
internal var lights:Object;
internal var images:Object;
internal var effects:Object;
internal var §_-DW§:Object;
internal var §_-GB§:Object;
public var materials:Object;
internal var logger:DaeLogger;
public var versionMajor:uint;
public var versionMinor:uint;
public var unitScaleFactor:Number = 1;
public function DaeDocument(document:XML, units:Number)
{
super();
this.data = document;
var versionComponents:Array = this.data.@version[0].toString().split(/[.,]/);
this.versionMajor = parseInt(versionComponents[1],10);
this.versionMinor = parseInt(versionComponents[2],10);
var colladaUnit:Number = Number(parseFloat(this.data.asset[0].unit[0].@meter));
if(units > 0)
{
this.unitScaleFactor = colladaUnit / units;
}
else
{
this.unitScaleFactor = 1;
}
this.logger = new DaeLogger();
this.constructStructures();
this.constructScenes();
this.registerInstanceControllers();
this.constructAnimations();
}
private function getLocalID(url:XML) : String
{
var path:String = url.toString();
if(path.charAt(0) == "#")
{
return path.substr(1);
}
this.logger.logExternalError(url);
return null;
}
private function constructStructures() : void
{
var element:XML = null;
var source:DaeSource = null;
var light:DaeLight = null;
var image:DaeImage = null;
var effect:DaeEffect = null;
var material:DaeMaterial = null;
var geom:DaeGeometry = null;
var controller:DaeController = null;
var node:DaeNode = null;
this.§_-DR§ = new Object();
this.arrays = new Object();
for each(element in this.data..source)
{
source = new DaeSource(element,this);
if(source.id != null)
{
this.§_-DR§[source.id] = source;
}
}
this.lights = new Object();
for each(element in this.data.library_lights.light)
{
light = new DaeLight(element,this);
if(light.id != null)
{
this.lights[light.id] = light;
}
}
this.images = new Object();
for each(element in this.data.library_images.image)
{
image = new DaeImage(element,this);
if(image.id != null)
{
this.images[image.id] = image;
}
}
this.effects = new Object();
for each(element in this.data.library_effects.effect)
{
effect = new DaeEffect(element,this);
if(effect.id != null)
{
this.effects[effect.id] = effect;
}
}
this.materials = new Object();
for each(element in this.data.library_materials.material)
{
material = new DaeMaterial(element,this);
if(material.id != null)
{
this.materials[material.id] = material;
}
}
this.geometries = new Object();
this.vertices = new Object();
for each(element in this.data.library_geometries.geometry)
{
geom = new DaeGeometry(element,this);
if(geom.id != null)
{
this.geometries[geom.id] = geom;
}
}
this.§_-DW§ = new Object();
for each(element in this.data.library_controllers.controller)
{
controller = new DaeController(element,this);
if(controller.id != null)
{
this.§_-DW§[controller.id] = controller;
}
}
this.nodes = new Object();
for each(element in this.data.library_nodes.node)
{
node = new DaeNode(element,this);
if(node.id != null)
{
this.nodes[node.id] = node;
}
}
}
private function constructScenes() : void
{
var element:XML = null;
var vscene:DaeVisualScene = null;
var vsceneURL:XML = this.data.scene.instance_visual_scene.@url[0];
var vsceneID:String = this.getLocalID(vsceneURL);
for each(element in this.data.library_visual_scenes.visual_scene)
{
vscene = new DaeVisualScene(element,this);
if(vscene.id == vsceneID)
{
this.scene = vscene;
}
}
if(vsceneID != null && this.scene == null)
{
this.logger.logNotFoundError(vsceneURL);
}
}
private function registerInstanceControllers() : void
{
var i:int = 0;
var count:int = 0;
if(this.scene != null)
{
for(i = 0,count = int(this.scene.nodes.length); i < count; i++)
{
this.scene.nodes[i].registerInstanceControllers();
}
}
}
private function constructAnimations() : void
{
var element:XML = null;
var sampler:DaeSampler = null;
var channel:DaeChannel = null;
var node:DaeNode = null;
this.§_-GB§ = new Object();
for each(element in this.data.library_animations..sampler)
{
sampler = new DaeSampler(element,this);
if(sampler.id != null)
{
this.§_-GB§[sampler.id] = sampler;
}
}
for each(element in this.data.library_animations..channel)
{
channel = new DaeChannel(element,this);
node = channel.node;
if(node != null)
{
node.addChannel(channel);
}
}
}
public function findArray(url:XML) : DaeArray
{
return this.arrays[this.getLocalID(url)];
}
public function findSource(url:XML) : DaeSource
{
return this.§_-DR§[this.getLocalID(url)];
}
public function findLight(url:XML) : DaeLight
{
return this.lights[this.getLocalID(url)];
}
public function findImage(url:XML) : DaeImage
{
return this.images[this.getLocalID(url)];
}
public function findImageByID(id:String) : DaeImage
{
return this.images[id];
}
public function findEffect(url:XML) : DaeEffect
{
return this.effects[this.getLocalID(url)];
}
public function findMaterial(url:XML) : DaeMaterial
{
return this.materials[this.getLocalID(url)];
}
public function findVertices(url:XML) : DaeVertices
{
return this.vertices[this.getLocalID(url)];
}
public function findGeometry(url:XML) : DaeGeometry
{
return this.geometries[this.getLocalID(url)];
}
public function findNode(url:XML) : DaeNode
{
return this.nodes[this.getLocalID(url)];
}
public function findNodeByID(id:String) : DaeNode
{
return this.nodes[id];
}
public function findController(url:XML) : DaeController
{
return this.§_-DW§[this.getLocalID(url)];
}
public function findSampler(url:XML) : DaeSampler
{
return this.§_-GB§[this.getLocalID(url)];
}
}
}

View File

@@ -0,0 +1,255 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.loaders.ParserMaterial;
import alternativa.engine3d.resources.ExternalTextureResource;
use namespace collada;
public class DaeEffect extends DaeElement
{
public static var commonAlways:Boolean = false;
private var §_-3x§:Object;
private var §_-El§:Object;
private var §_-3H§:Object;
private var diffuse:DaeEffectParam;
private var ambient:DaeEffectParam;
private var transparent:DaeEffectParam;
private var transparency:DaeEffectParam;
private var bump:DaeEffectParam;
private var reflective:DaeEffectParam;
private var emission:DaeEffectParam;
private var specular:DaeEffectParam;
public function DaeEffect(data:XML, document:DaeDocument)
{
super(data,document);
this.constructImages();
}
private function constructImages() : void
{
var element:XML = null;
var image:DaeImage = null;
var list:XMLList = data..image;
for each(element in list)
{
image = new DaeImage(element,document);
if(image.id != null)
{
document.images[image.id] = image;
}
}
}
override protected function parseImplementation() : Boolean
{
var shader:XML;
var element:XML = null;
var param:DaeParam = null;
var technique:XML = null;
var bumpXML:XML = null;
var diffuseXML:XML = null;
var transparentXML:XML = null;
var transparencyXML:XML = null;
var ambientXML:XML = null;
var reflectiveXML:XML = null;
var emissionXML:XML = null;
var specularXML:XML = null;
this.§_-3x§ = new Object();
for each(element in data.newparam)
{
param = new DaeParam(element,document);
this.§_-3x§[param.sid] = param;
}
this.§_-El§ = new Object();
for each(element in data.profile_COMMON.newparam)
{
param = new DaeParam(element,document);
this.§_-El§[param.sid] = param;
}
this.§_-3H§ = new Object();
technique = data.profile_COMMON.technique[0];
if(technique != null)
{
for each(element in technique.newparam)
{
param = new DaeParam(element,document);
this.§_-3H§[param.sid] = param;
}
}
shader = data.profile_COMMON.technique.*.(localName() == "constant" || localName() == "lambert" || localName() == "phong" || localName() == "blinn")[0];
if(shader != null)
{
diffuseXML = null;
if(shader.localName() == "constant")
{
diffuseXML = shader.emission[0];
}
else
{
diffuseXML = shader.diffuse[0];
emissionXML = shader.emission[0];
if(emissionXML != null)
{
this.emission = new DaeEffectParam(emissionXML,this);
}
}
if(diffuseXML != null)
{
this.diffuse = new DaeEffectParam(diffuseXML,this);
}
if(shader.localName() == "phong" || shader.localName() == "blinn")
{
specularXML = shader.specular[0];
if(specularXML != null)
{
this.specular = new DaeEffectParam(specularXML,this);
}
}
transparentXML = shader.transparent[0];
if(transparentXML != null)
{
this.transparent = new DaeEffectParam(transparentXML,this);
}
transparencyXML = shader.transparency[0];
if(transparencyXML != null)
{
this.transparency = new DaeEffectParam(transparencyXML,this);
}
ambientXML = shader.ambient[0];
if(ambientXML != null)
{
this.ambient = new DaeEffectParam(ambientXML,this);
}
reflectiveXML = shader.reflective[0];
if(reflectiveXML != null)
{
this.reflective = new DaeEffectParam(reflectiveXML,this);
}
}
bumpXML = data.profile_COMMON.technique.extra.technique.(Boolean(hasOwnProperty("@profile")) && @profile == "OpenCOLLADA3dsMax").bump[0];
if(bumpXML != null)
{
this.bump = new DaeEffectParam(bumpXML,this);
}
return true;
}
internal function getParam(name:String, setparams:Object) : DaeParam
{
var param:DaeParam = setparams[name];
if(param != null)
{
return param;
}
param = this.§_-3H§[name];
if(param != null)
{
return param;
}
param = this.§_-El§[name];
if(param != null)
{
return param;
}
return this.§_-3x§[name];
}
private function float4ToUint(value:Array, alpha:Boolean = true) : uint
{
var a:uint = 0;
var r:uint = value[0] * 255;
var g:uint = value[1] * 255;
var b:uint = value[2] * 255;
if(alpha)
{
a = value[3] * 255;
return a << 24 | r << 16 | g << 8 | b;
}
return r << 16 | g << 8 | b;
}
public function getMaterial(setparams:Object) : ParserMaterial
{
var material:ParserMaterial = null;
if(this.diffuse != null)
{
material = new ParserMaterial();
if(Boolean(this.diffuse))
{
this.pushMap(material,this.diffuse,setparams);
}
if(this.specular != null)
{
this.pushMap(material,this.specular,setparams);
}
if(this.emission != null)
{
this.pushMap(material,this.emission,setparams);
}
if(this.transparency != null)
{
material.transparency = this.transparency.getFloat(setparams);
}
if(this.transparent != null)
{
this.pushMap(material,this.transparent,setparams);
}
if(this.bump != null)
{
this.pushMap(material,this.bump,setparams);
}
if(Boolean(this.ambient))
{
this.pushMap(material,this.ambient,setparams);
}
if(Boolean(this.reflective))
{
this.pushMap(material,this.reflective,setparams);
}
return material;
}
return null;
}
private function pushMap(material:ParserMaterial, param:DaeEffectParam, setparams:Object) : void
{
var _loc5_:DaeImage = null;
var color:Array = param.getColor(setparams);
if(color != null)
{
material.colors[cloneString(param.data.localName())] = this.float4ToUint(color,true);
}
else
{
_loc5_ = param.getImage(setparams);
if(_loc5_ != null)
{
material.textures[cloneString(param.data.localName())] = new ExternalTextureResource(cloneString(_loc5_.init_from));
}
}
}
public function get mainTexCoords() : String
{
var channel:String = null;
channel = channel == null && this.diffuse != null ? this.diffuse.texCoord : channel;
channel = channel == null && this.transparent != null ? this.transparent.texCoord : channel;
channel = channel == null && this.bump != null ? this.bump.texCoord : channel;
channel = channel == null && this.emission != null ? this.emission.texCoord : channel;
return channel == null && this.specular != null ? this.specular.texCoord : channel;
}
}
}

View File

@@ -0,0 +1,100 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeEffectParam extends DaeElement
{
private var effect:DaeEffect;
public function DaeEffectParam(data:XML, effect:DaeEffect)
{
super(data,effect.document);
this.effect = effect;
}
public function getFloat(setparams:Object) : Number
{
var param:DaeParam = null;
var floatXML:XML = data.float[0];
if(floatXML != null)
{
return parseNumber(floatXML);
}
var paramRef:XML = data.param.@ref[0];
if(paramRef != null)
{
param = this.effect.getParam(paramRef.toString(),setparams);
if(param != null)
{
return param.getFloat();
}
}
return NaN;
}
public function getColor(setparams:Object) : Array
{
var param:DaeParam = null;
var colorXML:XML = data.color[0];
if(colorXML != null)
{
return parseNumbersArray(colorXML);
}
var paramRef:XML = data.param.@ref[0];
if(paramRef != null)
{
param = this.effect.getParam(paramRef.toString(),setparams);
if(param != null)
{
return param.getFloat4();
}
}
return null;
}
private function get texture() : String
{
var attr:XML = data.texture.@texture[0];
return attr == null ? null : attr.toString();
}
public function getSampler(setparams:Object) : DaeParam
{
var sid:String = this.texture;
if(sid != null)
{
return this.effect.getParam(sid,setparams);
}
return null;
}
public function getImage(setparams:Object) : DaeImage
{
var surfaceSID:String = null;
var surface:DaeParam = null;
var sampler:DaeParam = this.getSampler(setparams);
if(sampler != null)
{
surfaceSID = sampler.surfaceSID;
if(surfaceSID != null)
{
surface = this.effect.getParam(surfaceSID,setparams);
if(surface != null)
{
return surface.image;
}
return null;
}
return sampler.image;
}
return document.findImageByID(this.texture);
}
public function get texCoord() : String
{
var attr:XML = data.texture.@texcoord[0];
return attr == null ? null : attr.toString();
}
}
}

View File

@@ -0,0 +1,109 @@
package alternativa.engine3d.loaders.collada
{
import flash.utils.ByteArray;
use namespace collada;
public class DaeElement
{
private static var _byteArray:ByteArray = new ByteArray();
public var document:DaeDocument;
public var data:XML;
private var §_-Ba§:int = -1;
public function DaeElement(data:XML, document:DaeDocument)
{
super();
this.document = document;
this.data = data;
}
public function cloneString(str:String) : String
{
if(str == null)
{
return null;
}
_byteArray.position = 0;
_byteArray.writeUTF(str);
_byteArray.position = 0;
return _byteArray.readUTF();
}
public function parse() : Boolean
{
if(this.§_-Ba§ < 0)
{
this.§_-Ba§ = this.parseImplementation() ? 1 : 0;
return this.§_-Ba§ != 0;
}
return this.§_-Ba§ != 0;
}
protected function parseImplementation() : Boolean
{
return true;
}
protected function parseStringArray(element:XML) : Array
{
return element.text().toString().split(/\s+/);
}
protected function parseNumbersArray(element:XML) : Array
{
var value:String = null;
var arr:Array = element.text().toString().split(/\s+/);
for(var i:int = 0,var count:int = int(arr.length); i < count; i++)
{
value = arr[i];
if(value.indexOf(",") != -1)
{
value = value.replace(/,/,".");
}
arr[i] = parseFloat(value);
}
return arr;
}
protected function parseIntsArray(element:XML) : Array
{
var value:String = null;
var arr:Array = element.text().toString().split(/\s+/);
for(var i:int = 0,var count:int = int(arr.length); i < count; i++)
{
value = arr[i];
arr[i] = parseInt(value,10);
}
return arr;
}
protected function parseNumber(element:XML) : Number
{
var value:String = element.toString().replace(/,/,".");
return parseFloat(value);
}
public function get id() : String
{
var idXML:XML = this.data.@id[0];
return idXML == null ? null : idXML.toString();
}
public function get sid() : String
{
var attr:XML = this.data.@sid[0];
return attr == null ? null : attr.toString();
}
public function get name() : String
{
var nameXML:XML = this.data.@name[0];
return nameXML == null ? null : nameXML.toString();
}
}
}

View File

@@ -0,0 +1,209 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.core.VertexAttributes;
import alternativa.engine3d.loaders.ParserMaterial;
import alternativa.engine3d.objects.Mesh;
import alternativa.engine3d.resources.Geometry;
import flash.utils.ByteArray;
import flash.utils.Endian;
use namespace collada;
use namespace alternativa3d;
public class DaeGeometry extends DaeElement
{
internal var §_-FV§:Vector.<DaeVertex>;
internal var primitives:Vector.<DaePrimitive>;
internal var geometry:Geometry;
private var vertices:DaeVertices;
public function DaeGeometry(data:XML, document:DaeDocument)
{
super(data,document);
this.constructVertices();
}
private function constructVertices() : void
{
var verticesXML:XML = data.mesh.vertices[0];
if(verticesXML != null)
{
this.vertices = new DaeVertices(verticesXML,document);
document.vertices[this.vertices.id] = this.vertices;
}
}
override protected function parseImplementation() : Boolean
{
var numVertices:int = 0;
var i:int = 0;
var p:DaePrimitive = null;
var channels:uint = 0;
var attributes:Array = null;
var index:int = 0;
var data:ByteArray = null;
var numMappings:int = 0;
var vertex:DaeVertex = null;
var j:int = 0;
if(this.vertices != null)
{
this.parsePrimitives();
this.vertices.parse();
numVertices = this.vertices.§_-E6§.numbers.length / this.vertices.§_-E6§.stride;
this.geometry = new Geometry();
this.§_-FV§ = new Vector.<DaeVertex>(numVertices);
channels = 0;
for(i = 0; i < this.primitives.length; )
{
p = this.primitives[i];
p.parse();
if(p.verticesEquals(this.vertices))
{
numVertices = int(this.§_-FV§.length);
channels |= p.fillGeometry(this.geometry,this.§_-FV§);
}
i++;
}
attributes = new Array(3);
attributes[0] = VertexAttributes.POSITION;
attributes[1] = VertexAttributes.POSITION;
attributes[2] = VertexAttributes.POSITION;
index = 3;
if(Boolean(channels & DaePrimitive.NORMALS))
{
var _loc11_:* = index++;
attributes[_loc11_] = VertexAttributes.NORMAL;
var _loc12_:* = index++;
attributes[_loc12_] = VertexAttributes.NORMAL;
var _loc13_:* = index++;
attributes[_loc13_] = VertexAttributes.NORMAL;
}
if(Boolean(channels & DaePrimitive.TANGENT4))
{
_loc11_ = index++;
attributes[_loc11_] = VertexAttributes.TANGENT4;
_loc12_ = index++;
attributes[_loc12_] = VertexAttributes.TANGENT4;
_loc13_ = index++;
attributes[_loc13_] = VertexAttributes.TANGENT4;
var _loc14_:* = index++;
attributes[_loc14_] = VertexAttributes.TANGENT4;
}
for(i = 0; i < 8; )
{
if(Boolean(channels & DaePrimitive.TEXCOORDS[i]))
{
_loc11_ = index++;
attributes[_loc11_] = VertexAttributes.TEXCOORDS[i];
_loc12_ = index++;
attributes[_loc12_] = VertexAttributes.TEXCOORDS[i];
}
i++;
}
this.geometry.addVertexStream(attributes);
numVertices = int(this.§_-FV§.length);
data = new ByteArray();
data.endian = Endian.LITTLE_ENDIAN;
numMappings = int(attributes.length);
data.length = 4 * numMappings * numVertices;
for(i = 0; i < numVertices; )
{
vertex = this.§_-FV§[i];
if(vertex != null)
{
data.position = 4 * numMappings * i;
data.writeFloat(vertex.x);
data.writeFloat(vertex.y);
data.writeFloat(vertex.z);
if(vertex.normal != null)
{
data.writeFloat(vertex.normal.x);
data.writeFloat(vertex.normal.y);
data.writeFloat(vertex.normal.z);
}
if(vertex.§_-hC§ != null)
{
data.writeFloat(vertex.§_-hC§.x);
data.writeFloat(vertex.§_-hC§.y);
data.writeFloat(vertex.§_-hC§.z);
data.writeFloat(vertex.§_-hC§.w);
}
for(j = 0; j < vertex.uvs.length; )
{
data.writeFloat(vertex.uvs[j]);
j++;
}
}
i++;
}
this.geometry.alternativa3d::_vertexStreams[0].data = data;
this.geometry.alternativa3d::_numVertices = numVertices;
return true;
}
return false;
}
private function parsePrimitives() : void
{
var child:XML = null;
var _loc5_:DaePrimitive = null;
this.primitives = new Vector.<DaePrimitive>();
var children:XMLList = data.mesh.children();
for(var i:int = 0,var count:int = int(children.length()); i < count; )
{
child = children[i];
switch(child.localName())
{
case "polygons":
case "polylist":
case "triangles":
case "trifans":
case "tristrips":
_loc5_ = new DaePrimitive(child,document);
this.primitives.push(_loc5_);
break;
}
i++;
}
}
public function parseMesh(materials:Object) : Mesh
{
var mesh:Mesh = null;
var i:int = 0;
var p:DaePrimitive = null;
var instanceMaterial:DaeInstanceMaterial = null;
var material:ParserMaterial = null;
var daeMaterial:DaeMaterial = null;
if(data.mesh.length() > 0)
{
mesh = new Mesh();
mesh.geometry = this.geometry;
for(i = 0; i < this.primitives.length; i++)
{
p = this.primitives[i];
instanceMaterial = materials[p.materialSymbol];
if(instanceMaterial != null)
{
daeMaterial = instanceMaterial.material;
if(daeMaterial != null)
{
daeMaterial.parse();
material = daeMaterial.material;
daeMaterial.used = true;
}
}
mesh.addSurface(material,p.indexBegin,p.numTriangles);
}
mesh.calculateBoundBox();
return mesh;
}
return null;
}
}
}

View File

@@ -0,0 +1,29 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeImage extends DaeElement
{
public function DaeImage(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get init_from() : String
{
var refXML:XML = null;
var element:XML = data.init_from[0];
if(element != null)
{
if(document.versionMajor > 4)
{
refXML = element.ref[0];
return refXML == null ? null : refXML.text().toString();
}
return element.text().toString();
}
return null;
}
}
}

View File

@@ -0,0 +1,54 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeInput extends DaeElement
{
public function DaeInput(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get semantic() : String
{
var attribute:XML = data.@semantic[0];
return attribute == null ? null : attribute.toString();
}
public function get source() : XML
{
return data.@source[0];
}
public function get offset() : int
{
var attr:XML = data.@offset[0];
return attr == null ? 0 : int(parseInt(attr.toString(),10));
}
public function get setNum() : int
{
var attr:XML = data.@set[0];
return attr == null ? 0 : int(parseInt(attr.toString(),10));
}
public function prepareSource(minComponents:int) : DaeSource
{
var source:DaeSource = document.findSource(this.source);
if(source != null)
{
source.parse();
if(source.numbers != null && source.stride >= minComponents)
{
return source;
}
}
else
{
document.logger.logNotFoundError(data.@source[0]);
}
return null;
}
}
}

View File

@@ -0,0 +1,122 @@
package alternativa.engine3d.loaders.collada
{
import flash.utils.Dictionary;
use namespace collada;
public class DaeInstanceController extends DaeElement
{
public var node:DaeNode;
public var topmostJoints:Vector.<DaeNode>;
public function DaeInstanceController(data:XML, document:DaeDocument, node:DaeNode)
{
super(data,document);
this.node = node;
}
override protected function parseImplementation() : Boolean
{
var controller:DaeController = this.controller;
if(controller != null)
{
this.topmostJoints = controller.findRootJointNodes(this.skeletons);
if(this.topmostJoints != null && this.topmostJoints.length > 1)
{
this.replaceNodesByTopmost(this.topmostJoints);
}
}
return this.topmostJoints != null;
}
private function replaceNodesByTopmost(nodes:Vector.<DaeNode>) : void
{
var i:int = 0;
var node:DaeNode = null;
var parent:DaeNode = null;
var numNodes:int = int(nodes.length);
var parents:Dictionary = new Dictionary();
for(i = 0; i < numNodes; i++)
{
node = nodes[i];
for(parent = node.parent; parent != null; parent = parent.parent)
{
if(Boolean(parents[parent]))
{
++parents[parent];
}
else
{
parents[parent] = 1;
}
}
}
for(i = 0; i < numNodes; i++)
{
node = nodes[i];
while(true)
{
parent = node.parent;
if(!(parent != null && parents[parent] != numNodes))
{
break;
}
node = node.parent;
}
nodes[i] = node;
}
}
private function get controller() : DaeController
{
var controller:DaeController = document.findController(data.@url[0]);
if(controller == null)
{
document.logger.logNotFoundError(data.@url[0]);
}
return controller;
}
private function get skeletons() : Vector.<DaeNode>
{
var skeletons:Vector.<DaeNode> = null;
var i:int = 0;
var count:int = 0;
var skeletonXML:XML = null;
var skel:DaeNode = null;
var list:XMLList = data.skeleton;
if(list.length() > 0)
{
skeletons = new Vector.<DaeNode>();
for(i = 0,count = int(list.length()); i < count; i++)
{
skeletonXML = list[i];
skel = document.findNode(skeletonXML.text()[0]);
if(skel != null)
{
skeletons.push(skel);
}
else
{
document.logger.logNotFoundError(skeletonXML);
}
}
return skeletons;
}
return null;
}
public function parseSkin(materials:Object) : DaeObject
{
var controller:DaeController = this.controller;
if(controller != null)
{
controller.parse();
return controller.parseSkin(materials,this.topmostJoints,this.skeletons);
}
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeInstanceMaterial extends DaeElement
{
public function DaeInstanceMaterial(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get symbol() : String
{
var attribute:XML = data.@symbol[0];
return attribute == null ? null : attribute.toString();
}
private function get target() : XML
{
return data.@target[0];
}
public function get material() : DaeMaterial
{
var mat:DaeMaterial = document.findMaterial(this.target);
if(mat == null)
{
document.logger.logNotFoundError(this.target);
}
return mat;
}
public function getBindVertexInputSetNum(semantic:String) : int
{
var bindVertexInputXML:XML = null;
var setNumXML:XML = null;
bindVertexInputXML = data.bind_vertex_input.(@semantic == semantic)[0];
if(bindVertexInputXML == null)
{
return 0;
}
setNumXML = bindVertexInputXML.@input_set[0];
return setNumXML == null ? 0 : int(parseInt(setNumXML.toString(),10));
}
}
}

View File

@@ -0,0 +1,137 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.core.Light3D;
import alternativa.engine3d.lights.AmbientLight;
import alternativa.engine3d.lights.DirectionalLight;
import alternativa.engine3d.lights.OmniLight;
import alternativa.engine3d.lights.SpotLight;
use namespace collada;
public class DaeLight extends DaeElement
{
public function DaeLight(data:XML, document:DaeDocument)
{
super(data,document);
}
private function float4ToUint(value:Array) : uint
{
var r:uint = value[0] * 255;
var g:uint = value[1] * 255;
var b:uint = value[2] * 255;
return r << 16 | g << 8 | b | 4278190080;
}
public function get revertDirection() : Boolean
{
var info:XML = data.technique_common.children()[0];
return info == null ? false : info.localName() == "directional" || info.localName() == "spot";
}
public function parseLight() : Light3D
{
var info:XML = null;
var extra:XML = null;
var light:Light3D = null;
var color:uint = 0;
var constantAttenuationXML:XML = null;
var linearAttenuationXML:XML = null;
var linearAttenuation:Number = NaN;
var attenuationStart:Number = NaN;
var attenuationEnd:Number = NaN;
var dLight:DirectionalLight = null;
var oLight:OmniLight = null;
var hotspot:Number = NaN;
var fallof:Number = NaN;
var DEG2RAD:Number = NaN;
var sLight:SpotLight = null;
info = data.technique_common.children()[0];
extra = data.extra.technique.(@profile[0] == "OpenCOLLADA3dsMax").light[0];
light = null;
if(info != null)
{
color = this.float4ToUint(parseNumbersArray(info.color[0]));
linearAttenuation = 0;
attenuationStart = 0;
attenuationEnd = 1;
switch(info.localName())
{
case "ambient":
light = new AmbientLight(color);
break;
case "directional":
dLight = new DirectionalLight(color);
light = dLight;
break;
case "point":
if(extra != null)
{
attenuationStart = parseNumber(extra.attenuation_far_start[0]);
attenuationEnd = parseNumber(extra.attenuation_far_end[0]);
}
else
{
constantAttenuationXML = info.constant_attenuation[0];
linearAttenuationXML = info.linear_attenuation[0];
if(constantAttenuationXML != null)
{
attenuationStart = -parseNumber(constantAttenuationXML);
}
if(linearAttenuationXML != null)
{
linearAttenuation = parseNumber(linearAttenuationXML);
}
if(linearAttenuation > 0)
{
attenuationEnd = 1 / linearAttenuation + attenuationStart;
}
else
{
attenuationEnd = attenuationStart + 1;
}
}
oLight = new OmniLight(color,attenuationStart,attenuationEnd);
light = oLight;
break;
case "spot":
hotspot = 0;
fallof = Math.PI / 4;
DEG2RAD = Math.PI / 180;
if(extra != null)
{
attenuationStart = parseNumber(extra.attenuation_far_start[0]);
attenuationEnd = parseNumber(extra.attenuation_far_end[0]);
hotspot = DEG2RAD * parseNumber(extra.hotspot_beam[0]);
fallof = DEG2RAD * parseNumber(extra.falloff[0]);
}
else
{
constantAttenuationXML = info.constant_attenuation[0];
linearAttenuationXML = info.linear_attenuation[0];
if(constantAttenuationXML != null)
{
attenuationStart = -parseNumber(constantAttenuationXML);
}
if(linearAttenuationXML != null)
{
linearAttenuation = parseNumber(linearAttenuationXML);
}
if(linearAttenuation > 0)
{
attenuationEnd = 1 / linearAttenuation + attenuationStart;
}
else
{
attenuationEnd = attenuationStart + 1;
}
}
sLight = new SpotLight(color,attenuationStart,attenuationEnd,hotspot,fallof);
light = sLight;
}
}
return light;
}
}
}

View File

@@ -0,0 +1,57 @@
package alternativa.engine3d.loaders.collada
{
public class DaeLogger
{
public function DaeLogger()
{
super();
}
private function logMessage(message:String, element:XML) : void
{
var name:String = element.nodeKind() == "attribute" ? "@" + element.localName() : element.localName() + "";
for(var parent:* = element.parent(); parent != null; )
{
name = parent.localName() + "" + "." + name;
parent = parent.parent();
}
trace(message,"| \"" + name + "\"");
}
private function logError(message:String, element:XML) : void
{
this.logMessage("[ERROR] " + message,element);
}
public function logExternalError(element:XML) : void
{
this.logError("External urls don\'t supported",element);
}
public function logSkewError(element:XML) : void
{
this.logError("<skew> don\'t supported",element);
}
public function logJointInAnotherSceneError(element:XML) : void
{
this.logError("Joints in different scenes don\'t supported",element);
}
public function logInstanceNodeError(element:XML) : void
{
this.logError("<instance_node> don\'t supported",element);
}
public function logNotFoundError(element:XML) : void
{
this.logError("Element with url \"" + element.toString() + "\" not found",element);
}
public function logNotEnoughDataError(element:XML) : void
{
this.logError("Not enough data",element);
}
}
}

View File

@@ -0,0 +1,57 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.loaders.ParserMaterial;
use namespace collada;
public class DaeMaterial extends DaeElement
{
public var material:ParserMaterial;
public var mainTexCoords:String;
public var used:Boolean = false;
public function DaeMaterial(data:XML, document:DaeDocument)
{
super(data,document);
}
private function parseSetParams() : Object
{
var element:XML = null;
var param:DaeParam = null;
var params:Object = new Object();
var list:XMLList = data.instance_effect.setparam;
for each(element in list)
{
param = new DaeParam(element,document);
params[param.ref] = param;
}
return params;
}
private function get effectURL() : XML
{
return data.instance_effect.@url[0];
}
override protected function parseImplementation() : Boolean
{
var effect:DaeEffect = document.findEffect(this.effectURL);
if(effect != null)
{
effect.parse();
this.material = effect.getMaterial(this.parseSetParams());
this.mainTexCoords = effect.mainTexCoords;
if(this.material != null)
{
this.material.name = cloneString(name);
}
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,567 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.animation.§_-FA§;
import alternativa.engine3d.animation.keys.§_-Np§;
import alternativa.engine3d.animation.keys.§_-ew§;
import alternativa.engine3d.animation.keys.§_-kB§;
import alternativa.engine3d.core.Light3D;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.objects.Mesh;
import alternativa.engine3d.objects.Skin;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
use namespace collada;
public class DaeNode extends DaeElement
{
public var scene:DaeVisualScene;
public var parent:DaeNode;
public var skinOrTopmostJoint:Boolean = false;
private var channels:Vector.<DaeChannel>;
private var §_-DE§:Vector.<DaeInstanceController>;
public var nodes:Vector.<DaeNode>;
public var objects:Vector.<DaeObject>;
public var skins:Vector.<DaeObject>;
public function DaeNode(data:XML, document:DaeDocument, scene:DaeVisualScene = null, parent:DaeNode = null)
{
super(data,document);
this.scene = scene;
this.parent = parent;
this.constructNodes();
}
public function get animName() : String
{
var n:String = this.name;
return n == null ? this.id : n;
}
private function constructNodes() : void
{
var node:DaeNode = null;
var nodesList:XMLList = data.node;
var count:int = int(nodesList.length());
this.nodes = new Vector.<DaeNode>(count);
for(var i:int = 0; i < count; i++)
{
node = new DaeNode(nodesList[i],document,this.scene,this);
if(node.id != null)
{
document.nodes[node.id] = node;
}
this.nodes[i] = node;
}
}
internal function registerInstanceControllers() : void
{
var i:int = 0;
var instanceControllerXML:XML = null;
var instanceController:DaeInstanceController = null;
var jointNodes:Vector.<DaeNode> = null;
var numNodes:int = 0;
var jointNode:DaeNode = null;
var j:int = 0;
var instanceControllerXMLs:XMLList = data.instance_controller;
var count:int = int(instanceControllerXMLs.length());
for(i = 0; i < count; )
{
this.skinOrTopmostJoint = true;
instanceControllerXML = instanceControllerXMLs[i];
instanceController = new DaeInstanceController(instanceControllerXML,document,this);
if(instanceController.parse())
{
jointNodes = instanceController.topmostJoints;
numNodes = int(jointNodes.length);
if(numNodes > 0)
{
jointNode = jointNodes[0];
jointNode.addInstanceController(instanceController);
for(j = 0; j < numNodes; j++)
{
jointNodes[j].skinOrTopmostJoint = true;
}
}
}
i++;
}
count = int(this.nodes.length);
for(i = 0; i < count; i++)
{
this.nodes[i].registerInstanceControllers();
}
}
public function addChannel(channel:DaeChannel) : void
{
if(this.channels == null)
{
this.channels = new Vector.<DaeChannel>();
}
this.channels.push(channel);
}
public function addInstanceController(controller:DaeInstanceController) : void
{
if(this.§_-DE§ == null)
{
this.§_-DE§ = new Vector.<DaeInstanceController>();
}
this.§_-DE§.push(controller);
}
override protected function parseImplementation() : Boolean
{
this.skins = this.parseSkins();
this.objects = this.parseObjects();
return true;
}
private function parseInstanceMaterials(geometry:XML) : Object
{
var instance:DaeInstanceMaterial = null;
var instances:Object = new Object();
var list:XMLList = geometry.bind_material.technique_common.instance_material;
for(var i:int = 0,var count:int = int(list.length()); i < count; i++)
{
instance = new DaeInstanceMaterial(list[i],document);
instances[instance.symbol] = instance;
}
return instances;
}
public function getNodeBySid(sid:String) : DaeNode
{
var i:int = 0;
var temp:Vector.<Vector.<DaeNode>> = null;
var children:Vector.<DaeNode> = null;
var count:int = 0;
var j:int = 0;
var node:DaeNode = null;
if(sid == this.sid)
{
return this;
}
var levelNodes:Vector.<Vector.<DaeNode>> = new Vector.<Vector.<DaeNode>>();
var levelNodes2:Vector.<Vector.<DaeNode>> = new Vector.<Vector.<DaeNode>>();
levelNodes.push(this.nodes);
for(var len:int = int(levelNodes.length); len > 0; )
{
for(i = 0; i < len; i++)
{
children = levelNodes[i];
count = int(children.length);
for(j = 0; j < count; )
{
node = children[j];
if(node.sid == sid)
{
return node;
}
if(node.nodes.length > 0)
{
levelNodes2.push(node.nodes);
}
j++;
}
}
temp = levelNodes;
levelNodes = levelNodes2;
levelNodes2 = temp;
levelNodes2.length = 0;
len = int(levelNodes.length);
}
return null;
}
public function parseSkins() : Vector.<DaeObject>
{
var instanceController:DaeInstanceController = null;
var skinAndAnimatedJoints:DaeObject = null;
var skin:Skin = null;
if(this.§_-DE§ == null)
{
return null;
}
var skins:Vector.<DaeObject> = new Vector.<DaeObject>();
for(var i:int = 0,var count:int = int(this.§_-DE§.length); i < count; )
{
instanceController = this.§_-DE§[i];
instanceController.parse();
skinAndAnimatedJoints = instanceController.parseSkin(this.parseInstanceMaterials(instanceController.data));
if(skinAndAnimatedJoints != null)
{
skin = Skin(skinAndAnimatedJoints.object);
skin.name = cloneString(instanceController.node.name);
skins.push(skinAndAnimatedJoints);
}
i++;
}
return skins.length > 0 ? skins : null;
}
public function parseObjects() : Vector.<DaeObject>
{
var i:int = 0;
var count:int = 0;
var child:XML = null;
var _loc6_:DaeLight = null;
var _loc7_:DaeGeometry = null;
var light:Light3D = null;
var rotXMatrix:Matrix3D = null;
var mesh:Mesh = null;
var objects:Vector.<DaeObject> = new Vector.<DaeObject>();
var children:XMLList = data.children();
for(i = 0,count = int(children.length()); i < count; )
{
child = children[i];
switch(child.localName())
{
case "instance_light":
_loc6_ = document.findLight(child.@url[0]);
if(_loc6_ != null)
{
light = _loc6_.parseLight();
if(light != null)
{
light.name = cloneString(name);
if(_loc6_.revertDirection)
{
rotXMatrix = new Matrix3D();
rotXMatrix.appendRotation(180,Vector3D.X_AXIS);
objects.push(new DaeObject(this.applyTransformations(light,rotXMatrix)));
}
else
{
objects.push(this.applyAnimation(this.applyTransformations(light)));
}
}
}
else
{
document.logger.logNotFoundError(child.@url[0]);
}
break;
case "instance_geometry":
_loc7_ = document.findGeometry(child.@url[0]);
if(_loc7_ != null)
{
_loc7_.parse();
mesh = _loc7_.parseMesh(this.parseInstanceMaterials(child));
if(mesh != null)
{
mesh.name = cloneString(name);
objects.push(this.applyAnimation(this.applyTransformations(mesh)));
}
}
else
{
document.logger.logNotFoundError(child.@url[0]);
}
break;
case "instance_node":
document.logger.logInstanceNodeError(child);
break;
}
i++;
}
return objects.length > 0 ? objects : null;
}
private function getMatrix(initialMatrix:Matrix3D = null) : Matrix3D
{
var components:Array = null;
var child:XML = null;
var sid:XML = null;
var matrix:Matrix3D = initialMatrix == null ? new Matrix3D() : initialMatrix;
var children:XMLList = data.children();
for(var i:int = children.length() - 1; i >= 0; i--)
{
child = children[i];
sid = child.@sid[0];
if(sid != null && sid.toString() == "post-rotationY")
{
continue;
}
switch(child.localName())
{
case "scale":
components = parseNumbersArray(child);
matrix.appendScale(components[0],components[1],components[2]);
break;
case "rotate":
components = parseNumbersArray(child);
matrix.appendRotation(components[3],new Vector3D(components[0],components[1],components[2]));
break;
case "translate":
components = parseNumbersArray(child);
matrix.appendTranslation(components[0] * document.unitScaleFactor,components[1] * document.unitScaleFactor,components[2] * document.unitScaleFactor);
break;
case "matrix":
components = parseNumbersArray(child);
matrix.append(new Matrix3D(Vector.<Number>([components[0],components[4],components[8],components[12],components[1],components[5],components[9],components[13],components[2],components[6],components[10],components[14],components[3] * document.unitScaleFactor,components[7] * document.unitScaleFactor,components[11] * document.unitScaleFactor,components[15]])));
break;
case "lookat":
break;
case "skew":
document.logger.logSkewError(child);
break;
}
}
return matrix;
}
public function applyTransformations(object:Object3D, prepend:Matrix3D = null, append:Matrix3D = null) : Object3D
{
var matrix:Matrix3D = this.getMatrix(prepend);
if(append != null)
{
matrix.append(append);
}
var vs:Vector.<Vector3D> = matrix.decompose();
var t:Vector3D = vs[0];
var r:Vector3D = vs[1];
var s:Vector3D = vs[2];
object.x = t.x;
object.y = t.y;
object.z = t.z;
object.rotationX = r.x;
object.rotationY = r.y;
object.rotationZ = r.z;
object.scaleX = s.x;
object.scaleY = s.y;
object.scaleZ = s.z;
return object;
}
public function applyAnimation(object:Object3D) : DaeObject
{
var animation:§_-FA§ = this.parseAnimation(object);
if(animation == null)
{
return new DaeObject(object);
}
object.name = this.animName;
animation.§_-L6§(object,false);
return new DaeObject(object,animation);
}
public function parseAnimation(object:Object3D = null) : §_-FA§
{
if(this.channels == null || !this.hasTransformationAnimation())
{
return null;
}
var channel:DaeChannel = this.getChannel(DaeChannel.PARAM_MATRIX);
if(channel != null)
{
return this.createClip(channel.tracks);
}
var clip:§_-FA§ = new §_-FA§();
var components:Vector.<Vector3D> = object != null ? null : this.getMatrix().decompose();
channel = this.getChannel(DaeChannel.PARAM_TRANSLATE);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
channel = this.getChannel(DaeChannel.PARAM_TRANSLATE_X);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("x",object == null ? Number(components[0].x) : object.x));
}
channel = this.getChannel(DaeChannel.PARAM_TRANSLATE_Y);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("y",object == null ? Number(components[0].y) : object.y));
}
channel = this.getChannel(DaeChannel.PARAM_TRANSLATE_Z);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("z",object == null ? Number(components[0].z) : object.z));
}
}
channel = this.getChannel(DaeChannel.PARAM_ROTATION_X);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("rotationX",object == null ? Number(components[1].x) : object.rotationX));
}
channel = this.getChannel(DaeChannel.PARAM_ROTATION_Y);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("rotationY",object == null ? Number(components[1].y) : object.rotationY));
}
channel = this.getChannel(DaeChannel.PARAM_ROTATION_Z);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("rotationZ",object == null ? Number(components[1].z) : object.rotationZ));
}
channel = this.getChannel(DaeChannel.PARAM_SCALE);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
channel = this.getChannel(DaeChannel.PARAM_SCALE_X);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("scaleX",object == null ? Number(components[2].x) : object.scaleX));
}
channel = this.getChannel(DaeChannel.PARAM_SCALE_Y);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("scaleY",object == null ? Number(components[2].y) : object.scaleY));
}
channel = this.getChannel(DaeChannel.PARAM_SCALE_Z);
if(channel != null)
{
this.addTracksToClip(clip,channel.tracks);
}
else
{
clip.§_-nn§(this.createValueStaticTrack("scaleZ",object == null ? Number(components[2].z) : object.scaleZ));
}
}
if(clip.numTracks > 0)
{
return clip;
}
return null;
}
private function createClip(tracks:Vector.<§_-Np§>) : §_-FA§
{
var clip:§_-FA§ = new §_-FA§();
for(var i:int = 0,var count:int = int(tracks.length); i < count; i++)
{
clip.§_-nn§(tracks[i]);
}
return clip;
}
private function addTracksToClip(clip:§_-FA§, tracks:Vector.<§_-Np§>) : void
{
for(var i:int = 0,var count:int = int(tracks.length); i < count; i++)
{
clip.§_-nn§(tracks[i]);
}
}
private function hasTransformationAnimation() : Boolean
{
var channel:DaeChannel = null;
var result:Boolean = false;
for(var i:int = 0,var count:int = int(this.channels.length); i < count; )
{
channel = this.channels[i];
channel.parse();
result = channel.§_-dS§ == DaeChannel.PARAM_MATRIX;
result ||= channel.§_-dS§ == DaeChannel.PARAM_TRANSLATE;
result ||= channel.§_-dS§ == DaeChannel.PARAM_TRANSLATE_X;
result ||= channel.§_-dS§ == DaeChannel.PARAM_TRANSLATE_Y;
result ||= channel.§_-dS§ == DaeChannel.PARAM_TRANSLATE_Z;
result ||= channel.§_-dS§ == DaeChannel.PARAM_ROTATION_X;
result ||= channel.§_-dS§ == DaeChannel.PARAM_ROTATION_Y;
result ||= channel.§_-dS§ == DaeChannel.PARAM_ROTATION_Z;
result ||= channel.§_-dS§ == DaeChannel.PARAM_SCALE;
result ||= channel.§_-dS§ == DaeChannel.PARAM_SCALE_X;
result ||= channel.§_-dS§ == DaeChannel.PARAM_SCALE_Y;
result ||= channel.§_-dS§ == DaeChannel.PARAM_SCALE_Z;
if(result)
{
return true;
}
i++;
}
return false;
}
private function getChannel(param:String) : DaeChannel
{
var channel:DaeChannel = null;
for(var i:int = 0,var count:int = int(this.channels.length); i < count; )
{
channel = this.channels[i];
channel.parse();
if(channel.§_-dS§ == param)
{
return channel;
}
i++;
}
return null;
}
private function concatTracks(source:Vector.<§_-Np§>, dest:Vector.<§_-Np§>) : void
{
for(var i:int = 0,var count:int = int(source.length); i < count; i++)
{
dest.push(source[i]);
}
}
private function createValueStaticTrack(property:String, value:Number) : §_-Np§
{
var track:§_-kB§ = new §_-kB§(this.animName,property);
track.addKey(0,value);
return track;
}
public function createStaticTransformTrack() : §_-ew§
{
var track:§_-ew§ = new §_-ew§(this.animName);
track.addKey(0,this.getMatrix());
return track;
}
public function get layer() : String
{
var layerXML:XML = data.@layer[0];
return layerXML == null ? null : layerXML.toString();
}
}
}

View File

@@ -0,0 +1,22 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.animation.§_-FA§;
import alternativa.engine3d.core.Object3D;
public class DaeObject
{
public var object:Object3D;
public var animation:§_-FA§;
public var jointNode:DaeNode;
public function DaeObject(object:Object3D, animation:§_-FA§ = null)
{
super();
this.object = object;
this.animation = animation;
}
}
}

View File

@@ -0,0 +1,88 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeParam extends DaeElement
{
public function DaeParam(data:XML, document:DaeDocument)
{
super(data,document);
}
public function get ref() : String
{
var attribute:XML = data.@ref[0];
return attribute == null ? null : attribute.toString();
}
public function getFloat() : Number
{
var floatXML:XML = data.float[0];
if(floatXML != null)
{
return parseNumber(floatXML);
}
return NaN;
}
public function getFloat4() : Array
{
var components:Array = null;
var element:XML = data.float4[0];
if(element == null)
{
element = data.float3[0];
if(element != null)
{
components = parseNumbersArray(element);
components[3] = 1;
}
}
else
{
components = parseNumbersArray(element);
}
return components;
}
public function get surfaceSID() : String
{
var element:XML = data.sampler2D.source[0];
return element == null ? null : element.text().toString();
}
public function get wrap_s() : String
{
var element:XML = data.sampler2D.wrap_s[0];
return element == null ? null : element.text().toString();
}
public function get image() : DaeImage
{
var image:DaeImage = null;
var init_from:XML = null;
var _loc4_:XML = null;
var surface:XML = data.surface[0];
if(surface != null)
{
init_from = surface.init_from[0];
if(init_from == null)
{
return null;
}
image = document.findImageByID(init_from.text().toString());
}
else
{
_loc4_ = data.instance_image.@url[0];
if(_loc4_ == null)
{
return null;
}
image = document.findImage(_loc4_);
}
return image;
}
}
}

View File

@@ -0,0 +1,135 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.animation.keys.§_-Np§;
import alternativa.engine3d.animation.keys.§_-ew§;
import alternativa.engine3d.animation.keys.§_-kB§;
import flash.geom.Matrix3D;
use namespace collada;
public class DaeSampler extends DaeElement
{
private var §_-G6§:Vector.<Number>;
private var values:Vector.<Number>;
private var §_-JC§:int;
private var §_-7i§:int;
public function DaeSampler(data:XML, document:DaeDocument)
{
super(data,document);
}
override protected function parseImplementation() : Boolean
{
var inputSource:DaeSource = null;
var outputSource:DaeSource = null;
var input:DaeInput = null;
var semantic:String = null;
var inputsList:XMLList = data.input;
for(var i:int = 0,var count:int = int(inputsList.length()); i < count; i++)
{
input = new DaeInput(inputsList[i],document);
semantic = input.semantic;
if(semantic == null)
{
continue;
}
switch(semantic)
{
case "INPUT":
inputSource = input.prepareSource(1);
if(inputSource != null)
{
this.§_-G6§ = inputSource.numbers;
this.§_-JC§ = inputSource.stride;
}
break;
case "OUTPUT":
outputSource = input.prepareSource(1);
if(outputSource != null)
{
this.values = outputSource.numbers;
this.§_-7i§ = outputSource.stride;
}
break;
}
}
return true;
}
public function parseNumbersTrack(objectName:String, property:String) : §_-kB§
{
var track:§_-kB§ = null;
var count:int = 0;
var i:int = 0;
if(this.§_-G6§ != null && this.values != null && this.§_-JC§ > 0)
{
track = new §_-kB§(objectName,property);
count = this.§_-G6§.length / this.§_-JC§;
for(i = 0; i < count; i++)
{
track.addKey(this.§_-G6§[int(this.§_-JC§ * i)],this.values[int(this.§_-7i§ * i)]);
}
return track;
}
return null;
}
public function parseTransformationTrack(objectName:String) : §_-Np§
{
var track:§_-ew§ = null;
var count:int = 0;
var i:int = 0;
var index:int = 0;
var matrix:Matrix3D = null;
if(this.§_-G6§ != null && this.values != null && this.§_-JC§ != 0)
{
track = new §_-ew§(objectName);
count = this.§_-G6§.length / this.§_-JC§;
for(i = 0; i < count; i++)
{
index = this.§_-7i§ * i;
matrix = new Matrix3D(Vector.<Number>([this.values[index],this.values[index + 4],this.values[index + 8],this.values[index + 12],this.values[index + 1],this.values[index + 5],this.values[index + 9],this.values[index + 13],this.values[index + 2],this.values[index + 6],this.values[index + 10],this.values[index + 14],this.values[index + 3],this.values[index + 7],this.values[index + 11],this.values[index + 15]]));
track.addKey(this.§_-G6§[i * this.§_-JC§],matrix);
}
return track;
}
return null;
}
public function parsePointsTracks(objectName:String, xProperty:String, yProperty:String, zProperty:String) : Vector.<§_-Np§>
{
var xTrack:§_-kB§ = null;
var yTrack:§_-kB§ = null;
var zTrack:§_-kB§ = null;
var count:int = 0;
var i:int = 0;
var index:int = 0;
var time:Number = NaN;
if(this.§_-G6§ != null && this.values != null && this.§_-JC§ != 0)
{
xTrack = new §_-kB§(objectName,xProperty);
xTrack.object = objectName;
yTrack = new §_-kB§(objectName,yProperty);
yTrack.object = objectName;
zTrack = new §_-kB§(objectName,zProperty);
zTrack.object = objectName;
count = this.§_-G6§.length / this.§_-JC§;
for(i = 0; i < count; i++)
{
index = i * this.§_-7i§;
time = this.§_-G6§[i * this.§_-JC§];
xTrack.addKey(time,this.values[index]);
yTrack.addKey(time,this.values[index + 1]);
zTrack.addKey(time,this.values[index + 2]);
}
return Vector.<§_-Np§>([xTrack,yTrack,zTrack]);
}
return null;
}
}
}

View File

@@ -0,0 +1,170 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeSource extends DaeElement
{
private const §_-XM§:String = "float_array";
private const §_-g6§:String = "int_array";
private const §_-ZJ§:String = "Name_array";
public var numbers:Vector.<Number>;
public var §_-op§:Vector.<int>;
public var names:Vector.<String>;
public var stride:int;
public function DaeSource(data:XML, document:DaeDocument)
{
super(data,document);
this.constructArrays();
}
private function constructArrays() : void
{
var child:XML = null;
var _loc5_:DaeArray = null;
var children:XMLList = data.children();
for(var i:int = 0,var count:int = int(children.length()); i < count; )
{
child = children[i];
switch(child.localName())
{
case this.§_-XM§:
case this.§_-g6§:
case this.§_-ZJ§:
_loc5_ = new DaeArray(child,document);
if(_loc5_.id != null)
{
document.arrays[_loc5_.id] = _loc5_;
}
break;
}
i++;
}
}
private function get accessor() : XML
{
return data.technique_common.accessor[0];
}
override protected function parseImplementation() : Boolean
{
var arrayXML:XML = null;
var array:DaeArray = null;
var countXML:String = null;
var count:int = 0;
var offsetXML:XML = null;
var strideXML:XML = null;
var offset:int = 0;
var stride:int = 0;
var accessor:XML = this.accessor;
if(accessor != null)
{
arrayXML = accessor.@source[0];
array = arrayXML == null ? null : document.findArray(arrayXML);
if(array != null)
{
countXML = accessor.@count[0];
if(countXML != null)
{
count = int(parseInt(countXML.toString(),10));
offsetXML = accessor.@offset[0];
strideXML = accessor.@stride[0];
offset = offsetXML == null ? 0 : int(parseInt(offsetXML.toString(),10));
stride = strideXML == null ? 1 : int(parseInt(strideXML.toString(),10));
array.parse();
if(array.array.length < offset + count * stride)
{
document.logger.logNotEnoughDataError(accessor);
return false;
}
this.stride = this.parseArray(offset,count,stride,array.array,array.type);
return true;
}
}
else
{
document.logger.logNotFoundError(arrayXML);
}
}
return false;
}
private function numValidParams(params:XMLList) : int
{
var res:int = 0;
for(var i:int = 0,var count:int = int(params.length()); i < count; )
{
if(params[i].@name[0] != null)
{
res++;
}
i++;
}
return res;
}
private function parseArray(offset:int, count:int, stride:int, array:Array, type:String) : int
{
var param:XML = null;
var j:int = 0;
var value:String = null;
var params:XMLList = this.accessor.param;
var arrStride:int = int(Math.max(this.numValidParams(params),stride));
switch(type)
{
case this.§_-XM§:
this.numbers = new Vector.<Number>(int(arrStride * count));
break;
case this.§_-g6§:
this.§_-op§ = new Vector.<int>(int(arrStride * count));
break;
case this.§_-ZJ§:
this.names = new Vector.<String>(int(arrStride * count));
}
var curr:int = 0;
for(var i:int = 0; i < arrStride; )
{
param = params[i];
if(param == null || Boolean(param.hasOwnProperty("@name")))
{
switch(type)
{
case this.§_-XM§:
for(j = 0; j < count; j++)
{
value = array[int(offset + stride * j + i)];
if(value.indexOf(",") != -1)
{
value = value.replace(/,/,".");
}
this.numbers[int(arrStride * j + curr)] = parseFloat(value);
}
break;
case this.§_-g6§:
for(j = 0; j < count; j++)
{
this.§_-op§[int(arrStride * j + curr)] = parseInt(array[int(offset + stride * j + i)],10);
}
break;
case this.§_-ZJ§:
for(j = 0; j < count; j++)
{
this.names[int(arrStride * j + curr)] = array[int(offset + stride * j + i)];
}
}
curr++;
}
i++;
}
return arrStride;
}
}
}

View File

@@ -0,0 +1,74 @@
package alternativa.engine3d.loaders.collada
{
import flash.geom.Vector3D;
public class DaeVertex
{
public var §_-Eq§:int;
public var §_-AR§:int;
public var indices:Vector.<int> = new Vector.<int>();
public var x:Number;
public var y:Number;
public var z:Number;
public var uvs:Vector.<Number> = new Vector.<Number>();
public var normal:Vector3D;
public var §_-hC§:Vector3D;
public function DaeVertex()
{
super();
}
public function addPosition(data:Vector.<Number>, dataIndex:int, stride:int, unitScaleFactor:Number) : void
{
this.indices.push(dataIndex);
var offset:int = stride * dataIndex;
this.x = data[int(offset)] * unitScaleFactor;
this.y = data[int(offset + 1)] * unitScaleFactor;
this.z = data[int(offset + 2)] * unitScaleFactor;
}
public function addNormal(data:Vector.<Number>, dataIndex:int, stride:int) : void
{
this.indices.push(dataIndex);
var offset:int = stride * dataIndex;
this.normal = new Vector3D();
this.normal.x = data[int(offset++)];
this.normal.y = data[int(offset++)];
this.normal.z = data[offset];
}
public function addTangentBiDirection(tangentData:Vector.<Number>, tangentDataIndex:int, tangentStride:int, biNormalData:Vector.<Number>, biNormalDataIndex:int, biNormalStride:int) : void
{
this.indices.push(tangentDataIndex);
this.indices.push(biNormalDataIndex);
var tangentOffset:int = tangentStride * tangentDataIndex;
var biNormalOffset:int = biNormalStride * biNormalDataIndex;
var biNormalX:Number = biNormalData[int(biNormalOffset++)];
var biNormalY:Number = biNormalData[int(biNormalOffset++)];
var biNormalZ:Number = biNormalData[biNormalOffset];
this.§_-hC§ = new Vector3D(tangentData[int(tangentOffset++)],tangentData[int(tangentOffset++)],tangentData[tangentOffset]);
var crossX:Number = this.normal.y * this.§_-hC§.z - this.normal.z * this.§_-hC§.y;
var crossY:Number = this.normal.z * this.§_-hC§.x - this.normal.x * this.§_-hC§.z;
var crossZ:Number = this.normal.x * this.§_-hC§.y - this.normal.y * this.§_-hC§.x;
var dot:Number = crossX * biNormalX + crossY * biNormalY + crossZ * biNormalZ;
this.§_-hC§.w = dot < 0 ? -1 : 1;
}
public function appendUV(data:Vector.<Number>, dataIndex:int, stride:int) : void
{
this.indices.push(dataIndex);
this.uvs.push(data[int(dataIndex * stride)]);
this.uvs.push(1 - data[int(dataIndex * stride + 1)]);
}
}
}

View File

@@ -0,0 +1,33 @@
package alternativa.engine3d.loaders.collada
{
import alternativa.engine3d.alternativa3d;
use namespace alternativa3d;
use namespace collada;
public class DaeVertices extends DaeElement
{
public var §_-E6§:DaeSource;
public function DaeVertices(data:XML, document:DaeDocument)
{
super(data,document);
}
override protected function parseImplementation() : Boolean
{
var inputXML:XML = null;
inputXML = data.input.(@semantic == "POSITION")[0];
if(inputXML != null)
{
this.§_-E6§ = new DaeInput(inputXML,document).prepareSource(3);
if(this.§_-E6§ != null)
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,33 @@
package alternativa.engine3d.loaders.collada
{
use namespace collada;
public class DaeVisualScene extends DaeElement
{
public var nodes:Vector.<DaeNode>;
public function DaeVisualScene(data:XML, document:DaeDocument)
{
super(data,document);
this.constructNodes();
}
public function constructNodes() : void
{
var node:DaeNode = null;
var nodesList:XMLList = data.node;
var count:int = int(nodesList.length());
this.nodes = new Vector.<DaeNode>(count);
for(var i:int = 0; i < count; i++)
{
node = new DaeNode(nodesList[i],document,this);
if(node.id != null)
{
document.nodes[node.id] = node;
}
this.nodes[i] = node;
}
}
}
}

View File

@@ -0,0 +1,5 @@
package alternativa.engine3d.loaders.collada
{
public namespace collada = "http://www.collada.org/2005/11/COLLADASchema";
}