Add celestial body

This commit is contained in:
hodasemi 2025-03-13 22:09:11 +01:00
parent c1c29efcf0
commit 363ab111bc
4 changed files with 206 additions and 9 deletions

View file

@ -6,6 +6,7 @@ edition = "2024"
[dependencies]
anyhow.workspace = true
ecs.workspace = true
hexasphere = "15.1.0"
engine = { path = "../../engine" }
skybox = { path = "../../skybox" }

View file

@ -0,0 +1,192 @@
use std::time::Duration;
use anyhow::Result;
use ecs::*;
use engine::prelude::{
cgmath::{Matrix4, Vector3},
*,
};
use hexasphere::shapes::IcoSphere;
pub struct CelestialObject;
impl CelestialObject {
pub fn new(
world: &mut World,
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)?]);
draw.set_transform(celestial_settings.model_matrix())?;
entity_object.insert_component(draw);
entity_object.insert_component(celestial_settings);
if let Some(e) = celestial_reference.into() {
entity_object.insert_component(CelestialReference { entity: e });
}
Ok(entity_object)
}
fn create_asset(world: &World, subdivisions: usize) -> Result<AssetMesh> {
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 buffer = {
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
))?;
Buffer::builder()
.set_memory_usage(MemoryUsage::CpuToGpu)
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
.set_data(
&Self::create_sphere(subdivisions)
.into_iter()
.map(|(v, n)| PositionNormal::new(v, n))
.collect::<Vec<_>>(),
)
.build(context.device().clone())?
.into_device_local(
&mut recorder,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
)?
};
// submit
let submit = SubmitInfo::default().add_command_buffer(&command_buffer);
let fence = Fence::builder().build(context.device().clone())?;
context
.queue()
.lock()
.unwrap()
.submit(Some(&fence), &[submit])?;
context
.device()
.wait_for_fences(&[&fence], true, Duration::from_secs(1))?;
let mut asset_mesh = AssetMesh::new(context.device(), scene.render_type())?;
asset_mesh.add_primitive(
buffer,
None,
None,
PrimitiveMaterial {
emissive_factor: [0.65, 0.65, 0.65],
metallic_factor: 0.5,
roughness_factor: 0.7,
..PrimitiveMaterial::default()
},
false,
)?;
Ok(asset_mesh)
}
fn create_sphere(subdivisions: usize) -> Vec<(Vector3<f32>, Vector3<f32>)> {
let sphere = IcoSphere::new(subdivisions, |_| ());
let points = sphere
.raw_points()
.into_iter()
.map(|v| Vector3::from(v.to_array()))
.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];
let v1 = p1 - p2;
let v2 = p1 - p3;
let n = v2.cross(v1);
[(p1, n), (p2, n), (p3, n)]
})
.flatten()
.collect()
}
}
#[derive(Debug)]
pub struct CelestialObjectSettings {
pub location: Vector3<f32>,
pub radius: f32,
pub density: f32,
pub velocity: f32,
last_update: Duration,
}
impl CelestialObjectSettings {
fn model_matrix(&self) -> Matrix4<f32> {
Matrix4::from_translation(self.location) * Matrix4::from_scale(self.radius)
}
pub fn update(
&mut self,
now: Duration,
draw: &Draw,
celestial_object_settings_reference: &CelestialObjectSettings,
) -> Result<()> {
Ok(())
}
}
impl Default for CelestialObjectSettings {
fn default() -> Self {
Self {
location: Vector3::zero(),
radius: 1.0,
density: 1.0,
velocity: 0.0,
last_update: Duration::default(),
}
}
}
impl EntityComponent for CelestialObjectSettings {
fn name(&self) -> &str {
Self::debug_name()
}
}
impl ComponentDebug for CelestialObjectSettings {
fn debug_name() -> &'static str {
"CelestialObjectSettings"
}
}
#[derive(Debug)]
pub struct CelestialReference {
pub entity: Entity,
}
impl EntityComponent for CelestialReference {
fn name(&self) -> &str {
Self::debug_name()
}
}
impl ComponentDebug for CelestialReference {
fn debug_name() -> &'static str {
"CelestialReference"
}
}

View file

@ -8,7 +8,7 @@ use engine::prelude::{
*,
};
use crate::FREE_CAMERA_CONTROL;
use crate::{FREE_CAMERA_CONTROL, celestial_object::CelestialObject};
#[derive(Clone, Copy, Debug)]
struct PlayerEntity(Entity);
@ -268,16 +268,19 @@ impl Game {
}
pub fn setup_scene(world: &mut World) -> Result<()> {
let mut fighter = AssetHandler::create(world).create_entity("fighter_edited")?;
fighter.insert_component(FreeSpaceControl::new(
0.02,
FreeSpaceControlSettings::default(),
));
// let mut fighter = AssetHandler::create(world).create_entity("fighter_edited")?;
// fighter.insert_component(FreeSpaceControl::new(
// 0.02,
// FreeSpaceControlSettings::default(),
// ));
let player = PlayerEntity(world.add_entity(fighter)?);
world.resources.insert(player);
// let player = PlayerEntity(world.add_entity(fighter)?);
// world.resources.insert(player);
world.resources.insert(InputSettings::default());
let example_planet = CelestialObject::new(world, 5, None)?;
world.add_entity(example_planet)?;
let context = world.resources.get::<Context>();
let mut light = Light::point_light(context.device())?;
light.set_position(vec3(10_000.0, 10_000.0, 10_000.0))?;

View file

@ -1,3 +1,4 @@
mod celestial_object;
mod game;
mod game_state;
@ -11,7 +12,7 @@ use game::Game;
use game_state::GameState;
use skybox::SkyBox;
const FREE_CAMERA_CONTROL: bool = false;
const FREE_CAMERA_CONTROL: bool = true;
fn main() -> Result<()> {
let mut world_builder = World::builder();