WS30 Line Features
Adds a LINE_FEATURES STG Verb of the form LINE_FEATURES <file.txt> <Material> Where <file.txt> is a text file consisting of line features to be rendered with the appropriate <Material> definition. Each line of <file.txt> has the form <w> <attr> <a> <b> <c> <d> <lon1> <lat1> <lon2> <lat2> ... Where <w> is the line feature width in m <attr> is an integer for attributes - likely a bitmask* <a> <b> <c> <d> are floats* <lonN> <latN> are the lon/lat of point N on the line feature * denotes values that may be feature-dependent. For example to indicate street lighting, kerbing etc. There must be at least two points on the line feature.
This commit is contained in:
@@ -2,6 +2,7 @@ include (SimGearComponent)
|
||||
|
||||
set(HEADERS
|
||||
GroundLightManager.hxx
|
||||
LineFeatureBin.hxx
|
||||
ReaderWriterSPT.hxx
|
||||
ReaderWriterSTG.hxx
|
||||
SGBuildingBin.hxx
|
||||
@@ -28,6 +29,7 @@ set(HEADERS
|
||||
|
||||
set(SOURCES
|
||||
GroundLightManager.cxx
|
||||
LineFeatureBin.cxx
|
||||
ReaderWriterSPT.cxx
|
||||
ReaderWriterSTG.cxx
|
||||
SGBuildingBin.cxx
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#define RAILWAY_DETAILED "OBJECT_RAILWAY_DETAILED"
|
||||
#define BUILDING_LIST "BUILDING_LIST"
|
||||
#define TREE_LIST "TREE_LIST"
|
||||
#define LINE_FEATURE_LIST "LINE_FEATURE_LIST"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
@@ -152,6 +153,13 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
double _lon, _lat, _elev;
|
||||
};
|
||||
|
||||
struct _LineFeatureList {
|
||||
_LineFeatureList() { }
|
||||
std::string _filename;
|
||||
std::string _material;
|
||||
SGBucket _bucket;
|
||||
};
|
||||
|
||||
|
||||
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
||||
|
||||
@@ -279,7 +287,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get materials definition for buildings");
|
||||
} else {
|
||||
for (const auto& b : _treeList) {
|
||||
// Build buildings for each list of buildings
|
||||
// Build trees for each list of trees
|
||||
SGGeod geodPos = SGGeod::fromDegM(b._lon, b._lat, 0.0);
|
||||
SGSharedPtr<SGMaterial> mat = matlib->find(b._material_name, geodPos);
|
||||
|
||||
@@ -310,6 +318,19 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
}
|
||||
}
|
||||
|
||||
if (!_lineFeatureList.empty()) {
|
||||
|
||||
LineFeatureBinList lineFeatures;
|
||||
|
||||
for (const auto& b : _lineFeatureList) {
|
||||
// add the lineFeatures to the list
|
||||
const auto path = SGPath(b._filename);
|
||||
lineFeatures.push_back(LineFeatureBin(path, b._material));
|
||||
}
|
||||
|
||||
VPBTechnique::addLineFeatureList(_bucket, lineFeatures);
|
||||
}
|
||||
|
||||
return group.release();
|
||||
}
|
||||
|
||||
@@ -318,6 +339,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::list<_Sign> _signList;
|
||||
std::list<_BuildingList> _buildingList;
|
||||
std::list<_TreeList> _treeList;
|
||||
std::list<_LineFeatureList> _lineFeatureList;
|
||||
|
||||
/// The original options to use for this bunch of models
|
||||
osg::ref_ptr<SGReaderWriterOptions> _options;
|
||||
@@ -568,7 +590,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
if (token == BUILDING_ROUGH || token == BUILDING_DETAILED) {
|
||||
opt->setMaterialName("OSM_Building");
|
||||
} else if (token == ROAD_ROUGH || token == ROAD_DETAILED) {
|
||||
opt->setMaterialName("OSM_Road");
|
||||
opt->setMaterialName("OSM_LineFeature");
|
||||
} else if (token == RAILWAY_ROUGH || token == RAILWAY_DETAILED) {
|
||||
opt->setMaterialName("OSM_Railway");
|
||||
} else {
|
||||
@@ -611,6 +633,12 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
in >> treelist._material_name >> treelist._lon >> treelist._lat >> treelist._elev;
|
||||
checkInsideBucket(absoluteFileName, treelist._lon, treelist._lat);
|
||||
_treeListList.push_back(treelist);
|
||||
} else if (token == LINE_FEATURE_LIST) {
|
||||
_LineFeatureList lineFeaturelist;
|
||||
lineFeaturelist._filename = path.utf8Str();
|
||||
in >> lineFeaturelist._material;
|
||||
lineFeaturelist._bucket = bucketIndexFromFileName(absoluteFileName.file_base().c_str());
|
||||
_lineFeatureListList.push_back(lineFeaturelist);
|
||||
} else {
|
||||
// Check registered callback for token. Keep lock until callback completed to make sure it will not be
|
||||
// executed after a thread successfully executed removeSTGObjectHandler()
|
||||
@@ -723,7 +751,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
i->_elev += elevation(*terrainGroup, SGGeod::fromDeg(i->_lon, i->_lat));
|
||||
}
|
||||
|
||||
if (_objectStaticList.empty() && _signList.empty() && _buildingListList.empty() && _treeListList.empty()) {
|
||||
if (_objectStaticList.empty() && _signList.empty() && _buildingListList.empty() && _treeListList.empty() && _lineFeatureListList.empty()) {
|
||||
// The simple case, just return the terrain group
|
||||
return terrainGroup.release();
|
||||
} else {
|
||||
@@ -742,6 +770,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
readFileCallback->_objectStaticList = _objectStaticList;
|
||||
readFileCallback->_buildingList = _buildingListList;
|
||||
readFileCallback->_treeList = _treeListList;
|
||||
readFileCallback->_lineFeatureList = _lineFeatureListList;
|
||||
readFileCallback->_signList = _signList;
|
||||
readFileCallback->_options = options;
|
||||
readFileCallback->_bucket = bucket;
|
||||
@@ -771,6 +800,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::list<_Sign> _signList;
|
||||
std::list<_BuildingList> _buildingListList;
|
||||
std::list<_TreeList> _treeListList;
|
||||
std::list<_LineFeatureList> _lineFeatureListList;
|
||||
};
|
||||
|
||||
ReaderWriterSTG::ReaderWriterSTG()
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <osgSim/ElevationSlice>
|
||||
|
||||
#include <osgTerrain/TerrainTile>
|
||||
#include <osgTerrain/Terrain>
|
||||
|
||||
@@ -26,6 +28,7 @@
|
||||
#include <osgUtil/MeshOptimizers>
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Texture2D>
|
||||
@@ -37,11 +40,14 @@
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/scene/material/Effect.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/model/model.hxx>
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/util/SGSceneFeatures.hxx>
|
||||
|
||||
|
||||
#include "VPBTechnique.hxx"
|
||||
#include "TreeBin.hxx"
|
||||
|
||||
@@ -159,6 +165,7 @@ void VPBTechnique::init(int dirtyMask, bool assumeMultiThreaded)
|
||||
{
|
||||
applyColorLayers(*buffer, masterLocator);
|
||||
applyTrees(*buffer, masterLocator);
|
||||
applyLineFeatures(*buffer, masterLocator);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -166,6 +173,7 @@ void VPBTechnique::init(int dirtyMask, bool assumeMultiThreaded)
|
||||
generateGeometry(*buffer, masterLocator, centerModel);
|
||||
applyColorLayers(*buffer, masterLocator);
|
||||
applyTrees(*buffer, masterLocator);
|
||||
applyLineFeatures(*buffer, masterLocator);
|
||||
}
|
||||
|
||||
if (buffer->_transform.valid()) buffer->_transform->setThreadSafeRefUnref(true);
|
||||
@@ -1563,7 +1571,7 @@ void VPBTechnique::applyTrees(BufferData& buffer, Locator* masterLocator)
|
||||
{
|
||||
bool use_random_vegetation = false;
|
||||
float vegetation_density = 1.0;
|
||||
int vegetation_lod_range = 6;
|
||||
int vegetation_lod_level = 6;
|
||||
float randomness = 1.0;
|
||||
|
||||
SGPropertyNode* propertyNode = _options->getPropertyNode().get();
|
||||
@@ -1571,11 +1579,11 @@ void VPBTechnique::applyTrees(BufferData& buffer, Locator* masterLocator)
|
||||
if (propertyNode) {
|
||||
use_random_vegetation = propertyNode->getBoolValue("/sim/rendering/random-vegetation", use_random_vegetation);
|
||||
vegetation_density = propertyNode->getFloatValue("/sim/rendering/vegetation-density", vegetation_density);
|
||||
vegetation_lod_range = propertyNode->getIntValue("/sim/rendering/vegetation-lod", vegetation_lod_range);
|
||||
vegetation_lod_level = propertyNode->getIntValue("/sim/rendering/static-lod/vegetation-lod-level", vegetation_lod_level);
|
||||
}
|
||||
|
||||
// Do not generate vegetation for tiles too far away or if we explicitly don't generate vegetation
|
||||
if ((!use_random_vegetation) || (_terrainTile->getTileID().level < vegetation_lod_range)) {
|
||||
if ((!use_random_vegetation) || (_terrainTile->getTileID().level < vegetation_lod_level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1599,13 +1607,10 @@ void VPBTechnique::applyTrees(BufferData& buffer, Locator* masterLocator)
|
||||
delete matcache;
|
||||
}
|
||||
|
||||
// Should probably be an error if we can't find a material, but we
|
||||
// return for now.
|
||||
|
||||
if (!mat)
|
||||
{
|
||||
if (!mat) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to find EvergreenForestmaterial at " << loc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TreeBin* bin = new TreeBin();
|
||||
bin->texture = mat->get_tree_texture();
|
||||
@@ -1742,6 +1747,224 @@ void VPBTechnique::applyTrees(BufferData& buffer, Locator* masterLocator)
|
||||
buffer._transform->addChild(trees);
|
||||
}
|
||||
|
||||
void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
||||
{
|
||||
int roads_lod_range = 6;
|
||||
|
||||
SGPropertyNode* propertyNode = _options->getPropertyNode().get();
|
||||
|
||||
if (propertyNode) {
|
||||
roads_lod_range = propertyNode->getIntValue("/sim/rendering/static-lod/roads-lod-range", roads_lod_range);
|
||||
}
|
||||
|
||||
// Do not generate vegetation for tiles too far away
|
||||
//if (_terrainTile->getTileID().level < roads_lod_range) {
|
||||
if (_terrainTile->getTileID().level < roads_lod_range) {
|
||||
return;
|
||||
}
|
||||
|
||||
SGMaterialLibPtr matlib = _options->getMaterialLib();
|
||||
SGMaterial* mat = 0;
|
||||
osg::Vec3d world;
|
||||
SGGeod loc;
|
||||
|
||||
if (! matlib) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to get materials library to generate roads");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the center of the tile, sadly non-trivial.
|
||||
osg::Vec3d tileloc = computeCenter(buffer, masterLocator);
|
||||
masterLocator->convertLocalToModel(tileloc, world);
|
||||
const SGVec3d world2 = SGVec3d(world.x(), world.y(), world.z());
|
||||
loc = SGGeod::fromCart(world2);
|
||||
|
||||
const osg::Matrixd R_vert = makeZUpFrameRelative(loc);
|
||||
|
||||
// Get all appropriate roads. We assume that the VPB terrain tile is smaller than a Bucket size.
|
||||
SGBucket bucket = SGBucket(loc);
|
||||
auto roads = std::find_if(_lineFeatureLists.begin(), _lineFeatureLists.end(), [bucket](BucketLineFeatureBinList b){return (b.first == bucket);});
|
||||
|
||||
if (roads == _lineFeatureLists.end()) return;
|
||||
|
||||
SGMaterialCache* matcache = _options->getMaterialLib()->generateMatCache(loc, _options);
|
||||
|
||||
for (; roads != _lineFeatureLists.end(); ++roads) {
|
||||
LineFeatureBinList roadBins = roads->second;
|
||||
|
||||
for (auto rb = roadBins.begin(); rb != roadBins.end(); ++rb)
|
||||
{
|
||||
mat = matcache->find(rb->getMaterial());
|
||||
|
||||
if (!mat) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to find material " << rb->getMaterial() << " at " << loc << " " << bucket);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int xsize = mat->get_xsize();
|
||||
unsigned int ysize = mat->get_ysize();
|
||||
|
||||
// Generate a geometry for this set of roads.
|
||||
osg::Vec3Array* v = new osg::Vec3Array;
|
||||
osg::Vec2Array* t = new osg::Vec2Array;
|
||||
osg::Vec3Array* n = new osg::Vec3Array;
|
||||
osg::Vec4Array* c = new osg::Vec4Array;
|
||||
|
||||
auto lineFeatures = rb->getLineFeatures();
|
||||
|
||||
for (auto r = lineFeatures.begin(); r != lineFeatures.end(); ++r) {
|
||||
generateLineFeature(buffer, masterLocator, *r, world, R_vert, v, t, n, xsize, ysize);
|
||||
}
|
||||
|
||||
if (v->size() == 0) continue;
|
||||
|
||||
c->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
geometry->setVertexArray(v);
|
||||
geometry->setTexCoordArray(0, t, osg::Array::BIND_PER_VERTEX);
|
||||
geometry->setTexCoordArray(1, t, osg::Array::BIND_PER_VERTEX);
|
||||
geometry->setNormalArray(n, osg::Array::BIND_PER_VERTEX);
|
||||
geometry->setColorArray(c, osg::Array::BIND_OVERALL);
|
||||
geometry->setUseDisplayList( false );
|
||||
geometry->setUseVertexBufferObjects( true );
|
||||
geometry->addPrimitiveSet( new osg::DrawArrays( GL_TRIANGLES, 0, v->size()) );
|
||||
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
geode->setMaterial(mat);
|
||||
geode->setEffect(mat->get_one_effect(0));
|
||||
buffer._transform->addChild(geode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VPBTechnique::generateLineFeature(BufferData& buffer, Locator* masterLocator, LineFeatureBin::LineFeature road, osg::Vec3d modelCenter, const osg::Matrixd R_vert, osg::Vec3Array* v, osg::Vec2Array* t, osg::Vec3Array* n, unsigned int xsize, unsigned int ysize)
|
||||
{
|
||||
if (road._nodes.size() < 2) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Coding error - LineFeatureBin::LineFeature with fewer than two nodes");
|
||||
return;
|
||||
}
|
||||
|
||||
SGVec3d tmp;
|
||||
osg::Vec3d ma, mb;
|
||||
std::list<osg::Vec3d> roadPoints;
|
||||
|
||||
auto road_iter = road._nodes.begin();
|
||||
|
||||
SGGeodesy::SGGeodToCart(SGGeod(*road_iter), tmp);
|
||||
ma = toOsg(tmp) - modelCenter;
|
||||
|
||||
osg::Vec3d intersect = getMeshIntersection(buffer, masterLocator, ma);
|
||||
|
||||
// If we've got an intersection, add it to the list
|
||||
if (intersect != ma) roadPoints.push_back(intersect);
|
||||
|
||||
road_iter++;
|
||||
|
||||
for (; road_iter != road._nodes.end(); road_iter++) {
|
||||
SGGeodesy::SGGeodToCart(SGGeod(*road_iter), tmp);
|
||||
mb = toOsg(tmp) - modelCenter;
|
||||
|
||||
intersect = getMeshIntersection(buffer, masterLocator, mb);
|
||||
if (intersect != mb) roadPoints.push_back(intersect);
|
||||
|
||||
osgSim::ElevationSlice es;
|
||||
es.setStartPoint(ma);
|
||||
es.setEndPoint(mb);
|
||||
es.computeIntersections(buffer._geometry);
|
||||
|
||||
auto esl = es.getIntersections();
|
||||
for(auto eslitr = esl.begin(); eslitr != esl.end(); ++eslitr)
|
||||
{
|
||||
roadPoints.push_back(*eslitr);
|
||||
}
|
||||
|
||||
// Now traverse the next segment
|
||||
ma = mb;
|
||||
}
|
||||
|
||||
// We now have a series of points following the topography of the elevation mesh.
|
||||
float xtex, ytex;
|
||||
osg::Vec3d local, origin, top, start, end;
|
||||
osg::Vec3d up = osg::Matrixd::inverse(R_vert) * osg::Vec3d(0,0,1);
|
||||
|
||||
auto iter = roadPoints.begin();
|
||||
start = *iter + up;
|
||||
iter++;
|
||||
|
||||
float ytex_base = 0.0f;
|
||||
|
||||
for (; iter != roadPoints.end(); iter++) {
|
||||
end = *iter + up;
|
||||
|
||||
// Find a spanwise vector
|
||||
osg::Vec3d spanwise = ((end-start) ^ up);
|
||||
spanwise.normalize();
|
||||
|
||||
// Define the road extents
|
||||
const osg::Vec3d a = start - spanwise * road._width * 0.5;
|
||||
const osg::Vec3d b = start + spanwise * road._width * 0.5;
|
||||
const osg::Vec3d c = end - spanwise * road._width * 0.5;
|
||||
const osg::Vec3d d = end + spanwise * road._width * 0.5;
|
||||
|
||||
// Determine the x and y texture coordinates for the edges
|
||||
xtex = 0.5 * road._width / xsize;
|
||||
ytex = ytex_base + (end-start).length() / ysize;
|
||||
|
||||
// Now generate two triangles, .
|
||||
v->push_back(a);
|
||||
v->push_back(b);
|
||||
v->push_back(c);
|
||||
|
||||
t->push_back(osg::Vec2d(0, ytex_base));
|
||||
t->push_back(osg::Vec2d(xtex, ytex_base));
|
||||
t->push_back(osg::Vec2d(0, ytex));
|
||||
|
||||
v->push_back(b);
|
||||
v->push_back(d);
|
||||
v->push_back(c);
|
||||
|
||||
t->push_back(osg::Vec2d(xtex, ytex_base));
|
||||
t->push_back(osg::Vec2d(xtex, ytex));
|
||||
t->push_back(osg::Vec2d(0, ytex));
|
||||
|
||||
// Normal is straight from the quad
|
||||
osg::Vec3d normal = (end-start)^spanwise;
|
||||
normal.normalize();
|
||||
for (unsigned int i = 0; i < 6; i++) n->push_back(normal);
|
||||
|
||||
start = end;
|
||||
ytex_base = ytex;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the intersection of a given SGGeod with the terrain mesh
|
||||
osg::Vec3d VPBTechnique::getMeshIntersection(BufferData& buffer, Locator* masterLocator, osg::Vec3d pt)
|
||||
{
|
||||
SGVec3d tmp;
|
||||
osg::Vec3d local, origin, top;
|
||||
|
||||
// Get a vertical line segment.
|
||||
masterLocator->convertModelToLocal(pt, local);
|
||||
masterLocator->convertLocalToModel(osg::Vec3d(local.x(), local.y(), -1000.0), origin);
|
||||
masterLocator->convertLocalToModel(osg::Vec3d(local.x(), local.y(), 100000.0), top);
|
||||
|
||||
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector;
|
||||
intersector = new osgUtil::LineSegmentIntersector(origin, top);
|
||||
osgUtil::IntersectionVisitor visitor(intersector.get());
|
||||
buffer._geometry->accept(visitor);
|
||||
|
||||
if (intersector->containsIntersections()) {
|
||||
// We have an intersection with the terrain model, so return it
|
||||
return intersector->getFirstIntersection().getWorldIntersectPoint();
|
||||
} else {
|
||||
// No intersection. Likely this point is outside our geometry. So just return the cartesian element.
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
|
||||
void VPBTechnique::update(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (_terrainTile) _terrainTile->osg::Group::traverse(nv);
|
||||
@@ -1876,3 +2099,20 @@ osg::Vec3d VPBTechnique::checkAgainstElevationConstraints(osg::Vec3d origin, osg
|
||||
}
|
||||
}
|
||||
|
||||
void VPBTechnique::addLineFeatureList(SGBucket bucket, LineFeatureBinList roadList)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(VPBTechnique::_lineFeatureLists_mutex); // Lock the _lineFeatureLists for this scope
|
||||
_lineFeatureLists.push_back(std::pair(bucket, roadList));
|
||||
}
|
||||
|
||||
void VPBTechnique::unloadLineFeatures(SGBucket bucket)
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Erasing all roads with entry " << bucket);
|
||||
const std::lock_guard<std::mutex> lock(VPBTechnique::_lineFeatureLists_mutex); // Lock the _lineFeatureLists for this scope
|
||||
// C++ 20...
|
||||
//std::erase_if(_lineFeatureLists, [bucket](BucketLineFeatureBinList p) { return p.first == bucket; } );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
#include <osgTerrain/TerrainTechnique>
|
||||
#include <osgTerrain/Locator>
|
||||
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/tgdb/LineFeatureBin.hxx>
|
||||
|
||||
using namespace osgTerrain;
|
||||
|
||||
@@ -87,10 +89,15 @@ class VPBTechnique : public TerrainTechnique
|
||||
* for all graphics contexts. */
|
||||
virtual void releaseGLObjects(osg::State* = 0) const;
|
||||
|
||||
// Elevation constraints ensure that the terrain mesh is placed underneath objects such as airports
|
||||
static void addElevationConstraint(osg::ref_ptr<osg::Node> constraint, osg::Group* terrain);
|
||||
static void removeElevationConstraint(osg::ref_ptr<osg::Node> constraint);
|
||||
static osg::Vec3d checkAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex, float vertex_gap);
|
||||
|
||||
// LineFeatures are draped over the underlying mesh.
|
||||
static void addLineFeatureList(SGBucket bucket, LineFeatureBinList roadList);
|
||||
static void unloadLineFeatures(SGBucket bucket);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~VPBTechnique();
|
||||
@@ -121,6 +128,18 @@ class VPBTechnique : public TerrainTechnique
|
||||
|
||||
virtual void applyTrees(BufferData& buffer, Locator* masterLocator);
|
||||
|
||||
virtual void applyLineFeatures(BufferData& buffer, Locator* masterLocator);
|
||||
virtual void generateLineFeature(BufferData& buffer, Locator*
|
||||
masterLocator, LineFeatureBin::LineFeature road,
|
||||
osg::Vec3d modelCenter,
|
||||
const osg::Matrixd R_vert,
|
||||
osg::Vec3Array* v,
|
||||
osg::Vec2Array* t,
|
||||
osg::Vec3Array* n,
|
||||
unsigned int xsize,
|
||||
unsigned int ysize);
|
||||
virtual osg::Vec3d getMeshIntersection(BufferData& buffer, Locator* masterLocator, osg::Vec3d pt);
|
||||
|
||||
OpenThreads::Mutex _writeBufferMutex;
|
||||
osg::ref_ptr<BufferData> _currentBufferData;
|
||||
osg::ref_ptr<BufferData> _newBufferData;
|
||||
@@ -138,6 +157,12 @@ class VPBTechnique : public TerrainTechnique
|
||||
inline static osg::ref_ptr<osg::Group> _constraintGroup = new osg::Group();;
|
||||
inline static std::mutex _constraint_mutex; // protects the _constraintGroup;
|
||||
static osg::Vec2d* _randomOffsets;
|
||||
|
||||
typedef std::pair<SGBucket, LineFeatureBinList> BucketLineFeatureBinList;
|
||||
|
||||
inline static std::list<BucketLineFeatureBinList> _lineFeatureLists;
|
||||
inline static std::mutex _lineFeatureLists_mutex; // protects the _roadLists;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user