Skip to content

Exporter: PS1 TMD + TIM (GT4 / FT4 / G4 / F4 primitives) #357

Description

@fernandotonon

Overview

Add a PS1-style mesh exporter targeting the Sony TMD mesh format and TIM image format, so meshes can be authored in QtMeshEditor and dropped into PS1 homebrew (PSn00bSDK, Lameguy's tools) or emulator demos.

GT4/FT4/G4/F4 are PS1 GPU primitive opcodes, not a file format — they are emitted inside a TMD per polygon based on shading + texture flags:

Opcode Shading Textured
GT4 Gouraud yes
FT4 Flat yes
G4 Gouraud no (vertex color)
F4 Flat no (single color)

(In practice the triangle-based equivalents — GT3/FT3/G3/F3 — should be the default since our pipeline is triangle-based. We can offer a quad-merge pass later.)

Prerequisite

Block on the Phase 5 epic (#260) finishing. This is its own scope and shouldn't share branches with active animation/PBR work.

Scope

1. TMD writer

  • New class PS1TMDExporter (mirrors FBXExporter pattern in src/FBX/).
  • Walks the active Ogre mesh: per-submesh, write a TMD object with vertex / normal / primitive blocks.
  • Choose primitive opcode per face from material flags:
    • Material has a diffuse texture → textured (T variant)
    • Material vertex-color attribute mode → smooth (G variant) vs flat (F variant)
  • Convert positions to PS1 fixed-point (16-bit shorts, scale-aware).
  • Per-face vertex colors = sample material diffuse if no per-vertex color is present.

2. TIM writer + palette quantizer

  • New class PS1TIMExporter. Supports 4 bpp (16-color CLUT), 8 bpp (256-color CLUT), 15 bpp (direct).
  • Use a simple median-cut or octree quantizer for 4/8 bpp from 24-bit RGB input.
  • Caller picks VRAM page coords + CLUT coords (default to a sensible auto-layout).

3. Integration points

  • GUI: "PS1 TMD" entry in the Export menu.
  • CLI: qtmesh convert model.fbx -o model.tmd (auto-generates the matching .tim per material).
  • MCP: export_tmd tool with optional bpp + VRAM layout args.

4. Sentry breadcrumbs

  • file.export for every TMD/TIM written, with poly count + bpp.

Out of scope (future)

  • HMD (hierarchical/animated) — separate issue if needed for skeletal export.
  • Quad merging (use F4/FT4/G4/GT4 quads instead of two triangles).
  • VRAM packer / atlas across multiple TIMs.
  • DMA-ready ordering tables.

Acceptance criteria

  • Cube + textured cube round-trip: load .obj → export .tmd + .tim → loads correctly in a known PS1 viewer (e.g. Lameguy's tmdview)
  • Material with no texture exports F3/G3 polys, no TIM written
  • Material with texture exports FT3/GT3 polys + matching TIM
  • Per-vertex colors preserved through G* opcodes
  • CLI qtmesh convert handles the .tmd extension
  • MCP tool exposed and documented

References

  • Sony PSY-Q PlayStation Programmer Tool Guide (TMD chapter)
  • Lameguy's PS1 documentation (psxdev.ru wiki, psn00bsdk docs)
  • TIM format spec (4/8/15/24 bpp variants + CLUT)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions