New materials.xml format
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user