BonesIO Question

Started by AGP, July 10, 2020, 06:56:38 AM

Previous topic - Next topic

AGP

How is it that when you load your SkinClipSequences from a bones file instead of each SkinClip having identical Skeletons they each share the same instance of a Skeleton?

raft

not sure what's asked here, but loaded SkinClips and SkinClipSequences share the same Skeleton instance.

AGP

That's right. The question was: how? When I'm doing the same thing with JSON, I'm getting identical copies of the skeleton (the model loads but no animation will work).

AGP

This is not that old, much more ambitious project, by the way. I came very close to exporting a fully-ready, animated and textured, JSON-serialized model right out of both Max and Blender. This is just so I can get Bones out of Java. But I suspect that if you answer at all it will be with, "I don't know."

raft

sorry for the late answer, somehow I didnt receive the notification email.

BonesIO class reads and writes using Java serialization. Java serialization preserves objects references.

So, as long as SkinClips and SkinClipSequences share the same Skeleton instance when they are written by BonesIO, they will share the same Skeleton instance when read by BonesIO.


AGP

Thanks for replying. My problem is Gson's fault. Clean, near-identical to yours, code produced a perfect model, loaded quickly, but with many copies of the same Skeleton. It turns out that Gson doesn't do instances very well. I'm working on a registerTypeAdapterFactory solution which is producing NullPointerExceptions for SkinClipSequences (but for no other class, including Skeleton and SkeletonPose). I also tried Jackson with no success, so I returned to Gson. I expect to succeed soon, and I will post the sources for BonesIO, AnimatedGroup and Animated3D here.

AGP

I'm stuck, now, at an Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: there is already a channel for joint 84. But I'm serializing the data as-is. I wonder if it's related to the potentially null instances of JointChannel in SkinClip.iterator().

raft

Difficult to make a comment without knowing how you are actually importing/reading the data.

AGP

I made the SkinClips work (in the sense that they're filled properly) by making a custom serializer and deserializer for them. But now I'm getting the same instancing issue with Skeletons. So I wrote the hacky method below and called it at the very end of the appropriate AnimatedGroup constructor. Now when I comment out the if (skeleton != pose.skeleton) test in SkinClip.applyTo(...), my model gets all bunched-up once, then doesn't animated at all (but doesn't crash, either) again.


private void attemptSkeletonInstanceFix() {//Gson Skeleton instance crap
     SkinClip lastClip = skinClipSequence.getClip(0);
     if (lastClip.getSkeleton().equals(objects[0].getSkeleton()) && lastClip.getSkeleton() != objects[0].getSkeleton()) {
lastClip.skeleton = objects[0].getSkeleton();
     }
     for (int i = 1; i < skinClipSequence.getSize(); i++) {
if (lastClip.getSkeleton().equals(skinClipSequence.getClip(i).getSkeleton()) && lastClip.getSkeleton() != skinClipSequence.getClip(i).getSkeleton())
     skinClipSequence.getClip(i).skeleton = lastClip.getSkeleton();
lastClip = skinClipSequence.getClip(i);
     }
     for (Animated3D object : objects)
object.currentPose.skeleton = objects[0].getSkeleton();
}

raft

isnt this always returning false?
if (lastClip.getSkeleton().equals(objects[0].getSkeleton()) && lastClip.getSkeleton() != objects[0].getSkeleton())

like
if (a.equals(b) && a != b)

AGP

No, one compares the values, the other tests if they're the same instance.

AGP

#11
Single-part objects are working! Now for the ones that have more than one part, could the following method be breaking something (currently one of the parts of the model animates properly while the rest stays still)? From what I understand, to be in an AnimatedGroup every Animated3D must share the same skeleton, so this method shouldn't break anything. Right?


private void attemptSkeletonInstanceFix() {//Gson Skeleton instance crap
     Skeleton skel = objects[0].getSkeleton();
     for (int i = 0; i < skinClipSequence.getSize(); i++) {
if (skinClipSequence.getClip(i).getSkeleton() != skel)
     skinClipSequence.getClip(i).skeleton = skel;
     }
     for (Animated3D object : objects)
object.currentPose.skeleton = skel;
}

raft

that's correct, every Animated3D must share the same skeleton to be in the same AnimatedGroup.

I cant see anything breaking the animation in that method.

AGP

After a lot of trial-and-error and writing and re-writing my loader on C#, I loaded the model and filled its SkinClips. Alas, the problem is now very similar to the one I had on that older project. The first screenshot shows the simple model properly loaded and not yet animated. The second shows it the second I call animateSkin(...). I have multiple frames for every animation (it's not that bunching-up-once-and-never-moving-again error), but the frames all destroy the model in similar ways.




AGP

It's working for one-part models in C# as well, and I get the same problem with multi-part models as I did in Java.

Here's a question so that I may solve the multiple Skeleton references once and for all: which are all the classes that hold an instance to Skeleton (I don't use IDEs and Windows is surprisingly not helpful even with the searches reading inside the files)?