116 lines
3.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use bevy::asset::RenderAssetUsages;
use bevy::pbr::wireframe::{Wireframe, WireframeColor};
use bevy::prelude::*;
use bevy::render::mesh::*;
use big_space::floating_origins::FloatingOrigin;
use big_space::prelude::GridCell;
use noise::{Fbm, NoiseFn, Perlin};
use crate::plugins::big_space::big_space_plugin::RootGrid;
use crate::plugins::environment::systems::camera_system::CameraController;
#[derive(Component)]
pub struct PlanetMaker;
#[derive(Resource)]
pub struct PlanetNoise(pub Fbm<Perlin>);
pub fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
root: Res<RootGrid>,
) {
// Diameter ~ Earth (~12,742 km) × 2 to exaggerate terrain if desired
let radius = 12_742_000.0;
let sphere_mesh = meshes.add(
SphereMeshBuilder::new(radius, SphereKind::Ico { subdivisions: 100 })
.build(),
);
let material_handle = materials.add(StandardMaterial::from(Color::rgb(0.3, 0.6, 1.0)));
commands.entity(root.0).with_children(|parent| {
parent.spawn((
Name::new("Planet"),
Mesh3d(sphere_mesh.clone()),
MeshMaterial3d(material_handle),
GridCell::<i64>::ZERO,
Transform::default(),
PlanetMaker,
Wireframe,
));
});
}
pub(crate) fn setup_noise(mut commands: Commands) {
let fbm_noise = Fbm::<Perlin>::new(0);
commands.insert_resource(PlanetNoise(fbm_noise));
}
pub fn deform_planet(
mut meshes: ResMut<Assets<Mesh>>,
noise: Res<PlanetNoise>,
query: Query<&Mesh3d, With<PlanetMaker>>,
) {
let frequency = 4.0 / 12_742_000.0;
let amplitude = 100_000.0;
for mesh3d in query.iter() {
let handle: &Handle<Mesh> = &mesh3d.0;
if let Some(mesh) = meshes.get_mut(handle) {
// 1. Immutable borrow to extract normals (or default)
let normals: Vec<[f32; 3]> = if let Some(VertexAttributeValues::Float32x3(vals)) =
mesh.attribute(Mesh::ATTRIBUTE_NORMAL)
{
vals.clone()
} else {
// default normals if none exist
let count = mesh
.attribute(Mesh::ATTRIBUTE_POSITION)
.and_then(|attr| match attr {
VertexAttributeValues::Float32x3(v) => Some(v.len()),
_ => None,
})
.unwrap_or(0);
vec![[0.0, 1.0, 0.0]; count]
};
// 2. Drop the immutable borrow, then mutable-borrow positions
if let Some(VertexAttributeValues::Float32x3(positions)) =
mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION)
{
// Now mutate positions using the pre-fetched normals
for (i, pos) in positions.iter_mut().enumerate() {
let mut vertex = Vec3::new(pos[0], pos[1], pos[2]);
let normal = Vec3::new(
normals[i][0],
normals[i][1],
normals[i][2],
);
let unit_dir = vertex.normalize();
let sample = [
unit_dir.x as f64 * frequency as f64,
unit_dir.y as f64 * frequency as f64,
unit_dir.z as f64 * frequency as f64,
];
let noise_value = noise.0.get(sample) as f32;
let offset = normal * (noise_value * amplitude);
let new_pos = unit_dir * (vertex.length() + offset.length());
*pos = [new_pos.x, new_pos.y, new_pos.z];
}
mesh.compute_smooth_normals();
}
// Force AABB recalc
mesh.remove_attribute(Mesh::ATTRIBUTE_COLOR);
}
}
}