snapRootBoneXZ: flachsten Joint mit Translations snappen statt nur Tiefe-0
Rigs wo Hips auf Tiefe 1 liegt (Kind des Root) wurden bisher nicht gesnappt weil nur Tiefe-0-Joints gefunden wurden. Jetzt wird die kleinste Tiefe unter allen Joints mit Translation-Track gesucht und nur diese Ebene eingefroren. Passt zu beiden Rig-Strukturen (Root-Translation und Hips-Translation). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -261,12 +261,29 @@ public class AnimationLibrary extends BaseAppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Friert X und Z des Root-Knochens (kein Eltern-Joint) auf den Wert von Frame 0 ein.
|
* Friert X und Z des "Hüft-Knochens" auf den Wert von Frame 0 ein.
|
||||||
* Y (Höhenachse, JME3 Y-Up) bleibt vollständig erhalten — sit_down / Jump / Bounce laufen korrekt.
|
* Y (Höhenachse, JME3 Y-Up) bleibt vollständig erhalten — sit_down / Jump / Bounce laufen korrekt.
|
||||||
|
*
|
||||||
|
* Strategie: findet die kleinste Tiefe unter allen Joints die einen Translation-Track haben.
|
||||||
|
* Bei Rigs wo Root (Tiefe 0) selbst Translations hat, wird Root gesnappt.
|
||||||
|
* Bei Rigs wo Hips (Tiefe 1) die erste Ebene mit Translations ist (Root hat nur Rotation),
|
||||||
|
* wird Hips gesnappt. So passt der Snap zu beiden Rig-Strukturen.
|
||||||
* Erstellt einen neuen in-memory-Clip; J3O-Dateien bleiben unverändert.
|
* Erstellt einen neuen in-memory-Clip; J3O-Dateien bleiben unverändert.
|
||||||
*/
|
*/
|
||||||
private static AnimClip snapRootBoneXZ(AnimClip clip, Armature armature) {
|
private static AnimClip snapRootBoneXZ(AnimClip clip, Armature armature) {
|
||||||
if (clip == null || armature == null) return clip;
|
if (clip == null || armature == null) return clip;
|
||||||
|
|
||||||
|
// Tiefe des flachsten Joints mit Translation-Track bestimmen
|
||||||
|
int minDepth = Integer.MAX_VALUE;
|
||||||
|
for (AnimTrack<?> track : clip.getTracks()) {
|
||||||
|
if (!(track instanceof TransformTrack tt) || !(tt.getTarget() instanceof Joint j)) continue;
|
||||||
|
Vector3f[] tr = tt.getTranslations();
|
||||||
|
if (tr != null && tr.length > 0) {
|
||||||
|
minDepth = Math.min(minDepth, jointDepth(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (minDepth == Integer.MAX_VALUE) return clip; // keine Translation-Tracks vorhanden
|
||||||
|
|
||||||
List<AnimTrack<?>> newTracks = new ArrayList<>();
|
List<AnimTrack<?>> newTracks = new ArrayList<>();
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (AnimTrack<?> track : clip.getTracks()) {
|
for (AnimTrack<?> track : clip.getTracks()) {
|
||||||
@@ -274,12 +291,8 @@ public class AnimationLibrary extends BaseAppState {
|
|||||||
newTracks.add(track);
|
newTracks.add(track);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (j.getParent() != null) {
|
|
||||||
newTracks.add(track);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Vector3f[] translations = tt.getTranslations();
|
Vector3f[] translations = tt.getTranslations();
|
||||||
if (translations == null || translations.length == 0) {
|
if (translations == null || translations.length == 0 || jointDepth(j) != minDepth) {
|
||||||
newTracks.add(track);
|
newTracks.add(track);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -291,8 +304,8 @@ public class AnimationLibrary extends BaseAppState {
|
|||||||
}
|
}
|
||||||
newTracks.add(new TransformTrack(j, tt.getTimes(), snapped, tt.getRotations(), tt.getScales()));
|
newTracks.add(new TransformTrack(j, tt.getTimes(), snapped, tt.getRotations(), tt.getScales()));
|
||||||
modified = true;
|
modified = true;
|
||||||
log.debug("[AnimLib] '{}': Root-Joint '{}' XZ={},{} eingefroren, Y frei",
|
log.info("[AnimLib] '{}': Tiefe-{}-Joint '{}' XZ={},{} eingefroren, Y frei",
|
||||||
clip.getName(), j.getName(), f0x, f0z);
|
clip.getName(), minDepth, j.getName(), f0x, f0z);
|
||||||
}
|
}
|
||||||
if (!modified) return clip;
|
if (!modified) return clip;
|
||||||
AnimClip result = new AnimClip(clip.getName());
|
AnimClip result = new AnimClip(clip.getName());
|
||||||
@@ -300,6 +313,13 @@ public class AnimationLibrary extends BaseAppState {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int jointDepth(Joint j) {
|
||||||
|
int d = 0;
|
||||||
|
Joint p = j.getParent();
|
||||||
|
while (p != null) { d++; p = p.getParent(); }
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
/** Loggt alle Tracks eines Clips: Bone-Name, hat Translation (T), Rotation (R), Scale (S). */
|
/** Loggt alle Tracks eines Clips: Bone-Name, hat Translation (T), Rotation (R), Scale (S). */
|
||||||
private void dumpClipTracks(com.jme3.anim.AnimClip clip) {
|
private void dumpClipTracks(com.jme3.anim.AnimClip clip) {
|
||||||
log.info("[ClipDump] '{}' length={}s tracks={}",
|
log.info("[ClipDump] '{}' length={}s tracks={}",
|
||||||
|
|||||||
Reference in New Issue
Block a user