Clustered Mesh
ClusteredMesh | |||
---|---|---|---|
aka CollisionMeshData | |||
Track unit 203's clustered mesh. | |||
Type ID | 0x24 | ||
Category | Generic | ||
Memory distribution |
Main Memory only | ||
Imported by | ID List | ||
Editor available? |
Viewer only Use Blender addons |
Development Information on versions of the Clustered Mesh resource type used during development. |
Clustered Mesh resources were used for world collision (WORLDCOL) prior to the introduction of the Polygon Soup List resource type.
Structures
CgsPhysics::CollisionMeshData
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x4 | Volume* | mpCollisionVolume | ||
0x4 | 0xC | Padding | |||
0x10 | 0x10 | Vector3Plus | mBoundingSphere |
rw::collision::Volume
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x40 | Matrix44Affine | transform | ||
0x40 | 0x4 | Volume::VTable* | vTable | When written to file, this actually represents an rw::collision::VolumeType instead rather than a pointer. This is always VOLUMETYPEAGGREGATE , which has a value of 6.
| |
0x44 | 0x4 | ClusteredMesh* | This is actually implemented as a 12-byte union accepting multiple types, including three floats representing triangles or boxes. The union type used is defined by the VolumeType in the vTable. The Clustered Mesh resource type however only accepts a ClusteredMesh pointer here (represented by the aggregate volume type), and will cause undefined behaviour if other types are used instead.
| ||
0x48 | 0x8 | Union padding | |||
0x50 | 0x4 | float32_t | radius | ||
0x54 | 0x4 | uint32_t | groupID | ||
0x58 | 0x4 | uint32_t | surfaceID | ||
0x5C | 0x4 | uint32_t | m_flags | See VolumeFlag |
rw::collision::VolumeFlag
Note that this is sourced from February 2007 data and may or may not have changed in later versions.
Name | Value | Comments |
---|---|---|
VOLUMEFLAG_ISENABLED | 1 | |
VOLUMEFLAG_TRIANGLENORMALISDIRTY | 2 | |
VOLUMEFLAG_TRIANGLEONESIDED | 16 | These precise values (but not the existence of the flags themselves) are technically platform-specific and is documented for PS3. It may or may not be actually different on other platforms. |
VOLUMEFLAG_TRIANGLEEDGE0CONVEX | 32 | |
VOLUMEFLAG_TRIANGLEEDGE1CONVEX | 64 | |
VOLUMEFLAG_TRIANGLEEDGE2CONVEX | 128 | |
VOLUMEFLAG_TRIANGLEUSEEDGECOS | 256 | |
VOLUMEFLAG_TRIANGLEVERT0DISABLE | 512 | |
VOLUMEFLAG_TRIANGLEVERT1DISABLE | 1024 | |
VOLUMEFLAG_TRIANGLEVERT2DISABLE | 2048 | |
VOLUMEFLAG_FORCEENUMSIZEINT | 0x7FFFFFFF |
rw::collision::Aggregate
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x20 | AABBox | m_AABB | ||
0x20 | 0x4 | Aggregate::VTable* | m_vTable | Garbage data in the file - always replaced on read | |
0x24 | 0x4 | uint32_t | m_numTagBits | ||
0x28 | 0x4 | uint32_t | m_numVolumes | ||
0x2C | 0x4 | uint32_t | pad |
rw::collision::Procedural
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x30 | Aggregate | Base class |
rw::collision::ClusteredMesh
The base pointer resets here - all pointer offsets here are relative to the start of this struct.
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x30 | Procedural | Base class | ||
0x30 | 0x4 | KDTree* | mKDTree | ||
0x34 | 0x4 | uint32_t* | mCluster | Effectively a ClusteredMeshCluster** | |
0x38 | 0x8 | ClusterParams | mClusterParams | ||
0x40 | 0x4 | uint32_t | mNumClusters | ||
0x44 | 0x4 | uint32_t | mMaxClusters | ||
0x48 | 0x4 | uint32_t | mNumUnits | ||
0x4C | 0x4 | uint32_t | mMaxUnits | ||
0x50 | 0x4 | uint32_t | mSizeOfThis | ||
0x54 | 0x2 | uint16_t | mDefaultGroupId | ||
0x56 | 0x2 | uint16_t | mDefaultSurfaceId | ||
0x58 | 0x1 | uint8_t | mDefaultEdgeAngle | ||
0x59 | 0x7 | Padding |
rw::collision::AALineClipper::AABBox
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x10 | vpu::Vector3 | m_min | ||
0x10 | 0x10 | vpu::Vector3 | m_max |
rw::collision::ClusterParams
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x4 | float32_t | mVertexCompressionGranularity | Relevant for cluster compression modes 1 and 2 | |
0x4 | 0x2 | uint16_t | mFlags | Likely CMFlags | |
0x6 | 0x1 | uint8_t | mGroupIdSize | Number of bytes | 1 or 2 |
0x7 | 0x1 | uint8_t | mSurfaceIdSize | Number of bytes | 1 or 2 |
rw::collision::CMFlags
Note that this is sourced from February 2007 data and may or may not have changed in later versions.
Name | Value | Comments |
---|---|---|
CMFLAG_INT16VERTEX | 1 | |
CMFLAG_INT16NORMAL | 2 | |
CMFLAG_20BITCLUSTERINDEX | 4 | |
CMFLAG_ONESIDED | 16 | |
CMFLAG_FORCEENUMSIZEINT | 0x7FFFFFFF |
rw::collision::KDTree
The base pointer resets here - all pointer offsets here are relative to the start of this struct.
32-bit
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x4 | BranchNode* | m_branchNodes | ||
0x4 | 0x4 | uint32_t | m_numBranchNodes | ||
0x8 | 0x4 | uint32_t | m_numEntries | ||
0xC | 0x4 | Padding | |||
0x10 | 0x20 | AABBox | m_bbox |
rw::collision::KDTree::BranchNode
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x4 | uint32_t | m_parent | ||
0x4 | 0x4 | uint32_t | m_axis | ||
0x8 | 0x10 | NodeRef[2] | m_childRefs | ||
0x18 | 0x8 | float32_t[2] | m_extents |
rw::collision::KDTree::NodeRef
Offset | Length | Type | Name | Description | Comments |
---|---|---|---|---|---|
0x0 | 0x4 | uint32_t | m_content | ||
0x4 | 0x4 | uint32_t | m_index |
rw::collision::ClusteredMeshCluster
Offset | Length | Type | Name | Description | Comments | ||
---|---|---|---|---|---|---|---|
0x0 | 0x2 | uint16_t | unitCount | ||||
0x2 | 0x2 | uint16_t | unitDataSize | ||||
0x4 | 0x2 | uint16_t | unitDataStart | The index of the vertex array where unit data starts | |||
0x6 | 0x2 | uint16_t | normalStart | The index of the vertex array where normal data starts | |||
0x8 | 0x2 | uint16_t | totalSize | ||||
0xA | 0x1 | uint8_t | vertexCount | ||||
0xB | 0x1 | uint8_t | normalCount | ||||
0xC | 0x1 | uint8_t | compressionMode | VERTICES_UNCOMPRESSED = 0 VERTICES_16BIT_COMPRESSED = 1 VERTICES_32BIT_COMPRESSED = 2 |
|||
0xD | 0x3 | uint8_t[3] | Padding | ||||
0x10 | 0x10 | vpu::Vector3[1] | vertexArray | Variable size data |
Unit data |
Vertex data
Offset | Length | Type | Name | Comments |
---|---|---|---|---|
0x0 (repeating) |
0x10 | vpu::Vector3 | Raw vector (mVertexCompressionGranularity unused) |
Offset | Length | Type | Name | Comments |
---|---|---|---|---|
0x0 | 0xC | int32_t[3] | vertexOffsetData | Component base |
0xC (repeating) |
0x6 | Vertex16[3] | vertData | Add to initial int32_t components and then multiply components by mVertexCompressionGranularity to get coordinate |
Offset | Length | Type | Name | Comments |
---|---|---|---|---|
0x0 (repeating) |
0xC | Vertex32[3] | vertData | Multiply components by mVertexCompressionGranularity to get coordinate |
rw::collision::ClusteredMeshCluster::Vertex16
Offset | Length | Type | Name |
---|---|---|---|
0x0 | 0x2 | uint16_t | x |
0x2 | 0x2 | uint16_t | y |
0x4 | 0x2 | uint16_t | z |
rw::collision::ClusteredMeshCluster::Vertex32
Offset | Length | Type | Name |
---|---|---|---|
0x0 | 0x4 | int32_t | x |
0x4 | 0x4 | int32_t | y |
0x8 | 0x4 | int32_t | z |
Unit data
This is a byte stream. Exact offsets are variable and depends on several factors, as detailed below.
Length | Type | Description | Comments |
---|---|---|---|
0x1 | uint8_t | Lower nibble (type) [unused] UNITTYPE_OLDTRIANGLE = 0 UNITTYPE_TRIANGLE = 1 UNITTYPE_QUAD = 2 UNITTYPE_TRILIST = 3 Upper nibble (flags) UNITFLAG_NORMAL = 1 UNITFLAG_EDGEANGLE = 2 UNITFLAG_GROUPID = 4 UNITFLAG_SURFACEID = 8 [unused] UNITFLAG_USEOLDTRI = all bits set (including type) |
|
0x1 | uint8_t | Only present if type == UNITTYPE_TRILIST Triangle count |
For UNITTYPE_OLDTRIANGLE/UNITTYPE_TRIANGLE this is implicitly 1 and for UNITTYPE_QUAD this is implicitly 2 |
Vertex count (triangle count + 2) |
uint8_t | Vertex index | |
0x1 | uint8_t | Only present with UNITFLAG_NORMAL Normal index probably |
|
Edge count (triangle count + 2) |
uint8_t | Only present with UNITFLAG_EDGEANGLE Edge cosines? Mask with 0x1F and flags above that? rw::colison::UnitEdgeFlags is likely relevant | |
Group ID size (see ClusterParams) | uint8_t or uint16_t | Only present with UNITFLAG_GROUPID Group ID |
This is always little endian. |
Surface ID size (see ClusterParams) | uint8_t or uint16_t | Only present with UNITFLAG_SURFACEID Surface ID |
This is always little endian. |