Merge branch 'combat' of https://gitlab.com/veloren/veloren into combat

This commit is contained in:
Adam Whitehurst 2020-03-21 07:08:14 -07:00
commit 79de60d791
16 changed files with 623 additions and 560 deletions

View File

@ -5,6 +5,7 @@ use crate::{
character_behavior::{CharacterBehavior, JoinData},
phys::GRAVITY,
},
util::safe_slerp,
};
use std::collections::VecDeque;
use vek::{
@ -67,16 +68,11 @@ impl CharacterBehavior for Data {
};
// Smooth orientation
if ori_dir.magnitude_squared() > 0.0001
&& (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared()
> 0.001
{
update.ori.0 = vek::ops::Slerp::slerp(
update.ori.0,
ori_dir.into(),
if data.physics.on_ground { 9.0 } else { 2.0 } * data.dt.0,
);
}
update.ori.0 = safe_slerp(
update.ori.0,
ori_dir.into(),
if data.physics.on_ground { 9.0 } else { 2.0 } * data.dt.0,
);
// Apply Vertical Climbing Movement
if let (true, Some(_wall_dir)) = (

View File

@ -1,6 +1,7 @@
use crate::{
comp::{Attacking, CharacterState, EnergySource, StateUpdate},
sys::character_behavior::*,
util::safe_slerp,
};
use std::{collections::VecDeque, time::Duration};
use vek::Vec3;
@ -34,7 +35,6 @@ impl CharacterBehavior for Data {
if self.initialize {
update.vel.0 = data.inputs.look_dir * 20.0;
update.ori.0 = update.vel.0;
}
if self.buildup_duration != Duration::default() && data.physics.touch_entity.is_none() {
@ -99,6 +99,8 @@ impl CharacterBehavior for Data {
}
}
update.ori.0 = safe_slerp(update.ori.0, update.vel.0, 9.0 * data.dt.0);
update
}
}

View File

@ -1,9 +1,10 @@
use crate::{
comp::{CharacterState, StateUpdate},
sys::character_behavior::{CharacterBehavior, JoinData},
util::safe_slerp,
};
use std::collections::VecDeque;
use vek::{Vec2, Vec3};
use vek::Vec2;
// Gravity is 9.81 * 4, so this makes gravity equal to .15
const GLIDE_ANTIGRAV: f32 = crate::sys::phys::GRAVITY * 0.96;
@ -46,12 +47,7 @@ impl CharacterBehavior for Data {
// Determine orientation vector from movement direction vector
let ori_dir = Vec2::from(update.vel.0);
if ori_dir.magnitude_squared() > 0.0001
&& (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared()
> 0.001
{
update.ori.0 = vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), 2.0 * data.dt.0);
}
update.ori.0 = safe_slerp(update.ori.0, ori_dir.into(), 2.0 * data.dt.0);
// Apply Glide antigrav lift
if Vec2::<f32>::from(update.vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)

View File

@ -1,6 +1,7 @@
use crate::{
comp::{CharacterState, StateUpdate},
sys::character_behavior::{CharacterBehavior, JoinData},
util::safe_slerp,
};
use std::{collections::VecDeque, time::Duration};
use vek::Vec3;
@ -33,14 +34,7 @@ impl CharacterBehavior for Data {
* ROLL_SPEED;
// Smooth orientation
if update.vel.0.magnitude_squared() > 0.0001
&& (update.ori.0.normalized() - Vec3::from(update.vel.0).normalized())
.magnitude_squared()
> 0.001
{
update.ori.0 =
vek::ops::Slerp::slerp(update.ori.0, update.vel.0.into(), 9.0 * data.dt.0);
}
update.ori.0 = safe_slerp(update.ori.0, update.vel.0.into(), 9.0 * data.dt.0);
if self.remaining_duration == Duration::default() {
// Roll duration has expired

View File

@ -3,9 +3,10 @@ use crate::{
event::LocalEvent,
states::*,
sys::{character_behavior::JoinData, phys::GRAVITY},
util::safe_slerp,
};
use std::time::Duration;
use vek::vec::{Vec2, Vec3};
use vek::vec::Vec2;
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
const BASE_HUMANOID_ACCEL: f32 = 100.0;
@ -59,18 +60,13 @@ fn basic_move(data: &JoinData, update: &mut StateUpdate) {
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, strength: f32) {
// Set direction based on move direction
let ori_dir = if update.character.is_attack() || update.character.is_block() {
Vec2::from(data.inputs.look_dir).normalized()
Vec2::from(data.inputs.look_dir)
} else {
Vec2::from(data.inputs.move_dir)
};
// Smooth orientation
if ori_dir.magnitude_squared() > 0.0001
&& (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared()
> 0.001
{
update.ori.0 = vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), strength * data.dt.0);
}
update.ori.0 = safe_slerp(update.ori.0, ori_dir.into(), strength * data.dt.0);
}
/// Updates components to move player as if theyre swimming

View File

@ -1,261 +0,0 @@
use super::phys::GRAVITY;
use crate::{
comp::{
ActionState, CharacterState, Controller, Energy, EnergySource, Mounting, MovementState::*,
Ori, PhysicsState, Pos, Stats, Vel,
},
event::{EventBus, ServerEvent},
state::DeltaTime,
sync::Uid,
terrain::TerrainGrid,
};
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
use std::time::Duration;
use vek::*;
pub const ROLL_DURATION: Duration = Duration::from_millis(600);
const BASE_HUMANOID_ACCEL: f32 = 100.0;
const BASE_HUMANOID_SPEED: f32 = 120.0;
const BASE_HUMANOID_AIR_ACCEL: f32 = 15.0;
const BASE_HUMANOID_AIR_SPEED: f32 = 100.0;
const BASE_HUMANOID_WATER_ACCEL: f32 = 70.0;
const BASE_HUMANOID_WATER_SPEED: f32 = 120.0;
const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0;
const ROLL_SPEED: f32 = 17.0;
const CHARGE_SPEED: f32 = 20.0;
const GLIDE_ACCEL: f32 = 15.0;
const GLIDE_SPEED: f32 = 45.0;
const BLOCK_ACCEL: f32 = 30.0;
const BLOCK_SPEED: f32 = 75.0;
// Gravity is 9.81 * 4, so this makes gravity equal to .15
const GLIDE_ANTIGRAV: f32 = GRAVITY * 0.96;
const CLIMB_SPEED: f32 = 5.0;
const CLIMB_COST: i32 = 5;
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
/// # Movement System
/// #### Applies forces, calculates new positions and velocities,7
/// #### based on Controller(Inputs) and CharacterState.
/// ----
///
/// **Writes:**
/// Pos, Vel, Ori
///
/// **Reads:**
/// Uid, Stats, Controller, PhysicsState, CharacterState, Mounting
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
ReadExpect<'a, TerrainGrid>,
Read<'a, EventBus<ServerEvent>>,
Read<'a, DeltaTime>,
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
WriteStorage<'a, Energy>,
ReadStorage<'a, Uid>,
ReadStorage<'a, Stats>,
ReadStorage<'a, Controller>,
ReadStorage<'a, PhysicsState>,
ReadStorage<'a, CharacterState>,
ReadStorage<'a, Mounting>,
);
fn run(
&mut self,
(
entities,
_terrain,
_server_bus,
dt,
mut positions,
mut velocities,
mut orientations,
mut energies,
uids,
stats,
controllers,
physics_states,
character_states,
mountings,
): Self::SystemData,
) {
// Apply movement inputs
for (
_entity,
mut _pos,
mut vel,
mut ori,
mut energy,
_uid,
stats,
controller,
physics,
character,
mount,
) in (
&entities,
&mut positions,
&mut velocities,
&mut orientations,
&mut energies.restrict_mut(),
&uids,
&stats,
&controllers,
&physics_states,
&character_states,
mountings.maybe(),
)
.join()
{
if stats.is_dead {
continue;
}
if mount.is_some() {
continue;
}
let inputs = &controller.inputs;
if character.action.is_dodge() {
vel.0 = Vec3::new(0.0, 0.0, vel.0.z)
+ (vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5 * inputs.move_dir.try_normalized().unwrap_or_default())
.try_normalized()
.unwrap_or_default()
* ROLL_SPEED;
} else if character.action.is_charge() {
vel.0 = Vec3::new(0.0, 0.0, vel.0.z)
+ (vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5 * inputs.move_dir.try_normalized().unwrap_or_default())
.try_normalized()
.unwrap_or_default()
* CHARGE_SPEED;
} else if character.action.is_block() {
vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir
* match physics.on_ground {
true if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL,
_ => 0.0,
}
} else {
// Move player according to move_dir
vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir
* match (physics.on_ground, &character.movement) {
(true, Run)
if vel.0.magnitude_squared()
< (BASE_HUMANOID_SPEED + stats.fitness as f32 * 50.0).powf(2.0) =>
{
BASE_HUMANOID_ACCEL
},
(false, Climb)
if vel.0.magnitude_squared() < BASE_HUMANOID_SPEED.powf(2.0) =>
{
BASE_HUMANOID_CLIMB_ACCEL
},
(false, Glide) if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => {
GLIDE_ACCEL
},
(false, Fall) | (false, Jump)
if vel.0.magnitude_squared()
< (BASE_HUMANOID_AIR_SPEED + stats.fitness as f32 * 10.0)
.powf(2.0) =>
{
BASE_HUMANOID_AIR_ACCEL
},
(false, Swim)
if vel.0.magnitude_squared()
< (BASE_HUMANOID_WATER_SPEED + stats.fitness as f32 * 30.0)
.powf(2.0) =>
{
BASE_HUMANOID_WATER_ACCEL + stats.fitness as f32 * 10.0
},
_ => 0.0,
};
}
// Set direction based on move direction when on the ground
let ori_dir = if
//character.action.is_wield() ||
character.action.is_attack() || character.action.is_block() {
Vec2::from(inputs.look_dir).normalized()
} else if let (Climb, Some(wall_dir)) = (character.movement, physics.on_wall) {
if Vec2::<f32>::from(wall_dir).magnitude_squared() > 0.001 {
Vec2::from(wall_dir).normalized()
} else {
Vec2::from(inputs.move_dir)
}
} else if let Glide = character.movement {
// Note: non-gliding forces will also affect velocity and thus orientation
// producing potentially unexpected changes in direction
Vec2::from(vel.0)
} else {
if let ActionState::Roll { .. } = character.action {
// So can can't spin/slip around while rolling
Vec2::from(vel.0)
} else {
Vec2::from(inputs.move_dir)
}
};
if ori_dir.magnitude_squared() > 0.0001
&& (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared()
> 0.001
{
ori.0 = vek::ops::Slerp::slerp(
ori.0,
ori_dir.into(),
if physics.on_ground { 9.0 } else { 2.0 } * dt.0,
);
}
// Glide
if character.movement == Glide
&& Vec2::<f32>::from(vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)
&& vel.0.z < 0.0
{
let lift = GLIDE_ANTIGRAV + vel.0.z.abs().powf(2.0) * 0.15;
vel.0.z += dt.0
* lift
* (Vec2::<f32>::from(vel.0).magnitude() * 0.075)
.min(1.0)
.max(0.2);
}
// Climb
if let (true, Some(_wall_dir)) = (
character.movement == Climb && vel.0.z <= CLIMB_SPEED,
physics.on_wall,
) {
if inputs.climb_down.is_pressed() && !inputs.climb.is_pressed() {
if energy
.get_mut_unchecked()
.try_change_by(-CLIMB_COST, EnergySource::Climb)
.is_ok()
{
vel.0 -= dt.0 * vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 6.0);
}
} else if inputs.climb.is_pressed() && !inputs.climb_down.is_pressed() {
if energy
.get_mut_unchecked()
.try_change_by(-CLIMB_COST, EnergySource::Climb)
.is_ok()
{
vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED).max(0.0);
}
} else {
vel.0.z = (vel.0.z - dt.0 * GRAVITY * 0.01).min(CLIMB_SPEED);
}
}
if character.movement == Swim && inputs.jump.is_pressed() {
vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(BASE_HUMANOID_WATER_SPEED);
}
}
}
}

