PagedLOD for random trees, buildings and objects.
This commit is contained in:
parent
3ec9c7ae6e
commit
5bc535a8d2
@ -110,10 +110,10 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
// Set up the building set based on the material definitions
|
||||
SGBuildingBin::SGBuildingBin(const SGMaterial *mat) {
|
||||
|
||||
material_name = mat->get_names()[0];
|
||||
material_name = new std::string(mat->get_names()[0]);
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Building material " << material_name);
|
||||
texture = mat->get_building_texture();
|
||||
lightMap = mat->get_building_lightmap();
|
||||
texture = new std::string(mat->get_building_texture());
|
||||
lightMap = new std::string(mat->get_building_lightmap());
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Building texture " << texture);
|
||||
|
||||
// Generate a random seed for the building generation.
|
||||
@ -721,7 +721,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
ref_ptr<Group> SGBuildingBin::createBuildingsGroup(Matrix transInv, const SGReaderWriterOptions* options)
|
||||
{
|
||||
ref_ptr<Effect> effect;
|
||||
EffectMap::iterator iter = buildingEffectMap.find(texture);
|
||||
EffectMap::iterator iter = buildingEffectMap.find(*texture);
|
||||
|
||||
if ((iter == buildingEffectMap.end())||
|
||||
(!iter->second.lock(effect)))
|
||||
@ -731,15 +731,15 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
||||
// Main texture - n=0
|
||||
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
||||
->setStringValue(texture);
|
||||
->setStringValue(*texture);
|
||||
|
||||
// Light map - n=3
|
||||
params->getChild("texture", 3, true)->getChild("image", 0, true)
|
||||
->setStringValue(lightMap);
|
||||
->setStringValue(*lightMap);
|
||||
|
||||
effect = makeEffect(effectProp, true, options);
|
||||
if (iter == buildingEffectMap.end())
|
||||
buildingEffectMap.insert(EffectMap::value_type(texture, effect));
|
||||
buildingEffectMap.insert(EffectMap::value_type(*texture, effect));
|
||||
else
|
||||
iter->second = effect; // update existing, but empty observer
|
||||
}
|
||||
@ -819,27 +819,28 @@ 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.
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix& transform,
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList& buildings, const osg::Matrix& transform,
|
||||
const SGReaderWriterOptions* options)
|
||||
{
|
||||
Matrix transInv = Matrix::inverse(transform);
|
||||
static Matrix ident;
|
||||
// Set up some shared structures.
|
||||
MatrixTransform* mt = new MatrixTransform(transform);
|
||||
SGBuildingBinList::iterator i;
|
||||
|
||||
SGBuildingBin* bin = NULL;
|
||||
|
||||
BOOST_FOREACH(bin, buildings)
|
||||
{
|
||||
for (i = buildings.begin(); i != buildings.end(); ++i) {
|
||||
SGBuildingBin* bin = *i;
|
||||
ref_ptr<Group> group = bin->createBuildingsGroup(transInv, options);
|
||||
|
||||
for (size_t i = 0; i < group->getNumChildren(); ++i)
|
||||
mt->addChild(group->getChild(i));
|
||||
for (size_t j = 0; j < group->getNumChildren(); ++j) {
|
||||
mt->addChild(group->getChild(j));
|
||||
}
|
||||
|
||||
delete bin;
|
||||
}
|
||||
|
||||
buildings.clear();
|
||||
|
||||
QuadTreeCleaner cleaner;
|
||||
mt->accept(cleaner);
|
||||
return mt;
|
||||
|
@ -100,9 +100,9 @@ private:
|
||||
BuildingList mediumBuildings;
|
||||
BuildingList largeBuildings;
|
||||
|
||||
std::string material_name;
|
||||
std::string texture;
|
||||
std::string lightMap;
|
||||
std::string* material_name;
|
||||
std::string* texture;
|
||||
std::string* lightMap;
|
||||
|
||||
// Fraction of buildings of this type
|
||||
float smallBuildingFraction;
|
||||
@ -184,7 +184,7 @@ public:
|
||||
|
||||
bool checkMinDist (SGVec3f p, float radius);
|
||||
|
||||
std::string getMaterialName() { return material_name; }
|
||||
std::string* getMaterialName() { return material_name; }
|
||||
|
||||
BuildingType getBuildingType(float roll);
|
||||
|
||||
@ -313,7 +313,7 @@ public:
|
||||
typedef std::list<SGBuildingBin*> SGBuildingBinList;
|
||||
|
||||
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList buildinglist, const osg::Matrix& transform,
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList& buildinglist, const osg::Matrix& transform,
|
||||
const SGReaderWriterOptions* options);
|
||||
}
|
||||
#endif
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <osg/LOD>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Point>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Switch>
|
||||
|
||||
@ -59,6 +60,7 @@
|
||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||
#include <simgear/scene/util/QuadTreeBuilder.hxx>
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/util/OptionsReadFileCallback.hxx>
|
||||
|
||||
#include "SGTexturedTriangleBin.hxx"
|
||||
#include "SGLightBin.hxx"
|
||||
@ -77,7 +79,8 @@ typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
|
||||
typedef std::list<SGLightBin> SGLightListBin;
|
||||
typedef std::list<SGDirectionalLightBin> SGDirectionalLightListBin;
|
||||
|
||||
struct SGTileGeometryBin {
|
||||
class SGTileGeometryBin : public osg::Referenced {
|
||||
public:
|
||||
SGMaterialTriangleMap materialTriangleMap;
|
||||
SGLightBin tileLights;
|
||||
SGLightBin randomTileLights;
|
||||
@ -486,28 +489,25 @@ struct SGTileGeometryBin {
|
||||
continue;
|
||||
|
||||
osg::Texture2D* object_mask = mat->get_object_mask(triangleBin);
|
||||
osg::Image* img;
|
||||
if (object_mask != NULL) {
|
||||
img = object_mask->getImage();
|
||||
}
|
||||
|
||||
int group_count = mat->get_object_group_count();
|
||||
float building_coverage = mat->get_building_coverage();
|
||||
float cos_zero_density_angle = mat->get_cos_object_zero_density_slope_angle();
|
||||
float cos_max_density_angle = mat->get_cos_object_max_density_slope_angle();
|
||||
|
||||
bool found = false;
|
||||
SGBuildingBin* bin = NULL;
|
||||
if (building_coverage == 0)
|
||||
continue;
|
||||
|
||||
SGBuildingBin* bin;
|
||||
|
||||
if (building_coverage > 0) {
|
||||
BOOST_FOREACH(bin, randomBuildings)
|
||||
{
|
||||
if (bin->getMaterialName() == mat->get_names()[0]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
bin = new SGBuildingBin(mat);
|
||||
randomBuildings.push_back(bin);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned num = i->second.getNumTriangles();
|
||||
int random_dropped = 0;
|
||||
@ -638,8 +638,6 @@ struct SGTileGeometryBin {
|
||||
(int)object->get_randomized_range_m(&seed),
|
||||
rotation);
|
||||
}
|
||||
|
||||
n -= 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -678,6 +676,7 @@ struct SGTileGeometryBin {
|
||||
|
||||
// Place an object each unit of area
|
||||
while (num > 1.0) {
|
||||
num -= 1.0;
|
||||
|
||||
// Set the next location to place a building
|
||||
a += stepv0;
|
||||
@ -721,7 +720,6 @@ struct SGTileGeometryBin {
|
||||
} else {
|
||||
// Fails mask test - try again.
|
||||
mask_dropped++;
|
||||
num -= 1.0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -744,7 +742,6 @@ struct SGTileGeometryBin {
|
||||
float edge_dist = *std::min_element(edges, edges + 3);
|
||||
|
||||
if (edge_dist < radius) {
|
||||
num -= 1.0;
|
||||
triangle_dropped++;
|
||||
continue;
|
||||
}
|
||||
@ -762,7 +759,6 @@ struct SGTileGeometryBin {
|
||||
}
|
||||
|
||||
if (close) {
|
||||
num -= 1.0;
|
||||
building_dropped++;
|
||||
continue;
|
||||
}
|
||||
@ -776,7 +772,6 @@ struct SGTileGeometryBin {
|
||||
}
|
||||
|
||||
if (close) {
|
||||
num -= 1.0;
|
||||
random_dropped++;
|
||||
continue;
|
||||
}
|
||||
@ -784,7 +779,6 @@ struct SGTileGeometryBin {
|
||||
std::pair<SGVec3f, float> pt = std::make_pair(buildingCenter, radius);
|
||||
triangleBuildingList.push_back(pt);
|
||||
bin->insert(randomPoint, rotation, buildingtype);
|
||||
num -= 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,22 +886,184 @@ struct GetModelLODCoord {
|
||||
typedef QuadTreeBuilder<osg::LOD*, ModelLOD, MakeQuadLeaf, AddModelLOD,
|
||||
GetModelLODCoord> RandomObjectsQuadtree;
|
||||
|
||||
osg::Node*
|
||||
SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options)
|
||||
{
|
||||
SGBinObject tile;
|
||||
if (!tile.read_bin(path))
|
||||
return NULL;
|
||||
class RandomObjectCallback : public OptionsReadFileCallback {
|
||||
public:
|
||||
virtual osgDB::ReaderWriter::ReadResult
|
||||
readNode(const std::string&, const osgDB::Options*)
|
||||
{
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
group->setName("Random Object and Lighting Group");
|
||||
group->setDataVariance(osg::Object::STATIC);
|
||||
|
||||
SGMaterialLib* matlib = 0;
|
||||
osg::LOD* lightLOD = generateLightingTileObjects();
|
||||
if (lightLOD)
|
||||
group->addChild(lightLOD);
|
||||
|
||||
osg::LOD* objectLOD = generateRandomTileObjects();
|
||||
if (objectLOD)
|
||||
group->addChild(objectLOD);
|
||||
|
||||
return group.release();
|
||||
}
|
||||
|
||||
// Generate all the lighting objects for the tile.
|
||||
osg::LOD* generateLightingTileObjects()
|
||||
{
|
||||
SGMaterialLib* matlib;
|
||||
|
||||
if (_options)
|
||||
matlib = _options->getMaterialLib();
|
||||
|
||||
// FIXME: ugly, has a side effect
|
||||
if (matlib)
|
||||
_tileGeometryBin->computeRandomSurfaceLights(matlib);
|
||||
|
||||
GroundLightManager* lightManager = GroundLightManager::instance();
|
||||
osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
|
||||
SGVec3f up(0, 0, 1);
|
||||
|
||||
if (_tileGeometryBin->tileLights.getNumLights() > 0
|
||||
|| _tileGeometryBin->randomTileLights.getNumLights() > 0) {
|
||||
osg::Group* groundLights0 = new osg::Group;
|
||||
groundLights0->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->tileLights));
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->randomTileLights, 4, -0.3f));
|
||||
groundLights0->addChild(geode);
|
||||
lightGroup->addChild(groundLights0);
|
||||
}
|
||||
|
||||
if (_tileGeometryBin->randomTileLights.getNumLights() > 0) {
|
||||
osg::Group* groundLights1 = new osg::Group;
|
||||
groundLights1->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
|
||||
osg::Group* groundLights2 = new osg::Group;
|
||||
groundLights2->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->randomTileLights, 2, -0.15f));
|
||||
groundLights1->addChild(geode);
|
||||
lightGroup->addChild(groundLights1);
|
||||
geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->randomTileLights));
|
||||
groundLights2->addChild(geode);
|
||||
lightGroup->addChild(groundLights2);
|
||||
}
|
||||
|
||||
if (!_tileGeometryBin->vasiLights.empty()) {
|
||||
EffectGeode* vasiGeode = new EffectGeode;
|
||||
Effect* vasiEffect
|
||||
= getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true);
|
||||
vasiGeode->setEffect(vasiEffect);
|
||||
SGVec4f red(1, 0, 0, 1);
|
||||
SGMaterial* mat = 0;
|
||||
if (matlib)
|
||||
mat = matlib->find("RWY_RED_LIGHTS");
|
||||
if (mat)
|
||||
red = mat->get_light_color();
|
||||
SGVec4f white(1, 1, 1, 1);
|
||||
mat = 0;
|
||||
if (matlib)
|
||||
mat = matlib->find("RWY_WHITE_LIGHTS");
|
||||
if (mat)
|
||||
white = mat->get_light_color();
|
||||
SGDirectionalLightListBin::const_iterator i;
|
||||
for (i = _tileGeometryBin->vasiLights.begin();
|
||||
i != _tileGeometryBin->vasiLights.end(); ++i) {
|
||||
vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
|
||||
}
|
||||
vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
|
||||
lightGroup->addChild(vasiGeode);
|
||||
}
|
||||
|
||||
Effect* runwayEffect = 0;
|
||||
if (_tileGeometryBin->runwayLights.getNumLights() > 0
|
||||
|| !_tileGeometryBin->rabitLights.empty()
|
||||
|| !_tileGeometryBin->reilLights.empty()
|
||||
|| !_tileGeometryBin->odalLights.empty()
|
||||
|| _tileGeometryBin->taxiLights.getNumLights() > 0)
|
||||
runwayEffect = getLightEffect(16, osg::Vec3(1, 0.001, 0.0002), 1, 16, true);
|
||||
if (_tileGeometryBin->runwayLights.getNumLights() > 0
|
||||
|| !_tileGeometryBin->rabitLights.empty()
|
||||
|| !_tileGeometryBin->reilLights.empty()
|
||||
|| !_tileGeometryBin->odalLights.empty()
|
||||
|| !_tileGeometryBin->holdshortLights.empty()
|
||||
|| !_tileGeometryBin->guardLights.empty()) {
|
||||
osg::Group* rwyLights = new osg::Group;
|
||||
rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
|
||||
rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
|
||||
if (_tileGeometryBin->runwayLights.getNumLights() != 0) {
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(runwayEffect);
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->runwayLights));
|
||||
rwyLights->addChild(geode);
|
||||
}
|
||||
SGDirectionalLightListBin::const_iterator i;
|
||||
for (i = _tileGeometryBin->rabitLights.begin();
|
||||
i != _tileGeometryBin->rabitLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getSequenced(*i));
|
||||
}
|
||||
for (i = _tileGeometryBin->reilLights.begin();
|
||||
i != _tileGeometryBin->reilLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getSequenced(*i));
|
||||
}
|
||||
for (i = _tileGeometryBin->holdshortLights.begin();
|
||||
i != _tileGeometryBin->holdshortLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getHoldShort(*i));
|
||||
}
|
||||
for (i = _tileGeometryBin->guardLights.begin();
|
||||
i != _tileGeometryBin->guardLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getGuard(*i));
|
||||
}
|
||||
SGLightListBin::const_iterator j;
|
||||
for (j = _tileGeometryBin->odalLights.begin();
|
||||
j != _tileGeometryBin->odalLights.end(); ++j) {
|
||||
rwyLights->addChild(SGLightFactory::getOdal(*j));
|
||||
}
|
||||
lightGroup->addChild(rwyLights);
|
||||
}
|
||||
|
||||
if (_tileGeometryBin->taxiLights.getNumLights() > 0) {
|
||||
osg::Group* taxiLights = new osg::Group;
|
||||
taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
|
||||
taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(runwayEffect);
|
||||
geode->addDrawable(SGLightFactory::getLights(_tileGeometryBin->taxiLights));
|
||||
taxiLights->addChild(geode);
|
||||
lightGroup->addChild(taxiLights);
|
||||
}
|
||||
|
||||
osg::LOD* lightLOD = NULL;
|
||||
|
||||
if (lightGroup->getNumChildren() > 0) {
|
||||
lightLOD = new osg::LOD;
|
||||
lightLOD->addChild(lightGroup.get(), 0, 60000);
|
||||
// VASI is always on, so doesn't use light bits.
|
||||
lightLOD->setNodeMask(LIGHTS_BITS | MODEL_BIT | PERMANENTLIGHT_BIT);
|
||||
}
|
||||
|
||||
return lightLOD;
|
||||
}
|
||||
|
||||
// Generate all the random forest, objects and buildings for the tile
|
||||
osg::LOD* generateRandomTileObjects()
|
||||
{
|
||||
SGMaterialLib* matlib;
|
||||
bool use_random_objects = false;
|
||||
bool use_random_vegetation = false;
|
||||
bool use_random_buildings = false;
|
||||
float vegetation_density = 1.0f;
|
||||
float building_density = 1.0f;
|
||||
if (options) {
|
||||
matlib = options->getMaterialLib();
|
||||
SGPropertyNode* propertyNode = options->getPropertyNode().get();
|
||||
|
||||
osg::ref_ptr<osg::Group> randomObjects;
|
||||
osg::ref_ptr<osg::Group> forestNode;
|
||||
osg::ref_ptr<osg::Group> buildingNode;
|
||||
|
||||
if (_options) {
|
||||
matlib = _options->getMaterialLib();
|
||||
SGPropertyNode* propertyNode = _options->getPropertyNode().get();
|
||||
if (propertyNode) {
|
||||
use_random_objects
|
||||
= propertyNode->getBoolValue("/sim/rendering/random-objects",
|
||||
@ -927,60 +1083,28 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
|
||||
}
|
||||
}
|
||||
|
||||
SGVec3d center = tile.get_gbs_center();
|
||||
SGGeod geodPos = SGGeod::fromCart(center);
|
||||
SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
|
||||
|
||||
// rotate the tiles so that the bounding boxes get nearly axis aligned.
|
||||
// this will help the collision tree's bounding boxes a bit ...
|
||||
std::vector<SGVec3d> nodes = tile.get_wgs84_nodes();
|
||||
for (unsigned i = 0; i < nodes.size(); ++i)
|
||||
nodes[i] = hlOr.transform(nodes[i]);
|
||||
tile.set_wgs84_nodes(nodes);
|
||||
|
||||
SGQuatf hlOrf(hlOr[0], hlOr[1], hlOr[2], hlOr[3]);
|
||||
std::vector<SGVec3f> normals = tile.get_normals();
|
||||
for (unsigned i = 0; i < normals.size(); ++i)
|
||||
normals[i] = hlOrf.transform(normals[i]);
|
||||
tile.set_normals(normals);
|
||||
|
||||
SGTileGeometryBin tileGeometryBin;
|
||||
if (!tileGeometryBin.insertBinObj(tile, matlib))
|
||||
return NULL;
|
||||
|
||||
SGVec3f up(0, 0, 1);
|
||||
GroundLightManager* lightManager = GroundLightManager::instance();
|
||||
|
||||
osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
|
||||
osg::ref_ptr<osg::Group> randomObjects;
|
||||
osg::ref_ptr<osg::Group> forestNode;
|
||||
osg::ref_ptr<osg::Group> buildingNode;
|
||||
osg::Group* terrainGroup = new osg::Group;
|
||||
terrainGroup->setName("BTGTerrainGroup");
|
||||
|
||||
osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
|
||||
if (node)
|
||||
terrainGroup->addChild(node);
|
||||
|
||||
if (matlib && (use_random_objects || use_random_buildings)) {
|
||||
tileGeometryBin.computeRandomObjectsAndBuildings(matlib,
|
||||
_tileGeometryBin->computeRandomObjectsAndBuildings(matlib,
|
||||
building_density,
|
||||
use_random_objects,
|
||||
use_random_buildings);
|
||||
}
|
||||
|
||||
if (tileGeometryBin.randomModels.getNumModels() > 0) {
|
||||
|
||||
if (_tileGeometryBin->randomModels.getNumModels() > 0) {
|
||||
// Generate a repeatable random seed
|
||||
mt seed;
|
||||
mt_init(&seed, unsigned(123));
|
||||
|
||||
std::vector<ModelLOD> models;
|
||||
for (unsigned int i = 0;
|
||||
i < tileGeometryBin.randomModels.getNumModels(); i++) {
|
||||
i < _tileGeometryBin->randomModels.getNumModels(); i++) {
|
||||
SGMatModelBin::MatModel obj
|
||||
= tileGeometryBin.randomModels.getMatModel(i);
|
||||
= _tileGeometryBin->randomModels.getMatModel(i);
|
||||
|
||||
SGPropertyNode* root = options->getPropertyNode()->getRootNode();
|
||||
SGPropertyNode* root = _options->getPropertyNode()->getRootNode();
|
||||
osg::Node* node = obj.model->get_random_model(root, &seed);
|
||||
|
||||
// Create a matrix to place the object in the correct
|
||||
@ -1005,7 +1129,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
|
||||
|
||||
osg::MatrixTransform* position =
|
||||
new osg::MatrixTransform(transformMat);
|
||||
position->setName("positionRandomeModel");
|
||||
position->setName("positionRandomModel");
|
||||
position->addChild(node);
|
||||
models.push_back(ModelLOD(position, obj.lod));
|
||||
}
|
||||
@ -1015,160 +1139,28 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
|
||||
randomObjects->setName("Random objects");
|
||||
}
|
||||
|
||||
if (! tileGeometryBin.randomBuildings.empty()) {
|
||||
buildingNode = createRandomBuildings(tileGeometryBin.randomBuildings, osg::Matrix::identity(),
|
||||
options);
|
||||
if (! _tileGeometryBin->randomBuildings.empty()) {
|
||||
buildingNode = createRandomBuildings(_tileGeometryBin->randomBuildings, osg::Matrix::identity(),
|
||||
_options);
|
||||
buildingNode->setName("Random buildings");
|
||||
_tileGeometryBin->randomBuildings.clear();
|
||||
}
|
||||
|
||||
if (use_random_vegetation && matlib) {
|
||||
// Now add some random forest.
|
||||
tileGeometryBin.computeRandomForest(matlib, vegetation_density);
|
||||
_tileGeometryBin->computeRandomForest(matlib, vegetation_density);
|
||||
|
||||
if (! tileGeometryBin.randomForest.empty()) {
|
||||
forestNode = createForest(tileGeometryBin.randomForest, osg::Matrix::identity(),
|
||||
options);
|
||||
if (! _tileGeometryBin->randomForest.empty()) {
|
||||
forestNode = createForest(_tileGeometryBin->randomForest, osg::Matrix::identity(),
|
||||
_options);
|
||||
forestNode->setName("Random trees");
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: ugly, has a side effect
|
||||
if (matlib)
|
||||
tileGeometryBin.computeRandomSurfaceLights(matlib);
|
||||
|
||||
if (tileGeometryBin.tileLights.getNumLights() > 0
|
||||
|| tileGeometryBin.randomTileLights.getNumLights() > 0) {
|
||||
osg::Group* groundLights0 = new osg::Group;
|
||||
groundLights0->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
|
||||
groundLights0->addChild(geode);
|
||||
lightGroup->addChild(groundLights0);
|
||||
}
|
||||
|
||||
if (tileGeometryBin.randomTileLights.getNumLights() > 0) {
|
||||
osg::Group* groundLights1 = new osg::Group;
|
||||
groundLights1->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
|
||||
osg::Group* groundLights2 = new osg::Group;
|
||||
groundLights2->setStateSet(lightManager->getGroundLightStateSet());
|
||||
groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
|
||||
groundLights1->addChild(geode);
|
||||
lightGroup->addChild(groundLights1);
|
||||
geode = new osg::Geode;
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
|
||||
groundLights2->addChild(geode);
|
||||
lightGroup->addChild(groundLights2);
|
||||
}
|
||||
|
||||
if (!tileGeometryBin.vasiLights.empty()) {
|
||||
EffectGeode* vasiGeode = new EffectGeode;
|
||||
Effect* vasiEffect
|
||||
= getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true);
|
||||
vasiGeode->setEffect(vasiEffect);
|
||||
SGVec4f red(1, 0, 0, 1);
|
||||
SGMaterial* mat = 0;
|
||||
if (matlib)
|
||||
mat = matlib->find("RWY_RED_LIGHTS");
|
||||
if (mat)
|
||||
red = mat->get_light_color();
|
||||
SGVec4f white(1, 1, 1, 1);
|
||||
mat = 0;
|
||||
if (matlib)
|
||||
mat = matlib->find("RWY_WHITE_LIGHTS");
|
||||
if (mat)
|
||||
white = mat->get_light_color();
|
||||
SGDirectionalLightListBin::const_iterator i;
|
||||
for (i = tileGeometryBin.vasiLights.begin();
|
||||
i != tileGeometryBin.vasiLights.end(); ++i) {
|
||||
vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
|
||||
}
|
||||
vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
|
||||
lightGroup->addChild(vasiGeode);
|
||||
}
|
||||
|
||||
Effect* runwayEffect = 0;
|
||||
if (tileGeometryBin.runwayLights.getNumLights() > 0
|
||||
|| !tileGeometryBin.rabitLights.empty()
|
||||
|| !tileGeometryBin.reilLights.empty()
|
||||
|| !tileGeometryBin.odalLights.empty()
|
||||
|| tileGeometryBin.taxiLights.getNumLights() > 0)
|
||||
runwayEffect = getLightEffect(16, osg::Vec3(1, 0.001, 0.0002), 1, 16, true);
|
||||
if (tileGeometryBin.runwayLights.getNumLights() > 0
|
||||
|| !tileGeometryBin.rabitLights.empty()
|
||||
|| !tileGeometryBin.reilLights.empty()
|
||||
|| !tileGeometryBin.odalLights.empty()
|
||||
|| !tileGeometryBin.holdshortLights.empty()
|
||||
|| !tileGeometryBin.guardLights.empty()) {
|
||||
osg::Group* rwyLights = new osg::Group;
|
||||
rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
|
||||
rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
|
||||
if (tileGeometryBin.runwayLights.getNumLights() != 0) {
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(runwayEffect);
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin
|
||||
.runwayLights));
|
||||
rwyLights->addChild(geode);
|
||||
}
|
||||
SGDirectionalLightListBin::const_iterator i;
|
||||
for (i = tileGeometryBin.rabitLights.begin();
|
||||
i != tileGeometryBin.rabitLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getSequenced(*i));
|
||||
}
|
||||
for (i = tileGeometryBin.reilLights.begin();
|
||||
i != tileGeometryBin.reilLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getSequenced(*i));
|
||||
}
|
||||
for (i = tileGeometryBin.holdshortLights.begin();
|
||||
i != tileGeometryBin.holdshortLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getHoldShort(*i));
|
||||
}
|
||||
for (i = tileGeometryBin.guardLights.begin();
|
||||
i != tileGeometryBin.guardLights.end(); ++i) {
|
||||
rwyLights->addChild(SGLightFactory::getGuard(*i));
|
||||
}
|
||||
SGLightListBin::const_iterator j;
|
||||
for (j = tileGeometryBin.odalLights.begin();
|
||||
j != tileGeometryBin.odalLights.end(); ++j) {
|
||||
rwyLights->addChild(SGLightFactory::getOdal(*j));
|
||||
}
|
||||
lightGroup->addChild(rwyLights);
|
||||
}
|
||||
|
||||
if (tileGeometryBin.taxiLights.getNumLights() > 0) {
|
||||
osg::Group* taxiLights = new osg::Group;
|
||||
taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
|
||||
taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(runwayEffect);
|
||||
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.taxiLights));
|
||||
taxiLights->addChild(geode);
|
||||
lightGroup->addChild(taxiLights);
|
||||
}
|
||||
|
||||
// The toplevel transform for that tile.
|
||||
osg::MatrixTransform* transform = new osg::MatrixTransform;
|
||||
transform->setName(path);
|
||||
transform->setMatrix(osg::Matrix::rotate(toOsg(hlOr))*
|
||||
osg::Matrix::translate(toOsg(center)));
|
||||
transform->addChild(terrainGroup);
|
||||
if (lightGroup->getNumChildren() > 0) {
|
||||
osg::LOD* lightLOD = new osg::LOD;
|
||||
lightLOD->addChild(lightGroup.get(), 0, 60000);
|
||||
// VASI is always on, so doesn't use light bits.
|
||||
lightLOD->setNodeMask(LIGHTS_BITS | MODEL_BIT | PERMANENTLIGHT_BIT);
|
||||
transform->addChild(lightLOD);
|
||||
}
|
||||
osg::LOD* objectLOD = NULL;
|
||||
|
||||
if (randomObjects.valid() || forestNode.valid() || buildingNode.valid()) {
|
||||
|
||||
// Add a LoD node, so we don't try to display anything when the tile center
|
||||
// is more than 20km away.
|
||||
osg::LOD* objectLOD = new osg::LOD;
|
||||
objectLOD = new osg::LOD;
|
||||
|
||||
if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000);
|
||||
if (forestNode.valid()) objectLOD->addChild(forestNode.get(), 0, 20000);
|
||||
@ -1176,8 +1168,83 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
|
||||
|
||||
unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECEIVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT;
|
||||
objectLOD->setNodeMask(nodeMask);
|
||||
transform->addChild(objectLOD);
|
||||
}
|
||||
|
||||
return objectLOD;
|
||||
}
|
||||
|
||||
/// The original options to use for this bunch of models
|
||||
osg::ref_ptr<SGReaderWriterOptions> _options;
|
||||
osg::ref_ptr<SGTileGeometryBin> _tileGeometryBin;
|
||||
};
|
||||
|
||||
osg::Node*
|
||||
SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options)
|
||||
{
|
||||
SGBinObject tile;
|
||||
if (!tile.read_bin(path))
|
||||
return NULL;
|
||||
|
||||
SGMaterialLib* matlib = 0;
|
||||
|
||||
if (options) {
|
||||
matlib = options->getMaterialLib();
|
||||
}
|
||||
|
||||
SGVec3d center = tile.get_gbs_center();
|
||||
SGGeod geodPos = SGGeod::fromCart(center);
|
||||
SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
|
||||
|
||||
// rotate the tiles so that the bounding boxes get nearly axis aligned.
|
||||
// this will help the collision tree's bounding boxes a bit ...
|
||||
std::vector<SGVec3d> nodes = tile.get_wgs84_nodes();
|
||||
for (unsigned i = 0; i < nodes.size(); ++i)
|
||||
nodes[i] = hlOr.transform(nodes[i]);
|
||||
tile.set_wgs84_nodes(nodes);
|
||||
|
||||
SGQuatf hlOrf(hlOr[0], hlOr[1], hlOr[2], hlOr[3]);
|
||||
std::vector<SGVec3f> normals = tile.get_normals();
|
||||
for (unsigned i = 0; i < normals.size(); ++i)
|
||||
normals[i] = hlOrf.transform(normals[i]);
|
||||
tile.set_normals(normals);
|
||||
|
||||
osg::ref_ptr<SGTileGeometryBin> tileGeometryBin = new SGTileGeometryBin;
|
||||
|
||||
if (!tileGeometryBin->insertBinObj(tile, matlib))
|
||||
return NULL;
|
||||
|
||||
osg::Group* terrainGroup = new osg::Group;
|
||||
terrainGroup->setName("BTGTerrainGroup");
|
||||
|
||||
osg::Node* node = tileGeometryBin->getSurfaceGeometry(matlib);
|
||||
if (node)
|
||||
terrainGroup->addChild(node);
|
||||
|
||||
// The toplevel transform for that tile.
|
||||
osg::MatrixTransform* transform = new osg::MatrixTransform;
|
||||
transform->setName(path);
|
||||
transform->setMatrix(osg::Matrix::rotate(toOsg(hlOr))*
|
||||
osg::Matrix::translate(toOsg(center)));
|
||||
transform->addChild(terrainGroup);
|
||||
|
||||
// PagedLOD for the random objects so we don't need to generate
|
||||
// them all on tile loading.
|
||||
osg::PagedLOD* pagedLOD = new osg::PagedLOD;
|
||||
pagedLOD->setCenterMode(osg::PagedLOD::USE_BOUNDING_SPHERE_CENTER);
|
||||
pagedLOD->setName("pagedObjectLOD");
|
||||
|
||||
// we just need to know about the read file callback that itself holds the data
|
||||
osg::ref_ptr<RandomObjectCallback> randomObjectCallback = new RandomObjectCallback;
|
||||
randomObjectCallback->_options = SGReaderWriterOptions::copyOrCreate(options);
|
||||
randomObjectCallback->_tileGeometryBin = tileGeometryBin;
|
||||
|
||||
osg::ref_ptr<osgDB::Options> callbackOptions = new osgDB::Options;
|
||||
callbackOptions->setReadFileCallback(randomObjectCallback.get());
|
||||
pagedLOD->setDatabaseOptions(callbackOptions.get());
|
||||
|
||||
pagedLOD->setFileName(pagedLOD->getNumChildren(), "Dummy name - use the stored data in the read file callback");
|
||||
pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 35000);
|
||||
transform->addChild(pagedLOD);
|
||||
transform->setNodeMask( ~simgear::MODELLIGHT_BIT );
|
||||
|
||||
return transform;
|
||||
|
Loading…
Reference in New Issue
Block a user