Merge branch 'plantation' into next
This commit is contained in:
@@ -375,6 +375,29 @@ interpolate(T tau, const SGVec2<T>& v1, const SGVec2<T>& v2)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for point_in_triangle
|
||||||
|
template <typename T>
|
||||||
|
inline
|
||||||
|
T
|
||||||
|
pt_determine(const SGVec2<T>& pt1, const SGVec2<T>& pt2, const SGVec2<T>& pt3)
|
||||||
|
{
|
||||||
|
return (pt1.x()-pt3.x()) * (pt2.y()-pt3.y()) - (pt2.x() - pt3.x()) * (pt1.y() - pt3.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is testpt inside the triangle formed by the other three points?
|
||||||
|
template <typename T>
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
point_in_triangle(const SGVec2<T>& testpt, const SGVec2<T>& pt1, const SGVec2<T>& pt2, const SGVec2<T>& pt3)
|
||||||
|
{
|
||||||
|
T d1 = pt_determine(testpt,pt1,pt2);
|
||||||
|
T d2 = pt_determine(testpt,pt2,pt3);
|
||||||
|
T d3 = pt_determine(testpt,pt3,pt1);
|
||||||
|
bool has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
|
||||||
|
bool has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
|
||||||
|
return !(has_neg && has_pos);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
|
|
||||||
// Random vegetation properties
|
// Random vegetation properties
|
||||||
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
|
||||||
|
is_plantation = props->getBoolValue("plantation",false);
|
||||||
tree_effect = props->getStringValue("tree-effect", "Effects/tree");
|
tree_effect = props->getStringValue("tree-effect", "Effects/tree");
|
||||||
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
||||||
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
||||||
|
|||||||
@@ -244,6 +244,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline double get_wood_coverage () const { return wood_coverage; }
|
inline double get_wood_coverage () const { return wood_coverage; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether or not vegetation is regularly spaced
|
||||||
|
*
|
||||||
|
* @return flag: if true, vegetation is regularly spaced.
|
||||||
|
*/
|
||||||
|
inline bool get_is_plantation () const { return is_plantation; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the tree height.
|
* Get the tree height.
|
||||||
*
|
*
|
||||||
@@ -455,6 +462,9 @@ private:
|
|||||||
// coverage of woods
|
// coverage of woods
|
||||||
double wood_coverage;
|
double wood_coverage;
|
||||||
|
|
||||||
|
// are trees regularly planted?
|
||||||
|
bool is_plantation;
|
||||||
|
|
||||||
// Range at which trees become visible
|
// Range at which trees become visible
|
||||||
double tree_range;
|
double tree_range;
|
||||||
|
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
|
bool is_plantation,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points,
|
||||||
std::vector<SGVec3f>& normals)
|
std::vector<SGVec3f>& normals)
|
||||||
{
|
{
|
||||||
@@ -334,44 +335,97 @@ public:
|
|||||||
if (area <= SGLimitsf::min())
|
if (area <= SGLimitsf::min())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Determine the number of trees, taking into account vegetation
|
if (!is_plantation) {
|
||||||
// density (which is linear) and the slope density factor.
|
// Determine the number of trees, taking into account vegetation
|
||||||
// Use a zombie door method to create the proper random chance
|
// density (which is linear) and the slope density factor.
|
||||||
// of a tree being created for partial values.
|
// Use a zombie door method to create the proper random chance
|
||||||
int woodcount = (int) (vegetation_density * vegetation_density *
|
// of a tree being created for partial values.
|
||||||
slope_density *
|
int woodcount = (int) (vegetation_density * vegetation_density *
|
||||||
area / wood_coverage + mt_rand(&seed));
|
slope_density *
|
||||||
|
area / wood_coverage + mt_rand(&seed));
|
||||||
|
for (int j = 0; j < woodcount; j++) {
|
||||||
|
// Use barycentric coordinates
|
||||||
|
float a = mt_rand(&seed);
|
||||||
|
float b = mt_rand(&seed);
|
||||||
|
|
||||||
for (int j = 0; j < woodcount; j++) {
|
if ( a + b > 1.0f ) {
|
||||||
float a = mt_rand(&seed);
|
a = 1.0f - a;
|
||||||
float b = mt_rand(&seed);
|
b = 1.0f - b;
|
||||||
|
}
|
||||||
|
|
||||||
if ( a + b > 1.0f ) {
|
float c = 1.0f - a - b;
|
||||||
a = 1.0f - a;
|
|
||||||
b = 1.0f - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
float c = 1.0f - a - b;
|
SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
||||||
|
|
||||||
SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
|
// Check this random point against the object mask
|
||||||
|
// green (for trees) channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
||||||
|
|
||||||
if (object_mask != NULL) {
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
// The red channel contains the rotation for this object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
|
||||||
// Check this random point against the object mask
|
}
|
||||||
// green (for trees) channel.
|
}
|
||||||
osg::Image* img = object_mask->getImage();
|
} else { // regularly-spaced vegetation
|
||||||
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
// separate vegetation in integral 1m units
|
||||||
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
int separation = (int) ceil(sqrt(wood_coverage));
|
||||||
|
float max_x = ceil(max(max(v1.x(),v2.x()),v0.x()));
|
||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
float min_x = floor(min(min(v1.x(),v2.x()),v0.x()));
|
||||||
// The red channel contains the rotation for this object
|
float max_y = ceil(max(max(v1.y(),v2.y()),v0.y()));
|
||||||
points.push_back(randomPoint);
|
float min_y = floor(min(min(v1.y(),v2.y()),v0.y()));
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
|
/* equation of the plane ax+by+cz+d=0, need d */
|
||||||
|
|
||||||
|
float d = -1*(normal.x()*v0.x() + normal.y()*v0.y()+normal.z()*v0.z());
|
||||||
|
/* Now loop over a grid, skipping points not in the triangle */
|
||||||
|
int x_steps = (int) (max_x - min_x)/separation;
|
||||||
|
int y_steps = (int) (max_y - min_y)/separation;
|
||||||
|
SGVec2f v02d = SGVec2f(v0.x(),v0.y());
|
||||||
|
SGVec2f v12d = SGVec2f(v1.x(),v1.y());
|
||||||
|
SGVec2f v22d = SGVec2f(v2.x(),v2.y());
|
||||||
|
|
||||||
|
for (int jx = 0; jx < x_steps; jx++) {
|
||||||
|
float ptx = min_x + jx * separation;
|
||||||
|
|
||||||
|
for (int jy = 0; jy < y_steps; jy++) {
|
||||||
|
float pty = min_y + jy * separation;
|
||||||
|
SGVec2f newpt = SGVec2f(ptx,pty);
|
||||||
|
if (!point_in_triangle(newpt,v02d,v12d,v22d))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// z = (-ax-by-d)/c; c is not zero as
|
||||||
|
// that would be alpha of 1.0
|
||||||
|
|
||||||
|
float ptz = (-normal.x()*ptx - normal.y()*pty-d)/normal.z();
|
||||||
|
SGVec3f randomPoint = SGVec3f(ptx,pty,ptz);
|
||||||
|
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
// Check this point against the object mask
|
||||||
|
// green (for trees) channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * newpt.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * newpt.y()) % img->t();
|
||||||
|
|
||||||
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
|
// The red channel contains the rotation for this object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
points.push_back(randomPoint);
|
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ public:
|
|||||||
float vegetation_density,
|
float vegetation_density,
|
||||||
float cos_max_density_angle,
|
float cos_max_density_angle,
|
||||||
float cos_zero_density_angle,
|
float cos_zero_density_angle,
|
||||||
|
bool is_plantation,
|
||||||
std::vector<SGVec3f>& points,
|
std::vector<SGVec3f>& points,
|
||||||
std::vector<SGVec3f>& normals)
|
std::vector<SGVec3f>& normals)
|
||||||
{
|
{
|
||||||
@@ -249,45 +250,99 @@ public:
|
|||||||
float area = 0.5f*length(normal);
|
float area = 0.5f*length(normal);
|
||||||
if (area <= SGLimitsf::min())
|
if (area <= SGLimitsf::min())
|
||||||
continue;
|
continue;
|
||||||
|
if (!is_plantation) {
|
||||||
|
// 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));
|
||||||
|
|
||||||
// Determine the number of trees, taking into account vegetation
|
for (int j = 0; j < woodcount; j++) {
|
||||||
// density (which is linear) and the slope density factor.
|
float a = mt_rand(&seed);
|
||||||
// Use a zombie door method to create the proper random chance
|
float b = mt_rand(&seed);
|
||||||
// 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++) {
|
if ( a + b > 1.0f ) {
|
||||||
float a = mt_rand(&seed);
|
a = 1.0f - a;
|
||||||
float b = mt_rand(&seed);
|
b = 1.0f - b;
|
||||||
|
}
|
||||||
|
|
||||||
if ( a + b > 1.0f ) {
|
float c = 1.0f - a - b;
|
||||||
a = 1.0f - a;
|
|
||||||
b = 1.0f - b;
|
SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
|
||||||
|
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
||||||
|
|
||||||
|
// Check this random point against the object mask
|
||||||
|
// green (for trees) channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
||||||
|
|
||||||
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
|
// The red channel contains the rotation for this object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else { // regularly-spaced vegetation
|
||||||
|
|
||||||
|
int separation = (int) ceil(sqrt(wood_coverage));
|
||||||
|
float max_x = ceil(max(max(v1.x(),v2.x()),v0.x()));
|
||||||
|
float min_x = floor(min(min(v1.x(),v2.x()),v0.x()));
|
||||||
|
float max_y = ceil(max(max(v1.y(),v2.y()),v0.y()));
|
||||||
|
float min_y = floor(min(min(v1.y(),v2.y()),v0.y()));
|
||||||
|
|
||||||
float c = 1.0f - a - b;
|
// equation of the plane ax+by+cz+d=0, need d
|
||||||
|
|
||||||
SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
|
float d = -1*(normal.x()*v0.x() + normal.y()*v0.y()+normal.z()*v0.z());
|
||||||
|
|
||||||
if (object_mask != NULL) {
|
// Now loop over a grid, skipping points not in the triangle
|
||||||
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
|
||||||
|
|
||||||
// Check this random point against the object mask
|
int x_steps = (int) (max_x - min_x)/separation;
|
||||||
// green (for trees) channel.
|
int y_steps = (int) (max_y - min_y)/separation;
|
||||||
osg::Image* img = object_mask->getImage();
|
SGVec2f v02d = SGVec2f(v0.x(),v0.y());
|
||||||
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
SGVec2f v12d = SGVec2f(v1.x(),v1.y());
|
||||||
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
SGVec2f v22d = SGVec2f(v2.x(),v2.y());
|
||||||
|
|
||||||
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
for (int jx = 0; jx < x_steps; jx++) {
|
||||||
// The red channel contains the rotation for this object
|
float ptx = min_x + jx * separation;
|
||||||
points.push_back(randomPoint);
|
|
||||||
normals.push_back(normalize(normal));
|
for (int jy = 0; jy < y_steps; jy++) {
|
||||||
|
float pty = min_y + jy * separation;
|
||||||
|
SGVec2f newpt = SGVec2f(ptx,pty);
|
||||||
|
if (!point_in_triangle(newpt,v02d,v12d,v22d))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// z = (-ax-by-d)/c; c is not zero as
|
||||||
|
// that would be alpha of 1.0
|
||||||
|
|
||||||
|
float ptz = (-normal.x()*ptx - normal.y()*pty-d)/normal.z();
|
||||||
|
SGVec3f randomPoint = SGVec3f(ptx,pty,ptz);
|
||||||
|
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
// Check this point against the object mask
|
||||||
|
// green (for trees) channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * newpt.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * newpt.y()) % img->t();
|
||||||
|
|
||||||
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
|
// The red channel contains the rotation for this object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
normals.push_back(normalize(normal));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
points.push_back(randomPoint);
|
|
||||||
normals.push_back(normalize(normal));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -753,6 +753,7 @@ public:
|
|||||||
vegetation_density,
|
vegetation_density,
|
||||||
mat->get_cos_tree_max_density_slope_angle(),
|
mat->get_cos_tree_max_density_slope_angle(),
|
||||||
mat->get_cos_tree_zero_density_slope_angle(),
|
mat->get_cos_tree_zero_density_slope_angle(),
|
||||||
|
mat->get_is_plantation(),
|
||||||
randomPoints,
|
randomPoints,
|
||||||
randomPointNormals);
|
randomPointNormals);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user