141
common/src/util/color.rs Normal file
View File

@ -0,0 +1,141 @@
use vek::{Mat3, Rgb, Rgba, Vec3};
#[inline(always)]
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
col.map(|c| {
if c <= 0.104 {
c * 0.08677088
} else {
0.012522878 * c + 0.682171111 * c * c + 0.305306011 * c * c * c
}
})
}
#[inline(always)]
pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
col.map(|c| {
if c <= 0.0060 {
c * 11.500726
} else {
let s1 = c.sqrt();
let s2 = s1.sqrt();
let s3 = s2.sqrt();
0.585122381 * s1 + 0.783140355 * s2 - 0.368262736 * s3
}
})
}
#[inline(always)]
pub fn srgba_to_linear(col: Rgba<f32>) -> Rgba<f32> {
Rgba::from_translucent(srgb_to_linear(Rgb::from(col)), col.a)
}
#[inline(always)]
pub fn linear_to_srgba(col: Rgba<f32>) -> Rgba<f32> {
Rgba::from_translucent(linear_to_srgb(Rgb::from(col)), col.a)
}
/// Convert rgb to hsv. Expects rgb to be [0, 1].
#[inline(always)]
pub fn rgb_to_hsv(rgb: Rgb<f32>) -> Vec3<f32> {
let (r, g, b) = rgb.into_tuple();
let (max, min, diff, add) = {
let (max, min, diff, add) = if r > g {
(r, g, g - b, 0.0)
} else {
(g, r, b - r, 2.0)
};
if b > max {
(b, min, r - g, 4.0)
} else {
(max, b.min(min), diff, add)
}
};
let v = max;
let h = if max == min {
0.0
} else {
let mut h = 60.0 * (add + diff / (max - min));
if h < 0.0 {
h += 360.0;
}
h
};
let s = if max == 0.0 { 0.0 } else { (max - min) / max };
Vec3::new(h, s, v)
}
/// Convert hsv to rgb. Expects h [0, 360], s [0, 1], v [0, 1]
#[inline(always)]
pub fn hsv_to_rgb(hsv: Vec3<f32>) -> Rgb<f32> {
let (h, s, v) = hsv.into_tuple();
let c = s * v;
let h = h / 60.0;
let x = c * (1.0 - (h % 2.0 - 1.0).abs());
let m = v - c;
let (r, g, b) = if h >= 0.0 && h <= 1.0 {
(c, x, 0.0)
} else if h <= 2.0 {
(x, c, 0.0)
} else if h <= 3.0 {
(0.0, c, x)
} else if h <= 4.0 {
(0.0, x, c)
} else if h <= 5.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
};
Rgb::new(r + m, g + m, b + m)
}
/// Convert linear rgb to CIExyY
#[inline(always)]
pub fn rgb_to_xyy(rgb: Rgb<f32>) -> Vec3<f32> {
// XYZ
let xyz = Mat3::new(
0.4124, 0.3576, 0.1805, 0.2126, 0.7152, 0.0722, 0.0193, 0.1192, 0.9504,
) * Vec3::from(rgb);
let sum = xyz.sum();
Vec3::new(xyz.x / sum, xyz.y / sum, xyz.y)
}
/// Convert to CIExyY to linear rgb
#[inline(always)]
pub fn xyy_to_rgb(xyy: Vec3<f32>) -> Rgb<f32> {
let xyz = Vec3::new(
xyy.z / xyy.y * xyy.x,
xyy.z,
xyy.z / xyy.y * (1.0 - xyy.x - xyy.y),
);
Rgb::from(
Mat3::new(
3.2406, -1.5372, -0.4986, -0.9689, 1.8758, 0.0415, 0.0557, -0.2040, 1.0570,
) * xyz,
)
}
// TO-DO: speed this up
#[inline(always)]
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
let mut hsv = rgb_to_hsv(srgb_to_linear(col));
hsv.y *= 1.0 + value;
linear_to_srgb(hsv_to_rgb(hsv).map(|e| e.min(1.0).max(0.0)))
}
/// Preserves the luma of one color while changing its chromaticty to match the
/// other
#[inline(always)]
pub fn chromify_srgb(luma: Rgb<f32>, chroma: Rgb<f32>) -> Rgb<f32> {
let l = rgb_to_xyy(srgb_to_linear(luma)).z;
let mut xyy = rgb_to_xyy(srgb_to_linear(chroma));
xyy.z = l;
linear_to_srgb(xyy_to_rgb(xyy).map(|e| e.min(1.0).max(0.0)))
}

