New materials.xml format

This commit is contained in:
Stuart Buchanan
2014-08-09 20:34:08 +01:00
parent 14f2f9e917
commit e7e616e07c
7 changed files with 268 additions and 130 deletions

View File

@@ -96,19 +96,27 @@ void SGMaterial::_internal_state::add_texture(const std::string &t, int i)
SGMaterial::SGMaterial( const SGReaderWriterOptions* options,
const SGPropertyNode *props,
SGPropertyNode *prop_root )
SGPropertyNode *prop_root,
AreaList *a,
SGSharedPtr<const SGCondition> c)
{
init();
areas = a;
condition = c;
read_properties( options, props, prop_root );
buildEffectProperties(options);
}
SGMaterial::SGMaterial( const osgDB::Options* options,
const SGPropertyNode *props,
SGPropertyNode *prop_root)
SGPropertyNode *prop_root,
AreaList *a,
SGSharedPtr<const SGCondition> c)
{
osg::ref_ptr<SGReaderWriterOptions> opt;
opt = SGReaderWriterOptions::copyOrCreate(options);
areas = a;
condition = c;
init();
read_properties(opt.get(), props, prop_root);
buildEffectProperties(opt.get());
@@ -409,12 +417,6 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
} else {
parameters = new SGPropertyNode();
}
// Read conditions node
const SGPropertyNode *conditionNode = props->getChild("condition");
if (conditionNode) {
condition = sgReadCondition(prop_root, conditionNode);
}
}
@@ -552,13 +554,43 @@ SGMaterialGlyph* SGMaterial::get_glyph (const std::string& name) const
return it->second;
}
bool SGMaterial::valid() const
{
if (condition) {
return condition->test();
} else {
return true;
}
bool SGMaterial::valid(SGVec2f loc) const
{
SG_LOG( SG_TERRAIN, SG_BULK, "Checking materials for location ("
<< loc.x() << ","
<< loc.y() << ")");
// Check location first again the areas the material is valid for
AreaList::const_iterator i = areas->begin();
if (i == areas->end()) {
// No areas defined, so simply check against condition
if (condition) {
return condition->test();
} else {
return true;
}
}
for (; i != areas->end(); i++) {
SG_LOG( SG_TERRAIN, SG_BULK, "Checking area ("
<< i->x() << ","
<< i->y() << ") width:"
<< i->width() << " height:"
<< i->height());
// Areas defined, so check that the tile location falls within it
// before checking against condition
if (i->contains(loc.x(), loc.y())) {
if (condition) {
return condition->test();
} else {
return true;
}
}
}
return false;
}

View File

@@ -42,14 +42,18 @@ namespace osg
class StateSet;
}
typedef osg::ref_ptr<osg::Texture2D> Texture2DRef;
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/threads/SGThread.hxx> // for SGMutex
#include <simgear/math/SGLimits.hxx>
#include <simgear/math/SGMisc.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/math/SGVec2.hxx>
#include <simgear/math/SGRect.hxx>
#include <simgear/bvh/BVHMaterial.hxx>
typedef osg::ref_ptr<osg::Texture2D> Texture2DRef;
typedef std::vector<SGRect <float> > AreaList;
namespace simgear
{
class Effect;
@@ -88,13 +92,19 @@ public:
* state information for the material. This node is usually
* loaded from the $FG_ROOT/materials.xml file.
*/
SGMaterial( const osgDB::Options*,
const SGPropertyNode *props,
SGPropertyNode *prop_root);
SGMaterial(const osgDB::Options*,
const SGPropertyNode *props,
SGPropertyNode *prop_root,
AreaList *a,
SGSharedPtr<const SGCondition> c);
SGMaterial(const simgear::SGReaderWriterOptions*,
const SGPropertyNode *props,
SGPropertyNode *prop_root);
SGPropertyNode *prop_root,
AreaList *a,
SGSharedPtr<const SGCondition> c);
/**
* Destructor.
*/
@@ -306,9 +316,9 @@ public:
/**
* Evaluate whether this material is valid given the current global
* property state.
* property state and the tile location.
*/
bool valid() const;
bool valid(SGVec2f loc) const;
/**
* Return pointer to glyph class, or 0 if it doesn't exist.
@@ -474,6 +484,9 @@ private:
// Condition, indicating when this material is active
SGSharedPtr<const SGCondition> condition;
// List of geographical rectangles for this material
AreaList* areas;
// Parameters from the materials file
const SGPropertyNode* parameters;

View File

@@ -37,6 +37,7 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
@@ -68,11 +69,11 @@ SGMaterialLib::SGMaterialLib ( void ) :
bool SGMaterialLib::load( const string &fg_root, const string& mpath,
SGPropertyNode *prop_root )
{
SGPropertyNode materials;
SGPropertyNode materialblocks;
SG_LOG( SG_INPUT, SG_INFO, "Reading materials from " << mpath );
try {
readProperties( mpath, &materials );
readProperties( mpath, &materialblocks );
} catch (const sg_exception &ex) {
SG_LOG( SG_INPUT, SG_ALERT, "Error reading materials: "
<< ex.getMessage() );
@@ -82,44 +83,88 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath,
= new osgDB::Options;
options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
options->setDatabasePath(fg_root);
int nMaterials = materials.nChildren();
for (int i = 0; i < nMaterials; i++) {
const SGPropertyNode *node = materials.getChild(i);
if (!strcmp(node->getName(), "material")) {
SGSharedPtr<SGMaterial> m = new SGMaterial(options.get(), node, prop_root);
std::vector<SGPropertyNode_ptr>names = node->getChildren("name");
for ( unsigned int j = 0; j < names.size(); j++ ) {
string name = names[j]->getStringValue();
// cerr << "Material " << name << endl;
matlib[name].push_back(m);
m->add_name(name);
SG_LOG( SG_TERRAIN, SG_DEBUG, " Loading material "
<< names[j]->getStringValue() );
}
} else {
SG_LOG(SG_INPUT, SG_WARN,
"Skipping bad material entry " << node->getName());
}
simgear::PropertyList blocks = materialblocks.getChildren("region");
simgear::PropertyList::const_iterator block_iter = blocks.begin();
for (; block_iter != blocks.end(); block_iter++) {
SGPropertyNode_ptr node = block_iter->get();
// Read name node purely for logging purposes
const SGPropertyNode *nameNode = node->getChild("name");
if (nameNode) {
SG_LOG( SG_TERRAIN, SG_INFO, "Loading region "
<< nameNode->getStringValue());
}
// Read list of areas
AreaList* arealist = new AreaList;
const simgear::PropertyList areas = node->getChildren("area");
simgear::PropertyList::const_iterator area_iter = areas.begin();
for (; area_iter != areas.end(); area_iter++) {
float x1 = area_iter->get()->getFloatValue("lon1", -180.0f);
float x2 = area_iter->get()->getFloatValue("lon2", 180.0);
float y1 = area_iter->get()->getFloatValue("lat1", -90.0f);
float y2 = area_iter->get()->getFloatValue("lat2", 90.0f);
SGRect<float> rect = SGRect<float>(
fminf(x1, x2),
fminf(y1, y2),
fabs(x2 - x1),
fabs(y2 - y1));
arealist->push_back(rect);
SG_LOG( SG_TERRAIN, SG_INFO, " Area ("
<< rect.x() << ","
<< rect.y() << ") width:"
<< rect.width() << " height:"
<< rect.height());
}
// Read conditions node
const SGPropertyNode *conditionNode = node->getChild("condition");
SGSharedPtr<const SGCondition> condition;
if (conditionNode) {
condition = sgReadCondition(prop_root, conditionNode);
}
// Now build all the materials for this set of areas and conditions
const simgear::PropertyList materials = node->getChildren("material");
simgear::PropertyList::const_iterator materials_iter = materials.begin();
for (; materials_iter != materials.end(); materials_iter++) {
const SGPropertyNode *node = materials_iter->get();
SGSharedPtr<SGMaterial> m =
new SGMaterial(options.get(), node, prop_root, arealist, condition);
std::vector<SGPropertyNode_ptr>names = node->getChildren("name");
for ( unsigned int j = 0; j < names.size(); j++ ) {
string name = names[j]->getStringValue();
// cerr << "Material " << name << endl;
matlib[name].push_back(m);
m->add_name(name);
SG_LOG( SG_TERRAIN, SG_DEBUG, " Loading material "
<< names[j]->getStringValue() );
}
}
}
return true;
}
// find a material record by material name
SGMaterial *SGMaterialLib::find( const string& material ) const
// find a material record by material name and tile center
SGMaterial *SGMaterialLib::find( const string& material, const SGVec2f center ) const
{
SGMaterial *result = NULL;
const_material_map_iterator it = matlib.find( material );
if ( it != end() ) {
// We now have a list of materials that match this
// name. Find the first one that either doesn't have
// a condition, or has a condition that evaluates
// to true.
material_list::const_iterator iter = it->second.begin();
while (iter != it->second.end()) {
// name. Find the first one that matches.
// We start at the end of the list, as the materials
// list is ordered with the smallest regions at the end.
material_list::const_reverse_iterator iter = it->second.rbegin();
while (iter != it->second.rend()) {
result = *iter;
if (result->valid()) {
if (result->valid(center)) {
return result;
}
iter++;
@@ -129,31 +174,31 @@ SGMaterial *SGMaterialLib::find( const string& material ) const
return NULL;
}
void SGMaterialLib::refreshActiveMaterials()
// find a material record by material name and tile center
SGMaterial *SGMaterialLib::find( const string& material, const SGGeod& center ) const
{
active_material_cache newCache;
material_map_iterator it = matlib.begin();
for (; it != matlib.end(); ++it) {
newCache[it->first] = find(it->first);
}
// use this approach to minimise the time we're holding the lock
// lock on the mutex (and hence, would block findCached calls)
SGGuard<SGMutex> g(d->mutex);
active_cache = newCache;
SGVec2f c = SGVec2f(center.getLongitudeDeg(), center.getLatitudeDeg());
return find(material, c);
}
SGMaterial *SGMaterialLib::findCached( const string& material ) const
SGMaterialCache *SGMaterialLib::generateMatCache(SGVec2f center)
{
SGGuard<SGMutex> g(d->mutex);
SGMaterialCache* newCache = new SGMaterialCache();
material_map::const_reverse_iterator it = matlib.rbegin();
for (; it != matlib.rend(); ++it) {
newCache->insert(it->first, find(it->first, center));
}
active_material_cache::const_iterator it = active_cache.find(material);
if (it == active_cache.end())
return NULL;
return it->second;
return newCache;
}
SGMaterialCache *SGMaterialLib::generateMatCache(SGGeod center)
{
SGVec2f c = SGVec2f(center.getLongitudeDeg(), center.getLatitudeDeg());
return SGMaterialLib::generateMatCache(c);
}
// Destructor
SGMaterialLib::~SGMaterialLib ( void ) {
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
@@ -176,3 +221,28 @@ const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
return 0;
return userData->getMaterial();
}
// Constructor
SGMaterialCache::SGMaterialCache ( void )
{
}
// Insertion into the material cache
void SGMaterialCache::insert(const std::string& name, SGSharedPtr<SGMaterial> material) {
cache[name] = material;
}
// Search of the material cache
SGMaterial *SGMaterialCache::find(const string& material) const
{
SGMaterialCache::material_cache::const_iterator it = cache.find(material);
if (it == cache.end())
return NULL;
return it->second;
}
// Destructor
SGMaterialCache::~SGMaterialCache ( void ) {
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
}

View File

@@ -29,6 +29,7 @@
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/SGMath.hxx>
#include <memory>
#include <string> // Standard C++ string library
@@ -41,6 +42,27 @@ class SGPropertyNode;
namespace simgear { class Effect; }
namespace osg { class Geode; }
// Material cache class
class SGMaterialCache : public osg::Referenced
{
private:
typedef std::map < std::string, SGSharedPtr<SGMaterial> > material_cache;
material_cache cache;
public:
// Constructor
SGMaterialCache ( void );
// Insertion
void insert( const std::string& name, SGSharedPtr<SGMaterial> material );
// Lookup
SGMaterial *find( const std::string& material ) const;
// Destructor
~SGMaterialCache ( void );
};
// Material management class
class SGMaterialLib : public SGReferenced
{
@@ -59,9 +81,6 @@ private:
material_map matlib;
typedef std::map < std::string, SGSharedPtr<SGMaterial> > active_material_cache;
active_material_cache active_cache;
public:
// Constructor
@@ -71,24 +90,24 @@ public:
bool load( const std::string &fg_root, const std::string& mpath,
SGPropertyNode *prop_root );
// find a material record by material name
SGMaterial *find( const std::string& material ) const;
SGMaterial *find( const std::string& material, SGVec2f center ) const;
SGMaterial *find( const std::string& material, const SGGeod& center ) const;
/**
* Material lookup involves evaluation of SGConditions to determine which
* possible material (by season, region, etc) is valid. This involves
* vproperty tree queries, so repeated calls to find() can cause
* Material lookup involves evaluation of position and SGConditions to
* determine which possible material (by season, region, etc) is valid.
* This involves property tree queries, so repeated calls to find() can cause
* race conditions when called from the osgDB pager thread. (especially
* during startup)
*
* To fix this, and also avoid repeated re-evaluation of the material
* conditions, we provide a version which uses a cached, threadsafe table
* of the currently valid materials. The main thread calls the refresh
* method below to evaluate the valid materials, and findCached can be
* safely called from other threads with no access to unprotected state.
* conditions, we provide factory method to generate a material library
* cache of the valid materials based on the current state and a given position.
*/
SGMaterial *findCached( const std::string& material ) const;
void refreshActiveMaterials();
SGMaterialCache *generateMatCache( SGVec2f center);
SGMaterialCache *generateMatCache( SGGeod center);
material_map_iterator begin() { return matlib.begin(); }
const_material_map_iterator begin() const { return matlib.begin(); }
@@ -99,6 +118,7 @@ public:
// Destructor
~SGMaterialLib ( void );
};
typedef SGSharedPtr<SGMaterialLib> SGMaterialLibPtr;

