Reduce tree and object cover on steep slopes, configurable through materials.xml
This commit is contained in:
@@ -320,6 +320,9 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
||||
building_large_max_width = props->getFloatValue("building-large-max-width-m", 75.0);
|
||||
building_large_min_depth = props->getFloatValue("building-large-min-depth-m", 50.0);
|
||||
building_large_max_depth = props->getFloatValue("building-large-max-depth-m", 75.0);
|
||||
|
||||
cos_object_max_density_slope_angle = cos(props->getFloatValue("object-max-density-angle-deg", 20.0) * osg::PI/180.0);
|
||||
cos_object_zero_density_slope_angle = cos(props->getFloatValue("object-zero-density-angle-deg", 30.0) * osg::PI/180.0);
|
||||
|
||||
// Random vegetation properties
|
||||
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
||||
@@ -327,6 +330,8 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
||||
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
||||
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
||||
tree_varieties = props->getIntValue("tree-varieties", 1);
|
||||
cos_tree_max_density_slope_angle = cos(props->getFloatValue("tree-max-density-angle-deg", 45.0) * osg::PI/180.0);
|
||||
cos_tree_zero_density_slope_angle = cos(props->getFloatValue("tree-zero-density-angle-deg", 60.0) * osg::PI/180.0);
|
||||
|
||||
const SGPropertyNode* treeTexNode = props->getChild("tree-texture");
|
||||
|
||||
|
||||
@@ -210,6 +210,9 @@ public:
|
||||
inline double get_building_large_max_width () const { return building_large_max_width; }
|
||||
inline double get_building_large_min_depth () const { return building_large_min_depth; }
|
||||
inline double get_building_large_max_depth () const { return building_large_max_depth; }
|
||||
|
||||
inline double get_cos_object_max_density_slope_angle () const { return cos_object_max_density_slope_angle; }
|
||||
inline double get_cos_object_zero_density_slope_angle () const { return cos_object_zero_density_slope_angle; }
|
||||
|
||||
/**
|
||||
* Get the wood coverage.
|
||||
@@ -255,6 +258,24 @@ public:
|
||||
*/
|
||||
inline std::string get_tree_texture () const { return tree_texture; }
|
||||
|
||||
/**
|
||||
* Get the cosine of the maximum tree density slope angle. We
|
||||
* use the cosine as it can be compared directly to the z component
|
||||
* of a triangle normal.
|
||||
*
|
||||
* @return the cosine of the maximum tree density slope angle.
|
||||
*/
|
||||
inline double get_cos_tree_max_density_slope_angle () const { return cos_tree_max_density_slope_angle; }
|
||||
|
||||
/**
|
||||
* Get the cosine of the maximum tree density slope angle. We
|
||||
* use the cosine as it can be compared directly to the z component
|
||||
* of a triangle normal.
|
||||
*
|
||||
* @return the cosine of the maximum tree density slope angle.
|
||||
*/
|
||||
inline double get_cos_tree_zero_density_slope_angle () const { return cos_tree_zero_density_slope_angle; }
|
||||
|
||||
/**
|
||||
* Get the list of names for this material
|
||||
*/
|
||||
@@ -301,7 +322,7 @@ public:
|
||||
return SGVec2f((0 < tex_width) ? 1000.0f/tex_width : 1.0f,
|
||||
(0 < tex_height) ? 1000.0f/tex_height : 1.0f);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -394,6 +415,12 @@ private:
|
||||
double building_large_min_depth;
|
||||
double building_large_max_depth;
|
||||
|
||||
// Cosine of the angle of maximum and zero density,
|
||||
// used to stop buildings and random objects from being
|
||||
// created on too steep a slope.
|
||||
double cos_object_max_density_slope_angle;
|
||||
double cos_object_zero_density_slope_angle;
|
||||
|
||||
// coverage of woods
|
||||
double wood_coverage;
|
||||
|
||||
@@ -408,6 +435,11 @@ private:
|
||||
|
||||
// Number of varieties of tree texture
|
||||
int tree_varieties;
|
||||
|
||||
// cosine of the tile angle of maximum and zero density,
|
||||
// used to stop trees from being created on too steep a slope.
|
||||
double cos_tree_max_density_slope_angle;
|
||||
double cos_tree_zero_density_slope_angle;
|
||||
|
||||
// material properties
|
||||
SGVec4f ambient, diffuse, specular, emission;
|
||||
|
||||
@@ -173,6 +173,8 @@ public:
|
||||
void addRandomTreePoints(float wood_coverage,
|
||||
osg::Texture2D* object_mask,
|
||||
float vegetation_density,
|
||||
float cos_max_density_angle,
|
||||
float cos_zero_density_angle,
|
||||
std::vector<SGVec3f>& points)
|
||||
{
|
||||
unsigned num = getNumTriangles();
|
||||
@@ -186,21 +188,33 @@ public:
|
||||
SGVec2f t2 = getVertex(triangleRef[2]).texCoord;
|
||||
SGVec3f normal = cross(v1 - v0, v2 - v0);
|
||||
|
||||
// Ensure the slope isn't too steep by checking the
|
||||
// cos of the angle between the slope normal and the
|
||||
// vertical (conveniently the z-component of the normalized
|
||||
// normal) and values passed in.
|
||||
float alpha = normalize(normal).z();
|
||||
float slope_density = 1.0;
|
||||
|
||||
if (alpha < cos_zero_density_angle)
|
||||
continue; // Too steep for any vegetation
|
||||
|
||||
if (alpha < cos_max_density_angle) {
|
||||
slope_density =
|
||||
(alpha - cos_zero_density_angle) / (cos_max_density_angle - cos_zero_density_angle);
|
||||
}
|
||||
|
||||
// Compute the area
|
||||
float area = 0.5f*length(normal);
|
||||
if (area <= SGLimitsf::min())
|
||||
continue;
|
||||
|
||||
// For partial units of area, use a zombie door method to
|
||||
// create the proper random chance of a point being created
|
||||
// for this triangle
|
||||
float unit = area + mt_rand(&seed)*wood_coverage;
|
||||
|
||||
// Vegetation density is linear, while we're creating woodland
|
||||
// by area.
|
||||
int woodcount = (int) (vegetation_density *
|
||||
vegetation_density *
|
||||
unit / wood_coverage);
|
||||
|
||||
// Determine the number of trees, taking into account vegetation
|
||||
// density (which is linear) and the slope density factor.
|
||||
// Use a zombie door method to create the proper random chance
|
||||
// of a tree being created for partial values.
|
||||
int woodcount = (int) (vegetation_density * vegetation_density *
|
||||
slope_density *
|
||||
area / wood_coverage + mt_rand(&seed));
|
||||
|
||||
for (int j = 0; j < woodcount; j++) {
|
||||
float a = mt_rand(&seed);
|
||||
|
||||
@@ -476,10 +476,11 @@ struct SGTileGeometryBin {
|
||||
if (!mat)
|
||||
continue;
|
||||
|
||||
osg::Texture2D* object_mask = mat->get_object_mask(triangleBin);
|
||||
|
||||
int group_count = mat->get_object_group_count();
|
||||
float building_coverage = mat->get_building_coverage();
|
||||
osg::Texture2D* object_mask = mat->get_object_mask(triangleBin);
|
||||
int group_count = mat->get_object_group_count();
|
||||
float building_coverage = mat->get_building_coverage();
|
||||
float cos_zero_density_angle = mat->get_cos_object_zero_density_slope_angle();
|
||||
float cos_max_density_angle = mat->get_cos_object_max_density_slope_angle();
|
||||
|
||||
bool found = false;
|
||||
SGBuildingBin* bin = NULL;
|
||||
@@ -516,6 +517,19 @@ struct SGTileGeometryBin {
|
||||
SGVec2f t1 = triangleBin.getVertex(triangleRef[2]).texCoord - torigin;
|
||||
SGVec3f normal = cross(v0, v1);
|
||||
|
||||
// Ensure the slope isn't too steep by checking the
|
||||
// cos of the angle between the slope normal and the
|
||||
// vertical (conveniently the z-component of the normalized
|
||||
// normal) and values passed in.
|
||||
float cos = normalize(normal).z();
|
||||
float slope_density = 1.0;
|
||||
if (cos < cos_zero_density_angle) continue; // Too steep for any objects
|
||||
if (cos < cos_max_density_angle) {
|
||||
slope_density =
|
||||
(cos - cos_zero_density_angle) /
|
||||
(cos_max_density_angle - cos_zero_density_angle);
|
||||
}
|
||||
|
||||
// Containers to hold the random buildings and objects generated
|
||||
// for this triangle for collision detection purposes.
|
||||
std::vector< std::pair< SGVec3f, float> > triangleObjectsList;
|
||||
@@ -541,8 +555,12 @@ struct SGTileGeometryBin {
|
||||
for (int k = 0; k < nObjects; k++) {
|
||||
SGMatModel * object = object_group->get_object(k);
|
||||
|
||||
// Determine the number of objecst to place, taking into account
|
||||
// the slope density factor.
|
||||
double n = slope_density * area / object->get_coverage_m2();
|
||||
|
||||
// Use the zombie door method to determine fractional object placement.
|
||||
double n = area / object->get_coverage_m2() + mt_rand(&seed);
|
||||
n = n + mt_rand(&seed);
|
||||
|
||||
// place an object each unit of area
|
||||
while ( n > 1.0 ) {
|
||||
@@ -619,17 +637,20 @@ struct SGTileGeometryBin {
|
||||
}
|
||||
|
||||
// Random objects now generated. Now generate the random buildings (if any);
|
||||
if (use_random_buildings && (building_coverage > 0)) {
|
||||
if (use_random_buildings && (building_coverage > 0) && (building_density > 0)) {
|
||||
|
||||
// Calculate the number of buildings, taking into account building density (which is linear)
|
||||
// and the slope density factor.
|
||||
double num = building_density * building_density * slope_density * area / building_coverage;
|
||||
|
||||
// For partial units of area, use a zombie door method to
|
||||
// create the proper random chance of an object being created
|
||||
// for this triangle.
|
||||
double num = area / building_coverage + mt_rand(&seed);
|
||||
num = num + mt_rand(&seed);
|
||||
|
||||
if (num < 1.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply density, which is linear, while we're dealing in areas
|
||||
num = num * building_density * building_density;
|
||||
|
||||
// Cosine of the angle between the two vectors.
|
||||
float cosine = (dot(v0, v1) / (length(v0) * length(v1)));
|
||||
@@ -784,7 +805,7 @@ struct SGTileGeometryBin {
|
||||
continue;
|
||||
|
||||
float wood_coverage = mat->get_wood_coverage();
|
||||
if (wood_coverage <= 0)
|
||||
if ((wood_coverage <= 0) || (vegetation_density <= 0))
|
||||
continue;
|
||||
|
||||
// Attributes that don't vary by tree but do vary by material
|
||||
@@ -818,6 +839,8 @@ struct SGTileGeometryBin {
|
||||
i->second.addRandomTreePoints(wood_coverage,
|
||||
mat->get_object_mask(i->second),
|
||||
vegetation_density,
|
||||
mat->get_cos_tree_max_density_slope_angle(),
|
||||
mat->get_cos_tree_zero_density_slope_angle(),
|
||||
randomPoints);
|
||||
|
||||
std::vector<SGVec3f>::iterator k;
|
||||
|
||||
Reference in New Issue
Block a user