topical media & game development
student-ar-org-ascollada-core-DaeSkin.ax
student-ar-org-ascollada-core-DaeSkin.ax
[swf]
flex
/*
* Copyright 2007 (c) Tim Knip, ascollada.org.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.ascollada.core
{
import org.ascollada.ASCollada;
import org.ascollada.core.DaeEntity;
import org.ascollada.core.DaeSource;
import org.ascollada.core.DaeVertexWeights;
import org.ascollada.utils.Logger;
public class @ax-student-ar-org-ascollada-core-DaeSkin extends DaeEntity
{
bind shape matrix
public var bind_shape_matrix:Array;
public var source:String;
public var joints:Array;
public var bind_matrices:Array;
public var vertex_weights:Array;
public var blendWeightsByJointID:Object;
public var jointsType:String;
@param node
@return
public function @ax-student-ar-org-ascollada-core-DaeSkin( node:XML = null ):void
{
super( node );
}
@param node
@return
public function findJointBindMatrix( node:DaeNode ):Array
{
var id:String = this.jointsType == "IDREF" ? node.id : node.sid;
for( var i:int = 0; i < this.joints.length; i++ )
{
if( id == this.joints[i] )
return this.bind_matrices[i];
}
return null;
}
@param id
@return
public function findJointBindMatrix2( id:String ):Array
{
for( var i:int = 0; i < this.joints.length; i++ )
{
if( id == this.joints[i] )
return this.bind_matrices[i];
}
return null;
}
@param node
@return
public function findJointVertexWeights( node:DaeNode ):Array
{
var id:String = this.jointsType == "IDREF" ? node.id : node.sid;
var weights:Array = new Array();
for( var i:int = 0; i < this.vertex_weights.length; i++ )
{
var arr:Array = this.vertex_weights[i];
for( var j:int = 0; j < arr.length; j++ )
if( arr[j].joint == id )
weights.push( arr[j] );
}
return weights;
}
@param node
@return
public function findJointVertexWeightsByIDOrSID( id:String ):Array
{
var weights:Array = new Array();
for( var i:int = 0; i < this.vertex_weights.length; i++ )
{
var arr:Array = this.vertex_weights[i];
for( var j:int = 0; j < arr.length; j++ )
if( arr[j].joint == id )
weights.push( arr[j] );
}
return weights;
}
@param node
@return
override public function read( node:XML ):void
{
this.joints = new Array();
this.vertex_weights = new Array();
this.bind_matrices = new Array();
if( node.localName() != ASCollada.DAE_CONTROLLER_SKIN_ELEMENT )
return;
super.read( node );
// required - ref to skin's geometry
this.source = getAttribute(node, ASCollada.DAE_SOURCE_ATTRIBUTE);
Logger.log( "reading skin, source: " + this.source );
// optional - bind_shape_matrix, defaults to identity matrix
var bindList:XMLList = getNodeList(node, ASCollada.DAE_BINDSHAPEMX_SKIN_PARAMETER);
if( bindList.length() )
this.bind_shape_matrix = getFloats( bindList[0] );
else
this.bind_shape_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
// 3 or more <source> elements
var sourceList:XMLList = getNodeList(node, ASCollada.DAE_SOURCE_ELEMENT);
if( sourceList.length() < 3 )
throw new Error( "<skin> requires a minimum of 3 <source> elements!" );
// exactly 1 <joints> element
var jointsNode:XML = getNode(node, ASCollada.DAE_JOINTS_ELEMENT);
if( !jointsNode )
throw new Error( "need exactly one <joints> element!" );
// exactly 1 <vertex_weights> element
var weightsNode:XML = getNode(node, ASCollada.DAE_WEIGHTS_ELEMENT);
if( !weightsNode )
throw new Error( "need exactly one <vertex_weights> element!" );
var jointsList:XMLList = getNodeList(jointsNode, ASCollada.DAE_INPUT_ELEMENT);
var weights:DaeVertexWeights = new DaeVertexWeights( weightsNode );
var srcNode:XML;
var input:DaeInput;
// fetch sources for <joints>
var src:DaeSource
var sources:Object = new Object();
for each( var inputNode:XML in jointsList )
{
input = new DaeInput( inputNode );
srcNode = getNodeById(node, ASCollada.DAE_SOURCE_ELEMENT, input.source);
if( !srcNode )
throw new Error( "source not found! (id='" + input.source + "')" );
src = new DaeSource( srcNode );
switch( input.semantic )
{
case ASCollada.DAE_JOINT_SKIN_INPUT:
this.joints = src.values;
this.jointsType = src.accessor.params[ASCollada.DAE_JOINT_SKIN_INPUT];
//Logger.log( " => => joints: " + this.joints );
break;
case ASCollada.DAE_BINDMATRIX_SKIN_INPUT:
this.bind_matrices = src.values;
//Logger.log( " => => bind_matrices: " + this.bind_matrices );
break;
default:
break;
}
}
var maxOffset:int = 0;
var jointOffset:uint = 0;
var weightOffset:uint = 1;
var tmpWeights:Array;
// fetch sources for <vertex_weights>
for each( input in weights.inputs )
{
srcNode = getNodeById(node, ASCollada.DAE_SOURCE_ELEMENT, input.source);
if( !srcNode )
throw new Error( "source not found! (id='" + input.source + "')" );
src = new DaeSource( srcNode );
switch( input.semantic )
{
case ASCollada.DAE_JOINT_SKIN_INPUT:
jointOffset = input.offset;
maxOffset++;
break;
case ASCollada.DAE_WEIGHT_SKIN_INPUT:
tmpWeights = src.values;
weightOffset = input.offset;
maxOffset++;
//Logger.trace( " => => => vertex_weights: " + tmpWeights );
break;
default:
break;
}
}
//Logger.trace( " => source: " + this.source );
//Logger.trace( " => bind_shape_matrix: " + this.bind_shape_matrix );
//Logger.trace( " => max offset: " + maxOffset + " " + jointOffset + " " + weightOffset );
var cur:int = 0;
for( var i:int = 0; i < weights.vcounts.length; i++ )
{
var vcount:int = weights.vcounts[i];
var tmp:Array = new Array();
for( var j:int = 0; j < vcount; j++ )
{
var jidx:int = weights.v[cur + jointOffset ];
var widx:int = weights.v[cur + weightOffset];
var w:Number = tmpWeights[ widx ];
var jnt:String = jidx < 0 ? null : this.joints[ jidx ];
var blendWeight:DaeBlendWeight = new DaeBlendWeight( i, jnt, w );
tmp.push( blendWeight );
cur += maxOffset;
}
this.vertex_weights[i] = tmp;
}
Logger.log( " => => #vertex_weights " + vertex_weights.length );
}
normalize blendweights.
@param blendWeights the weights to normalize.
private function normalizeBlendWeights( blendWeights:Array ):void
{
var i:int, j:int;
for( i = 0; i < blendWeights.length; i++ )
{
var arr:Array = blendWeights[i]
var weightSum:Number = 0;
for( j = 0; j < arr.length; j++ )
{
weightSum += arr[j].weight;
arr[j].originalWeight = arr[j].weight;
}
if( weightSum == 0.0 || weightSum == 1.0 ) continue;
var invWeightSum:Number = 1.0 / weightSum;
for( j = 0; j < arr.length; j++ )
arr[j].weight *= invWeightSum;
}
}
}
}
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.