STUFF System

From Mod Wiki

The STUFF System is a quick and easy way of distributing thousands of models across a terrain. It is mainly used for adding grass, plants, small shrubs, stones and twigs on top of the MegaTexture.

Overview

A screenshot comparison from Valley showing the difference between the bare terrain and the STUFF distribution.

You can place "STUFF" in your map with the DistributeStuff console command. This command takes a single parameter, the filename of a "stuff generation" (.sg) file. See the reference section below to find how these scripts are set up.

After running DistributeStuff, a stuff.clustb file will appear in the "/base/stuff/[mapname]" directory, this file contains the actual positions of all the scattered objects, so the mask images and the .sg file do not need to distributed with the game.

Making It Appear In The Level

You need a "stuffsystem" entity in your map before the STUFF will be visible. The following entity is all you need.

{
"classname" "stuffsystem"
"name" "my_stuff"
"origin" "0 0 0"
}

Compile your map with this entity added before doing any of the following steps, or you may not be able to view your STUFF distribution in-game.

Working Conventions

  • .stuff reference files should be stored in the following location: "base/stuff/[mapname].stuff
  • .sg scripts should be stored in the following location: "base/stuff/[mapname]/[mapname].sg"
  • Related media (masks, STUFF models and colour maps) should be stored in the same folder as the .sg file, for ease of access.
    • Keep STUFF models unique on a per-map basis so you can easily adjust one map's "STUFF" without affecting any other levels accidentally.

StuffType (.stuff) Reference

.stuff files specify the different types of model you can scatter around, the declarations in these files are referenced by the STUFF system. A simple example:

stuffType [mapname]/grass {
	Model	"stuff/[mapname]/grass_01.ase"
	Model	"stuff/[mapname]/grass_02.lwo" 
}

stuffType [mapname]/plants {
	Model	"stuff/[mapname]/plant_01.lwo"
	Model	"stuff/[mapname]/plant_02.lwo" 
}
  • stuffType is the declaration name that is referenced by other parts of the STUFF system (.sg and .clustb files refer to this).
  • Model should contain a path to a valid model (ASE, LWO and OBJ should all work). This model is scattered by this stuff declaration. If more than one model is specified, each will be randomly chosen and placed when the distributeStuff command is run.
    • More unique models can lead to a more natural-looking distribution, especially in the case of shrubs and plants.
    • You can put the same model multiple times in a single declaration, that way the chances of that model being chosen compared to other models are bigger. So if you put 9 times one model and 1 time another, 9 out of 10 models (on average) will be the first model.

StuffGeneration (.sg) reference

Here is an example script:

 version 1
 {
 	model "models/terrain/[mapname].lwo"
 }
sdStuffLayer {
	Density  10
	Distancescale 1
	Distribution Area
	StuffType "[mapname]/grass"
	Mask "stuff/[mapname]/mask_grass.tga"
	ColorMap "stuff/[mapname]/grass_colour.tga"
}
 sdStuffLayer {
 	Density 4
 	Distancescale 2
 	Distribution Area
 	StuffType "[mapname]/plants"
 	Mask "stuff/[mapname]/mask_plants.tga"
 	ColorMap "stuff/[mapname]/plants_color.tga"
 }
  • version should always be set to 1.
  • model should point to your map's terrain mesh.
  • sdStuffLayer is a single layer over the whole terrain mesh that distributes STUFF models based on the following values:
    • Density is a value which behaves differently depending on the Distribution type used. See below for details.
    • Distribution specifies how the STUFF is distributed (positioned) over the terrain, and can be one of the following values:
      • Area means the STUFF is uniformly distributed over the whole terrain, independent of the underlying geometry. In this case, the Density value specifies the number of objects "per square unit". You will nearly always want to use this type of distribution.
      • Vertex places a single STUFF model on every vertex of the terrain mesh. In this case, the Density value is unused.
      • Triangle places the same number of STUFF models on every triangle of the terrain mesh. In this case, the Density value specifies how many objects should be created per triangle.
    • Distancescale will scale all distances used during rendering of this STUFF layer by an arbitrary amount. Setting this value to 1 will render STUFF models to the extent of the r_stuffFadeEnd cvar. Setting this value to 2 will make the STUFF models fade out twice as close, etc. This value should never be set lower than 1, as this will lead to visual "popping" errors in the distance.
    • Mask specifies a grayscale TGA file that defines the density of STUFF models. White means full density (as specified by the density parameter) gray to black means successively lower densities until there are no objects placed at all. This parameter is optional (but recommended!), as the default is a fully white map.
    • ColorMap specifies an RGB colour TGA file that defines the color of the individual stuff objects. In this way certain areas can have drier brown grass for example. This parameter is optional, the default is a fully white map.
    • CutOff is an integer defining at wich value stuff should stop appearing in your mask. The default value is 16 which means grayscale values in the mask lower than 16 will not spawn any stuff.
    • Orientation will control the orientation of the STUFF models, there are two options:
      • local orients STUFF models according to the normals of the model used for distribution (default behaviour).
      • world will always orient STUFF models upwards (ETQW never uses this, since local looks more natural).

You can define as many sdStuffLayers in a .sg file as you like, but bear in mind that each one will be an additional rendering batch. Try and use as few layers as possible to achieve the visual effect you want.

distributeStuff

Once you have set up your .stuff and .sg files, you can generate your STUFF cluster (.clustb) file by running the following command in the game console:

distributeStuff stuff/[mapname]/[mapname].sg

Note you can run distributeStuff with your map loaded in game, then use reloadmodels to reload the STUFF cluster and see your changes immediately.

Performance Notes

As STUFF potentially allows you to have thousands of objects added to the map by just a few parameters you should be careful not to overuse STUFF. Some performance hints:

  • Keep the density as low as possible for the effect you want, as this is the parameter that affects the number of objects that get generated. You could in theory have a dark gray mask and a higher density (resulting in the same overall number of objects) but it's a better idea to keep distribution masks "normalized" (ie. the full range from black to white).
  • With grass, the actual draw speed is not necessarily related to the total number of grass plants visible, the speed hit is when a lot of alpha-tested grass textures cover the same screen area (causing a high amount of overdraw) so it is better to render sparse grass to a further distance than dense grass that fades fast.
    • To this end, it makes sense to have two grass layers - one would be sparse and fade to the distance, the other would fade very close but be more dense. This gives a more pleasing visual result with less performance loss.