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

bum*_*ack 14 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

资产(一个或多个)加载完成后,我有一个有效的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;
Run Code Online (Sandbox Code Playgroud)

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

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

bum*_*ack 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;
Run Code Online (Sandbox Code Playgroud)

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

_myPose.jointPoses[2].translation.x = 100;
Run Code Online (Sandbox Code Playgroud)

如果您不知道关节的索引,而是通过名称来寻址骨骼,那么这应该可行:

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

如果您经常使用名称查找(例如每帧)并且模型中有很多骨骼,建议建立一个Dictionary可以按名称查找骨骼索引的位置。原因是 的实现jointIndexFromName对所有关节执行线性搜索,如果多次执行此操作会造成浪费。