Weapon trails now works with dual wielding

This commit is contained in:
Sam 2022-02-16 12:37:52 -05:00
parent a967daa2f5
commit b3a19ebc00
22 changed files with 138 additions and 81 deletions

View File

@ -113,7 +113,8 @@ impl Skeleton for ArthropodSkeleton {
orientation: mount_orientation,
scale: Vec3::one(),
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -137,7 +137,8 @@ impl Skeleton for BipedLargeSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -83,7 +83,8 @@ impl Skeleton for BipedSmallSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -106,7 +106,8 @@ impl Skeleton for BirdLargeSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -60,7 +60,8 @@ impl Skeleton for BirdMediumSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -79,6 +79,7 @@ skeleton_impls!(struct CharacterSkeleton {
:: // Begin non-bone fields
holding_lantern: bool,
main_weapon_trail: bool,
off_weapon_trail: bool,
});
impl CharacterSkeleton {
@ -127,6 +128,7 @@ impl Skeleton for CharacterSkeleton {
shorts_mat
} * Mat4::<f32>::from(self.lantern);
let main_mat = control_l_mat * Mat4::<f32>::from(self.main);
let second_mat = control_r_mat * Mat4::<f32>::from(self.second);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(head_mat),
@ -142,7 +144,7 @@ impl Skeleton for CharacterSkeleton {
make_bone(chest_mat * Mat4::<f32>::from(self.shoulder_r)),
make_bone(chest_mat * Mat4::<f32>::from(self.glider)),
make_bone(main_mat),
make_bone(control_r_mat * Mat4::<f32>::from(self.second)),
make_bone(second_mat),
make_bone(lantern_mat),
// FIXME: Should this be control_l_mat?
make_bone(control_mat * hand_l_mat * Mat4::<f32>::from(self.hold)),
@ -157,7 +159,8 @@ impl Skeleton for CharacterSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: self.main_weapon_trail.then_some(main_mat),
main_weapon_trail_mat: self.main_weapon_trail.then_some(main_mat),
off_weapon_trail_mat: self.off_weapon_trail.then_some(second_mat),
}
}
}

View File

@ -81,7 +81,8 @@ impl Skeleton for DragonSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -60,7 +60,8 @@ impl Skeleton for FishMediumSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -51,7 +51,8 @@ impl Skeleton for FishSmallSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -37,7 +37,8 @@ impl Skeleton for FixtureSkeleton {
Offsets {
lantern: None,
mount_bone: Transform::default(),
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -83,7 +83,8 @@ impl Skeleton for GolemSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -43,7 +43,8 @@ impl Skeleton for ItemDropSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -1,7 +1,4 @@
#![feature(
generic_associated_types,
bool_to_option,
)]
#![feature(generic_associated_types, bool_to_option)]
#![allow(incomplete_features)]
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
@ -106,7 +103,8 @@ pub fn init() { lazy_static::initialize(&LIB); }
pub struct Offsets {
pub lantern: Option<Vec3<f32>>,
pub mount_bone: Transform<f32, f32, f32>,
pub weapon_trail_mat: Option<Mat4<f32>>,
pub main_weapon_trail_mat: Option<Mat4<f32>>,
pub off_weapon_trail_mat: Option<Mat4<f32>>,
}
pub trait Skeleton: Send + Sync + 'static {

View File

