如何在Away3D中以编程方式移动已加载资源的骨骼?

时间:2013-12-04 10:11:35

标签: actionscript-3 away3d

我正在将3D资源加载到Away3D场景中,我想在代码中移动骨骼的位置。

资源加载一切顺利,我在加载时抓住指向MeshSkeleton的指针:

private function onAssetComplete(evt:AssetEvent):void
{
    if(evt.asset.assetType == AssetType.SKELETON){
        _skeleton = evt.asset as Skeleton;
    } else if (evt.asset.assetType == AssetType.MESH) {
        _mesh = evt.asset as Mesh;
    }
}

资产加载完成后,我有一个有效的SkeletonMesh实例,模型在我的场景中也可见。接下来我尝试的是以下内容。

// create a matrix with the desired joint (bone) position
var pos:Matrix3D = new Matrix3D();
pos.position = new Vector3D(60, 0, 0);
pos.invert();

// get the joint I'd like to modifiy. The bone is named "left"
var joint:SkeletonJoint = _skeleton.jointFromName("left");

// assign joint position
joint.inverseBindPose = pos.rawData;

此代码运行时没有错误,但新位置未应用于可见几何体,例如。骨骼的位置根本没有变化。

我在这里缺少一个额外的步骤吗?我是否必须以某种方式将骨架重新分配给Mesh?或者我是否必须明确告诉网格骨骼位置已经改变了?

1 个答案:

答案 0 :(得分:2)

这可能不是解决这个问题的最佳方法,但这就是我想到的:

Away3D仅在存在动画时将关节变换应用于几何体。要应用变换,您的几何体必须具有动画,您必须在代码中创建动画。这是你如何做到的(最好是你的LoaderEvent.RESOURCE_COMPLETE处理程序方法:

// create a new pose for the skeleton
var rootPose:SkeletonPose = new SkeletonPose();

// add all the joints to the pose
// the _skeleton member is being assigned during the loading phase where you
// look for AssetType.SKELETON inside a AssetEvent.ASSET_COMPLETE listener
for each(var joint:SkeletonJoint in _skeleton.joints){
    var m:Matrix3D = new Matrix3D(joint.inverseBindPose);
    m.invert();
    var p:JointPose = new JointPose();
    p.translation = m.transformVector(p.translation);
    p.orientation.fromMatrix(m);
    rootPose.jointPoses.push(p);
}

// create idle animation clip by adding the root pose twice
var clip:SkeletonClipNode = new SkeletonClipNode();
clip.addFrame(rootPose, 1000);
clip.addFrame(rootPose, 1000);
clip.name = "idle";

// build animation set
var animSet:SkeletonAnimationSet = new SkeletonAnimationSet(3);
animSet.addAnimation(clip);

// setup animator with set and skeleton
var animator:SkeletonAnimator = new SkeletonAnimator(animSet, _skeleton);

// assign the newly created animator to your Mesh.
// This example assumes that you grabbed the pointer to _myMesh during the 
// asset loading stage (by looking for AssetType.MESH)
_myMesh.animator = animator;

// run the animation
animator.play("idle");

// it's best to keep a member that points to your pose for
// further modification
_myPose = rootPose;

在初始化步骤之后,您可以动态修改关节姿势(通过修改translation属性来改变位置,通过改变orientation属性来改变旋转)。例如:

_myPose.jointPoses[2].translation.x = 100;

如果您不知道关节的索引而是通过名称来解决骨骼,那么这应该有效:

var jointIndex:int = _skeleton.jointIndexFromName("myBoneName");
_myPose.jointPoses[jointIndex].translation.y = 10;

如果您经常使用名称查找(比如说每一帧)并且模型中有很多骨骼,建议您构建一个Dictionary,您可以在其中按名称查找骨骼索引。这样做的原因是jointIndexFromName的实现会对所有关节执行线性搜索,如果多次这样做会造成浪费。