Polygon Soup List/Burnout Paradise

From Burnout Wiki
PolygonSoupList
aka CollisionMeshData

Track unit 203's polygon soup.
Resource names TRK_COL_*
*Track unit ID
Type ID 0x43
Category Generic
Memory
distribution
Main Memory only
Imports Unknown
Imported by ID List
Editor
available?
Viewer only
Use Blender addons

Polygon Soup List resources contain collision data for track units. They are also linked to roads, AI behaviour, and respawn locations.

This resource type supersedes the Clustered Mesh type.

Note: The PS4 version of the game contains more polygons in its resources.

Structures

Header

CgsGeometric::PolygonSoupList

32-bit

Offset Length Type Name Description Comments
0x0 0x20 AxisAlignedBox mOverallAabb Bounding box
0x20 0x4 PolygonSoup** mpapPolySoups Polygon soups
0x24 0x4 AxisAlignedBox4* mpaPolySoupBoxes Polygon soup bounding boxes
0x28 0x4 int32_t miNumPolySoups Number of polygon soups
0x2C 0x4 int32_t miDataSize Resource data length

64-bit

Offset Length Type Name Description Comments
0x0 0x20 AxisAlignedBox mOverallAabb Bounding box
0x20 0x8 PolygonSoup** mpapPolySoups Polygon soups
0x28 0x8 AxisAlignedBox4* mpaPolySoupBoxes Polygon soup bounding boxes
0x30 0x4 int32_t miNumPolySoups Number of polygon soups
0x34 0x4 int32_t miDataSize Resource data length

Polygon soup

CgsGeometric::PolygonSoup

32-bit

Offset Length Type Name Description Comments
0x0 0xC int32_t[3] maiVertexOffsets
Hmmm...
Hmmm...
To do:
Needs research
0xC 0x4 float32_t mfComprGranularity
Hmmm...
Hmmm...
To do:
Needs research
0x10 0x4 PolygonSoupPoly* mpaPolygons Polygons
0x14 0x4 PolygonSoupVertex* mpaVertices Packed vertices
Hmmm...
Hmmm...
To do:
Unpacking info
0x18 0x2 uint16_t mu16DataSize Combined length of soup, polygons, and vertices
0x1A 0x1 uint8_t mu8TotalNumPolys Number of polygons
0x1B 0x1 uint8_t mu8NumQuads Number of quads
0x1C 0x1 uint8_t mu8NumVertices Number of vertices
0x1D 0x3 Padding

64-bit

Offset Length Type Name Description Comments
0x0 0xC int32_t[3] maiVertexOffsets
Hmmm...
Hmmm...
To do:
Needs research
0xC 0x4 float32_t mfComprGranularity
Hmmm...
Hmmm...
To do:
Needs research
0x10 0x8 PolygonSoupPoly* mpaPolygons Polygons
0x18 0x8 PolygonSoupVertex* mpaVertices Packed vertices
Hmmm...
Hmmm...
To do:
Unpacking info
0x20 0x2 uint16_t mu16DataSize Combined length of soup, polygons, and vertices
0x22 0x1 uint8_t mu8TotalNumPolys Number of polygons
0x23 0x1 uint8_t mu8NumQuads Number of quads
0x24 0x1 uint8_t mu8NumVertices Number of vertices
0x25 0xB Padding

CgsGeometric::PolygonSoupPoly

Offset Length Type Name Description Comments
0x0 0x4 uint32_t muCollisionTag Collision tag See CollisionTag
0x4 0x4 uint8_t[4] mau8VertexIndices Vertex indices
0x8 0x4 uint8_t[4] mau8EdgeCosines Compressed edge cosines To get radians: value / 255 * π
Sine of radians is uncompressed edge cosine
Hmmm...
Hmmm...
To do:
Confirm this is the same in BP as in NFS.

CgsGeometric::PolygonSoupVertex

Offset Length Type Name Description Comments
0x0 0x2 uint16_t mu16X
0x2 0x2 uint16_t mu16Y
0x4 0x2 uint16_t mu16Z

Collision tag

BrnWorld::CollisionTag

IMPORTANT: The position of the group and material tags are flipped in soups, so the material tag is at offset 0x0 and the group tag is at 0x2. This is likely a side effect of the field being written as uint32_t instead of CollisionTag. It is also byteswapped as a 32-bit field on little endian systems, not two 16-bit fields.

The above behavior has been confirmed by CollisionDebugComponent::DrawCollisionPolyCallback(), which modifies the value from its uint32_t parameter luPolyTag, flipping the field positions before using it as a CollisionTag when calling GetPolyColour().

Offset Length Type Name Description Comments
0x0 0x2 uint16_t mu16GroupTag Group tag
0x2 0x2 uint16_t mu16MaterialTag Material tag
Group tag bit fields
Offset (bits) Length (bits) Name Description Comments
0 1 Highest bit Always set
1 15 AI section index From AI Sections resource
Material tag bit fields
Offset (bits) Length (bits) Name Description Comments
0 1 Highest bit Always set
1 3 Flags See collision tag flags
4 2 Reserved Reserved/unused space
Hmmm...
Hmmm...
To do:
Not unused anymore. Both bits can be set, sometimes together. Flags?
6 6 Surface ID From surface list
12 4 Traffic info/data/direction If 0, GetTrafficInfo() returns E_TRAFFIC_DIRECTION_NO_LANES.
If 1, it returns E_TRAFFIC_DIRECTION_UNKNOWN.
Otherwise, E_TRAFFIC_DIRECTION_VALID is returned.
If the traffic direction is valid, the traffic angle parameter is set.
To get the angle (in radians), do: (value - 2) / 14 * 2π
2 is the minimum angle and 14 is the value range.
See also: TrafficDirection

Example collision tag

Taken from a soup, so keep the flipped field positions in mind.

Hex: 84 20 95 C1
Bit value 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0
Parsed value 1 Flags: 0x4000 N/A 2 0
Description Flags: Fatal Reserved Surface index 2 No lanes
(cont.) 1 0 0 1 1 0 1 1 1 1 1 1 0 1 0 1
1 0x1BF5
AI section index 7157

Boxes

CgsGeometric::AxisAlignedBox

Offset Length Type Name Description Comments
0x0 0x10 Vector3 mMin
0x10 0x10 Vector3 mMax

CgsGeometric::AxisAlignedBox4

Offset Length Type Name Description Comments
0x0 0x10 Vector4 mAabbMinX
0x10 0x10 Vector4 mAabbMinY
0x20 0x10 Vector4 mAabbMinZ
0x30 0x10 Vector4 mAabbMaxX
0x40 0x10 Vector4 mAabbMaxY
0x50 0x10 Vector4 mAabbMaxZ
0x60 0x10 Mask4 mValidMasks

Enumerations

Collision tag flags

Name Value Comments
KU_COLLISION_FLAG_SUPERFATAL 0x1000
KU_COLLISION_FLAG_DRIVEABLE 0x2000
KU_COLLISION_FLAG_FATAL 0x4000

BrnWorld::TrafficDirection

Name Value Comments
E_TRAFFIC_DIRECTION_VALID 0
E_TRAFFIC_DIRECTION_UNKNOWN 1
E_TRAFFIC_DIRECTION_NO_LANES 2