mirror of
https://github.com/eliasstepanik/voxel-simulation.git
synced 2026-01-22 02:58:30 +00:00
Added the possibility for loading textures for voxels.
This commit is contained in:
parent
f5714ff105
commit
d131c4f67a
@ -23,4 +23,4 @@ rayon = "1.10.0"
|
|||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
bevy_app_compute = "0.16"
|
bevy_app_compute = "0.16"
|
||||||
bytemuck = { version = "1.14", features = ["derive"] }
|
bytemuck = { version = "1.14", features = ["derive"] }
|
||||||
|
image = { version = "0.24", default-features = false, features = ["png"] }
|
||||||
|
|||||||
@ -77,7 +77,7 @@ pub fn generate_voxel_sphere_parallel(octree: &mut SparseVoxelOctree, center: Ve
|
|||||||
center.y + iy as f32 * step,
|
center.y + iy as f32 * step,
|
||||||
center.z + iz as f32 * step,
|
center.z + iz as f32 * step,
|
||||||
);
|
);
|
||||||
(pos, Voxel::random_sides())
|
(pos, Voxel::grass_block())
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
@ -115,7 +115,7 @@ fn generate_voxel_sphere(octree: &mut SparseVoxelOctree, planet_radius: i32) {
|
|||||||
let position = Vec3::new(wx, wy, wz);
|
let position = Vec3::new(wx, wy, wz);
|
||||||
|
|
||||||
// Insert the voxel
|
// Insert the voxel
|
||||||
let voxel = Voxel::random_sides();
|
let voxel = Voxel::grass_block();
|
||||||
octree.insert(position, voxel);
|
octree.insert(position, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ fn generate_voxel_rect(octree: &mut SparseVoxelOctree) {
|
|||||||
let position = Vec3::new(wx, wy, wz);
|
let position = Vec3::new(wx, wy, wz);
|
||||||
|
|
||||||
// Insert the voxel
|
// Insert the voxel
|
||||||
let voxel = Voxel::random_sides();
|
let voxel = Voxel::grass_block();
|
||||||
octree.insert(position, voxel);
|
octree.insert(position, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ fn generate_large_plane(octree: &mut SparseVoxelOctree, width: usize, depth: usi
|
|||||||
let position = Vec3::new(wx, wy, wz);
|
let position = Vec3::new(wx, wy, wz);
|
||||||
|
|
||||||
// Insert the voxel
|
// Insert the voxel
|
||||||
let voxel = Voxel::random_sides();
|
let voxel = Voxel::grass_block();
|
||||||
octree.insert(position, voxel);
|
octree.insert(position, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ pub fn generate_solid_plane_with_noise(
|
|||||||
for iy in 0..=max_layer {
|
for iy in 0..=max_layer {
|
||||||
let position = Vec3::new(x * step, iy as f32 * step, z * step);
|
let position = Vec3::new(x * step, iy as f32 * step, z * step);
|
||||||
|
|
||||||
let voxel = Voxel::random_sides();
|
let voxel = Voxel::grass_block();
|
||||||
octree.insert(position, voxel);
|
octree.insert(position, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use bevy::asset::RenderAssetUsages;
|
use bevy::asset::RenderAssetUsages;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat};
|
use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat};
|
||||||
|
use image::GenericImageView;
|
||||||
|
|
||||||
/// Configuration and handle for the voxel texture atlas.
|
/// Configuration and handle for the voxel texture atlas.
|
||||||
#[derive(Resource, Clone)]
|
#[derive(Resource, Clone)]
|
||||||
@ -11,32 +12,37 @@ pub struct VoxelTextureAtlas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VoxelTextureAtlas {
|
impl VoxelTextureAtlas {
|
||||||
/// Create a simple procedural atlas with solid colors.
|
/// Generate an atlas from PNG files located in `assets/textures/packs/mc/grass`.
|
||||||
pub fn generate(images: &mut Assets<Image>) -> Self {
|
pub fn generate(images: &mut Assets<Image>) -> Self {
|
||||||
let tile_size = 16u32;
|
// Include the PNG files at compile time so we don't rely on runtime IO.
|
||||||
let columns = 2;
|
const TOP: &[u8] = include_bytes!("../../../../../assets/textures/packs/mc/grass/grass_block_top.png");
|
||||||
let rows = 3;
|
const BOTTOM: &[u8] = include_bytes!("../../../../../assets/textures/packs/mc/grass/dirt.png");
|
||||||
|
const SIDE: &[u8] = include_bytes!("../../../../../assets/textures/packs/mc/grass/grass_block_side.png");
|
||||||
|
|
||||||
|
let textures = [TOP, BOTTOM, SIDE];
|
||||||
|
// Assume all textures have the same dimensions
|
||||||
|
let first = image::load_from_memory(TOP).expect("failed to load texture");
|
||||||
|
let tile_size = first.width();
|
||||||
|
|
||||||
|
let columns = textures.len();
|
||||||
|
let rows = 1usize;
|
||||||
let width = tile_size * columns as u32;
|
let width = tile_size * columns as u32;
|
||||||
let height = tile_size * rows as u32;
|
let height = tile_size;
|
||||||
let mut data = vec![0u8; (width * height * 4) as usize];
|
let mut data = vec![0u8; (width * height * 4) as usize];
|
||||||
let colors = [
|
|
||||||
[255, 0, 0, 255], // 0: red
|
for (i, tex_bytes) in textures.iter().enumerate() {
|
||||||
[0, 0, 0, 255], // 1: black
|
let img = image::load_from_memory(tex_bytes)
|
||||||
[0, 255, 0, 255], // 2: green
|
.expect("failed to load texture")
|
||||||
[0, 0, 255, 255], // 3: blue
|
.to_rgba8();
|
||||||
[255, 255, 0, 255], // 4: yellow
|
|
||||||
[255, 0, 255, 255], // 5: magenta
|
|
||||||
];
|
|
||||||
for (i, col) in colors.iter().enumerate() {
|
|
||||||
let cx = (i % columns) as u32 * tile_size;
|
|
||||||
let cy = (i / columns) as u32 * tile_size;
|
|
||||||
for y in 0..tile_size {
|
for y in 0..tile_size {
|
||||||
for x in 0..tile_size {
|
for x in 0..tile_size {
|
||||||
let idx = (((cy + y) * width + (cx + x)) * 4) as usize;
|
let idx = (((y) * width + x + (i as u32) * tile_size) * 4) as usize;
|
||||||
data[idx..idx + 4].copy_from_slice(col);
|
let pixel = img.get_pixel(x, y).0;
|
||||||
|
data[idx..idx + 4].copy_from_slice(&pixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let image = Image::new_fill(
|
let image = Image::new_fill(
|
||||||
Extent3d {
|
Extent3d {
|
||||||
width,
|
width,
|
||||||
@ -48,6 +54,7 @@ impl VoxelTextureAtlas {
|
|||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
RenderAssetUsages::default(),
|
RenderAssetUsages::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let handle = images.add(image);
|
let handle = images.add(image);
|
||||||
Self {
|
Self {
|
||||||
handle,
|
handle,
|
||||||
|
|||||||
@ -84,6 +84,16 @@ impl Voxel {
|
|||||||
}
|
}
|
||||||
Self { textures }
|
Self { textures }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a simple grass block using the first three atlas indices.
|
||||||
|
/// Index 0: grass top, index 1: dirt (bottom), index 2: grass sides.
|
||||||
|
pub fn grass_block() -> Self {
|
||||||
|
let mut textures = [2usize; 6];
|
||||||
|
// Face order: left, right, bottom, top, back, front
|
||||||
|
textures[3] = 0; // top
|
||||||
|
textures[2] = 1; // bottom
|
||||||
|
Self { textures }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const NEIGHBOR_OFFSETS: [(f32, f32, f32); 6] = [
|
pub const NEIGHBOR_OFFSETS: [(f32, f32, f32); 6] = [
|
||||||
|
|||||||
@ -36,7 +36,7 @@ pub fn voxel_system(
|
|||||||
|
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyQ) && window.cursor_options.visible == false {
|
if keyboard_input.just_pressed(KeyCode::KeyQ) && window.cursor_options.visible == false {
|
||||||
for mut octree in octree_query.iter_mut() {
|
for mut octree in octree_query.iter_mut() {
|
||||||
octree.insert(transform.translation, Voxel::random_sides());
|
octree.insert(transform.translation, Voxel::grass_block());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if keyboard_input.just_pressed(KeyCode::F4) {
|
if keyboard_input.just_pressed(KeyCode::F4) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user