Compare commits
3 Commits
21c8af0105
...
6bb195da90
| Author | SHA1 | Date | |
|---|---|---|---|
| 6bb195da90 | |||
| b498d0fd5b | |||
| 911b512208 |
@@ -13,13 +13,13 @@
|
|||||||
"grip": {
|
"grip": {
|
||||||
"posX": 0.10248406,
|
"posX": 0.10248406,
|
||||||
"posY": 0.104730606,
|
"posY": 0.104730606,
|
||||||
"posZ": 0.5130257,
|
"posZ": 0.4630257,
|
||||||
"rotX": 0.0,
|
"rotX": 0.0,
|
||||||
"rotY": 0.0,
|
"rotY": 0.0,
|
||||||
"rotZ": 0.0,
|
"rotZ": 0.0,
|
||||||
"grip2PosX": 0.0024840608,
|
"grip2PosX": 0.0024840608,
|
||||||
"grip2PosY": 0.104730606,
|
"grip2PosY": 0.104730606,
|
||||||
"grip2PosZ": 0.5630257,
|
"grip2PosZ": 0.6630257,
|
||||||
"handOffsetX": 0.0,
|
"handOffsetX": 0.0,
|
||||||
"handOffsetY": 0.0,
|
"handOffsetY": 0.0,
|
||||||
"handOffsetZ": 0.0
|
"handOffsetZ": 0.0
|
||||||
|
|||||||
@@ -37,20 +37,22 @@ public class GripEditorController implements ItemEditorView.GripEditorLauncher {
|
|||||||
public void applyGripGuess(float gX, float gY, float gZ) {
|
public void applyGripGuess(float gX, float gY, float gZ) {
|
||||||
if (posXSpin == null) return;
|
if (posXSpin == null) return;
|
||||||
suppressSpinnerEvents = true;
|
suppressSpinnerEvents = true;
|
||||||
|
float bladeDirZ = ctx.input().gripEditorBladeDirZ; // -1 = Klinge bei -Z, +1 = Klinge bei +Z
|
||||||
|
// 5cm Richtung Pommel von der erkannten Parierstange
|
||||||
|
float posZ = gZ + bladeDirZ * 0.05f;
|
||||||
posXSpin.getValueFactory().setValue((double) gX);
|
posXSpin.getValueFactory().setValue((double) gX);
|
||||||
posYSpin.getValueFactory().setValue((double) gY);
|
posYSpin.getValueFactory().setValue((double) gY);
|
||||||
posZSpin.getValueFactory().setValue((double) gZ);
|
posZSpin.getValueFactory().setValue((double) posZ);
|
||||||
// Rotation zurücksetzen: Schaft zeigt zur Klinge, gelber Stab nach oben
|
// Rotation zurücksetzen: Schaft zeigt zur Klinge, gelber Stab nach oben
|
||||||
rotXSpin.getValueFactory().setValue(0.0);
|
rotXSpin.getValueFactory().setValue(0.0);
|
||||||
rotYSpin.getValueFactory().setValue(0.0);
|
rotYSpin.getValueFactory().setValue(0.0);
|
||||||
rotZSpin.getValueFactory().setValue(0.0);
|
rotZSpin.getValueFactory().setValue(0.0);
|
||||||
// 2. Griff (linke Hand): direkt angrenzend an den 1. Griff, 5cm weiter Richtung Pommel.
|
// 2. Griff (linke Hand): 20cm Richtung Pommel vom 1. Griff (Zweihänder-Grifflänge).
|
||||||
// Grip2-Spinner = Modell-Koordinaten direkt (kein HAND_GRIP_OFFSET), deshalb JSON-Pos von Grip1 verwenden.
|
// Grip2-Spinner = Modell-Koordinaten direkt (kein HAND_GRIP_OFFSET), deshalb JSON-Pos von Grip1 verwenden.
|
||||||
float bladeDirZ = ctx.input().gripEditorBladeDirZ; // -1 = Klinge bei -Z, +1 = Klinge bei +Z
|
float grip1JsonZ = posZ + ItemGrip.HAND_GRIP_OFFSET_Z;
|
||||||
float grip1JsonZ = gZ + ItemGrip.HAND_GRIP_OFFSET_Z;
|
|
||||||
grip2XSpin.getValueFactory().setValue((double) gX);
|
grip2XSpin.getValueFactory().setValue((double) gX);
|
||||||
grip2YSpin.getValueFactory().setValue((double) gY);
|
grip2YSpin.getValueFactory().setValue((double) gY);
|
||||||
grip2ZSpin.getValueFactory().setValue((double)(grip1JsonZ - bladeDirZ * 0.05f));
|
grip2ZSpin.getValueFactory().setValue((double)(grip1JsonZ - bladeDirZ * 0.20f));
|
||||||
suppressSpinnerEvents = false;
|
suppressSpinnerEvents = false;
|
||||||
onSpinnerChanged();
|
onSpinnerChanged();
|
||||||
}
|
}
|
||||||
@@ -220,7 +222,7 @@ public class GripEditorController implements ItemEditorView.GripEditorLauncher {
|
|||||||
row("Z:", rotZSpin),
|
row("Z:", rotZSpin),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
styledTitle("2. Griff – Linke Hand (m)"),
|
styledTitle("2. Griff – Linke Hand (m)"),
|
||||||
styledHint("Zweiter Griffpunkt (blaues Gizmo) für Zweihänder.\nDirekt angrenzend an den 1. Griff, Richtung Knauf."),
|
styledHint("Zweiter Griffpunkt (blaues Gizmo) für Zweihänder.\n~20cm Richtung Knauf vom 1. Griff."),
|
||||||
row("X:", grip2XSpin),
|
row("X:", grip2XSpin),
|
||||||
row("Y:", grip2YSpin),
|
row("Y:", grip2YSpin),
|
||||||
row("Z:", grip2ZSpin),
|
row("Z:", grip2ZSpin),
|
||||||
|
|||||||
@@ -222,38 +222,41 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
|
|||||||
s.setLocalTranslation(weaponPos);
|
s.setLocalTranslation(weaponPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Zweihänder: Schwert dreht sich frei um Griff1 (rechte Handteller-Innenfläche) als Pivot;
|
|
||||||
* die Richtung wird so gewählt, dass Griff2 so nah wie möglich am linken Handteller liegt.
|
|
||||||
*/
|
|
||||||
private void applyTwoHandTransform(Spatial s, Vector3f bonePosInChar, Quaternion boneRotInChar,
|
private void applyTwoHandTransform(Spatial s, Vector3f bonePosInChar, Quaternion boneRotInChar,
|
||||||
ItemGrip grip, Quaternion charWorldRotInv, Vector3f charWorldPos) {
|
ItemGrip grip, Quaternion charWorldRotInv, Vector3f charWorldPos) {
|
||||||
Quaternion gripRot = new Quaternion().fromAngles(
|
Quaternion gripRot = new Quaternion().fromAngles(
|
||||||
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
|
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
|
||||||
Quaternion animDelta = (handBindRotInChar != null)
|
Quaternion animDelta = (handBindRotInChar != null)
|
||||||
? boneRotInChar.mult(handBindRotInChar.inverse()) : boneRotInChar;
|
? boneRotInChar.mult(handBindRotInChar.inverse()) : boneRotInChar;
|
||||||
boolean bladeAtMinusZ3 = grip.getGrip2PosZ() > grip.getPosZ();
|
boolean bladeAtMinusZ = grip.getGrip2PosZ() > grip.getPosZ();
|
||||||
Quaternion bladeFlip3 = bladeAtMinusZ3
|
Quaternion bladeFlip = bladeAtMinusZ
|
||||||
? new Quaternion().fromAngles(com.jme3.math.FastMath.PI, 0f, 0f)
|
? new Quaternion().fromAngles(com.jme3.math.FastMath.PI, 0f, 0f)
|
||||||
: new Quaternion();
|
: new Quaternion();
|
||||||
Quaternion weaponRot = animDelta.mult(bladeFlip3).mult(gripRot.inverse());
|
Quaternion weaponRot = animDelta.mult(bladeFlip).mult(gripRot.inverse());
|
||||||
|
|
||||||
// Griff-Achse im Modell-Space: Griff1 → Griff2
|
|
||||||
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
|
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
|
||||||
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
|
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
|
||||||
Vector3f modelGripAxis = g2.subtract(g1).normalizeLocal();
|
// Griffspanne virtuell auf 22cm; g1 (rechte Hand) 10cm weiter Richtung Klinge
|
||||||
Vector3f currentGripAxis = weaponRot.mult(modelGripAxis);
|
Vector3f gripAxis = g1.subtract(g2).normalizeLocal();
|
||||||
|
Vector3f gripCenter = g1.add(g2).multLocal(0.5f);
|
||||||
|
g1 = gripCenter.add(gripAxis.mult(0.21f));
|
||||||
|
g2 = gripCenter.subtract(gripAxis.mult(0.11f));
|
||||||
|
Vector3f leftHandInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
|
||||||
|
Quaternion leftBoneRotInChar = charWorldRotInv.mult(leftForeArmNode.getWorldRotation());
|
||||||
|
Vector3f leftHandballen = (palmOffsetLocal != null)
|
||||||
|
? leftHandInChar.subtract(leftBoneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
|
||||||
|
: leftHandInChar;
|
||||||
|
leftHandballen.addLocal(0.10f, 0f, 0f);
|
||||||
|
|
||||||
// Zielachse: rechtes Handgelenk → linkes Handgelenk im Char-Space
|
// Swing: Griffachse auf linken Handballen ausrichten (inkl. X-Korrektur)
|
||||||
Vector3f rightWristInChar = charWorldRotInv.mult(handNode.getWorldTranslation().subtract(charWorldPos));
|
Vector3f currentGripDir = weaponRot.mult(g2.subtract(g1).normalizeLocal());
|
||||||
Vector3f leftWristInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
|
Vector3f targetDir = leftHandballen.subtract(bonePosInChar).normalizeLocal();
|
||||||
Vector3f targetGripAxis = leftWristInChar.subtract(rightWristInChar).normalizeLocal();
|
float dot = currentGripDir.dot(targetDir);
|
||||||
|
if (dot > 0f) {
|
||||||
|
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
|
||||||
|
}
|
||||||
|
|
||||||
Quaternion swingCorr = swingFromTo(currentGripAxis, targetGripAxis);
|
// g1 exakt an der rechten Hand anpinnen — linke-Hand-Korrekturen beeinflussen rechte nicht
|
||||||
weaponRot = swingCorr.mult(weaponRot);
|
|
||||||
|
|
||||||
// Grip1 direkt am Handteller platzieren (bonePosInChar enthält palmOffset bereits).
|
|
||||||
// Kein zusätzlicher HAND_GRIP_OFFSET – wir haben die exakten Greifpositionen.
|
|
||||||
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
|
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
|
||||||
s.setLocalRotation(weaponRot);
|
s.setLocalRotation(weaponRot);
|
||||||
s.setLocalTranslation(weaponPos);
|
s.setLocalTranslation(weaponPos);
|
||||||
@@ -262,15 +265,15 @@ public class NpcWeaponAttachmentControl extends AbstractControl {
|
|||||||
private static Quaternion swingFromTo(Vector3f from, Vector3f to) {
|
private static Quaternion swingFromTo(Vector3f from, Vector3f to) {
|
||||||
float dot = com.jme3.math.FastMath.clamp(from.dot(to), -1f, 1f);
|
float dot = com.jme3.math.FastMath.clamp(from.dot(to), -1f, 1f);
|
||||||
Vector3f axis = from.cross(to);
|
Vector3f axis = from.cross(to);
|
||||||
float axisLen = axis.length();
|
float len = axis.length();
|
||||||
if (axisLen < 0.001f) {
|
if (len < 0.001f) {
|
||||||
if (dot > 0f) return new Quaternion();
|
if (dot > 0f) return new Quaternion();
|
||||||
Vector3f perp = Math.abs(from.x) <= Math.abs(from.y)
|
Vector3f perp = Math.abs(from.x) <= Math.abs(from.y)
|
||||||
? from.cross(Vector3f.UNIT_X).normalizeLocal()
|
? from.cross(Vector3f.UNIT_X).normalizeLocal()
|
||||||
: from.cross(Vector3f.UNIT_Y).normalizeLocal();
|
: from.cross(Vector3f.UNIT_Y).normalizeLocal();
|
||||||
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.PI, perp);
|
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.PI, perp);
|
||||||
}
|
}
|
||||||
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.acos(dot), axis.divideLocal(axisLen));
|
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.acos(dot), axis.divideLocal(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Quaternion BACK_ROT_NORM = new Quaternion(0f, -(float) Math.sqrt(0.5), (float) Math.sqrt(0.5), 0f);
|
private static final Quaternion BACK_ROT_NORM = new Quaternion(0f, -(float) Math.sqrt(0.5), (float) Math.sqrt(0.5), 0f);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class WeaponAttachmentControl extends AbstractControl {
|
|||||||
private Item lastEquippedWeapon;
|
private Item lastEquippedWeapon;
|
||||||
private boolean lastDrawnState = false;
|
private boolean lastDrawnState = false;
|
||||||
private Spatial weaponSpatial;
|
private Spatial weaponSpatial;
|
||||||
private boolean gripDiagLogged = false;
|
private boolean gripDiagLogged = false;
|
||||||
|
|
||||||
private Item lastEquippedShield;
|
private Item lastEquippedShield;
|
||||||
private Spatial shieldSpatial;
|
private Spatial shieldSpatial;
|
||||||
@@ -270,43 +270,44 @@ public class WeaponAttachmentControl extends AbstractControl {
|
|||||||
weaponSpatial.setLocalTranslation(weaponPos);
|
weaponSpatial.setLocalTranslation(weaponPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Zweihänder-Constraint: orientiert die Waffe so, dass die Linie grip1→grip2 (Modell-Space)
|
|
||||||
* auf die Linie RightHand→LeftHand (Char-Space) zeigt. Roll bleibt aus gripRot erhalten.
|
|
||||||
*/
|
|
||||||
private void applyTwoHandTransform(Vector3f bonePosInChar, Quaternion boneRotInChar,
|
private void applyTwoHandTransform(Vector3f bonePosInChar, Quaternion boneRotInChar,
|
||||||
ItemGrip grip,
|
ItemGrip grip,
|
||||||
Quaternion charWorldRotInv, Vector3f charWorldPos) {
|
Quaternion charWorldRotInv, Vector3f charWorldPos) {
|
||||||
// Erst Standard-Einhand-Rotation berechnen (gibt Roll-Basis aus gripRot)
|
// Basis-Rotation aus rechter Hand (gibt Roll/Handflächenausrichtung)
|
||||||
Quaternion gripRot = new Quaternion().fromAngles(
|
Quaternion gripRot = new Quaternion().fromAngles(
|
||||||
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
|
DEG_TO_RAD * grip.getRotX(), DEG_TO_RAD * grip.getRotY(), DEG_TO_RAD * grip.getRotZ());
|
||||||
Quaternion animDelta = (handBindRotInChar != null)
|
Quaternion animDelta = (handBindRotInChar != null)
|
||||||
? boneRotInChar.mult(handBindRotInChar.inverse()) : boneRotInChar;
|
? boneRotInChar.mult(handBindRotInChar.inverse()) : boneRotInChar;
|
||||||
boolean bladeAtMinusZ3 = grip.getGrip2PosZ() > grip.getPosZ();
|
boolean bladeAtMinusZ = grip.getGrip2PosZ() > grip.getPosZ();
|
||||||
Quaternion bladeFlip3 = bladeAtMinusZ3
|
Quaternion bladeFlip = bladeAtMinusZ
|
||||||
? new Quaternion().fromAngles(com.jme3.math.FastMath.PI, 0f, 0f)
|
? new Quaternion().fromAngles(com.jme3.math.FastMath.PI, 0f, 0f)
|
||||||
: new Quaternion();
|
: new Quaternion();
|
||||||
Quaternion weaponRot = animDelta.mult(bladeFlip3).mult(gripRot.inverse());
|
Quaternion weaponRot = animDelta.mult(bladeFlip).mult(gripRot.inverse());
|
||||||
|
|
||||||
// Griff-Achse im Modell-Space: grip1 → grip2
|
|
||||||
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
|
Vector3f g1 = new Vector3f(grip.getPosX(), grip.getPosY(), grip.getPosZ());
|
||||||
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
|
Vector3f g2 = new Vector3f(grip.getGrip2PosX(), grip.getGrip2PosY(), grip.getGrip2PosZ());
|
||||||
Vector3f modelGripAxis = g2.subtract(g1).normalizeLocal();
|
// Griffspanne virtuell auf 22cm; g1 (rechte Hand) 10cm weiter Richtung Klinge
|
||||||
|
Vector3f gripAxis = g1.subtract(g2).normalizeLocal();
|
||||||
|
Vector3f gripCenter = g1.add(g2).multLocal(0.5f);
|
||||||
|
g1 = gripCenter.add(gripAxis.mult(0.21f));
|
||||||
|
g2 = gripCenter.subtract(gripAxis.mult(0.11f));
|
||||||
|
Vector3f leftHandInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
|
||||||
|
// Linke Hand: Handballen-Korrektur (Palm-Offset entgegen Fingerrichtung) – nur für midTarget, nicht für targetDir
|
||||||
|
Quaternion leftBoneRotInChar = charWorldRotInv.mult(leftForeArmNode.getWorldRotation());
|
||||||
|
Vector3f leftHandballen = (palmOffsetLocal != null)
|
||||||
|
? leftHandInChar.subtract(leftBoneRotInChar.mult(palmOffsetLocal.mult(0.5f)))
|
||||||
|
: leftHandInChar;
|
||||||
|
leftHandballen.addLocal(0.10f, 0f, 0f);
|
||||||
|
|
||||||
// Aktuelle Griff-Achse im Char-Space (nach Einhand-Rotation)
|
// Swing: Griffachse auf linken Handballen ausrichten (inkl. X-Korrektur)
|
||||||
Vector3f currentGripAxis = weaponRot.mult(modelGripAxis);
|
Vector3f currentGripDir = weaponRot.mult(g2.subtract(g1).normalizeLocal());
|
||||||
|
Vector3f targetDir = leftHandballen.subtract(bonePosInChar).normalizeLocal();
|
||||||
|
float dot = currentGripDir.dot(targetDir);
|
||||||
|
if (dot > 0f) {
|
||||||
|
weaponRot = swingFromTo(currentGripDir, targetDir).mult(weaponRot);
|
||||||
|
}
|
||||||
|
|
||||||
// Ziel-Achse: rechtes Handgelenk → linkes Handgelenk im Char-Space
|
// g1 exakt an der rechten Hand anpinnen — linke-Hand-Korrekturen beeinflussen rechte nicht
|
||||||
Vector3f rightWristInChar = charWorldRotInv.mult(handNode.getWorldTranslation().subtract(charWorldPos));
|
|
||||||
Vector3f leftWristInChar = charWorldRotInv.mult(leftForeArmNode.getWorldTranslation().subtract(charWorldPos));
|
|
||||||
Vector3f targetGripAxis = leftWristInChar.subtract(rightWristInChar).normalizeLocal();
|
|
||||||
|
|
||||||
// Minimale Swing-Rotation: dreht currentGripAxis → targetGripAxis, kein Roll-Einfluss
|
|
||||||
Quaternion swingCorr = swingFromTo(currentGripAxis, targetGripAxis);
|
|
||||||
weaponRot = swingCorr.mult(weaponRot);
|
|
||||||
|
|
||||||
// Grip1 direkt am Handteller platzieren (bonePosInChar enthält palmOffset bereits).
|
|
||||||
// Kein zusätzlicher HAND_GRIP_OFFSET – wir haben die exakten Greifpositionen.
|
|
||||||
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
|
Vector3f weaponPos = bonePosInChar.subtract(weaponRot.mult(g1));
|
||||||
weaponSpatial.setLocalRotation(weaponRot);
|
weaponSpatial.setLocalRotation(weaponRot);
|
||||||
weaponSpatial.setLocalTranslation(weaponPos);
|
weaponSpatial.setLocalTranslation(weaponPos);
|
||||||
@@ -315,15 +316,15 @@ public class WeaponAttachmentControl extends AbstractControl {
|
|||||||
private static Quaternion swingFromTo(Vector3f from, Vector3f to) {
|
private static Quaternion swingFromTo(Vector3f from, Vector3f to) {
|
||||||
float dot = com.jme3.math.FastMath.clamp(from.dot(to), -1f, 1f);
|
float dot = com.jme3.math.FastMath.clamp(from.dot(to), -1f, 1f);
|
||||||
Vector3f axis = from.cross(to);
|
Vector3f axis = from.cross(to);
|
||||||
float axisLen = axis.length();
|
float len = axis.length();
|
||||||
if (axisLen < 0.001f) {
|
if (len < 0.001f) {
|
||||||
if (dot > 0f) return new Quaternion();
|
if (dot > 0f) return new Quaternion();
|
||||||
Vector3f perp = Math.abs(from.x) <= Math.abs(from.y)
|
Vector3f perp = Math.abs(from.x) <= Math.abs(from.y)
|
||||||
? from.cross(Vector3f.UNIT_X).normalizeLocal()
|
? from.cross(Vector3f.UNIT_X).normalizeLocal()
|
||||||
: from.cross(Vector3f.UNIT_Y).normalizeLocal();
|
: from.cross(Vector3f.UNIT_Y).normalizeLocal();
|
||||||
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.PI, perp);
|
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.PI, perp);
|
||||||
}
|
}
|
||||||
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.acos(dot), axis.divideLocal(axisLen));
|
return new Quaternion().fromAngleNormalAxis(com.jme3.math.FastMath.acos(dot), axis.divideLocal(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float round1(float v) { return Math.round(v * 10f) / 10f; }
|
private static float round1(float v) { return Math.round(v * 10f) / 10f; }
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ public class WorldItemsState extends BaseAppState {
|
|||||||
boolean doLog = hoverLogTimer >= 1f && !items.isEmpty();
|
boolean doLog = hoverLogTimer >= 1f && !items.isEmpty();
|
||||||
if (hoverLogTimer >= 1f) hoverLogTimer = 0f;
|
if (hoverLogTimer >= 1f) hoverLogTimer = 0f;
|
||||||
if (doLog) {
|
if (doLog) {
|
||||||
log.info("[Hover] items={} screenW={} screenH={} centerX={} hMargin={}",
|
log.debug("[Hover] items={} screenW={} screenH={} centerX={} hMargin={}",
|
||||||
items.size(), cam.getWidth(), cam.getHeight(), centerX, hMargin);
|
items.size(), cam.getWidth(), cam.getHeight(), centerX, hMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,39 +261,39 @@ public class WorldItemsState extends BaseAppState {
|
|||||||
|
|
||||||
// Distanz vom Charakter (nicht von der Kamera)
|
// Distanz vom Charakter (nicht von der Kamera)
|
||||||
float charDist = worldPos.distance(charPos);
|
float charDist = worldPos.distance(charPos);
|
||||||
if (doLog) log.info("[Hover] item[{}] id={} charDist={}", i, pi.itemId(), charDist);
|
if (doLog) log.debug("[Hover] item[{}] id={} charDist={}", i, pi.itemId(), charDist);
|
||||||
|
|
||||||
if (charDist > INTERACT_RANGE) {
|
if (charDist > INTERACT_RANGE) {
|
||||||
if (doLog) log.info("[Hover] → skip: außerhalb Reichweite ({} > {})", charDist, INTERACT_RANGE);
|
if (doLog) log.debug("[Hover] → skip: außerhalb Reichweite ({} > {})", charDist, INTERACT_RANGE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Muss vor der Kamera liegen
|
// Muss vor der Kamera liegen
|
||||||
Vector3f camToItem = worldPos.subtract(cam.getLocation());
|
Vector3f camToItem = worldPos.subtract(cam.getLocation());
|
||||||
if (camToItem.dot(cam.getDirection()) <= 0f) {
|
if (camToItem.dot(cam.getDirection()) <= 0f) {
|
||||||
if (doLog) log.info("[Hover] → skip: hinter der Kamera");
|
if (doLog) log.debug("[Hover] → skip: hinter der Kamera");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bildschirmprojektion (von der Kamera aus)
|
// Bildschirmprojektion (von der Kamera aus)
|
||||||
Vector3f screen = cam.getScreenCoordinates(worldPos);
|
Vector3f screen = cam.getScreenCoordinates(worldPos);
|
||||||
float hDiff = Math.abs(screen.x - centerX);
|
float hDiff = Math.abs(screen.x - centerX);
|
||||||
if (doLog) log.info("[Hover] screen=({},{},{}) hDiff={} hMargin={}",
|
if (doLog) log.debug("[Hover] screen=({},{},{}) hDiff={} hMargin={}",
|
||||||
(int)screen.x, (int)screen.y, screen.z, (int)hDiff, (int)hMargin);
|
(int)screen.x, (int)screen.y, screen.z, (int)hDiff, (int)hMargin);
|
||||||
|
|
||||||
if (hDiff > hMargin) {
|
if (hDiff > hMargin) {
|
||||||
if (doLog) log.info("[Hover] → skip: horizontal außerhalb Mitte");
|
if (doLog) log.debug("[Hover] → skip: horizontal außerhalb Mitte");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (screen.y < 0f || screen.y > screenH) {
|
if (screen.y < 0f || screen.y > screenH) {
|
||||||
if (doLog) log.info("[Hover] → skip: vertikal außerhalb Bildschirm");
|
if (doLog) log.debug("[Hover] → skip: vertikal außerhalb Bildschirm");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verdeckungsprüfung: Strahl von Kamera zum Item
|
// Verdeckungsprüfung: Strahl von Kamera zum Item
|
||||||
float camDist = camToItem.length();
|
float camDist = camToItem.length();
|
||||||
if (isOccluded(camToItem.normalize(), camDist, i, doLog)) {
|
if (isOccluded(camToItem.normalize(), camDist, i, doLog)) {
|
||||||
if (doLog) log.info("[Hover] → skip: verdeckt");
|
if (doLog) log.debug("[Hover] → skip: verdeckt");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ public class WorldItemsState extends BaseAppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doLog) log.info("[Hover] → hoveredIdx={}", bestIdx);
|
if (doLog) log.debug("[Hover] → hoveredIdx={}", bestIdx);
|
||||||
setHovered(bestIdx);
|
setHovered(bestIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,25 +312,25 @@ public class WorldItemsState extends BaseAppState {
|
|||||||
CollisionResults results = new CollisionResults();
|
CollisionResults results = new CollisionResults();
|
||||||
rootNode.collideWith(ray, results);
|
rootNode.collideWith(ray, results);
|
||||||
|
|
||||||
if (doLog) log.info("[Hover] occlusion: {} Treffer, itemDist={:.2f}", results.size(), itemDist);
|
if (doLog) log.debug("[Hover] occlusion: {} Treffer, itemDist={:.2f}", results.size(), itemDist);
|
||||||
|
|
||||||
for (int j = 0; j < results.size(); j++) {
|
for (int j = 0; j < results.size(); j++) {
|
||||||
CollisionResult cr = results.getCollision(j);
|
CollisionResult cr = results.getCollision(j);
|
||||||
float d = cr.getDistance();
|
float d = cr.getDistance();
|
||||||
if (d < 1.5f) {
|
if (d < 1.5f) {
|
||||||
if (doLog) log.info("[Hover] [{}] d={:.2f} → Nah-Clip skip ({})", j, d, cr.getGeometry().getName());
|
if (doLog) log.debug("[Hover] [{}] d={:.2f} → Nah-Clip skip ({})", j, d, cr.getGeometry().getName());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (d > itemDist - 0.15f) {
|
if (d > itemDist - 0.15f) {
|
||||||
if (doLog) log.info("[Hover] [{}] d={:.2f} → am/hinter Item, kein Blocker ({})", j, d, cr.getGeometry().getName());
|
if (doLog) log.debug("[Hover] [{}] d={:.2f} → am/hinter Item, kein Blocker ({})", j, d, cr.getGeometry().getName());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int vidx = findVisualIndex(cr.getGeometry());
|
int vidx = findVisualIndex(cr.getGeometry());
|
||||||
if (vidx == itemIdx) {
|
if (vidx == itemIdx) {
|
||||||
if (doLog) log.info("[Hover] [{}] d={:.2f} → Item selbst ({})", j, d, cr.getGeometry().getName());
|
if (doLog) log.debug("[Hover] [{}] d={:.2f} → Item selbst ({})", j, d, cr.getGeometry().getName());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (doLog) log.info("[Hover] [{}] d={:.2f} → BLOCKIERT durch '{}'", j, d, cr.getGeometry().getName());
|
if (doLog) log.debug("[Hover] [{}] d={:.2f} → BLOCKIERT durch '{}'", j, d, cr.getGeometry().getName());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user