Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
Classes | Namespaces
psxm.hh File Reference

The PXM2 mesh format, and a reader for it. More...

#include <stdint.h>
Include dependency graph for psxm.hh:

Go to the source code of this file.

Classes

struct  psxm::Header
 
struct  psxm::Vec3
 
struct  psxm::UV
 
struct  psxm::Triangle
 
class  psxm::Model
 Points into a PXM2 blob without copying it, so the blob has to outlive it. For an asset linked in by the build rule that costs nothing. More...
 

Namespaces

namespace  psxm
 

Detailed Description

The PXM2 mesh format, and a reader for it.

PXM2 is what the nugget.psxm xmake rule (tools/xmake/assets.lua) produces from a Wavefront OBJ: a triangle mesh in the units the GTE and the GPU take directly, so the runtime only points into it. Textures are not part of it; they travel separately, typically as TIMs.

All fields are little endian. The layout is:

Offset Size Contents
0 24 Header
vertexOffset 6 * count vertices, three int16 x, y, z each
normalOffset 6 * count normals, three int16 x, y, z each, 4.12
triangleOffset 20 * count Triangle records

The offsets are relative to the start of the blob and each section starts on a four byte boundary; the bytes between sections are zero. Readers find the sections through the offsets, never by assuming they follow each other, so a section added later does not move the existing ones.

Coordinates are in the converter's fixed-point scale (OBJ units times the rule's nugget.psxm.scale, 256 by default), with Y negated from the OBJ so that it grows downwards like the screen. Normals take the same Y flip and are scaled by 4096; identical normals are stored once. Corner order is kept as authored, except that a face whose winding disagrees with its own authored normal is reordered to match it. Front faces then wind positively once projected.

Each triangle holds three vertex indices, three normal indices (one per corner, so smooth and hard edges both work), and three texture coordinates in texels, with V flipped from the OBJ because VRAM grows downwards. Indices are zero based and always below the matching count.