WS30: AREA_FEATURE_LIST STG verb - lakes, lochs
- Add and AREA_FEATURE_LIST STG verb. - /sim/rendering/static-lod/area-features-lod-level to control point at which such feature are rendered - /sim/rendering/static-lod/lod-leve[n]/area-features-min-width sets the minimum width for feature rendering at that LoD level. STG Format: AREA_FEATURE_LIST <file> <material> File format: Area Attrib A B C D lon0 lat0 lon1 lat1 lon2 lat2 lon3 lat4.... where: Area is the area of the feature in m^2 Attrib is an integer attribute (currently unused) A, B, C, D are generic float attributes. Their interpretation may vary by feature type lon[n], lat[n] are pairs of lon/lat defining straight road segments
This commit is contained in:
parent
5f026c840c
commit
769e00ffdf
109
simgear/scene/tgdb/AreaFeatureBin.cxx
Normal file
109
simgear/scene/tgdb/AreaFeatureBin.cxx
Normal file
@ -0,0 +1,109 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2008 Stuart Buchanan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <simgear/scene/util/OsgMath.hxx>
|
||||
|
||||
#include "AreaFeatureBin.hxx"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
AreaFeatureBin::AreaFeatureBin(const SGPath& absoluteFileName, const std::string material) :
|
||||
_material(material)
|
||||
{
|
||||
if (!absoluteFileName.exists()) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "AreaFeature list file " << absoluteFileName << " does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
sg_gzifstream stream(absoluteFileName);
|
||||
if (!stream.is_open()) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to open " << absoluteFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!stream.eof()) {
|
||||
// read a line. Each line defines a single line feature, consisting of a width followed by a series of lon/lat positions.
|
||||
// Or a comment, starting with #
|
||||
std::string line;
|
||||
std::getline(stream, line);
|
||||
|
||||
// strip comments
|
||||
std::string::size_type hash_pos = line.find('#');
|
||||
if (hash_pos != std::string::npos)
|
||||
line.resize(hash_pos);
|
||||
|
||||
// and process further
|
||||
std::stringstream in(line);
|
||||
|
||||
// Area format is Area A B C D lon0 lat0 lon1 lat1 lon2 lat2 lon3 lat4....
|
||||
// where:
|
||||
// Area is the area of the feature in m^2
|
||||
// A, B, C, D are generic attributes. Their interpretation may vary by feature type
|
||||
// lon[n], lat[n] are pairs of lon/lat defining straight road segments
|
||||
int attributes = 0;
|
||||
float area=0, a=0, b=0, c=0, d=0;
|
||||
std::list<osg::Vec3d> nodes;
|
||||
|
||||
in >> area >> attributes >> a >> b >> c >> d;
|
||||
|
||||
if (in.bad() || in.fail()) {
|
||||
SG_LOG(SG_TERRAIN, SG_WARN, "Error parsing area entry in: " << absoluteFileName << " line: \"" << line << "\"");
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
double lon = 0.0f, lat=0.0f;
|
||||
in >> lon >> lat;
|
||||
|
||||
if (in.bad() || in.fail()) {
|
||||
break;
|
||||
}
|
||||
|
||||
SGVec3d tmp;
|
||||
SGGeodesy::SGGeodToCart(SGGeod::fromDeg(lon, lat), tmp);
|
||||
nodes.push_back(toOsg(tmp));
|
||||
}
|
||||
|
||||
if (nodes.size() > 2) {
|
||||
insert(AreaFeature(nodes, area, attributes, a, b, c, d));
|
||||
} else {
|
||||
SG_LOG(SG_TERRAIN, SG_WARN, "AreaFeature definition with fewer than three lon/lat nodes : " << absoluteFileName << " line: \"" << line << "\"");
|
||||
}
|
||||
}
|
||||
|
||||
stream.close();
|
||||
};
|
||||
|
||||
|
||||
}
|
80
simgear/scene/tgdb/AreaFeatureBin.hxx
Normal file
80
simgear/scene/tgdb/AreaFeatureBin.hxx
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2021 Stuart Buchanan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AREA_BIN_HXX
|
||||
#define AREA_BIN_HXX
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/Matrix>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
class AreaFeatureBin {
|
||||
public:
|
||||
AreaFeatureBin() = default;
|
||||
AreaFeatureBin(const SGPath& absoluteFileName, const std::string material);
|
||||
|
||||
~AreaFeatureBin() = default;
|
||||
|
||||
struct AreaFeature {
|
||||
const std::list<osg::Vec3d> _nodes;
|
||||
const float _area;
|
||||
const int _attributes;
|
||||
const float _a;
|
||||
const float _b;
|
||||
const float _c;
|
||||
const float _d;
|
||||
AreaFeature(const std::list<osg::Vec3d> nodes, const float area, const int attributes, const float a, const float b, const float c, const float d) :
|
||||
_nodes(nodes), _area(area), _attributes(attributes), _a(a), _b(b), _c(c), _d(d)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<AreaFeature> AreaFeatureList;
|
||||
|
||||
void insert(const AreaFeature& t) {
|
||||
_areaFeatureList.push_back(t);
|
||||
}
|
||||
|
||||
const AreaFeatureList getAreaFeatures() const {
|
||||
return _areaFeatureList;
|
||||
}
|
||||
|
||||
const std::string getMaterial() const {
|
||||
return _material;
|
||||
}
|
||||
|
||||
private:
|
||||
AreaFeatureList _areaFeatureList;
|
||||
const std::string _material;
|
||||
};
|
||||
|
||||
typedef std::list<AreaFeatureBin> AreaFeatureBinList;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -2,6 +2,7 @@ include (SimGearComponent)
|
||||
|
||||
set(HEADERS
|
||||
GroundLightManager.hxx
|
||||
AreaFeatureBin.hxx
|
||||
LineFeatureBin.hxx
|
||||
ReaderWriterSPT.hxx
|
||||
ReaderWriterSTG.hxx
|
||||
@ -30,6 +31,7 @@ set(HEADERS
|
||||
|
||||
set(SOURCES
|
||||
GroundLightManager.cxx
|
||||
AreaFeatureBin.cxx
|
||||
LineFeatureBin.cxx
|
||||
ReaderWriterSPT.cxx
|
||||
ReaderWriterSTG.cxx
|
||||
|
@ -66,9 +66,10 @@ LineFeatureBin::LineFeatureBin(const SGPath& absoluteFileName, const std::string
|
||||
// and process further
|
||||
std::stringstream in(line);
|
||||
|
||||
// Line format is W A B C D lon0 lat0 lon1 lat1 lon2 lat2 lon3 lat4....
|
||||
// Line format is W attr A B C D lon0 lat0 lon1 lat1 lon2 lat2 lon3 lat4....
|
||||
// where:
|
||||
// W is the width in m
|
||||
// attr is an integer attribute set
|
||||
// A, B, C, D are generic attributes. Their interpretation may vary by feature type
|
||||
// lon[n], lat[n] are pairs of lon/lat defining straight road segments
|
||||
float w = 0.0f;
|
||||
|
@ -71,6 +71,7 @@
|
||||
#define BUILDING_LIST "BUILDING_LIST"
|
||||
#define TREE_LIST "TREE_LIST"
|
||||
#define LINE_FEATURE_LIST "LINE_FEATURE_LIST"
|
||||
#define AREA_FEATURE_LIST "AREA_FEATURE_LIST"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
@ -159,7 +160,12 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::string _material;
|
||||
SGBucket _bucket;
|
||||
};
|
||||
|
||||
struct _AreaFeatureList {
|
||||
_AreaFeatureList() { }
|
||||
std::string _filename;
|
||||
std::string _material;
|
||||
SGBucket _bucket;
|
||||
};
|
||||
|
||||
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
||||
|
||||
@ -334,6 +340,19 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
VPBTechnique::addLineFeatureList(_bucket, lineFeatures, _terrainNode);
|
||||
}
|
||||
|
||||
if (!_areaFeatureList.empty()) {
|
||||
|
||||
AreaFeatureBinList areaFeatures;
|
||||
|
||||
for (const auto& b : _areaFeatureList) {
|
||||
// add the lineFeatures to the list
|
||||
const auto path = SGPath(b._filename);
|
||||
areaFeatures.push_back(AreaFeatureBin(path, b._material));
|
||||
}
|
||||
|
||||
VPBTechnique::addAreaFeatureList(_bucket, areaFeatures, _terrainNode);
|
||||
}
|
||||
|
||||
return group.release();
|
||||
}
|
||||
|
||||
@ -343,6 +362,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::list<_BuildingList> _buildingList;
|
||||
std::list<_TreeList> _treeList;
|
||||
std::list<_LineFeatureList> _lineFeatureList;
|
||||
std::list<_AreaFeatureList> _areaFeatureList;
|
||||
osg::ref_ptr<osg::Node> _terrainNode;
|
||||
|
||||
/// The original options to use for this bunch of models
|
||||
@ -646,6 +666,12 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
in >> lineFeaturelist._material;
|
||||
lineFeaturelist._bucket = bucketIndexFromFileName(absoluteFileName.file_base().c_str());
|
||||
_lineFeatureListList.push_back(lineFeaturelist);
|
||||
} else if (token == AREA_FEATURE_LIST) {
|
||||
_AreaFeatureList areaFeaturelist;
|
||||
areaFeaturelist._filename = path.utf8Str();
|
||||
in >> areaFeaturelist._material;
|
||||
areaFeaturelist._bucket = bucketIndexFromFileName(absoluteFileName.file_base().c_str());
|
||||
_areaFeatureListList.push_back(areaFeaturelist);
|
||||
} 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()
|
||||
@ -762,7 +788,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
i->_elev += elevation(*terrainGroup, SGGeod::fromDeg(i->_lon, i->_lat));
|
||||
}
|
||||
|
||||
if (_objectStaticList.empty() && _signList.empty() && _buildingListList.empty() && _treeListList.empty() && _lineFeatureListList.empty()) {
|
||||
if (_objectStaticList.empty() && _signList.empty() && _buildingListList.empty() && _treeListList.empty() && _lineFeatureListList.empty() && _areaFeatureListList.empty()) {
|
||||
// The simple case, just return the terrain group
|
||||
return terrainGroup.release();
|
||||
} else {
|
||||
@ -787,6 +813,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
|
||||
if (vpb_active && vpb_node) {
|
||||
readFileCallback->_lineFeatureList = _lineFeatureListList;
|
||||
readFileCallback->_areaFeatureList = _areaFeatureListList;
|
||||
readFileCallback->_terrainNode = vpb_node;
|
||||
}
|
||||
|
||||
@ -817,6 +844,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::list<_BuildingList> _buildingListList;
|
||||
std::list<_TreeList> _treeListList;
|
||||
std::list<_LineFeatureList> _lineFeatureListList;
|
||||
std::list<_AreaFeatureList> _areaFeatureListList;
|
||||
};
|
||||
|
||||
ReaderWriterSTG::ReaderWriterSTG()
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
#include <osgUtil/IntersectionVisitor>
|
||||
#include <osgUtil/MeshOptimizers>
|
||||
#include <osgUtil/Tessellator>
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
@ -167,6 +168,7 @@ void VPBTechnique::init(int dirtyMask, bool assumeMultiThreaded)
|
||||
applyColorLayers(*buffer, masterLocator);
|
||||
applyTrees(*buffer, masterLocator);
|
||||
applyLineFeatures(*buffer, masterLocator);
|
||||
applyAreaFeatures(*buffer, masterLocator);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -175,6 +177,7 @@ void VPBTechnique::init(int dirtyMask, bool assumeMultiThreaded)
|
||||
applyColorLayers(*buffer, masterLocator);
|
||||
applyTrees(*buffer, masterLocator);
|
||||
applyLineFeatures(*buffer, masterLocator);
|
||||
applyAreaFeatures(*buffer, masterLocator);
|
||||
}
|
||||
|
||||
if (buffer->_transform.valid()) buffer->_transform->setThreadSafeRefUnref(true);
|
||||
@ -1456,10 +1459,6 @@ void VPBTechnique::applyTrees(BufferData& buffer, Locator* masterLocator)
|
||||
const int land_class = int(round(tc.x() * 255.0));
|
||||
mat = matcache->find(land_class);
|
||||
|
||||
if ((land_class == 26) || (land_class == 27)) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Placing trees for " << land_class << " " << mat->get_one_texture(0,0) << " " << mat->get_names()[0]);
|
||||
}
|
||||
|
||||
if (!mat) {
|
||||
//SG_LOG(SG_TERRAIN, SG_ALERT, "Failed to find material for landclass " << land_class << " (" << tc.r() << ")");
|
||||
continue;
|
||||
@ -1774,6 +1773,162 @@ void VPBTechnique::generateLineFeature(BufferData& buffer, Locator* masterLocato
|
||||
}
|
||||
}
|
||||
|
||||
void VPBTechnique::applyAreaFeatures(BufferData& buffer, Locator* masterLocator)
|
||||
{
|
||||
unsigned int area_features_lod_range = 6;
|
||||
float minArea = 1000.0;
|
||||
|
||||
const unsigned int tileLevel = _terrainTile->getTileID().level;
|
||||
const SGPropertyNode* propertyNode = _options->getPropertyNode().get();
|
||||
|
||||
if (propertyNode) {
|
||||
const SGPropertyNode* static_lod = propertyNode->getNode("/sim/rendering/static-lod");
|
||||
area_features_lod_range = static_lod->getIntValue("area-features-lod-level", area_features_lod_range);
|
||||
if (static_lod->getChildren("lod-level").size() > tileLevel) {
|
||||
minArea = static_lod->getChildren("lod-level")[tileLevel]->getFloatValue("area-features-min-width", minArea);
|
||||
minArea *= minArea;
|
||||
}
|
||||
}
|
||||
|
||||
if (tileLevel < area_features_lod_range) {
|
||||
// Do not generate areas for tiles too far away
|
||||
return;
|
||||
}
|
||||
|
||||
const SGMaterialLibPtr matlib = _options->getMaterialLib();
|
||||
SGMaterial* mat = 0;
|
||||
|
||||
if (! matlib) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to get materials library to generate areas");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get all appropriate areas. We assume that the VPB terrain tile is smaller than a Bucket size.
|
||||
const osg::Vec3d world = buffer._transform->getMatrix().getTrans();
|
||||
const SGGeod loc = SGGeod::fromCart(toSG(world));
|
||||
const SGBucket bucket = SGBucket(loc);
|
||||
auto areas = std::find_if(_areaFeatureLists.begin(), _areaFeatureLists.end(), [bucket](BucketAreaFeatureBinList b){return (b.first == bucket);});
|
||||
|
||||
if (areas == _areaFeatureLists.end()) return;
|
||||
|
||||
SGMaterialCache* matcache = _options->getMaterialLib()->generateMatCache(loc, _options);
|
||||
|
||||
for (; areas != _areaFeatureLists.end(); ++areas) {
|
||||
const AreaFeatureBinList areaBins = areas->second;
|
||||
|
||||
for (auto rb = areaBins.begin(); rb != areaBins.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 areas.
|
||||
osg::Vec3Array* v = new osg::Vec3Array;
|
||||
osg::Vec2Array* t = new osg::Vec2Array;
|
||||
osg::Vec3Array* n = new osg::Vec3Array;
|
||||
osg::Vec4Array* c = new osg::Vec4Array;
|
||||
|
||||
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 );
|
||||
|
||||
auto areaFeatures = rb->getAreaFeatures();
|
||||
|
||||
for (auto r = areaFeatures.begin(); r != areaFeatures.end(); ++r) {
|
||||
if (r->_area > minArea) generateAreaFeature(buffer, masterLocator, *r, world, geometry, v, t, n, xsize, ysize);
|
||||
}
|
||||
|
||||
if (v->size() == 0) continue;
|
||||
c->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
|
||||
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
geode->setMaterial(mat);
|
||||
geode->setEffect(mat->get_one_effect(0));
|
||||
geode->setNodeMask( ~(simgear::CASTSHADOW_BIT | simgear::MODELLIGHT_BIT) );
|
||||
buffer._transform->addChild(geode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VPBTechnique::generateAreaFeature(BufferData& buffer, Locator* masterLocator, AreaFeatureBin::AreaFeature area, osg::Vec3d modelCenter, osg::Geometry* geometry, osg::Vec3Array* v, osg::Vec2Array* t, osg::Vec3Array* n, unsigned int xsize, unsigned int ysize)
|
||||
{
|
||||
if (area._nodes.size() < 3) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Coding error - AreaFeatureBin::LineFeature with fewer than three nodes");
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Vec3d ma;
|
||||
|
||||
// We're in Earth-centered coordinates, so "up" is simply directly away from (0,0,0)
|
||||
osg::Vec3d up = modelCenter;
|
||||
up.normalize();
|
||||
|
||||
osg::ref_ptr<osgUtil::Tessellator> tessellator = new osgUtil::Tessellator;
|
||||
tessellator->setBoundaryOnly(false);
|
||||
tessellator->setTessellationNormal(up);
|
||||
tessellator->beginTessellation();
|
||||
tessellator->beginContour();
|
||||
|
||||
// Build up the tesselator while also determining the correct elevation for the feature.
|
||||
double elev = 0;
|
||||
unsigned int elev_count = 0;
|
||||
|
||||
auto area_iter = area._nodes.begin();
|
||||
osg::Vec3d pt = *area_iter - modelCenter;
|
||||
ma = getMeshIntersection(buffer, masterLocator, pt, up);
|
||||
|
||||
// Only build this area if the first vertex is on the mesh. This ensures that the
|
||||
// area is only generated once, no matter how many tiles it spans.
|
||||
if (ma == pt) return;
|
||||
|
||||
for (; area_iter != area._nodes.end(); area_iter++) {
|
||||
pt = *area_iter - modelCenter;
|
||||
ma = getMeshIntersection(buffer, masterLocator, pt, up);
|
||||
if (ma !=pt) {
|
||||
elev += up*ma;
|
||||
elev_count++;
|
||||
}
|
||||
tessellator->addVertex(new osg::Vec3f(*area_iter - modelCenter));
|
||||
}
|
||||
|
||||
tessellator->endContour();
|
||||
tessellator->endTessellation();
|
||||
|
||||
auto primList = tessellator->getPrimList();
|
||||
if (primList.size() == 0) return;
|
||||
|
||||
unsigned int idx = 0;
|
||||
|
||||
auto primItr = primList.begin();
|
||||
for (; primItr < primList.end(); ++ primItr) {
|
||||
auto vertices = (*primItr)->_vertices;
|
||||
std::for_each( vertices.begin(),
|
||||
vertices.end(),
|
||||
[v, t, n, up, elev, elev_count](auto vtx) {
|
||||
v->push_back(*vtx + up * (elev / elev_count));
|
||||
t->push_back(osg::Vec2f(vtx->x(), vtx->y()));
|
||||
n->push_back(up);
|
||||
}
|
||||
);
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays((*primItr)->_mode, idx, vertices.size()));
|
||||
idx += vertices.size();
|
||||
}
|
||||
}
|
||||
|
||||
// Find the intersection of a given SGGeod with the terrain mesh
|
||||
osg::Vec3d VPBTechnique::getMeshIntersection(BufferData& buffer, Locator* masterLocator, osg::Vec3d pt, osg::Vec3d up)
|
||||
{
|
||||
@ -1961,12 +2116,42 @@ void VPBTechnique::addLineFeatureList(SGBucket bucket, LineFeatureBinList roadLi
|
||||
terrainNode->accept(ftv);
|
||||
}
|
||||
|
||||
void VPBTechnique::unloadLineFeatures(SGBucket bucket)
|
||||
void VPBTechnique::addAreaFeatureList(SGBucket bucket, AreaFeatureBinList areaList, osg::ref_ptr<osg::Node> terrainNode)
|
||||
{
|
||||
if (areaList.empty()) return;
|
||||
|
||||
// Block to mutex the List alone
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(VPBTechnique::_areaFeatureLists_mutex); // Lock the _lineFeatureLists for this scope
|
||||
_areaFeatureLists.push_back(std::pair(bucket, areaList));
|
||||
}
|
||||
|
||||
// We need to trigger a re-build of the appropriate Terrain tile, so create a pretend node and run the TerrainVisitor to
|
||||
// "dirty" the TerrainTile that it intersects with.
|
||||
osg::ref_ptr<osg::Node> n = new osg::Node();
|
||||
|
||||
//SGVec3d coord1, coord2;
|
||||
//SGGeodesy::SGGeodToCart(SGGeod::fromDegM(bucket.get_center_lon() -0.5*bucket.get_width(), bucket.get_center_lat() -0.5*bucket.get_height(), 0.0), coord1);
|
||||
//SGGeodesy::SGGeodToCart(SGGeod::fromDegM(bucket.get_center_lon() +0.5*bucket.get_width(), bucket.get_center_lat() +0.5*bucket.get_height(), 0.0), coord2);
|
||||
//osg::BoundingBox bbox = osg::BoundingBox(toOsg(coord1), toOsg(coord2));
|
||||
//n->setInitialBound(bbox);
|
||||
|
||||
SGVec3d coord;
|
||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegM(bucket.get_center_lon(), bucket.get_center_lat(), 0.0), coord);
|
||||
n->setInitialBound(osg::BoundingSphere(toOsg(coord), max(bucket.get_width_m(), bucket.get_height_m())));
|
||||
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Adding line features to " << bucket.gen_index_str());
|
||||
TerrainVisitor ftv(n, TerrainTile::ALL_DIRTY, 0);
|
||||
terrainNode->accept(ftv);
|
||||
}
|
||||
|
||||
void VPBTechnique::unloadFeatures(SGBucket bucket)
|
||||
{
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "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; } );
|
||||
//std::erase_if(_lineFeatureLists, [bucket](BucketAreaFeatureBinList p) { return p.first == bucket; } );
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/tgdb/AreaFeatureBin.hxx>
|
||||
#include <simgear/scene/tgdb/LineFeatureBin.hxx>
|
||||
|
||||
using namespace osgTerrain;
|
||||
@ -94,9 +95,10 @@ class VPBTechnique : public TerrainTechnique
|
||||
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.
|
||||
// LineFeatures and AreaFeaturesare draped over the underlying mesh.
|
||||
static void addLineFeatureList(SGBucket bucket, LineFeatureBinList roadList, osg::ref_ptr<osg::Node> terrainNode);
|
||||
static void unloadLineFeatures(SGBucket bucket);
|
||||
static void addAreaFeatureList(SGBucket bucket, AreaFeatureBinList areaList, osg::ref_ptr<osg::Node> terrainNode);
|
||||
static void unloadFeatures(SGBucket bucket);
|
||||
|
||||
protected:
|
||||
|
||||
@ -142,6 +144,18 @@ class VPBTechnique : public TerrainTechnique
|
||||
osg::Vec3Array* n,
|
||||
unsigned int xsize,
|
||||
unsigned int ysize);
|
||||
|
||||
virtual void applyAreaFeatures(BufferData& buffer, Locator* masterLocator);
|
||||
virtual void generateAreaFeature(BufferData& buffer, Locator*
|
||||
masterLocator, AreaFeatureBin::AreaFeature area,
|
||||
osg::Vec3d modelCenter,
|
||||
osg::Geometry* geometry,
|
||||
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, osg::Vec3d up);
|
||||
|
||||
OpenThreads::Mutex _writeBufferMutex;
|
||||
@ -161,9 +175,13 @@ class VPBTechnique : public TerrainTechnique
|
||||
static osg::Vec2d* _randomOffsets;
|
||||
|
||||
typedef std::pair<SGBucket, LineFeatureBinList> BucketLineFeatureBinList;
|
||||
typedef std::pair<SGBucket, AreaFeatureBinList> BucketAreaFeatureBinList;
|
||||
|
||||
inline static std::list<BucketLineFeatureBinList> _lineFeatureLists;
|
||||
inline static std::mutex _lineFeatureLists_mutex; // protects the _roadLists;
|
||||
inline static std::mutex _lineFeatureLists_mutex; // protects the _lineFeatureLists;
|
||||
|
||||
inline static std::list<BucketAreaFeatureBinList> _areaFeatureLists;
|
||||
inline static std::mutex _areaFeatureLists_mutex; // protects the _areaFeatureLists;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user