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
engine/src/scene
content/components
rendering/shaders/raytracing/hardware/default
examples/free_space/src

View file

@ -12,6 +12,23 @@ pub struct 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 {
self.min[0] == 0.0
&& self.min[1] == 0.0

View file

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

View file

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

View file

@ -1,3 +1,4 @@
use core::f32;
use std::time::Duration;
use anyhow::Result;
@ -8,21 +9,57 @@ use engine::prelude::{
};
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;
impl CelestialObject {
pub fn new(
world: &mut World,
class: CelestialClass,
subdivisions: usize,
celestial_reference: impl Into<Option<Entity>>,
) -> Result<EntityObject> {
let mut entity_object = AssetHandler::create(world).empty_entity();
let celestial_settings = CelestialObjectSettings::default();
let draw = Draw::new(vec![Self::create_asset(world, subdivisions)?]);
let mut celestial_settings = CelestialObjectSettings::default();
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())?;
entity_object.insert_component(draw);
entity_object.insert_component(bounding_box);
entity_object.insert_component(celestial_settings);
if let Some(e) = celestial_reference.into() {
@ -32,13 +69,19 @@ impl CelestialObject {
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 scene = world.resources.get::<Scene>();
let command_buffer = CommandBuffer::new_primary()
.build(context.device().clone(), context.queue().clone())?;
let (sphere, bounding_box) = Self::create_sphere(subdivisions);
let buffer = {
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
@ -48,7 +91,7 @@ impl CelestialObject {
.set_memory_usage(MemoryUsage::CpuToGpu)
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
.set_data(
&Self::create_sphere(subdivisions)
&sphere
.into_iter()
.map(|(v, n)| PositionNormal::new(v, n))
.collect::<Vec<_>>(),
@ -83,6 +126,7 @@ impl CelestialObject {
None,
None,
PrimitiveMaterial {
color: class.color(),
emissive_factor: [0.65, 0.65, 0.65],
metallic_factor: 0.5,
roughness_factor: 0.7,
@ -92,35 +136,44 @@ impl CelestialObject {
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 points = sphere
.raw_points()
.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>>>();
sphere
.get_all_indices()
.chunks(3)
.map(|triangle| {
let p1 = points[triangle[0] as usize];
let p2 = points[triangle[1] as usize];
let p3 = points[triangle[2] as usize];
(
sphere
.get_all_indices()
.chunks(3)
.map(|triangle| {
let p1 = points[triangle[0] as usize];
let p2 = points[triangle[1] as usize];
let p3 = points[triangle[2] as usize];
let v1 = p1 - p2;
let v2 = p1 - p3;
let v1 = p1 - p2;
let v2 = p1 - p3;
let n = v2.cross(v1);
let n = v2.cross(v1);
[(p1, n), (p2, n), (p3, n)]
})
.flatten()
.collect()
[(p1, n), (p2, n), (p3, n)]
})
.flatten()
.collect(),
bounding_box,
)
}
}
@ -135,8 +188,18 @@ pub struct CelestialObjectSettings {
}
impl CelestialObjectSettings {
fn model_matrix(&self) -> Matrix4<f32> {
Matrix4::from_translation(self.location) * Matrix4::from_scale(self.radius)
const SCALE: f32 = 0.5;
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(
@ -145,6 +208,10 @@ impl CelestialObjectSettings {
draw: &Draw,
celestial_object_settings_reference: &CelestialObjectSettings,
) -> Result<()> {
self.last_update = now;
// TODO: velocity calculation around celestial reference
Ok(())
}
}
@ -153,7 +220,7 @@ impl Default for CelestialObjectSettings {
fn default() -> Self {
Self {
location: Vector3::zero(),
radius: 1.0,
radius: 2.0,
density: 1.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)]
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(
"celestial velocity update",
100,
Self::celestial_velocity_update,
(EmptyFilter, EmptyFilter),
)?;
world_builder.add_update(
"celestial buffer update",
110,
Self::celestial_buffer_update,
EmptyFilter,
)?;
Ok(())
}
@ -278,7 +297,16 @@ impl Game {
// world.resources.insert(player);
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)?;
let context = world.resources.get::<Context>();
@ -325,4 +353,32 @@ impl Game {
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(())
}
}