Vegetation placement based on slope orientation

Hillside slope orientation is a common form of ecological patterning for vegetation that helps determine preferred zones for a given sub-species within a set biome, or habitat. This allows for additional landform based patterning of forests, shrublands, etc., and helps simulate different vegetation patterns when approaching a location from different angles.

Ideally this kind of control would be based on the hillside concepts of sunside, shadeside, windward, and leeward, but for most cases simple cardinal direction control is sufficient. Basic proof of concept below.

Lumberyard version: 1.10.0

File: dev\Gems\Gestures\Code\Sandbox\Editor\VegetationObject.h

Insert at line: 127 - Operators

void SetOrientationSlopeCutoff(float slopeCutoff) { mv_orientation_slope_cutoff = slopeCutoff; };
void SetNorthFacing(bool nFace) { mv_northFacing = nFace; };
void SetEastFacing(bool eFace) { mv_eastFacing = eFace; };
void SetSouthFacing(bool sFace) { mv_southFacing = sFace; };
void SetWestFacing(bool wFace) { mv_westFacing = wFace; };

Insert at line: 147 - Accessors

float GetOrientationSlopeCutoff() const { return mv_orientation_slope_cutoff; };
bool GetNorthFacing() const { return mv_northFacing; };
bool GetEastFacing() const { return mv_eastFacing; };
bool GetSouthFacing() const { return mv_southFacing; };
bool GetWestFacing() const { return mv_westFacing; };

Insert at line: 291 - Variables

CSmartVariable<float> mv_orientation_slope_cutoff;
CSmartVariable<bool> mv_northFacing;
CSmartVariable<bool> mv_eastFacing;
CSmartVariable<bool> mv_southFacing;
CSmartVariable<bool> mv_westFacing;

File: dev\Gems\Gestures\Code\Sandbox\Editor\VegetationObject.cpp

Insert at line: 127 - Init variables

mv_orientation_slope_cutoff = 15;
mv_northFacing = true;
mv_eastFacing = true;
mv_southFacing = true;
mv_westFacing = true;

Insert at line: 145 - Add variable controls to tool ui

AddVariable(mv_orientation_slope_cutoff, "Orientation Slope Cutoff", functor(*this, &CVegetationObject::OnVarChange));
AddVariable(mv_northFacing, "NorthFacing", functor(*this, &CVegetationObject::OnVarChange));
AddVariable(mv_eastFacing, "EastFacing", functor(*this, &CVegetationObject::OnVarChange));
AddVariable(mv_southFacing, "SouthFacing", functor(*this, &CVegetationObject::OnVarChange));
AddVariable(mv_westFacing, "WestFacing", functor(*this, &CVegetationObject::OnVarChange));

File: dev\Gems\Gestures\Code\Sandbox\Editor\VegetationMap.cpp

Insert at line: 1315 - PaintBrush()

float OrientationSlopeCutoff = object->GetOrientationSlopeCutoff();
bool NorthFacing = object->GetNorthFacing();
bool EastFacing = object->GetEastFacing();
bool SouthFacing = object->GetSouthFacing();
bool WestFacing = object->GetWestFacing();

Insert at line: 1394 - PaintBrush()

	// Calculate the slope orientation for this spot
const Vec3 vTerrainNormal = GetIEditor()->Get3DEngine()->GetTerrainSurfaceNormal(*pPos);
float vTerrainOrientation = atan2(vTerrainNormal.y, vTerrainNormal.x) * (180.0f / gf_PI);
if (vTerrainOrientation < 0)
{
vTerrainOrientation += 360;
}
if (vTerrainOrientation > 360)
{
vTerrainOrientation -= 360;
}
if (slope > OrientationSlopeCutoff)
{
if (!NorthFacing)
{
if (vTerrainOrientation >= 45.0f && vTerrainOrientation <= 135.0f)
{
continue;
}
}
if (!EastFacing)
{
if (vTerrainOrientation >= 135.0f && vTerrainOrientation <= 225.0f)
{
continue;
}
}
if (!SouthFacing)
{
if (vTerrainOrientation >= 225.0f && vTerrainOrientation <= 315.0f)
{
continue;
}
}
if (!WestFacing)
{
if (vTerrainOrientation >= 315.0f || (vTerrainOrientation <= 45.0f && vTerrainOrientation >= 0))
{
continue;
}
}
}

Thanks! This is a great idea for broadening the options for vegetation placement. We’ve noted this change and we’ll see if there’s a way to work this concept in as we revisit the vegetation system. For consistency with other parameters, we would likely generalize this to be more of a min / max angle style of parameter, as opposed to cardinal directions. We appreciate the contribution! Going forward, for anything more you would like to contribute please use GitHub as those submissions go directly to the team now.