221 lines
4.5 KiB
Markdown
221 lines
4.5 KiB
Markdown
# 📄 Introduction into FastVoxel
|
||
|
||
## Surface generation
|
||
|
||
Default generator: `SimpleSurfaceGenerator`
|
||
|
||
It uses `fastnoise-lite` to create a heightmap, then fills voxel columns from the bottom up.
|
||
|
||
Files:
|
||
|
||
- `src/generation/generator.rs`
|
||
- `src/generation/simple_heightmap.rs`
|
||
|
||
Generation uses traits, so you can plug in whatever mumbo jumbo nonsense you want later: caves, biomes, multiverse, whatever.
|
||
|
||
## Meshing
|
||
|
||
Multiple meshers exist because one was simply not enough to satisfy my unhealthy obsession with "doing it right this time."
|
||
[engine development perfectionism disorder. there's no cure.]
|
||
|
||
- `CullingMesher` – basic visible-face meshing
|
||
- `TexturedMesher` – UV-aware cube meshing (Minecraft basically)
|
||
- `BinaryGreedyMesher` – experimental optimization attempt
|
||
|
||
Files:
|
||
|
||
- `src/meshing/mesher.rs`
|
||
- `src/meshing/textured_mesher.rs`
|
||
- `src/meshing/binary_greedy_mesher.rs`
|
||
|
||
The textured mesher is currently the most practical one because it respects UVs and etc. simply because you can define the material for it.
|
||
It's not optimized though.
|
||
|
||
## Godot integration
|
||
|
||
The engine exposes several handy APIs for the editor:
|
||
|
||
- `WorldConfig` – generation settings
|
||
- `VoxelRegistry` – voxel definitions and atlas stuff
|
||
- `World` – main terrain node
|
||
- `WorldPlugin` – editor plugin hooks
|
||
|
||
Files:
|
||
|
||
- `src/editor/world_config.rs`
|
||
- `src/editor/voxel_registry.rs`
|
||
- `src/editor/world_node.rs`
|
||
- `src/editor/world_plugin.rs`
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
src/
|
||
├── chunk/ # chunk data, columns, manager
|
||
├── editor/ # Godot resources + editor plugin
|
||
├── generation/ # terrain generators
|
||
├── meshing/ # meshing algorithems
|
||
├── rendering/ # mesh to Godot conversion
|
||
├── terrain/ # I'm not so sure
|
||
└── voxel/ # registry + older voxel logic
|
||
```
|
||
|
||
## Build and Install
|
||
|
||
Requirements:
|
||
|
||
- Rust toolchain
|
||
- Godot 4 project with GDExtension
|
||
- Optional sibling project for `build.sh` to work.
|
||
|
||
### Build the extension
|
||
|
||
```
|
||
cargo build --release
|
||
```
|
||
|
||
### Helper script
|
||
|
||
`build.sh` builds & copies the extension to:
|
||
|
||
```
|
||
../minekoloft/addons/fastvoxel/bin/linux
|
||
```
|
||
|
||
Run with:
|
||
|
||
```
|
||
./build.sh
|
||
```
|
||
|
||
If your project is elsewhere, edit the path.
|
||
|
||
## Using It in Godot
|
||
|
||
Typical use:
|
||
|
||
1. build the Rust extension
|
||
2. install addon in your Godot project
|
||
3. create `WorldConfig`
|
||
4. create `VoxelRegistry`
|
||
5. add `World` node
|
||
6. assign config + registry
|
||
7. generate terrain
|
||
8. Call the "update with player position" API every frame. Spam it. It returns early and won't yell at you.
|
||
|
||
### WorldConfig
|
||
|
||
Contains:
|
||
|
||
- chunk_size
|
||
- render_distance
|
||
- worker_threads
|
||
- seed
|
||
- frequency
|
||
- terrain_height
|
||
|
||
Defaults:
|
||
|
||
- chunk: `32,32,32`
|
||
- render dist: `8`
|
||
- threads: `4`
|
||
- seed: `1234`
|
||
- freq: `0.03`
|
||
- terrain height: `6`
|
||
|
||
### VoxelRegistry
|
||
|
||
Each voxel defines:
|
||
|
||
- type
|
||
- atlas size
|
||
- tile index per face (top, bottom, left, right, front, back)
|
||
|
||
Mesher uses this for UVs.
|
||
|
||
### Runtime API
|
||
|
||
World node provides:
|
||
|
||
- `generate_terrain()`
|
||
- `regenerate_terrain()`
|
||
- `clear_terrain()`
|
||
- `update_from_gdscript(player_world_pos)`
|
||
|
||
GDScript example:
|
||
|
||
```gdscript
|
||
@onready var world = $World
|
||
@onready var player = $Player
|
||
|
||
func _ready():
|
||
world.generate_terrain()
|
||
|
||
func _process(_delta):
|
||
world.update_from_gdscript(player.global_position)
|
||
```
|
||
|
||
## Engine-Level API Notes
|
||
|
||
### Generation trait
|
||
|
||
```rust
|
||
pub trait SurfaceGenerator: Send + Sync {
|
||
fn generate(&self, column: &mut ChunkColumn);
|
||
fn sample_voxel(&self, pos: Vector3i) -> bool;
|
||
}
|
||
```
|
||
|
||
### Mesher trait
|
||
|
||
```rust
|
||
pub trait Mesher: Send + Sync {
|
||
fn generate_mesh(&self, chunk: &Chunk, mesh: &mut ChunkMesh);
|
||
fn generate_mesh_with_registry(
|
||
&self,
|
||
chunk: &Chunk,
|
||
registry: &VoxelRegistry,
|
||
mesh: &mut ChunkMesh,
|
||
);
|
||
fn get_name(&self) -> &str;
|
||
}
|
||
```
|
||
|
||
### ChunkManager
|
||
|
||
Handles:
|
||
|
||
- chunk lifetime
|
||
- generation around player
|
||
- unloading distant chunks
|
||
- meshing
|
||
- sending meshes to renderer
|
||
- attaching instances to scene
|
||
|
||
Basically the project's overworked intern.
|
||
|
||
## Current State
|
||
|
||
Mid-development, active refactors, might panic on unwrap.
|
||
Direction is clear though:
|
||
|
||
- compact chunk storage
|
||
- trait-based generation
|
||
- modular meshing
|
||
- Godot resource workflow
|
||
- runtime streaming
|
||
|
||
## Why This Document Exists
|
||
|
||
Because why not? If you actually wanted to read the code, you wouldn't be here.
|
||
|
||
## Future Work
|
||
|
||
- finish terrain/world refactor
|
||
- more screenshots
|
||
- stable API for godot
|
||
- multithreaded chunk gen (**GOD HELP**)
|
||
- Better Godot material integration for voxel meshes (so things look less like programmer art).
|
||
- fix the greedy meshing
|
||
- sample Godot project
|