detail_object_collection

Detail objects are 2D sprites which can be painted onto the BSP using Sapien. They are used to add grass and other small details which fade in/out by distance. They can also take on the colour tint of the shader_environment base map where painted.

Placement

You can paint detail objects into a BSP using Sapien. Some tips to keep in mind are:

  • Avoid painting detail objects in BSP overlap areas since they may noticeably change during BSP transitions.
  • Use a low density; detail objects are not depth-sorted for rendering so dense clusters of them will appear to render out of order from certain viewing angles.
  • Changes to the detail object tag require reloading Sapien to take effect. Some changes require repainting.

Detail objects are stored in the BSP tag rather than the scenario, and it's easy to accidentally clear them. Activities which modify the BSP tag, like changing cluster properties (weather, background sounds), will result in all detail objects being cleared. You should usually leave painting detail objects until the end of level creation, once the BSP is finalized.

Both CE and H1A Sapien have a bug where loaded detail objects are incorrectly saved back to the BSP tag with their global z offset added. This means opening the scenario and causing the BSP to be resaved (e.g. by painting more detail objects) will cause all previous detail objects to be shifted vertically by their Z offset. Changes to just the scenario or resaving the BSP tag in Guerilla do not cause this. Again, leave painting detail objects to the end of level creation.

Colour and lighting

Detail objects can pick up colour and shading from the local environment. Their final colour results from a combination of:

This final colour is "baked" into the BSP tag for each detail object instance. Changing any of the above inputs, including the level's lightmaps, requires relighting detail objects to calculate their new colour. You can do this in Sapien using Shift + Control + L while Detail objects is active in the Hierarchy window.

Cells

Detail objects are grouped into cells, which are 8x8 world unit axis-aligned boxes that exist only where detail objects have been painted. Cell boundaries always exist on multiples of 8 world units. The game will render details objects for any cells within 8 world units of the camera, so setting far fade distance higher than 8 will result in the detail objects abruptly disappearing when their cell is out of range.

You can visualize cell activity in Standaone with debug_detail_objects. Sapien will also display a blue bounding box around all cells which would be active from the point in the level where the cursor points.

Empty cells are removed when the BSP tag is saved in Sapien.

Related HaloScript

Function/global

Type

(debug_detail_objects [boolean])

When enabled, active detail object cells will be outlined in blue and individual detail objects are highlighted with red markers.

Global

Structure and fields

FieldTypeComments
collection typeenum

Sets how the detail objects are oriented.

OptionValueComments
screen facing0x0

The detail objects always face the viewer directly, even when standing above them. This type does not render in H1A.

viewer facing0x1

The detail objects stand vertically but always spin to face toward the viewer. This type is ideal for grass.

global z offsetfloat
  • Unit: world units

Sets a Z offset added to loaded detail objects to either raise them above the ground or lower them into it, e.g. with a small negative value to compensate for an empty border in the texture. This can be changed without having to repaint. You do not need to set a Z offset to raise sprites so their bottom edge touches the ground; the game already does this. The Z offset is just for fine-tuning height.

Note that Sapien does not account for this modified Z height when resaving the BSP tag, causing detail objects to be shifted vertically. If you wish to avoid this, ensure your sprites are painted to the bottom of the texture and set this value to 0.

Historial tag extractors like the MEK have also not accounted for this offset when extracting the BSP tag, resulting in incorrect detail object locations. Ensure you're using an up-to-date extractor like Invader.

sprite plateTagDependency: bitmap
  • Non-null

A reference to a bitmap which contains sprites for the detail object. This bitmap must have sprites type or the game will crash. The bitmap can contain multiple sequences, indexed by each detail object type's sequence index. The alpha channel of the sprite determines its transparency.

typesBlock
  • HEK max count: 16
FieldTypeComments
nameTagString

A name which makes this type easy to identify when painting in Sapien.

sequence indexuint8

Sets the sequence from the sprite plate used for this type, since bitmaps can contain multiple sequences each with multiple sprites. Sprite plates with a single sequence should just use index 0.

flagsbitfield

Flags altering the appearance of the detail object.

FlagMaskComments
unused a0x1
  • Unused
unused b0x2
  • Unused
interpolate color in hsv0x4

Determines if random colour variation is interpolated in HSV space instead of RGB. This results in colours transitioning through intermediate hues like a rainbow.

more colors0x8

If set, HSV interpolation goes the "long way" around.

first sprite indexuint8
  • Cache only
sprite countuint8
  • Cache only
color override factorfloat
  • Min: 0
  • Max: 1

Fraction of detail object colour to use instead of the base map colour in the environment. A value of 0 means the detail objects colours are fully multiplied by the sampled colour of the base map they are painted over, while a value of 1 means they will be unaffected by the environment and look like the sprite bitmap. This setting doesn't affect sampling of lightmaps.

Changing this setting requires relighting detail objects.

near fade distancefloat
  • Unit: world units

Sets the distance from the camera's view plane where the detail objects start to fade out. Detail objects closer than this will be opaque.

far fade distancefloat
  • Unit: world units

Sets the distance from the camera's view plane where the detail objects fade out completely. This should usually be no higher than 8, since only detail objects belong to cells within 8 units are rendered.

sizefloat
  • Unit: world units per pixel

Sets the size of a pixel of the detail object. For example, a sprite that is 16 pixels tall at a scale of 0.004 will be 16 * 0.004 = 0.064 world units tall ingame.

minimum colorColorRGB

Sets the start of the colour variation range. Set to white for no colour variation. Halo will sample a random value from this range to multiply against the detail object texture. The interpolation can be done in either RGB or HSV space depending on the flags.

maximum colorColorRGB

Sets the end of the colour variation range. Set to white for no colour variation.

ambient colorColorARGBInt

Sets the ambient light colour of the detail objects, which is multiplied against the texure when rendering. This takes precedence over the sampled lightmap colour depending on the alpha value, with 0 being lightmap only and 255 being this ambient colour only.

RGB Color with alpha, with 8-bit color depth per channel (0-255)

FieldTypeComments
alphauint8
reduint8
greenuint8
blueuint8

Acknowledgements

Thanks to the following individuals for their research or contributions to this topic:

  • Conscars (Testing tag fields)
  • Kavawuvi (Invader tag definitions)
  • MosesOfEgypt (Tag structure research)