Manually construct Mesh from IcoSphere to do noise displacement.
This commit is contained in:
parent
8000f1f5b8
commit
212d9daac9
3 changed files with 78 additions and 6 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1066,8 +1066,10 @@ dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_polyline",
|
"bevy_polyline",
|
||||||
"bevy_rapier3d",
|
"bevy_rapier3d",
|
||||||
|
"hexasphere",
|
||||||
"noise",
|
"noise",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
"wgpu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -7,6 +7,8 @@ edition = "2021"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
bevy_polyline = "0.1"
|
bevy_polyline = "0.1"
|
||||||
noise = { git = "https://github.com/Razaekel/noise-rs" }
|
noise = { git = "https://github.com/Razaekel/noise-rs" }
|
||||||
|
hexasphere = "6.0.0"
|
||||||
|
wgpu = "0.12.0"
|
||||||
|
|
||||||
[dependencies.bevy]
|
[dependencies.bevy]
|
||||||
version = "0.6"
|
version = "0.6"
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
use bevy::prelude::*;
|
use bevy::{
|
||||||
|
prelude::{shape::Icosphere, *},
|
||||||
|
render::mesh::Indices,
|
||||||
|
};
|
||||||
|
use hexasphere::shapes::IcoSphere;
|
||||||
|
use noise::{HybridMulti, NoiseFn, Perlin};
|
||||||
|
use wgpu::PrimitiveTopology;
|
||||||
|
|
||||||
use crate::Label;
|
use crate::Label;
|
||||||
|
|
||||||
|
@ -17,13 +23,18 @@ fn spawn_giant_sphere(
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
let mut color = Color::DARK_GRAY;
|
let mut color = Color::DARK_GRAY;
|
||||||
color.set_a(0.8);
|
color.set_a(0.92);
|
||||||
|
|
||||||
|
let isphere = shape::Icosphere {
|
||||||
|
radius: PLANET_RADIUS,
|
||||||
|
subdivisions: 26,
|
||||||
|
};
|
||||||
|
|
||||||
|
let pmesh = gen_planet(isphere);
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn_bundle(PbrBundle {
|
.spawn_bundle(PbrBundle {
|
||||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
mesh: meshes.add(pmesh),
|
||||||
radius: PLANET_RADIUS,
|
|
||||||
subdivisions: 24,
|
|
||||||
})),
|
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: color,
|
base_color: color,
|
||||||
metallic: 0.65,
|
metallic: 0.65,
|
||||||
|
@ -60,3 +71,60 @@ impl Plugin for CyberGeomPlugin {
|
||||||
.add_startup_system(spawn_cyberbike.label(Label::Geometry));
|
.add_startup_system(spawn_cyberbike.label(Label::Geometry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// utils
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn gen_planet(sphere: Icosphere) -> Mesh {
|
||||||
|
// straight-up stolen from Bevy's impl of Mesh from Icosphere, so I can do the
|
||||||
|
// displacement before normals are calculated.
|
||||||
|
let generated = IcoSphere::new(sphere.subdivisions, |point| {
|
||||||
|
let inclination = point.y.acos();
|
||||||
|
let azimuth = point.z.atan2(point.x);
|
||||||
|
|
||||||
|
let norm_inclination = inclination / std::f32::consts::PI;
|
||||||
|
let norm_azimuth = 0.5 - (azimuth / std::f32::consts::TAU);
|
||||||
|
|
||||||
|
[norm_azimuth, norm_inclination]
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: use displaced points for normals by replacing raw_points with
|
||||||
|
// noise-displaced points.
|
||||||
|
let noise = HybridMulti::<Perlin>::default();
|
||||||
|
let raw_points = generated.raw_points();
|
||||||
|
|
||||||
|
let points = raw_points
|
||||||
|
.iter()
|
||||||
|
.map(|&p| {
|
||||||
|
let pt = p * sphere.radius;
|
||||||
|
let disp = noise.get(pt.as_dvec3().into()) as f32;
|
||||||
|
let disp = p * disp * 20.0;
|
||||||
|
let pt = pt + disp;
|
||||||
|
pt.into()
|
||||||
|
})
|
||||||
|
.collect::<Vec<[f32; 3]>>();
|
||||||
|
|
||||||
|
let normals = raw_points
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<[f32; 3]>>();
|
||||||
|
|
||||||
|
let uvs = generated.raw_data().to_owned();
|
||||||
|
|
||||||
|
let mut indices = Vec::with_capacity(generated.indices_per_main_triangle() * 20);
|
||||||
|
|
||||||
|
for i in 0..20 {
|
||||||
|
generated.get_indices(i, &mut indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
let indices = Indices::U32(indices);
|
||||||
|
|
||||||
|
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
|
||||||
|
mesh.set_indices(Some(indices));
|
||||||
|
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, points);
|
||||||
|
mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
|
||||||
|
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
|
||||||
|
mesh
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue