Weiter Ingame an den animationen gepfeilt
This commit is contained in:
@@ -336,21 +336,14 @@ public class AnimationLibrary extends BaseAppState {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Clips mit Vorwärts-Root-Motion in Local-Y (rennen, gehen, springen):
|
||||
// Y wird auf 0 eingefroren → kein Drift. Alle anderen Clips: Y bleibt frei (Hinsetzen usw.)
|
||||
private static final java.util.Set<String> LOCOMOTION_CLIPS = java.util.Set.of(
|
||||
"running", "walking", "sprinting", "running_jump"
|
||||
);
|
||||
|
||||
/**
|
||||
* Entfernt Root-Motion aus dem flachsten Bone mit Translation-Track (typischerweise Hips).
|
||||
* Nur dieser eine Bone wird modifiziert — alle anderen Bones bleiben unverändert.
|
||||
*
|
||||
* In diesen Mixamo-Exporten ist die Achsenbelegung des Hips-Bones:
|
||||
* Local X → seitlich → wird auf 0 eingefroren (kein Seiten-Drift)
|
||||
* Local Y → vorwärts → wird auf 0 eingefroren für Lauf-Clips (kein Vorwärts-Drift)
|
||||
* bleibt frei für Sitz/Stand-Clips (leichte Neigungsbewegung)
|
||||
* Local Z → Höhe → IMMER frei lassen (Charakter-Höhe und Setz-Bewegung erhalten)
|
||||
* Achsenbelegung dieses Mixamo-Exports im Hips-Bone-Local-Space:
|
||||
* Local X → JME3-X (seitlich) → wird auf 0 eingefroren
|
||||
* Local Y → JME3-Y (Höhe oben) → IMMER frei lassen (Charakter-Höhe erhalten)
|
||||
* Local Z → JME3-Z (vorwärts) → wird auf 0 eingefroren (alle Clips auf der Stelle)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static AnimClip snapRootBoneXZ(AnimClip clip, Armature armature) {
|
||||
@@ -367,8 +360,6 @@ public class AnimationLibrary extends BaseAppState {
|
||||
}
|
||||
if (minDepth == Integer.MAX_VALUE) return clip;
|
||||
|
||||
boolean isLocomotion = LOCOMOTION_CLIPS.contains(clip.getName().toLowerCase(java.util.Locale.ROOT));
|
||||
|
||||
List<AnimTrack<?>> newTracks = new ArrayList<>();
|
||||
boolean modified = false;
|
||||
for (AnimTrack<?> track : clip.getTracks()) {
|
||||
@@ -383,11 +374,6 @@ public class AnimationLibrary extends BaseAppState {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Y-Normalisierung für Nicht-Lauf-Clips: Frame-0 auf Bind-Pose-Y
|
||||
float bindY = j.getInitialTransform().getTranslation().y;
|
||||
float frame0Y = translations[0].y;
|
||||
float yOffset = bindY - frame0Y;
|
||||
|
||||
// Diagnostik
|
||||
float yMin = Float.MAX_VALUE, yMax = -Float.MAX_VALUE;
|
||||
float xRange = 0, zRange = 0;
|
||||
@@ -397,21 +383,18 @@ public class AnimationLibrary extends BaseAppState {
|
||||
xRange = Math.max(xRange, Math.abs(t.x - translations[0].x));
|
||||
zRange = Math.max(zRange, Math.abs(t.z - translations[0].z));
|
||||
}
|
||||
log.info("[AnimLib] snap '{}' root='{}' locomotion={} bindY={} frame0Y={} yOffset={} yRange={} xRange={} zRange={}",
|
||||
clip.getName(), j.getName(), isLocomotion,
|
||||
String.format("%.3f", bindY), String.format("%.3f", frame0Y),
|
||||
String.format("%.3f", yOffset), String.format("%.3f", yMax - yMin),
|
||||
String.format("%.3f", xRange), String.format("%.3f", zRange));
|
||||
log.info("[AnimLib] snap '{}' root='{}' xRange={} yRange={} zRange={}",
|
||||
clip.getName(), j.getName(),
|
||||
String.format("%.3f", xRange),
|
||||
String.format("%.3f", yMax - yMin),
|
||||
String.format("%.3f", zRange));
|
||||
|
||||
Vector3f[] snapped = new Vector3f[translations.length];
|
||||
for (int i = 0; i < translations.length; i++) {
|
||||
float newY = isLocomotion
|
||||
? 0f // Lauf-Clips: Y einfrieren (Vorwärts-Drift weg)
|
||||
: (translations[i].y + yOffset); // Rest: Y normalisiert (Neigung erhalten)
|
||||
snapped[i] = new Vector3f(
|
||||
0f, // X immer 0 (Seiten-Drift weg)
|
||||
newY,
|
||||
translations[i].z // Z immer frei (Höhe und Setz-Bewegung erhalten)
|
||||
0f, // X = 0 (kein seitlicher Drift)
|
||||
translations[i].y, // Y frei (Höhe; Y=oben in bone-local / JME3-Y)
|
||||
0f // Z = 0 (kein Vorwärts-Drift; Z=vorwärts in bone-local)
|
||||
);
|
||||
}
|
||||
newTracks.add(new TransformTrack(j, tt.getTimes(), snapped, tt.getRotations(), tt.getScales()));
|
||||
|
||||
@@ -168,7 +168,7 @@ public class PlayerInputControl {
|
||||
visualBaseTranslation = visual.getLocalTranslation().clone();
|
||||
}
|
||||
try {
|
||||
AnimSet as = AnimSet.load(assetRoot.resolve("animations/sets"), animSetName);
|
||||
AnimSet as = AnimSet.load(assetRoot.resolve("Characters").resolve("sets"), animSetName);
|
||||
animOffsets = as.getAnimOffsets();
|
||||
log.info("[AnimCtx] {} Anim-Offset-Einträge geladen.", animOffsets.size());
|
||||
} catch (Exception e) {
|
||||
@@ -629,6 +629,7 @@ public class PlayerInputControl {
|
||||
}
|
||||
String clip = AnimationLibrary.getClipForAction(assetRoot, animSetName, action);
|
||||
log.info("[Anim] {} → clip='{}' (set={})", action, clip, animSetName);
|
||||
if (runningClip != null) nextTransitionLength = 0.15;
|
||||
if (clip != null && tryPlay(clip)) return;
|
||||
if (action != AnimationAction.DEFAULT) {
|
||||
String defClip = AnimationLibrary.getClipForAction(assetRoot, animSetName, AnimationAction.DEFAULT);
|
||||
|
||||
@@ -277,6 +277,12 @@ public class CharacterNavigator {
|
||||
}
|
||||
if (clip == null) return;
|
||||
if (!animLib.applyTo(clip, visual)) return;
|
||||
if (currentAnim != null) {
|
||||
com.jme3.anim.tween.action.Action nextAction = animComposer.action(clip);
|
||||
if (nextAction instanceof com.jme3.anim.tween.action.BlendableAction ba) {
|
||||
ba.setTransitionLength(0.15);
|
||||
}
|
||||
}
|
||||
com.jme3.anim.tween.action.Action act = animComposer.setCurrentAction(clip);
|
||||
if (act == null) return;
|
||||
if (skinningControl != null && !skinningControl.isEnabled()) {
|
||||
|
||||
Reference in New Issue
Block a user