Skip to content
Brass Orrery

Orrery Terrain · OrreryTerrainRenderer module · class

FTerrainGrassSystem

Experimental

Grass for one world's terrain.

Declaration

class FTerrainGrassSystem : public FGCObject
Header
#include "Grass/TerrainGrassSystem.h"
Module
PublicDependencyModuleNames.Add("OrreryTerrainRenderer"); in your module’s Build.cs.
Stability
Experimental: supported, may change in a minor version, with a changelog line.
Thread
Game thread only.
Derives from
FGCObject

Description

Per resident chunk it keeps the latest posts (shared, never copied). A (sub-cell, variety) is wanted while some view is within the variety's end cull distance × r.OrreryTerrain.Grass.CullDistanceScale × grass.CullDistanceScale × GuardBand of the sub-cell's bounds, and stops being wanted, its component released at once, beyond × DiscardBand; an end cull of 0 wants every sub-cell of every resident chunk. A build is one worker task per (chunk, variety): ScatterDiffSubCells against the posts the last build targeted, then ScatterSubCell, the transforms and the cluster tree for each sub-cell that is wanted and either dirty or not built yet. No result is shown before the second tick after its posts arrived (the tick the heightfield shows them), and a result whose sub-cell is no longer wanted is dropped.

An edit's refresh (new posts under a chunk's built grass) builds every variety of the chunk at once, oldest edit first, the chunk's tasks sharing one diff, at most .Grass.EditChunks chunks in flight and outside .Grass.MaxTasks; it is shown whole, every variety and dirty sub-cell of the chunk in one tick, once all its tasks have finished, within .Grass.EditBudgetMs (at least one chunk a tick). So the grass under an edit follows each new revision of its posts on the tick the heightfield does, whatever the frame time, and its edge is the paint's or the ground's, never a cell's. Sub-cells that enter the band build nearest first, at most .Grass.MaxTasks tasks in flight, and are shown oldest first within .Grass.AcceptBudgetMs (at least one a tick). A clean sub-cell keeps its component, at the datum it was built with. With .Grass.DuringStroke 0 an open stroke holds the refresh: a newly wanted sub-cell is built against the posts the others were built from, so the grass stays consistent until the stroke ends.

Scalability is checked once per tick (cached console variables): a change of grass.densityScale or r.OrreryTerrain.Grass.DensityScale (the product, clamped to 0..1, thins varieties whose grass type enables density scaling, so a lower value shows a subset), of grass.CullDistanceScale or r.OrreryTerrain.Grass.CullDistanceScale, or of sg.FoliageQuality (the varieties' per-quality density and cull distances are read again) rebuilds every built cell; the components stay until their replacement is shown, so the grass never blinks out. A change that adds or removes a variety releases everything first.

A tick visits only the chunks whose grass is wanted, built or in flight, and those within some variety's guard band; every other resident chunk costs one box test, and a visited chunk skips a variety with nothing wanted whose band it is outside So a frame with no grass in range costs about one box test per resident chunk, not chunk × variety, and the grass built is the same as a walk of every chunk × variety (r.OrreryTerrain.Grass.Gate 0, a development A/B).

Holds UObjects in plain members and reports them itself (FGCObject); no UPROPERTY, no hot data on the GC's path.

Note.

Game thread only.

Functions

  • ShouldRunstatic

    The real gate: grass runs only in a process that renders and is not a dedicated server.

  • Createstatic

    Make the grass system of World, or null where grass must not run (ShouldRun with IsRunningDedicatedServer(), the world's net mode and FApp::CanEverRender()).

  • SetLayerSet

    Use this layer set's grass: releases every component and loads its grass types asynchronously; building starts on the first tick after they have loaded.

  • GetLayerSet
  • SetHost

    The terrain actor the components belong to (their outer), or null when the terrain went away.

  • OnPosts

    A chunk's new posts (keeps the reference; empty posts evict the chunk).

  • OnEvicted

    A chunk left residency: its components go back to the pool and its results in flight are dropped.

  • Tick

    Advance one frame: collect finished tasks, accept results within the budget, update the bands and launch tasks.

  • IsIdle

    Whether no grass build is pending: the varieties are loaded, no chunk's posts wait for the next tick, no task runs, no result waits to be accepted, and no wanted sub-cell is unbuilt or built against older posts.

  • NumComponents
  • NumInstances
  • NumTasksInFlight
  • NumResultsWaiting
  • NumResidentChunks
  • GetVarieties
  • GetCounters
  • GetPresentProfile

    The component layer's running profile (empty before the host is set).

  • GetScatterSettings

    The kernel settings variety VarietyIndex is placed with this tick (the world seed and the density scaling).

  • GetChunkRules

    The kernel rules chunk Tile is placed with: the material's auto rules with the chunk's noise origin.

  • ForEachComponent

    Visit every live component in canonical order (tile Y, tile X, variety, sub-cell).

  • AddReferencedObjects
  • GetReferencerName