View File

@ -1,3 +1,5 @@
mod color;
pub const GIT_VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/githash"));
lazy_static::lazy_static! {
@ -5,144 +7,85 @@ lazy_static::lazy_static! {
pub static ref GIT_DATE: &'static str = GIT_VERSION.split("/").nth(1).expect("failed to retrieve git_date!");
}
use vek::{Mat3, Rgb, Rgba, Vec3};
pub use color::*;
/// Begone ye NaN's
/// Slerp two `Vec3`s skipping the slerp if their directions are very close
/// This avoids a case where `vek`s slerp produces NaN's
/// Additionally, it avoids unnecessary calculations if they are near identical
/// Assumes `from` is normalized and returns a normalized vector, but `to`
/// doesn't need to be normalized
// TODO: in some cases we might want to base the slerp rate on the magnitude of
// `to` for example when `to` is velocity and `from` is orientation
#[inline(always)]
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
col.map(|c| {
if c <= 0.104 {
c * 0.08677088
} else {
0.012522878 * c + 0.682171111 * c * c + 0.305306011 * c * c * c
pub fn safe_slerp(from: vek::Vec3<f32>, to: vek::Vec3<f32>, factor: f32) -> vek::Vec3<f32> {
use vek::Vec3;
debug_assert!(!to.map(f32::is_nan).reduce_or());
debug_assert!(!from.map(f32::is_nan).reduce_or());
// Ensure from is normalized
#[cfg(debug_assertions)]
{
if {
let len_sq = from.magnitude_squared();
len_sq < 0.999 || len_sq > 1.001
} {
panic!("Called safe_slerp with unnormalized from: {:?}", from);
}
})
}
}
#[inline(always)]
pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
col.map(|c| {
if c <= 0.0060 {
c * 11.500726
let to = if to.magnitude_squared() > 0.001 {
to.normalized()
} else {
return from;
};
let dot = from.dot(to);
if dot > 0.999 {
// Close together, just use to
return to;
}
let (from, to, factor) = if dot < -0.999 {
// Not linearly independent (slerp will fail since it doesn't check for this)
// Instead we will choose a midpoint and slerp from or to that depending on the
// factor
let mid_dir = if from.z > 0.999 {
// If vec's lie along the z-axis default to (1, 0, 0) as midpoint
Vec3::unit_x()
} else {
let s1 = c.sqrt();
let s2 = s1.sqrt();
let s3 = s2.sqrt();
0.585122381 * s1 + 0.783140355 * s2 - 0.368262736 * s3
}
})
}
#[inline(always)]
pub fn srgba_to_linear(col: Rgba<f32>) -> Rgba<f32> {
Rgba::from_translucent(srgb_to_linear(Rgb::from(col)), col.a)
}
#[inline(always)]
pub fn linear_to_srgba(col: Rgba<f32>) -> Rgba<f32> {
Rgba::from_translucent(linear_to_srgb(Rgb::from(col)), col.a)
}
/// Convert rgb to hsv. Expects rgb to be [0, 1].
#[inline(always)]
pub fn rgb_to_hsv(rgb: Rgb<f32>) -> Vec3<f32> {
let (r, g, b) = rgb.into_tuple();
let (max, min, diff, add) = {
let (max, min, diff, add) = if r > g {
(r, g, g - b, 0.0)
} else {
(g, r, b - r, 2.0)
// Default to picking midpoint in the xy plane
Vec3::new(from.y, -from.x, 0.0).normalized()
};
if b > max {
(b, min, r - g, 4.0)
if factor > 0.5 {
(mid_dir, to, factor * 2.0 - 1.0)
} else {
(max, b.min(min), diff, add)
(from, mid_dir, factor * 2.0)
}
} else {
(from, to, factor)
};
let v = max;
let h = if max == min {
0.0
} else {
let mut h = 60.0 * (add + diff / (max - min));
if h < 0.0 {
h += 360.0;
let slerped = Vec3::slerp(from, to, factor);
let slerped_normalized = slerped.normalized();
// Ensure normalization worked
// This should not be possible but I will leave it here for now just in case
// something was missed
#[cfg(debug_assertions)]
{
if {
let len_sq = slerped_normalized.magnitude_squared();
len_sq < 0.999 || len_sq > 1.001
} || slerped_normalized.map(f32::is_nan).reduce_or()
{
panic!(
"Failed to normalize {:?} produced from:\nslerp(\n {:?},\n {:?},\n \
{:?},\n)\nWith result: {:?})",
slerped, from, to, factor, slerped_normalized
);
}
h
};
let s = if max == 0.0 { 0.0 } else { (max - min) / max };
}
Vec3::new(h, s, v)
}
/// Convert hsv to rgb. Expects h [0, 360], s [0, 1], v [0, 1]
#[inline(always)]
pub fn hsv_to_rgb(hsv: Vec3<f32>) -> Rgb<f32> {
let (h, s, v) = hsv.into_tuple();
let c = s * v;
let h = h / 60.0;
let x = c * (1.0 - (h % 2.0 - 1.0).abs());
let m = v - c;
let (r, g, b) = if h >= 0.0 && h <= 1.0 {
(c, x, 0.0)
} else if h <= 2.0 {
(x, c, 0.0)
} else if h <= 3.0 {
(0.0, c, x)
} else if h <= 4.0 {
(0.0, x, c)
} else if h <= 5.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
};
Rgb::new(r + m, g + m, b + m)
}
/// Convert linear rgb to CIExyY
#[inline(always)]
pub fn rgb_to_xyy(rgb: Rgb<f32>) -> Vec3<f32> {
// XYZ
let xyz = Mat3::new(
0.4124, 0.3576, 0.1805, 0.2126, 0.7152, 0.0722, 0.0193, 0.1192, 0.9504,
) * Vec3::from(rgb);
let sum = xyz.sum();
Vec3::new(xyz.x / sum, xyz.y / sum, xyz.y)
}
/// Convert to CIExyY to linear rgb
#[inline(always)]
pub fn xyy_to_rgb(xyy: Vec3<f32>) -> Rgb<f32> {
let xyz = Vec3::new(
xyy.z / xyy.y * xyy.x,
xyy.z,
xyy.z / xyy.y * (1.0 - xyy.x - xyy.y),
);
Rgb::from(
Mat3::new(
3.2406, -1.5372, -0.4986, -0.9689, 1.8758, 0.0415, 0.0557, -0.2040, 1.0570,
) * xyz,
)
}
// TO-DO: speed this up
#[inline(always)]
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
let mut hsv = rgb_to_hsv(srgb_to_linear(col));
hsv.y *= 1.0 + value;
linear_to_srgb(hsv_to_rgb(hsv).map(|e| e.min(1.0).max(0.0)))
}
/// Preserves the luma of one color while changing its chromaticty to match the
/// other
#[inline(always)]
pub fn chromify_srgb(luma: Rgb<f32>, chroma: Rgb<f32>) -> Rgb<f32> {
let l = rgb_to_xyy(srgb_to_linear(luma)).z;
let mut xyy = rgb_to_xyy(srgb_to_linear(chroma));
xyy.z = l;
linear_to_srgb(xyy_to_rgb(xyy).map(|e| e.min(1.0).max(0.0)))
slerped_normalized
}

View File

@ -23,7 +23,6 @@ impl Animation for AttackAnimation {
let mut next = (*skeleton).clone();
let lab = 1.0;
//let test = (anim_time as f32 * 16.0 * lab as f32).cos();
let accel_med = 1.0 - (anim_time as f32 * 16.0 * lab as f32).cos();
let accel_slow = 1.0 - (anim_time as f32 * 12.0 * lab as f32).cos();
@ -114,9 +113,11 @@ impl Animation for AttackAnimation {
next.main.scale = Vec3::one();
},
Some(ToolKind::Hammer(_)) => {
next.l_hand.offset = Vec3::new(0.0, 1.0, 5.0);
next.l_hand.offset = Vec3::new(0.0, 3.0, 8.0);
//0,1,5
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.04;
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(0.0, 0.0, -3.0);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.05;
@ -133,29 +134,23 @@ impl Animation for AttackAnimation {
next.control.scale = Vec3::one();
},
Some(ToolKind::Staff(_)) => {
next.l_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
next.l_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-8.0 + accel_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + accel_fast * 3.0,
0.0,
);
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.offset = Vec3::new(0.0, 1.0, 0.0);
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(0.0, 0.0, 10.0);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(0.0, 6.0, -4.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-8.0 - slow * 1.0, 3.0 - slow * 5.0, 0.0);
next.control.ori = Quaternion::rotation_x(-1.2)
* Quaternion::rotation_y(slow * 1.5)
* Quaternion::rotation_z(1.4 + slow * 0.5);
next.control.scale = Vec3::one();
},
Some(ToolKind::Shield(_)) => {
next.l_hand.offset =
@ -183,25 +178,27 @@ impl Animation for AttackAnimation {
next.main.scale = Vec3::one();
},
Some(ToolKind::Bow(_)) => {
next.l_hand.offset = Vec3::new(-7.0, -2.0 + slow * 5.0, -1.0);
next.l_hand.ori = Quaternion::rotation_x(PI / 2.0)
* Quaternion::rotation_y(-0.3)
* Quaternion::rotation_z(0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(1.0, 8.0, 2.5);
next.r_hand.ori = Quaternion::rotation_x(PI / 2.0)
next.l_hand.offset = Vec3::new(1.0, -4.0, -1.0);
next.l_hand.ori = Quaternion::rotation_x(1.27)
* Quaternion::rotation_y(-0.6)
* Quaternion::rotation_z(-0.3);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(3.0, -1.0, -6.0);
next.r_hand.ori = Quaternion::rotation_x(1.27)
* Quaternion::rotation_y(-0.6)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(3.0, 2.0, -13.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.3)
* Quaternion::rotation_z(0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-4.0 + skeleton_attr.weapon_x,
15.0 + skeleton_attr.weapon_y,
-4.0,
);
next.main.ori = Quaternion::rotation_x(0.0)
* Quaternion::rotation_y(0.4)
* Quaternion::rotation_z(0.0);
* Quaternion::rotation_z(-0.6);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-7.0, 6.0, 6.0);
next.control.ori = Quaternion::rotation_x(0.0)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.control.scale = Vec3::one();
},
Some(ToolKind::Dagger(_)) => {
next.l_hand.offset =

View File

@ -9,6 +9,7 @@ pub mod idle;
pub mod jump;
pub mod roll;
pub mod run;
pub mod shoot;
pub mod sit;
pub mod stand;
pub mod swim;
@ -19,8 +20,8 @@ pub use self::{
attack::AttackAnimation, block::BlockAnimation, blockidle::BlockIdleAnimation,
charge::ChargeAnimation, cidle::CidleAnimation, climb::ClimbAnimation,
gliding::GlidingAnimation, idle::IdleAnimation, jump::JumpAnimation, roll::RollAnimation,
run::RunAnimation, sit::SitAnimation, stand::StandAnimation, swim::SwimAnimation,
wield::WieldAnimation,
run::RunAnimation, shoot::ShootAnimation, sit::SitAnimation, stand::StandAnimation,
swim::SwimAnimation, wield::WieldAnimation,
};
use super::{Bone, Skeleton};

View File

@ -0,0 +1,297 @@
use super::{super::Animation, CharacterSkeleton, SkeletonAttr};
use common::comp::item::ToolKind;
use vek::*;
pub struct Input {
pub attack: bool,
}
pub struct ShootAnimation;
impl Animation for ShootAnimation {
type Dependency = (Option<ToolKind>, f64);
type Skeleton = CharacterSkeleton;
fn update_skeleton(
skeleton: &Self::Skeleton,
(active_tool_kind, _global_time): Self::Dependency,
anim_time: f64,
rate: &mut f32,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
*rate = 1.0;
let mut next = (*skeleton).clone();
let lab = 1.0;
let accel_med = 1.0 - (anim_time as f32 * 16.0 * lab as f32).cos();
let accel_slow = 1.0 - (anim_time as f32 * 12.0 * lab as f32).cos();
let accel_fast = 1.0 - (anim_time as f32 * 24.0 * lab as f32).cos();
let quick = (((5.0)
/ (0.5 + 4.5 * ((anim_time as f32 * lab as f32 * 2.0).cos()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * lab as f32 * 2.0).cos());
let slow = (((5.0)
/ (1.1 + 3.9 * ((anim_time as f32 * lab as f32 * 12.4).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * lab as f32 * 12.4).sin());
let slower = (((5.0)
/ (0.1 + 4.9 * ((anim_time as f32 * lab as f32 * 4.0).sin()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * lab as f32 * 4.0).sin());
let sloweralt = (((5.0)
/ (0.1 + 4.9 * ((anim_time as f32 * lab as f32 * 4.0).cos()).powf(2.0 as f32)))
.sqrt())
* ((anim_time as f32 * lab as f32 * 4.0).cos());
next.head.offset = Vec3::new(
0.0 + skeleton_attr.neck_right,
-2.0 + skeleton_attr.neck_forward - quick * 3.5,
skeleton_attr.neck_height + 21.0,
);
next.head.ori = Quaternion::rotation_z(quick * 0.15)
* Quaternion::rotation_x(quick * 0.09)
* Quaternion::rotation_y(0.0);
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0 - quick * 1.5, 7.0);
next.chest.ori = Quaternion::rotation_z(quick * 0.15)
* Quaternion::rotation_x(quick * 0.09)
* Quaternion::rotation_y(0.0);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0 - quick * 1.0, 5.0);
next.belt.ori = Quaternion::rotation_z(quick * 0.2)
* Quaternion::rotation_x(quick * 0.12)
* Quaternion::rotation_y(0.0);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, -quick * 0.5, 2.0);
next.shorts.ori = Quaternion::rotation_z(quick * 0.08)
* Quaternion::rotation_x(quick * 0.05)
* Quaternion::rotation_y(0.0);
next.shorts.scale = Vec3::one();
match active_tool_kind {
//TODO: Inventory
Some(ToolKind::Sword(_)) => {
next.l_hand.offset = Vec3::new(0.0, 1.0, 0.0);
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.04;
next.r_hand.offset = Vec3::new(0.0, 0.0, -3.0);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(0.0, 6.0, -1.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-8.0 - slow * 1.0, 3.0 - slow * 5.0, 0.0);
next.control.ori = Quaternion::rotation_x(-1.2)
* Quaternion::rotation_y(slow * 1.5)
* Quaternion::rotation_z(1.4 + slow * 0.5);
next.control.scale = Vec3::one();
},
Some(ToolKind::Axe(_)) => {
next.l_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
next.l_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-8.0 + accel_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + accel_fast * 3.0,
0.0,
);
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.main.scale = Vec3::one();
},
Some(ToolKind::Hammer(_)) => {
next.l_hand.offset = Vec3::new(0.0, 3.0, 8.0);
//0,1,5
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(0.0, 0.0, -3.0);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(0.0, 6.0, -1.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-6.0, 3.0, 5.0 + slower * 5.0);
next.control.ori = Quaternion::rotation_x(-0.2 + slower * 2.0)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(1.4 + 1.57);
next.control.scale = Vec3::one();
},
Some(ToolKind::Staff(_)) => {
next.l_hand.offset = Vec3::new(1.0, -2.0, -5.0);
next.l_hand.ori = Quaternion::rotation_x(1.47) * Quaternion::rotation_y(-0.3);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(9.0, 1.0, 0.0);
next.r_hand.ori = Quaternion::rotation_x(1.8)
* Quaternion::rotation_y(0.5)
* Quaternion::rotation_z(-0.27);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(11.0, 9.0, 10.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(3.14 + 0.3)
* Quaternion::rotation_z(0.9);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-7.0, 6.0, 6.0 - quick * 5.0);
next.control.ori = Quaternion::rotation_x(quick * 1.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(quick * 1.5);
next.control.scale = Vec3::one();
},
Some(ToolKind::Shield(_)) => {
next.l_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
next.l_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-8.0 + accel_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + accel_fast * 3.0,
0.0,
);
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.main.scale = Vec3::one();
},
Some(ToolKind::Bow(_)) => {
next.l_hand.offset = Vec3::new(
1.0 - sloweralt * 2.0,
-4.0 - sloweralt * 7.0,
-1.0 + sloweralt * 6.0,
);
next.l_hand.ori = Quaternion::rotation_x(1.20)
* Quaternion::rotation_y(-0.6 + sloweralt * 0.8)
* Quaternion::rotation_z(-0.3 + sloweralt * 0.9);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(3.0, -1.0, -5.0);
next.r_hand.ori = Quaternion::rotation_x(1.20)
* Quaternion::rotation_y(-0.6)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(3.0, 2.0, -13.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.3)
* Quaternion::rotation_z(-0.6);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-7.0, 6.0, 6.0);
next.control.ori = Quaternion::rotation_x((sloweralt * 0.4).max(0.4))
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.control.scale = Vec3::one();
},
Some(ToolKind::Dagger(_)) => {
next.l_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
next.l_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-8.0 + accel_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + accel_fast * 3.0,
0.0,
);
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.main.scale = Vec3::one();
},
Some(ToolKind::Debug(_)) => {
next.l_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
next.l_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset =
Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-8.0 + accel_slow * 10.0 + skeleton_attr.weapon_x,
8.0 + accel_fast * 3.0,
0.0,
);
next.main.ori = Quaternion::rotation_z(-0.8)
* Quaternion::rotation_x(0.0 + accel_med * -0.8)
* Quaternion::rotation_y(0.0 + accel_med * -0.4);
next.main.scale = Vec3::one();
},
_ => {},
}
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.glider.offset = Vec3::new(0.0, 5.0, 0.0);
next.glider.ori = Quaternion::rotation_y(0.0);
next.glider.scale = Vec3::one() * 0.0;
next.lantern.offset = Vec3::new(0.0, 0.0, 0.0);
next.lantern.ori = Quaternion::rotation_x(0.0);
next.lantern.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, 0.0, 0.1) * skeleton_attr.scaler;
next.torso.ori =
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next.l_control.offset = Vec3::new(0.0, 0.0, 0.0);
next.l_control.ori = Quaternion::rotation_x(0.0);
next.l_control.scale = Vec3::one();
next.r_control.offset = Vec3::new(0.0, 0.0, 0.0);
next.r_control.ori = Quaternion::rotation_x(0.0);
next.r_control.scale = Vec3::one();
next
}
}

View File

@ -61,10 +61,10 @@ impl Animation for WieldAnimation {
* Quaternion::rotation_z(-0.8);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(0.0, 0.0, 0.0);
next.control.ori = Quaternion::rotation_x(wave_ultra_slow_cos * 0.1)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(wave_ultra_slow * 0.1);
next.control.offset = Vec3::new(0.0, 0.0, -2.0);
next.control.ori = Quaternion::rotation_x(wave_ultra_slow_cos * 0.1 + 0.2)
* Quaternion::rotation_y(-0.3)
* Quaternion::rotation_z(wave_ultra_slow * 0.1 - 0.5);
next.control.scale = Vec3::one();
},
Some(ToolKind::Hammer(_)) => {
@ -87,29 +87,25 @@ impl Animation for WieldAnimation {
next.control.scale = Vec3::one();
},
Some(ToolKind::Staff(_)) => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
1.0 + wave_ultra_slow_cos * 0.5,
5.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(1.27);
next.l_hand.scale = Vec3::one() * 1.0;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
-1.5 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(1.27);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
8.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
17.0 + wave_ultra_slow * 1.0,
);
next.main.ori = Quaternion::rotation_x(-0.3 + PI)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.l_hand.offset = Vec3::new(1.0, -2.0, -5.0);
next.l_hand.ori = Quaternion::rotation_x(1.47) * Quaternion::rotation_y(-0.3);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(9.0, 1.0, 0.0);
next.r_hand.ori = Quaternion::rotation_x(1.8)
* Quaternion::rotation_y(0.5)
* Quaternion::rotation_z(-0.27);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(11.0, 9.0, 10.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(3.14 + 0.3)
* Quaternion::rotation_z(0.9);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-7.0, 6.0, 6.0);
next.control.ori = Quaternion::rotation_x(wave_ultra_slow * 0.2)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(wave_ultra_slow_cos * 0.1);
next.control.scale = Vec3::one();
},
Some(ToolKind::Shield(_)) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
@ -129,33 +125,27 @@ impl Animation for WieldAnimation {
next.main.scale = Vec3::one();
},
Some(ToolKind::Bow(_)) => {
next.l_hand.offset = Vec3::new(
-1.0 - wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
5.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(PI / 2.0)
* Quaternion::rotation_y(-0.3)
* Quaternion::rotation_z(0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
1.0 + wave_ultra_slow_cos * 1.0,
8.0 + wave_ultra_slow_cos * 0.5,
2.5 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(PI / 2.0)
next.l_hand.offset = Vec3::new(1.0, -4.0, -1.0);
next.l_hand.ori = Quaternion::rotation_x(1.20)
* Quaternion::rotation_y(-0.6)
* Quaternion::rotation_z(-0.3);
next.l_hand.scale = Vec3::one() * 1.05;
next.r_hand.offset = Vec3::new(3.0, -1.0, -5.0);
next.r_hand.ori = Quaternion::rotation_x(1.20)
* Quaternion::rotation_y(-0.6)
* Quaternion::rotation_z(-0.3);
next.r_hand.scale = Vec3::one() * 1.05;
next.main.offset = Vec3::new(3.0, 2.0, -13.0);
next.main.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.3)
* Quaternion::rotation_z(0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.main.offset = Vec3::new(
-4.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
15.0 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
-4.0 + wave_ultra_slow * 1.0,
);
next.main.ori = Quaternion::rotation_x(0.0)
* Quaternion::rotation_y(0.4)
* Quaternion::rotation_z(0.0);
* Quaternion::rotation_z(-0.6);
next.main.scale = Vec3::one();
next.control.offset = Vec3::new(-7.0, 6.0, 6.0);
next.control.ori = Quaternion::rotation_x(wave_ultra_slow * 0.2)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(wave_ultra_slow_cos * 0.1);
next.control.scale = Vec3::one();
},
Some(ToolKind::Dagger(_)) => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);

View File

@ -44,7 +44,7 @@ impl Bone {
// TODO: Make configurable.
let factor = (15.0 * dt).min(1.0);
self.offset += (target.offset - self.offset) * factor;
self.ori = vek::ops::Slerp::slerp(self.ori, target.ori, factor);
self.ori = vek::Slerp::slerp(self.ori, target.ori, factor);
self.scale += (target.scale - self.scale) * factor;
}
}

View File

@ -2,6 +2,7 @@ use crate::ecs::comp::Interpolated;
use common::{
comp::{Ori, Pos, Vel},
state::DeltaTime,
util::safe_slerp,
};
use log::warn;
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
@ -29,14 +30,7 @@ impl<'a> System<'a> for Sys {
// Update interpolation values
if i.pos.distance_squared(pos.0) < 64.0 * 64.0 {
i.pos = Lerp::lerp(i.pos, pos.0 + vel.0 * 0.03, 10.0 * dt.0);
let ori_interp = Slerp::slerp(i.ori, ori.0, 5.0 * dt.0);
// Check for NaNs
// TODO: why are we getting NaNs here! Zero-length ori vectors?
i.ori = if !ori_interp.map(|e| e.is_nan()).reduce_or() {
ori_interp
} else {
ori.0
};
i.ori = safe_slerp(i.ori, ori.0, 5.0 * dt.0);
} else {
i.pos = pos.0;
i.ori = ori.0;

View File

@ -12,6 +12,7 @@ use crate::{
object::ObjectSkeleton, quadruped_medium::QuadrupedMediumSkeleton,
quadruped_small::QuadrupedSmallSkeleton, Animation, Skeleton,
},
ecs::comp::Interpolated,
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
scene::{
camera::{Camera, CameraMode},
@ -115,8 +116,8 @@ impl FigureMgr {
for (
entity,
pos,
interpolated,
vel,
ori,
scale,
body,
character,
@ -127,8 +128,8 @@ impl FigureMgr {
) in (
&ecs.entities(),
&ecs.read_storage::<Pos>(),
ecs.read_storage::<Interpolated>().maybe(),
&ecs.read_storage::<Vel>(),
ecs.read_storage::<Ori>().maybe(),
ecs.read_storage::<Scale>().maybe(),
&ecs.read_storage::<Body>(),
ecs.read_storage::<CharacterState>().maybe(),
@ -139,7 +140,9 @@ impl FigureMgr {
)
.join()
{
let ori = ori.copied().unwrap_or(Ori(Vec3::unit_y()));
let (pos, ori) = interpolated
.map(|i| (Pos(i.pos), Ori(i.ori)))
.unwrap_or((*pos, Ori(Vec3::unit_y())));
// Don't process figures outside the vd
let vd_frac = Vec2::from(pos.0 - player_pos)
@ -477,7 +480,7 @@ impl FigureMgr {
)
},
CharacterState::BasicRanged(_) => {
anim::character::AttackAnimation::update_skeleton(
anim::character::ShootAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
state.state_time,
@ -613,7 +616,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -694,7 +696,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -777,7 +778,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -852,7 +852,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -927,7 +926,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1002,7 +1000,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1077,7 +1074,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1152,7 +1148,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1227,7 +1222,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1302,7 +1296,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1322,7 +1315,6 @@ impl FigureMgr {
state.update(
renderer,
pos.0,
vel.0,
ori.0,
scale,
col,
@ -1678,8 +1670,6 @@ pub struct FigureState<S: Skeleton> {
locals: Consts<FigureLocals>,
state_time: f64,
skeleton: S,
pos: Vec3<f32>,
ori: Vec3<f32>,
last_ori: Vec3<f32>,
lpindex: u8,
visible: bool,
@ -1694,8 +1684,6 @@ impl<S: Skeleton> FigureState<S> {
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
state_time: 0.0,
skeleton,
pos: Vec3::zero(),
ori: Vec3::zero(),
last_ori: Vec3::zero(),
lpindex: 0,
visible: false,
@ -1706,7 +1694,6 @@ impl<S: Skeleton> FigureState<S> {
&mut self,
renderer: &mut Renderer,
pos: Vec3<f32>,
vel: Vec3<f32>,
ori: Vec3<f32>,
scale: f32,
col: Rgba<f32>,
@ -1717,23 +1704,14 @@ impl<S: Skeleton> FigureState<S> {
) {
self.visible = visible;
self.lpindex = lpindex;
// What is going on here?
// (note: that ori is now the slerped ori)
self.last_ori = Lerp::lerp(self.last_ori, ori, 15.0 * dt);
// Update interpolation values
// TODO: use values from Interpolated component instead of recalculating
if self.pos.distance_squared(pos) < 64.0 * 64.0 {
self.pos = Lerp::lerp(self.pos, pos + vel * 0.03, 10.0 * dt);
self.ori = Slerp::slerp(self.ori, ori, 5.0 * dt);
} else {
self.pos = pos;
self.ori = ori;
}
self.state_time += (dt * state_animation_rate) as f64;
// TODO: what are the interpolated ori values used for if not here???
let mat = Mat4::<f32>::identity()
* Mat4::translation_3d(self.pos)
* Mat4::translation_3d(pos)
* Mat4::rotation_z(-ori.x.atan2(ori.y))
* Mat4::rotation_x(ori.z.atan2(Vec2::from(ori).magnitude()))
* Mat4::scaling_3d(Vec3::from(0.8 * scale));

View File

@ -192,7 +192,6 @@ impl Scene {
self.figure_state.update(
renderer,
Vec3::zero(),
Vec3::zero(),
Vec3::new(self.char_ori.sin(), -self.char_ori.cos(), 0.0),
1.0,
Rgba::broadcast(1.0),