Clustered Mesh: Difference between revisions
Content added Content deleted
No edit summary |
m (typo) |
||
Line 18: | Line 18: | ||
==== 32-bit ==== |
==== 32-bit ==== |
||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! |
! Offset !! Length !! Type !! Name !! Description !! Comments |
||
|- |
|- |
||
| 0x0 || 0x4 || [[#rw::collision::VolRef::Volume|Volume]]* || mpCollisionVolume || || |
| 0x0 || 0x4 || [[#rw::collision::VolRef::Volume|Volume]]* || mpCollisionVolume || || |
Revision as of 16:30, 17 March 2024
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::VolRef::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 | List of flags is unknown |
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 | List of flags is unknown | |
0x6 | 0x1 | uint8_t | mGroupIdSize | Number of bytes | 1 or 2 |
0x7 | 0x1 | uint8_t | mSurfaceIdSize | Number of bytes | 1 or 2 |
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 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 |
No known samples |
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. |