mesh files use game space (right-handed, y up): obj/gltf import and export no longer mirror models, per-mesh handedness keeps meshes of old projects as they were, python tools follow (--export-space for the old files)

This commit is contained in:
MineTec committed 2026-11-07 12:48:43 +01:00
1 parent c4fa500198
commit 4a58910fba
26 files changed
+525 -96

No files matched your search

+4
View File
@@ -164,6 +164,10 @@ Ctrl inverts `enabled` while dragging.
* Rotate gizmo: the edge-on fallback uses the screen angle with the mirrored sign.
* Standard views: **top** = x to the right, game z (grid rows) downwards (cell (0,0) top left, as the
MAP/region grid is laid out; yaw π); **front** looks along game −z (x right); **side** looks along −x.
* Files (Import mesh, OBJ and glTF export, the Python geom tools) are right-handed y-up **game
space** (= export space with z negated and the winding reversed), so they look the same in
Blender as in the editor and the game (2026-11-07; before, they were export space and appeared
mirrored – see editor-tools-geometry.md "Handedness").
* Spaces: render/export space = (x, y, −z_game); model and inspector values (strats, waypoints,
zones, lights, collision) are game space, tiles store export floats. LGHT point lights/directions
are stored in game space (engine negates z on load). Strat yaw: `rotateY(−ry·2π/4096)` in export
+15 -4
View File
@@ -28,9 +28,18 @@ the spatial partition is the grid itself (cell lists) + a 32-zone visibility tab
## 2. Coordinate spaces [certain]
* **Export space** (= MAP floats "A", = vertex data of TRAK/STPC): right-handed, **y up**,
grid cells lie at x ∈ [0,W), **z ∈ (−H, 0]**. The OBJ export uses this space.
* **Export space** (= MAP floats "A", = vertex data of TRAK/STPC): **y up**, grid cells lie at
x ∈ [0,W), **z ∈ (−H, 0]**. The engine draws it with a Direct3D camera, i.e. **left-handed**:
a right-handed tool shows export-space data mirrored (see editor-render.md).
* **Game space** (MAP fixed point "B", collision, strats): (x, y, −z), 20.12 fixed point (4096 = 1).
As the game shows it, game space is **right-handed** (y up).
* **File space** (OBJ/glTF of all tools, since 2026-11-07) = game space: right-handed, y up,
z > 0 in the grid, so Blender shows a level the same way round as the game and a model from
Blender appears in game as modelled. Converting export ↔ file negates z and reverses the corner
order (first corner kept: export (0,1,2) ↔ file (0,2,1); `geomlib.to_file/file_order`).
Used by `geom_export`/`geom_import`/`geom_demo` (`--export-space` = old raw export space, z < 0),
the editor's Import mesh, OBJ export and glTF export. Verified in game and Blender with an
asymmetric "F" (`img/editor/handed_*.jpg`, editor-tools-geometry.md).
The renderer converts B back: pos = (Bx, By, −Bz)/4096, angle = rot·2π/4096.
* Tile transform (local vertex v → world, export space), a = rot/4096·2π:
`X = x + vx·cos a − vz·sin a ; Y = y + vy ; Z = z + vx·sin a + vz·cos a`
@@ -197,9 +206,11 @@ Implemented in `tools/geom_import.py` (OBJ → TRAK + MAP tile part, rest of the
* Whether the player start point/camera is coupled to geometry (objects.md).
## 10. Tools
* `geom_export.py WAD OUT [--collision] [--objects]` → level.obj/mtl (UV, vertex colours, one
* OBJ files of all three tools are file space = game space (section 2); `--export-space` on
`geom_export`/`geom_import` = the old raw export space (z < 0).
* `geom_export.py WAD OUT [--collision] [--objects] [--export-space]` → level.obj/mtl (UV, vertex colours, one
object per tile), page_NN.png, collision.obj (groups matNN_grpG), objects.obj, preview_top/persp.png
(textured software renderer).
* `geom_import.py BASE.wad MESH.obj NEW.wad [--coll-obj C.obj] [--keep-tiles] [--zones flat|keep] [--default-tex N]`
* `geom_import.py BASE.wad MESH.obj NEW.wad [--coll-obj C.obj] [--keep-tiles] [--zones flat|keep] [--default-tex N] [--export-space]`
* `geom_demo.py BASE.wad demo.obj [--plaza]` – example geometry made of texture-tile quads.
* `geomlib.py` – parser/builder (TRAK, STPC models, MAP tile part, TEXT table/pages, collision).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

+2 -2
View File
@@ -265,8 +265,8 @@ X display → own `Xvfb :7` (never :0, :5 belongs to lamatest). Procedure (scrip
1. `geom_export.py out/testwelt.wad GE` → level.obj/mtl + page_NN.png
2. Strat positions: run the level script with `levelbuild.Level` (without `L.build`), `L.strats` as JSON
3. `DISPLAY=:7 STRATS=strats.json VIEWS=schraeg,schraeg2,oben blender -b -P render_level.py -- GE r 64`:
own OBJ reader (the 3.0 importer does not know vertex colours), mirroring OBJ→game (y_blender =
−game z, flip winding), material = texture (closest) × vertex colour, a little emission,
own OBJ reader (the 3.0 importer does not know vertex colours), OBJ (= game space since
2026-11-07) → Blender z up (y_blender = −game z, winding kept), material = texture (closest) × vertex colour, a little emission,
sun + sky, markers for strats (coins gold, llama start orange cone, gallery objects
in row colour, animals white, exit purple ring); writes PNG + JSON per view with
image coordinates of the area names.