STG-defined buildings using Random Building shader
Support BUILDING_LIST STG verb which references a file containing the cartesian coordinates of individual buildings, to be generated using the random-building shader approach. BUILDING_LIST buildings.txt OSM_Building -2.72943543 56.00080606 36.1 0 buildings.txt: 0 0 0 0 0 0 100 0 0 0 0 200 0 0 0 0 300 0 0 1 0 400 0 0 1 0 500 0 0 2 100 0 0 0 2 200 0 0 0 2 300 0 0 0 2 400 0 0 15 2
This commit is contained in:
@@ -50,6 +50,8 @@
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/tgdb/apt_signs.hxx>
|
||||
#include <simgear/scene/tgdb/obj.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/tgdb/SGBuildingBin.hxx>
|
||||
|
||||
#include "SGOceanTile.hxx"
|
||||
|
||||
@@ -59,6 +61,7 @@
|
||||
#define ROAD_DETAILED "OBJECT_ROAD_DETAILED"
|
||||
#define RAILWAY_ROUGH "OBJECT_RAILWAY_ROUGH"
|
||||
#define RAILWAY_DETAILED "OBJECT_RAILWAY_DETAILED"
|
||||
#define BUILDING_LIST "BUILDING_LIST"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
@@ -121,6 +124,12 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
double _hdg;
|
||||
int _size;
|
||||
};
|
||||
struct _BuildingList {
|
||||
_BuildingList() : _lon(0), _lat(0), _elev(0) { }
|
||||
std::string _filename;
|
||||
std::string _material_name;
|
||||
double _lon, _lat, _elev;
|
||||
};
|
||||
|
||||
class DelayLoadReadFileCallback : public OptionsReadFileCallback {
|
||||
|
||||
@@ -185,8 +194,6 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
};
|
||||
typedef QuadTreeBuilder<osg::LOD*, _ObjectStatic, MakeQuadLeaf, AddModelLOD,
|
||||
GetModelLODCoord> STGObjectsQuadtree;
|
||||
|
||||
|
||||
public:
|
||||
virtual osgDB::ReaderWriter::ReadResult
|
||||
readNode(const std::string&, const osgDB::Options*)
|
||||
@@ -203,12 +210,40 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
if (signBuilder.getSignsGroup())
|
||||
group->addChild(signBuilder.getSignsGroup());
|
||||
|
||||
if (_buildingList.size() > 0) {
|
||||
SGMaterialLibPtr matlib = _options->getMaterialLib();
|
||||
bool useVBOs = (_options->getPluginStringData("SimGear::USE_VBOS") == "ON");
|
||||
|
||||
if (!matlib) {
|
||||
SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get materials definition for buildings");
|
||||
} else {
|
||||
for (std::list<_BuildingList>::iterator i = _buildingList.begin(); i != _buildingList.end(); ++i) {
|
||||
// Build buildings for each list of buildings
|
||||
SGGeod geodPos = SGGeod::fromDegM(i->_lon, i->_lat, 0.0);
|
||||
SGMaterial* mat = matlib->find(i->_material_name, geodPos);
|
||||
SGPath path = SGPath(i->_filename);
|
||||
SGBuildingBin* buildingBin = new SGBuildingBin(path, mat, useVBOs);
|
||||
|
||||
SGBuildingBinList buildingBinList;
|
||||
buildingBinList.push_back(buildingBin);
|
||||
|
||||
osg::MatrixTransform* matrixTransform;
|
||||
matrixTransform = new osg::MatrixTransform(makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev)));
|
||||
matrixTransform->setName("rotateBuildings");
|
||||
matrixTransform->setDataVariance(osg::Object::STATIC);
|
||||
matrixTransform->addChild(createRandomBuildings(buildingBinList, osg::Matrix::identity(), _options));
|
||||
group->addChild(matrixTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return group.release();
|
||||
}
|
||||
|
||||
mt _seed;
|
||||
std::list<_ObjectStatic> _objectStaticList;
|
||||
std::list<_Sign> _signList;
|
||||
std::list<_BuildingList> _buildingList;
|
||||
|
||||
/// The original options to use for this bunch of models
|
||||
osg::ref_ptr<SGReaderWriterOptions> _options;
|
||||
@@ -315,7 +350,6 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
|
||||
// starting with 2018.3 we will use deltas rather than absolutes as it is more intuitive for the user
|
||||
// and somewhat easier to visualise
|
||||
|
||||
double detailedRange = atof(options->getPluginStringData("SimGear::LOD_RANGE_DETAILED").c_str());
|
||||
double bareRangeDelta = atof(options->getPluginStringData("SimGear::LOD_RANGE_BARE").c_str());
|
||||
double roughRangeDelta = atof(options->getPluginStringData("SimGear::LOD_RANGE_ROUGH").c_str());
|
||||
@@ -490,6 +524,13 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
obj._options = opt;
|
||||
checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
|
||||
_objectStaticList.push_back(obj);
|
||||
} else if (token == BUILDING_LIST) {
|
||||
_BuildingList buildinglist;
|
||||
buildinglist._filename = path.local8BitStr();
|
||||
in >> buildinglist._material_name >> buildinglist._lon >> buildinglist._lat >> buildinglist._elev;
|
||||
checkInsideBucket(absoluteFileName, buildinglist._lon, buildinglist._lat);
|
||||
_buildingListList.push_back(buildinglist);
|
||||
//SG_LOG(SG_TERRAIN, SG_ALERT, "Building list: " << buildinglist._filename << " " << buildinglist._material_name << " " << buildinglist._lon << " " << buildinglist._lat);
|
||||
} else {
|
||||
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
|
||||
<< ": Unknown token '" << token << "'" );
|
||||
@@ -560,6 +601,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
// we just need to know about the read file callback that itself holds the data
|
||||
osg::ref_ptr<DelayLoadReadFileCallback> readFileCallback = new DelayLoadReadFileCallback;
|
||||
readFileCallback->_objectStaticList = _objectStaticList;
|
||||
readFileCallback->_buildingList = _buildingListList;
|
||||
readFileCallback->_signList = _signList;
|
||||
readFileCallback->_options = options;
|
||||
readFileCallback->_bucket = bucket;
|
||||
@@ -584,6 +626,7 @@ struct ReaderWriterSTG::_ModelBin {
|
||||
std::list<_Object> _objectList;
|
||||
std::list<_ObjectStatic> _objectStaticList;
|
||||
std::list<_Sign> _signList;
|
||||
std::list<_BuildingList> _buildingListList;
|
||||
};
|
||||
|
||||
ReaderWriterSTG::ReaderWriterSTG()
|
||||
|
||||
@@ -44,12 +44,11 @@
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
#include <simgear/math/SGLimits.hxx>
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/scene/material/Effect.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/model/model.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
@@ -107,6 +106,59 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
return bb;
|
||||
}
|
||||
|
||||
// Set up a BuildingBin from a file containing a list of individual building
|
||||
// positions.
|
||||
SGBuildingBin::SGBuildingBin(const SGPath& absoluteFileName, const SGMaterial *mat, bool useVBOs) :
|
||||
SGBuildingBin::SGBuildingBin(mat, useVBOs)
|
||||
{
|
||||
if (!absoluteFileName.exists()) {
|
||||
SG_LOG(SG_TERRAIN, SG_ALERT, "Building 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 << " does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
while (!stream.eof()) {
|
||||
// read a line. Each line defines a single builing position, and may have
|
||||
// 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);
|
||||
|
||||
// Line format is X Y Z R T
|
||||
// where:
|
||||
// X,Y,Z are the cartesian coordinates of the bottom SW corner of the building. +X is East, +Y is North
|
||||
// R is the building rotation in degrees centered on the SW corner
|
||||
// T is the building type [0, 1, 2] for SMALL, MEDIUM, LARGE
|
||||
float x, y, z, r;
|
||||
int t;
|
||||
in >> x >> y >> z >> r >> t;
|
||||
|
||||
//SG_LOG(SG_TERRAIN, SG_ALERT, "Building entry " << x << " " << y << " " << z << " " << t );
|
||||
SGVec3f p = SGVec3f(x,y,z);
|
||||
BuildingType type = BuildingType::SMALL;
|
||||
if (t == 1) type = BuildingType::MEDIUM;
|
||||
if (t == 2) type = BuildingType::LARGE;
|
||||
|
||||
// Rotation is in the file as degrees, but in the datastructure normalized
|
||||
// to 0.0 - 1.0
|
||||
insert(p, (float) (r / 360.0f), type);
|
||||
}
|
||||
|
||||
stream.close();
|
||||
};
|
||||
|
||||
// Set up the building set based on the material definitions
|
||||
SGBuildingBin::SGBuildingBin(const SGMaterial *mat, bool useVBOs) {
|
||||
|
||||
@@ -165,7 +217,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
if (useVBOs) {
|
||||
sharedGeometry->setUseVertexBufferObjects(true);
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int j = 0; j < BUILDING_SET_SIZE; j++) {
|
||||
float width;
|
||||
float depth;
|
||||
@@ -820,8 +872,8 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
};
|
||||
|
||||
// This actually returns a MatrixTransform node. If we rotate the whole
|
||||
// forest into the local Z-up coordinate system we can reuse the
|
||||
// primitive building geometry for all the forests of the same type.
|
||||
// set of buildings into the local Z-up coordinate system we can reuse the
|
||||
// primitive building geometry for all the buildings of the same type.
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList& buildings, const osg::Matrix& transform,
|
||||
const SGReaderWriterOptions* options)
|
||||
{
|
||||
|
||||
@@ -36,10 +36,12 @@
|
||||
#include <osg/Material>
|
||||
#include <osg/CullFace>
|
||||
|
||||
|
||||
#include <simgear/scene/util/OsgMath.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
||||
#include <simgear/scene/material/Effect.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
|
||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
||||
#include <simgear/scene/util/RenderConstants.hxx>
|
||||
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
||||
@@ -169,6 +171,7 @@ private:
|
||||
public:
|
||||
|
||||
SGBuildingBin(const SGMaterial *mat, bool useVBOs);
|
||||
SGBuildingBin(const SGPath& absoluteFileName, const SGMaterial *mat, bool useVBOs);
|
||||
|
||||
~SGBuildingBin() {
|
||||
smallBuildings.clear();
|
||||
|
||||
@@ -230,9 +230,9 @@ void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t)
|
||||
posArray->insert(posArray->end(), 4, pos);
|
||||
|
||||
size_t numVerts = posArray->size();
|
||||
int imax = 2;
|
||||
unsigned int imax = 2;
|
||||
if (use_tree_shadows) { imax = 3; }
|
||||
for (int i = 0; i < imax; ++i) {
|
||||
for (unsigned int i = 0; i < imax; ++i) {
|
||||
if (i < geom->getNumPrimitiveSets()) {
|
||||
DrawArrays* primSet = static_cast<DrawArrays*>(geom->getPrimitiveSet(i));
|
||||
if (primSet != nullptr)
|
||||
|
||||
Reference in New Issue
Block a user