Compare commits
14 Commits
cylinder
...
entity-deb
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ed031919 | |||
| 364939167c | |||
| 8b6f3620f8 | |||
| 71426c257f | |||
| 041cc15f20 | |||
| 6ef6174693 | |||
| 70fb970582 | |||
| 31184d21da | |||
| 6b4b17f49d | |||
| d0c17873f6 | |||
| d39705d5e7 | |||
| a3a50580f8 | |||
| d5bf4549a9 | |||
| b5da85fae1 |
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -911,7 +911,7 @@ checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixed_wide"
|
name = "fixed_wide"
|
||||||
version = "0.2.0"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bnum",
|
"bnum",
|
||||||
@@ -1838,7 +1838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1860,7 +1860,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linear_ops"
|
name = "linear_ops"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixed_wide",
|
"fixed_wide",
|
||||||
"paste",
|
"paste",
|
||||||
@@ -3732,6 +3732,7 @@ dependencies = [
|
|||||||
"id",
|
"id",
|
||||||
"linear_ops",
|
"linear_ops",
|
||||||
"ratio_ops",
|
"ratio_ops",
|
||||||
|
"vbsp",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -24,7 +24,3 @@ resolver = "2"
|
|||||||
#lto = true
|
#lto = true
|
||||||
strip = true
|
strip = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
strip = false
|
|
||||||
opt-level = 3
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use strafesnet_settings::settings;
|
|||||||
use strafesnet_session::session;
|
use strafesnet_session::session;
|
||||||
use strafesnet_common::model::{self, ColorId, NormalId, PolygonIter, PositionId, RenderConfigId, TextureCoordinateId, VertexId};
|
use strafesnet_common::model::{self, ColorId, NormalId, PolygonIter, PositionId, RenderConfigId, TextureCoordinateId, VertexId};
|
||||||
use wgpu::{util::DeviceExt,AstcBlock,AstcChannel};
|
use wgpu::{util::DeviceExt,AstcBlock,AstcChannel};
|
||||||
use crate::model::{self as model_graphics,IndexedGraphicsMeshOwnedRenderConfig,IndexedGraphicsMeshOwnedRenderConfigId,GraphicsMeshOwnedRenderConfig,GraphicsModelColor4,GraphicsModelOwned,GraphicsVertex};
|
use crate::model::{self as model_graphics,IndexedGraphicsMeshOwnedRenderConfig,IndexedGraphicsMeshOwnedRenderConfigId,GraphicsMeshOwnedRenderConfig,GraphicsModelColor4,GraphicsModelOwned,GraphicsVertex,DebugGraphicsVertex};
|
||||||
|
|
||||||
pub fn required_limits()->wgpu::Limits{
|
pub fn required_limits()->wgpu::Limits{
|
||||||
wgpu::Limits::default()
|
wgpu::Limits::default()
|
||||||
@@ -36,12 +36,22 @@ struct GraphicsModel{
|
|||||||
instance_count:u32,
|
instance_count:u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DebugGraphicsMesh{
|
||||||
|
indices:Indices,
|
||||||
|
vertex_buf:wgpu::Buffer,
|
||||||
|
}
|
||||||
|
struct DebugGraphicsModel{
|
||||||
|
debug_mesh_id:u32,
|
||||||
|
bind_group:wgpu::BindGroup,
|
||||||
|
}
|
||||||
|
|
||||||
struct GraphicsSamplers{
|
struct GraphicsSamplers{
|
||||||
repeat:wgpu::Sampler,
|
repeat:wgpu::Sampler,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GraphicsBindGroupLayouts{
|
struct GraphicsBindGroupLayouts{
|
||||||
model:wgpu::BindGroupLayout,
|
model:wgpu::BindGroupLayout,
|
||||||
|
debug_model:wgpu::BindGroupLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GraphicsBindGroups{
|
struct GraphicsBindGroups{
|
||||||
@@ -52,6 +62,7 @@ struct GraphicsBindGroups{
|
|||||||
struct GraphicsPipelines{
|
struct GraphicsPipelines{
|
||||||
skybox:wgpu::RenderPipeline,
|
skybox:wgpu::RenderPipeline,
|
||||||
model:wgpu::RenderPipeline,
|
model:wgpu::RenderPipeline,
|
||||||
|
debug:wgpu::RenderPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GraphicsCamera{
|
struct GraphicsCamera{
|
||||||
@@ -103,26 +114,6 @@ impl std::default::Default for GraphicsCamera{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MODEL_BUFFER_SIZE:usize=4*4 + 12 + 4;//let size=std::mem::size_of::<ModelInstance>();
|
|
||||||
const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*4;
|
|
||||||
fn get_instances_buffer_data(instances:&[GraphicsModelOwned])->Vec<f32>{
|
|
||||||
let mut raw=Vec::with_capacity(MODEL_BUFFER_SIZE*instances.len());
|
|
||||||
for mi in instances{
|
|
||||||
//model transform
|
|
||||||
raw.extend_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&mi.transform)[..]);
|
|
||||||
//normal transform
|
|
||||||
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.x_axis));
|
|
||||||
raw.extend_from_slice(&[0.0]);
|
|
||||||
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.y_axis));
|
|
||||||
raw.extend_from_slice(&[0.0]);
|
|
||||||
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.z_axis));
|
|
||||||
raw.extend_from_slice(&[0.0]);
|
|
||||||
//color
|
|
||||||
raw.extend_from_slice(AsRef::<[f32; 4]>::as_ref(&mi.color.get()));
|
|
||||||
}
|
|
||||||
raw
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GraphicsState{
|
pub struct GraphicsState{
|
||||||
pipelines:GraphicsPipelines,
|
pipelines:GraphicsPipelines,
|
||||||
bind_groups:GraphicsBindGroups,
|
bind_groups:GraphicsBindGroups,
|
||||||
@@ -132,6 +123,8 @@ pub struct GraphicsState{
|
|||||||
camera_buf:wgpu::Buffer,
|
camera_buf:wgpu::Buffer,
|
||||||
temp_squid_texture_view:wgpu::TextureView,
|
temp_squid_texture_view:wgpu::TextureView,
|
||||||
models:Vec<GraphicsModel>,
|
models:Vec<GraphicsModel>,
|
||||||
|
debug_meshes:Vec<DebugGraphicsMesh>,
|
||||||
|
debug_models:Vec<DebugGraphicsModel>,
|
||||||
depth_view:wgpu::TextureView,
|
depth_view:wgpu::TextureView,
|
||||||
staging_belt:wgpu::util::StagingBelt,
|
staging_belt:wgpu::util::StagingBelt,
|
||||||
}
|
}
|
||||||
@@ -166,6 +159,76 @@ impl GraphicsState{
|
|||||||
self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2();
|
self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2();
|
||||||
}
|
}
|
||||||
pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:&map::CompleteMap){
|
pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:&map::CompleteMap){
|
||||||
|
//generate debug meshes, each debug model refers to one
|
||||||
|
self.debug_meshes=map.meshes.iter().map(|mesh|{
|
||||||
|
let vertices:Vec<DebugGraphicsVertex>=mesh.unique_vertices.iter().map(|vertex|{
|
||||||
|
DebugGraphicsVertex{
|
||||||
|
pos:mesh.unique_pos[vertex.pos.get() as usize].to_array().map(Into::into),
|
||||||
|
normal:mesh.unique_normal[vertex.normal.get() as usize].to_array().map(Into::into),
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
let vertex_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
|
||||||
|
label:Some("Vertex"),
|
||||||
|
contents:bytemuck::cast_slice(&vertices),
|
||||||
|
usage:wgpu::BufferUsages::VERTEX,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut indices=Vec::new();
|
||||||
|
for physics_group in &mesh.physics_groups{
|
||||||
|
for polygon_group_id in &physics_group.groups{
|
||||||
|
for poly in mesh.polygon_groups[polygon_group_id.get() as usize].polys(){
|
||||||
|
// triangulate
|
||||||
|
let mut poly_vertices=poly.into_iter().copied();
|
||||||
|
if let (Some(a),Some(mut b))=(poly_vertices.next(),poly_vertices.next()){
|
||||||
|
for c in poly_vertices{
|
||||||
|
indices.extend([a,b,c]);
|
||||||
|
b=c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugGraphicsMesh{
|
||||||
|
indices:if (u32::MAX as usize)<vertices.len(){
|
||||||
|
panic!("Model has too many vertices!")
|
||||||
|
}else if (u16::MAX as usize)<vertices.len(){
|
||||||
|
Indices::new(device,&indices.into_iter().map(|vertex_idx|vertex_idx.get() as u32).collect(),wgpu::IndexFormat::Uint32)
|
||||||
|
}else{
|
||||||
|
Indices::new(device,&indices.into_iter().map(|vertex_idx|vertex_idx.get() as u16).collect(),wgpu::IndexFormat::Uint16)
|
||||||
|
},
|
||||||
|
vertex_buf,
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
//generate debug models, only one will be rendered at a time
|
||||||
|
self.debug_models=map.models.iter().enumerate().map(|(model_id,model)|{
|
||||||
|
let model_uniforms=get_instance_buffer_data(&GraphicsModelOwned{
|
||||||
|
transform:model.transform.into(),
|
||||||
|
normal_transform:glam::Mat3::from_cols_array_2d(&model.transform.matrix3.to_array().map(|row|row.map(Into::into))).inverse().transpose(),
|
||||||
|
color:GraphicsModelColor4::new(glam::vec4(1.0,0.0,0.0,0.2)),
|
||||||
|
});
|
||||||
|
let model_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
|
||||||
|
label:Some(format!("Debug Model{} Buf",model_id).as_str()),
|
||||||
|
contents:bytemuck::cast_slice(&model_uniforms),
|
||||||
|
usage:wgpu::BufferUsages::UNIFORM|wgpu::BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
let bind_group=device.create_bind_group(&wgpu::BindGroupDescriptor{
|
||||||
|
layout:&self.bind_group_layouts.debug_model,
|
||||||
|
entries:&[
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
binding:0,
|
||||||
|
resource:model_buf.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
label:Some(format!("Debug Model{} Bind Group",model_id).as_str()),
|
||||||
|
});
|
||||||
|
DebugGraphicsModel{
|
||||||
|
debug_mesh_id:model.mesh.get(),
|
||||||
|
bind_group,
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
//generate texture view per texture
|
//generate texture view per texture
|
||||||
let texture_views:HashMap<strafesnet_common::model::TextureId,wgpu::TextureView>=map.textures.iter().enumerate().filter_map(|(texture_id,texture_data)|{
|
let texture_views:HashMap<strafesnet_common::model::TextureId,wgpu::TextureView>=map.textures.iter().enumerate().filter_map(|(texture_id,texture_data)|{
|
||||||
let texture_id=model::TextureId::new(texture_id as u32);
|
let texture_id=model::TextureId::new(texture_id as u32);
|
||||||
@@ -608,6 +671,21 @@ impl GraphicsState{
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
let debug_model_bind_group_layout=device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor{
|
||||||
|
label:Some("Debug Model Bind Group Layout"),
|
||||||
|
entries:&[
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
binding:0,
|
||||||
|
visibility:wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||||
|
ty:wgpu::BindingType::Buffer{
|
||||||
|
ty:wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset:false,
|
||||||
|
min_binding_size:None,
|
||||||
|
},
|
||||||
|
count:None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
let clamp_sampler=device.create_sampler(&wgpu::SamplerDescriptor{
|
let clamp_sampler=device.create_sampler(&wgpu::SamplerDescriptor{
|
||||||
label:Some("Clamp Sampler"),
|
label:Some("Clamp Sampler"),
|
||||||
@@ -756,6 +834,14 @@ impl GraphicsState{
|
|||||||
],
|
],
|
||||||
push_constant_ranges:&[],
|
push_constant_ranges:&[],
|
||||||
});
|
});
|
||||||
|
let debug_model_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
||||||
|
label:None,
|
||||||
|
bind_group_layouts:&[
|
||||||
|
&camera_bind_group_layout,
|
||||||
|
&debug_model_bind_group_layout,
|
||||||
|
],
|
||||||
|
push_constant_ranges:&[],
|
||||||
|
});
|
||||||
let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
||||||
label:None,
|
label:None,
|
||||||
bind_group_layouts:&[
|
bind_group_layouts:&[
|
||||||
@@ -831,6 +917,45 @@ impl GraphicsState{
|
|||||||
multiview:None,
|
multiview:None,
|
||||||
cache:None,
|
cache:None,
|
||||||
});
|
});
|
||||||
|
let debug_model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{
|
||||||
|
label:Some("Debug Model Pipeline"),
|
||||||
|
layout:Some(&debug_model_pipeline_layout),
|
||||||
|
vertex:wgpu::VertexState{
|
||||||
|
module:&shader,
|
||||||
|
entry_point:Some("vs_debug"),
|
||||||
|
buffers:&[wgpu::VertexBufferLayout{
|
||||||
|
array_stride:std::mem::size_of::<DebugGraphicsVertex>() as wgpu::BufferAddress,
|
||||||
|
step_mode:wgpu::VertexStepMode::Vertex,
|
||||||
|
attributes:&wgpu::vertex_attr_array![0=>Float32x3,1=>Float32x3],
|
||||||
|
}],
|
||||||
|
compilation_options:wgpu::PipelineCompilationOptions::default(),
|
||||||
|
},
|
||||||
|
fragment:Some(wgpu::FragmentState{
|
||||||
|
module:&shader,
|
||||||
|
entry_point:Some("fs_debug"),
|
||||||
|
targets:&[Some(wgpu::ColorTargetState{
|
||||||
|
format:config.view_formats[0],
|
||||||
|
blend:Some(wgpu::BlendState::ALPHA_BLENDING),
|
||||||
|
write_mask:wgpu::ColorWrites::default(),
|
||||||
|
})],
|
||||||
|
compilation_options:wgpu::PipelineCompilationOptions::default(),
|
||||||
|
}),
|
||||||
|
primitive:wgpu::PrimitiveState{
|
||||||
|
front_face:wgpu::FrontFace::Cw,
|
||||||
|
cull_mode:Some(wgpu::Face::Front),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
depth_stencil:Some(wgpu::DepthStencilState{
|
||||||
|
format:Self::DEPTH_FORMAT,
|
||||||
|
depth_write_enabled:true,
|
||||||
|
depth_compare:wgpu::CompareFunction::Always,
|
||||||
|
stencil:wgpu::StencilState::default(),
|
||||||
|
bias:wgpu::DepthBiasState::default(),
|
||||||
|
}),
|
||||||
|
multisample:wgpu::MultisampleState::default(),
|
||||||
|
multiview:None,
|
||||||
|
cache:None,
|
||||||
|
});
|
||||||
|
|
||||||
let camera=GraphicsCamera::default();
|
let camera=GraphicsCamera::default();
|
||||||
let camera_uniforms=camera.to_uniform_data(glam::Vec3::ZERO,glam::Vec2::ZERO);
|
let camera_uniforms=camera.to_uniform_data(glam::Vec3::ZERO,glam::Vec2::ZERO);
|
||||||
@@ -870,7 +995,8 @@ impl GraphicsState{
|
|||||||
Self{
|
Self{
|
||||||
pipelines:GraphicsPipelines{
|
pipelines:GraphicsPipelines{
|
||||||
skybox:sky_pipeline,
|
skybox:sky_pipeline,
|
||||||
model:model_pipeline
|
model:model_pipeline,
|
||||||
|
debug:debug_model_pipeline,
|
||||||
},
|
},
|
||||||
bind_groups:GraphicsBindGroups{
|
bind_groups:GraphicsBindGroups{
|
||||||
camera:camera_bind_group,
|
camera:camera_bind_group,
|
||||||
@@ -879,9 +1005,14 @@ impl GraphicsState{
|
|||||||
camera,
|
camera,
|
||||||
camera_buf,
|
camera_buf,
|
||||||
models:Vec::new(),
|
models:Vec::new(),
|
||||||
|
debug_meshes:Vec::new(),
|
||||||
|
debug_models:Vec::new(),
|
||||||
depth_view,
|
depth_view,
|
||||||
staging_belt:wgpu::util::StagingBelt::new(0x100),
|
staging_belt:wgpu::util::StagingBelt::new(0x100),
|
||||||
bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout},
|
bind_group_layouts:GraphicsBindGroupLayouts{
|
||||||
|
model:model_bind_group_layout,
|
||||||
|
debug_model:debug_model_bind_group_layout,
|
||||||
|
},
|
||||||
samplers:GraphicsSamplers{repeat:repeat_sampler},
|
samplers:GraphicsSamplers{repeat:repeat_sampler},
|
||||||
temp_squid_texture_view:squid_texture_view,
|
temp_squid_texture_view:squid_texture_view,
|
||||||
}
|
}
|
||||||
@@ -969,6 +1100,7 @@ impl GraphicsState{
|
|||||||
rpass.set_bind_group(0,&self.bind_groups.camera,&[]);
|
rpass.set_bind_group(0,&self.bind_groups.camera,&[]);
|
||||||
rpass.set_bind_group(1,&self.bind_groups.skybox_texture,&[]);
|
rpass.set_bind_group(1,&self.bind_groups.skybox_texture,&[]);
|
||||||
|
|
||||||
|
// Draw all models.
|
||||||
rpass.set_pipeline(&self.pipelines.model);
|
rpass.set_pipeline(&self.pipelines.model);
|
||||||
for model in &self.models{
|
for model in &self.models{
|
||||||
rpass.set_bind_group(2,&model.bind_group,&[]);
|
rpass.set_bind_group(2,&model.bind_group,&[]);
|
||||||
@@ -980,6 +1112,19 @@ impl GraphicsState{
|
|||||||
|
|
||||||
rpass.set_pipeline(&self.pipelines.skybox);
|
rpass.set_pipeline(&self.pipelines.skybox);
|
||||||
rpass.draw(0..3,0..1);
|
rpass.draw(0..3,0..1);
|
||||||
|
|
||||||
|
// render a single debug_model in red
|
||||||
|
if let Some(model_id)=frame_state.debug_model{
|
||||||
|
if let Some(model)=self.debug_models.get(model_id.get() as usize){
|
||||||
|
let mesh=&self.debug_meshes[model.debug_mesh_id as usize];
|
||||||
|
rpass.set_pipeline(&self.pipelines.debug);
|
||||||
|
rpass.set_bind_group(1,&model.bind_group,&[]);
|
||||||
|
rpass.set_vertex_buffer(0,mesh.vertex_buf.slice(..));
|
||||||
|
rpass.set_index_buffer(mesh.indices.buf.slice(..),mesh.indices.format);
|
||||||
|
//TODO: loop over triangle strips
|
||||||
|
rpass.draw_indexed(0..mesh.indices.count,0,0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.submit(std::iter::once(encoder.finish()));
|
queue.submit(std::iter::once(encoder.finish()));
|
||||||
@@ -987,3 +1132,24 @@ impl GraphicsState{
|
|||||||
self.staging_belt.recall();
|
self.staging_belt.recall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const MODEL_BUFFER_SIZE:usize=4*4 + 12 + 4;//let size=std::mem::size_of::<ModelInstance>();
|
||||||
|
const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*core::mem::size_of::<f32>();
|
||||||
|
fn get_instance_buffer_data(instance:&GraphicsModelOwned)->[f32;MODEL_BUFFER_SIZE]{
|
||||||
|
let mut out=[0.0;MODEL_BUFFER_SIZE];
|
||||||
|
out[0..16].copy_from_slice(instance.transform.as_ref());
|
||||||
|
out[16..19].copy_from_slice(instance.normal_transform.x_axis.as_ref());
|
||||||
|
// out[20]=0.0;
|
||||||
|
out[20..23].copy_from_slice(instance.normal_transform.y_axis.as_ref());
|
||||||
|
// out[24]=0.0;
|
||||||
|
out[24..27].copy_from_slice(instance.normal_transform.z_axis.as_ref());
|
||||||
|
// out[28]=0.0;
|
||||||
|
out[28..32].copy_from_slice(instance.color.get().as_ref());
|
||||||
|
out
|
||||||
|
}
|
||||||
|
fn get_instances_buffer_data(instances:&[GraphicsModelOwned])->Vec<f32>{
|
||||||
|
let mut raw=Vec::with_capacity(MODEL_BUFFER_SIZE*instances.len());
|
||||||
|
for mi in instances{
|
||||||
|
raw.extend_from_slice(&get_instance_buffer_data(mi));
|
||||||
|
}
|
||||||
|
raw
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ pub struct GraphicsVertex{
|
|||||||
pub normal:[f32;3],
|
pub normal:[f32;3],
|
||||||
pub color:[f32;4],
|
pub color:[f32;4],
|
||||||
}
|
}
|
||||||
|
#[derive(Clone,Copy,Pod,Zeroable)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DebugGraphicsVertex{
|
||||||
|
pub pos:[f32;3],
|
||||||
|
pub normal:[f32;3],
|
||||||
|
}
|
||||||
#[derive(Clone,Copy,id::Id)]
|
#[derive(Clone,Copy,id::Id)]
|
||||||
pub struct IndexedGraphicsMeshOwnedRenderConfigId(u32);
|
pub struct IndexedGraphicsMeshOwnedRenderConfigId(u32);
|
||||||
pub struct IndexedGraphicsMeshOwnedRenderConfig{
|
pub struct IndexedGraphicsMeshOwnedRenderConfig{
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ impl<T> Body<T>
|
|||||||
pub fn extrapolated_position(&self,time:Time<T>)->Planar64Vec3{
|
pub fn extrapolated_position(&self,time:Time<T>)->Planar64Vec3{
|
||||||
let dt=time-self.time;
|
let dt=time-self.time;
|
||||||
self.position
|
self.position
|
||||||
+(self.velocity*dt).map(|elem|elem.divide().clamp_1())
|
+(self.velocity*dt).map(|elem|elem.divide().fix_1())
|
||||||
+self.acceleration.map(|elem|(dt*dt*elem/2).divide().clamp_1())
|
+self.acceleration.map(|elem|(dt*dt*elem/2).divide().fix_1())
|
||||||
}
|
}
|
||||||
pub fn extrapolated_velocity(&self,time:Time<T>)->Planar64Vec3{
|
pub fn extrapolated_velocity(&self,time:Time<T>)->Planar64Vec3{
|
||||||
let dt=time-self.time;
|
let dt=time-self.time;
|
||||||
self.velocity+(self.acceleration*dt).map(|elem|elem.divide().clamp_1())
|
self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1())
|
||||||
}
|
}
|
||||||
pub fn advance_time(&mut self,time:Time<T>){
|
pub fn advance_time(&mut self,time:Time<T>){
|
||||||
self.position=self.extrapolated_position(time);
|
self.position=self.extrapolated_position(time);
|
||||||
@@ -71,12 +71,12 @@ impl<T> Body<T>
|
|||||||
D2:Copy,
|
D2:Copy,
|
||||||
Planar64:core::ops::Mul<D2,Output=N4>,
|
Planar64:core::ops::Mul<D2,Output=N4>,
|
||||||
N4:integer::Divide<D2,Output=T1>,
|
N4:integer::Divide<D2,Output=T1>,
|
||||||
T1:integer::Clamp<Planar64>,
|
T1:integer::Fix<Planar64>,
|
||||||
{
|
{
|
||||||
// a*dt^2/2 + v*dt + p
|
// a*dt^2/2 + v*dt + p
|
||||||
// (a*dt/2+v)*dt+p
|
// (a*dt/2+v)*dt+p
|
||||||
(self.acceleration.map(|elem|dt*elem/2)+self.velocity).map(|elem|dt.mul_ratio(elem))
|
(self.acceleration.map(|elem|dt*elem/2)+self.velocity).map(|elem|dt.mul_ratio(elem))
|
||||||
.map(|elem|elem.divide().clamp())+self.position
|
.map(|elem|elem.divide().fix())+self.position
|
||||||
}
|
}
|
||||||
pub fn extrapolated_velocity_ratio_dt<Num,Den,N1,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3
|
pub fn extrapolated_velocity_ratio_dt<Num,Den,N1,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3
|
||||||
where
|
where
|
||||||
@@ -85,10 +85,10 @@ impl<T> Body<T>
|
|||||||
Num:core::ops::Mul<Planar64,Output=N1>,
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
Planar64:core::ops::Mul<Den,Output=N1>,
|
Planar64:core::ops::Mul<Den,Output=N1>,
|
||||||
N1:integer::Divide<Den,Output=T1>,
|
N1:integer::Divide<Den,Output=T1>,
|
||||||
T1:integer::Clamp<Planar64>,
|
T1:integer::Fix<Planar64>,
|
||||||
{
|
{
|
||||||
// a*dt + v
|
// a*dt + v
|
||||||
self.acceleration.map(|elem|(dt*elem).divide().clamp())+self.velocity
|
self.acceleration.map(|elem|(dt*elem).divide().fix())+self.velocity
|
||||||
}
|
}
|
||||||
pub fn advance_time_ratio_dt(&mut self,dt:crate::model::GigaTime){
|
pub fn advance_time_ratio_dt(&mut self,dt:crate::model::GigaTime){
|
||||||
self.position=self.extrapolated_position_ratio_dt(dt);
|
self.position=self.extrapolated_position_ratio_dt(dt);
|
||||||
|
|||||||
@@ -57,14 +57,13 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//test each edge collision time, ignoring roots with zero or conflicting derivative
|
//test each edge collision time, ignoring roots with zero or conflicting derivative
|
||||||
for &directed_edge_id in mesh.face_edges(face_id).as_ref(){
|
for &directed_edge_id in mesh.face_edges(face_id).iter(){
|
||||||
let edge_n=mesh.directed_edge_n(directed_edge_id);
|
let edge_n=mesh.directed_edge_n(directed_edge_id);
|
||||||
let n=n.cross(edge_n);
|
let n=n.cross(edge_n);
|
||||||
let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref();
|
let verts=mesh.edge_verts(directed_edge_id.as_undirected());
|
||||||
//WARNING: d is moved out of the *2 block because of adding two vertices!
|
//WARNING: d is moved out of the *2 block because of adding two vertices!
|
||||||
//WARNING: precision is swept under the rug!
|
//WARNING: precision is swept under the rug!
|
||||||
//wrap for speed
|
for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(verts[0])+mesh.vert(verts[1]))).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){
|
||||||
for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){
|
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
||||||
@@ -78,15 +77,13 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
//test each face collision time, ignoring roots with zero or conflicting derivative
|
//test each face collision time, ignoring roots with zero or conflicting derivative
|
||||||
let edge_n=mesh.edge_n(edge_id);
|
let edge_n=mesh.edge_n(edge_id);
|
||||||
let edge_verts=mesh.edge_verts(edge_id);
|
let edge_verts=mesh.edge_verts(edge_id);
|
||||||
let &[ev0,ev1]=edge_verts.as_ref();
|
let delta_pos=body.position*2-(mesh.vert(edge_verts[0])+mesh.vert(edge_verts[1]));
|
||||||
let delta_pos=body.position*2-(mesh.vert(ev0)+mesh.vert(ev1));
|
for (i,&edge_face_id) in mesh.edge_faces(edge_id).iter().enumerate(){
|
||||||
for (i,&edge_face_id) in mesh.edge_faces(edge_id).as_ref().iter().enumerate(){
|
|
||||||
let face_n=mesh.face_nd(edge_face_id).0;
|
let face_n=mesh.face_nd(edge_face_id).0;
|
||||||
//edge_n gets parity from the order of edge_faces
|
//edge_n gets parity from the order of edge_faces
|
||||||
let n=face_n.cross(edge_n)*((i as i64)*2-1);
|
let n=face_n.cross(edge_n)*((i as i64)*2-1);
|
||||||
//WARNING yada yada d *2
|
//WARNING yada yada d *2
|
||||||
//wrap for speed
|
for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){
|
||||||
for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){
|
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Face(edge_face_id),dt);
|
best_transition=Transition::Next(FEV::Face(edge_face_id),dt);
|
||||||
@@ -95,12 +92,12 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//test each vertex collision time, ignoring roots with zero or conflicting derivative
|
//test each vertex collision time, ignoring roots with zero or conflicting derivative
|
||||||
for (i,&vert_id) in edge_verts.as_ref().iter().enumerate(){
|
for (i,&vert_id) in edge_verts.iter().enumerate(){
|
||||||
//vertex normal gets parity from vert index
|
//vertex normal gets parity from vert index
|
||||||
let n=edge_n*(1-2*(i as i64));
|
let n=edge_n*(1-2*(i as i64));
|
||||||
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4());
|
let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4());
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Vert(vert_id),dt);
|
best_transition=Transition::Next(FEV::Vert(vert_id),dt);
|
||||||
break;
|
break;
|
||||||
@@ -111,12 +108,12 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
},
|
},
|
||||||
&FEV::Vert(vert_id)=>{
|
&FEV::Vert(vert_id)=>{
|
||||||
//test each edge collision time, ignoring roots with zero or conflicting derivative
|
//test each edge collision time, ignoring roots with zero or conflicting derivative
|
||||||
for &directed_edge_id in mesh.vert_edges(vert_id).as_ref(){
|
for &directed_edge_id in mesh.vert_edges(vert_id).iter(){
|
||||||
//edge is directed away from vertex, but we want the dot product to turn out negative
|
//edge is directed away from vertex, but we want the dot product to turn out negative
|
||||||
let n=-mesh.directed_edge_n(directed_edge_id);
|
let n=-mesh.directed_edge_n(directed_edge_id);
|
||||||
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4());
|
let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4());
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
||||||
break;
|
break;
|
||||||
@@ -131,11 +128,11 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
pub fn crawl(mut self,mesh:&M,relative_body:&Body,start_time:Time,time_limit:Time)->CrawlResult<M>{
|
pub fn crawl(mut self,mesh:&M,relative_body:&Body,start_time:Time,time_limit:Time)->CrawlResult<M>{
|
||||||
let mut body_time={
|
let mut body_time={
|
||||||
let r=(start_time-relative_body.time).to_ratio();
|
let r=(start_time-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.widen_4(),r.den.widen_4())
|
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
||||||
};
|
};
|
||||||
let time_limit={
|
let time_limit={
|
||||||
let r=(time_limit-relative_body.time).to_ratio();
|
let r=(time_limit-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.widen_4(),r.den.widen_4())
|
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
||||||
};
|
};
|
||||||
for _ in 0..20{
|
for _ in 0..20{
|
||||||
match self.next_transition(body_time,mesh,relative_body,time_limit){
|
match self.next_transition(body_time,mesh,relative_body,time_limit){
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
use std::collections::{HashMap,HashSet};
|
use std::collections::{HashMap,HashSet};
|
||||||
|
use crate::model::DirectedEdge;
|
||||||
use crate::model::{self as model_physics,PhysicsMesh,PhysicsMeshTransform,TransformedMesh,MeshQuery,PhysicsMeshId,PhysicsSubmeshId};
|
use crate::model::{self as model_physics,PhysicsMesh,PhysicsMeshTransform,TransformedMesh,MeshQuery,PhysicsMeshId,PhysicsSubmeshId};
|
||||||
use strafesnet_common::bvh;
|
use strafesnet_common::bvh;
|
||||||
use strafesnet_common::map;
|
use strafesnet_common::map;
|
||||||
@@ -117,8 +118,8 @@ impl TransientAcceleration{
|
|||||||
}else{
|
}else{
|
||||||
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
||||||
TransientAcceleration::Reachable{
|
TransientAcceleration::Reachable{
|
||||||
acceleration:target_diff.with_length(accel).divide().wrap_1(),
|
acceleration:target_diff.with_length(accel).divide().fix_1(),
|
||||||
time:time+Time::from((target_diff.length()/accel).divide().clamp_1())
|
time:time+Time::from((target_diff.length()/accel).divide().fix_1())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,7 +281,8 @@ impl PhysicsCamera{
|
|||||||
.clamp(Self::ANGLE_PITCH_LOWER_LIMIT,Self::ANGLE_PITCH_UPPER_LIMIT);
|
.clamp(Self::ANGLE_PITCH_LOWER_LIMIT,Self::ANGLE_PITCH_UPPER_LIMIT);
|
||||||
mat3::from_rotation_yx(ax,ay)
|
mat3::from_rotation_yx(ax,ay)
|
||||||
}
|
}
|
||||||
fn rotation(&self)->Planar64Mat3{
|
#[inline]
|
||||||
|
pub fn rotation(&self)->Planar64Mat3{
|
||||||
self.get_rotation(self.clamped_mouse_pos)
|
self.get_rotation(self.clamped_mouse_pos)
|
||||||
}
|
}
|
||||||
fn simulate_move_rotation(&self,mouse_delta:glam::IVec2)->Planar64Mat3{
|
fn simulate_move_rotation(&self,mouse_delta:glam::IVec2)->Planar64Mat3{
|
||||||
@@ -407,7 +409,7 @@ impl HitboxMesh{
|
|||||||
let transform=PhysicsMeshTransform::new(transform);
|
let transform=PhysicsMeshTransform::new(transform);
|
||||||
let transformed_mesh=TransformedMesh::new(mesh.complete_mesh_view(),&transform);
|
let transformed_mesh=TransformedMesh::new(mesh.complete_mesh_view(),&transform);
|
||||||
for vert in transformed_mesh.verts(){
|
for vert in transformed_mesh.verts(){
|
||||||
aabb.grow(vert.narrow_1().unwrap());
|
aabb.grow(vert.fix_1());
|
||||||
}
|
}
|
||||||
Self{
|
Self{
|
||||||
halfsize:aabb.size()>>1,
|
halfsize:aabb.size()>>1,
|
||||||
@@ -460,12 +462,12 @@ impl StyleHelper for StyleModifiers{
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
||||||
(camera.rotation_y()*self.get_control_dir(controls)).wrap_1()
|
(camera.rotation_y()*self.get_control_dir(controls)).fix_1()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_propulsion_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
fn get_propulsion_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
||||||
//don't interpolate this! discrete mouse movement, constant acceleration
|
//don't interpolate this! discrete mouse movement, constant acceleration
|
||||||
(camera.rotation()*self.get_control_dir(controls)).wrap_1()
|
(camera.rotation()*self.get_control_dir(controls)).fix_1()
|
||||||
}
|
}
|
||||||
fn calculate_mesh(&self)->HitboxMesh{
|
fn calculate_mesh(&self)->HitboxMesh{
|
||||||
let mesh=match self.hitbox.mesh{
|
let mesh=match self.hitbox.mesh{
|
||||||
@@ -931,6 +933,7 @@ pub struct PhysicsData{
|
|||||||
modes:gameplay_modes::Modes,
|
modes:gameplay_modes::Modes,
|
||||||
//cached calculations
|
//cached calculations
|
||||||
hitbox_mesh:HitboxMesh,
|
hitbox_mesh:HitboxMesh,
|
||||||
|
pub le_models:Vec<strafesnet_common::model::Model>,
|
||||||
}
|
}
|
||||||
impl Default for PhysicsData{
|
impl Default for PhysicsData{
|
||||||
fn default()->Self{
|
fn default()->Self{
|
||||||
@@ -939,6 +942,7 @@ impl Default for PhysicsData{
|
|||||||
models:Default::default(),
|
models:Default::default(),
|
||||||
modes:Default::default(),
|
modes:Default::default(),
|
||||||
hitbox_mesh:StyleModifiers::default().calculate_mesh(),
|
hitbox_mesh:StyleModifiers::default().calculate_mesh(),
|
||||||
|
le_models:Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -980,9 +984,37 @@ impl PhysicsContext<'_>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl PhysicsData{
|
impl PhysicsData{
|
||||||
|
pub fn trace_ray(&self,ray:strafesnet_common::ray::Ray)->Option<ModelId>{
|
||||||
|
let (_time,convex_mesh_id)=self.bvh.sample_ray(&ray,Time::ZERO,Time::MAX/4,|&model,ray|{
|
||||||
|
let mesh=self.models.mesh(model);
|
||||||
|
// brute force trace every face
|
||||||
|
mesh.faces().filter_map(|face_id|{
|
||||||
|
let (n,d)=mesh.face_nd(face_id);
|
||||||
|
// trace ray onto face
|
||||||
|
// n.(o+d*t)==n.p
|
||||||
|
// n.o + n.d * t == n.p
|
||||||
|
// t == (n.p - n.o)/n.d
|
||||||
|
let nd=n.dot(ray.direction);
|
||||||
|
if nd.is_zero(){
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let t=(d-n.dot(ray.origin))/nd;
|
||||||
|
// check if point of intersection is behind face edges
|
||||||
|
// *2 because average of 2 vertices
|
||||||
|
let p=ray.extrapolate(t)*2;
|
||||||
|
mesh.face_edges(face_id).iter().all(|&directed_edge_id|{
|
||||||
|
let edge_n=mesh.directed_edge_n(directed_edge_id);
|
||||||
|
let cross_n=edge_n.cross(n);
|
||||||
|
let &[vert0,vert1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref();
|
||||||
|
cross_n.dot(p)<cross_n.dot(mesh.vert(vert0)+mesh.vert(vert1))
|
||||||
|
}).then(||t)
|
||||||
|
}).min().map(Into::into)
|
||||||
|
})?;
|
||||||
|
Some(convex_mesh_id.model_id.into())
|
||||||
|
}
|
||||||
/// use with caution, this is the only non-instruction way to mess with physics
|
/// use with caution, this is the only non-instruction way to mess with physics
|
||||||
pub fn generate_models(&mut self,map:&map::CompleteMap){
|
pub fn generate_models(&mut self,map:&map::CompleteMap){
|
||||||
let modes=map.modes.clone().denormalize();
|
let mut modes=map.modes.clone().denormalize();
|
||||||
let mut used_contact_attributes=Vec::new();
|
let mut used_contact_attributes=Vec::new();
|
||||||
let mut used_intersect_attributes=Vec::new();
|
let mut used_intersect_attributes=Vec::new();
|
||||||
|
|
||||||
@@ -1084,7 +1116,7 @@ impl PhysicsData{
|
|||||||
let mut aabb=aabb::Aabb::default();
|
let mut aabb=aabb::Aabb::default();
|
||||||
let transformed_mesh=TransformedMesh::new(view,transform);
|
let transformed_mesh=TransformedMesh::new(view,transform);
|
||||||
for v in transformed_mesh.verts(){
|
for v in transformed_mesh.verts(){
|
||||||
aabb.grow(v.narrow_1().unwrap());
|
aabb.grow(v.fix_1());
|
||||||
}
|
}
|
||||||
(ConvexMeshId{
|
(ConvexMeshId{
|
||||||
model_id,
|
model_id,
|
||||||
@@ -1112,6 +1144,7 @@ impl PhysicsData{
|
|||||||
self.bvh=bvh;
|
self.bvh=bvh;
|
||||||
self.models=models;
|
self.models=models;
|
||||||
self.modes=modes;
|
self.modes=modes;
|
||||||
|
self.le_models=map.models.clone();
|
||||||
//hitbox_mesh is unchanged
|
//hitbox_mesh is unchanged
|
||||||
println!("Physics Objects: {}",model_count);
|
println!("Physics Objects: {}",model_count);
|
||||||
}
|
}
|
||||||
@@ -1162,8 +1195,7 @@ fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&Contact
|
|||||||
let model_mesh=models.contact_mesh(contact);
|
let model_mesh=models.contact_mesh(contact);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||||
// TODO: normalize to i64::MAX>>1
|
// TODO: normalize to i64::MAX>>1
|
||||||
// wrap for speed
|
minkowski.face_nd(contact.face_id).0.fix_1()
|
||||||
minkowski.face_nd(contact.face_id).0.wrap_1()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recalculate_touching(
|
fn recalculate_touching(
|
||||||
@@ -1322,7 +1354,7 @@ fn teleport_to_spawn(
|
|||||||
const EPSILON:Planar64=Planar64::raw((1<<32)/16);
|
const EPSILON:Planar64=Planar64::raw((1<<32)/16);
|
||||||
let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?;
|
let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?;
|
||||||
//TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation
|
//TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation
|
||||||
let point=transform.vertex.transform_point3(vec3::Y).clamp_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]);
|
let point=transform.vertex.transform_point3(vec3::Y).fix_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]);
|
||||||
teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time);
|
teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1486,7 +1518,7 @@ fn collision_start_contact(
|
|||||||
Some(gameplay_attributes::ContactingBehaviour::Surf)=>(),
|
Some(gameplay_attributes::ContactingBehaviour::Surf)=>(),
|
||||||
Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
||||||
&Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{
|
&Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{
|
||||||
let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).wrap_1();
|
let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).fix_1();
|
||||||
set_velocity(body,touching,models,hitbox_mesh,reflected_velocity);
|
set_velocity(body,touching,models,hitbox_mesh,reflected_velocity);
|
||||||
},
|
},
|
||||||
Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=>
|
Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=>
|
||||||
@@ -1709,7 +1741,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
|
|||||||
let control_dir=state.style.get_control_dir(masked_controls);
|
let control_dir=state.style.get_control_dir(masked_controls);
|
||||||
if control_dir!=vec3::ZERO{
|
if control_dir!=vec3::ZERO{
|
||||||
let camera_mat=state.camera.simulate_move_rotation_y(state.input_state.lerp_delta(state.time).x);
|
let camera_mat=state.camera.simulate_move_rotation_y(state.input_state.lerp_delta(state.time).x);
|
||||||
if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().wrap_1()){
|
if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().fix_1()){
|
||||||
//this is wrong but will work ig
|
//this is wrong but will work ig
|
||||||
//need to note which push planes activate in push solve and keep those
|
//need to note which push planes activate in push solve and keep those
|
||||||
state.cull_velocity(data,ticked_velocity);
|
state.cull_velocity(data,ticked_velocity);
|
||||||
|
|||||||
@@ -152,19 +152,18 @@ const fn get_push_ray_0(point:Planar64Vec3)->Ray{
|
|||||||
Ray{origin:point,direction:vec3::ZERO}
|
Ray{origin:point,direction:vec3::ZERO}
|
||||||
}
|
}
|
||||||
fn get_push_ray_1(point:Planar64Vec3,c0:&Contact)->Option<Ray>{
|
fn get_push_ray_1(point:Planar64Vec3,c0:&Contact)->Option<Ray>{
|
||||||
//wrap for speed
|
let direction=solve1(c0)?.divide().fix_1();
|
||||||
let direction=solve1(c0)?.divide().wrap_1();
|
|
||||||
let [s0]=decompose1(direction,c0.velocity)?;
|
let [s0]=decompose1(direction,c0.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let origin=point+solve1(
|
let origin=point+solve1(
|
||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
)?.divide().wrap_1();
|
)?.divide().fix_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
||||||
let direction=solve2(c0,c1)?.divide().wrap_1();
|
let direction=solve2(c0,c1)?.divide().fix_1();
|
||||||
let [s0,s1]=decompose2(direction,c0.velocity,c1.velocity)?;
|
let [s0,s1]=decompose2(direction,c0.velocity,c1.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
@@ -172,11 +171,11 @@ fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
|||||||
let origin=point+solve2(
|
let origin=point+solve2(
|
||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
&c1.relative_to(point),
|
&c1.relative_to(point),
|
||||||
)?.divide().wrap_1();
|
)?.divide().fix_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Option<Ray>{
|
fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Option<Ray>{
|
||||||
let direction=solve3(c0,c1,c2)?.divide().wrap_1();
|
let direction=solve3(c0,c1,c2)?.divide().fix_1();
|
||||||
let [s0,s1,s2]=decompose3(direction,c0.velocity,c1.velocity,c2.velocity)?;
|
let [s0,s1,s2]=decompose3(direction,c0.velocity,c1.velocity,c2.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO)||s2.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO)||s2.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
@@ -185,7 +184,7 @@ fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Optio
|
|||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
&c1.relative_to(point),
|
&c1.relative_to(point),
|
||||||
&c2.relative_to(point),
|
&c2.relative_to(point),
|
||||||
)?.divide().wrap_1();
|
)?.divide().fix_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use strafesnet_common::gameplay_modes::{ModeId,StageId};
|
use strafesnet_common::gameplay_modes::{ModeId,StageId};
|
||||||
use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,InstructionFeedback,TimedInstruction};
|
use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,InstructionFeedback,TimedInstruction};
|
||||||
|
use strafesnet_common::model::ModelId;
|
||||||
// session represents the non-hardware state of the client.
|
// session represents the non-hardware state of the client.
|
||||||
// Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state.
|
// Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state.
|
||||||
use strafesnet_common::physics::{
|
use strafesnet_common::physics::{
|
||||||
@@ -61,6 +62,7 @@ pub struct FrameState{
|
|||||||
pub body:physics::Body,
|
pub body:physics::Body,
|
||||||
pub camera:physics::PhysicsCamera,
|
pub camera:physics::PhysicsCamera,
|
||||||
pub time:PhysicsTime,
|
pub time:PhysicsTime,
|
||||||
|
pub debug_model:Option<strafesnet_common::model::ModelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Simulation{
|
pub struct Simulation{
|
||||||
@@ -77,11 +79,12 @@ impl Simulation{
|
|||||||
physics,
|
physics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_frame_state(&self,time:SessionTime)->FrameState{
|
pub fn get_frame_state(&self,time:SessionTime,debug_model:Option<ModelId>)->FrameState{
|
||||||
FrameState{
|
FrameState{
|
||||||
body:self.physics.camera_body(),
|
body:self.physics.camera_body(),
|
||||||
camera:self.physics.camera(),
|
camera:self.physics.camera(),
|
||||||
time:self.timer.time(time),
|
time:self.timer.time(time),
|
||||||
|
debug_model,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,6 +164,7 @@ pub struct Session{
|
|||||||
recording:Recording,
|
recording:Recording,
|
||||||
//players:HashMap<PlayerId,Simulation>,
|
//players:HashMap<PlayerId,Simulation>,
|
||||||
replays:HashMap<BotId,Replay>,
|
replays:HashMap<BotId,Replay>,
|
||||||
|
last_ray_hit:Option<strafesnet_common::model::ModelId>,
|
||||||
}
|
}
|
||||||
impl Session{
|
impl Session{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -177,6 +181,7 @@ impl Session{
|
|||||||
view_state:ViewState::Play,
|
view_state:ViewState::Play,
|
||||||
recording:Default::default(),
|
recording:Default::default(),
|
||||||
replays:HashMap::new(),
|
replays:HashMap::new(),
|
||||||
|
last_ray_hit:None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn clear_recording(&mut self){
|
fn clear_recording(&mut self){
|
||||||
@@ -188,12 +193,30 @@ impl Session{
|
|||||||
}
|
}
|
||||||
pub fn get_frame_state(&self,time:SessionTime)->Option<FrameState>{
|
pub fn get_frame_state(&self,time:SessionTime)->Option<FrameState>{
|
||||||
match &self.view_state{
|
match &self.view_state{
|
||||||
ViewState::Play=>Some(self.simulation.get_frame_state(time)),
|
ViewState::Play=>Some(self.simulation.get_frame_state(time,self.last_ray_hit)),
|
||||||
ViewState::Replay(bot_id)=>self.replays.get(bot_id).map(|replay|
|
ViewState::Replay(bot_id)=>self.replays.get(bot_id).map(|replay|
|
||||||
replay.simulation.get_frame_state(time)
|
replay.simulation.get_frame_state(time,None)
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn debug_raycast_print_model_id_if_changed(&mut self,time:SessionTime){
|
||||||
|
if let Some(frame_state)=self.get_frame_state(time){
|
||||||
|
let ray=strafesnet_common::ray::Ray{
|
||||||
|
origin:frame_state.body.extrapolated_position(self.simulation.timer.time(time)),
|
||||||
|
direction:-frame_state.camera.rotation().z_axis,
|
||||||
|
};
|
||||||
|
let model_id=self.geometry_shared.trace_ray(ray);
|
||||||
|
if model_id!=self.last_ray_hit{
|
||||||
|
println!("hit={model_id:?}");
|
||||||
|
self.last_ray_hit=model_id;
|
||||||
|
if let Some(model_id)=model_id{
|
||||||
|
if let Some(model)=self.geometry_shared.le_models.get(model_id.get() as usize){
|
||||||
|
println!("{}",model.debug_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn user_settings(&self)->&UserSettings{
|
pub fn user_settings(&self)->&UserSettings{
|
||||||
&self.user_settings
|
&self.user_settings
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -5,12 +6,7 @@ use std::time::Instant;
|
|||||||
use strafesnet_physics::physics::{PhysicsData,PhysicsState,PhysicsContext};
|
use strafesnet_physics::physics::{PhysicsData,PhysicsState,PhysicsContext};
|
||||||
|
|
||||||
fn main(){
|
fn main(){
|
||||||
let arg=std::env::args().skip(1).next();
|
test_determinism().unwrap();
|
||||||
match arg.as_deref(){
|
|
||||||
Some("determinism")|None=>test_determinism().unwrap(),
|
|
||||||
Some("replay")=>run_replay().unwrap(),
|
|
||||||
_=>println!("invalid argument"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ pub enum PlanesToFacesError{
|
|||||||
InitFace2,
|
InitFace2,
|
||||||
InitIntersection,
|
InitIntersection,
|
||||||
FindNewIntersection,
|
FindNewIntersection,
|
||||||
// Narrow(strafesnet_common::integer::NarrowError),
|
|
||||||
EmptyFaces,
|
EmptyFaces,
|
||||||
InfiniteLoop1,
|
InfiniteLoop1,
|
||||||
InfiniteLoop2,
|
InfiniteLoop2,
|
||||||
@@ -82,12 +81,12 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,Plan
|
|||||||
// test if any *other* faces occlude the intersection
|
// test if any *other* faces occlude the intersection
|
||||||
for new_face in &face_list{
|
for new_face in &face_list{
|
||||||
// new face occludes intersection point
|
// new face occludes intersection point
|
||||||
if (new_face.dot.widen_2()/Planar64::ONE).lt_ratio(new_face.normal.dot(intersection.num)/intersection.den){
|
if (new_face.dot.fix_2()/Planar64::ONE).lt_ratio(new_face.normal.dot(intersection.num)/intersection.den){
|
||||||
// replace one of the faces with the new face
|
// replace one of the faces with the new face
|
||||||
// dont' try to replace face0 because we are exploring that face in particular
|
// dont' try to replace face0 because we are exploring that face in particular
|
||||||
if let Some(new_intersection)=solve3(face0,new_face,face2){
|
if let Some(new_intersection)=solve3(face0,new_face,face2){
|
||||||
// face1 does not occlude (or intersect) the new intersection
|
// face1 does not occlude (or intersect) the new intersection
|
||||||
if (face1.dot.widen_2()/Planar64::ONE).gt_ratio(face1.normal.dot(new_intersection.num)/new_intersection.den){
|
if (face1.dot.fix_2()/Planar64::ONE).gt_ratio(face1.normal.dot(new_intersection.num)/new_intersection.den){
|
||||||
face1=new_face;
|
face1=new_face;
|
||||||
intersection=new_intersection;
|
intersection=new_intersection;
|
||||||
continue 'find;
|
continue 'find;
|
||||||
@@ -95,7 +94,7 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,Plan
|
|||||||
}
|
}
|
||||||
if let Some(new_intersection)=solve3(face0,face1,new_face){
|
if let Some(new_intersection)=solve3(face0,face1,new_face){
|
||||||
// face2 does not occlude (or intersect) the new intersection
|
// face2 does not occlude (or intersect) the new intersection
|
||||||
if (face2.dot.widen_2()/Planar64::ONE).gt_ratio(face2.normal.dot(new_intersection.num)/new_intersection.den){
|
if (face2.dot.fix_2()/Planar64::ONE).gt_ratio(face2.normal.dot(new_intersection.num)/new_intersection.den){
|
||||||
face2=new_face;
|
face2=new_face;
|
||||||
intersection=new_intersection;
|
intersection=new_intersection;
|
||||||
continue 'find;
|
continue 'find;
|
||||||
@@ -120,7 +119,7 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,Plan
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// new_face occludes intersection meaning intersection is not on convex solid and face0 is degenrate
|
// new_face occludes intersection meaning intersection is not on convex solid and face0 is degenrate
|
||||||
if (new_face.dot.widen_2()/Planar64::ONE).lt_ratio(new_face.normal.dot(intersection.num)/intersection.den){
|
if (new_face.dot.fix_2()/Planar64::ONE).lt_ratio(new_face.normal.dot(intersection.num)/intersection.den){
|
||||||
// abort! reject face0 entirely
|
// abort! reject face0 entirely
|
||||||
continue 'face;
|
continue 'face;
|
||||||
}
|
}
|
||||||
@@ -138,7 +137,7 @@ fn planes_to_faces(face_list:std::collections::HashSet<Face>)->Result<Faces,Plan
|
|||||||
loop{
|
loop{
|
||||||
// push point onto vertices
|
// push point onto vertices
|
||||||
// problem: this may push a vertex that does not fit in the fixed point range and is thus meaningless
|
// problem: this may push a vertex that does not fit in the fixed point range and is thus meaningless
|
||||||
face.push(intersection.divide().narrow_1().unwrap());
|
face.push(intersection.divide().fix_1());
|
||||||
|
|
||||||
// we looped back around to face1, we're done!
|
// we looped back around to face1, we're done!
|
||||||
if core::ptr::eq(face1,face2){
|
if core::ptr::eq(face1,face2){
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ fn add_brush<'a>(
|
|||||||
origin:vbsp::Vector,
|
origin:vbsp::Vector,
|
||||||
rendercolor:vbsp::Color,
|
rendercolor:vbsp::Color,
|
||||||
attributes:attr::CollisionAttributesId,
|
attributes:attr::CollisionAttributesId,
|
||||||
|
debug_info:model::DebugInfo,
|
||||||
){
|
){
|
||||||
let transform=integer::Planar64Affine3::from_translation(
|
let transform=integer::Planar64Affine3::from_translation(
|
||||||
valve_transform(origin.into())
|
valve_transform(origin.into())
|
||||||
@@ -53,13 +54,13 @@ fn add_brush<'a>(
|
|||||||
rendercolor.b as f32
|
rendercolor.b as f32
|
||||||
])/255.0).extend(1.0);
|
])/255.0).extend(1.0);
|
||||||
|
|
||||||
match model.chars().next(){
|
match model.split_at(1){
|
||||||
// The first character of brush.model is '*'
|
// The first character of brush.model is '*'
|
||||||
Some('*')=>match model[1..].parse(){
|
("*",id_str)=>match id_str.parse(){
|
||||||
Ok(mesh_id)=>{
|
Ok(mesh_id)=>{
|
||||||
let mesh=model::MeshId::new(mesh_id);
|
let mesh=model::MeshId::new(mesh_id);
|
||||||
world_models.push(
|
world_models.push(
|
||||||
model::Model{mesh,attributes,transform,color}
|
model::Model{mesh,attributes,transform,color,debug_info}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Err(e)=>{
|
Err(e)=>{
|
||||||
@@ -70,7 +71,7 @@ fn add_brush<'a>(
|
|||||||
_=>{
|
_=>{
|
||||||
let mesh=mesh_deferred_loader.acquire_mesh_id(model);
|
let mesh=mesh_deferred_loader.acquire_mesh_id(model);
|
||||||
prop_models.push(
|
prop_models.push(
|
||||||
model::Model{mesh,attributes,transform,color}
|
model::Model{mesh,attributes,transform,color,debug_info}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,6 +140,7 @@ pub fn convert<'a>(
|
|||||||
valve_transform(prop.origin.into()),
|
valve_transform(prop.origin.into()),
|
||||||
),
|
),
|
||||||
color:glam::Vec4::ONE,
|
color:glam::Vec4::ONE,
|
||||||
|
debug_info:model::DebugInfo::Prop,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
@@ -207,54 +209,214 @@ pub fn convert<'a>(
|
|||||||
attributes:ATTRIBUTE_DECORATION,
|
attributes:ATTRIBUTE_DECORATION,
|
||||||
transform:integer::Planar64Affine3::IDENTITY,
|
transform:integer::Planar64Affine3::IDENTITY,
|
||||||
color:glam::Vec4::W,
|
color:glam::Vec4::W,
|
||||||
|
debug_info:model::DebugInfo::World,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// THE CUBE OF DESTINY
|
||||||
|
let destination_mesh_id=model::MeshId::new(world_meshes.len() as u32);
|
||||||
|
world_meshes.push(crate::brush::unit_cube());
|
||||||
|
|
||||||
const WHITE:vbsp::Color=vbsp::Color{r:255,g:255,b:255};
|
const WHITE:vbsp::Color=vbsp::Color{r:255,g:255,b:255};
|
||||||
|
const ENTITY_ATTRIBUTE:gameplay_attributes::CollisionAttributesId=ATTRIBUTE_DECORATION;
|
||||||
|
const ENTITY_TRIGGER_ATTRIBUTE:gameplay_attributes::CollisionAttributesId=ATTRIBUTE_INTERSECT_DEFAULT;
|
||||||
for raw_ent in &bsp.entities{
|
for raw_ent in &bsp.entities{
|
||||||
|
let debug_info=match model::EntityInfo::new(raw_ent.properties()){
|
||||||
|
Ok(entity_info)=>model::DebugInfo::Entity(entity_info),
|
||||||
|
Err(_)=>{
|
||||||
|
println!("EntityInfoError");
|
||||||
|
model::DebugInfo::World
|
||||||
|
},
|
||||||
|
};
|
||||||
|
macro_rules! ent_brush_default{
|
||||||
|
($entity:ident)=>{
|
||||||
|
add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,$entity.model,$entity.origin,$entity.rendercolor,ENTITY_ATTRIBUTE,debug_info)
|
||||||
|
};
|
||||||
|
} macro_rules! ent_brush_prop{
|
||||||
|
($entity:ident)=>{
|
||||||
|
add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,$entity.model,$entity.origin,WHITE,ENTITY_ATTRIBUTE,debug_info)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
macro_rules! ent_brush_trigger{
|
||||||
|
($entity:ident)=>{
|
||||||
|
add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,$entity.model,$entity.origin,WHITE,ENTITY_TRIGGER_ATTRIBUTE,debug_info)
|
||||||
|
};
|
||||||
|
}
|
||||||
match raw_ent.parse(){
|
match raw_ent.parse(){
|
||||||
Ok(Entity::Cycler(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::AmbientGeneric(_ambient_generic))=>(),
|
||||||
Ok(Entity::EnvSprite(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::Cycler(brush))=>ent_brush_default!(brush),
|
||||||
Ok(Entity::FuncBreakable(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvBeam(_env_beam))=>(),
|
||||||
Ok(Entity::FuncBrush(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvBubbles(_env_bubbles))=>(),
|
||||||
Ok(Entity::FuncButton(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvDetailController(_env_detail_controller))=>(),
|
||||||
Ok(Entity::FuncDoor(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvEmbers(_env_embers))=>(),
|
||||||
Ok(Entity::FuncDoorRotating(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvEntityMaker(_env_entity_maker))=>(),
|
||||||
Ok(Entity::FuncIllusionary(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvExplosion(_env_explosion))=>(),
|
||||||
Ok(Entity::FuncMonitor(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvFade(_env_fade))=>(),
|
||||||
Ok(Entity::FuncMovelinear(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvFire(_env_fire))=>(),
|
||||||
Ok(Entity::FuncPhysbox(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvFireTrail(_env_fire_trail))=>(),
|
||||||
Ok(Entity::FuncPhysboxMultiplayer(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvFiresource(_env_firesource))=>(),
|
||||||
Ok(Entity::FuncRotButton(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvFogController(_env_fog_controller))=>(),
|
||||||
Ok(Entity::FuncRotating(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvHudhint(_env_hudhint))=>(),
|
||||||
Ok(Entity::FuncTracktrain(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvLaser(_env_laser))=>(),
|
||||||
Ok(Entity::FuncTrain(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvLightglow(_env_lightglow))=>(),
|
||||||
Ok(Entity::FuncWall(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin.unwrap_or_default(),brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvPhysexplosion(_env_physexplosion))=>(),
|
||||||
Ok(Entity::FuncWallToggle(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin.unwrap_or_default(),brush.rendercolor,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvProjectedtexture(_env_projectedtexture))=>(),
|
||||||
Ok(Entity::FuncWaterAnalog(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor.unwrap_or(WHITE),ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvScreenoverlay(_env_screenoverlay))=>(),
|
||||||
Ok(Entity::PropDoorRotating(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvShake(_env_shake))=>(),
|
||||||
Ok(Entity::PropDynamic(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvShooter(_env_shooter))=>(),
|
||||||
Ok(Entity::PropDynamicOverride(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSmokestack(_env_smokestack))=>(),
|
||||||
Ok(Entity::PropPhysics(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSoundscape(_env_soundscape))=>(),
|
||||||
Ok(Entity::PropPhysicsMultiplayer(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSoundscapeProxy(_env_soundscape_proxy))=>(),
|
||||||
Ok(Entity::PropPhysicsOverride(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSoundscapeTriggerable(_env_soundscape_triggerable))=>(),
|
||||||
Ok(Entity::PropRagdoll(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSpark(_env_spark))=>(),
|
||||||
Ok(Entity::TriggerGravity(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSprite(brush))=>ent_brush_default!(brush),
|
||||||
Ok(Entity::TriggerHurt(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSpritetrail(_env_spritetrail))=>(),
|
||||||
Ok(Entity::TriggerLook(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSteam(_env_steam))=>(),
|
||||||
Ok(Entity::TriggerMultiple(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model.unwrap_or_default(),brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvSun(_env_sun))=>(),
|
||||||
Ok(Entity::TriggerOnce(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvTonemapController(_env_tonemap_controller))=>(),
|
||||||
Ok(Entity::TriggerProximity(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::EnvWind(_env_wind))=>(),
|
||||||
Ok(Entity::TriggerPush(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
// trigger_teleport.filtername probably has to do with one of these
|
||||||
Ok(Entity::TriggerSoundscape(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::FilterActivatorClass(_filter_activator_class))=>(),
|
||||||
Ok(Entity::TriggerTeleport(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model.unwrap_or_default(),brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::FilterActivatorName(_filter_activator_name))=>(),
|
||||||
Ok(Entity::TriggerVphysicsMotion(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::FilterDamageType(_filter_damage_type))=>(),
|
||||||
Ok(Entity::TriggerWind(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,WHITE,ATTRIBUTE_DECORATION),
|
Ok(Entity::FilterMulti(_filter_multi))=>(),
|
||||||
Ok(Entity::InfoPlayerCounterterrorist(spawn))=>{
|
Ok(Entity::FuncAreaportal(_func_areaportal))=>(),
|
||||||
found_spawn=Some(valve_transform(spawn.origin.into()));
|
Ok(Entity::FuncAreaportalwindow(_func_areaportalwindow))=>(),
|
||||||
},
|
Ok(Entity::FuncBombTarget(_func_bomb_target))=>(),
|
||||||
Ok(Entity::InfoPlayerTerrorist(spawn))=>{
|
Ok(Entity::FuncBreakable(brush))=>ent_brush_default!(brush),
|
||||||
found_spawn=Some(valve_transform(spawn.origin.into()));
|
Ok(Entity::FuncBreakableSurf(_func_breakable_surf))=>(),
|
||||||
},
|
Ok(Entity::FuncBrush(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncButton(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncBuyzone(_func_buyzone))=>(),
|
||||||
|
Ok(Entity::FuncClipVphysics(_func_clip_vphysics))=>(),
|
||||||
|
Ok(Entity::FuncConveyor(_func_conveyor))=>(),
|
||||||
|
// FuncDoor is Platform
|
||||||
|
Ok(Entity::FuncDoor(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncDoorRotating(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncDustcloud(_func_dustcloud))=>(),
|
||||||
|
Ok(Entity::FuncDustmotes(_func_dustmotes))=>(),
|
||||||
|
Ok(Entity::FuncFishPool(_func_fish_pool))=>(),
|
||||||
|
Ok(Entity::FuncFootstepControl(_func_footstep_control))=>(),
|
||||||
|
Ok(Entity::FuncHostageRescue(_func_hostage_rescue))=>(),
|
||||||
|
Ok(Entity::FuncIllusionary(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor,ATTRIBUTE_DECORATION,debug_info),
|
||||||
|
Ok(Entity::FuncLod(_func_lod))=>(),
|
||||||
|
Ok(Entity::FuncMonitor(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncMovelinear(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncOccluder(_func_occluder))=>(),
|
||||||
|
Ok(Entity::FuncPhysbox(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncPhysboxMultiplayer(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncPrecipitation(_func_precipitation))=>(),
|
||||||
|
Ok(Entity::FuncRotButton(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::FuncRotating(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncSmokevolume(_func_smokevolume))=>(),
|
||||||
|
Ok(Entity::FuncTracktrain(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncTrain(brush))=>ent_brush_default!(brush),
|
||||||
|
Ok(Entity::FuncWall(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin.unwrap_or_default(),brush.rendercolor,ENTITY_ATTRIBUTE,debug_info),
|
||||||
|
Ok(Entity::FuncWallToggle(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin.unwrap_or_default(),brush.rendercolor,ENTITY_ATTRIBUTE,debug_info),
|
||||||
|
Ok(Entity::FuncWaterAnalog(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model,brush.origin,brush.rendercolor.unwrap_or(WHITE),ENTITY_ATTRIBUTE,debug_info),
|
||||||
|
Ok(Entity::GamePlayerEquip(_game_player_equip))=>(),
|
||||||
|
Ok(Entity::GameText(_game_text))=>(),
|
||||||
|
Ok(Entity::GameUi(_game_ui))=>(),
|
||||||
|
Ok(Entity::GameWeaponManager(_game_weapon_manager))=>(),
|
||||||
|
Ok(Entity::HostageEntity(_hostage_entity))=>(),
|
||||||
|
Ok(Entity::InfoCameraLink(_info_camera_link))=>(),
|
||||||
|
Ok(Entity::InfoLadder(_info_ladder))=>(),
|
||||||
|
Ok(Entity::InfoLightingRelative(_info_lighting_relative))=>(),
|
||||||
|
Ok(Entity::InfoMapParameters(_info_map_parameters))=>(),
|
||||||
|
Ok(Entity::InfoNode(_info_node))=>(),
|
||||||
|
Ok(Entity::InfoNodeHint(_info_node_hint))=>(),
|
||||||
|
Ok(Entity::InfoParticleSystem(_info_particle_system))=>(),
|
||||||
|
Ok(Entity::InfoPlayerCounterterrorist(spawn))=>found_spawn=Some(spawn.origin),
|
||||||
|
Ok(Entity::InfoPlayerLogo(_info_player_logo))=>(),
|
||||||
|
Ok(Entity::InfoPlayerStart(_info_player_start))=>(),
|
||||||
|
Ok(Entity::InfoPlayerTerrorist(spawn))=>found_spawn=Some(spawn.origin),
|
||||||
|
Ok(Entity::InfoTarget(_info_target))=>(),
|
||||||
|
// InfoTeleportDestination is Spawn#
|
||||||
|
Ok(Entity::InfoTeleportDestination(_info_teleport_destination))=>(),
|
||||||
|
Ok(Entity::Infodecal(_infodecal))=>(),
|
||||||
|
Ok(Entity::KeyframeRope(_keyframe_rope))=>(),
|
||||||
|
Ok(Entity::Light(_light))=>(),
|
||||||
|
Ok(Entity::LightEnvironment(_light_environment))=>(),
|
||||||
|
Ok(Entity::LightSpot(_light_spot))=>(),
|
||||||
|
Ok(Entity::LogicAuto(_logic_auto))=>(),
|
||||||
|
Ok(Entity::LogicBranch(_logic_branch))=>(),
|
||||||
|
Ok(Entity::LogicCase(_logic_case))=>(),
|
||||||
|
Ok(Entity::LogicCompare(_logic_compare))=>(),
|
||||||
|
Ok(Entity::LogicMeasureMovement(_logic_measure_movement))=>(),
|
||||||
|
Ok(Entity::LogicRelay(_logic_relay))=>(),
|
||||||
|
Ok(Entity::LogicTimer(_logic_timer))=>(),
|
||||||
|
Ok(Entity::MathCounter(_math_counter))=>(),
|
||||||
|
Ok(Entity::MoveRope(_move_rope))=>(),
|
||||||
|
Ok(Entity::PathTrack(_path_track))=>(),
|
||||||
|
Ok(Entity::PhysBallsocket(_phys_ballsocket))=>(),
|
||||||
|
Ok(Entity::PhysConstraint(_phys_constraint))=>(),
|
||||||
|
Ok(Entity::PhysConstraintsystem(_phys_constraintsystem))=>(),
|
||||||
|
Ok(Entity::PhysHinge(_phys_hinge))=>(),
|
||||||
|
Ok(Entity::PhysKeepupright(_phys_keepupright))=>(),
|
||||||
|
Ok(Entity::PhysLengthconstraint(_phys_lengthconstraint))=>(),
|
||||||
|
Ok(Entity::PhysPulleyconstraint(_phys_pulleyconstraint))=>(),
|
||||||
|
Ok(Entity::PhysRagdollconstraint(_phys_ragdollconstraint))=>(),
|
||||||
|
Ok(Entity::PhysRagdollmagnet(_phys_ragdollmagnet))=>(),
|
||||||
|
Ok(Entity::PhysThruster(_phys_thruster))=>(),
|
||||||
|
Ok(Entity::PhysTorque(_phys_torque))=>(),
|
||||||
|
Ok(Entity::PlayerSpeedmod(_player_speedmod))=>(),
|
||||||
|
Ok(Entity::PlayerWeaponstrip(_player_weaponstrip))=>(),
|
||||||
|
Ok(Entity::PointCamera(_point_camera))=>(),
|
||||||
|
Ok(Entity::PointClientcommand(_point_clientcommand))=>(),
|
||||||
|
Ok(Entity::PointDevshotCamera(_point_devshot_camera))=>(),
|
||||||
|
Ok(Entity::PointServercommand(_point_servercommand))=>(),
|
||||||
|
Ok(Entity::PointSpotlight(_point_spotlight))=>(),
|
||||||
|
Ok(Entity::PointSurroundtest(_point_surroundtest))=>(),
|
||||||
|
Ok(Entity::PointTemplate(_point_template))=>(),
|
||||||
|
Ok(Entity::PointTesla(_point_tesla))=>(),
|
||||||
|
Ok(Entity::PointViewcontrol(_point_viewcontrol))=>(),
|
||||||
|
Ok(Entity::PropDoorRotating(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropDynamic(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropDynamicOverride(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropPhysics(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropPhysicsMultiplayer(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropPhysicsOverride(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::PropRagdoll(brush))=>ent_brush_prop!(brush),
|
||||||
|
Ok(Entity::ShadowControl(_shadow_control))=>(),
|
||||||
|
Ok(Entity::SkyCamera(_sky_camera))=>(),
|
||||||
|
Ok(Entity::TriggerGravity(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerHurt(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerLook(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerMultiple(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model.unwrap_or_default(),brush.origin,WHITE,ENTITY_TRIGGER_ATTRIBUTE,debug_info),
|
||||||
|
Ok(Entity::TriggerOnce(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerProximity(brush))=>ent_brush_trigger!(brush),
|
||||||
|
// TriggerPush is booster
|
||||||
|
Ok(Entity::TriggerPush(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerSoundscape(brush))=>ent_brush_trigger!(brush),
|
||||||
|
// TriggerTeleport is Trigger#
|
||||||
|
Ok(Entity::TriggerTeleport(brush))=>add_brush(mesh_deferred_loader,&mut world_models,&mut prop_models,brush.model.unwrap_or_default(),brush.origin,WHITE,ENTITY_TRIGGER_ATTRIBUTE,debug_info),
|
||||||
|
Ok(Entity::TriggerVphysicsMotion(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::TriggerWind(brush))=>ent_brush_trigger!(brush),
|
||||||
|
Ok(Entity::WaterLodControl(_water_lod_control))=>(),
|
||||||
|
Ok(Entity::WeaponAk47(_weapon_ak47))=>(),
|
||||||
|
Ok(Entity::WeaponAwp(_weapon_awp))=>(),
|
||||||
|
Ok(Entity::WeaponDeagle(_weapon_deagle))=>(),
|
||||||
|
Ok(Entity::WeaponElite(_weapon_elite))=>(),
|
||||||
|
Ok(Entity::WeaponFamas(_weapon_famas))=>(),
|
||||||
|
Ok(Entity::WeaponFiveseven(_weapon_fiveseven))=>(),
|
||||||
|
Ok(Entity::WeaponFlashbang(_weapon_flashbang))=>(),
|
||||||
|
Ok(Entity::WeaponG3sg1(_weapon_g3sg1))=>(),
|
||||||
|
Ok(Entity::WeaponGlock(_weapon_glock))=>(),
|
||||||
|
Ok(Entity::WeaponHegrenade(_weapon_hegrenade))=>(),
|
||||||
|
Ok(Entity::WeaponKnife(_weapon_knife))=>(),
|
||||||
|
Ok(Entity::WeaponM249(_weapon_m249))=>(),
|
||||||
|
Ok(Entity::WeaponM3(_weapon_m3))=>(),
|
||||||
|
Ok(Entity::WeaponM4a1(_weapon_m4a1))=>(),
|
||||||
|
Ok(Entity::WeaponMac10(_weapon_mac10))=>(),
|
||||||
|
Ok(Entity::WeaponP228(_weapon_p228))=>(),
|
||||||
|
Ok(Entity::WeaponP90(_weapon_p90))=>(),
|
||||||
|
Ok(Entity::WeaponScout(_weapon_scout))=>(),
|
||||||
|
Ok(Entity::WeaponSg550(_weapon_sg550))=>(),
|
||||||
|
Ok(Entity::WeaponSmokegrenade(_weapon_smokegrenade))=>(),
|
||||||
|
Ok(Entity::WeaponTmp(_weapon_tmp))=>(),
|
||||||
|
Ok(Entity::WeaponUmp45(_weapon_ump45))=>(),
|
||||||
|
Ok(Entity::WeaponUsp(_weapon_usp))=>(),
|
||||||
|
Ok(Entity::WeaponXm1014(_weapon_xm1014))=>(),
|
||||||
|
Ok(Entity::Worldspawn(_worldspawn))=>(),
|
||||||
Err(e)=>{
|
Err(e)=>{
|
||||||
println!("Bsp Entity parse error: {e}");
|
println!("Bsp Entity parse error: {e}");
|
||||||
},
|
},
|
||||||
@@ -290,6 +452,13 @@ pub fn convert<'a>(
|
|||||||
Ok(mesh)=>{
|
Ok(mesh)=>{
|
||||||
let mesh_id=model::MeshId::new(world_meshes.len() as u32);
|
let mesh_id=model::MeshId::new(world_meshes.len() as u32);
|
||||||
world_meshes.push(mesh);
|
world_meshes.push(mesh);
|
||||||
|
let sides={
|
||||||
|
let brush_start_idx=brush.brush_side as usize;
|
||||||
|
let sides_range=brush_start_idx..brush_start_idx+brush.num_brush_sides as usize;
|
||||||
|
bsp.brush_sides[sides_range].iter().filter_map(|side|bsp.texture_info(side.texture_info as usize)).map(|texture_info|{
|
||||||
|
texture_info.flags
|
||||||
|
}).collect()
|
||||||
|
};
|
||||||
world_models.push(model::Model{
|
world_models.push(model::Model{
|
||||||
mesh:mesh_id,
|
mesh:mesh_id,
|
||||||
attributes,
|
attributes,
|
||||||
@@ -298,6 +467,7 @@ pub fn convert<'a>(
|
|||||||
integer::vec3::ZERO,
|
integer::vec3::ZERO,
|
||||||
),
|
),
|
||||||
color:glam::Vec4::ONE,
|
color:glam::Vec4::ONE,
|
||||||
|
debug_info:model::DebugInfo::Brush(model::BrushInfo{flags:brush.flags,sides}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(e)=>println!("Brush mesh error: {e}"),
|
Err(e)=>println!("Brush mesh error: {e}"),
|
||||||
@@ -306,16 +476,14 @@ pub fn convert<'a>(
|
|||||||
|
|
||||||
let mut modes_list=Vec::new();
|
let mut modes_list=Vec::new();
|
||||||
if let Some(spawn_point)=found_spawn{
|
if let Some(spawn_point)=found_spawn{
|
||||||
// create a new mesh
|
|
||||||
let mesh_id=model::MeshId::new(world_meshes.len() as u32);
|
|
||||||
world_meshes.push(crate::brush::unit_cube());
|
|
||||||
// create a new model
|
// create a new model
|
||||||
let model_id=model::ModelId::new(world_models.len() as u32);
|
let model_id=model::ModelId::new(world_models.len() as u32);
|
||||||
world_models.push(model::Model{
|
world_models.push(model::Model{
|
||||||
mesh:mesh_id,
|
mesh:destination_mesh_id,
|
||||||
attributes:ATTRIBUTE_INTERSECT_DEFAULT,
|
attributes:ATTRIBUTE_INTERSECT_DEFAULT,
|
||||||
transform:integer::Planar64Affine3::from_translation(spawn_point),
|
transform:integer::Planar64Affine3::from_translation(valve_transform(spawn_point.into())),
|
||||||
color:glam::Vec4::W,
|
color:glam::Vec4::W,
|
||||||
|
debug_info:model::DebugInfo::World,
|
||||||
});
|
});
|
||||||
|
|
||||||
let first_stage=Stage::empty(model_id);
|
let first_stage=Stage::empty(model_id);
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec = "0.7.4"
|
arrayvec = "0.7.4"
|
||||||
bitflags = "2.6.0"
|
bitflags = "2.6.0"
|
||||||
fixed_wide = { version = "0.2.0", path = "../fixed_wide", registry = "strafesnet", features = ["deferred-division","zeroes","wide-mul"] }
|
fixed_wide = { version = "0.1.2", path = "../fixed_wide", registry = "strafesnet", features = ["deferred-division","zeroes","wide-mul"] }
|
||||||
linear_ops = { version = "0.1.1", path = "../linear_ops", registry = "strafesnet", features = ["deferred-division","named-fields"] }
|
linear_ops = { version = "0.1.0", path = "../linear_ops", registry = "strafesnet", features = ["deferred-division","named-fields"] }
|
||||||
ratio_ops = { version = "0.1.0", path = "../ratio_ops", registry = "strafesnet" }
|
ratio_ops = { version = "0.1.0", path = "../ratio_ops", registry = "strafesnet" }
|
||||||
glam = "0.30.0"
|
glam = "0.30.0"
|
||||||
id = { version = "0.1.0", registry = "strafesnet" }
|
id = { version = "0.1.0", registry = "strafesnet" }
|
||||||
|
vbsp = "0.8.0"
|
||||||
|
|||||||
@@ -66,18 +66,18 @@ impl JumpImpulse{
|
|||||||
_mass:Planar64,
|
_mass:Planar64,
|
||||||
)->Planar64Vec3{
|
)->Planar64Vec3{
|
||||||
match self{
|
match self{
|
||||||
&JumpImpulse::Time(time)=>velocity-(*gravity*time).map(|t|t.divide().clamp_1()),
|
&JumpImpulse::Time(time)=>velocity-(*gravity*time).map(|t|t.divide().fix_1()),
|
||||||
&JumpImpulse::Height(height)=>{
|
&JumpImpulse::Height(height)=>{
|
||||||
//height==-v.y*v.y/(2*g.y);
|
//height==-v.y*v.y/(2*g.y);
|
||||||
//use energy to determine max height
|
//use energy to determine max height
|
||||||
let gg=gravity.length_squared();
|
let gg=gravity.length_squared();
|
||||||
let g=gg.sqrt();
|
let g=gg.sqrt().fix_1();
|
||||||
let v_g=gravity.dot(velocity);
|
let v_g=gravity.dot(velocity);
|
||||||
//do it backwards
|
//do it backwards
|
||||||
let radicand=v_g*v_g+(g*height*2).widen_4();
|
let radicand=v_g*v_g+(g*height*2).fix_4();
|
||||||
velocity-(*gravity*(radicand.sqrt().wrap_2()+v_g)/gg).divide().clamp_1()
|
velocity-(*gravity*(radicand.sqrt().fix_2()+v_g)/gg).divide().fix_1()
|
||||||
},
|
},
|
||||||
&JumpImpulse::Linear(jump_speed)=>velocity+(jump_dir*jump_speed/jump_dir.length()).divide().clamp_1(),
|
&JumpImpulse::Linear(jump_speed)=>velocity+(jump_dir*jump_speed/jump_dir.length()).divide().fix_1(),
|
||||||
&JumpImpulse::Energy(_energy)=>{
|
&JumpImpulse::Energy(_energy)=>{
|
||||||
//calculate energy
|
//calculate energy
|
||||||
//let e=gravity.dot(velocity);
|
//let e=gravity.dot(velocity);
|
||||||
@@ -91,10 +91,10 @@ impl JumpImpulse{
|
|||||||
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
|
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
|
||||||
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
|
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
|
||||||
match self{
|
match self{
|
||||||
&JumpImpulse::Time(time)=>(gravity.length().wrap_1()*time/2).divide().clamp_1(),
|
&JumpImpulse::Time(time)=>(gravity.length().fix_1()*time/2).divide().fix_1(),
|
||||||
&JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt().wrap_1(),
|
&JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt().fix_1(),
|
||||||
&JumpImpulse::Linear(deltav)=>deltav,
|
&JumpImpulse::Linear(deltav)=>deltav,
|
||||||
&JumpImpulse::Energy(energy)=>(energy.sqrt()*2/mass.sqrt()).divide().clamp_1(),
|
&JumpImpulse::Energy(energy)=>(energy.sqrt()*2/mass.sqrt()).divide().fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,10 +126,10 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let j=boost_vel.dot(jump_dir);
|
let j=boost_vel.dot(jump_dir);
|
||||||
let js=jump_speed.widen_2();
|
let js=jump_speed.fix_2();
|
||||||
if j<js{
|
if j<js{
|
||||||
//weak booster: just do a regular jump
|
//weak booster: just do a regular jump
|
||||||
boost_vel+jump_dir.with_length(js-j).divide().wrap_1()
|
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//activate booster normally, jump does nothing
|
//activate booster normally, jump does nothing
|
||||||
boost_vel
|
boost_vel
|
||||||
@@ -142,13 +142,13 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let j=boost_vel.dot(jump_dir);
|
let j=boost_vel.dot(jump_dir);
|
||||||
let js=jump_speed.widen_2();
|
let js=jump_speed.fix_2();
|
||||||
if j<js{
|
if j<js{
|
||||||
//speed in direction of jump cannot be lower than amount
|
//speed in direction of jump cannot be lower than amount
|
||||||
boost_vel+jump_dir.with_length(js-j).divide().wrap_1()
|
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//boost and jump add together
|
//boost and jump add together
|
||||||
boost_vel+jump_dir.with_length(js).divide().wrap_1()
|
boost_vel+jump_dir.with_length(js).divide().fix_1()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(false,JumpCalculation::Max)=>{
|
(false,JumpCalculation::Max)=>{
|
||||||
@@ -159,10 +159,10 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let boost_dot=boost_vel.dot(jump_dir);
|
let boost_dot=boost_vel.dot(jump_dir);
|
||||||
let js=jump_speed.widen_2();
|
let js=jump_speed.fix_2();
|
||||||
if boost_dot<js{
|
if boost_dot<js{
|
||||||
//weak boost is extended to jump speed
|
//weak boost is extended to jump speed
|
||||||
boost_vel+jump_dir.with_length(js-boost_dot).divide().wrap_1()
|
boost_vel+jump_dir.with_length(js-boost_dot).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//activate booster normally, jump does nothing
|
//activate booster normally, jump does nothing
|
||||||
boost_vel
|
boost_vel
|
||||||
@@ -174,7 +174,7 @@ impl JumpSettings{
|
|||||||
Some(booster)=>booster.boost(rel_velocity),
|
Some(booster)=>booster.boost(rel_velocity),
|
||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
boost_vel+jump_dir.with_length(jump_speed).divide().wrap_1()
|
boost_vel+jump_dir.with_length(jump_speed).divide().fix_1()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,9 +267,9 @@ pub struct StrafeSettings{
|
|||||||
impl StrafeSettings{
|
impl StrafeSettings{
|
||||||
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
|
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
|
||||||
let d=velocity.dot(control_dir);
|
let d=velocity.dot(control_dir);
|
||||||
let mv=self.mv.widen_2();
|
let mv=self.mv.fix_2();
|
||||||
match d<mv{
|
match d<mv{
|
||||||
true=>Some(velocity+(control_dir*self.air_accel_limit.map_or(mv-d,|limit|limit.widen_2().min(mv-d))).wrap_1()),
|
true=>Some(velocity+(control_dir*self.air_accel_limit.map_or(mv-d,|limit|limit.fix_2().min(mv-d))).fix_1()),
|
||||||
false=>None,
|
false=>None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,7 +290,7 @@ pub struct PropulsionSettings{
|
|||||||
}
|
}
|
||||||
impl PropulsionSettings{
|
impl PropulsionSettings{
|
||||||
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
|
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
|
||||||
(control_dir*self.magnitude).clamp_1()
|
(control_dir*self.magnitude).fix_1()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,13 +310,13 @@ pub struct WalkSettings{
|
|||||||
impl WalkSettings{
|
impl WalkSettings{
|
||||||
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
||||||
//TODO: fallible walk accel
|
//TODO: fallible walk accel
|
||||||
let diff_len=target_diff.length().wrap_1();
|
let diff_len=target_diff.length().fix_1();
|
||||||
let friction=if diff_len<self.accelerate.topspeed{
|
let friction=if diff_len<self.accelerate.topspeed{
|
||||||
self.static_friction
|
self.static_friction
|
||||||
}else{
|
}else{
|
||||||
self.kinetic_friction
|
self.kinetic_friction
|
||||||
};
|
};
|
||||||
self.accelerate.accel.min((-gravity.y*friction).clamp_1())
|
self.accelerate.accel.min((-gravity.y*friction).fix_1())
|
||||||
}
|
}
|
||||||
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
||||||
if control_dir==crate::integer::vec3::ZERO{
|
if control_dir==crate::integer::vec3::ZERO{
|
||||||
@@ -332,7 +332,7 @@ impl WalkSettings{
|
|||||||
if cr==crate::integer::vec3::ZERO_2{
|
if cr==crate::integer::vec3::ZERO_2{
|
||||||
crate::integer::vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}else{
|
}else{
|
||||||
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().clamp_1()
|
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
crate::integer::vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
@@ -341,7 +341,7 @@ impl WalkSettings{
|
|||||||
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
|
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
|
||||||
//normal is not guaranteed to be unit length
|
//normal is not guaranteed to be unit length
|
||||||
let ny=normal.dot(up);
|
let ny=normal.dot(up);
|
||||||
let h=normal.length().wrap_1();
|
let h=normal.length().fix_1();
|
||||||
//remember this is a normal vector
|
//remember this is a normal vector
|
||||||
ny.is_positive()&&h*self.surf_dot<ny
|
ny.is_positive()&&h*self.surf_dot<ny
|
||||||
}
|
}
|
||||||
@@ -368,13 +368,13 @@ impl LadderSettings{
|
|||||||
let nnmm=nn*mm;
|
let nnmm=nn*mm;
|
||||||
let d=normal.dot(control_dir);
|
let d=normal.dot(control_dir);
|
||||||
let mut dd=d*d;
|
let mut dd=d*d;
|
||||||
if (self.dot*self.dot*nnmm).clamp_4()<dd{
|
if (self.dot*self.dot*nnmm).fix_4()<dd{
|
||||||
if d.is_negative(){
|
if d.is_negative(){
|
||||||
control_dir=Planar64Vec3::new([Planar64::ZERO,mm.clamp_1(),Planar64::ZERO]);
|
control_dir=Planar64Vec3::new([Planar64::ZERO,mm.fix_1(),Planar64::ZERO]);
|
||||||
}else{
|
}else{
|
||||||
control_dir=Planar64Vec3::new([Planar64::ZERO,-mm.clamp_1(),Planar64::ZERO]);
|
control_dir=Planar64Vec3::new([Planar64::ZERO,-mm.fix_1(),Planar64::ZERO]);
|
||||||
}
|
}
|
||||||
dd=(normal.y*normal.y).widen_4();
|
dd=(normal.y*normal.y).fix_4();
|
||||||
}
|
}
|
||||||
//n=d if you are standing on top of a ladder and press E.
|
//n=d if you are standing on top of a ladder and press E.
|
||||||
//two fixes:
|
//two fixes:
|
||||||
@@ -385,7 +385,7 @@ impl LadderSettings{
|
|||||||
if cr==crate::integer::vec3::ZERO_2{
|
if cr==crate::integer::vec3::ZERO_2{
|
||||||
crate::integer::vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}else{
|
}else{
|
||||||
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().clamp_1()
|
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
crate::integer::vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
@@ -417,7 +417,7 @@ impl Hitbox{
|
|||||||
}
|
}
|
||||||
pub fn source()->Self{
|
pub fn source()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:((int3(33,73,33)>>1)*VALVE_SCALE).narrow_1().unwrap(),
|
halfsize:((int3(33,73,33)>>1)*VALVE_SCALE).fix_1(),
|
||||||
mesh:HitboxMesh::Box,
|
mesh:HitboxMesh::Box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,11 +538,11 @@ impl StyleModifiers{
|
|||||||
tick_rate:Ratio64::new(100,AbsoluteTime::ONE_SECOND.get() as u64).unwrap(),
|
tick_rate:Ratio64::new(100,AbsoluteTime::ONE_SECOND.get() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).narrow_1().unwrap()),
|
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
|
||||||
calculation:JumpCalculation::JumpThenBoost,
|
calculation:JumpCalculation::JumpThenBoost,
|
||||||
limit_minimum:true,
|
limit_minimum:true,
|
||||||
}),
|
}),
|
||||||
gravity:(int3(0,-800,0)*VALVE_SCALE).narrow_1().unwrap(),
|
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
|
||||||
mass:int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
@@ -565,7 +565,7 @@ impl StyleModifiers{
|
|||||||
magnitude:int(12),//?
|
magnitude:int(12),//?
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).narrow_1().unwrap(),
|
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn source_surf()->Self{
|
pub fn source_surf()->Self{
|
||||||
@@ -574,16 +574,16 @@ impl StyleModifiers{
|
|||||||
controls_mask_state:Controls::all(),
|
controls_mask_state:Controls::all(),
|
||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:ControlsActivation::full_2d(),
|
enable:ControlsActivation::full_2d(),
|
||||||
air_accel_limit:Some((int(150)*66*VALVE_SCALE).narrow_1().unwrap()),
|
air_accel_limit:Some((int(150)*66*VALVE_SCALE).fix_1()),
|
||||||
mv:Planar64::raw(30<<28),
|
mv:Planar64::raw(30<<28),
|
||||||
tick_rate:Ratio64::new(66,AbsoluteTime::ONE_SECOND.get() as u64).unwrap(),
|
tick_rate:Ratio64::new(66,AbsoluteTime::ONE_SECOND.get() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).narrow_1().unwrap()),
|
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
|
||||||
calculation:JumpCalculation::JumpThenBoost,
|
calculation:JumpCalculation::JumpThenBoost,
|
||||||
limit_minimum:true,
|
limit_minimum:true,
|
||||||
}),
|
}),
|
||||||
gravity:(int3(0,-800,0)*VALVE_SCALE).narrow_1().unwrap(),
|
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
|
||||||
mass:int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
@@ -606,7 +606,7 @@ impl StyleModifiers{
|
|||||||
magnitude:int(12),//?
|
magnitude:int(12),//?
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).narrow_1().unwrap(),
|
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
pub use fixed_wide::fixed::*;
|
pub use fixed_wide::fixed::{Fixed,Fix};
|
||||||
pub use ratio_ops::ratio::{Ratio,Divide};
|
pub use ratio_ops::ratio::{Ratio,Divide};
|
||||||
|
|
||||||
//integer units
|
//integer units
|
||||||
@@ -60,7 +60,7 @@ impl<T> Time<T>{
|
|||||||
impl<T> From<Planar64> for Time<T>{
|
impl<T> From<Planar64> for Time<T>{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(value:Planar64)->Self{
|
fn from(value:Planar64)->Self{
|
||||||
Self::raw((value*Planar64::raw(1_000_000_000)).clamp_1().to_raw())
|
Self::raw((value*Planar64::raw(1_000_000_000)).fix_1().to_raw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> From<Time<T>> for Ratio<Planar64,Planar64>{
|
impl<T> From<Time<T>> for Ratio<Planar64,Planar64>{
|
||||||
@@ -73,11 +73,11 @@ impl<T,Num,Den,N1,T1> From<Ratio<Num,Den>> for Time<T>
|
|||||||
where
|
where
|
||||||
Num:core::ops::Mul<Planar64,Output=N1>,
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
N1:Divide<Den,Output=T1>,
|
N1:Divide<Den,Output=T1>,
|
||||||
T1:Clamp<Planar64>,
|
T1:Fix<Planar64>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(value:Ratio<Num,Den>)->Self{
|
fn from(value:Ratio<Num,Den>)->Self{
|
||||||
Self::raw((value*Planar64::raw(1_000_000_000)).divide().clamp().to_raw())
|
Self::raw((value*Planar64::raw(1_000_000_000)).divide().fix().to_raw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> std::fmt::Display for Time<T>{
|
impl<T> std::fmt::Display for Time<T>{
|
||||||
@@ -401,10 +401,6 @@ impl Angle32{
|
|||||||
pub const NEG_FRAC_PI_2:Self=Self(-1<<30);
|
pub const NEG_FRAC_PI_2:Self=Self(-1<<30);
|
||||||
pub const PI:Self=Self(-1<<31);
|
pub const PI:Self=Self(-1<<31);
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn raw(num:i32)->Self{
|
|
||||||
Self(num)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn wrap_from_i64(theta:i64)->Self{
|
pub const fn wrap_from_i64(theta:i64)->Self{
|
||||||
//take lower bits
|
//take lower bits
|
||||||
//note: this was checked on compiler explorer and compiles to 1 instruction!
|
//note: this was checked on compiler explorer and compiles to 1 instruction!
|
||||||
@@ -519,8 +515,8 @@ fn angle_sin_cos(){
|
|||||||
println!("cordic s={} c={}",(s/h).divide(),(c/h).divide());
|
println!("cordic s={} c={}",(s/h).divide(),(c/h).divide());
|
||||||
let (fs,fc)=f.sin_cos();
|
let (fs,fc)=f.sin_cos();
|
||||||
println!("float s={} c={}",fs,fc);
|
println!("float s={} c={}",fs,fc);
|
||||||
assert!(close_enough((c/h).divide().wrap_1(),Planar64::raw((fc*((1u64<<32) as f64)) as i64)));
|
assert!(close_enough((c/h).divide().fix_1(),Planar64::raw((fc*((1u64<<32) as f64)) as i64)));
|
||||||
assert!(close_enough((s/h).divide().wrap_1(),Planar64::raw((fs*((1u64<<32) as f64)) as i64)));
|
assert!(close_enough((s/h).divide().fix_1(),Planar64::raw((fs*((1u64<<32) as f64)) as i64)));
|
||||||
}
|
}
|
||||||
test_angle(1.0);
|
test_angle(1.0);
|
||||||
test_angle(std::f64::consts::PI/4.0);
|
test_angle(std::f64::consts::PI/4.0);
|
||||||
@@ -562,10 +558,6 @@ pub mod vec3{
|
|||||||
pub const MAX:Planar64Vec3=Planar64Vec3::new([Planar64::MAX;3]);
|
pub const MAX:Planar64Vec3=Planar64Vec3::new([Planar64::MAX;3]);
|
||||||
pub const ZERO:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO;3]);
|
pub const ZERO:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO;3]);
|
||||||
pub const ZERO_2:linear_ops::types::Vector3<Fixed::<2,64>>=linear_ops::types::Vector3::new([Fixed::<2,64>::ZERO;3]);
|
pub const ZERO_2:linear_ops::types::Vector3<Fixed::<2,64>>=linear_ops::types::Vector3::new([Fixed::<2,64>::ZERO;3]);
|
||||||
pub const ZERO_3:linear_ops::types::Vector3<Fixed::<3,96>>=linear_ops::types::Vector3::new([Fixed::<3,96>::ZERO;3]);
|
|
||||||
pub const ZERO_4:linear_ops::types::Vector3<Fixed::<4,128>>=linear_ops::types::Vector3::new([Fixed::<4,128>::ZERO;3]);
|
|
||||||
pub const ZERO_5:linear_ops::types::Vector3<Fixed::<5,160>>=linear_ops::types::Vector3::new([Fixed::<5,160>::ZERO;3]);
|
|
||||||
pub const ZERO_6:linear_ops::types::Vector3<Fixed::<6,192>>=linear_ops::types::Vector3::new([Fixed::<6,192>::ZERO;3]);
|
|
||||||
pub const X:Planar64Vec3=Planar64Vec3::new([Planar64::ONE,Planar64::ZERO,Planar64::ZERO]);
|
pub const X:Planar64Vec3=Planar64Vec3::new([Planar64::ONE,Planar64::ZERO,Planar64::ZERO]);
|
||||||
pub const Y:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ONE,Planar64::ZERO]);
|
pub const Y:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ONE,Planar64::ZERO]);
|
||||||
pub const Z:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ZERO,Planar64::ONE]);
|
pub const Z:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ZERO,Planar64::ONE]);
|
||||||
@@ -633,8 +625,8 @@ pub mod mat3{
|
|||||||
let (yc,ys)=y.cos_sin();
|
let (yc,ys)=y.cos_sin();
|
||||||
Planar64Mat3::from_cols([
|
Planar64Mat3::from_cols([
|
||||||
Planar64Vec3::new([xc,Planar64::ZERO,-xs]),
|
Planar64Vec3::new([xc,Planar64::ZERO,-xs]),
|
||||||
Planar64Vec3::new([(xs*ys).wrap_1(),yc,(xc*ys).wrap_1()]),
|
Planar64Vec3::new([(xs*ys).fix_1(),yc,(xc*ys).fix_1()]),
|
||||||
Planar64Vec3::new([(xs*yc).wrap_1(),-ys,(xc*yc).wrap_1()]),
|
Planar64Vec3::new([(xs*yc).fix_1(),-ys,(xc*yc).fix_1()]),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -676,7 +668,7 @@ impl Planar64Affine3{
|
|||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_point3(&self,point:Planar64Vec3)->vec3::Vector3<Fixed<2,64>>{
|
pub fn transform_point3(&self,point:Planar64Vec3)->vec3::Vector3<Fixed<2,64>>{
|
||||||
self.translation.widen_2()+self.matrix3*point
|
self.translation.fix_2()+self.matrix3*point
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Into<glam::Mat4> for Planar64Affine3{
|
impl Into<glam::Mat4> for Planar64Affine3{
|
||||||
|
|||||||
@@ -208,9 +208,87 @@ impl MeshBuilder{
|
|||||||
|
|
||||||
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
pub struct ModelId(u32);
|
pub struct ModelId(u32);
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Model{
|
pub struct Model{
|
||||||
pub mesh:MeshId,
|
pub mesh:MeshId,
|
||||||
pub attributes:gameplay_attributes::CollisionAttributesId,
|
pub attributes:gameplay_attributes::CollisionAttributesId,
|
||||||
pub color:Color4,//transparency is in here
|
pub color:Color4,//transparency is in here
|
||||||
pub transform:Planar64Affine3,
|
pub transform:Planar64Affine3,
|
||||||
|
pub debug_info:DebugInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub enum DebugInfo{
|
||||||
|
World,
|
||||||
|
Prop,
|
||||||
|
Brush(BrushInfo),
|
||||||
|
Entity(EntityInfo),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for DebugInfo{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
match self{
|
||||||
|
DebugInfo::World=>write!(f,"World"),
|
||||||
|
DebugInfo::Prop=>write!(f,"Prop"),
|
||||||
|
DebugInfo::Brush(brush_info)=>brush_info.fmt(f),
|
||||||
|
DebugInfo::Entity(entity_info)=>entity_info.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct BrushInfo{
|
||||||
|
pub flags:vbsp::BrushFlags,
|
||||||
|
pub sides:Vec<vbsp::TextureFlags>,
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for BrushInfo{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
let noice=self.flags.iter_names().filter_map(|(name,flags)|{
|
||||||
|
(flags.bits()!=0).then(||name)
|
||||||
|
}).collect::<Vec<&str>>().join("|");
|
||||||
|
writeln!(f,"brush_info.flags={noice}")?;
|
||||||
|
for (i,side) in self.sides.iter().enumerate(){
|
||||||
|
let noice_string=side.iter_names().filter_map(|(name,flags)|{
|
||||||
|
(flags.bits()!=0).then(||name)
|
||||||
|
}).collect::<Vec<&str>>().join("|");
|
||||||
|
writeln!(f,"brush_info.sides[{i}]={noice_string}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct EntityInfo{
|
||||||
|
pub classname:Box<str>,
|
||||||
|
pub properties:Vec<(Box<str>,Box<str>)>,
|
||||||
|
}
|
||||||
|
pub enum EntityInfoError{
|
||||||
|
MissingClassname,
|
||||||
|
}
|
||||||
|
impl EntityInfo{
|
||||||
|
pub fn new<'a>(iter:impl IntoIterator<Item=(&'a str,&'a str)>)->Result<Self,EntityInfoError>{
|
||||||
|
let mut classname:Option<Box<str>>=None;
|
||||||
|
let mut properties:Vec<(Box<str>,Box<str>)>=Vec::new();
|
||||||
|
for (name,value) in iter{
|
||||||
|
match name{
|
||||||
|
"classname"=>classname=Some(value.into()),
|
||||||
|
"hammerid"=>(),
|
||||||
|
_=>properties.push((name.into(),value.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
properties.sort_by(|(n0,_),(n1,_)|n0.cmp(n1));
|
||||||
|
let Some(classname)=classname else{
|
||||||
|
return Err(EntityInfoError::MissingClassname);
|
||||||
|
};
|
||||||
|
Ok(EntityInfo{classname,properties})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for EntityInfo{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
writeln!(f,"struct {}{{",self.classname)?;
|
||||||
|
for (name,value) in &self.properties{
|
||||||
|
writeln!(f,"\t{name}:{value},")?;
|
||||||
|
}
|
||||||
|
write!(f,"}}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ impl Ray{
|
|||||||
Num:core::ops::Mul<Planar64,Output=N1>,
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
Planar64:core::ops::Mul<Den,Output=N1>,
|
Planar64:core::ops::Mul<Den,Output=N1>,
|
||||||
N1:integer::Divide<Den,Output=T1>,
|
N1:integer::Divide<Den,Output=T1>,
|
||||||
T1:integer::Clamp<Planar64>,
|
T1:integer::Fix<Planar64>,
|
||||||
{
|
{
|
||||||
self.origin+self.direction.map(|elem|(t*elem).divide().clamp())
|
self.origin+self.direction.map(|elem|(t*elem).divide().fix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fixed_wide"
|
name = "fixed_wide"
|
||||||
version = "0.2.0"
|
version = "0.1.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
repository = "https://git.itzana.me/StrafesNET/strafe-project"
|
repository = "https://git.itzana.me/StrafesNET/strafe-project"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|||||||
@@ -663,94 +663,74 @@ macro_repeated!(
|
|||||||
1,2,3,4,5,6,7,8
|
1,2,3,4,5,6,7,8
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug,Eq,PartialEq)]
|
pub trait Fix<Out>{
|
||||||
pub enum NarrowError{
|
fn fix(self)->Out;
|
||||||
Overflow,
|
|
||||||
Underflow,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Wrap<Output>{
|
macro_rules! impl_fix_rhs_lt_lhs_not_const_generic{
|
||||||
fn wrap(self)->Output;
|
|
||||||
}
|
|
||||||
pub trait Clamp<Output>{
|
|
||||||
fn clamp(self)->Output;
|
|
||||||
}
|
|
||||||
impl<const N:usize,const F:usize> Clamp<Fixed<N,F>> for Result<Fixed<N,F>,NarrowError>{
|
|
||||||
fn clamp(self)->Fixed<N,F>{
|
|
||||||
match self{
|
|
||||||
Ok(fixed)=>fixed,
|
|
||||||
Err(NarrowError::Overflow)=>Fixed::MAX,
|
|
||||||
Err(NarrowError::Underflow)=>Fixed::MIN,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_narrow_not_const_generic{
|
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
($lhs:expr,$rhs:expr)
|
($lhs:expr,$rhs:expr)
|
||||||
)=>{
|
)=>{
|
||||||
paste::item!{
|
impl Fixed<$lhs,{$lhs*32}>
|
||||||
impl Fixed<$lhs,{$lhs*32}>
|
{
|
||||||
{
|
paste::item!{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn [<wrap_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
pub fn [<fix_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
Fixed::from_bits(bnum::cast::As::as_::<BInt::<$rhs>>(self.bits.shr(($lhs-$rhs)*32)))
|
Fixed::from_bits(bnum::cast::As::as_::<BInt::<$rhs>>(self.bits.shr(($lhs-$rhs)*32)))
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn [<narrow_ $rhs>](self)->Result<Fixed<$rhs,{$rhs*32}>,NarrowError>{
|
|
||||||
if Fixed::<$rhs,{$rhs*32}>::MAX.[<widen_ $lhs>]().bits<self.bits{
|
|
||||||
return Err(NarrowError::Overflow);
|
|
||||||
}
|
|
||||||
if self.bits<Fixed::<$rhs,{$rhs*32}>::MIN.[<widen_ $lhs>]().bits{
|
|
||||||
return Err(NarrowError::Underflow);
|
|
||||||
}
|
|
||||||
Ok(self.[<wrap_ $rhs>]())
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn [<clamp_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
|
||||||
self.[<narrow_ $rhs>]().clamp()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Wrap<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
}
|
||||||
#[inline]
|
impl Fix<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
||||||
fn wrap(self)->Fixed<$rhs,{$rhs*32}>{
|
fn fix(self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
self.[<wrap_ $rhs>]()
|
paste::item!{
|
||||||
}
|
self.[<fix_ $rhs>]()
|
||||||
}
|
|
||||||
impl TryInto<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
|
||||||
type Error=NarrowError;
|
|
||||||
#[inline]
|
|
||||||
fn try_into(self)->Result<Fixed<$rhs,{$rhs*32}>,Self::Error>{
|
|
||||||
self.[<narrow_ $rhs>]()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Clamp<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
|
||||||
#[inline]
|
|
||||||
fn clamp(self)->Fixed<$rhs,{$rhs*32}>{
|
|
||||||
self.[<clamp_ $rhs>]()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
macro_rules! impl_widen_not_const_generic{
|
macro_rules! impl_fix_lhs_lt_rhs_not_const_generic{
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
($lhs:expr,$rhs:expr)
|
($lhs:expr,$rhs:expr)
|
||||||
)=>{
|
)=>{
|
||||||
paste::item!{
|
impl Fixed<$lhs,{$lhs*32}>
|
||||||
impl Fixed<$lhs,{$lhs*32}>
|
{
|
||||||
{
|
paste::item!{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn [<widen_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
pub fn [<fix_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
Fixed::from_bits(bnum::cast::As::as_::<BInt::<$rhs>>(self.bits).shl(($rhs-$lhs)*32))
|
Fixed::from_bits(bnum::cast::As::as_::<BInt::<$rhs>>(self.bits).shl(($rhs-$lhs)*32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Into<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
}
|
||||||
|
impl Fix<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
||||||
|
fn fix(self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
|
paste::item!{
|
||||||
|
self.[<fix_ $rhs>]()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
macro_rules! impl_fix_lhs_eq_rhs_not_const_generic{
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
($lhs:expr,$rhs:expr)
|
||||||
|
)=>{
|
||||||
|
impl Fixed<$lhs,{$lhs*32}>
|
||||||
|
{
|
||||||
|
paste::item!{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self)->Fixed<$rhs,{$rhs*32}>{
|
pub fn [<fix_ $rhs>](self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
self.[<widen_ $rhs>]()
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Fix<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
||||||
|
fn fix(self)->Fixed<$rhs,{$rhs*32}>{
|
||||||
|
paste::item!{
|
||||||
|
self.[<fix_ $rhs>]()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -760,7 +740,7 @@ macro_rules! impl_widen_not_const_generic{
|
|||||||
// I LOVE NOT BEING ABLE TO USE CONST GENERICS
|
// I LOVE NOT BEING ABLE TO USE CONST GENERICS
|
||||||
|
|
||||||
macro_repeated!(
|
macro_repeated!(
|
||||||
impl_narrow_not_const_generic,(),
|
impl_fix_rhs_lt_lhs_not_const_generic,(),
|
||||||
(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),
|
(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),
|
||||||
(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2),(13,2),(14,2),(15,2),(16,2),
|
(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2),(13,2),(14,2),(15,2),(16,2),
|
||||||
(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3),(13,3),(14,3),(15,3),(16,3),
|
(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3),(13,3),(14,3),(15,3),(16,3),
|
||||||
@@ -778,7 +758,7 @@ macro_repeated!(
|
|||||||
(16,15)
|
(16,15)
|
||||||
);
|
);
|
||||||
macro_repeated!(
|
macro_repeated!(
|
||||||
impl_widen_not_const_generic,(),
|
impl_fix_lhs_lt_rhs_not_const_generic,(),
|
||||||
(1,2),
|
(1,2),
|
||||||
(1,3),(2,3),
|
(1,3),(2,3),
|
||||||
(1,4),(2,4),(3,4),
|
(1,4),(2,4),(3,4),
|
||||||
@@ -793,8 +773,11 @@ macro_repeated!(
|
|||||||
(1,13),(2,13),(3,13),(4,13),(5,13),(6,13),(7,13),(8,13),(9,13),(10,13),(11,13),(12,13),
|
(1,13),(2,13),(3,13),(4,13),(5,13),(6,13),(7,13),(8,13),(9,13),(10,13),(11,13),(12,13),
|
||||||
(1,14),(2,14),(3,14),(4,14),(5,14),(6,14),(7,14),(8,14),(9,14),(10,14),(11,14),(12,14),(13,14),
|
(1,14),(2,14),(3,14),(4,14),(5,14),(6,14),(7,14),(8,14),(9,14),(10,14),(11,14),(12,14),(13,14),
|
||||||
(1,15),(2,15),(3,15),(4,15),(5,15),(6,15),(7,15),(8,15),(9,15),(10,15),(11,15),(12,15),(13,15),(14,15),
|
(1,15),(2,15),(3,15),(4,15),(5,15),(6,15),(7,15),(8,15),(9,15),(10,15),(11,15),(12,15),(13,15),(14,15),
|
||||||
(1,16),(2,16),(3,16),(4,16),(5,16),(6,16),(7,16),(8,16),(9,16),(10,16),(11,16),(12,16),(13,16),(14,16),(15,16),
|
(1,16),(2,16),(3,16),(4,16),(5,16),(6,16),(7,16),(8,16),(9,16),(10,16),(11,16),(12,16),(13,16),(14,16),(15,16)
|
||||||
(1,17)
|
);
|
||||||
|
macro_repeated!(
|
||||||
|
impl_fix_lhs_eq_rhs_not_const_generic,(),
|
||||||
|
(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16)
|
||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! impl_not_const_generic{
|
macro_rules! impl_not_const_generic{
|
||||||
@@ -814,7 +797,7 @@ macro_rules! impl_not_const_generic{
|
|||||||
let mut result=Self::ZERO;
|
let mut result=Self::ZERO;
|
||||||
|
|
||||||
//resize self to match the wide mul output
|
//resize self to match the wide mul output
|
||||||
let wide_self=self.[<widen_ $_2n>]();
|
let wide_self=self.[<fix_ $_2n>]();
|
||||||
//descend down the bits and check if flipping each bit would push the square over the input value
|
//descend down the bits and check if flipping each bit would push the square over the input value
|
||||||
for shift in (0..=max_shift).rev(){
|
for shift in (0..=max_shift).rev(){
|
||||||
result.as_bits_mut().as_bits_mut().set_bit(shift,true);
|
result.as_bits_mut().as_bits_mut().set_bit(shift,true);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ fn from_f32(){
|
|||||||
let b:Result<I32F32,_>=Into::<f32>::into(I32F32::MIN).try_into();
|
let b:Result<I32F32,_>=Into::<f32>::into(I32F32::MIN).try_into();
|
||||||
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
||||||
//16 is within the 24 bits of float precision
|
//16 is within the 24 bits of float precision
|
||||||
let b:Result<I32F32,_>=Into::<f32>::into(-I32F32::MIN.widen_2()).try_into();
|
let b:Result<I32F32,_>=Into::<f32>::into(-I32F32::MIN.fix_2()).try_into();
|
||||||
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
||||||
let b:Result<I32F32,_>=f32::MIN_POSITIVE.try_into();
|
let b:Result<I32F32,_>=f32::MIN_POSITIVE.try_into();
|
||||||
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Underflow));
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Underflow));
|
||||||
@@ -136,24 +136,11 @@ fn test_bint(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrap(){
|
fn test_fix(){
|
||||||
assert_eq!(I32F32::ONE,I256F256::ONE.wrap_1());
|
assert_eq!(I32F32::ONE.fix_8(),I256F256::ONE);
|
||||||
assert_eq!(I32F32::NEG_ONE,I256F256::NEG_ONE.wrap_1());
|
assert_eq!(I32F32::ONE,I256F256::ONE.fix_1());
|
||||||
}
|
assert_eq!(I32F32::NEG_ONE.fix_8(),I256F256::NEG_ONE);
|
||||||
#[test]
|
assert_eq!(I32F32::NEG_ONE,I256F256::NEG_ONE.fix_1());
|
||||||
fn test_narrow(){
|
|
||||||
assert_eq!(Ok(I32F32::ONE),I256F256::ONE.narrow_1());
|
|
||||||
assert_eq!(Ok(I32F32::NEG_ONE),I256F256::NEG_ONE.narrow_1());
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_widen(){
|
|
||||||
assert_eq!(I32F32::ONE.widen_8(),I256F256::ONE);
|
|
||||||
assert_eq!(I32F32::NEG_ONE.widen_8(),I256F256::NEG_ONE);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_clamp(){
|
|
||||||
assert_eq!(I32F32::ONE,I256F256::ONE.clamp_1());
|
|
||||||
assert_eq!(I32F32::NEG_ONE,I256F256::NEG_ONE.clamp_1());
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt(){
|
fn test_sqrt(){
|
||||||
|
|||||||
@@ -15,10 +15,8 @@ macro_rules! impl_zeroes{
|
|||||||
let radicand=a1*a1-a2*a0*4;
|
let radicand=a1*a1-a2*a0*4;
|
||||||
match radicand.cmp(&<Self as core::ops::Mul>::Output::ZERO){
|
match radicand.cmp(&<Self as core::ops::Mul>::Output::ZERO){
|
||||||
Ordering::Greater=>{
|
Ordering::Greater=>{
|
||||||
// using wrap because sqrt always halves the number of leading digits.
|
|
||||||
// clamp would be more defensive, but is slower.
|
|
||||||
paste::item!{
|
paste::item!{
|
||||||
let planar_radicand=radicand.sqrt().[<wrap_ $n>]();
|
let planar_radicand=radicand.sqrt().[<fix_ $n>]();
|
||||||
}
|
}
|
||||||
//sort roots ascending and avoid taking the difference of large numbers
|
//sort roots ascending and avoid taking the difference of large numbers
|
||||||
let zeroes=match (a2pos,Self::ZERO<a1){
|
let zeroes=match (a2pos,Self::ZERO<a1){
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "linear_ops"
|
name = "linear_ops"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
repository = "https://git.itzana.me/StrafesNET/strafe-project"
|
repository = "https://git.itzana.me/StrafesNET/strafe-project"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@@ -15,7 +15,7 @@ deferred-division=["dep:ratio_ops"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ratio_ops = { version = "0.1.0", path = "../ratio_ops", registry = "strafesnet", optional = true }
|
ratio_ops = { version = "0.1.0", path = "../ratio_ops", registry = "strafesnet", optional = true }
|
||||||
fixed_wide = { version = "0.2.0", path = "../fixed_wide", registry = "strafesnet", optional = true }
|
fixed_wide = { version = "0.1.2", path = "../fixed_wide", registry = "strafesnet", optional = true }
|
||||||
paste = { version = "1.0.15", optional = true }
|
paste = { version = "1.0.15", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -38,95 +38,40 @@ macro_rules! impl_fixed_wide_vector {
|
|||||||
$crate::macro_4!(impl_fixed_wide_vector_not_const_generic,());
|
$crate::macro_4!(impl_fixed_wide_vector_not_const_generic,());
|
||||||
// I LOVE NOT BEING ABLE TO USE CONST GENERICS
|
// I LOVE NOT BEING ABLE TO USE CONST GENERICS
|
||||||
$crate::macro_repeated!(
|
$crate::macro_repeated!(
|
||||||
impl_narrow_not_const_generic,(),
|
impl_fix_not_const_generic,(),
|
||||||
(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),
|
(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),
|
||||||
(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2),(13,2),(14,2),(15,2),(16,2),
|
(1,2),(2,2),(3,2),(4,2),(5,2),(6,2),(7,2),(8,2),(9,2),(10,2),(11,2),(12,2),(13,2),(14,2),(15,2),(16,2),
|
||||||
(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3),(13,3),(14,3),(15,3),(16,3),
|
(1,3),(2,3),(3,3),(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3),(13,3),(14,3),(15,3),(16,3),
|
||||||
(5,4),(6,4),(7,4),(8,4),(9,4),(10,4),(11,4),(12,4),(13,4),(14,4),(15,4),(16,4),
|
(1,4),(2,4),(3,4),(4,4),(5,4),(6,4),(7,4),(8,4),(9,4),(10,4),(11,4),(12,4),(13,4),(14,4),(15,4),(16,4),
|
||||||
(6,5),(7,5),(8,5),(9,5),(10,5),(11,5),(12,5),(13,5),(14,5),(15,5),(16,5),
|
(1,5),(2,5),(3,5),(4,5),(5,5),(6,5),(7,5),(8,5),(9,5),(10,5),(11,5),(12,5),(13,5),(14,5),(15,5),(16,5),
|
||||||
(7,6),(8,6),(9,6),(10,6),(11,6),(12,6),(13,6),(14,6),(15,6),(16,6),
|
(1,6),(2,6),(3,6),(4,6),(5,6),(6,6),(7,6),(8,6),(9,6),(10,6),(11,6),(12,6),(13,6),(14,6),(15,6),(16,6),
|
||||||
(8,7),(9,7),(10,7),(11,7),(12,7),(13,7),(14,7),(15,7),(16,7),
|
(1,7),(2,7),(3,7),(4,7),(5,7),(6,7),(7,7),(8,7),(9,7),(10,7),(11,7),(12,7),(13,7),(14,7),(15,7),(16,7),
|
||||||
(9,8),(10,8),(11,8),(12,8),(13,8),(14,8),(15,8),(16,8),
|
(1,8),(2,8),(3,8),(4,8),(5,8),(6,8),(7,8),(8,8),(9,8),(10,8),(11,8),(12,8),(13,8),(14,8),(15,8),(16,8),
|
||||||
(10,9),(11,9),(12,9),(13,9),(14,9),(15,9),(16,9),
|
(1,9),(2,9),(3,9),(4,9),(5,9),(6,9),(7,9),(8,9),(9,9),(10,9),(11,9),(12,9),(13,9),(14,9),(15,9),(16,9),
|
||||||
(11,10),(12,10),(13,10),(14,10),(15,10),(16,10),
|
(1,10),(2,10),(3,10),(4,10),(5,10),(6,10),(7,10),(8,10),(9,10),(10,10),(11,10),(12,10),(13,10),(14,10),(15,10),(16,10),
|
||||||
(12,11),(13,11),(14,11),(15,11),(16,11),
|
(1,11),(2,11),(3,11),(4,11),(5,11),(6,11),(7,11),(8,11),(9,11),(10,11),(11,11),(12,11),(13,11),(14,11),(15,11),(16,11),
|
||||||
(13,12),(14,12),(15,12),(16,12),
|
(1,12),(2,12),(3,12),(4,12),(5,12),(6,12),(7,12),(8,12),(9,12),(10,12),(11,12),(12,12),(13,12),(14,12),(15,12),(16,12),
|
||||||
(14,13),(15,13),(16,13),
|
(1,13),(2,13),(3,13),(4,13),(5,13),(6,13),(7,13),(8,13),(9,13),(10,13),(11,13),(12,13),(13,13),(14,13),(15,13),(16,13),
|
||||||
(15,14),(16,14),
|
(1,14),(2,14),(3,14),(4,14),(5,14),(6,14),(7,14),(8,14),(9,14),(10,14),(11,14),(12,14),(13,14),(14,14),(15,14),(16,14),
|
||||||
(16,15)
|
(1,15),(2,15),(3,15),(4,15),(5,15),(6,15),(7,15),(8,15),(9,15),(10,15),(11,15),(12,15),(13,15),(14,15),(15,15),(16,15),
|
||||||
|
(1,16),(2,16),(3,16),(4,16),(5,16),(6,16),(7,16),(8,16),(9,16),(10,16),(11,16),(12,16),(13,16),(14,16),(15,16),(16,16)
|
||||||
);
|
);
|
||||||
$crate::macro_repeated!(
|
|
||||||
impl_widen_not_const_generic,(),
|
|
||||||
(1,2),
|
|
||||||
(1,3),(2,3),
|
|
||||||
(1,4),(2,4),(3,4),
|
|
||||||
(1,5),(2,5),(3,5),(4,5),
|
|
||||||
(1,6),(2,6),(3,6),(4,6),(5,6),
|
|
||||||
(1,7),(2,7),(3,7),(4,7),(5,7),(6,7),
|
|
||||||
(1,8),(2,8),(3,8),(4,8),(5,8),(6,8),(7,8),
|
|
||||||
(1,9),(2,9),(3,9),(4,9),(5,9),(6,9),(7,9),(8,9),
|
|
||||||
(1,10),(2,10),(3,10),(4,10),(5,10),(6,10),(7,10),(8,10),(9,10),
|
|
||||||
(1,11),(2,11),(3,11),(4,11),(5,11),(6,11),(7,11),(8,11),(9,11),(10,11),
|
|
||||||
(1,12),(2,12),(3,12),(4,12),(5,12),(6,12),(7,12),(8,12),(9,12),(10,12),(11,12),
|
|
||||||
(1,13),(2,13),(3,13),(4,13),(5,13),(6,13),(7,13),(8,13),(9,13),(10,13),(11,13),(12,13),
|
|
||||||
(1,14),(2,14),(3,14),(4,14),(5,14),(6,14),(7,14),(8,14),(9,14),(10,14),(11,14),(12,14),(13,14),
|
|
||||||
(1,15),(2,15),(3,15),(4,15),(5,15),(6,15),(7,15),(8,15),(9,15),(10,15),(11,15),(12,15),(13,15),(14,15),
|
|
||||||
(1,16),(2,16),(3,16),(4,16),(5,16),(6,16),(7,16),(8,16),(9,16),(10,16),(11,16),(12,16),(13,16),(14,16),(15,16),
|
|
||||||
(1,17)
|
|
||||||
);
|
|
||||||
impl<const N:usize,T:fixed_wide::fixed::Wrap<U>,U> fixed_wide::fixed::Wrap<Vector<N,U>> for Vector<N,T>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn wrap(self)->Vector<N,U>{
|
|
||||||
self.map(|t|t.wrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<const N:usize,T:fixed_wide::fixed::Clamp<U>,U> fixed_wide::fixed::Clamp<Vector<N,U>> for Vector<N,T>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn clamp(self)->Vector<N,U>{
|
|
||||||
self.map(|t|t.clamp())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export(local_inner_macros)]
|
#[macro_export(local_inner_macros)]
|
||||||
macro_rules! impl_narrow_not_const_generic{
|
macro_rules! impl_fix_not_const_generic{
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
($lhs:expr,$rhs:expr)
|
($lhs:expr,$rhs:expr)
|
||||||
)=>{
|
)=>{
|
||||||
paste::item!{
|
impl<const N:usize> Vector<N,fixed_wide::fixed::Fixed<$lhs,{$lhs*32}>>
|
||||||
impl<const N:usize> Vector<N,fixed_wide::fixed::Fixed<$lhs,{$lhs*32}>>{
|
{
|
||||||
|
paste::item!{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn [<wrap_ $rhs>](self)->Vector<N,fixed_wide::fixed::Fixed<$rhs,{$rhs*32}>>{
|
pub fn [<fix_ $rhs>](self)->Vector<N,fixed_wide::fixed::Fixed<$rhs,{$rhs*32}>>{
|
||||||
self.map(|t|t.[<wrap_ $rhs>]())
|
self.map(|t|t.[<fix_ $rhs>]())
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn [<narrow_ $rhs>](self)->Vector<N,Result<fixed_wide::fixed::Fixed<$rhs,{$rhs*32}>,fixed_wide::fixed::NarrowError>>{
|
|
||||||
self.map(|t|t.[<narrow_ $rhs>]())
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn [<clamp_ $rhs>](self)->Vector<N,fixed_wide::fixed::Fixed<$rhs,{$rhs*32}>>{
|
|
||||||
self.map(|t|t.[<clamp_ $rhs>]())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[macro_export(local_inner_macros)]
|
|
||||||
macro_rules! impl_widen_not_const_generic{
|
|
||||||
(
|
|
||||||
(),
|
|
||||||
($lhs:expr,$rhs:expr)
|
|
||||||
)=>{
|
|
||||||
paste::item!{
|
|
||||||
impl<const N:usize> Vector<N,fixed_wide::fixed::Fixed<$lhs,{$lhs*32}>>{
|
|
||||||
#[inline]
|
|
||||||
pub fn [<widen_ $rhs>](self)->Vector<N,fixed_wide::fixed::Fixed<$rhs,{$rhs*32}>>{
|
|
||||||
self.map(|t|t.[<widen_ $rhs>]())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,15 +58,6 @@ macro_rules! impl_vector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N:usize,T,E:std::fmt::Debug> Vector<N,Result<T,E>>{
|
|
||||||
#[inline]
|
|
||||||
pub fn unwrap(self)->Vector<N,T>{
|
|
||||||
Vector{
|
|
||||||
array:self.array.map(Result::unwrap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N:usize,T:Ord> Vector<N,T>{
|
impl<const N:usize,T:Ord> Vector<N,T>{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn min(self,rhs:Self)->Self{
|
pub fn min(self,rhs:Self)->Self{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ fn planar64_affine3_from_roblox(cf:&rbx_dom_weak::types::CFrame,size:&rbx_dom_we
|
|||||||
*integer::try_from_f32(size.y/2.0).unwrap(),
|
*integer::try_from_f32(size.y/2.0).unwrap(),
|
||||||
vec3::try_from_f32_array([cf.orientation.x.z,cf.orientation.y.z,cf.orientation.z.z]).unwrap()
|
vec3::try_from_f32_array([cf.orientation.x.z,cf.orientation.y.z,cf.orientation.z.z]).unwrap()
|
||||||
*integer::try_from_f32(size.z/2.0).unwrap(),
|
*integer::try_from_f32(size.z/2.0).unwrap(),
|
||||||
].map(|t|t.narrow_1().unwrap())),
|
].map(|t|t.fix_1())),
|
||||||
vec3::try_from_f32_array([cf.position.x,cf.position.y,cf.position.z]).unwrap()
|
vec3::try_from_f32_array([cf.position.x,cf.position.y,cf.position.z]).unwrap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -837,9 +837,9 @@ impl PartialMap1<'_>{
|
|||||||
color:deferred_model_deferred_attributes.model.color,
|
color:deferred_model_deferred_attributes.model.color,
|
||||||
transform:Planar64Affine3::new(
|
transform:Planar64Affine3::new(
|
||||||
Planar64Mat3::from_cols([
|
Planar64Mat3::from_cols([
|
||||||
(deferred_model_deferred_attributes.model.transform.matrix3.x_axis*2/size.x).divide().narrow_1().unwrap(),
|
(deferred_model_deferred_attributes.model.transform.matrix3.x_axis*2/size.x).divide().fix_1(),
|
||||||
(deferred_model_deferred_attributes.model.transform.matrix3.y_axis*2/size.y).divide().narrow_1().unwrap(),
|
(deferred_model_deferred_attributes.model.transform.matrix3.y_axis*2/size.y).divide().fix_1(),
|
||||||
(deferred_model_deferred_attributes.model.transform.matrix3.z_axis*2/size.z).divide().narrow_1().unwrap(),
|
(deferred_model_deferred_attributes.model.transform.matrix3.z_axis*2/size.z).divide().fix_1()
|
||||||
]),
|
]),
|
||||||
deferred_model_deferred_attributes.model.transform.translation
|
deferred_model_deferred_attributes.model.transform.translation
|
||||||
),
|
),
|
||||||
@@ -861,9 +861,9 @@ impl PartialMap1<'_>{
|
|||||||
color:deferred_union_deferred_attributes.model.color,
|
color:deferred_union_deferred_attributes.model.color,
|
||||||
transform:Planar64Affine3::new(
|
transform:Planar64Affine3::new(
|
||||||
Planar64Mat3::from_cols([
|
Planar64Mat3::from_cols([
|
||||||
(deferred_union_deferred_attributes.model.transform.matrix3.x_axis*2/size.x).divide().narrow_1().unwrap(),
|
(deferred_union_deferred_attributes.model.transform.matrix3.x_axis*2/size.x).divide().fix_1(),
|
||||||
(deferred_union_deferred_attributes.model.transform.matrix3.y_axis*2/size.y).divide().narrow_1().unwrap(),
|
(deferred_union_deferred_attributes.model.transform.matrix3.y_axis*2/size.y).divide().fix_1(),
|
||||||
(deferred_union_deferred_attributes.model.transform.matrix3.z_axis*2/size.z).divide().narrow_1().unwrap(),
|
(deferred_union_deferred_attributes.model.transform.matrix3.z_axis*2/size.z).divide().fix_1()
|
||||||
]),
|
]),
|
||||||
deferred_union_deferred_attributes.model.transform.translation
|
deferred_union_deferred_attributes.model.transform.translation
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ pub fn write_map<W:BinWriterExt>(mut writer:W,map:strafesnet_common::map::Comple
|
|||||||
let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?;
|
let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?;
|
||||||
let mut aabb=strafesnet_common::aabb::Aabb::default();
|
let mut aabb=strafesnet_common::aabb::Aabb::default();
|
||||||
for &pos in &mesh.unique_pos{
|
for &pos in &mesh.unique_pos{
|
||||||
aabb.grow(model.transform.transform_point3(pos).narrow_1().unwrap());
|
aabb.grow(model.transform.transform_point3(pos).fix_1());
|
||||||
}
|
}
|
||||||
Ok(((model::ModelId::new(model_id as u32),model.into()),aabb))
|
Ok(((model::ModelId::new(model_id as u32),model.into()),aabb))
|
||||||
}).collect::<Result<Vec<_>,_>>()?;
|
}).collect::<Result<Vec<_>,_>>()?;
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ impl Into<strafesnet_common::model::Model> for Model{
|
|||||||
]),
|
]),
|
||||||
strafesnet_common::integer::vec3::raw_xyz(_9,_a,_b)
|
strafesnet_common::integer::vec3::raw_xyz(_9,_a,_b)
|
||||||
),
|
),
|
||||||
|
debug_info:strafesnet_common::model::DebugInfo::World,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,5 +77,8 @@ pub fn new<'a>(
|
|||||||
run_session_instruction!(ins.time,SessionInstruction::LoadReplay(bot));
|
run_session_instruction!(ins.time,SessionInstruction::LoadReplay(bot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//whatever just do it
|
||||||
|
session.debug_raycast_print_model_id_if_changed(ins.time);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,29 @@ fn vs_entity_texture(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@group(1)
|
||||||
|
@binding(0)
|
||||||
|
var<uniform> model_instance: ModelInstance;
|
||||||
|
|
||||||
|
struct DebugEntityOutput {
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
@location(1) normal: vec3<f32>,
|
||||||
|
@location(2) view: vec3<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_debug(
|
||||||
|
@location(0) pos: vec3<f32>,
|
||||||
|
@location(1) normal: vec3<f32>,
|
||||||
|
) -> DebugEntityOutput {
|
||||||
|
var position: vec4<f32> = model_instance.transform * vec4<f32>(pos, 1.0);
|
||||||
|
var result: DebugEntityOutput;
|
||||||
|
result.normal = model_instance.normal_transform * normal;
|
||||||
|
result.view = position.xyz - camera.view_inv[3].xyz;//col(3)
|
||||||
|
result.position = camera.proj * camera.view * position;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//group 2 is the skybox texture
|
//group 2 is the skybox texture
|
||||||
@group(1)
|
@group(1)
|
||||||
@binding(0)
|
@binding(0)
|
||||||
@@ -110,3 +133,8 @@ fn fs_entity_texture(vertex: EntityOutputTexture) -> @location(0) vec4<f32> {
|
|||||||
let reflected_color = textureSample(cube_texture, cube_sampler, reflected).rgb;
|
let reflected_color = textureSample(cube_texture, cube_sampler, reflected).rgb;
|
||||||
return mix(vec4<f32>(vec3<f32>(0.05) + 0.2 * reflected_color,1.0),mix(vertex.model_color,vec4<f32>(fragment_color.rgb,1.0),fragment_color.a),0.5+0.5*abs(d));
|
return mix(vec4<f32>(vec3<f32>(0.05) + 0.2 * reflected_color,1.0),mix(vertex.model_color,vec4<f32>(fragment_color.rgb,1.0),fragment_color.a),0.5+0.5*abs(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_debug(vertex: DebugEntityOutput) -> @location(0) vec4<f32> {
|
||||||
|
return model_instance.color;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user