193 lines
5.1 KiB
Rust
193 lines
5.1 KiB
Rust
|
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"
|
||
|
}
|
||
|
}
|