Grass library and terrain selection
Grass and low clutter use a world-level library and terrain rules. The stored chain supplies models, group choices, densities and scale ranges; it does not supply the resulting per-plant position list. Exact runtime scattering remains unresolved. Observed · stored library and model bodies Unknown · scatter producer
The whole-world cell lists GrassEntityGroup, which reaches SETUP_GrassUS_NAT. Its GrassComponent references the library, GrassSettings and 46 managed model Entities. A model index is its position in that array, matching GrassModelID and its library settings index on all 46 models; it is not the number in its Entity name. Proven · 46-way identity join Observed · world chain
Each of the 46 GrassEntity_Model N Entities has a GrassVisual, a Visual-derived class with one extra stored byte, whose instance is a GrassVisualInstance (0xD4569683, derived from MeshInstanceData) holding zero matrices. These Entities are the model library; plant positions are not stored in them. The setup GrassComponent bodies on SETUP_GrassUS_NAT (two stored copies) are 988 and 1,012 bytes. Observed · all 46 model Entities
Library structure
Section titled “Library structure”The only examined GrassPatternLibrary is 30,247 bytes and closes exactly: byte 1, u32 model count, byte 0, 46 pairs of 72-byte GrassModel and 60-byte BoundingVolume objects, zero u32, 190 groups and a 443-byte tail. The groups contain 218 rules: 61 empty groups, 57 with one rule, 55 with two and 17 with three. Proven · complete library
Includes the twelve-byte object header; all 218 rules of the complete installed library are consumed exactly.
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 8 | u64 | object identity | Proven | |
| 0x8 | 4 | u32 = 0xA6FC073D | GrassPatternElement class | Proven | |
| 0xC | 2 | u16 | GrassModelIndex | Proven | |
| 0xE | 1 | u8 | TilingLogCount | Proven | |
| 0xF | 4 | f32 | Density | Proven | |
| 0x13 | 4 | f32 | TiltFactor | Proven | |
| 0x17 | 1 | u8 | ScalingEnabled | Proven | |
| 0x18 | 4 | f32 | ScaleA | Proven | |
| 0x1C | 4 | f32 | ScaleB | Proven | |
| 0x20 | 1 | u8 | HeightScalingEnabled | Proven | |
| 0x21 | 4 | f32 | HeightScaleA | Proven | |
| 0x25 | 4 | f32 | HeightScaleB | Proven | |
| 0x29 | 4 | f32 | unnamed float | Unknown | 5 on 145 rules; 0 on 66; also 2.5 |
| 0x2D | 49 | bytes | remaining fields | Unknown | includes byte 100, a u16, ten floats and six final bytes; semantics not established |
Model settings include ZOffset, terrain-normal following, softness, normal bend, translucency and impostor controls. Their trailing LOD table commonly stores 00 01 02 03 03 and distance triples 5/10/20, 10/20/40 or 20/40/80. The interpretation of the latter as metre distances follows names and values. Proven · all 46 settings objects Inferred · distance units
Each model Entity directly names a GrassMesh_Model with three ranges carrying the same material, representing model LODs rather than three independently chosen materials. The material family is Clutters_Grass. Proven · all 46 model/mesh joins
Terrain group and weight
Section titled “Terrain group and weight”The terrain picker first gets a group from the material byte through the library’s 256-entry table. Block 5 overrides that choice unless its value is 0xFE, which leaves the material-derived group. 0xFF denotes no group. The table is all 0xFF except its final entry in the examined library, making an unpainted 0xFE override commonly yield no grass, without making 0xFE itself the no-grass code. Observed · picker disassembly and complete library table
Block 4 supplies a weight: w=value>>1, except value 1 also counts as weight 1. Weight zero disables the group. Every node stores block-4 value 0x60, giving weight 0x30; the picker builds 17,424 group/weight pairs and a short group summary per node. Proven · all-node constant raster Observed · picker
Five rules in groups 185–189 refer to model indices 46–50 outside the 46-model set. No measured terrain override reaches those groups. A rule existing in the library is therefore not evidence that it is active terrain content. Observed · library and terrain value joins
Draw data and settings
Section titled “Draw data and settings”GrassSettings includes WorldExtent 16,384, WorldMinZ 0, WorldMaxZ 7,168 and a visibility-distance value 250. Four tables of sixteen u16 start-distance values differ by model class. Not every remaining setting field has a reconciled serialization meaning. Observed · settings body and registry
The draw shaders consume instance transforms and fade data. The matrix portion is three float4 rows rather than a stored full 4×4 array; apparent four-vector records include other instance data. Two compute programs previously associated with grass are named WorldParticles_EmitEntity and WorldParticles_EmitTerrain, and are not evidence for grass scattering. Observed · shader declarations and engine shader names
The exact instance count, within-cell position, random seed, rotation, slope rejection and scale sampling remain unresolved. Density and scale-range fields are stored; their names alone do not prove a particular stochastic generator. Unknown