@Kasya
Why do you mean that SkeletonPrototype should be backed by SkeletonInstance? It is vice-versa (if you follow the usual nomenclature). A prototype is a general, perhaps "global" entity, while an instance is more a specialized or local entity. Hence we have a many-to-one relation from instances to their prototype. In other words, the instances refer to the prototype. Hence, the correct c'tor would be
SkeletonInstance::SkeletonInstance(SkeletonPrototype& backing) ...
Whether overhanding "backing" here at all is questionable. That depends on whether we need it for some task. E.g. in my engine there is the need to lock shared objects that are in use, so that they can't be deleted as long as some other object is referring to it (catchword "smart pointers"). As written above, the prototype is shared by instances, so I lock the prototype from being deleted at least as long as at least one instance is referring to it. Another aspect is that my engine has a build in editor capability, so it is fine if the designer can inspect to which skeleton prototype the instance belongs to. As a conclusion you can drop that parameter until it gets classified as senseful. In the latter case you will of course need some field to store it. As written in my previous posts, the examples I show may be incomplete w.r.t. such things.
Think of the SkeletonInstance as a complex variable that stores an entire pose. The value of the instance is the summary of all joint positions and orientations (as said, it is complex), and there are operators and/or routines to manipulate that value. This is analogously to a simple, say, integer variable like
int a;
where operators like assign, plus, and minus exist for.
From the above it should be clear that the SkeletonPrototype object should
never be affected by the runtime system. Instead, the SkeletonInstance objects will be affected. In particular, the instance has bones and the bones has the Vector3Variable and QuaternionVariable. The instance provides this to the outer world, but self does not anything (okay, in fact "not very much") to the content. This is, as said, like a variable, that
stores a value but does not alter it. Now, an altering instance is the animation. See my previous lengthy post with the title "Here we go ... Don't shoot me, you've asked for details ;)" in the 5th code snippet the "contribute" routine; there happens the main manipulation stuff.
The SkeletonPrototype::newInstance(...) routine is what is called a "factory" method. Factory methods are e.g. good for generating new objects in dependency on the own state, but without the need to make the state public. So clients need not know about the specialities of the object providing the factory, they only need to know the factory method itself. Instead of letting a client iterate the prototype's bones, creating the instance's bones, and connect them, we sensefully wrap this tasks into the factory.
We have in fact several places where we can build a SkeletonInstance. We can let it be done by a client anywhere. That is often not good because "anywhere" may be needed from several clients (e.g. the AI and scripting). Having a defined place is hence senseful. There is the c'tor of SkeletonInstance (useable when overhanding the backing prototype), a static factory in SkeletonInstance, and a factory method in SkeletonPrototype. Using the c'tor doesn't allow caching. Factory methods, on the other hand, are good in dealing with caches. The static factory is less senseful, since it needs to iterate all cached instances until one is found that belongs to the correct prototype. Hence, asking the particular prototype directly (remembder that the prototype is a kind of singleton) seems me the best way.
Another aspect comes from the edit ability build into my engine, but that is something you can ignore. However, I only show possibilities. You can do something else, of course, whatever fits best into your application.
Now, to give you some clues, the implemention (w/o caching) is like
SkeletonInstance*SkeletonPrototype::newInstance() const { SkeletonInstance* result = new SkeletonInstance(/* *this */); // parameter according to the needs forEach( Bone* currentBone in _bones ) { SkeletonInstance::Bone* companion = new SkeletonInstance::Bone(*currentBone); result->addBone(companion); } return result;}
and with caching (as a forecast ;)) perhaps like
SkeletonInstance*SkeletonPrototype::newInstance() const { SkeletonInstance* result = fromCache(); if(!result) { result = new SkeletonInstance(/* *this */); // parameter according to the needs forEach( Bone* currentBone in _bones ) { SkeletonInstance::Bone* companion = new SkeletonInstance::Bone(*currentBone); result->addBone(companion); } } return result;}
Please compare this also with the factory of AnimationInstance I've presented in the post cited already above.