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:
1 parent
c4fa500198
commit
4a58910fba
26 files changed
+525
-96
No files matched your search
+16
-7
@@ -4,8 +4,9 @@
|
||||
geom_import.py base.wad mesh.obj new.wad [--default-tex N] [--no-coll] [--mat N]
|
||||
[--keep-tiles] [--band 6]
|
||||
|
||||
Input OBJ in the export space of geom_export.py (y up, 1 unit = 1 tile, z < 0 lies in the
|
||||
grid; grid cell (cx,cz) = (floor(x), floor(-z)), must be within 0..W-1 / 0..H-1).
|
||||
Input OBJ in game space as geom_export.py writes it (right-handed, y up, 1 unit = 1 tile, z > 0
|
||||
lies in the grid; grid cell (cx,cz) = (floor(x), floor(z)), must be within 0..W-1 / 0..H-1), i.e.
|
||||
as Blender shows it. --export-space reads the old convention (raw export space, z < 0).
|
||||
|
||||
Textures: the engine has NO free UVs. Each triangle shows one half of a texture
|
||||
rectangle (entry of the TEXT table); the corners are chosen via face flags.
|
||||
@@ -43,7 +44,8 @@ import geomlib as G # noqa: E402
|
||||
PATTERNS = [0x800, 0x810, 0x820, 0x830, 0x000, 0x020]
|
||||
|
||||
|
||||
def read_obj(path):
|
||||
def read_obj(path, export_space=False):
|
||||
"""Faces and points in export space (converted from file space unless export_space)."""
|
||||
V, C, VT = [], [], []
|
||||
faces = [] # (idx list, vt list or None, material, group)
|
||||
mat, grp = None, ''
|
||||
@@ -52,7 +54,8 @@ def read_obj(path):
|
||||
if not p:
|
||||
continue
|
||||
if p[0] == 'v':
|
||||
V.append(tuple(float(x) for x in p[1:4]))
|
||||
v = tuple(float(x) for x in p[1:4])
|
||||
V.append(v if export_space else G.to_file(v))
|
||||
C.append(tuple(float(x) for x in p[4:7]) if len(p) >= 7 else None)
|
||||
elif p[0] == 'vt':
|
||||
VT.append((float(p[1]), float(p[2])))
|
||||
@@ -67,7 +70,11 @@ def read_obj(path):
|
||||
a = int(s[0]); vi.append(a - 1 if a > 0 else len(V) + a)
|
||||
if len(s) > 1 and s[1]:
|
||||
b = int(s[1]); ti.append(b - 1 if b > 0 else len(VT) + b)
|
||||
faces.append((vi, ti if len(ti) == len(vi) else None, mat, grp))
|
||||
ti = ti if len(ti) == len(vi) else None
|
||||
if not export_space:
|
||||
vi = G.file_order(vi)
|
||||
ti = ti and G.file_order(ti)
|
||||
faces.append((vi, ti, mat, grp))
|
||||
return V, C, VT, faces
|
||||
|
||||
|
||||
@@ -116,12 +123,14 @@ def main():
|
||||
ap.add_argument('--zones', choices=['flat', 'keep'], default='flat',
|
||||
help='flat: disable zone visibility (PVS), draw everything; keep: original')
|
||||
ap.add_argument('--band', type=float, default=6.0, help='height band per tile (units)')
|
||||
ap.add_argument('--export-space', action='store_true',
|
||||
help='OBJ in raw export space (z < 0; files of geom_export --export-space / before 2026-11-07)')
|
||||
a = ap.parse_args()
|
||||
|
||||
ch, wf, trak, mp = G.load_level(a.base)
|
||||
pages, texs = G.parse_text(G.wad_get(ch, 'TEXT'))
|
||||
W, H = mp['W'], mp['H']
|
||||
V, C, VT, faces = read_obj(a.obj)
|
||||
V, C, VT, faces = read_obj(a.obj, a.export_space)
|
||||
deftex = a.default_tex
|
||||
if deftex is None:
|
||||
deftex = next(i for i, t in enumerate(texs) if not (t['flags'] & 1) and t['page'] >= 0)
|
||||
@@ -160,7 +169,7 @@ def main():
|
||||
tris.append((P, Cc, tex, fl))
|
||||
|
||||
if a.coll_obj:
|
||||
cV, _, _, cfaces = read_obj(a.coll_obj)
|
||||
cV, _, _, cfaces = read_obj(a.coll_obj, a.export_space)
|
||||
polys = []
|
||||
for vi, ti, mat, grp in cfaces:
|
||||
m = re.search(r'mat(\d+)', grp or '')
|
||||
|
||||
Reference in new issue
Block a user