@ -49,7 +49,8 @@ impl Skeleton for ObjectSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -97,7 +97,8 @@ impl Skeleton for QuadrupedLowSkeleton {
orientation: mount_orientation,
scale: Vec3::one(),
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -109,7 +109,8 @@ impl Skeleton for QuadrupedMediumSkeleton {
orientation: mount_orientation,
scale: Vec3::one(),
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -74,7 +74,8 @@ impl Skeleton for QuadrupedSmallSkeleton {
orientation: mount_orientation,
scale: Vec3::one(),
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -53,7 +53,8 @@ impl Skeleton for ShipSkeleton {
),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -84,7 +84,8 @@ impl Skeleton for TheropodSkeleton {
.into(),
..Default::default()
},
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}
}

View File

@ -33,9 +33,8 @@ use common::{
comp::{
inventory::slot::EquipSlot,
item::{Hands, ItemKind, ToolKind},
Body, CharacterState, Collider, Controller, Health, Inventory, Item,
ItemKey, Last, LightAnimation, LightEmitter, Ori, PhysicsState, PoiseState, Pos, Scale,
Vel,
Body, CharacterState, Collider, Controller, Health, Inventory, Item, ItemKey, Last,
LightAnimation, LightEmitter, Ori, PhysicsState, PoiseState, Pos, Scale, Vel,
},
link::Is,
mounting::Rider,
@ -6192,7 +6191,8 @@ impl FigureColLights {
pub struct FigureStateMeta {
lantern_offset: Option<anim::vek::Vec3<f32>>,
abs_trail_points: Option<(anim::vek::Vec3<f32>, anim::vek::Vec3<f32>)>,
main_abs_trail_points: Option<(anim::vek::Vec3<f32>, anim::vek::Vec3<f32>)>,
off_abs_trail_points: Option<(anim::vek::Vec3<f32>, anim::vek::Vec3<f32>)>,
// Animation to be applied to rider of this entity
mount_transform: anim::vek::Transform<f32, f32, f32>,
// Contains the position of this figure or if it is a rider it will contain the mount's
@ -6270,7 +6270,8 @@ impl<S: Skeleton> FigureState<S> {
Self {
meta: FigureStateMeta {
lantern_offset: offsets.lantern,
abs_trail_points: None,
main_abs_trail_points: None,
off_abs_trail_points: None,
mount_transform: offsets.mount_bone,
mount_world_pos: anim::vek::Vec3::zero(),
state_time: 0.0,
@ -6440,37 +6441,62 @@ impl<S: Skeleton> FigureState<S> {
renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]);
self.lantern_offset = offsets.lantern;
// Handle weapon trails
let weapon_offsets = offsets.weapon_trail_mat.map(|mat| {
let (trail_start, trail_end) = match tools.0 {
Some(ToolKind::Sword) => (20.25, 29.25),
// TODO: Make sure these are good positions, only did tweaking on sword
Some(ToolKind::Axe) => (10.0, 19.25),
Some(ToolKind::Hammer) => (10.0, 19.25),
_ => (0.0, 0.0),
};
(
(mat * anim::vek::Vec4::new(0.0, 0.0, trail_start, 1.0)).xyz(),
(mat * anim::vek::Vec4::new(0.0, 0.0, trail_end, 1.0)).xyz(),
)
});
let offsets_abs_trail_points = weapon_offsets.map(|(a, b)| (a + pos, b + pos));
if let Some(trail_mgr) = trail_mgr {
if let Some(quad_mesh) = entity
.as_ref()
.and_then(|e| trail_mgr.entity_meshes.get_mut(e))
fn handle_weapon_trails(
trail_mgr: &mut TrailMgr,
new_weapon_trail_mat: Option<anim::vek::Mat4<f32>>,
old_abs_trail_points: &mut Option<(anim::vek::Vec3<f32>, anim::vek::Vec3<f32>)>,
entity: EcsEntity,
is_main_weapon: bool,
pos: anim::vek::Vec3<f32>,
tools: (Option<ToolKind>, Option<ToolKind>),
) {
let weapon_offsets = new_weapon_trail_mat.map(|mat| {
let (trail_start, trail_end) = match tools.0 {
Some(ToolKind::Sword) => (20.25, 29.25),
// TODO: Make sure these are good positions, only did tweaking on sword
Some(ToolKind::Axe) => (10.0, 19.25),
Some(ToolKind::Hammer) => (10.0, 19.25),
_ => (0.0, 0.0),
};
(
(mat * anim::vek::Vec4::new(0.0, 0.0, trail_start, 1.0)).xyz(),
(mat * anim::vek::Vec4::new(0.0, 0.0, trail_end, 1.0)).xyz(),
)
});
let new_abs_trail_points = weapon_offsets.map(|(a, b)| (a + pos, b + pos));
let trail_mgr_offset = trail_mgr.offset;
let quad_mesh = trail_mgr.entity_mesh_or_insert(entity, is_main_weapon);
if let (Some((p1, p2)), Some((p4, p3))) = (&old_abs_trail_points, new_abs_trail_points)
{
if let (Some((p1, p2)), Some((p4, p3))) =
(self.abs_trail_points, offsets_abs_trail_points)
{
let vertex = |p: anim::vek::Vec3<f32>| trail::Vertex {
pos: p.into_array(),
};
let quad = Quad::new(vertex(p1), vertex(p2), vertex(p3), vertex(p4));
quad_mesh.replace_quad(trail_mgr.offset * 4, quad);
}
let vertex = |p: anim::vek::Vec3<f32>| trail::Vertex {
pos: p.into_array(),
};
let quad = Quad::new(vertex(*p1), vertex(*p2), vertex(p3), vertex(p4));
quad_mesh.replace_quad(trail_mgr_offset * 4, quad);
}
*old_abs_trail_points = new_abs_trail_points;
}
if let (Some(trail_mgr), Some(entity)) = (trail_mgr, entity) {
handle_weapon_trails(
trail_mgr,
offsets.main_weapon_trail_mat,
&mut self.main_abs_trail_points,
*entity,
true,
*pos,
*tools,
);
handle_weapon_trails(
trail_mgr,
offsets.off_weapon_trail_mat,
&mut self.off_abs_trail_points,
*entity,
false,
*pos,
*tools,
);
}
self.abs_trail_points = offsets_abs_trail_points;
// TODO: compute the mount bone only when it is needed
self.mount_transform = offsets.mount_bone;

View File

@ -49,7 +49,8 @@ impl anim::Skeleton for VolumeKey {
anim::Offsets {
lantern: None,
mount_bone: anim::vek::Transform::default(),
weapon_trail_mat: None,
main_weapon_trail_mat: None,
off_weapon_trail_mat: None,
}
}

View File

@ -1,14 +1,19 @@
use super::SceneData;
use crate::render::{DynamicModel, Mesh, Quad, Renderer, TrailDrawer, TrailVertex};
use common::comp::CharacterState;
use common_base::span;
use specs::{Entity as EcsEntity, Join, WorldExt};
use specs::Entity as EcsEntity;
use std::collections::HashMap;
// use vek::*;
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct MeshKey {
entity: EcsEntity,
is_main_weapon: bool,
}
pub struct TrailMgr {
/// Meshes for each entity
pub entity_meshes: HashMap<EcsEntity, Mesh<TrailVertex>>,
entity_meshes: HashMap<MeshKey, Mesh<TrailVertex>>,
/// Offset
pub offset: usize,
@ -47,7 +52,8 @@ impl TrailMgr {
// Verts per quad are in b, c, a, d order
vertices[i * 4 + 2] = vertices[i * 4 + 2] * TRAIL_SHRINKAGE
+ vertices[i * 4] * (1.0 - TRAIL_SHRINKAGE);
if i != (self.offset + TRAIL_DYNAMIC_MODEL_SIZE - 1) % TRAIL_DYNAMIC_MODEL_SIZE {
if i != (self.offset + TRAIL_DYNAMIC_MODEL_SIZE - 1) % TRAIL_DYNAMIC_MODEL_SIZE
{
// Avoid shrinking edge of most recent quad so that edges of quads align
vertices[i * 4 + 3] = vertices[i * 4 + 3] * TRAIL_SHRINKAGE
+ vertices[i * 4 + 1] * (1.0 - TRAIL_SHRINKAGE);
@ -59,26 +65,9 @@ impl TrailMgr {
mesh.replace_quad(self.offset * 4, Quad::new(zero, zero, zero, zero));
});
// Create a mesh for each entity that doesn't already have one
let ecs = scene_data.state.ecs();
for (entity, _char_state) in
(&ecs.entities(), &ecs.read_storage::<CharacterState>()).join()
{
// Result returned doesn't matter, it just needs to only insert if entry didn't
// already exist
if let Ok(mesh) = self.entity_meshes.try_insert(entity, Mesh::new()) {
// Allocate up to necessary length so repalce_quad works as expected elsewhere
let zero = TrailVertex::zero();
for _ in 0..TRAIL_DYNAMIC_MODEL_SIZE {
mesh.push_quad(Quad::new(zero, zero, zero, zero));
}
}
}
// Clear meshes for entities that no longer exist (is this even
// necessary? not sure if this growing too big is a concern)
// Clear meshes for entities that only have zero quads in mesh
self.entity_meshes
.retain(|entity, _| ecs.entities().is_alive(*entity));
.retain(|_, mesh| mesh.iter().any(|vert| *vert != TrailVertex::zero()));
// Create dynamic model from currently existing meshes
let mut big_mesh = Mesh::new();
@ -111,4 +100,27 @@ impl TrailMgr {
drawer.draw(&self.dynamic_model, self.model_len);
}
}
pub fn entity_mesh_or_insert(
&mut self,
entity: EcsEntity,
is_main_weapon: bool,
) -> &mut Mesh<TrailVertex> {
let key = MeshKey {
entity,
is_main_weapon,
};
self.entity_meshes
.entry(key)
.or_insert_with(Self::default_trail_mesh)
}
fn default_trail_mesh() -> Mesh<TrailVertex> {
let mut mesh = Mesh::new();
let zero = TrailVertex::zero();
for _ in 0..TRAIL_DYNAMIC_MODEL_SIZE {
mesh.push_quad(Quad::new(zero, zero, zero, zero));
}
mesh
}
}