I’m sorry I keep rambling like this, and I suppose the devs consider 3.6/fp10 long dead, and so on, but I hope maybe someone will find it useful. I should maybe file bug reports instead, and I might do so once I get some feedback/options on the matter.
I’m also sorry that the code i’m talking about is so old. There were so many issues at once when I tried to upgrade to the latest, and also extreme performance hits, so I decided I would upgrade one revision at a time, so I could understand (and possibly fix) the problems. For the most parts, I’ve checked the latest code and determined that the problems are still there.
——-
Ok, next step was trying to clone the damn thing, including getting it to animate separately. This proved hard work as well Remember, I compare this to 3.4-ish (<r2395), which I had working.
Cloning, using ObjectContainer3D::cloneAll(), now requires me to set the target myself:
for each(var animationData:AnimationData in clonedObject.animationLibrary) {
animationData.animator.target = clonedObject;
}
Another issue with Animator when cloning is that the animation will lose its length. I fixed this by adding this line to Animator::clone():
anim._totalFrames = _totalFrames;
But of course, the cloned object wasn’t moving… Main reason is the “new” way, where the animator doesn’t explicitly update the vertices, but just indirectly by making them dirty. The “new” Vertex, has a reference to its SkinVertex, but when cloning this was not set.
I had to make a few modifications to Geometry to fix this. I know it has been totally rewritten since, removing all dealings with skinvertices, so this is possibly only of historical interest. I did these changes in Geometry::clonseSkinVertex():
if (result == null) {
result = new SkinVertex(cloneVertex(skinVertex.skinnedVertex));
// ADDED: the vertex must have a back-reference to the skinvertex
result.skinnedVertex.skinVertex = result;
result.weights = skinVertex.weights.concat();
var _skinVertex_controllers:Array = skinVertex.controllers;
var _skinController:SkinController;
for each (var skinController:SkinController in _skinVertex_controllers) {
_skinController = cloneSkinController(skinController);
// ADDED: controller must know its vertices
_skinController.skinVertices.push(result);
result.controllers.push(_skinController);
}
clonedskinvertices[skinVertex] = result;
}
Also, the new bones didn’t have a SkinController attached to them, so I had to change ObjectContainer3D:cloneBones()
for each (skinController in skinControllers) {
var bone:Bone = root.getBoneByName(skinController.name);
if (bone) {
skinController.joint = bone.joint;
// ADDED: actually associate the bone with its controller
bone.controller = skinController;
...
I found this weird since the comment above it all says “wire up new bones to new skincontrollers”, but I couldn’t see that being done anywhere.
Alright, now it was roughly working. However, close to my original issue with animating the original; all “extremity vertices” (fingers, toes) were fixed.
The problem was again that some SkinControllers weren’t cloned; those that were intermediates and didn’t have any vertices of their own. Again apologizing, this is obsolete code now, but this was because in Geometry::clone(), only the controllers cloned as a result of cloning skin vertices were added. Thus I made this modification to Geometry, so that it added all SkinControllers, and cloned those that hadn’t already been cloned:
//for each (var skinController:SkinController in clonedskincontrollers)
// geometry.skinControllers.push(skinController);
for each(var skinController:SkinController in skinControllers)
geometry.skinControllers.push(cloneSkinController(skinController));
That at least gave me all the skincontrollers in the cloned object, but it still wasn’t working. Many bones didin’t have the child bones (via the joint) that they should. I don’t completely understand this, but this is the Bone::cloneAll() function:
public override function cloneAll(object:Object3D = null):Object3D
{
var bone:Bone = (object as Bone) || new Bone();
bone.removeChild(joint);
super.cloneAll(bone);
bone.boneId = boneId;
bone.joint = bone.children[0];
return bone;
}
When creating a new Bone, it will have an empty joint, so super.cloneAll() will add the proper cloned joint at bone.children[1], and thus “bone.joint = bone.children[0];” will cause the bone’s joint to point to the empty default container.
I thought that maybe the removeChild() is supposed to fix that, but it doesn’t. It tries to remove the original bone’s joint from the new/cloned bone, which should never be there. Perhaps that is a safe gaurd to make sure just that never happens, but I changed that line to:
bone.removeChild(bone.joint);
Which will remove the existing (default) joint, and thus the structure that super.cloneAll() will build up will be the first child, and be the actual joint.
Now it’s working!!!!