mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Finished adding tether graphics
This commit is contained in:
@ -804,4 +804,17 @@ vec3 simple_lighting(vec3 pos, vec3 col, float shade) {
|
|||||||
return col * clamp(2.5 / dot(d, d), shade * (get_sun_brightness() + 0.01), 1);
|
return col * clamp(2.5 / dot(d, d), shade * (get_sun_brightness() + 0.01), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float wind_wave(float off, float scaling, float speed, float strength) {
|
||||||
|
float aspeed = abs(speed);
|
||||||
|
|
||||||
|
// TODO: Right now, the wind model is pretty simplistic. This means that there is frequently no wind at all, which
|
||||||
|
// looks bad. For now, we add a lower bound on the wind speed to keep things looking nice.
|
||||||
|
strength = max(strength, 6.0);
|
||||||
|
aspeed = max(aspeed, 5.0);
|
||||||
|
|
||||||
|
return (sin(tick_loop(2.0 * PI, 0.35 * scaling * floor(aspeed), off)) * (1.0 - fract(aspeed))
|
||||||
|
+ sin(tick_loop(2.0 * PI, 0.35 * scaling * ceil(aspeed), off)) * fract(aspeed)) * abs(strength) * 0.25;
|
||||||
|
//return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,19 +76,6 @@ vec4 nearest_entity(in vec3 sprite_pos, const float entity_radius_factor) {
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
float wind_wave(float off, float scaling, float speed, float strength) {
|
|
||||||
float aspeed = abs(speed);
|
|
||||||
|
|
||||||
// TODO: Right now, the wind model is pretty simplistic. This means that there is frequently no wind at all, which
|
|
||||||
// looks bad. For now, we add a lower bound on the wind speed to keep things looking nice.
|
|
||||||
strength = max(strength, 6.0);
|
|
||||||
aspeed = max(aspeed, 5.0);
|
|
||||||
|
|
||||||
return (sin(tick_loop(2.0 * PI, 0.35 * scaling * floor(aspeed), off)) * (1.0 - fract(aspeed))
|
|
||||||
+ sin(tick_loop(2.0 * PI, 0.35 * scaling * ceil(aspeed), off)) * fract(aspeed)) * abs(strength) * 0.25;
|
|
||||||
//return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Matrix to transform this sprite instance from model space to chunk space
|
// Matrix to transform this sprite instance from model space to chunk space
|
||||||
mat4 inst_mat;
|
mat4 inst_mat;
|
||||||
|
@ -31,6 +31,7 @@ layout(location = 0) in vec3 f_pos;
|
|||||||
// in float f_ao;
|
// in float f_ao;
|
||||||
// flat in uint f_pos_norm;
|
// flat in uint f_pos_norm;
|
||||||
layout(location = 1) in vec3 f_norm;
|
layout(location = 1) in vec3 f_norm;
|
||||||
|
layout(location = 2) in vec3 m_pos;
|
||||||
// in float f_alt;
|
// in float f_alt;
|
||||||
// in vec4 f_shadow;
|
// in vec4 f_shadow;
|
||||||
// in vec3 light_pos[2];
|
// in vec3 light_pos[2];
|
||||||
@ -72,7 +73,11 @@ void main() {
|
|||||||
|
|
||||||
float f_ao = 1.0;
|
float f_ao = 1.0;
|
||||||
uint material = 0xFFu;
|
uint material = 0xFFu;
|
||||||
vec3 f_col = vec3(0.1);
|
vec3 f_col = mix(
|
||||||
|
vec3(0.035, 0.02, 0.01),
|
||||||
|
vec3(0.06, 0.05, 0.03),
|
||||||
|
floor(abs(fract(m_pos.z * 10.0) - 0.5) * 6.0) / 3.0
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_BAREMINIMUM
|
#ifdef EXPERIMENTAL_BAREMINIMUM
|
||||||
tgt_color = vec4(simple_lighting(f_pos.xyz, f_col, f_ao), 1);
|
tgt_color = vec4(simple_lighting(f_pos.xyz, f_col, f_ao), 1);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
||||||
|
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
|
#include <sky.glsl>
|
||||||
|
|
||||||
layout(location = 0) in vec3 v_pos;
|
layout(location = 0) in vec3 v_pos;
|
||||||
layout(location = 1) in vec3 v_norm;
|
layout(location = 1) in vec3 v_norm;
|
||||||
@ -23,13 +24,27 @@ layout (std140, set = 2, binding = 0)
|
|||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec4 pos_a;
|
vec4 pos_a;
|
||||||
vec4 pos_b;
|
vec4 pos_b;
|
||||||
|
float tether_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) out vec3 f_pos;
|
layout(location = 0) out vec3 f_pos;
|
||||||
layout(location = 1) out vec3 f_norm;
|
layout(location = 1) out vec3 f_norm;
|
||||||
|
layout(location = 2) out vec3 m_pos;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 pos = pos_a.xyz + v_pos * vec3(1, 1, 5);
|
m_pos = v_pos;
|
||||||
|
|
||||||
|
vec3 rz = normalize(pos_b.xyz - pos_a.xyz);
|
||||||
|
vec3 rx = normalize(cross(vec3(0, 0, 1), rz));
|
||||||
|
vec3 ry = normalize(cross(rz, rx));
|
||||||
|
float dist = distance(pos_a.xyz, pos_b.xyz);
|
||||||
|
vec3 pos = pos_a.xyz + (rx * v_pos.x + ry * v_pos.y) * 0.1 + rz * v_pos.z * dist;
|
||||||
|
vec2 ideal_wind_sway = wind_vel * vec2(
|
||||||
|
wind_wave(pos.y * 1.5, 2.9, wind_vel.x, wind_vel.y),
|
||||||
|
wind_wave(pos.x * 1.5, 3.1, wind_vel.y, wind_vel.x)
|
||||||
|
);
|
||||||
|
float dip = (1 - pow(abs(v_pos.z - 0.5) * 2.0, 2)) * max(tether_length - dist, 0.0);
|
||||||
|
pos += vec3(ideal_wind_sway * min(pow(dip, 2), 0.005), -0.5 * dip);
|
||||||
|
|
||||||
f_pos = pos + focus_pos.xyz;
|
f_pos = pos + focus_pos.xyz;
|
||||||
|
|
||||||
@ -37,7 +52,7 @@ void main() {
|
|||||||
f_pos.z -= pow(distance(f_pos.xy + focus_off.xy, focus_pos.xy + focus_off.xy) * 0.05, 2);
|
f_pos.z -= pow(distance(f_pos.xy + focus_off.xy, focus_pos.xy + focus_off.xy) * 0.05, 2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
f_norm = v_norm;
|
f_norm = rx * v_norm.x + ry * v_norm.y + rz * v_norm.z;
|
||||||
|
|
||||||
gl_Position = all_mat * vec4(f_pos, 1);
|
gl_Position = all_mat * vec4(f_pos, 1);
|
||||||
}
|
}
|
||||||
|
@ -1215,7 +1215,13 @@ impl Body {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tether_offset(&self) -> Vec3<f32> { Vec3::new(0.0, self.dimensions().y * 0.5, 0.0) }
|
pub fn tether_offset_leader(&self) -> Vec3<f32> {
|
||||||
|
Vec3::new(0.0, self.dimensions().y * -0.4, self.dimensions().z * 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tether_offset_follower(&self) -> Vec3<f32> {
|
||||||
|
Vec3::new(0.0, self.dimensions().y * 0.6, self.dimensions().z * 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn localize(&self) -> Content {
|
pub fn localize(&self) -> Content {
|
||||||
match self {
|
match self {
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
link::{Is, Link, LinkHandle, Role},
|
link::{Is, Link, LinkHandle, Role},
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
tether,
|
tether,
|
||||||
uid::{Uid, UidAllocator},
|
uid::{IdMaps, Uid},
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
};
|
};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
@ -2,10 +2,10 @@ use crate::{
|
|||||||
comp,
|
comp,
|
||||||
link::{Is, Link, LinkHandle, Role},
|
link::{Is, Link, LinkHandle, Role},
|
||||||
mounting::{Rider, VolumeRider},
|
mounting::{Rider, VolumeRider},
|
||||||
uid::{Uid, UidAllocator},
|
uid::{IdMaps, Uid},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{saveload::MarkerAllocator, Entities, Read, ReadStorage, WriteStorage};
|
use specs::{Entities, Read, ReadStorage, WriteStorage};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -37,20 +37,20 @@ pub enum TetherError {
|
|||||||
|
|
||||||
impl Link for Tethered {
|
impl Link for Tethered {
|
||||||
type CreateData<'a> = (
|
type CreateData<'a> = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, IdMaps>,
|
||||||
WriteStorage<'a, Is<Leader>>,
|
WriteStorage<'a, Is<Leader>>,
|
||||||
WriteStorage<'a, Is<Follower>>,
|
WriteStorage<'a, Is<Follower>>,
|
||||||
ReadStorage<'a, Is<Rider>>,
|
ReadStorage<'a, Is<Rider>>,
|
||||||
ReadStorage<'a, Is<VolumeRider>>,
|
ReadStorage<'a, Is<VolumeRider>>,
|
||||||
);
|
);
|
||||||
type DeleteData<'a> = (
|
type DeleteData<'a> = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, IdMaps>,
|
||||||
WriteStorage<'a, Is<Leader>>,
|
WriteStorage<'a, Is<Leader>>,
|
||||||
WriteStorage<'a, Is<Follower>>,
|
WriteStorage<'a, Is<Follower>>,
|
||||||
);
|
);
|
||||||
type Error = TetherError;
|
type Error = TetherError;
|
||||||
type PersistData<'a> = (
|
type PersistData<'a> = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, IdMaps>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
ReadStorage<'a, comp::Health>,
|
ReadStorage<'a, comp::Health>,
|
||||||
ReadStorage<'a, Is<Leader>>,
|
ReadStorage<'a, Is<Leader>>,
|
||||||
@ -59,15 +59,9 @@ impl Link for Tethered {
|
|||||||
|
|
||||||
fn create(
|
fn create(
|
||||||
this: &LinkHandle<Self>,
|
this: &LinkHandle<Self>,
|
||||||
(
|
(id_maps, is_leaders, is_followers, is_riders, is_volume_rider): &mut Self::CreateData<'_>,
|
||||||
uid_allocator,
|
|
||||||
is_leaders,
|
|
||||||
is_followers,
|
|
||||||
is_riders,
|
|
||||||
is_volume_rider,
|
|
||||||
): &mut Self::CreateData<'_>,
|
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = |uid: Uid| id_maps.uid_entity(uid);
|
||||||
|
|
||||||
if this.leader == this.follower {
|
if this.leader == this.follower {
|
||||||
// Forbid self-tethering
|
// Forbid self-tethering
|
||||||
@ -94,9 +88,9 @@ impl Link for Tethered {
|
|||||||
|
|
||||||
fn persist(
|
fn persist(
|
||||||
this: &LinkHandle<Self>,
|
this: &LinkHandle<Self>,
|
||||||
(uid_allocator, entities, healths, is_leaders, is_followers): &mut Self::PersistData<'_>,
|
(id_maps, entities, healths, is_leaders, is_followers): &mut Self::PersistData<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = |uid: Uid| id_maps.uid_entity(uid);
|
||||||
|
|
||||||
if let Some((leader, follower)) = entity(this.leader).zip(entity(this.follower)) {
|
if let Some((leader, follower)) = entity(this.leader).zip(entity(this.follower)) {
|
||||||
let is_alive = |entity| {
|
let is_alive = |entity| {
|
||||||
@ -115,9 +109,9 @@ impl Link for Tethered {
|
|||||||
|
|
||||||
fn delete(
|
fn delete(
|
||||||
this: &LinkHandle<Self>,
|
this: &LinkHandle<Self>,
|
||||||
(uid_allocator, is_leaders, is_followers): &mut Self::DeleteData<'_>,
|
(id_maps, is_leaders, is_followers): &mut Self::DeleteData<'_>,
|
||||||
) {
|
) {
|
||||||
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = |uid: Uid| id_maps.uid_entity(uid);
|
||||||
|
|
||||||
let leader = entity(this.leader);
|
let leader = entity(this.leader);
|
||||||
let follower = entity(this.follower);
|
let follower = entity(this.follower);
|
||||||
|
@ -3,14 +3,11 @@ use common::{
|
|||||||
link::Is,
|
link::Is,
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
tether::Follower,
|
tether::Follower,
|
||||||
uid::UidAllocator,
|
uid::IdMaps,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use specs::{
|
use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
|
||||||
saveload::{Marker, MarkerAllocator},
|
|
||||||
Entities, Join, Read, ReadStorage, WriteStorage,
|
|
||||||
};
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// This system is responsible for controlling mounts
|
/// This system is responsible for controlling mounts
|
||||||
@ -18,7 +15,7 @@ use vek::*;
|
|||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, IdMaps>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
ReadStorage<'a, Is<Follower>>,
|
ReadStorage<'a, Is<Follower>>,
|
||||||
@ -37,7 +34,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
fn run(
|
fn run(
|
||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(
|
(
|
||||||
uid_allocator,
|
id_maps,
|
||||||
entities,
|
entities,
|
||||||
dt,
|
dt,
|
||||||
is_followers,
|
is_followers,
|
||||||
@ -49,12 +46,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
masses,
|
masses,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
for (follower, is_follower, follower_body, scale) in
|
for (follower, is_follower, follower_body, follower_scale) in
|
||||||
(&entities, &is_followers, bodies.maybe(), scales.maybe()).join()
|
(&entities, &is_followers, bodies.maybe(), scales.maybe()).join()
|
||||||
{
|
{
|
||||||
let Some(leader) = uid_allocator
|
let Some(leader) = id_maps.uid_entity(is_follower.leader) else { continue };
|
||||||
.retrieve_entity_internal(is_follower.leader.id())
|
|
||||||
else { continue };
|
|
||||||
|
|
||||||
let (Some(leader_pos), Some(follower_pos)) = (
|
let (Some(leader_pos), Some(follower_pos)) = (
|
||||||
positions.get(leader).copied(),
|
positions.get(leader).copied(),
|
||||||
@ -67,18 +62,36 @@ impl<'a> System<'a> for Sys {
|
|||||||
) else { continue };
|
) else { continue };
|
||||||
|
|
||||||
if velocities.contains(follower) && velocities.contains(leader) {
|
if velocities.contains(follower) && velocities.contains(leader) {
|
||||||
|
let attach_offset = orientations
|
||||||
|
.get(leader)
|
||||||
|
.map(|ori| {
|
||||||
|
ori.to_quat()
|
||||||
|
* bodies
|
||||||
|
.get(leader)
|
||||||
|
.map(|b| {
|
||||||
|
b.tether_offset_leader()
|
||||||
|
* scales.get(leader).copied().unwrap_or(Scale(1.0)).0
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
let attach_pos = leader_pos.0 + attach_offset;
|
||||||
|
|
||||||
let tether_offset = orientations
|
let tether_offset = orientations
|
||||||
.get(follower)
|
.get(follower)
|
||||||
.map(|ori| {
|
.map(|ori| {
|
||||||
ori.to_quat()
|
ori.to_quat()
|
||||||
* follower_body
|
* follower_body
|
||||||
.map(|b| b.tether_offset() * scale.copied().unwrap_or(Scale(1.0)).0)
|
.map(|b| {
|
||||||
|
b.tether_offset_follower()
|
||||||
|
* follower_scale.copied().unwrap_or(Scale(1.0)).0
|
||||||
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let tether_pos = follower_pos.0 + tether_offset;
|
let tether_pos = follower_pos.0 + tether_offset;
|
||||||
let pull_factor =
|
let pull_factor =
|
||||||
(leader_pos.0.distance(tether_pos) - is_follower.tether_length).max(0.0);
|
(attach_pos.distance(tether_pos) - is_follower.tether_length).max(0.0);
|
||||||
let strength = pull_factor * 50000.0;
|
let strength = pull_factor * 50000.0;
|
||||||
let pull_dir = (leader_pos.0 - follower_pos.0)
|
let pull_dir = (leader_pos.0 - follower_pos.0)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
@ -91,8 +104,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
if let Some(follower_ori) = orientations.get_mut(follower) {
|
if let Some(follower_ori) = orientations.get_mut(follower) {
|
||||||
let turn_strength = pull_factor
|
let turn_strength = pull_factor
|
||||||
* (tether_offset.magnitude() * (leader_pos.0 - tether_pos).magnitude()
|
* (tether_offset.magnitude() * (attach_pos - tether_pos).magnitude()
|
||||||
- tether_offset.dot(leader_pos.0 - tether_pos).abs())
|
- tether_offset.dot(attach_pos - tether_pos).abs())
|
||||||
* 2.0;
|
* 2.0;
|
||||||
let target_ori = follower_ori.yawed_towards(Dir::new(pull_dir));
|
let target_ori = follower_ori.yawed_towards(Dir::new(pull_dir));
|
||||||
*follower_ori = follower_ori.slerped_towards(target_ori, turn_strength * dt.0);
|
*follower_ori = follower_ori.slerped_towards(target_ori, turn_strength * dt.0);
|
||||||
|
@ -1824,7 +1824,7 @@ fn handle_spawn_ship(
|
|||||||
.link(Tethered {
|
.link(Tethered {
|
||||||
leader,
|
leader,
|
||||||
follower,
|
follower,
|
||||||
tether_length: 4.0,
|
tether_length: 6.0,
|
||||||
})
|
})
|
||||||
.map_err(|_| "Failed to tether entities")?;
|
.map_err(|_| "Failed to tether entities")?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,19 +8,21 @@ use vek::*;
|
|||||||
pub struct Locals {
|
pub struct Locals {
|
||||||
pos_a: [f32; 4],
|
pos_a: [f32; 4],
|
||||||
pos_b: [f32; 4],
|
pos_b: [f32; 4],
|
||||||
|
tether_length: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Locals {
|
impl Locals {
|
||||||
pub fn new(pos_a: Vec3<f32>, pos_b: Vec3<f32>) -> Self {
|
pub fn new(pos_a: Vec3<f32>, pos_b: Vec3<f32>, tether_length: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pos_a: pos_a.with_w(0.0).into_array(),
|
pos_a: pos_a.with_w(0.0).into_array(),
|
||||||
pos_b: pos_b.with_w(0.0).into_array(),
|
pos_b: pos_b.with_w(0.0).into_array(),
|
||||||
|
tether_length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Locals {
|
impl Default for Locals {
|
||||||
fn default() -> Self { Self::new(Vec3::zero(), Vec3::zero()) }
|
fn default() -> Self { Self::new(Vec3::zero(), Vec3::zero(), 0.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BoundLocals = Bound<Consts<Locals>>;
|
pub type BoundLocals = Bound<Consts<Locals>>;
|
||||||
|
@ -13,11 +13,11 @@ use common::{
|
|||||||
comp,
|
comp,
|
||||||
link::Is,
|
link::Is,
|
||||||
tether::Follower,
|
tether::Follower,
|
||||||
uid::Uid,
|
uid::{IdMaps, Uid},
|
||||||
util::srgba_to_linear,
|
util::srgba_to_linear,
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use specs::Join;
|
use specs::{Join, WorldExt};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub struct TetherMgr {
|
pub struct TetherMgr {
|
||||||
@ -36,23 +36,48 @@ impl TetherMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client, focus_off: Vec3<f32>) {
|
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client, focus_off: Vec3<f32>) {
|
||||||
let positions = client.state().read_storage::<comp::Pos>();
|
let interpolated = client
|
||||||
|
.state()
|
||||||
|
.read_storage::<crate::ecs::comp::Interpolated>();
|
||||||
|
let scales = client.state().read_storage::<comp::Scale>();
|
||||||
|
let bodies = client.state().read_storage::<comp::Body>();
|
||||||
|
let id_maps = client.state().ecs().read_resource::<IdMaps>();
|
||||||
let is_followers = client.state().read_storage::<Is<Follower>>();
|
let is_followers = client.state().read_storage::<Is<Follower>>();
|
||||||
for (pos, is_follower) in (&positions, &is_followers).join() {
|
for (interp, is_follower, body, scale) in
|
||||||
|
(&interpolated, &is_followers, bodies.maybe(), scales.maybe()).join()
|
||||||
|
{
|
||||||
|
let Some(leader) = id_maps.uid_entity(is_follower.leader) else { continue };
|
||||||
|
let pos_a = interpolated.get(leader).map_or(Vec3::zero(), |i| i.pos)
|
||||||
|
+ interpolated.get(leader).zip(bodies.get(leader)).map_or(
|
||||||
|
Vec3::zero(),
|
||||||
|
|(i, body)| {
|
||||||
|
i.ori.to_quat()
|
||||||
|
* body.tether_offset_leader()
|
||||||
|
* scales.get(leader).copied().unwrap_or(comp::Scale(1.0)).0
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let pos_b = interp.pos
|
||||||
|
+ body.map_or(Vec3::zero(), |body| {
|
||||||
|
interp.ori.to_quat()
|
||||||
|
* body.tether_offset_follower()
|
||||||
|
* scale.copied().unwrap_or(comp::Scale(1.0)).0
|
||||||
|
});
|
||||||
|
|
||||||
let (locals, stale_flag) = self
|
let (locals, stale_flag) = self
|
||||||
.tethers
|
.tethers
|
||||||
.entry((is_follower.leader, is_follower.follower))
|
.entry((is_follower.leader, is_follower.follower))
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
(
|
(
|
||||||
renderer.create_tether_bound_locals(&[Locals::new(
|
renderer.create_tether_bound_locals(&[Locals::default()]),
|
||||||
pos.0 - focus_off,
|
|
||||||
pos.0 - focus_off,
|
|
||||||
)]),
|
|
||||||
self.stale_flag,
|
self.stale_flag,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
renderer.update_consts(locals, &[Locals::new(pos.0 - focus_off, pos.0 - focus_off)]);
|
renderer.update_consts(locals, &[Locals::new(
|
||||||
|
pos_a - focus_off,
|
||||||
|
pos_b - focus_off,
|
||||||
|
is_follower.tether_length,
|
||||||
|
)]);
|
||||||
|
|
||||||
*stale_flag = self.stale_flag;
|
*stale_flag = self.stale_flag;
|
||||||
}
|
}
|
||||||
@ -86,8 +111,8 @@ fn create_tether_mesh() -> Mesh<Vertex> {
|
|||||||
let z = s as f32 / SEGMENTS as f32;
|
let z = s as f32 / SEGMENTS as f32;
|
||||||
Quad {
|
Quad {
|
||||||
a: Vertex::new(start.with_z(z), start.with_z(0.0)),
|
a: Vertex::new(start.with_z(z), start.with_z(0.0)),
|
||||||
b: Vertex::new(start.with_z(z + 1.0), start.with_z(0.0)),
|
b: Vertex::new(start.with_z(z + 1.0 / SEGMENTS as f32), start.with_z(0.0)),
|
||||||
c: Vertex::new(end.with_z(z + 1.0), end.with_z(0.0)),
|
c: Vertex::new(end.with_z(z + 1.0 / SEGMENTS as f32), end.with_z(0.0)),
|
||||||
d: Vertex::new(end.with_z(z), end.with_z(0.0)),
|
d: Vertex::new(end.with_z(z), end.with_z(0.0)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user