docs: bring all READMEs current with actual code (post-sweep-10 truth pass)
Every README was read first, checked against the code in its directory, then rewritten to describe what the code actually does now. Corrected throughout: map size is config-driven (8192 default) not a fixed 4096; chunks are 24x24x256 not 32x32; road carving is implemented for all four tiers, not a 'next step'; Data/ and Resources/ are empty, not populated. Also fixed MATH_MARCHING_CUBES.md, which documented the density sign convention exactly backwards — it claimed positive was underground, where the code treats positive as above the surface and counts a corner inside when density < iso. Getting that backwards inverts every normal, a bug this project has hit before. The root README now carries accurate run steps: F5 runs the map generator (not the game), F6 on Scenes/Main.tscn runs the 3D world, and ChunkRadius is a load radius that should be dropped to 4-8 while iterating. Docs only. No code changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f9ea2da3f4
commit
d72ffc0183
13 changed files with 579 additions and 409 deletions
|
|
@ -1,27 +1,57 @@
|
|||
# Core Module - IslaApocalypse
|
||||
|
||||
**Phase 2 Status:** Active (Voxel Math & Parsing Online)
|
||||
|
||||
## Overview
|
||||
The `Core` directory contains the mathematical foundation, data structures, and parser required to bridge the 2D procedural generation with the 3D Voxel Engine. It is strictly logic-driven and contains no Godot Nodes or visual elements.
|
||||
|
||||
## Key Architecture & Components
|
||||
|
||||
### 1. The Data Bridge (`MapDataParser.cs`)
|
||||
Responsible for deserializing the highly compressed binary `.dat` file generated by the `/Tools` pipeline.
|
||||
* **Outputs:** A `WorldBlueprint` object held in RAM.
|
||||
* **Capabilities:** Reads the 2D heightmap, biome map, and town locations. Crucially, it parses all four tiers of A* road vectors (Highways, Branch Roads, Rugged Roads, Trails) for the Server to use in terrain flattening.
|
||||
|
||||
### 2. Voxel Data Containers (`ChunkData.cs` & `Constants.cs`)
|
||||
* **Chunk Dimensions:** Defined in `Constants.cs`. Currently optimized to `32x32` horizontal with a massive `256` vertical height limit to allow for true AAA-scale mountain ranges without heightmap compression.
|
||||
* **Seamless Borders:** `ChunkData.cs` expands its scalar field arrays (`Densities` and `BlockIDs`) by `+1` on all axes. This allows the Marching Cubes algorithm to sample the neighboring chunk's data, ensuring meshes connect perfectly without gaps.
|
||||
|
||||
### 3. The Math Engine (`MarchingCubes.cs`)
|
||||
Transforms the raw `ChunkData` scalar fields into physical Godot `ArrayMesh` geometry.
|
||||
* **Analytical Normals:** Instead of flat shading, the algorithm calculates exact 3D slope gradients at the corners of each voxel. This produces smooth, realistic lighting across curved terrain.
|
||||
* **Vertex Painting:** Reads the `BlockID` assigned to each voxel corner and applies physical RGB colors directly to the mesh vertices before committing the geometry.
|
||||
|
||||
### 4. Biome & Material Mapping (`BiomePalette.cs`, `BlockRegistry.cs`)
|
||||
Translates the 2D world into physical 3D materials.
|
||||
* **BlockRegistry:** A byte-based lookup table defining physical materials (`SAND`, `STONE`, `WASTELAND_DIRT`, `ASPHALT`).
|
||||
* **BiomePalette Logic:** Uses the 2D `Biome` pixel combined with the 3D `currentY` depth to determine the block type. For example, `Biome.Wasteland` combined with a depth of 0 yields `WASTELAND_DIRT`, while a depth > 4 yields `STONE`.
|
||||
# Core Module
|
||||
|
||||
Shared, stateless logic used by both the server and client paths: the `.dat` parser, the mesher, the
|
||||
voxel data containers, and the material lookups. **No Godot nodes, no scene state.** These scripts
|
||||
define what things are and how to calculate them; they never remember what is currently happening.
|
||||
|
||||
## Components
|
||||
|
||||
### `MapDataParser.cs` — the data bridge
|
||||
Deserializes the binary `.dat` blueprint written by `/Tools` into a `WorldBlueprint` held in RAM:
|
||||
map size, the float heightmap, the biome map, town locations, and **all four tiers** of A\* road
|
||||
vectors (Highways, Branch Roads, Rugged Roads, Trails).
|
||||
|
||||
Read order is fixed and must match the writer exactly: magic string `"ISLA_V1"` → map size →
|
||||
per-pixel `{height float, biome int}` in x-major order → towns → the four road tiers in order.
|
||||
|
||||
⚠ **Wire-format hazard.** Biome and town-tier enums are serialized as their **ordinal values**, with
|
||||
no version gate and no range validation on read. **Never reorder or insert members** in `Enums.cs` —
|
||||
append only, at the end. Reordering silently reinterprets every pixel of every existing `.dat`.
|
||||
(`RoadTier` is exempt: road tiers are stored in separate file sections, so that enum never hits disk.)
|
||||
|
||||
### `ChunkData.cs` + `Constants.cs` — voxel containers and tuning
|
||||
- **Chunk dimensions:** `24 × 24` horizontal, `256` vertical (`Constants.cs`).
|
||||
- **The `+1` padding is structural.** `Densities` and `BlockIDs` are one cell larger on every axis —
|
||||
`[25, 257, 25]` — so the mesher can evaluate the boundary cells shared with the neighbouring chunk
|
||||
and the meshes meet without gaps.
|
||||
- **Per-column data for rendering:** `SurfaceHeights` (the true, unrounded surface), `ColumnBiomes`,
|
||||
and `ColumnRoadMaterial` (0 = not a road). These let the mesher colour by real height rather than a
|
||||
rounded integer.
|
||||
- **Tunables in `Constants.cs`:** `BLEND_BAND_METERS` (how far one surface material fades into the
|
||||
next) and the per-tier road block — width, shoulder, grade-smoothing and surface material for each
|
||||
of the four road tiers, plus the derived cull padding.
|
||||
|
||||
### `MarchingCubes.cs` — the mesher
|
||||
Turns a chunk's density field into a Godot `ArrayMesh`.
|
||||
- **Analytical normals:** exact density gradients at each cell corner, interpolated along the edge by
|
||||
the same fraction used for the vertex position — smooth lighting without Godot's normal pass.
|
||||
- **Deterministic vertex welding:** shared vertices are keyed by an integer `EdgeKey` ordered
|
||||
lowest-to-highest, so neighbouring chunks compute identical keys and no float drift creeps in.
|
||||
- **Vertex colouring:** each vertex is coloured from its true float depth below the surface, fading
|
||||
between the two materials either side of a boundary rather than switching at an integer depth.
|
||||
|
||||
**Density sign convention (load-bearing):** density is **positive above** the surface and **negative
|
||||
below** it. A corner counts as inside the terrain when `density < ISO_LEVEL`.
|
||||
|
||||
### `BiomePalette.cs` + `BlockRegistry.cs` + `BlockData.cs` — materials
|
||||
- **`BlockRegistry`:** byte-ID lookup for every block (`AIR`, `BEDROCK`, `STONE`, `DIRT`, `SAND`, the
|
||||
three grasses, `SNOW`, `WASTELAND_DIRT`, `ASPHALT`).
|
||||
- **`BiomePalette`** answers "what material is here?" twice, deliberately:
|
||||
- `GetVoxelID(...)` — the authoritative **integer** classification by whole-block depth. Decides
|
||||
what is actually stored in each voxel; used for everything non-visual.
|
||||
- `GetBlendedVoxelIDs(...)` — the **rendering** version. Same question by *float* depth, returning
|
||||
the two materials either side of the nearest boundary plus how far between them the point is, so
|
||||
the renderer fades instead of snapping.
|
||||
|
||||
Both take a road-surface byte, so a trail is surfaced in dirt where a highway is surfaced in
|
||||
asphalt.
|
||||
|
|
|
|||
|
|
@ -13,16 +13,26 @@ Based on the answer, it draws a specific set of triangles *through* the invisibl
|
|||
|
||||
### 1. Density (The "Float" Value)
|
||||
In smooth voxels, a point in space isn't just "Solid" (1) or "Empty" (0). It has a continuous **Density** value.
|
||||
* ` 1.0` = Deep underground (Solid Rock).
|
||||
* ` 0.5` = Slightly underground (Dirt).
|
||||
|
||||
⚠ **Mind the sign — this project's convention is the opposite of many tutorials.** Density here is
|
||||
essentially *"how far above the surface am I?"*, computed as `(y − surfaceY)` normalised by the local
|
||||
slope. So it counts **upward**, not downward:
|
||||
|
||||
* ` 1.0` = High in the sky (Empty Space).
|
||||
* ` 0.5` = Slightly above ground (Air).
|
||||
* ` 0.0` = The exact surface of the ground.
|
||||
* `-0.5` = Slightly above ground (Air).
|
||||
* `-1.0` = High in the sky (Empty Space).
|
||||
* `-0.5` = Slightly underground (Dirt).
|
||||
* `-1.0` = Deep underground (Solid Rock).
|
||||
|
||||
### 2. The Iso-Level (The Threshold)
|
||||
The Iso-Level is the exact density value where the "skin" of the world is drawn. Usually, this is `0.0`.
|
||||
* If a corner's density is **greater** than `0.0`, it is "Inside" the terrain.
|
||||
* If a corner's density is **less** than `0.0`, it is "Outside" in the air.
|
||||
The Iso-Level is the exact density value where the "skin" of the world is drawn. Here it is `0.0`
|
||||
(`Constants.ISO_LEVEL`).
|
||||
* If a corner's density is **less** than `0.0`, it is "Inside" the terrain.
|
||||
* If a corner's density is **greater** than `0.0`, it is "Outside" in the air.
|
||||
|
||||
This matches the code: `MarchingCubes.GenerateMesh` sets a corner's bit when
|
||||
`cornerDensities[i] < isolevel`. Getting this backwards inverts every surface normal and makes the
|
||||
world render inside-out — which is a real bug this project has hit before.
|
||||
|
||||
### 3. The Triangulation Table (The Magic Array)
|
||||
A cube has 8 corners. Each corner can either be Inside or Outside.
|
||||
|
|
|
|||
|
|
@ -1,46 +1,50 @@
|
|||
# 📜 Core Scripts Directory - Isla Apocalypse
|
||||
|
||||
## Overview
|
||||
The `/Core/Scripts` directory is the dedicated code repository for all pure C# data structures, universal enumerations, and static mathematical utilities. Everything in this folder is compiled into the shared assembly used by both the authoritative `/Server` and the rendering `/Client`.
|
||||
|
||||
**Core Philosophy: "Pure Data, Zero State."**
|
||||
Scripts in this folder define *what* things are and *how* to calculate them, but they never remember *current* game events. They do not track who is online, what chunks are loaded, or what time of day it is. They are stateless, universal blueprints.
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Current Systems (Phase 2)
|
||||
|
||||
### 1. The Voxel Palette System
|
||||
* **`BlockData.cs`**: The fundamental `struct` defining the properties of a single voxel (ID, Name, IsSolid, BaseColor).
|
||||
* **`BlockRegistry.cs`**: The static master dictionary. Contains the hardcoded IDs for every block in the game (Air, Bedrock, Dirt, Asphalt) and provides a safe lookup method (`GetBlock`) for both the mesher and the physics engine.
|
||||
* **`BiomePalette.cs`**: The translation layer between 2D and 3D. Contains the logic that dictates the vertical stacking of blocks based on biome and depth (e.g., ensuring mountains have stone beneath snow, and roads are topped with asphalt).
|
||||
|
||||
### 2. Universal Identifiers
|
||||
* **`Enums.cs`**: The master repository for global enums (`Biome`, `TownTier`, `MapHalf`). By keeping these here, the offline Map Generator, the Server, and the Client are guaranteed to use the exact same integer values for biomes and POIs.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Future Roadmap & Planned Additions (Phase 2 & 3)
|
||||
|
||||
As we build the 3D Chunk Manager and multiplayer networking, this folder will expand to include:
|
||||
|
||||
### 3. The Blueprint Parser
|
||||
* **`MapDataParser.cs`** *(Next Step)*: A static utility to open and decode the `MapData_Seed_[X].dat` binary file into usable C# arrays for the Server to ingest.
|
||||
|
||||
### 4. Chunk Data Structures
|
||||
* **`ChunkData.cs`**: The raw 3D array (`byte[,,]`) that holds the voxel IDs for a specific 16x16x64 area.
|
||||
* *Note:* This structure will include the `IsPlayerProtected` boolean flag to support the "Land Claim" delta-backup system, preventing player bases from being wiped out by chunk corruption.
|
||||
|
||||
### 5. Math & Coordinate Utilities
|
||||
* **`VoxelMath.cs`**: Static helper functions for translating massive 3D World Coordinates into local Chunk Coordinates (e.g., finding out which specific chunk file to load when a player walks to X: 5000, Z: -200).
|
||||
|
||||
### 6. Network Packet Definitions
|
||||
* Structs that define the exact byte layout of multiplayer messages (e.g., `PlayerDigPacket`, `ChatPacket`) to ensure precise Server/Client synchronization.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Directory Rules & Best Practices
|
||||
|
||||
1. **No Godot Node Inheritance:** Scripts here should rarely, if ever, inherit from `Node` or `Node3D`. They are pure C# classes, structs, or static utilities.
|
||||
2. **No `_Process` or `_Ready`:** Because these are not attached to active objects in the game world, they do not use Godot's frame-by-frame loop functions.
|
||||
3. **Strictly Independent:** A script in `/Core/Scripts` cannot reference anything in `/Client` or `/Server`. The dependency flows one way: the Client and Server look *in* to the Core; the Core never looks *out*.
|
||||
# /Core/Scripts
|
||||
|
||||
Pure C# data structures, shared enums, and static maths. Compiled into the shared assembly used by
|
||||
both `/Server` and `/Client`.
|
||||
|
||||
**"Pure data, zero state."** These scripts define *what* things are and *how* to calculate them. They
|
||||
never track live game events — who is online, which chunks are loaded, what time it is.
|
||||
|
||||
## What's actually here
|
||||
|
||||
### Voxel materials
|
||||
- **`BlockData.cs`** — struct describing one block type (ID, name, IsSolid, BaseColor).
|
||||
- **`BlockRegistry.cs`** — the byte-ID master list (`AIR` 0, `BEDROCK`, `STONE`, `DIRT`, `SAND`, the
|
||||
three grasses, `SNOW`, `WASTELAND_DIRT`, `ASPHALT`) with a safe `GetBlock` lookup.
|
||||
- **`BiomePalette.cs`** — decides which material sits where, given biome, depth, and whether the
|
||||
column is roadbed. Two paths on purpose: an **integer** classification that decides what is stored
|
||||
in each voxel, and a **float-depth** version used for rendering that returns the two materials
|
||||
either side of a boundary so colours fade rather than snap.
|
||||
|
||||
⚠ Note that `BlockRegistry` and the mesher's colour table hold **different RGB values** for some
|
||||
blocks. The mesher's table is what you actually see; `BlockData.BaseColor` is currently unused by
|
||||
rendering.
|
||||
|
||||
### Shared identifiers
|
||||
- **`Enums.cs`** — `Biome`, `TownTier`, `MapHalf`, `RoadTier`.
|
||||
|
||||
⚠ **`Biome` and `TownTier` are the `.dat` wire format.** They are declared without explicit values,
|
||||
so each member's ordinal *is* the number written to disk, with no version gate and no validation on
|
||||
read. **Append only, at the end — never reorder or insert.** Doing so silently reinterprets every
|
||||
pixel and every settlement in every existing blueprint.
|
||||
`RoadTier` is exempt: road tiers live in separate sections of the file, so it is never serialized.
|
||||
|
||||
### World data
|
||||
- **`MapDataParser.cs`** — decodes the `.dat` blueprint into a `WorldBlueprint` (heightmap, biome map,
|
||||
towns, four road tiers).
|
||||
- **`ChunkData.cs`** — one chunk's density and block-ID fields, `+1` padded on every axis so the
|
||||
mesher can reach into the neighbouring chunk, plus the per-column data the renderer needs.
|
||||
- **`Constants.cs`** — chunk dimensions, `ISO_LEVEL`, `VOXEL_SCALE`, and the visual/road tunables
|
||||
(material blend band; per-tier road width, shoulder, grade smoothing and surface).
|
||||
|
||||
### Maths
|
||||
- **`MarchingCubes.cs`** — density field → `ArrayMesh`, with analytical normals and deterministic
|
||||
integer-keyed vertex welding.
|
||||
- **`MATH_MARCHING_CUBES.md`** — an explainer of the algorithm.
|
||||
|
||||
## Rules
|
||||
1. **No Godot node inheritance.** Pure classes, structs and statics.
|
||||
2. **No `_Process` / `_Ready`.** Nothing here is attached to a live scene object.
|
||||
3. **Dependencies flow inward only.** `/Server` and `/Client` reference `/Core`; `/Core` never
|
||||
references them.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue