diff --git a/assets/imported/animations/sitting.glb b/assets/imported/animations/sitting_bench.glb
similarity index 96%
rename from assets/imported/animations/sitting.glb
rename to assets/imported/animations/sitting_bench.glb
index 527905a..f47b3c1 100644
Binary files a/assets/imported/animations/sitting.glb and b/assets/imported/animations/sitting_bench.glb differ
diff --git a/assets/imported/animations/get_up_sitting.glb b/assets/imported/animations/stand_up_bench.glb
similarity index 99%
rename from assets/imported/animations/get_up_sitting.glb
rename to assets/imported/animations/stand_up_bench.glb
index 938f52f..99c6391 100644
Binary files a/assets/imported/animations/get_up_sitting.glb and b/assets/imported/animations/stand_up_bench.glb differ
diff --git a/assets/imported/animations/standup.glb b/assets/imported/animations/standup.glb
deleted file mode 100644
index a8f4b47..0000000
Binary files a/assets/imported/animations/standup.glb and /dev/null differ
diff --git a/blight-assets/src/main/resources/animations/clips/alive_again.j3o b/blight-assets/src/main/resources/animations/clips/alive_again.j3o
index c02ba23..33dcfcc 100644
Binary files a/blight-assets/src/main/resources/animations/clips/alive_again.j3o and b/blight-assets/src/main/resources/animations/clips/alive_again.j3o differ
diff --git a/blight-assets/src/main/resources/animations/clips/idle_jump.j3o b/blight-assets/src/main/resources/animations/clips/idle_jump.j3o
index 374e699..9f99790 100644
Binary files a/blight-assets/src/main/resources/animations/clips/idle_jump.j3o and b/blight-assets/src/main/resources/animations/clips/idle_jump.j3o differ
diff --git a/blight-assets/src/main/resources/animations/clips/sitting.j3o b/blight-assets/src/main/resources/animations/clips/sitting_bench.j3o
similarity index 93%
rename from blight-assets/src/main/resources/animations/clips/sitting.j3o
rename to blight-assets/src/main/resources/animations/clips/sitting_bench.j3o
index 80ad1b2..13a7ac5 100644
Binary files a/blight-assets/src/main/resources/animations/clips/sitting.j3o and b/blight-assets/src/main/resources/animations/clips/sitting_bench.j3o differ
diff --git a/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o b/blight-assets/src/main/resources/animations/clips/stand_up_bench.j3o
similarity index 99%
rename from blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o
rename to blight-assets/src/main/resources/animations/clips/stand_up_bench.j3o
index 1c6b149..45c4e30 100644
Binary files a/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o and b/blight-assets/src/main/resources/animations/clips/stand_up_bench.j3o differ
diff --git a/blight-assets/src/main/resources/animations/clips/standup.j3o b/blight-assets/src/main/resources/animations/clips/standup.j3o
deleted file mode 100644
index f3b210d..0000000
Binary files a/blight-assets/src/main/resources/animations/clips/standup.j3o and /dev/null differ
diff --git a/blight-assets/src/main/resources/animations/clips/tpose.j3o b/blight-assets/src/main/resources/animations/clips/tpose.j3o
index 465c246..8da9796 100644
Binary files a/blight-assets/src/main/resources/animations/clips/tpose.j3o and b/blight-assets/src/main/resources/animations/clips/tpose.j3o differ
diff --git a/blight-assets/src/main/resources/animations/sets/human.animset.json b/blight-assets/src/main/resources/animations/sets/human.animset.json
index 083ea5c..c3aba07 100644
--- a/blight-assets/src/main/resources/animations/sets/human.animset.json
+++ b/blight-assets/src/main/resources/animations/sets/human.animset.json
@@ -1,18 +1,19 @@
{
"clips": [
- "get_up_sitting",
+ "alive_again",
"idle",
"idle_jump",
"pickup",
"running",
"running_jump",
- "sitting",
+ "sit_down_bench",
+ "sitting_bench",
"sitting_floor",
"sprinting",
"stand_up",
+ "stand_up_bench",
"tpose",
- "walking",
- "sit_down_bench"
+ "walking"
],
"actionMap": {
"DEFAULT": "tpose",
@@ -20,12 +21,13 @@
"WALK": "walking",
"RUN": "running",
"SPRINT": "sprinting",
- "RUNNING_JUMP": "running_jump",
"JUMP": "idle_jump",
+ "RUNNING_JUMP": "running_jump",
"PICK_UP": "pickup",
- "SITTING": "sitting",
"SIT_DOWN": "sit_down_bench",
- "SIT_UP": "get_up_sitting"
+ "SIT_UP": "stand_up_bench",
+ "SITTING": "sitting_bench",
+ "REVIVE": "alive_again"
},
"previewModelPath": "Models/Chars/mainchar.j3o",
"motionKeyframes": {
diff --git a/blight-editor/src/main/resources/logback.xml b/blight-editor/src/main/resources/logback.xml
index 0ab35b2..eb72a9b 100644
--- a/blight-editor/src/main/resources/logback.xml
+++ b/blight-editor/src/main/resources/logback.xml
@@ -25,6 +25,7 @@
+
diff --git a/blight-game/src/main/java/de/blight/game/animation/AnimOffset.java b/blight-game/src/main/java/de/blight/game/animation/AnimOffset.java
new file mode 100644
index 0000000..9a76704
--- /dev/null
+++ b/blight-game/src/main/java/de/blight/game/animation/AnimOffset.java
@@ -0,0 +1,22 @@
+package de.blight.game.animation;
+
+/**
+ * Positions-/Rotations-Versatz für eine blockierende Animation.
+ *
+ * TX/TZ: Versatz in Charakter-lokalem Raum (TX=seitlich, TZ=vorwärts relativ zur Blickrichtung).
+ * TY: Versatz in Welt-Y (hoch/runter).
+ * RX/RY/RZ: Additiver Rotations-Versatz in Grad (Euler XYZ, relativ zur Startrotation).
+ */
+public class AnimOffset {
+
+ public float tx, ty, tz; // Positions-Versatz (Meter)
+ public float rx, ry, rz; // Rotations-Versatz (Grad)
+
+ public AnimOffset() {}
+
+ public AnimOffset(float tx, float ty, float tz,
+ float rx, float ry, float rz) {
+ this.tx = tx; this.ty = ty; this.tz = tz;
+ this.rx = rx; this.ry = ry; this.rz = rz;
+ }
+}
diff --git a/blight-game/src/main/java/de/blight/game/animation/FootIKControl.java b/blight-game/src/main/java/de/blight/game/animation/FootIKControl.java
new file mode 100644
index 0000000..f4d9496
--- /dev/null
+++ b/blight-game/src/main/java/de/blight/game/animation/FootIKControl.java
@@ -0,0 +1,226 @@
+package de.blight.game.animation;
+
+import com.jme3.anim.Armature;
+import com.jme3.anim.Joint;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.ViewPort;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.control.AbstractControl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 2-Bone-Foot-IK – hält die Füße an ihrer World-Space-Position fest.
+ *
+ * Muss NACH AnimComposer und SkinningControl zur Spatial hinzugefügt werden,
+ * damit controlUpdate() nach der Animations-Anwendung läuft.
+ */
+public final class FootIKControl extends AbstractControl {
+
+ private static final Logger log = LoggerFactory.getLogger(FootIKControl.class);
+
+ private final Armature armature;
+
+ private final Joint leftThigh, leftCalf, leftFoot;
+ private final Joint rightThigh, rightCalf, rightFoot;
+
+ // IK-Ziele in World-Space; null = IK inaktiv
+ private Vector3f leftWorldTarget = null;
+ private Vector3f rightWorldTarget = null;
+
+ private static final float MIN_CORRECTION_DIST = 0.005f;
+
+ private int debugFramesLeft = 0;
+
+ public FootIKControl(Armature armature) {
+ this.armature = armature;
+ leftThigh = findJoint(armature, "L_Thigh", "LeftUpLeg", "mixamorig:LeftUpLeg");
+ leftCalf = findJoint(armature, "L_Calf", "LeftLeg", "mixamorig:LeftLeg");
+ leftFoot = findJoint(armature, "L_Foot", "LeftFoot", "mixamorig:LeftFoot");
+ rightThigh = findJoint(armature, "R_Thigh", "RightUpLeg", "mixamorig:RightUpLeg");
+ rightCalf = findJoint(armature, "R_Calf", "RightLeg", "mixamorig:RightLeg");
+ rightFoot = findJoint(armature, "R_Foot", "RightFoot", "mixamorig:RightFoot");
+ log.info("[FootIK] Init: L={} R={}",
+ leftFoot != null ? leftFoot.getName() : "n/a",
+ rightFoot != null ? rightFoot.getName() : "n/a");
+ }
+
+ /**
+ * Fixiert die Füße an ihrer aktuellen World-Space-Position.
+ * Muss aufgerufen werden NACHDEM die neue Animation gesetzt wurde,
+ * aber BEVOR der kfOffset die Armature verschoben hat.
+ */
+ public void lockFeetAtCurrentWorldPos() {
+ Spatial sp = getSpatial();
+ if (sp == null || leftFoot == null || rightFoot == null) {
+ return;
+ }
+ leftWorldTarget = sp.localToWorld(
+ leftFoot.getModelTransform().getTranslation().clone(), new Vector3f());
+ rightWorldTarget = sp.localToWorld(
+ rightFoot.getModelTransform().getTranslation().clone(), new Vector3f());
+ debugFramesLeft = 10;
+ log.info("[FootIK] LockWorld: L={} R={}", fv(leftWorldTarget), fv(rightWorldTarget));
+ }
+
+ public void releaseFeet() {
+ leftWorldTarget = null;
+ rightWorldTarget = null;
+ debugFramesLeft = 0;
+ log.info("[FootIK] Freigegeben");
+ }
+
+ public boolean isActive() {
+ return leftWorldTarget != null || rightWorldTarget != null;
+ }
+
+ // ── Control-Update ────────────────────────────────────────────────────────
+
+ @Override
+ protected void controlUpdate(float tpf) {
+ if (leftWorldTarget == null && rightWorldTarget == null) {
+ return;
+ }
+
+ Spatial sp = getSpatial();
+ if (sp == null) {
+ return;
+ }
+
+ boolean dbg = debugFramesLeft > 0;
+ if (dbg) {
+ debugFramesLeft--;
+ }
+
+ if (leftWorldTarget != null && leftThigh != null && leftCalf != null && leftFoot != null) {
+ Vector3f modelTarget = sp.worldToLocal(leftWorldTarget, new Vector3f());
+ solveLeg(leftThigh, leftCalf, leftFoot, modelTarget, dbg, "L");
+ }
+ if (rightWorldTarget != null && rightThigh != null && rightCalf != null && rightFoot != null) {
+ Vector3f modelTarget = sp.worldToLocal(rightWorldTarget, new Vector3f());
+ solveLeg(rightThigh, rightCalf, rightFoot, modelTarget, dbg, "R");
+ }
+
+ armature.update();
+ }
+
+ @Override
+ protected void controlRender(RenderManager rm, ViewPort vp) {}
+
+ // ── 2-Bone-IK-Solver ─────────────────────────────────────────────────────
+
+ private void solveLeg(Joint thigh, Joint calf, Joint foot,
+ Vector3f target, boolean dbg, String side) {
+ Vector3f A = thigh.getModelTransform().getTranslation().clone();
+ Vector3f B = calf.getModelTransform().getTranslation().clone();
+ Vector3f C = foot.getModelTransform().getTranslation().clone();
+
+ float L1 = A.distance(B);
+ float L2 = B.distance(C);
+ if (L1 < 0.0001f || L2 < 0.0001f) {
+ return;
+ }
+
+ float footErr = C.distance(target);
+ if (dbg) {
+ log.info("[FootIK][{}] A={} B={} C={} T={} err={} L1={} L2={}",
+ side, fv(A), fv(B), fv(C), fv(target),
+ String.format("%.4f", footErr),
+ String.format("%.3f", L1), String.format("%.3f", L2));
+ }
+ if (footErr < MIN_CORRECTION_DIST) {
+ return;
+ }
+
+ float d = A.distance(target);
+ d = FastMath.clamp(d, Math.abs(L1 - L2) + 0.0001f, L1 + L2 - 0.0001f);
+
+ float cosA = (L1 * L1 + d * d - L2 * L2) / (2f * L1 * d);
+ float angleA = FastMath.acos(FastMath.clamp(cosA, -1f, 1f));
+
+ Vector3f dirAT = target.subtract(A).normalizeLocal();
+ Vector3f kneeDir = B.subtract(A).normalizeLocal();
+ float proj = dirAT.dot(kneeDir);
+ Vector3f perp = kneeDir.subtract(dirAT.mult(proj));
+ if (perp.lengthSquared() < 0.0001f) {
+ perp = findPerp(dirAT);
+ }
+ perp.normalizeLocal();
+
+ Vector3f B_new = A.add(
+ dirAT.mult(L1 * FastMath.cos(angleA)).addLocal(
+ perp.mult(L1 * FastMath.sin(angleA)))
+ );
+
+ // Oberschenkel rotieren
+ Vector3f curThighDir = B.subtract(A).normalizeLocal();
+ Vector3f dstThighDir = B_new.subtract(A).normalizeLocal();
+ Quaternion thighArc = rotArc(curThighDir, dstThighDir);
+ Quaternion thighModelRot = thigh.getModelTransform().getRotation().clone();
+ Quaternion newThighModelRot = thighArc.mult(thighModelRot);
+ Joint thighParent = thigh.getParent();
+ Quaternion parentRot = thighParent != null
+ ? thighParent.getModelTransform().getRotation() : new Quaternion();
+ thigh.setLocalRotation(parentRot.inverse().mult(newThighModelRot));
+
+ // Unterschenkel rotieren — Calf-Richtung NACH der Thigh-Rotation verwenden
+ Vector3f curCalfDirOrig = C.subtract(B).normalizeLocal();
+ Vector3f curCalfDirRotated = thighArc.mult(curCalfDirOrig);
+ Vector3f dstCalfDir = target.subtract(B_new).normalizeLocal();
+ Quaternion calfArc = rotArc(curCalfDirRotated, dstCalfDir);
+ Quaternion oldCalfLocalRot = calf.getLocalRotation().clone();
+ Quaternion actualCalfModel = newThighModelRot.mult(oldCalfLocalRot);
+ Quaternion newCalfModelRot = calfArc.mult(actualCalfModel);
+ calf.setLocalRotation(newThighModelRot.inverse().mult(newCalfModelRot));
+
+ if (dbg) {
+ float thighAngle = thighArc.toAngleAxis(new Vector3f()) * FastMath.RAD_TO_DEG;
+ float calfAngle = calfArc.toAngleAxis(new Vector3f()) * FastMath.RAD_TO_DEG;
+ log.info("[FootIK][{}] B_new={} thigh={}° calf={}°",
+ side, fv(B_new),
+ String.format("%.1f", thighAngle),
+ String.format("%.1f", calfAngle));
+ }
+ }
+
+ // ── Hilfsmethoden ────────────────────────────────────────────────────────
+
+ private static Quaternion rotArc(Vector3f from, Vector3f to) {
+ float dot = FastMath.clamp(from.dot(to), -1f, 1f);
+ if (dot > 0.9999f) {
+ return new Quaternion();
+ }
+ if (dot < -0.9999f) {
+ return new Quaternion().fromAngleAxis(FastMath.PI, findPerp(from));
+ }
+ Vector3f axis = from.cross(to).normalizeLocal();
+ Quaternion q = new Quaternion();
+ q.fromAngleAxis(FastMath.acos(dot), axis);
+ return q;
+ }
+
+ private static Vector3f findPerp(Vector3f v) {
+ Vector3f p = v.cross(Vector3f.UNIT_X);
+ if (p.lengthSquared() < 0.0001f) {
+ p = v.cross(Vector3f.UNIT_Z);
+ }
+ return p.normalizeLocal();
+ }
+
+ private static Joint findJoint(Armature arm, String... names) {
+ for (String n : names) {
+ Joint j = arm.getJoint(n);
+ if (j != null) {
+ return j;
+ }
+ }
+ return null;
+ }
+
+ private static String fv(Vector3f v) {
+ return String.format("(%.3f,%.3f,%.3f)", v.x, v.y, v.z);
+ }
+}
diff --git a/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java b/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java
index f30a063..3c514ae 100644
--- a/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java
+++ b/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java
@@ -557,7 +557,7 @@ public class PlayerInputControl {
public void clearKfOffset() {
log.info("[KF] clearKfOffset() → Lerp zu 0, current=({},{},{})", kfOffsetCurrent.x, kfOffsetCurrent.y, kfOffsetCurrent.z);
kfOffsetTarget.set(0, 0, 0);
- kfOffsetSpeed = 5.0f; // 0.25m in ~3 Frames bei 60fps
+ kfOffsetSpeed = 5.0f;
}
private void clearMotionKfOffset() {
diff --git a/blight-game/src/main/resources/logback.xml b/blight-game/src/main/resources/logback.xml
index 0a9fd60..338cdce 100644
--- a/blight-game/src/main/resources/logback.xml
+++ b/blight-game/src/main/resources/logback.xml
@@ -2,7 +2,7 @@
- ERROR
+ INFO
%d{HH:mm:ss.SSS} %-5level [%logger{30}] %msg%n%ex