Refactored constraint checking for random objects

The Random objects check now happens in the scanline read in VPBTechnique,
rather in the VBPMaterialHandler objects. These checks are not specific
to any handler, and are thus better suited to be outside of specific
material handling logic.
This commit is contained in:
Fahim Imaduddin Dalvi
2022-01-04 17:56:41 +03:00
parent 65542e7521
commit d4b02d58d6
4 changed files with 69 additions and 61 deletions

View File

@@ -58,16 +58,6 @@ bool VPBMaterialHandler::checkAgainstObjectMask(
return false;
}
bool VPBMaterialHandler::checkAgainstConstraints(
osg::ref_ptr<osg::Group> constraintGroup, osg::Vec3d origin,
osg::Vec3d vertex) {
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector;
intersector = new osgUtil::LineSegmentIntersector(origin, vertex);
osgUtil::IntersectionVisitor visitor(intersector.get());
constraintGroup->accept(visitor);
return intersector->containsIntersections();
}
double VPBMaterialHandler::det2(const osg::Vec2d a, const osg::Vec2d b) {
return a.x() * b.y() - b.x() * a.y();
}
@@ -160,12 +150,13 @@ bool VegetationHandler::handleNewMaterial(SGMaterial *mat) {
}
bool VegetationHandler::handleIteration(
SGMaterial *mat, osg::Image *objectMaskImage,
osg::ref_ptr<osg::Group> constraintGroup, const double lon,
const double lat, osg::Vec2d p, const double D, const osg::Vec2d ll_O,
const osg::Vec2d ll_x, const osg::Vec2d ll_y, const osg::Vec2d t_0,
osg::Vec2d t_x, osg::Vec2d t_y, const osg::Vec3d v_0, osg::Vec3d v_x,
osg::Vec3d v_y, float x_scale, float y_scale, osg::Vec3 n, osg::Vec3d up) {
SGMaterial* mat, osg::Image* objectMaskImage,
const double lon, const double lat,
osg::Vec2d p, const double D,
const osg::Vec2d ll_O, const osg::Vec2d ll_x, const osg::Vec2d ll_y,
const osg::Vec2d t_0, osg::Vec2d t_x, osg::Vec2d t_y,
float x_scale, float y_scale, osg::Vec2f& pointInTriangle)
{
const int lat_int = (lat + ll_O.y()) / delta_lat;
const int lon_int = (lon + ll_O.x()) / delta_lon;
@@ -195,16 +186,14 @@ bool VegetationHandler::handleIteration(
return false;
}
// Check against constraints to stop trees growing from roads;
const osg::Vec3 vp = v_x * x + v_y * y + v_0;
if (checkAgainstConstraints(constraintGroup, vp - up * 100, vp + up * 100))
return false;
bin->insert(SGVec3f(vp.x(), vp.y(), vp.z()), SGVec3f(n.x(), n.y(), n.z()));
pointInTriangle.set(x, y);
return true;
}
void VegetationHandler::placeObject(const osg::Vec3 vp, const osg::Vec3d up, const osg::Vec3 n) {
bin->insert(SGVec3f(vp.x(), vp.y(), vp.z()), SGVec3f(n.x(), n.y(), n.z()));
}
void VegetationHandler::finish(osg::ref_ptr<SGReaderWriterOptions> options,
osg::ref_ptr<osg::MatrixTransform> transform,
const SGGeod loc) {
@@ -287,12 +276,13 @@ bool RandomLightsHandler::handleNewMaterial(SGMaterial *mat) {
}
bool RandomLightsHandler::handleIteration(
SGMaterial *mat, osg::Image *objectMaskImage,
osg::ref_ptr<osg::Group> constraintGroup, const double lon,
const double lat, osg::Vec2d p, const double D, const osg::Vec2d ll_O,
const osg::Vec2d ll_x, const osg::Vec2d ll_y, const osg::Vec2d t_0,
osg::Vec2d t_x, osg::Vec2d t_y, const osg::Vec3d v_0, osg::Vec3d v_x,
osg::Vec3d v_y, float x_scale, float y_scale, osg::Vec3 n, osg::Vec3d up) {
SGMaterial* mat, osg::Image* objectMaskImage,
const double lon, const double lat,
osg::Vec2d p, const double D,
const osg::Vec2d ll_O, const osg::Vec2d ll_x, const osg::Vec2d ll_y,
const osg::Vec2d t_0, osg::Vec2d t_x, osg::Vec2d t_y,
float x_scale, float y_scale, osg::Vec2f& pointInTriangle)
{
const int lat_int = (lat + ll_O.y()) / delta_lat;
const int lon_int = (lon + ll_O.x()) / delta_lon;
@@ -325,13 +315,15 @@ bool RandomLightsHandler::handleIteration(
return false;
}
// Check against constraints to stop lights on roads
const osg::Vec3 vp = v_x * x + v_y * y + v_0;
if (checkAgainstConstraints(constraintGroup, vp - up * 100, vp + up * 100))
return false;
pointInTriangle.set(x, y);
float zombie = pc_map_rand(lon_int, lat_int, 6);
float factor = pc_map_rand(lon_int, lat_int, 7);
return true;
}
void RandomLightsHandler::placeObject(const osg::Vec3 vp, const osg::Vec3d up, const osg::Vec3 n)
{
float zombie = pc_map_rand(vp.x(), vp.y() + vp.z(), 6);
float factor = pc_map_rand(vp.x(), vp.y() + vp.z(), 7);
factor *= factor;
float bright = 1;
@@ -364,8 +356,6 @@ bool RandomLightsHandler::handleIteration(
bin->insert(
SGVec3f(finalPosition.x(), finalPosition.y(), finalPosition.z()),
size, intensity, onPeriod, color);
return true;
}
void RandomLightsHandler::finish(osg::ref_ptr<SGReaderWriterOptions> options,

View File

@@ -56,11 +56,6 @@ class VPBMaterialHandler {
float y_scale, const osg::Vec2d t_0,
osg::Vec2d t_x, osg::Vec2d t_y);
// Check a given vertex against any constraints E.g. to ensure we
// don't get objects like trees sprouting from roads or runways.
bool checkAgainstConstraints(osg::ref_ptr<osg::Group> constraintGroup,
osg::Vec3d origin, osg::Vec3d vertex);
double det2(const osg::Vec2d a, const osg::Vec2d b);
public:
@@ -80,16 +75,20 @@ class VPBMaterialHandler {
// Function that is called for each point in the scanline reading process
// Return false if the material is irrelevant to the handler
virtual bool handleIteration(SGMaterial *mat, osg::Image *objectMaskImage,
osg::ref_ptr<osg::Group> constraintGroup,
// Return true if the point should be used to place an object, updating
// the pointInTriangle variable with the x and y location within the
// current triangle
virtual bool handleIteration(SGMaterial* mat, osg::Image* objectMaskImage,
const double lon, const double lat,
osg::Vec2d p, const double D,
const osg::Vec2d ll_O, const osg::Vec2d ll_x,
const osg::Vec2d ll_y, const osg::Vec2d t_0,
osg::Vec2d t_x, osg::Vec2d t_y,
const osg::Vec3d v_0, osg::Vec3d v_x,
osg::Vec3d v_y, float x_scale, float y_scale,
osg::Vec3 n, osg::Vec3d up) = 0;
float x_scale, float y_scale,
osg::Vec2f& pointInTriangle) = 0;
// Place an object at the point given by vp
virtual void placeObject(const osg::Vec3 vp, const osg::Vec3d up, const osg::Vec3 n) = 0;
// Function that is called after the scanline is complete
virtual void finish(osg::ref_ptr<SGReaderWriterOptions> options,
@@ -116,15 +115,13 @@ class VegetationHandler : public VPBMaterialHandler {
osg::ref_ptr<TerrainTile> terrainTile);
void setLocation(const SGGeod loc, double r_E_lat, double r_E_lon);
bool handleNewMaterial(SGMaterial *mat);
bool handleIteration(SGMaterial *mat, osg::Image *objectMaskImage,
osg::ref_ptr<osg::Group> constraintGroup,
bool handleIteration(SGMaterial* mat, osg::Image* objectMaskImage,
const double lon, const double lat, osg::Vec2d p,
const double D, const osg::Vec2d ll_O,
const osg::Vec2d ll_x, const osg::Vec2d ll_y,
const osg::Vec2d t_0, osg::Vec2d t_x, osg::Vec2d t_y,
const osg::Vec3d v_0, osg::Vec3d v_x, osg::Vec3d v_y,
float x_scale, float y_scale, osg::Vec3 n,
osg::Vec3d up);
float x_scale, float y_scale, osg::Vec2f& pointInTriangle);
void placeObject(const osg::Vec3 vp, const osg::Vec3d up, const osg::Vec3 n);
void finish(osg::ref_ptr<SGReaderWriterOptions> options,
osg::ref_ptr<osg::MatrixTransform> transform, const SGGeod loc);
@@ -151,15 +148,13 @@ class RandomLightsHandler : public VPBMaterialHandler {
osg::ref_ptr<TerrainTile> terrainTile);
void setLocation(const SGGeod loc, double r_E_lat, double r_E_lon);
bool handleNewMaterial(SGMaterial *mat);
bool handleIteration(SGMaterial *mat, osg::Image *objectMaskImage,
osg::ref_ptr<osg::Group> constraintGroup,
bool handleIteration(SGMaterial* mat, osg::Image* objectMaskImage,
const double lon, const double lat, osg::Vec2d p,
const double D, const osg::Vec2d ll_O,
const osg::Vec2d ll_x, const osg::Vec2d ll_y,
const osg::Vec2d t_0, osg::Vec2d t_x, osg::Vec2d t_y,
const osg::Vec3d v_0, osg::Vec3d v_x, osg::Vec3d v_y,
float x_scale, float y_scale, osg::Vec3 n,
osg::Vec3d up);
float x_scale, float y_scale, osg::Vec2f& pointInTriangle);
void placeObject(const osg::Vec3 vp, const osg::Vec3d up, const osg::Vec3 n);
void finish(osg::ref_ptr<SGReaderWriterOptions> options,
osg::ref_ptr<osg::MatrixTransform> transform, const SGGeod loc);

View File

@@ -1634,10 +1634,18 @@ void VPBTechnique::applyMaterials(BufferData& buffer, Locator* masterLocator)
if (!mat) continue;
handler->handleIteration(mat, object_mask_image,
_randomObjectsConstraintGroup, lon, lat, p,
D, ll_O, ll_x, ll_y, t_0, t_x, t_y, v_0,
v_x, v_y, x_scale, y_scale, n, up);
osg::Vec2f pointInTriangle;
if (handler->handleIteration(mat, object_mask_image,
lon, lat, p,
D, ll_O, ll_x, ll_y, t_0, t_x, t_y, x_scale, y_scale, pointInTriangle)) {
// Check against constraints to stop lights on roads
const osg::Vec3 vp = v_x * pointInTriangle.x() + v_y * pointInTriangle.y() + v_0;
if (checkAgainstRandomObjectsConstraints(_randomObjectsConstraintGroup, vp - up * 100, vp + up * 100))
continue;
handler->placeObject(vp, up, n);
}
}
}
@@ -2382,6 +2390,17 @@ void VPBTechnique::addRandomObjectsConstraint(osg::ref_ptr<osg::Node> constraint
_randomObjectsConstraintGroup->addChild(constraint.get());
}
bool VPBTechnique::checkAgainstRandomObjectsConstraints(
osg::ref_ptr<osg::Group> constraintGroup, osg::Vec3d origin,
osg::Vec3d vertex)
{
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector;
intersector = new osgUtil::LineSegmentIntersector(origin, vertex);
osgUtil::IntersectionVisitor visitor(intersector.get());
constraintGroup->accept(visitor);
return intersector->containsIntersections();
}
// Remove a previously added constraint. E.g on model unload.
void VPBTechnique::removeRandomObjectsConstraint(osg::ref_ptr<osg::Node> constraint)
{

View File

@@ -186,6 +186,10 @@ class VPBTechnique : public TerrainTechnique
// we only use these internally and during generation of this particular tile.
virtual void addRandomObjectsConstraint(osg::ref_ptr<osg::Node> constraint);
virtual void removeRandomObjectsConstraint(osg::ref_ptr<osg::Node> constraint);
// Check a given vertex against any constraints E.g. to ensure we
// don't get objects like trees sprouting from roads or runways.
bool checkAgainstRandomObjectsConstraints(osg::ref_ptr<osg::Group> constraintGroup,
osg::Vec3d origin, osg::Vec3d vertex);
virtual void clearRandomObjectsConstraints();
OpenThreads::Mutex _writeBufferMutex;