#include "Effect.hxx"
#include "Technique.hxx"
+#include "Pass.hxx"
#include <algorithm>
#include <functional>
#include <osg/Drawable>
#include <osg/RenderInfo>
#include <osg/StateSet>
-
#include <osgUtil/CullVisitor>
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/ParameterOutput>
#include <simgear/structure/OSGUtils.hxx>
using namespace osg;
using namespace osgUtil;
+Effect::Effect()
+{
+}
+
Effect::Effect(const Effect& rhs, const CopyOp& copyop)
{
using namespace std;
backRefInsertIterator(techniques),
bind(simgear::clone_ref<Technique>, _1, copyop));
}
+
+// Assume that the last technique is always valid.
+StateSet* Effect::getDefaultStateSet()
+{
+ Technique* tniq = techniques.back().get();
+ if (!tniq)
+ return 0;
+ Pass* pass = tniq->passes.front().get();
+ if (!pass)
+ return 0;
+ return pass->getStateSet();
+}
+
// There should always be a valid technique in an effect.
Technique* Effect::chooseTechnique(RenderInfo* info)
technique->releaseGLObjects(state);
}
}
+
+Effect::~Effect()
+{
+}
+
+bool Effect_writeLocalData(const Object& obj, osgDB::Output& fw)
+{
+ const Effect& effect = static_cast<const Effect&>(obj);
+
+ fw.indent() << "techniques " << effect.techniques.size() << "\n";
+ BOOST_FOREACH(const ref_ptr<Technique>& technique, effect.techniques) {
+ fw.writeObject(*technique);
+ }
+ return true;
+}
+
+namespace
+{
+osgDB::RegisterDotOsgWrapperProxy effectProxy
+(
+ new Effect,
+ "simgear::Effect",
+ "Object simgear::Effect",
+ 0,
+ &Effect_writeLocalData
+ );
}
+}
+
{
public:
META_Object(simgear,Effect)
- Effect() {}
+ Effect();
Effect(const Effect& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
osg::StateSet* getDefaultStateSet();
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* state = 0) const;
protected:
- ~Effect() {}
+ ~Effect();
};
}
#endif
--- /dev/null
+// Copyright (C) 2008 Timothy Moore timoore@redhat.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "EffectCullVisitor.hxx"
+
+#include "EffectGeode.hxx"
+#include "Effect.hxx"
+#include "Technique.hxx"
+
+namespace simgear
+{
+
+using osgUtil::CullVisitor;
+
+EffectCullVisitor::EffectCullVisitor()
+{
+}
+
+EffectCullVisitor::EffectCullVisitor(const EffectCullVisitor& rhs) :
+ CullVisitor(rhs)
+{
+}
+
+CullVisitor* EffectCullVisitor::clone() const
+{
+ return new EffectCullVisitor(*this);
+}
+
+void EffectCullVisitor::apply(osg::Geode& node)
+{
+ if (isCulled(node))
+ return;
+ EffectGeode *eg = dynamic_cast<EffectGeode*>(&node);
+ if (!eg) {
+ CullVisitor::apply(node);
+ return;
+ }
+ Technique* technique = eg->getEffect()->chooseTechnique(&getRenderInfo());
+ if (!technique) {
+ CullVisitor::apply(node);
+ return;
+ }
+ for (EffectGeode::DrawablesIterator beginItr = eg->drawablesBegin(),
+ e = eg->drawablesEnd();
+ beginItr != e;
+ beginItr = technique->processDrawables(beginItr, e, this,
+ eg->isCullingActive()))
+ ;
+}
+}
--- /dev/null
+// Copyright (C) 2008 Timothy Moore timoore@redhat.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef SIMGEAR_EFFECT_CULL_VISITOR_HXX
+#define SIMGEAR_EFFECT_CULL_VISITOR_HXX 1
+
+#include <osgUtil/CullVisitor>
+
+namespace osg
+{
+class Geode;
+}
+
+namespace simgear
+{
+class EffectCullVisitor : public osgUtil::CullVisitor
+{
+public:
+ EffectCullVisitor();
+ EffectCullVisitor(const EffectCullVisitor&);
+ virtual osgUtil::CullVisitor* clone() const;
+ using osgUtil::CullVisitor::apply;
+ virtual void apply(osg::Geode& node);
+};
+}
+#endif
#include <osgUtil/CullVisitor>
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/ParameterOutput>
+
namespace simgear
{
using namespace osg;
using namespace osgUtil;
-void EffectGeode::traverse(NodeVisitor& nv)
+EffectGeode::EffectGeode()
{
- CullVisitor* cv = dynamic_cast<CullVisitor*>(&nv);
- if (!cv || !_effect.valid()) {
- Geode::traverse(nv);
- return;
- }
- Technique* technique = _effect->chooseTechnique(&cv->getRenderInfo());
- if (!technique) {
- Geode::traverse(nv);
- return;
- }
- for (DrawablesIterator beginItr = _drawables.begin();
- beginItr != _drawables.end();
- beginItr = technique->processDrawables(beginItr, _drawables.end(), cv,
- isCullingActive()))
- ;
+}
+
+EffectGeode::EffectGeode(const EffectGeode& rhs, const CopyOp& copyop) :
+ Geode(rhs, copyop)
+{
+ _effect = static_cast<Effect*>(rhs._effect->clone(copyop));
}
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
Geode::releaseGLObjects(state);
}
+bool EffectGeode_writeLocalData(const Object& obj, osgDB::Output& fw)
+{
+ const EffectGeode& eg = static_cast<const EffectGeode&>(obj);
+
+ fw.indent() << "effect\n";
+ fw.writeObject(*eg.getEffect());
+ return true;
+}
+
+namespace
+{
+osgDB::RegisterDotOsgWrapperProxy effectGeodeProxy
+(
+ new EffectGeode,
+ "simgear::EffectGeode",
+ "Object Node Geode simgear::EffectGeode",
+ 0,
+ &EffectGeode_writeLocalData
+ );
+}
}
EffectGeode(const EffectGeode& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
META_Node(simgear,EffectGeode);
- virtual void traverse(osg::NodeVisitor& nv);
Effect* getEffect() const { return _effect.get(); }
- void setEffect(Effect* effect);
+ void setEffect(Effect* effect) { _effect = effect; }
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* = 0) const;
typedef DrawableList::iterator DrawablesIterator;
+ DrawablesIterator drawablesBegin() { return _drawables.begin(); }
+ DrawablesIterator drawablesEnd() { return _drawables.end(); }
private:
osg::ref_ptr<Effect> _effect;
};
include_HEADERS = \
Effect.hxx \
+ EffectCullVisitor.hxx \
EffectGeode.hxx \
Pass.hxx \
Technique.hxx \
libsgmaterial_a_SOURCES = \
Effect.cxx \
+ EffectCullVisitor.cxx \
EffectGeode.cxx \
Pass.cxx \
Technique.cxx \
#include <simgear/structure/OSGUtils.hxx>
#include <osg/StateSet>
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/ParameterOutput>
namespace simgear
{
_stateSet->releaseGLObjects(state);
}
+bool Pass_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
+{
+ const Pass& pass = static_cast<const Pass&>(obj);
+
+ fw.indent() << "stateSet\n";
+ fw.writeObject(*pass.getStateSet());
+ return true;
+}
+
+namespace
+{
+osgDB::RegisterDotOsgWrapperProxy passProxy
+(
+ new Pass,
+ "simgear::Pass",
+ "Object simgear::Pass",
+ 0,
+ &Pass_writeLocalData
+ );
+}
}
Pass(const Pass& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
osg::StateSet* getStateSet() { return _stateSet.get(); }
+ const osg::StateSet* getStateSet() const { return _stateSet.get(); }
void setStateSet(osg::StateSet* stateSet) { _stateSet = stateSet; }
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* state = 0) const;
#include <osg/Math>
#include <osgUtil/CullVisitor>
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/ParameterOutput>
+
#include <simgear/structure/OSGUtils.hxx>
namespace simgear
}
}
-Technique::Technique() : _glVersion(1.1f)
+Technique::Technique(bool alwaysValid)
+ : _alwaysValid(alwaysValid), _glVersion(1.1f)
{
}
Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
- _contextMap(rhs._contextMap), _shadowingStateSet(rhs._shadowingStateSet),
- _glVersion(rhs._glVersion)
+ _contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
+ _shadowingStateSet(rhs._shadowingStateSet), _glVersion(rhs._glVersion)
{
using namespace std;
using namespace boost;
Technique::Status Technique::valid(osg::RenderInfo* renderInfo)
{
+ if (_alwaysValid)
+ return VALID;
unsigned contextID = renderInfo->getContextID();
ContextInfo& contextInfo = _contextMap[contextID];
Status status = contextInfo.valid();
Technique::Status Technique::getValidStatus(const RenderInfo* renderInfo) const
{
+ if (_alwaysValid)
+ return VALID;
ContextInfo& contextInfo = _contextMap[renderInfo->getContextID()];
return contextInfo.valid();
}
info.valid.compareAndSwap(oldVal, UNKNOWN);
}
}
+
+bool Technique_writeLocalData(const Object& obj, osgDB::Output& fw)
+{
+ const Technique& tniq = static_cast<const Technique&>(obj);
+ fw.indent() << "alwaysValid "
+ << (tniq.getAlwaysValid() ? "TRUE\n" : "FALSE\n");
+ fw.indent() << "glVersion " << tniq.getGLVersion() << "\n";
+ if (tniq.getShadowingStateSet()) {
+ fw.indent() << "shadowingStateSet\n";
+ fw.writeObject(*tniq.getShadowingStateSet());
+ }
+ fw.indent() << "passes\n";
+ BOOST_FOREACH(const ref_ptr<Pass>& pass, tniq.passes) {
+ fw.writeObject(*pass);
+ }
+ return true;
+}
+
+namespace
+{
+osgDB::RegisterDotOsgWrapperProxy TechniqueProxy
+(
+ new Technique,
+ "simgear::Technique",
+ "Object simgear::Technique",
+ 0,
+ &Technique_writeLocalData
+ );
+}
}
{
public:
META_Object(simgear,Technique);
- Technique();
+ Technique(bool alwaysValid = false);
Technique(const Technique& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
virtual ~Technique();
bool isCullingActive);
std::vector<osg::ref_ptr<Pass> > passes;
osg::StateSet* getShadowingStateSet() { return _shadowingStateSet.get(); }
+ const osg::StateSet* getShadowingStateSet() const
+ {
+ return _shadowingStateSet.get();
+ }
void setShadowingStateSet(osg::StateSet* ss) { _shadowingStateSet = ss; }
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* state = 0) const;
// Initial validity testing. Either the minimum OpenGL version
// must be supported, or the list of extensions must be supported.
- float getGLVersion() { return _glVersion; }
+ float getGLVersion() const { return _glVersion; }
void setGLVersion(float glVersion) { _glVersion = glVersion; }
std::vector<std::string> glExtensions;
+ bool getAlwaysValid() const { return _alwaysValid; }
+ void setAlwaysValid(bool val) { _alwaysValid = val; }
protected:
// Validity of technique in a graphics context.
struct ContextInfo : public osg::Referenced
};
typedef osg::buffered_object<ContextInfo> ContextMap;
mutable ContextMap _contextMap;
+ bool _alwaysValid;
osg::ref_ptr<osg::StateSet> _shadowingStateSet;
float _glVersion;
};
#include <string.h>
#include <map>
+#include "mat.hxx"
+
#include <osg/CullFace>
#include <osg/Material>
#include <osg/ShadeModel>
+#include <osg/StateSet>
#include <osg/TexEnv>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
-#include "mat.hxx"
+#include "Effect.hxx"
+#include "Technique.hxx"
+#include "Pass.hxx"
using std::map;
using namespace simgear;
// Constructors and destructor.
////////////////////////////////////////////////////////////////////////
+SGMaterial::_internal_state::_internal_state(osg::StateSet *s,
+ const std::string &t, bool l ) :
+ state(s), texture_path(t), texture_loaded(l)
+{
+}
SGMaterial::SGMaterial( const string &fg_root, const SGPropertyNode *props )
{
return st;
}
+Effect* SGMaterial::get_effect(int n)
+{
+ if (_status.size() == 0) {
+ SG_LOG( SG_GENERAL, SG_WARN, "No effect available.");
+ return 0;
+ }
+ int i = n >= 0 ? n : _current_ptr;
+ if(!_status[i].texture_loaded) {
+ assignTexture(_status[i].state.get(), _status[i].texture_path,
+ wrapu, wrapv, mipmap);
+ _status[i].texture_loaded = true;
+ }
+ // XXX This business of returning a "random" alternate texture is
+ // really bogus. It means that the appearance of the terrain
+ // depends on the order in which it is paged in!
+ _current_ptr = (_current_ptr + 1) % _status.size();
+ return _status[i].effect.get();
+}
void
SGMaterial::build_state( bool defer_tex_load )
{
StateAttributeFactory *attrFact = StateAttributeFactory::instance();
+ SGMaterialUserData* user = new SGMaterialUserData(this);
for (unsigned int i = 0; i < _status.size(); i++)
{
osg::StateSet *stateSet = new osg::StateSet;
- stateSet->setUserData(new SGMaterialUserData(this));
+ stateSet->setUserData(user);
// Set up the textured state
stateSet->setAttribute(attrFact->getSmoothShadeModel());
}
_status[i].state = stateSet;
+ Pass* pass = new Pass;
+ pass->setStateSet(_status[i].state.get());
+ Technique* tniq = new Technique(true);
+ tniq->passes.push_back(pass);
+ Effect* effect = new Effect;
+ effect->techniques.push_back(tniq);
+ effect->setUserData(user);
+ _status[i].effect = effect;
}
}
#include <simgear/math/SGMath.hxx>
#include <osg/ref_ptr>
-#include <osg/StateSet>
+
+namespace osg
+{
+class StateSet;
+}
#include <simgear/props/props.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include "matmodel.hxx"
-using std::string;
-using std::vector;
-using std::map;
-
+namespace simgear
+{
+class Effect;
+}
class SGMaterialGlyph;
* state information for the material. This node is usually
* loaded from the $FG_ROOT/materials.xml file.
*/
- SGMaterial( const string &fg_root, const SGPropertyNode *props);
+ SGMaterial( const std::string &fg_root, const SGPropertyNode *props);
/**
* @param texture_path A string containing an absolute path
* to a texture file (usually RGB).
*/
- SGMaterial( const string &texpath );
+ SGMaterial( const std::string &texpath );
/**
* Get the textured state.
*/
osg::StateSet *get_state (int n = -1);
-
+ simgear::Effect *get_effect(int n = -1);
/**
* Get the number of textures assigned to this material.
*
* @return the texture to use for trees.
*/
- inline string get_tree_texture () const { return tree_texture; }
+ inline std::string get_tree_texture () const { return tree_texture; }
/**
* Return if the surface material is solid, if it is not solid, a fluid
/**
* Get the list of names for this material
*/
- const vector<string>& get_names() const { return _names; }
+ const std::vector<std::string>& get_names() const { return _names; }
/**
* add the given name to the list of names this material is known
*/
- void add_name(const string& name) { _names.push_back(name); }
+ void add_name(const std::string& name) { _names.push_back(name); }
/**
* Get the number of randomly-placed objects defined for this material.
/**
* Return pointer to glyph class, or 0 if it doesn't exist.
*/
- SGMaterialGlyph * get_glyph (const string& name) const;
+ SGMaterialGlyph * get_glyph (const std::string& name) const;
void set_light_color(const SGVec4f& color)
{ emission = color; }
protected:
struct _internal_state {
- _internal_state( osg::StateSet *s, const string &t, bool l )
- : state(s), texture_path(t), texture_loaded(l) {}
+ _internal_state( osg::StateSet *s, const std::string &t, bool l );
osg::ref_ptr<osg::StateSet> state;
- string texture_path;
+ osg::ref_ptr<simgear::Effect> effect;
+ std::string texture_path;
bool texture_loaded;
};
////////////////////////////////////////////////////////////////////
// texture status
- vector<_internal_state> _status;
+ std::vector<_internal_state> _status;
// Round-robin counter
mutable unsigned int _current_ptr;
double shininess;
// the list of names for this material. May be empty.
- vector<string> _names;
+ std::vector<std::string> _names;
- vector<SGSharedPtr<SGMatModelGroup> > object_groups;
+ std::vector<SGSharedPtr<SGMatModelGroup> > object_groups;
// taxiway-/runway-sign texture elements
- map<string, SGSharedPtr<SGMaterialGlyph> > glyphs;
+ std::map<std::string, SGSharedPtr<SGMaterialGlyph> > glyphs;
// Tree texture, typically a strip of applicable tree textures
- string tree_texture;
+ std::string tree_texture;
\f
////////////////////////////////////////////////////////////////////
// Internal constructors and methods.
////////////////////////////////////////////////////////////////////
- SGMaterial( const string &fg_root, const SGMaterial &mat ); // unimplemented
+ SGMaterial( const std::string &fg_root, const SGMaterial &mat ); // unimplemented
- void read_properties( const string &fg_root, const SGPropertyNode *props );
+ void read_properties( const std::string &fg_root, const SGPropertyNode *props );
void build_state( bool defer_tex_load );
void set_state( osg::StateSet *s );
#include "mat.hxx"
+#include "Effect.hxx"
+#include "Technique.hxx"
#include "matlib.hxx"
using std::string;
layer_states[SG_CLOUD_CLEAR] = 0;
layer_states2[SG_CLOUD_CLEAR] = 0;
+#if 0
+ // experimental optimization that may not make any difference
+ // at all :/
osg::CopyOp copyOp;
for (int i = 0; i < SG_MAX_CLOUD_COVERAGES; ++i) {
StateAttributeFactory *saf = StateAttributeFactory::instance();
layer_states2[i]->setAttribute(saf ->getCullFaceBack());
}
}
- // OSGFIXME
-// SGNewCloud::loadTextures(texture_path.str());
-// layer3D->buildTestLayer();
+#endif
}
scale = 4000.0;
#include <simgear/io/sg_binobj.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_random.h>
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/model/SGOffsetTransform.hxx>
if (materialTriangleMap.empty())
return 0;
- osg::Geode* geode = new osg::Geode;
+ EffectGeode* eg = 0;
+ osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : 0);
+ //osg::Geode* geode = new osg::Geode;
SGMaterialTriangleMap::const_iterator i;
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
osg::Geometry* geometry = i->second.buildGeometry();
SGMaterial *mat = 0;
if (matlib)
mat = matlib->find(i->first);
+ eg = new EffectGeode;
if (mat)
- geometry->setStateSet(mat->get_state());
- geode->addDrawable(geometry);
+ eg->setEffect(mat->get_effect());
+ eg->addDrawable(geometry);
+ if (group)
+ group->addChild(eg);
}
- return geode;
+ if (group)
+ return group;
+ else
+ return eg;
}
void computeRandomSurfaceLights(SGMaterialLib* matlib)