Files
wsg/docs/user/meshes/sources.md
T
Jérôme Bousquié d4c2d93fc5 eng doc
2026-09-25 20:06:10 +02:00

114 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Geometry sources: procedural generators and file import
The `wsg::mesh` module is the single entry point for **where the geometry comes from**:
procedural generators or file import.
## Procedural primitives
Each primitive family is behind a **feature** — you only compile what you need.
| Feature | Function | Description |
|---------|----------|-------------|
| `prim-cube` | `cube(size)` | Centered cube, 24 vertices, per-face normals |
| `prim-plane` | `plane(w, d, seg_x, seg_z)` | Horizontal XZ plane (normal +Y), subdivided |
| `prim-sphere` | `uv_sphere(r, sectors, stacks)` | Lat/long sphere, smooth normals |
| `prim-sphere` | `icosphere(r, subdivisions)` | Icosphere (subdivided icosahedron) |
| `prim-cylinder` | `cylinder(r, h, sectors)` | Cylinder (side + caps), analytic normals |
| `prim-cone` | `cone(r, h, sectors)` | Cone (apex + closed base) |
| `prim-torus` | `torus(major, minor, seg_maj, seg_min)` | Torus, smooth normals |
### Default features
```toml
# Your project's Cargo.toml
[dependencies]
wsg-lib = { path = "../lib" }
# Default: all primitives enabled (all-prims)
```
```toml
# Only compile the cube and the sphere:
wsg-lib = { path = "../lib", default-features = false, features = ["prim-cube", "prim-sphere"] }
```
### Usage
```rust
use wsg_lib::prelude::*;
let cube = cube(2.0);
let sphere = uv_sphere(1.0, 32, 16);
let ico = icosphere(1.0, 2);
// All return a Geometry (positions + normals + UVs + indices)
assert_eq!(cube.positions.len(), 24);
```
## File import
| Feature | Function | Format |
|---------|----------|--------|
| `import-obj` | `load_obj(path)` / `parse_obj(str)` | Wavefront OBJ |
| `import-gltf` | `load_gltf(path)` | glTF 2.0 / GLB (stub) |
### OBJ parser
Supports: `v`, `vn`, `vt`, `f` (3–4 vertices, fan triangulation).
If the file has no normals, they are **computed** (area-weighted).
```rust
use wsg_lib::mesh::{load_obj, parse_obj};
// From a file
let geom = load_obj("model.obj")?;
// From a string
let geom = parse_obj("v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3\n")?;
```
### Errors
```rust
use wsg_lib::mesh::import::MeshImportError;
match load_obj("missing.obj") {
Ok(geom) => { /* … */ }
Err(MeshImportError::Io(e)) => eprintln!("file not accessible: {e}"),
Err(MeshImportError::Parse(e)) => eprintln!("invalid syntax: {e}"),
Err(MeshImportError::Unsupported(e)) => eprintln!("unsupported feature: {e}"),
}
```
## From `Geometry` to the scene
The `mesh` module produces `Geometry` (CPU data). To render it, go through
`Scene::create_mesh`, which uploads it to the GPU:
```rust
use wsg_lib::prelude::*;
use wsg_lib::mesh::cube;
// In AppHandler::setup:
let geom = cube(1.0);
app.scene.create_mesh("my_mesh", geom, Some("my_mat"))?;
app.scene.add_entity("my_entity", "my_mesh")?;
```
## Example
```sh
cargo run -p wsg-lib --example import --features import-obj -- model.obj
```
## Conventions
- **Y-up**, centered on the origin (except `plane`: XZ plane at y=0)
- **Outward** normals
- UVs in [0,1]²
- **CCW** winding (front face)
## Links
- [User README](../README.md) · [Meshes](meshes.md) · [Materials & textures](materials.md) · [Examples](../examples.md)
- [Root README](../../../README.md)