Add some bodies

This commit is contained in:
hodasemi 2025-03-14 13:25:11 +01:00
parent 363ab111bc
commit 402a1b8ddf
5 changed files with 169 additions and 29 deletions

View file

@ -12,6 +12,23 @@ pub struct BoundingBox {
} }
impl BoundingBox { impl BoundingBox {
pub fn init() -> Self {
Self {
min: [f32::INFINITY; 3],
max: [-f32::INFINITY; 3],
}
}
pub fn check(&mut self, v: Vector3<f32>) {
self.min[0] = self.min[0].min(v.x);
self.min[1] = self.min[1].min(v.y);
self.min[2] = self.min[2].min(v.z);
self.max[0] = self.max[0].max(v.x);
self.max[1] = self.max[1].max(v.y);
self.max[2] = self.max[2].max(v.z);
}
pub fn is_zero(&self) -> bool { pub fn is_zero(&self) -> bool {
self.min[0] == 0.0 self.min[0] == 0.0
&& self.min[1] == 0.0 && self.min[1] == 0.0

View file

@ -111,7 +111,7 @@ void own_implementation() {
int miss_shader_index = 0; int miss_shader_index = 0;
int sbt_record_stride = 0; int sbt_record_stride = 0;
float tmin = 0.001; float tmin = 0.001;
float tmax = 10000.0; float tmax = 1000000000.0;
vec3 direction = reflect(gl_WorldRayDirectionEXT, normal); vec3 direction = reflect(gl_WorldRayDirectionEXT, normal);
@ -145,7 +145,7 @@ void own_implementation() {
int miss_shader_index = 0; int miss_shader_index = 0;
int sbt_record_stride = 0; int sbt_record_stride = 0;
float tmin = 0.001; float tmin = 0.001;
float tmax = 10000.0; float tmax = 1000000000.0;
pay_load.depth++; pay_load.depth++;

View file

@ -41,7 +41,7 @@ void main()
int miss_shader_index = 0; int miss_shader_index = 0;
int sbt_record_stride = 0; int sbt_record_stride = 0;
float tmin = 0.001; float tmin = 0.001;
float tmax = 10000.0; float tmax = 1000000000.0;
pay_load.depth = 0; pay_load.depth = 0;

View file

@ -1,3 +1,4 @@
use core::f32;
use std::time::Duration; use std::time::Duration;
use anyhow::Result; use anyhow::Result;
@ -8,21 +9,57 @@ use engine::prelude::{
}; };
use hexasphere::shapes::IcoSphere; use hexasphere::shapes::IcoSphere;
#[derive(Clone, Copy, Debug)]
pub enum CelestialClass {
Sun,
Solid,
Gas,
}
impl CelestialClass {
/// in g/cm³
pub fn density(&self) -> f32 {
match self {
// our sun
CelestialClass::Sun => 1.41,
// earth
CelestialClass::Solid => 5.51,
// saturn
CelestialClass::Gas => 0.69,
}
}
pub fn color(&self) -> [f32; 4] {
match self {
CelestialClass::Sun => Color::Yellow.into(),
CelestialClass::Solid => Color::Green.into(),
CelestialClass::Gas => Color::Orange.into(),
}
}
}
pub struct CelestialObject; pub struct CelestialObject;
impl CelestialObject { impl CelestialObject {
pub fn new( pub fn new(
world: &mut World, world: &mut World,
class: CelestialClass,
subdivisions: usize, subdivisions: usize,
celestial_reference: impl Into<Option<Entity>>, celestial_reference: impl Into<Option<Entity>>,
) -> Result<EntityObject> { ) -> Result<EntityObject> {
let mut entity_object = AssetHandler::create(world).empty_entity(); let mut entity_object = AssetHandler::create(world).empty_entity();
let celestial_settings = CelestialObjectSettings::default(); let mut celestial_settings = CelestialObjectSettings::default();
let draw = Draw::new(vec![Self::create_asset(world, subdivisions)?]); celestial_settings.density = class.density();
let (mesh, bounding_box) = Self::create_asset(world, class, subdivisions)?;
let draw = Draw::new(vec![mesh]);
draw.set_transform(celestial_settings.model_matrix())?; draw.set_transform(celestial_settings.model_matrix())?;
entity_object.insert_component(draw); entity_object.insert_component(draw);
entity_object.insert_component(bounding_box);
entity_object.insert_component(celestial_settings); entity_object.insert_component(celestial_settings);
if let Some(e) = celestial_reference.into() { if let Some(e) = celestial_reference.into() {
@ -32,13 +69,19 @@ impl CelestialObject {
Ok(entity_object) Ok(entity_object)
} }
fn create_asset(world: &World, subdivisions: usize) -> Result<AssetMesh> { fn create_asset(
world: &World,
class: CelestialClass,
subdivisions: usize,
) -> Result<(AssetMesh, BoundingBox)> {
let context = world.resources.get::<Context>(); let context = world.resources.get::<Context>();
let scene = world.resources.get::<Scene>(); let scene = world.resources.get::<Scene>();
let command_buffer = CommandBuffer::new_primary() let command_buffer = CommandBuffer::new_primary()
.build(context.device().clone(), context.queue().clone())?; .build(context.device().clone(), context.queue().clone())?;
let (sphere, bounding_box) = Self::create_sphere(subdivisions);
let buffer = { let buffer = {
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new( let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
@ -48,7 +91,7 @@ impl CelestialObject {
.set_memory_usage(MemoryUsage::CpuToGpu) .set_memory_usage(MemoryUsage::CpuToGpu)
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT) .set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
.set_data( .set_data(
&Self::create_sphere(subdivisions) &sphere
.into_iter() .into_iter()
.map(|(v, n)| PositionNormal::new(v, n)) .map(|(v, n)| PositionNormal::new(v, n))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
@ -83,6 +126,7 @@ impl CelestialObject {
None, None,
None, None,
PrimitiveMaterial { PrimitiveMaterial {
color: class.color(),
emissive_factor: [0.65, 0.65, 0.65], emissive_factor: [0.65, 0.65, 0.65],
metallic_factor: 0.5, metallic_factor: 0.5,
roughness_factor: 0.7, roughness_factor: 0.7,
@ -92,35 +136,44 @@ impl CelestialObject {
false, false,
)?; )?;
Ok(asset_mesh) Ok((asset_mesh, bounding_box))
} }
fn create_sphere(subdivisions: usize) -> Vec<(Vector3<f32>, Vector3<f32>)> { fn create_sphere(subdivisions: usize) -> (Vec<(Vector3<f32>, Vector3<f32>)>, BoundingBox) {
let mut bounding_box = BoundingBox::init();
let sphere = IcoSphere::new(subdivisions, |_| ()); let sphere = IcoSphere::new(subdivisions, |_| ());
let points = sphere let points = sphere
.raw_points() .raw_points()
.into_iter() .into_iter()
.map(|v| Vector3::from(v.to_array())) .map(|v| {
let v = Vector3::from(v.to_array());
bounding_box.check(v);
v
})
.collect::<Vec<Vector3<f32>>>(); .collect::<Vec<Vector3<f32>>>();
sphere (
.get_all_indices() sphere
.chunks(3) .get_all_indices()
.map(|triangle| { .chunks(3)
let p1 = points[triangle[0] as usize]; .map(|triangle| {
let p2 = points[triangle[1] as usize]; let p1 = points[triangle[0] as usize];
let p3 = points[triangle[2] as usize]; let p2 = points[triangle[1] as usize];
let p3 = points[triangle[2] as usize];
let v1 = p1 - p2; let v1 = p1 - p2;
let v2 = p1 - p3; let v2 = p1 - p3;
let n = v2.cross(v1); let n = v2.cross(v1);
[(p1, n), (p2, n), (p3, n)] [(p1, n), (p2, n), (p3, n)]
}) })
.flatten() .flatten()
.collect() .collect(),
bounding_box,
)
} }
} }
@ -135,8 +188,18 @@ pub struct CelestialObjectSettings {
} }
impl CelestialObjectSettings { impl CelestialObjectSettings {
fn model_matrix(&self) -> Matrix4<f32> { const SCALE: f32 = 0.5;
Matrix4::from_translation(self.location) * Matrix4::from_scale(self.radius)
fn volume(&self) -> f32 {
(4.0 / 3.0) * f32::consts::PI * self.radius.powi(3)
}
fn mass(&self) -> f32 {
self.volume() * self.density
}
pub fn model_matrix(&self) -> Matrix4<f32> {
Matrix4::from_translation(self.location) * Matrix4::from_scale(self.radius * Self::SCALE)
} }
pub fn update( pub fn update(
@ -145,6 +208,10 @@ impl CelestialObjectSettings {
draw: &Draw, draw: &Draw,
celestial_object_settings_reference: &CelestialObjectSettings, celestial_object_settings_reference: &CelestialObjectSettings,
) -> Result<()> { ) -> Result<()> {
self.last_update = now;
// TODO: velocity calculation around celestial reference
Ok(()) Ok(())
} }
} }
@ -153,7 +220,7 @@ impl Default for CelestialObjectSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
location: Vector3::zero(), location: Vector3::zero(),
radius: 1.0, radius: 2.0,
density: 1.0, density: 1.0,
velocity: 0.0, velocity: 0.0,

View file

@ -8,7 +8,12 @@ use engine::prelude::{
*, *,
}; };
use crate::{FREE_CAMERA_CONTROL, celestial_object::CelestialObject}; use crate::{
FREE_CAMERA_CONTROL,
celestial_object::{
CelestialClass, CelestialObject, CelestialObjectSettings, CelestialReference,
},
};
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
struct PlayerEntity(Entity); struct PlayerEntity(Entity);
@ -264,6 +269,20 @@ impl Game {
world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?; world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?;
} }
world_builder.add_update(
"celestial velocity update",
100,
Self::celestial_velocity_update,
(EmptyFilter, EmptyFilter),
)?;
world_builder.add_update(
"celestial buffer update",
110,
Self::celestial_buffer_update,
EmptyFilter,
)?;
Ok(()) Ok(())
} }
@ -278,7 +297,16 @@ impl Game {
// world.resources.insert(player); // world.resources.insert(player);
world.resources.insert(InputSettings::default()); world.resources.insert(InputSettings::default());
let example_planet = CelestialObject::new(world, 5, None)?; let mut example_sun = CelestialObject::new(world, CelestialClass::Sun, 5, None)?;
let sun_settings = example_sun.get_component_mut::<CelestialObjectSettings>()?;
sun_settings.location = vec3(10_000.0, 10_000.0, 0.0);
sun_settings.radius = 1_000.0;
let sun_entity = world.add_entity(example_sun)?;
let mut example_planet = CelestialObject::new(world, CelestialClass::Solid, 5, sun_entity)?;
let sun_settings = example_planet.get_component_mut::<CelestialObjectSettings>()?;
sun_settings.location.x = 1000.0;
sun_settings.radius = 250.0;
world.add_entity(example_planet)?; world.add_entity(example_planet)?;
let context = world.resources.get::<Context>(); let context = world.resources.get::<Context>();
@ -325,4 +353,32 @@ impl Game {
view.update_buffer() view.update_buffer()
} }
fn celestial_buffer_update(
_: &mut World,
_: Entity,
draw: &mut Draw,
control: &mut CelestialObjectSettings,
) -> Result<()> {
draw.set_transform(control.model_matrix())?;
Ok(())
}
fn celestial_velocity_update(
world: &mut World,
(_, draw, lhs_control, reference): (
Entity,
&mut Draw,
&mut CelestialObjectSettings,
&mut CelestialReference,
),
(rhs_entity, rhs_control): (Entity, &mut CelestialObjectSettings),
) -> Result<()> {
if reference.entity == rhs_entity {
lhs_control.update(world.now(), draw, rhs_control)?;
}
Ok(())
}
} }