Merge branch 'feature/fixrate-interpolate'
ci/woodpecker/push/build Pipeline was successful
Details
ci/woodpecker/push/build Pipeline was successful
Details
This commit is contained in:
commit
73160172ee
|
@ -763,6 +763,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fps_counter"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3aaba7ff514ee9d802b562927f80b1e94e93d8e74c31b134c9c3762dabf1a36b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -2293,6 +2299,18 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "testbed"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-std",
|
||||||
|
"edict",
|
||||||
|
"fps_counter",
|
||||||
|
"lyra-engine",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.48"
|
version = "1.0.48"
|
||||||
|
|
|
@ -5,7 +5,8 @@ edition = "2021"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"lyra-resource"
|
"lyra-resource",
|
||||||
|
"examples/testbed"
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,5 +12,3 @@ async-std = "1.12.0"
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
fps_counter = "2.0.0"
|
fps_counter = "2.0.0"
|
||||||
edict = "0.5.0"
|
edict = "0.5.0"
|
||||||
|
|
||||||
[workspace]
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ async fn main() {
|
||||||
game.world().insert_resource(TpsAccumulator(0.0));
|
game.world().insert_resource(TpsAccumulator(0.0));
|
||||||
|
|
||||||
let mut sys = BatchedSystem::new();
|
let mut sys = BatchedSystem::new();
|
||||||
sys.with_criteria(FixedTimestep::new(30));
|
sys.with_criteria(FixedTimestep::new(45));
|
||||||
sys.with_system(spin_system);
|
sys.with_system(spin_system);
|
||||||
sys.with_system(fps_system);
|
sys.with_system(fps_system);
|
||||||
|
|
||||||
|
|
|
@ -85,4 +85,18 @@ impl Transform {
|
||||||
pub fn rotate_z(&mut self, angle: Angle) {
|
pub fn rotate_z(&mut self, angle: Angle) {
|
||||||
self.rotate(Quat::from_rotation_z(angle.to_radians()))
|
self.rotate(Quat::from_rotation_z(angle.to_radians()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a linear interpolation between `self` and `rhs` based on the value `alpha`.
|
||||||
|
///
|
||||||
|
/// When `alpha` is `0.0`, the result will be equal to `self`. When `alpha` is `1.0`, the result
|
||||||
|
/// will be equal to `rhs`. When `alpha` is outside of range `[0, 1]`, the result is linearly
|
||||||
|
/// extrapolated.
|
||||||
|
pub fn lerp(&self, rhs: Transform, alpha: f32) -> Self {
|
||||||
|
let mut res = self.clone();
|
||||||
|
res.translation = self.translation.lerp(rhs.translation, alpha);
|
||||||
|
res.rotation = self.rotation.lerp(rhs.rotation, alpha);
|
||||||
|
res.scale = self.scale.lerp(rhs.scale, alpha);
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,17 +2,19 @@ use edict::EntityId;
|
||||||
|
|
||||||
use crate::math::Transform;
|
use crate::math::Transform;
|
||||||
|
|
||||||
|
use super::renderer::CachedTransform;
|
||||||
|
|
||||||
pub struct RenderJob {
|
pub struct RenderJob {
|
||||||
pub entity: EntityId,
|
pub entity: EntityId,
|
||||||
pub shader_id: u64,
|
pub shader_id: u64,
|
||||||
pub mesh_buffer_id: uuid::Uuid,
|
pub mesh_buffer_id: uuid::Uuid,
|
||||||
|
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub last_transform: Option<Transform>, // TODO: render interpolation
|
pub last_transform: Option<CachedTransform>, // TODO: render interpolation
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderJob {
|
impl RenderJob {
|
||||||
pub fn new(entity: EntityId, shader_id: u64, mesh_buffer_id: uuid::Uuid, transform: Transform, last_transform: Option<Transform>) -> Self {
|
pub fn new(entity: EntityId, shader_id: u64, mesh_buffer_id: uuid::Uuid, transform: Transform, last_transform: Option<CachedTransform>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
entity,
|
entity,
|
||||||
shader_id,
|
shader_id,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::borrow::Cow;
|
||||||
use edict::query::EpochOf;
|
use edict::query::EpochOf;
|
||||||
use edict::{EntityId, Entities};
|
use edict::{EntityId, Entities};
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
|
use instant::Instant;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use wgpu::{BindGroup, BindGroupLayout, Limits};
|
use wgpu::{BindGroup, BindGroupLayout, Limits};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
@ -48,6 +49,14 @@ struct MeshBufferStorage {
|
||||||
transform_index: TransformBufferIndices,
|
transform_index: TransformBufferIndices,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CachedTransform {
|
||||||
|
last_updated_at: Option<Instant>,
|
||||||
|
cached_at: Instant,
|
||||||
|
to_transform: Transform,
|
||||||
|
from_transform: Transform,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BasicRenderer {
|
pub struct BasicRenderer {
|
||||||
pub surface: wgpu::Surface,
|
pub surface: wgpu::Surface,
|
||||||
pub device: wgpu::Device,
|
pub device: wgpu::Device,
|
||||||
|
@ -63,6 +72,7 @@ pub struct BasicRenderer {
|
||||||
|
|
||||||
mesh_buffers: HashMap<uuid::Uuid, MeshBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
mesh_buffers: HashMap<uuid::Uuid, MeshBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||||
entity_meshes: HashMap<EntityId, uuid::Uuid>,
|
entity_meshes: HashMap<EntityId, uuid::Uuid>,
|
||||||
|
entity_last_transforms: HashMap<EntityId, CachedTransform>,
|
||||||
|
|
||||||
transform_buffers: TransformBuffers,
|
transform_buffers: TransformBuffers,
|
||||||
transform_bind_group_layout: BindGroupLayout,
|
transform_bind_group_layout: BindGroupLayout,
|
||||||
|
@ -312,6 +322,7 @@ impl BasicRenderer {
|
||||||
texture_bind_group_layout,
|
texture_bind_group_layout,
|
||||||
default_texture_bind_group: default_tex_bindgroup,
|
default_texture_bind_group: default_tex_bindgroup,
|
||||||
depth_buffer_texture: depth_texture,
|
depth_buffer_texture: depth_texture,
|
||||||
|
entity_last_transforms: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// create the default pipelines
|
// create the default pipelines
|
||||||
|
@ -510,18 +521,50 @@ impl Renderer for BasicRenderer {
|
||||||
|
|
||||||
let mut alive_entities = HashSet::new();
|
let mut alive_entities = HashSet::new();
|
||||||
|
|
||||||
for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &ModelComponent, EpochOf<ModelComponent>, &TransformComponent)>().iter() {
|
let now_inst = Instant::now();
|
||||||
|
|
||||||
|
for (entity, model, model_epoch, transform, transform_epoch) in main_world.query::<(Entities, &ModelComponent, EpochOf<ModelComponent>, &TransformComponent, EpochOf<TransformComponent>)>().iter() {
|
||||||
alive_entities.insert(entity);
|
alive_entities.insert(entity);
|
||||||
|
|
||||||
let model = model.data.as_ref().unwrap().as_ref();
|
let cached = match self.entity_last_transforms.get_mut(&entity) {
|
||||||
|
Some(last) if transform_epoch == last_epoch => {
|
||||||
|
last.from_transform = last.to_transform;
|
||||||
|
last.to_transform = transform.transform;
|
||||||
|
last.last_updated_at = Some(last.cached_at);
|
||||||
|
last.cached_at = now_inst;
|
||||||
|
|
||||||
|
last.clone()
|
||||||
|
},
|
||||||
|
Some(last) => last.clone(),
|
||||||
|
None => {
|
||||||
|
let cached = CachedTransform {
|
||||||
|
last_updated_at: None,
|
||||||
|
cached_at: now_inst,
|
||||||
|
from_transform: transform.transform,
|
||||||
|
to_transform: transform.transform,
|
||||||
|
};
|
||||||
|
self.entity_last_transforms.insert(entity, cached.clone());
|
||||||
|
cached
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let fixed_time = match cached.last_updated_at {
|
||||||
|
Some(last_updated_at) => cached.cached_at - last_updated_at,
|
||||||
|
None => now_inst - cached.cached_at
|
||||||
|
}.as_secs_f32();
|
||||||
|
let accumulator = (now_inst - cached.cached_at).as_secs_f32();
|
||||||
|
let alpha = accumulator / fixed_time;
|
||||||
|
|
||||||
|
let transform_val = cached.from_transform.lerp(cached.to_transform, alpha);
|
||||||
|
|
||||||
|
let model = model.data.as_ref().unwrap().as_ref();
|
||||||
for mesh in model.meshes.iter() {
|
for mesh in model.meshes.iter() {
|
||||||
if !self.process_mesh(entity, transform.transform, mesh) && model_epoch == last_epoch {
|
if !self.process_mesh(entity, transform_val, mesh) && model_epoch == last_epoch {
|
||||||
self.update_mesh_buffers(entity, mesh);
|
self.update_mesh_buffers(entity, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
let shader = mesh.material().shader_uuid.unwrap_or(0);
|
let shader = mesh.material().shader_uuid.unwrap_or(0);
|
||||||
let job = RenderJob::new(entity, shader, mesh.uuid, transform.transform, None);
|
let job = RenderJob::new(entity, shader, mesh.uuid, transform_val, None);
|
||||||
self.render_jobs.push_back(job);
|
self.render_jobs.push_back(job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue