|
|
@@ -23,7 +23,6 @@ void HumanoidPoseController::kneel(float depth) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Smooth easing for more natural motion
|
|
|
float const eased_depth = depth * depth * (3.0F - 2.0F * depth);
|
|
|
|
|
|
float const kneel_offset = eased_depth * 0.40F;
|
|
|
@@ -32,21 +31,19 @@ void HumanoidPoseController::kneel(float depth) {
|
|
|
|
|
|
float const stance_narrow = 0.11F;
|
|
|
|
|
|
- // Left leg (kneeling leg) - knee on ground
|
|
|
float const left_knee_y = HP::GROUND_Y + 0.07F * eased_depth;
|
|
|
float const left_knee_z = -0.06F * eased_depth;
|
|
|
m_pose.knee_l = QVector3D(-stance_narrow, left_knee_y, left_knee_z);
|
|
|
- m_pose.foot_l = QVector3D(-stance_narrow - 0.025F, HP::GROUND_Y,
|
|
|
- left_knee_z - HP::LOWER_LEG_LEN * 0.93F * eased_depth);
|
|
|
+ m_pose.foot_l =
|
|
|
+ QVector3D(-stance_narrow - 0.025F, HP::GROUND_Y,
|
|
|
+ left_knee_z - HP::LOWER_LEG_LEN * 0.93F * eased_depth);
|
|
|
|
|
|
- // Right leg (support leg) - foot planted forward
|
|
|
float const right_knee_y = pelvis_y - 0.12F;
|
|
|
float const right_foot_z = 0.28F * eased_depth;
|
|
|
m_pose.knee_r = QVector3D(stance_narrow, right_knee_y, right_foot_z - 0.05F);
|
|
|
m_pose.foot_r = QVector3D(stance_narrow, HP::GROUND_Y + m_pose.foot_y_offset,
|
|
|
right_foot_z);
|
|
|
|
|
|
- // Upper body follows down with slight forward lean for stability
|
|
|
float const upper_body_drop = kneel_offset;
|
|
|
float const forward_lean = 0.03F * eased_depth;
|
|
|
|
|
|
@@ -55,7 +52,6 @@ void HumanoidPoseController::kneel(float depth) {
|
|
|
m_pose.neck_base.setY(m_pose.neck_base.y() - upper_body_drop);
|
|
|
m_pose.head_pos.setY(m_pose.head_pos.y() - upper_body_drop);
|
|
|
|
|
|
- // Slight forward lean for braced stance
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() + forward_lean);
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + forward_lean);
|
|
|
m_pose.neck_base.setZ(m_pose.neck_base.z() + forward_lean * 0.8F);
|
|
|
@@ -67,93 +63,78 @@ void HumanoidPoseController::kneelTransition(float progress, bool standing_up) {
|
|
|
|
|
|
progress = std::clamp(progress, 0.0F, 1.0F);
|
|
|
|
|
|
- // Easing function for natural motion
|
|
|
auto ease_in_out = [](float t) { return t * t * (3.0F - 2.0F * t); };
|
|
|
|
|
|
- // When standing up, invert the progress
|
|
|
float kneel_amount = standing_up ? (1.0F - progress) : progress;
|
|
|
float eased_progress = ease_in_out(progress);
|
|
|
|
|
|
- // Apply base kneel position
|
|
|
kneel(kneel_amount);
|
|
|
|
|
|
if (standing_up) {
|
|
|
- // Standing up animation enhancements
|
|
|
- // Early phase: push with front leg, shift weight forward
|
|
|
+
|
|
|
if (progress < 0.35F) {
|
|
|
float t = progress / 0.35F;
|
|
|
float push_t = ease_in_out(t);
|
|
|
|
|
|
- // Push forward with supporting leg
|
|
|
m_pose.foot_r.setZ(m_pose.foot_r.z() - 0.08F * push_t);
|
|
|
m_pose.knee_r.setZ(m_pose.knee_r.z() - 0.05F * push_t);
|
|
|
|
|
|
- // Lean forward to build momentum
|
|
|
float momentum_lean = 0.06F * push_t;
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() + momentum_lean);
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + momentum_lean);
|
|
|
m_pose.neck_base.setZ(m_pose.neck_base.z() + momentum_lean * 0.9F);
|
|
|
m_pose.head_pos.setZ(m_pose.head_pos.z() + momentum_lean * 0.7F);
|
|
|
|
|
|
- // Arms help with momentum
|
|
|
m_pose.hand_l.setZ(m_pose.hand_l.z() + 0.04F * push_t);
|
|
|
m_pose.hand_r.setZ(m_pose.hand_r.z() + 0.04F * push_t);
|
|
|
}
|
|
|
- // Middle phase: rise up, bring back leg forward
|
|
|
+
|
|
|
else if (progress < 0.70F) {
|
|
|
float t = (progress - 0.35F) / 0.35F;
|
|
|
float rise_t = ease_in_out(t);
|
|
|
|
|
|
- // Slight upward momentum boost
|
|
|
float lift_boost = 0.02F * std::sin(rise_t * std::numbers::pi_v<float>);
|
|
|
m_pose.pelvis_pos.setY(m_pose.pelvis_pos.y() + lift_boost);
|
|
|
m_pose.shoulder_l.setY(m_pose.shoulder_l.y() + lift_boost);
|
|
|
m_pose.shoulder_r.setY(m_pose.shoulder_r.y() + lift_boost);
|
|
|
|
|
|
- // Bring kneeling leg forward
|
|
|
m_pose.foot_l.setZ(m_pose.foot_l.z() + 0.15F * rise_t);
|
|
|
m_pose.knee_l.setZ(m_pose.knee_l.z() + 0.10F * rise_t);
|
|
|
m_pose.knee_l.setY(m_pose.knee_l.y() + 0.20F * rise_t);
|
|
|
}
|
|
|
- // Final phase: settle into standing position
|
|
|
+
|
|
|
else {
|
|
|
float t = (progress - 0.70F) / 0.30F;
|
|
|
float settle_t = ease_in_out(t);
|
|
|
|
|
|
- // Return forward lean to neutral
|
|
|
float correct_lean = -0.04F * settle_t * (1.0F - kneel_amount);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() + correct_lean);
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + correct_lean);
|
|
|
}
|
|
|
} else {
|
|
|
- // Kneeling down animation enhancements
|
|
|
- // Early phase: shift weight, prepare to kneel
|
|
|
+
|
|
|
if (progress < 0.30F) {
|
|
|
float t = progress / 0.30F;
|
|
|
float prep_t = ease_in_out(t);
|
|
|
|
|
|
- // Shift weight back slightly
|
|
|
m_pose.pelvis_pos.setZ(m_pose.pelvis_pos.z() - 0.03F * prep_t);
|
|
|
|
|
|
- // Arms move to brace
|
|
|
m_pose.hand_l.setY(m_pose.hand_l.y() - 0.02F * prep_t);
|
|
|
m_pose.hand_r.setY(m_pose.hand_r.y() - 0.02F * prep_t);
|
|
|
}
|
|
|
- // Middle phase: controlled descent
|
|
|
+
|
|
|
else if (progress < 0.75F) {
|
|
|
float t = (progress - 0.30F) / 0.45F;
|
|
|
|
|
|
- // Controlled forward lean during descent
|
|
|
float controlled_lean = 0.04F * std::sin(t * std::numbers::pi_v<float>);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() + controlled_lean);
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + controlled_lean);
|
|
|
}
|
|
|
- // Final phase: settle into kneel
|
|
|
+
|
|
|
else {
|
|
|
float t = (progress - 0.75F) / 0.25F;
|
|
|
float settle_t = ease_in_out(t);
|
|
|
|
|
|
- // Small adjustment as knee touches ground
|
|
|
m_pose.knee_l.setY(m_pose.knee_l.y() - 0.01F * settle_t);
|
|
|
}
|
|
|
}
|
|
|
@@ -361,7 +342,6 @@ void HumanoidPoseController::meleeStrike(float strike_phase) {
|
|
|
|
|
|
strike_phase = std::clamp(strike_phase, 0.0F, 1.0F);
|
|
|
|
|
|
- // Define key positions for a natural horizontal slash toward the target
|
|
|
QVector3D const rest_pos(0.22F, HP::SHOULDER_Y + 0.02F, 0.18F);
|
|
|
QVector3D const chamber_pos(0.30F, HP::SHOULDER_Y + 0.08F, 0.05F);
|
|
|
QVector3D const strike_pos(0.28F, HP::SHOULDER_Y - 0.05F, 0.65F);
|
|
|
@@ -370,44 +350,42 @@ void HumanoidPoseController::meleeStrike(float strike_phase) {
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics
|
|
|
float torso_twist = 0.0F;
|
|
|
float forward_lean = 0.0F;
|
|
|
float shoulder_dip = 0.0F;
|
|
|
float step_forward = 0.0F;
|
|
|
|
|
|
if (strike_phase < 0.20F) {
|
|
|
- // Phase 1: Chamber - pull weapon back, twist torso away
|
|
|
+
|
|
|
float t = strike_phase / 0.20F;
|
|
|
float ease_t = t * t;
|
|
|
hand_r_target = rest_pos * (1.0F - ease_t) + chamber_pos * ease_t;
|
|
|
- hand_l_target = QVector3D(-0.18F, HP::SHOULDER_Y + 0.02F, 0.22F - 0.08F * t);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.18F, HP::SHOULDER_Y + 0.02F, 0.22F - 0.08F * t);
|
|
|
|
|
|
- // Twist torso back to coil for the strike
|
|
|
torso_twist = -0.04F * ease_t;
|
|
|
shoulder_dip = -0.02F * ease_t;
|
|
|
} else if (strike_phase < 0.28F) {
|
|
|
- // Phase 2: Brief anticipation hold
|
|
|
+
|
|
|
hand_r_target = chamber_pos;
|
|
|
hand_l_target = QVector3D(-0.18F, HP::SHOULDER_Y + 0.02F, 0.14F);
|
|
|
torso_twist = -0.04F;
|
|
|
shoulder_dip = -0.02F;
|
|
|
} else if (strike_phase < 0.48F) {
|
|
|
- // Phase 3: Explosive strike - uncoil torso, step forward
|
|
|
+
|
|
|
float t = (strike_phase - 0.28F) / 0.20F;
|
|
|
- float power_t = t * t * (3.0F - 2.0F * t); // smoothstep for power
|
|
|
+ float power_t = t * t * (3.0F - 2.0F * t);
|
|
|
hand_r_target = chamber_pos * (1.0F - power_t) + strike_pos * power_t;
|
|
|
hand_l_target = QVector3D(-0.18F + 0.06F * power_t,
|
|
|
HP::SHOULDER_Y + 0.02F - 0.08F * power_t,
|
|
|
0.14F + 0.20F * power_t);
|
|
|
|
|
|
- // Uncoil torso forward and rotate into strike
|
|
|
torso_twist = -0.04F + 0.10F * power_t;
|
|
|
forward_lean = 0.08F * power_t;
|
|
|
shoulder_dip = -0.02F + 0.05F * power_t;
|
|
|
step_forward = 0.06F * power_t;
|
|
|
} else if (strike_phase < 0.65F) {
|
|
|
- // Phase 4: Follow-through - weapon continues past target
|
|
|
+
|
|
|
float t = (strike_phase - 0.48F) / 0.17F;
|
|
|
float ease_t = t * t;
|
|
|
hand_r_target = strike_pos * (1.0F - ease_t) + followthrough_pos * ease_t;
|
|
|
@@ -418,14 +396,14 @@ void HumanoidPoseController::meleeStrike(float strike_phase) {
|
|
|
shoulder_dip = 0.03F;
|
|
|
step_forward = 0.06F;
|
|
|
} else {
|
|
|
- // Phase 5: Recovery - return to guard
|
|
|
+
|
|
|
float t = (strike_phase - 0.65F) / 0.35F;
|
|
|
float ease_t = 1.0F - (1.0F - t) * (1.0F - t);
|
|
|
hand_r_target = followthrough_pos * (1.0F - ease_t) + rest_pos * ease_t;
|
|
|
- hand_l_target = QVector3D(-0.12F + (-0.18F + 0.12F) * ease_t,
|
|
|
- HP::SHOULDER_Y - 0.06F * (1.0F - ease_t) +
|
|
|
- 0.02F * ease_t,
|
|
|
- 0.34F * (1.0F - ease_t) + 0.22F * ease_t);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.12F + (-0.18F + 0.12F) * ease_t,
|
|
|
+ HP::SHOULDER_Y - 0.06F * (1.0F - ease_t) + 0.02F * ease_t,
|
|
|
+ 0.34F * (1.0F - ease_t) + 0.22F * ease_t);
|
|
|
|
|
|
torso_twist = 0.04F * (1.0F - ease_t);
|
|
|
forward_lean = 0.05F * (1.0F - ease_t);
|
|
|
@@ -433,7 +411,6 @@ void HumanoidPoseController::meleeStrike(float strike_phase) {
|
|
|
step_forward = 0.06F * (1.0F - ease_t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.5F);
|
|
|
@@ -479,7 +456,6 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
|
|
|
attack_phase = std::clamp(attack_phase, 0.0F, 1.0F);
|
|
|
|
|
|
- // Key positions for a powerful spear thrust
|
|
|
QVector3D const guard_pos(0.26F, HP::SHOULDER_Y + 0.08F, 0.28F);
|
|
|
QVector3D const chamber_pos(0.32F, HP::SHOULDER_Y + 0.12F, 0.02F);
|
|
|
QVector3D const thrust_pos(0.28F, HP::SHOULDER_Y + 0.05F, 0.95F);
|
|
|
@@ -489,7 +465,6 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics for spear thrust
|
|
|
float forward_lean = 0.0F;
|
|
|
float torso_twist = 0.0F;
|
|
|
float shoulder_drop = 0.0F;
|
|
|
@@ -505,45 +480,44 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
auto ease_out = [](float t) { return 1.0F - (1.0F - t) * (1.0F - t); };
|
|
|
|
|
|
if (attack_phase < 0.18F) {
|
|
|
- // Phase 1: Chamber - pull spear back, coil body
|
|
|
+
|
|
|
float const t = easeInOutCubic(attack_phase / 0.18F);
|
|
|
hand_r_target = guard_pos * (1.0F - t) + chamber_pos * t;
|
|
|
hand_l_target = QVector3D(-0.08F, HP::SHOULDER_Y - 0.04F,
|
|
|
0.22F * (1.0F - t) + 0.06F * t);
|
|
|
|
|
|
- // Twist body back to load power
|
|
|
torso_twist = -0.06F * t;
|
|
|
hip_rotation = -0.04F * t;
|
|
|
- forward_lean = -0.03F * t; // Slight lean back
|
|
|
+ forward_lean = -0.03F * t;
|
|
|
} else if (attack_phase < 0.28F) {
|
|
|
- // Phase 2: Tension hold - brief pause before explosion
|
|
|
+
|
|
|
float const t = (attack_phase - 0.18F) / 0.10F;
|
|
|
hand_r_target = chamber_pos;
|
|
|
hand_l_target = QVector3D(-0.08F, HP::SHOULDER_Y - 0.04F, 0.06F);
|
|
|
|
|
|
torso_twist = -0.06F;
|
|
|
hip_rotation = -0.04F;
|
|
|
- forward_lean = -0.03F - 0.02F * t; // Slight additional coil
|
|
|
+ forward_lean = -0.03F - 0.02F * t;
|
|
|
} else if (attack_phase < 0.48F) {
|
|
|
- // Phase 3: Explosive thrust - uncoil and drive forward
|
|
|
+
|
|
|
float t = (attack_phase - 0.28F) / 0.20F;
|
|
|
float power_t = t * t * t;
|
|
|
hand_r_target = chamber_pos * (1.0F - power_t) + thrust_pos * power_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.08F + 0.06F * power_t, HP::SHOULDER_Y - 0.04F + 0.02F * power_t,
|
|
|
- 0.06F + 0.50F * power_t);
|
|
|
+ hand_l_target = QVector3D(-0.08F + 0.06F * power_t,
|
|
|
+ HP::SHOULDER_Y - 0.04F + 0.02F * power_t,
|
|
|
+ 0.06F + 0.50F * power_t);
|
|
|
|
|
|
- // Explosive uncoil
|
|
|
torso_twist = -0.06F + 0.14F * power_t;
|
|
|
hip_rotation = -0.04F + 0.10F * power_t;
|
|
|
forward_lean = -0.05F + 0.18F * power_t;
|
|
|
shoulder_drop = 0.05F * power_t;
|
|
|
step_forward = 0.10F * power_t;
|
|
|
} else if (attack_phase < 0.60F) {
|
|
|
- // Phase 4: Full extension - maximum reach
|
|
|
+
|
|
|
float const t = smoothstep((attack_phase - 0.48F) / 0.12F);
|
|
|
hand_r_target = thrust_pos * (1.0F - t) + extended_pos * t;
|
|
|
- hand_l_target = QVector3D(-0.02F, HP::SHOULDER_Y - 0.02F, 0.56F + 0.10F * t);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.02F, HP::SHOULDER_Y - 0.02F, 0.56F + 0.10F * t);
|
|
|
|
|
|
torso_twist = 0.08F;
|
|
|
hip_rotation = 0.06F;
|
|
|
@@ -551,7 +525,7 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
shoulder_drop = 0.05F + 0.02F * t;
|
|
|
step_forward = 0.10F + 0.04F * t;
|
|
|
} else if (attack_phase < 0.78F) {
|
|
|
- // Phase 5: Withdraw - pull back from extension
|
|
|
+
|
|
|
float const t = easeInOutCubic((attack_phase - 0.60F) / 0.18F);
|
|
|
hand_r_target = extended_pos * (1.0F - t) + recover_pos * t;
|
|
|
hand_l_target = QVector3D(-0.02F * (1.0F - t) - 0.08F * t,
|
|
|
@@ -564,7 +538,7 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
shoulder_drop = 0.07F * (1.0F - t);
|
|
|
step_forward = 0.14F * (1.0F - t * 0.5F);
|
|
|
} else {
|
|
|
- // Phase 6: Recovery - return to guard
|
|
|
+
|
|
|
float const t = ease_out((attack_phase - 0.78F) / 0.22F);
|
|
|
hand_r_target = recover_pos * (1.0F - t) + guard_pos * t;
|
|
|
hand_l_target =
|
|
|
@@ -575,7 +549,6 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
step_forward = 0.07F * (1.0F - t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.4F);
|
|
|
@@ -603,7 +576,6 @@ void HumanoidPoseController::spearThrust(float attack_phase) {
|
|
|
m_pose.foot_l.setZ(m_pose.foot_l.z() - step_forward * 0.15F);
|
|
|
}
|
|
|
|
|
|
- // Compute offhand grip along spear shaft
|
|
|
float const thrust_extent =
|
|
|
std::clamp((attack_phase - 0.18F) / 0.60F, 0.0F, 1.0F);
|
|
|
float const along_offset = -0.08F + 0.04F * thrust_extent;
|
|
|
@@ -623,20 +595,22 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
attack_phase = std::clamp(attack_phase, 0.0F, 1.0F);
|
|
|
hold_depth = std::clamp(hold_depth, 0.0F, 1.0F);
|
|
|
|
|
|
- // Calculate lowered positions based on hold depth
|
|
|
float const height_offset = -hold_depth * 0.35F;
|
|
|
|
|
|
- // Key positions adjusted for kneeling - spear angled forward/down
|
|
|
- QVector3D const guard_pos(0.22F, HP::SHOULDER_Y + height_offset + 0.05F, 0.32F);
|
|
|
- QVector3D const chamber_pos(0.28F, HP::SHOULDER_Y + height_offset + 0.10F, 0.08F);
|
|
|
- QVector3D const thrust_pos(0.24F, HP::SHOULDER_Y + height_offset - 0.08F, 0.90F);
|
|
|
- QVector3D const extended_pos(0.22F, HP::SHOULDER_Y + height_offset - 0.12F, 1.00F);
|
|
|
- QVector3D const recover_pos(0.24F, HP::SHOULDER_Y + height_offset + 0.02F, 0.48F);
|
|
|
+ QVector3D const guard_pos(0.22F, HP::SHOULDER_Y + height_offset + 0.05F,
|
|
|
+ 0.32F);
|
|
|
+ QVector3D const chamber_pos(0.28F, HP::SHOULDER_Y + height_offset + 0.10F,
|
|
|
+ 0.08F);
|
|
|
+ QVector3D const thrust_pos(0.24F, HP::SHOULDER_Y + height_offset - 0.08F,
|
|
|
+ 0.90F);
|
|
|
+ QVector3D const extended_pos(0.22F, HP::SHOULDER_Y + height_offset - 0.12F,
|
|
|
+ 1.00F);
|
|
|
+ QVector3D const recover_pos(0.24F, HP::SHOULDER_Y + height_offset + 0.02F,
|
|
|
+ 0.48F);
|
|
|
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics for kneeling thrust - limited due to position
|
|
|
float forward_lean = 0.0F;
|
|
|
float torso_twist = 0.0F;
|
|
|
float shoulder_extension = 0.0F;
|
|
|
@@ -646,7 +620,7 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
auto ease_in = [](float t) { return t * t; };
|
|
|
|
|
|
if (attack_phase < 0.15F) {
|
|
|
- // Phase 1: Quick chamber from braced position
|
|
|
+
|
|
|
float const t = ease_in(attack_phase / 0.15F);
|
|
|
hand_r_target = guard_pos * (1.0F - t) + chamber_pos * t;
|
|
|
hand_l_target = QVector3D(-0.06F, HP::SHOULDER_Y + height_offset - 0.03F,
|
|
|
@@ -654,13 +628,14 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
|
|
|
torso_twist = -0.04F * t;
|
|
|
} else if (attack_phase < 0.22F) {
|
|
|
- // Phase 2: Brief tension
|
|
|
+
|
|
|
hand_r_target = chamber_pos;
|
|
|
- hand_l_target = QVector3D(-0.06F, HP::SHOULDER_Y + height_offset - 0.03F, 0.10F);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.06F, HP::SHOULDER_Y + height_offset - 0.03F, 0.10F);
|
|
|
|
|
|
torso_twist = -0.04F;
|
|
|
} else if (attack_phase < 0.42F) {
|
|
|
- // Phase 3: Explosive thrust from kneeling - drive from hip
|
|
|
+
|
|
|
float t = (attack_phase - 0.22F) / 0.20F;
|
|
|
float power_t = t * t * t;
|
|
|
hand_r_target = chamber_pos * (1.0F - power_t) + thrust_pos * power_t;
|
|
|
@@ -669,12 +644,11 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
HP::SHOULDER_Y + height_offset - 0.03F + 0.01F * power_t,
|
|
|
0.10F + 0.48F * power_t);
|
|
|
|
|
|
- // Drive forward from braced position
|
|
|
torso_twist = -0.04F + 0.10F * power_t;
|
|
|
forward_lean = 0.12F * power_t;
|
|
|
shoulder_extension = 0.06F * power_t;
|
|
|
} else if (attack_phase < 0.55F) {
|
|
|
- // Phase 4: Full extension - maximum reach from kneel
|
|
|
+
|
|
|
float const t = smoothstep((attack_phase - 0.42F) / 0.13F);
|
|
|
hand_r_target = thrust_pos * (1.0F - t) + extended_pos * t;
|
|
|
hand_l_target = QVector3D(-0.01F, HP::SHOULDER_Y + height_offset - 0.02F,
|
|
|
@@ -684,37 +658,36 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
forward_lean = 0.12F + 0.04F * t;
|
|
|
shoulder_extension = 0.06F + 0.03F * t;
|
|
|
} else if (attack_phase < 0.75F) {
|
|
|
- // Phase 5: Withdraw back to braced position
|
|
|
+
|
|
|
float const t = smoothstep((attack_phase - 0.55F) / 0.20F);
|
|
|
hand_r_target = extended_pos * (1.0F - t) + recover_pos * t;
|
|
|
hand_l_target = QVector3D(-0.01F * (1.0F - t) - 0.05F * t,
|
|
|
- HP::SHOULDER_Y + height_offset - 0.02F * (1.0F - t) -
|
|
|
- 0.04F * t,
|
|
|
+ HP::SHOULDER_Y + height_offset -
|
|
|
+ 0.02F * (1.0F - t) - 0.04F * t,
|
|
|
0.66F * (1.0F - t) + 0.40F * t);
|
|
|
|
|
|
torso_twist = 0.06F * (1.0F - t);
|
|
|
forward_lean = 0.16F * (1.0F - t) + 0.03F * t;
|
|
|
shoulder_extension = 0.09F * (1.0F - t);
|
|
|
} else {
|
|
|
- // Phase 6: Return to guard in hold position
|
|
|
+
|
|
|
float const t = ease_out((attack_phase - 0.75F) / 0.25F);
|
|
|
hand_r_target = recover_pos * (1.0F - t) + guard_pos * t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.05F - 0.01F * t, HP::SHOULDER_Y + height_offset - 0.04F * (1.0F - t) -
|
|
|
- 0.03F * t,
|
|
|
- 0.40F * (1.0F - t) + 0.28F * t);
|
|
|
+ hand_l_target = QVector3D(-0.05F - 0.01F * t,
|
|
|
+ HP::SHOULDER_Y + height_offset -
|
|
|
+ 0.04F * (1.0F - t) - 0.03F * t,
|
|
|
+ 0.40F * (1.0F - t) + 0.28F * t);
|
|
|
|
|
|
forward_lean = 0.03F * (1.0F - t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics (limited by kneeling position)
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.3F);
|
|
|
}
|
|
|
|
|
|
if (forward_lean > 0.001F) {
|
|
|
- // When kneeling, lean is more from upper body only
|
|
|
+
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() + forward_lean);
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + forward_lean);
|
|
|
m_pose.neck_base.setZ(m_pose.neck_base.z() + forward_lean * 0.9F);
|
|
|
@@ -722,12 +695,11 @@ void HumanoidPoseController::spearThrustFromHold(float attack_phase,
|
|
|
}
|
|
|
|
|
|
if (shoulder_extension > 0.001F) {
|
|
|
- // Extend right shoulder forward for reach
|
|
|
+
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + shoulder_extension);
|
|
|
m_pose.shoulder_r.setY(m_pose.shoulder_r.y() - shoulder_extension * 0.3F);
|
|
|
}
|
|
|
|
|
|
- // Compute offhand grip
|
|
|
float const thrust_extent =
|
|
|
std::clamp((attack_phase - 0.15F) / 0.55F, 0.0F, 1.0F);
|
|
|
float const along_offset = -0.06F + 0.03F * thrust_extent;
|
|
|
@@ -745,7 +717,6 @@ void HumanoidPoseController::sword_slash(float attack_phase) {
|
|
|
|
|
|
attack_phase = std::clamp(attack_phase, 0.0F, 1.0F);
|
|
|
|
|
|
- // Key positions for a diagonal downward slash
|
|
|
QVector3D const rest_pos(0.20F, HP::SHOULDER_Y + 0.05F, 0.15F);
|
|
|
QVector3D const chamber_pos(0.28F, HP::SHOULDER_Y + 0.20F, 0.02F);
|
|
|
QVector3D const apex_pos(0.30F, HP::SHOULDER_Y + 0.25F, 0.08F);
|
|
|
@@ -756,7 +727,6 @@ void HumanoidPoseController::sword_slash(float attack_phase) {
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics
|
|
|
float torso_twist = 0.0F;
|
|
|
float forward_lean = 0.0F;
|
|
|
float shoulder_rotation = 0.0F;
|
|
|
@@ -767,17 +737,17 @@ void HumanoidPoseController::sword_slash(float attack_phase) {
|
|
|
auto ease_in = [](float t) { return t * t; };
|
|
|
|
|
|
if (attack_phase < 0.15F) {
|
|
|
- // Phase 1: Prepare - raise weapon to chamber position
|
|
|
+
|
|
|
float t = attack_phase / 0.15F;
|
|
|
float ease_t = ease_in(t);
|
|
|
hand_r_target = rest_pos * (1.0F - ease_t) + chamber_pos * ease_t;
|
|
|
- hand_l_target = QVector3D(-0.20F, HP::SHOULDER_Y - 0.02F, 0.15F + 0.02F * t);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.20F, HP::SHOULDER_Y - 0.02F, 0.15F + 0.02F * t);
|
|
|
|
|
|
- // Rotate shoulders back, coiling for strike
|
|
|
torso_twist = -0.05F * ease_t;
|
|
|
shoulder_rotation = 0.03F * ease_t;
|
|
|
} else if (attack_phase < 0.28F) {
|
|
|
- // Phase 2: Apex - weapon at highest point, brief tension
|
|
|
+
|
|
|
float t = (attack_phase - 0.15F) / 0.13F;
|
|
|
float ease_t = smoothstep(t);
|
|
|
hand_r_target = chamber_pos * (1.0F - ease_t) + apex_pos * ease_t;
|
|
|
@@ -785,23 +755,22 @@ void HumanoidPoseController::sword_slash(float attack_phase) {
|
|
|
|
|
|
torso_twist = -0.05F;
|
|
|
shoulder_rotation = 0.03F + 0.02F * ease_t;
|
|
|
- weight_shift = -0.02F * ease_t; // Weight shifts back before strike
|
|
|
+ weight_shift = -0.02F * ease_t;
|
|
|
} else if (attack_phase < 0.48F) {
|
|
|
- // Phase 3: Strike - explosive diagonal slash downward
|
|
|
+
|
|
|
float t = (attack_phase - 0.28F) / 0.20F;
|
|
|
- float power_t = t * t * t; // Fast acceleration
|
|
|
+ float power_t = t * t * t;
|
|
|
hand_r_target = apex_pos * (1.0F - power_t) + strike_pos * power_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.20F + 0.08F * power_t,
|
|
|
- HP::SHOULDER_Y - 0.04F - 0.06F * power_t, 0.17F + 0.22F * power_t);
|
|
|
+ hand_l_target = QVector3D(-0.20F + 0.08F * power_t,
|
|
|
+ HP::SHOULDER_Y - 0.04F - 0.06F * power_t,
|
|
|
+ 0.17F + 0.22F * power_t);
|
|
|
|
|
|
- // Explosive uncoil - torso rotates into strike, body leans forward
|
|
|
torso_twist = -0.05F + 0.14F * power_t;
|
|
|
forward_lean = 0.10F * power_t;
|
|
|
shoulder_rotation = 0.05F - 0.08F * power_t;
|
|
|
weight_shift = -0.02F + 0.08F * power_t;
|
|
|
} else if (attack_phase < 0.62F) {
|
|
|
- // Phase 4: Follow-through - weapon continues past target
|
|
|
+
|
|
|
float t = (attack_phase - 0.48F) / 0.14F;
|
|
|
float ease_t = smoothstep(t);
|
|
|
hand_r_target = strike_pos * (1.0F - ease_t) + followthrough_pos * ease_t;
|
|
|
@@ -811,22 +780,20 @@ void HumanoidPoseController::sword_slash(float attack_phase) {
|
|
|
forward_lean = 0.10F - 0.02F * t;
|
|
|
weight_shift = 0.06F;
|
|
|
} else {
|
|
|
- // Phase 5: Recovery - return to guard
|
|
|
+
|
|
|
float t = (attack_phase - 0.62F) / 0.38F;
|
|
|
float ease_t = ease_out(t);
|
|
|
- hand_r_target =
|
|
|
- followthrough_pos * (1.0F - ease_t) + recover_pos * 0.5F * ease_t +
|
|
|
- rest_pos * 0.5F * ease_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.12F - 0.08F * ease_t, HP::SHOULDER_Y - 0.10F * (1.0F - ease_t),
|
|
|
- 0.39F * (1.0F - ease_t) + 0.15F * ease_t);
|
|
|
+ hand_r_target = followthrough_pos * (1.0F - ease_t) +
|
|
|
+ recover_pos * 0.5F * ease_t + rest_pos * 0.5F * ease_t;
|
|
|
+ hand_l_target = QVector3D(-0.12F - 0.08F * ease_t,
|
|
|
+ HP::SHOULDER_Y - 0.10F * (1.0F - ease_t),
|
|
|
+ 0.39F * (1.0F - ease_t) + 0.15F * ease_t);
|
|
|
|
|
|
torso_twist = 0.06F * (1.0F - ease_t);
|
|
|
forward_lean = 0.08F * (1.0F - ease_t);
|
|
|
weight_shift = 0.06F * (1.0F - ease_t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.6F);
|
|
|
@@ -919,22 +886,19 @@ void HumanoidPoseController::sword_slash_variant(float attack_phase,
|
|
|
|
|
|
attack_phase = std::clamp(attack_phase, 0.0F, 1.0F);
|
|
|
|
|
|
- // Strike direction constants
|
|
|
constexpr float kStrikeRightToLeft = 1.0F;
|
|
|
constexpr float kStrikeLeftToRight = -1.0F;
|
|
|
|
|
|
- // Base positions - will be modified by variant
|
|
|
QVector3D rest_pos(0.20F, HP::SHOULDER_Y + 0.05F, 0.15F);
|
|
|
QVector3D chamber_pos(0.28F, HP::SHOULDER_Y + 0.20F, 0.02F);
|
|
|
QVector3D apex_pos(0.30F, HP::SHOULDER_Y + 0.25F, 0.08F);
|
|
|
QVector3D strike_pos(0.18F, HP::SHOULDER_Y - 0.15F, 0.62F);
|
|
|
QVector3D followthrough_pos(0.05F, HP::WAIST_Y + 0.10F, 0.50F);
|
|
|
|
|
|
- // Variant-specific attack patterns
|
|
|
float strike_direction = kStrikeRightToLeft;
|
|
|
switch (variant % 3) {
|
|
|
case 1:
|
|
|
- // Left-to-right diagonal slash
|
|
|
+
|
|
|
chamber_pos = QVector3D(-0.10F, HP::SHOULDER_Y + 0.22F, 0.04F);
|
|
|
apex_pos = QVector3D(-0.08F, HP::SHOULDER_Y + 0.28F, 0.10F);
|
|
|
strike_pos = QVector3D(0.32F, HP::SHOULDER_Y - 0.12F, 0.58F);
|
|
|
@@ -942,7 +906,7 @@ void HumanoidPoseController::sword_slash_variant(float attack_phase,
|
|
|
strike_direction = kStrikeLeftToRight;
|
|
|
break;
|
|
|
case 2:
|
|
|
- // Horizontal slash from right
|
|
|
+
|
|
|
chamber_pos = QVector3D(0.35F, HP::SHOULDER_Y + 0.10F, 0.0F);
|
|
|
apex_pos = QVector3D(0.38F, HP::SHOULDER_Y + 0.08F, 0.06F);
|
|
|
strike_pos = QVector3D(0.05F, HP::SHOULDER_Y - 0.05F, 0.65F);
|
|
|
@@ -955,7 +919,6 @@ void HumanoidPoseController::sword_slash_variant(float attack_phase,
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics
|
|
|
float torso_twist = 0.0F;
|
|
|
float forward_lean = 0.0F;
|
|
|
float shoulder_rotation = 0.0F;
|
|
|
@@ -985,9 +948,9 @@ void HumanoidPoseController::sword_slash_variant(float attack_phase,
|
|
|
float t = (attack_phase - 0.28F) / 0.20F;
|
|
|
float power_t = t * t * t;
|
|
|
hand_r_target = apex_pos * (1.0F - power_t) + strike_pos * power_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.20F + 0.08F * power_t,
|
|
|
- HP::SHOULDER_Y - 0.04F - 0.06F * power_t, 0.17F + 0.22F * power_t);
|
|
|
+ hand_l_target = QVector3D(-0.20F + 0.08F * power_t,
|
|
|
+ HP::SHOULDER_Y - 0.04F - 0.06F * power_t,
|
|
|
+ 0.17F + 0.22F * power_t);
|
|
|
|
|
|
torso_twist = strike_direction * (-0.05F + 0.14F * power_t);
|
|
|
forward_lean = 0.10F * power_t;
|
|
|
@@ -1006,16 +969,15 @@ void HumanoidPoseController::sword_slash_variant(float attack_phase,
|
|
|
float t = (attack_phase - 0.62F) / 0.38F;
|
|
|
float ease_t = ease_out(t);
|
|
|
hand_r_target = followthrough_pos * (1.0F - ease_t) + rest_pos * ease_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.12F - 0.08F * ease_t, HP::SHOULDER_Y - 0.10F * (1.0F - ease_t),
|
|
|
- 0.39F * (1.0F - ease_t) + 0.15F * ease_t);
|
|
|
+ hand_l_target = QVector3D(-0.12F - 0.08F * ease_t,
|
|
|
+ HP::SHOULDER_Y - 0.10F * (1.0F - ease_t),
|
|
|
+ 0.39F * (1.0F - ease_t) + 0.15F * ease_t);
|
|
|
|
|
|
torso_twist = 0.06F * strike_direction * (1.0F - ease_t);
|
|
|
forward_lean = 0.08F * (1.0F - ease_t);
|
|
|
weight_shift = 0.06F * (1.0F - ease_t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.6F);
|
|
|
@@ -1048,25 +1010,22 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
|
|
|
attack_phase = std::clamp(attack_phase, 0.0F, 1.0F);
|
|
|
|
|
|
- // Thrust height constants for variants
|
|
|
constexpr float kThrustHigh = 1.0F;
|
|
|
constexpr float kThrustMiddle = 0.0F;
|
|
|
constexpr float kThrustLow = -1.0F;
|
|
|
|
|
|
- // Base key positions
|
|
|
QVector3D guard_pos(0.26F, HP::SHOULDER_Y + 0.08F, 0.28F);
|
|
|
QVector3D chamber_pos(0.32F, HP::SHOULDER_Y + 0.12F, 0.02F);
|
|
|
QVector3D thrust_pos(0.28F, HP::SHOULDER_Y + 0.05F, 0.95F);
|
|
|
QVector3D extended_pos(0.25F, HP::SHOULDER_Y + 0.02F, 1.05F);
|
|
|
QVector3D recover_pos(0.28F, HP::SHOULDER_Y + 0.06F, 0.45F);
|
|
|
|
|
|
- // Variant-specific thrust patterns
|
|
|
float thrust_height = kThrustMiddle;
|
|
|
float crouch_amount = 0.0F;
|
|
|
|
|
|
switch (variant % 3) {
|
|
|
case 1:
|
|
|
- // Low thrust - target legs/lower body, with crouch
|
|
|
+
|
|
|
chamber_pos = QVector3D(0.30F, HP::SHOULDER_Y + 0.18F, 0.0F);
|
|
|
thrust_pos = QVector3D(0.28F, HP::WAIST_Y + 0.15F, 0.98F);
|
|
|
extended_pos = QVector3D(0.25F, HP::WAIST_Y + 0.10F, 1.08F);
|
|
|
@@ -1075,21 +1034,20 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
crouch_amount = 0.08F;
|
|
|
break;
|
|
|
case 2:
|
|
|
- // High thrust - target head/upper body, slight upward angle
|
|
|
+
|
|
|
chamber_pos = QVector3D(0.35F, HP::SHOULDER_Y + 0.05F, 0.08F);
|
|
|
thrust_pos = QVector3D(0.30F, HP::SHOULDER_Y + 0.12F, 0.92F);
|
|
|
extended_pos = QVector3D(0.28F, HP::SHOULDER_Y + 0.15F, 1.02F);
|
|
|
thrust_height = kThrustHigh;
|
|
|
break;
|
|
|
default:
|
|
|
- // Standard middle thrust
|
|
|
+
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
QVector3D hand_r_target;
|
|
|
QVector3D hand_l_target;
|
|
|
|
|
|
- // Body dynamics for spear thrust variant
|
|
|
float forward_lean = 0.0F;
|
|
|
float torso_twist = 0.0F;
|
|
|
float shoulder_drop = 0.0F;
|
|
|
@@ -1106,7 +1064,7 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
auto ease_out = [](float t) { return 1.0F - (1.0F - t) * (1.0F - t); };
|
|
|
|
|
|
if (attack_phase < 0.18F) {
|
|
|
- // Phase 1: Chamber - pull spear back, coil body
|
|
|
+
|
|
|
float const t = easeInOutCubic(attack_phase / 0.18F);
|
|
|
hand_r_target = guard_pos * (1.0F - t) + chamber_pos * t;
|
|
|
hand_l_target = QVector3D(-0.08F, HP::SHOULDER_Y - 0.04F,
|
|
|
@@ -1117,7 +1075,7 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
forward_lean = -0.03F * t;
|
|
|
crouch_factor = crouch_amount * t;
|
|
|
} else if (attack_phase < 0.28F) {
|
|
|
- // Phase 2: Tension hold
|
|
|
+
|
|
|
hand_r_target = chamber_pos;
|
|
|
hand_l_target = QVector3D(-0.08F, HP::SHOULDER_Y - 0.04F, 0.06F);
|
|
|
|
|
|
@@ -1126,13 +1084,13 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
forward_lean = -0.03F;
|
|
|
crouch_factor = crouch_amount;
|
|
|
} else if (attack_phase < 0.48F) {
|
|
|
- // Phase 3: Explosive thrust
|
|
|
+
|
|
|
float t = (attack_phase - 0.28F) / 0.20F;
|
|
|
float power_t = t * t * t;
|
|
|
hand_r_target = chamber_pos * (1.0F - power_t) + thrust_pos * power_t;
|
|
|
- hand_l_target =
|
|
|
- QVector3D(-0.08F + 0.06F * power_t, HP::SHOULDER_Y - 0.04F + 0.02F * power_t,
|
|
|
- 0.06F + 0.50F * power_t);
|
|
|
+ hand_l_target = QVector3D(-0.08F + 0.06F * power_t,
|
|
|
+ HP::SHOULDER_Y - 0.04F + 0.02F * power_t,
|
|
|
+ 0.06F + 0.50F * power_t);
|
|
|
|
|
|
torso_twist = -0.06F + 0.14F * power_t;
|
|
|
hip_rotation = -0.04F + 0.10F * power_t;
|
|
|
@@ -1141,19 +1099,19 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
step_forward = 0.12F * power_t;
|
|
|
crouch_factor = crouch_amount * (1.0F - power_t * 0.3F);
|
|
|
|
|
|
- // Adjust for thrust height
|
|
|
if (thrust_height < 0) {
|
|
|
- // Low thrust - additional crouch during strike
|
|
|
+
|
|
|
crouch_factor += 0.06F * power_t;
|
|
|
} else if (thrust_height > 0) {
|
|
|
- // High thrust - rise up slightly
|
|
|
+
|
|
|
crouch_factor -= 0.03F * power_t;
|
|
|
}
|
|
|
} else if (attack_phase < 0.60F) {
|
|
|
- // Phase 4: Full extension
|
|
|
+
|
|
|
float const t = smoothstep((attack_phase - 0.48F) / 0.12F);
|
|
|
hand_r_target = thrust_pos * (1.0F - t) + extended_pos * t;
|
|
|
- hand_l_target = QVector3D(-0.02F, HP::SHOULDER_Y - 0.02F, 0.56F + 0.10F * t);
|
|
|
+ hand_l_target =
|
|
|
+ QVector3D(-0.02F, HP::SHOULDER_Y - 0.02F, 0.56F + 0.10F * t);
|
|
|
|
|
|
torso_twist = 0.08F;
|
|
|
hip_rotation = 0.06F;
|
|
|
@@ -1162,7 +1120,7 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
step_forward = 0.12F + 0.04F * t;
|
|
|
crouch_factor = crouch_amount * 0.7F;
|
|
|
} else if (attack_phase < 0.78F) {
|
|
|
- // Phase 5: Withdraw
|
|
|
+
|
|
|
float const t = easeInOutCubic((attack_phase - 0.60F) / 0.18F);
|
|
|
hand_r_target = extended_pos * (1.0F - t) + recover_pos * t;
|
|
|
hand_l_target = QVector3D(-0.02F * (1.0F - t) - 0.08F * t,
|
|
|
@@ -1176,7 +1134,7 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
step_forward = 0.16F * (1.0F - t * 0.5F);
|
|
|
crouch_factor = crouch_amount * 0.7F * (1.0F - t);
|
|
|
} else {
|
|
|
- // Phase 6: Recovery
|
|
|
+
|
|
|
float const t = ease_out((attack_phase - 0.78F) / 0.22F);
|
|
|
hand_r_target = recover_pos * (1.0F - t) + guard_pos * t;
|
|
|
hand_l_target =
|
|
|
@@ -1187,7 +1145,6 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
step_forward = 0.08F * (1.0F - t);
|
|
|
}
|
|
|
|
|
|
- // Apply body dynamics
|
|
|
if (std::abs(torso_twist) > 0.001F) {
|
|
|
m_pose.shoulder_r.setZ(m_pose.shoulder_r.z() + torso_twist);
|
|
|
m_pose.shoulder_l.setZ(m_pose.shoulder_l.z() - torso_twist * 0.4F);
|
|
|
@@ -1215,7 +1172,6 @@ void HumanoidPoseController::spear_thrust_variant(float attack_phase,
|
|
|
m_pose.foot_l.setZ(m_pose.foot_l.z() - step_forward * 0.15F);
|
|
|
}
|
|
|
|
|
|
- // Apply crouch for low thrusts
|
|
|
if (crouch_factor > 0.001F) {
|
|
|
m_pose.pelvis_pos.setY(m_pose.pelvis_pos.y() - crouch_factor);
|
|
|
m_pose.shoulder_l.setY(m_pose.shoulder_l.y() - crouch_factor * 0.6F);
|