mesh generation
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -13,7 +13,7 @@
|
|||||||
"program": "${workspaceRoot}/target/debug/phos.exe",
|
"program": "${workspaceRoot}/target/debug/phos.exe",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "Build",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
16
.vscode/tasks.json
vendored
16
.vscode/tasks.json
vendored
@@ -3,13 +3,15 @@
|
|||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command":"build",
|
"command": "",
|
||||||
"args":[],
|
"args": [
|
||||||
"group": {
|
"build"
|
||||||
"kind": "build",
|
],
|
||||||
"isDefault": true
|
"problemMatcher": [
|
||||||
},
|
"$rustc"
|
||||||
"label":"build"
|
],
|
||||||
|
"group": "build",
|
||||||
|
"label": "Build"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -2271,6 +2271,15 @@ version = "1.0.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iyes_perf_ui"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a49f5aa5866dadfdd274c45eddc0a94c84ad1ce0c02c27bcb33c34a20b961f9e"
|
||||||
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
@@ -2892,7 +2901,9 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy-inspector-egui",
|
"bevy-inspector-egui",
|
||||||
|
"iyes_perf_ui",
|
||||||
"noise 0.8.2",
|
"noise 0.8.2",
|
||||||
|
"world_generation",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4274,6 +4285,7 @@ dependencies = [
|
|||||||
name = "world_generation"
|
name = "world_generation"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
"noise 0.9.0",
|
"noise 0.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy = "0.13.1"
|
||||||
noise = "0.9.0"
|
noise = "0.9.0"
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
pub struct GenerationConfig {
|
|
||||||
pub noise_scale: f64,
|
|
||||||
pub sea_level: f64,
|
|
||||||
pub layers: Vec<GeneratorLayer>,
|
|
||||||
}
|
|
||||||
pub struct GeneratorLayer {
|
|
||||||
pub strength: f64,
|
|
||||||
pub min_value: f64,
|
|
||||||
pub base_roughness: f64,
|
|
||||||
pub roughness: f64,
|
|
||||||
pub persistence: f64,
|
|
||||||
pub is_rigid: bool,
|
|
||||||
pub weight: f64,
|
|
||||||
pub weight_multi: f64,
|
|
||||||
pub layers: usize,
|
|
||||||
pub first_layer_mask: bool,
|
|
||||||
}
|
|
||||||
pub struct Chunk {
|
|
||||||
pub points: Vec<f32>,
|
|
||||||
pub size: usize,
|
|
||||||
}
|
|
||||||
pub struct Map {
|
|
||||||
pub chunks: Vec<Chunk>,
|
|
||||||
pub height: usize,
|
|
||||||
pub width: usize,
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
mod data;
|
use crate::prelude::*;
|
||||||
use data::*;
|
use bevy::math::IVec2;
|
||||||
|
use noise::{NoiseFn, SuperSimplex};
|
||||||
|
|
||||||
pub fn generate_heightmap(
|
pub fn generate_heightmap(height: usize, width: usize, cfg: &GenerationConfig, seed: u32) -> Map {
|
||||||
height: usize,
|
|
||||||
width: usize,
|
|
||||||
cfg: &GenerationConfig,
|
|
||||||
seed: u32,
|
|
||||||
) -> Map {
|
|
||||||
let mut chunks: Vec<Chunk> = Vec::with_capacity(height * width);
|
let mut chunks: Vec<Chunk> = Vec::with_capacity(height * width);
|
||||||
for z in 0..height {
|
for z in 0..height {
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
@@ -42,6 +38,7 @@ pub fn generate_chunk(
|
|||||||
return Chunk {
|
return Chunk {
|
||||||
points: result,
|
points: result,
|
||||||
size: size,
|
size: size,
|
||||||
|
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
engine/world_generation/src/hex_utils.rs
Normal file
10
engine/world_generation/src/hex_utils.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub const OUTER_RADIUS: f32 = 1.;
|
||||||
|
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn to_hex_pos(pos: Vec3) -> Vec3 {
|
||||||
|
let x = (pos.x + pos.z * 0.5 - (pos.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
||||||
|
return Vec3::new(x, pos.y, pos.z * OUTER_RADIUS * 1.5);
|
||||||
|
}
|
||||||
@@ -1,9 +1,38 @@
|
|||||||
|
pub mod prelude {
|
||||||
|
use bevy::math::IVec2;
|
||||||
|
|
||||||
use noise::{NoiseFn, SuperSimplex};
|
pub struct GenerationConfig {
|
||||||
|
pub noise_scale: f64,
|
||||||
|
pub sea_level: f64,
|
||||||
|
pub layers: Vec<GeneratorLayer>,
|
||||||
|
}
|
||||||
|
pub struct GeneratorLayer {
|
||||||
|
pub strength: f64,
|
||||||
|
pub min_value: f64,
|
||||||
|
pub base_roughness: f64,
|
||||||
|
pub roughness: f64,
|
||||||
|
pub persistence: f64,
|
||||||
|
pub is_rigid: bool,
|
||||||
|
pub weight: f64,
|
||||||
|
pub weight_multi: f64,
|
||||||
|
pub layers: usize,
|
||||||
|
pub first_layer_mask: bool,
|
||||||
|
}
|
||||||
|
pub struct Chunk {
|
||||||
|
pub points: Vec<f32>,
|
||||||
|
pub size: usize,
|
||||||
|
pub chunk_offset: IVec2,
|
||||||
|
}
|
||||||
|
pub struct Map {
|
||||||
|
pub chunks: Vec<Chunk>,
|
||||||
|
pub height: usize,
|
||||||
|
pub width: usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod heightmap;
|
||||||
|
pub mod hex_utils;
|
||||||
|
pub mod mesh_generator;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
@@ -1,6 +1,73 @@
|
|||||||
mod data;
|
use crate::{
|
||||||
use data::Chunk;
|
hex_utils::{to_hex_pos, INNER_RADIUS, OUTER_RADIUS},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
use bevy::{
|
||||||
|
prelude::*,
|
||||||
|
render::{
|
||||||
|
mesh::{Indices, PrimitiveTopology},
|
||||||
|
render_asset::RenderAssetUsages,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn generate_chunk_mesh(chunk: &Chunk){
|
const HEX_CORNERS: [Vec3; 6] = [
|
||||||
|
Vec3::new(0., 0., OUTER_RADIUS),
|
||||||
|
Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(0., 0., -OUTER_RADIUS),
|
||||||
|
Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
|
||||||
|
let vertex_count: usize = chunk.size * chunk.size;
|
||||||
|
let mut verts = Vec::with_capacity(vertex_count);
|
||||||
|
let mut uvs = Vec::with_capacity(vertex_count);
|
||||||
|
let mut normals = Vec::with_capacity(vertex_count);
|
||||||
|
let mut indices = Vec::with_capacity(vertex_count);
|
||||||
|
|
||||||
|
for z in 0..chunk.size {
|
||||||
|
for x in 0..chunk.size {
|
||||||
|
let height = chunk.points[x + z * chunk.size];
|
||||||
|
let off_pos = Vec3::new(x as f32, height, z as f32);
|
||||||
|
let grid_pos = to_hex_pos(off_pos);
|
||||||
|
create_tile(grid_pos, &mut verts, &mut uvs, &mut normals, &mut indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mesh = Mesh::new(
|
||||||
|
PrimitiveTopology::TriangleList,
|
||||||
|
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
|
||||||
|
)
|
||||||
|
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, verts)
|
||||||
|
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
|
||||||
|
// .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
|
||||||
|
.with_inserted_indices(Indices::U32(indices))
|
||||||
|
.with_duplicated_vertices()
|
||||||
|
.with_computed_flat_normals();
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: figure out texture index
|
||||||
|
fn create_tile(
|
||||||
|
pos: Vec3,
|
||||||
|
verts: &mut Vec<Vec3>,
|
||||||
|
uvs: &mut Vec<Vec2>,
|
||||||
|
normals: &mut Vec<Vec3>,
|
||||||
|
indices: &mut Vec<u32>,
|
||||||
|
) {
|
||||||
|
let idx = verts.len() as u32;
|
||||||
|
let center = Vec3::new(pos.x, 0., pos.z);
|
||||||
|
normals.push(Vec3::Y);
|
||||||
|
uvs.push(pos.xz());
|
||||||
|
verts.push(pos);
|
||||||
|
for i in 0..6 {
|
||||||
|
let p = pos + HEX_CORNERS[i];
|
||||||
|
verts.push(p);
|
||||||
|
uvs.push(p.xz());
|
||||||
|
normals.push((p - center).normalize());
|
||||||
|
indices.push(idx);
|
||||||
|
indices.push(idx + 1 + i as u32);
|
||||||
|
indices.push(idx + 1 + ((i as u32 + 1) % 6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,8 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.13.0"
|
bevy = "0.13.1"
|
||||||
bevy-inspector-egui = "0.23.4"
|
bevy-inspector-egui = "0.23.4"
|
||||||
|
iyes_perf_ui = "0.2.3"
|
||||||
noise = "0.8.2"
|
noise = "0.8.2"
|
||||||
|
world_generation ={path="../../engine/world_generation"}
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
use bevy::{pbr::CascadeShadowConfig, prelude::*};
|
use bevy::{pbr::CascadeShadowConfig, prelude::*};
|
||||||
|
use iyes_perf_ui::prelude::*;
|
||||||
|
use world_generation::{
|
||||||
|
heightmap::generate_heightmap, hex_utils::to_hex_pos, mesh_generator::generate_chunk_mesh,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
pub struct PhosGamePlugin;
|
pub struct PhosGamePlugin;
|
||||||
|
|
||||||
impl Plugin for PhosGamePlugin {
|
impl Plugin for PhosGamePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Startup, init_game);
|
app.add_systems(Startup, init_game)
|
||||||
|
.add_systems(Startup, create_map);
|
||||||
|
app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin)
|
||||||
|
.add_plugins(bevy::diagnostic::EntityCountDiagnosticsPlugin)
|
||||||
|
.add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin)
|
||||||
|
.add_plugins(PerfUiPlugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_game(mut commands: Commands) {
|
fn init_game(mut commands: Commands) {
|
||||||
commands.spawn((
|
commands.spawn((Camera3dBundle {
|
||||||
Camera3dBundle {
|
transform: Transform::from_xyz(-200., 300., -200.)
|
||||||
transform: Transform::from_xyz(0., 50., 0.)
|
.looking_at(Vec3::new(1000., 0., 1000.), Vec3::Y),
|
||||||
.looking_at(Vec3::new(50., 0., 50.), Vec3::Y),
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},));
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
PerfUiRoot::default(),
|
||||||
|
PerfUiEntryFPS::default(),
|
||||||
|
PerfUiEntryClock::default(),
|
||||||
));
|
));
|
||||||
|
|
||||||
commands.spawn(DirectionalLightBundle {
|
commands.spawn(DirectionalLightBundle {
|
||||||
@@ -30,3 +43,50 @@ fn init_game(mut commands: Commands) {
|
|||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_map(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
) {
|
||||||
|
let heightmap = generate_heightmap(
|
||||||
|
32,
|
||||||
|
32,
|
||||||
|
&GenerationConfig {
|
||||||
|
layers: vec![GeneratorLayer {
|
||||||
|
base_roughness: 2.14,
|
||||||
|
roughness: 0.87,
|
||||||
|
strength: 2.93,
|
||||||
|
min_value: -0.2,
|
||||||
|
persistence: 0.77,
|
||||||
|
is_rigid: false,
|
||||||
|
weight: 0.,
|
||||||
|
weight_multi: 0.,
|
||||||
|
layers: 4,
|
||||||
|
first_layer_mask: false,
|
||||||
|
}],
|
||||||
|
noise_scale: 250.,
|
||||||
|
sea_level: 4.,
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
let debug_material = materials.add(StandardMaterial {
|
||||||
|
// base_color_texture: Some(images.add(uv_debug_texture())),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
|
||||||
|
for chunk in heightmap.chunks {
|
||||||
|
let mesh = generate_chunk_mesh(&chunk);
|
||||||
|
let pos = to_hex_pos(
|
||||||
|
Vec3::new(chunk.chunk_offset.x as f32, 0., chunk.chunk_offset.y as f32)
|
||||||
|
* chunk.size as f32,
|
||||||
|
);
|
||||||
|
commands.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(mesh),
|
||||||
|
material: debug_material.clone(),
|
||||||
|
transform: Transform::from_translation(pos),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user