View File

@@ -279,7 +279,10 @@ osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib, int latPoints,
double tex_width = 1000.0;
// find Ocean material in the properties list
SGMaterial *mat = matlib->findCached( "Ocean" );
SGMaterialCache* matcache = matlib->generateMatCache(b.get_center());
SGMaterial* mat = matcache->find( "Ocean" );
delete matcache;
if ( mat != NULL ) {
// set the texture width and height values for this
// material

View File

@@ -260,7 +260,7 @@ AirportSignBuilder::AirportSignBuilder(SGMaterialLib* mats, const SGGeod& center
assert(mats);
d->materials = mats;
d->signCaseGeometry = d->getGeometry(d->materials->find("signcase")->get_effect());
d->signCaseGeometry = d->getGeometry(d->materials->find("signcase", center)->get_effect());
}
osg::Node* AirportSignBuilder::getSignsGroup()
@@ -430,7 +430,7 @@ void AirportSignBuilder::addSign(const SGGeod& pos, double heading, const std::s
}
if (! newmat.empty()) {
material = d->materials->find(newmat);
material = d->materials->find(newmat, pos);
newmat.clear();
}
@@ -504,7 +504,7 @@ void AirportSignBuilder::addSign(const SGGeod& pos, double heading, const std::s
// Part II: typeset
double boxwidth = std::max(total_width1, total_width2) * 0.5;
double hpos = -boxwidth;
SGMaterial *mat = d->materials->find("signcase");
SGMaterial *mat = d->materials->find("signcase", pos);
double coverSize = fabs(total_width1 - total_width2) * 0.5;
element_info* s1 = new element_info(mat, mat->get_glyph("cover1"), sign_height, coverSize);

View File

@@ -141,7 +141,7 @@ public:
}
bool
insertPtGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
insertPtGeometry(const SGBinObject& obj, SGMaterialCache* matcache)
{
if (obj.get_pts_v().size() != obj.get_pts_n().size()) {
SG_LOG(SG_TERRAIN, SG_ALERT,
@@ -151,9 +151,7 @@ public:
for (unsigned grp = 0; grp < obj.get_pts_v().size(); ++grp) {
std::string materialName = obj.get_pt_materials()[grp];
SGMaterial* material = 0;
if (matlib)
material = matlib->findCached(materialName);
SGMaterial* material = matcache->find(materialName);
SGVec4f color = getMaterialLightColor(material);
if (3 <= materialName.size() && materialName.substr(0, 3) != "RWY") {
@@ -381,11 +379,11 @@ public:
}
}
SGVec2f getTexCoordScale(const std::string& name, SGMaterialLib* matlib)
SGVec2f getTexCoordScale(const std::string& name, SGMaterialCache* matcache)
{
if (!matlib)
if (!matcache)
return SGVec2f(1, 1);
SGMaterial* material = matlib->findCached(name);
SGMaterial* material = matcache->find(name);
if (!material)
return SGVec2f(1, 1);
@@ -393,7 +391,7 @@ public:
}
bool
insertSurfaceGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
insertSurfaceGeometry(const SGBinObject& obj, SGMaterialCache* matcache)
{
if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
obj.get_tris_tcs().size() < obj.get_tris_v().size()) {
@@ -404,7 +402,7 @@ public:
for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
std::string materialName = obj.get_tri_materials()[grp];
SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
SGVec2f tc1Scale(1.0, 1.0);
addTriangleGeometry(materialTriangleMap[materialName],
obj, grp, tc0Scale, tc1Scale );
@@ -418,7 +416,7 @@ public:
}
for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
std::string materialName = obj.get_strip_materials()[grp];
SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
SGVec2f tc1Scale(1.0, 1.0);
addStripGeometry(materialTriangleMap[materialName],
obj, grp, tc0Scale, tc1Scale);
@@ -432,7 +430,7 @@ public:
}
for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
std::string materialName = obj.get_fan_materials()[grp];
SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
SGVec2f tc1Scale(1.0, 1.0);
addFanGeometry(materialTriangleMap[materialName],
obj, grp, tc0Scale, tc1Scale );
@@ -440,7 +438,7 @@ public:
return true;
}
osg::Node* getSurfaceGeometry(SGMaterialLib* matlib, bool useVBOs) const
osg::Node* getSurfaceGeometry(SGMaterialCache* matcache, bool useVBOs) const
{
if (materialTriangleMap.empty())
return 0;
@@ -456,8 +454,8 @@ public:
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
osg::Geometry* geometry = i->second.buildGeometry(useVBOs);
SGMaterial *mat = NULL;
if (matlib) {
mat = matlib->findCached(i->first);
if (matcache) {
mat = matcache->find(i->first);
}
eg = new EffectGeode;
eg->setName("EffectGeode");
@@ -478,7 +476,7 @@ public:
}
}
void computeRandomSurfaceLights(SGMaterialLib* matlib)
void computeRandomSurfaceLights(SGMaterialCache* matcache)
{
SGMaterialTriangleMap::iterator i;
@@ -487,7 +485,7 @@ public:
mt_init(&seed, unsigned(123));
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
SGMaterial *mat = matlib->findCached(i->first);
SGMaterial *mat = matcache->find(i->first);
if (!mat)
continue;
@@ -530,7 +528,7 @@ public:
}
void computeRandomObjectsAndBuildings(
SGMaterialLib* matlib,
SGMaterialCache* matcache,
float building_density,
bool use_random_objects,
bool use_random_buildings,
@@ -543,7 +541,7 @@ public:
mt_init(&seed, unsigned(123));
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
SGMaterial *mat = matlib->findCached(i->first);
SGMaterial *mat = matcache->find(i->first);
SGTexturedTriangleBin triangleBin = i->second;
if (!mat)
@@ -850,7 +848,7 @@ public:
}
}
void computeRandomForest(SGMaterialLib* matlib, float vegetation_density)
void computeRandomForest(SGMaterialCache* matcache, float vegetation_density)
{
SGMaterialTriangleMap::iterator i;
@@ -860,7 +858,7 @@ public:
mt_init(&seed, unsigned(586));
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
SGMaterial *mat = matlib->findCached(i->first);
SGMaterial *mat = matcache->find(i->first);
if (!mat)
continue;
@@ -910,11 +908,11 @@ public:
}
}
bool insertBinObj(const SGBinObject& obj, SGMaterialLib* matlib)
bool insertBinObj(const SGBinObject& obj, SGMaterialCache* matcache)
{
if (!insertPtGeometry(obj, matlib))
if (!insertPtGeometry(obj, matcache))
return false;
if (!insertSurfaceGeometry(obj, matlib))
if (!insertSurfaceGeometry(obj, matcache))
return false;
return true;
}
@@ -978,6 +976,7 @@ public:
return NULL;
SGMaterialLibPtr matlib;
SGMaterialCache* matcache = 0;
bool useVBOs = false;
bool simplifyNear = false;
double ratio = SG_SIMPLIFIER_RATIO;
@@ -1001,6 +1000,9 @@ public:
SGGeod geodPos = SGGeod::fromCart(center);
SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
// Generate a materials cache
if (matlib) matcache = matlib->generateMatCache(geodPos);
// 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();
@@ -1016,10 +1018,10 @@ public:
osg::ref_ptr<SGTileGeometryBin> tileGeometryBin = new SGTileGeometryBin;
if (!tileGeometryBin->insertBinObj(tile, matlib))
if (!tileGeometryBin->insertBinObj(tile, matcache))
return NULL;
osg::Node* node = tileGeometryBin->getSurfaceGeometry(matlib, useVBOs);
osg::Node* node = tileGeometryBin->getSurfaceGeometry(matcache, useVBOs);
if (node && simplifyNear) {
osgUtil::Simplifier simplifier(ratio, maxError, maxLength);
node->accept(simplifier);
@@ -1031,14 +1033,8 @@ public:
// Generate all the lighting objects for the tile.
osg::LOD* generateLightingTileObjects()
{
SGMaterialLibPtr matlib;
if (_options)
matlib = _options->getMaterialLib();
// FIXME: ugly, has a side effect
if (matlib)
_tileGeometryBin->computeRandomSurfaceLights(matlib);
if (_matcache)
_tileGeometryBin->computeRandomSurfaceLights(_matcache);
GroundLightManager* lightManager = GroundLightManager::instance();
osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
@@ -1080,14 +1076,14 @@ public:
vasiGeode->setEffect(vasiEffect);
SGVec4f red(1, 0, 0, 1);
SGMaterial* mat = 0;
if (matlib)
mat = matlib->findCached("RWY_RED_LIGHTS");
if (_matcache)
mat = _matcache->find("RWY_RED_LIGHTS");
if (mat)
red = mat->get_light_color();
SGVec4f white(1, 1, 1, 1);
mat = 0;
if (matlib)
mat = matlib->findCached("RWY_WHITE_LIGHTS");
if (_matcache)
mat = _matcache->find("RWY_WHITE_LIGHTS");
if (mat)
white = mat->get_light_color();
SGDirectionalLightListBin::const_iterator i;
@@ -1211,7 +1207,7 @@ public:
if (matlib && (use_random_objects || use_random_buildings)) {
_tileGeometryBin->computeRandomObjectsAndBuildings(matlib,
_tileGeometryBin->computeRandomObjectsAndBuildings(_matcache,
building_density,
use_random_objects,
use_random_buildings,
@@ -1274,7 +1270,7 @@ public:
if (use_random_vegetation && matlib) {
// Now add some random forest.
_tileGeometryBin->computeRandomForest(matlib, vegetation_density);
_tileGeometryBin->computeRandomForest(_matcache, vegetation_density);
if (! _tileGeometryBin->randomForest.empty()) {
forestNode = createForest(_tileGeometryBin->randomForest, osg::Matrix::identity(),
@@ -1301,6 +1297,7 @@ public:
/// The original options to use for this bunch of models
osg::ref_ptr<SGReaderWriterOptions> _options;
osg::ref_ptr<SGMaterialCache> _matcache;
osg::ref_ptr<SGTileGeometryBin> _tileGeometryBin;
string _path;
bool _loadterrain;
@@ -1314,6 +1311,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
return NULL;
SGMaterialLibPtr matlib;
osg::ref_ptr<SGMaterialCache> matcache;
bool useVBOs = false;
bool simplifyDistant = false;
bool simplifyNear = false;
@@ -1340,6 +1338,8 @@ 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);
if (matlib)
matcache = matlib->generateMatCache(geodPos);
// rotate the tiles so that the bounding boxes get nearly axis aligned.
// this will help the collision tree's bounding boxes a bit ...
@@ -1356,11 +1356,10 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
osg::ref_ptr<SGTileGeometryBin> tileGeometryBin = new SGTileGeometryBin;
if (!tileGeometryBin->insertBinObj(tile, matlib))
if (!tileGeometryBin->insertBinObj(tile, matcache))
return NULL;
osg::Node* node = tileGeometryBin->getSurfaceGeometry(matlib, useVBOs);
osg::Node* node = tileGeometryBin->getSurfaceGeometry(matcache, useVBOs);
if (node && simplifyDistant) {
osgUtil::Simplifier simplifier(ratio, maxError, maxLength);
node->accept(simplifier);
@@ -1399,6 +1398,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
randomObjectCallback->_tileGeometryBin = tileGeometryBin;
randomObjectCallback->_path = std::string(path);
randomObjectCallback->_loadterrain = ! (simplifyNear == simplifyDistant);
randomObjectCallback->_matcache = matcache;
osg::ref_ptr<osgDB::Options> callbackOptions = new osgDB::Options;
callbackOptions->setReadFileCallback(randomObjectCallback.get());