Effects in models working for transparent materials and chrome animation
Implementation of animated effect values via the property system. Add names for TexEnvCombine attributes
This commit is contained in:
parent
cb07210bc7
commit
54c4055af3
@ -643,6 +643,15 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgprops"
|
Name="Lib_sgprops"
|
||||||
Filter="">
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\props\condition.cxx">
|
RelativePath="..\..\simgear\props\condition.cxx">
|
||||||
</File>
|
</File>
|
||||||
@ -1249,6 +1258,12 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.hxx">
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgbvh"
|
Name="Lib_sgbvh"
|
||||||
|
@ -983,6 +983,14 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgprops"
|
Name="Lib_sgprops"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\props\condition.cxx"
|
RelativePath="..\..\simgear\props\condition.cxx"
|
||||||
>
|
>
|
||||||
@ -991,6 +999,11 @@
|
|||||||
RelativePath="..\..\simgear\props\condition.hxx"
|
RelativePath="..\..\simgear\props\condition.hxx"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\props\props.cxx"
|
RelativePath="..\..\simgear\props\props.cxx"
|
||||||
>
|
>
|
||||||
@ -1809,6 +1822,14 @@
|
|||||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx"
|
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.cxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.hxx"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgbvh"
|
Name="Lib_sgbvh"
|
||||||
|
71
simgear/props/AtomicChangeListener.cxx
Normal file
71
simgear/props/AtomicChangeListener.cxx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "AtomicChangeListener.hxx"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include <simgear/structure/Singleton.hxx>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
MultiChangeListener::MultiChangeListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiChangeListener::valueChanged()
|
||||||
|
{
|
||||||
|
valueChangedImplementation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiChangeListener::valueChangedImplementation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomicChangeListener::AtomicChangeListener(std::vector<SGPropertyNode*>& nodes)
|
||||||
|
: _dirty(false), _valid(true)
|
||||||
|
{
|
||||||
|
listenToProperties(nodes.begin(), nodes.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicChangeListener::unregister_property(SGPropertyNode* node)
|
||||||
|
{
|
||||||
|
_valid = false;
|
||||||
|
// not necessary, but good hygine
|
||||||
|
vector<SGPropertyNode*>::iterator itr
|
||||||
|
= find(_watched.begin(), _watched.end(), node);
|
||||||
|
if (itr != _watched.end())
|
||||||
|
*itr = 0;
|
||||||
|
MultiChangeListener::unregister_property(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicChangeListener::fireChangeListeners()
|
||||||
|
{
|
||||||
|
vector<SGSharedPtr<AtomicChangeListener> >& listeners
|
||||||
|
= ListenerListSingleton::instance()->listeners;
|
||||||
|
for (vector<SGSharedPtr<AtomicChangeListener> >::iterator itr = listeners.begin(),
|
||||||
|
end = listeners.end();
|
||||||
|
itr != end;
|
||||||
|
++itr) {
|
||||||
|
(*itr)->valuesChanged();
|
||||||
|
(*itr)->_dirty = false;
|
||||||
|
}
|
||||||
|
listeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicChangeListener::valueChangedImplementation()
|
||||||
|
{
|
||||||
|
if (!_dirty) {
|
||||||
|
_dirty = true;
|
||||||
|
if (_valid)
|
||||||
|
ListenerListSingleton::instance()->listeners.push_back(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicChangeListener::valuesChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
105
simgear/props/AtomicChangeListener.hxx
Normal file
105
simgear/props/AtomicChangeListener.hxx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
|
||||||
|
#define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include <simgear/structure/Singleton.hxx>
|
||||||
|
|
||||||
|
#include "props.hxx"
|
||||||
|
#include "ExtendedPropertyAdapter.hxx"
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
// Performs an action when one of several nodes changes
|
||||||
|
class MultiChangeListener : private SGPropertyChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MultiChangeListener();
|
||||||
|
template<typename Pitr>
|
||||||
|
void listenToProperties(Pitr propsBegin, Pitr propsEnd)
|
||||||
|
{
|
||||||
|
for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
|
||||||
|
(*itr)->addChangeListener(this);
|
||||||
|
}
|
||||||
|
void valueChanged();
|
||||||
|
using SGPropertyChangeListener::unregister_property;
|
||||||
|
private:
|
||||||
|
virtual void valueChangedImplementation();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class AtomicChangeListener : public MultiChangeListener,
|
||||||
|
public virtual SGReferenced
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
|
||||||
|
/**
|
||||||
|
* Lookup / create child nodes from their relative names.
|
||||||
|
*/
|
||||||
|
template<typename Itr>
|
||||||
|
AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||||
|
Itr childNamesEnd)
|
||||||
|
: _dirty(false), _valid(true)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
for (Itr itr = childNamesBegin, end = childNamesEnd;
|
||||||
|
itr != end;
|
||||||
|
++itr)
|
||||||
|
_watched.push_back(makeNode(parent, *itr));
|
||||||
|
listenToProperties(_watched.begin(), _watched.end());
|
||||||
|
}
|
||||||
|
bool isDirty() { return _dirty; }
|
||||||
|
bool isValid() { return _valid; }
|
||||||
|
void unregister_property(SGPropertyNode* node);
|
||||||
|
static void fireChangeListeners();
|
||||||
|
private:
|
||||||
|
virtual void valueChangedImplementation();
|
||||||
|
virtual void valuesChanged();
|
||||||
|
bool _dirty;
|
||||||
|
bool _valid;
|
||||||
|
struct ListenerListSingleton : public Singleton<ListenerListSingleton>
|
||||||
|
{
|
||||||
|
std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
std::vector<SGPropertyNode*> _watched;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Func>
|
||||||
|
class ExtendedPropListener : public AtomicChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
|
||||||
|
bool initial = false)
|
||||||
|
: AtomicChangeListener(nodes), _func(func)
|
||||||
|
{
|
||||||
|
if (initial)
|
||||||
|
valuesChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
template<typename Itr>
|
||||||
|
ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||||
|
Itr childNamesEnd, const Func& func,
|
||||||
|
bool initial = false)
|
||||||
|
: AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
|
||||||
|
_func(func)
|
||||||
|
{
|
||||||
|
if (initial)
|
||||||
|
valuesChanged();
|
||||||
|
}
|
||||||
|
virtual void valuesChanged()
|
||||||
|
{
|
||||||
|
ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
|
||||||
|
T val = adaptor();
|
||||||
|
_func(val);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Func _func;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
72
simgear/props/ExtendedPropertyAdapter.hxx
Normal file
72
simgear/props/ExtendedPropertyAdapter.hxx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX
|
||||||
|
#define SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX 1
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/structure/exception.hxx>
|
||||||
|
|
||||||
|
#include "props.hxx"
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace props
|
||||||
|
{
|
||||||
|
// This should be in simgear/math/SGVec.hxx and friends
|
||||||
|
|
||||||
|
template<typename T> struct NumComponents;
|
||||||
|
|
||||||
|
template<> struct NumComponents<SGVec3d>
|
||||||
|
{
|
||||||
|
enum { num_components = 3 };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct NumComponents<SGVec4d>
|
||||||
|
{
|
||||||
|
enum { num_components = 4 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename NodeContainer>
|
||||||
|
class ExtendedPropertyAdapter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { num_components = props::NumComponents<T>::num_components };
|
||||||
|
ExtendedPropertyAdapter(const NodeContainer& elements)
|
||||||
|
: _elements(elements)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
T operator()() const
|
||||||
|
{
|
||||||
|
T result;
|
||||||
|
if (_elements.size() < num_components)
|
||||||
|
throw sg_exception();
|
||||||
|
for (int i = 0; i < num_components; ++i)
|
||||||
|
result[i] = _elements[i]->getValue<double>();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void set(const T& val)
|
||||||
|
{
|
||||||
|
if (_elements.size() < num_components)
|
||||||
|
throw sg_exception();
|
||||||
|
for (int i = 0; i < num_components; ++i)
|
||||||
|
_elements[i]->setValue(val[i]);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const NodeContainer& _elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename InIterator, typename OutIterator>
|
||||||
|
inline void makeChildList(SGPropertyNode* prop, InIterator inBegin,
|
||||||
|
InIterator inEnd, OutIterator outBegin)
|
||||||
|
{
|
||||||
|
std::transform(inBegin, inEnd, outBegin,
|
||||||
|
boost::bind(static_cast<SGPropertyNode* (SGPropertyNode::*)(const char*, int, bool)>(&SGPropertyNode::getChild), prop, _1, 0, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
@ -5,12 +5,15 @@ lib_LIBRARIES = libsgprops.a
|
|||||||
include_HEADERS = \
|
include_HEADERS = \
|
||||||
condition.hxx \
|
condition.hxx \
|
||||||
props.hxx \
|
props.hxx \
|
||||||
props_io.hxx
|
props_io.hxx \
|
||||||
|
AtomicChangeListener.hxx \
|
||||||
|
ExtendedPropertyAdapter.hxx
|
||||||
|
|
||||||
libsgprops_a_SOURCES = \
|
libsgprops_a_SOURCES = \
|
||||||
condition.cxx \
|
condition.cxx \
|
||||||
props.cxx \
|
props.cxx \
|
||||||
props_io.cxx
|
props_io.cxx \
|
||||||
|
AtomicChangeListener.cxx
|
||||||
|
|
||||||
noinst_PROGRAMS = props_test
|
noinst_PROGRAMS = props_test
|
||||||
|
|
||||||
|
@ -1927,13 +1927,26 @@ inline bool SGPropertyNode::setValue(const T& val,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function for creation of a child property node
|
* Utility function for creation of a child property node.
|
||||||
*/
|
*/
|
||||||
inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
|
inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
|
||||||
int index = 0)
|
int index = 0)
|
||||||
{
|
{
|
||||||
return parent->getChild(name, index, true);
|
return parent->getChild(name, index, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function for creation of a child property node using a
|
||||||
|
* relative path.
|
||||||
|
*/
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
template<typename StringType>
|
||||||
|
inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
|
||||||
|
{
|
||||||
|
return parent->getNode(name, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // __PROPS_HXX
|
#endif // __PROPS_HXX
|
||||||
|
|
||||||
// end of props.hxx
|
// end of props.hxx
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "Effect.hxx"
|
#include "Effect.hxx"
|
||||||
#include "EffectBuilder.hxx"
|
#include "EffectBuilder.hxx"
|
||||||
|
#include "EffectGeode.hxx"
|
||||||
#include "Technique.hxx"
|
#include "Technique.hxx"
|
||||||
#include "Pass.hxx"
|
#include "Pass.hxx"
|
||||||
#include "TextureBuilder.hxx"
|
#include "TextureBuilder.hxx"
|
||||||
@ -856,6 +857,8 @@ bool makeParametersFromStateSet(SGPropertyNode* effectRoot, const StateSet* ss)
|
|||||||
} else {
|
} else {
|
||||||
makeChild(blendNode, "active")->setValue(false);
|
makeChild(blendNode, "active")->setValue(false);
|
||||||
}
|
}
|
||||||
|
string renderingHint = findName(renderingHints, ss->getRenderingHint());
|
||||||
|
makeChild(paramRoot, "rendering-hint")->setStringValue(renderingHint);
|
||||||
makeTextureParameters(paramRoot, ss);
|
makeTextureParameters(paramRoot, ss);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -872,6 +875,26 @@ bool Effect::realizeTechniques(const osgDB::ReaderWriter::Options* options)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
EffectGeode* eg = dynamic_cast<EffectGeode*>(node);
|
||||||
|
if (!eg)
|
||||||
|
return;
|
||||||
|
Effect* effect = eg->getEffect();
|
||||||
|
if (!effect)
|
||||||
|
return;
|
||||||
|
SGPropertyNode* root = getPropertyRoot();
|
||||||
|
for (vector<SGSharedPtr<Updater> >::iterator itr = effect->_extraData.begin(),
|
||||||
|
end = effect->_extraData.end();
|
||||||
|
itr != end;
|
||||||
|
++itr) {
|
||||||
|
InitializeWhenAdded* adder
|
||||||
|
= dynamic_cast<InitializeWhenAdded*>(itr->ptr());
|
||||||
|
if (adder)
|
||||||
|
adder->initOnAdd(effect, root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Effect_writeLocalData(const Object& obj, osgDB::Output& fw)
|
bool Effect_writeLocalData(const Object& obj, osgDB::Output& fw)
|
||||||
{
|
{
|
||||||
const Effect& effect = static_cast<const Effect&>(obj);
|
const Effect& effect = static_cast<const Effect&>(obj);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <osgDB/ReaderWriter>
|
#include <osgDB/ReaderWriter>
|
||||||
|
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/scene/util/UpdateOnceCallback.hxx>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
@ -40,6 +41,32 @@ class CullVisitor;
|
|||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
class Technique;
|
class Technique;
|
||||||
|
class Effect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object to be initialized at some point after an effect -- and its
|
||||||
|
* containing effect geode -- are hooked into the scene graph. Some
|
||||||
|
* things, like manipulations of the global property tree, are are
|
||||||
|
* only safe in the update process.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class InitializeWhenAdded
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InitializeWhenAdded() : _initialized(false) {};
|
||||||
|
virtual ~InitializeWhenAdded() {};
|
||||||
|
void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
|
||||||
|
{
|
||||||
|
if (!_initialized) {
|
||||||
|
initOnAddImpl(effect, propRoot);
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool getInitialized() const { return _initialized; }
|
||||||
|
private:
|
||||||
|
virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
|
||||||
|
bool _initialized;
|
||||||
|
};
|
||||||
|
|
||||||
class Effect : public osg::Object
|
class Effect : public osg::Object
|
||||||
{
|
{
|
||||||
@ -56,12 +83,30 @@ public:
|
|||||||
Technique* chooseTechnique(osg::RenderInfo* renderInfo);
|
Technique* chooseTechnique(osg::RenderInfo* renderInfo);
|
||||||
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
||||||
virtual void releaseGLObjects(osg::State* state = 0) const;
|
virtual void releaseGLObjects(osg::State* state = 0) const;
|
||||||
/*
|
/**
|
||||||
* Build the techniques from the effect properties.
|
* Build the techniques from the effect properties.
|
||||||
*/
|
*/
|
||||||
bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
|
bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
|
||||||
|
/**
|
||||||
|
* Updaters that should be derefed when the effect is
|
||||||
|
* deleted. Updaters arrange to be run by listening on properties
|
||||||
|
* or something.
|
||||||
|
*/
|
||||||
|
struct Updater : public virtual SGReferenced
|
||||||
|
{
|
||||||
|
virtual ~Updater() {}
|
||||||
|
};
|
||||||
|
void addUpdater(Updater* data) { _extraData.push_back(data); }
|
||||||
|
// Callback that is added to the effect geode to initialize the
|
||||||
|
// effect.
|
||||||
|
friend struct InitializeCallback;
|
||||||
|
struct InitializeCallback : public UpdateOnceCallback
|
||||||
|
{
|
||||||
|
void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
std::vector<SGSharedPtr<Updater> > _extraData;
|
||||||
~Effect();
|
~Effect();
|
||||||
};
|
};
|
||||||
Effect* makeEffect(const std::string& name,
|
Effect* makeEffect(const std::string& name,
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
# include <simgear_config.h>
|
# include <simgear_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/scene/tgdb/userdata.hxx>
|
||||||
|
|
||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
#include "EffectBuilder.hxx"
|
#include "EffectBuilder.hxx"
|
||||||
@ -39,6 +41,16 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
|
|||||||
return getEffectPropertyNode(effect, child);
|
return getEffectPropertyNode(effect, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string getGlobalProperty(const SGPropertyNode* prop)
|
||||||
|
{
|
||||||
|
if (!prop)
|
||||||
|
return string();
|
||||||
|
const SGPropertyNode* useProp = prop->getChild("use");
|
||||||
|
if (!useProp)
|
||||||
|
return string();
|
||||||
|
return useProp->getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
BuilderException::BuilderException()
|
BuilderException::BuilderException()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -66,4 +78,8 @@ bool isAttributeActive(Effect* effect, const SGPropertyNode* prop)
|
|||||||
return !activeProp || activeProp->getValue<bool>();
|
return !activeProp || activeProp->getValue<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace effect
|
||||||
|
{
|
||||||
|
const char* colorFields[] = {"red", "green", "blue", "alpha"};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,21 +18,26 @@
|
|||||||
#define SIMGEAR_EFFECTBUILDER_HXX 1
|
#define SIMGEAR_EFFECTBUILDER_HXX 1
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <osgDB/Registry>
|
#include <osgDB/Registry>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
#include <boost/multi_index_container.hpp>
|
#include <boost/multi_index_container.hpp>
|
||||||
#include <boost/multi_index/member.hpp>
|
#include <boost/multi_index/member.hpp>
|
||||||
#include <boost/multi_index/ordered_index.hpp>
|
#include <boost/multi_index/ordered_index.hpp>
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/props/AtomicChangeListener.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/structure/Singleton.hxx>
|
#include <simgear/structure/Singleton.hxx>
|
||||||
|
|
||||||
|
#include "Effect.hxx"
|
||||||
/**
|
/**
|
||||||
* Support classes for parsing effects.
|
* Support classes for parsing effects.
|
||||||
*/
|
*/
|
||||||
@ -153,15 +158,10 @@ EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||||
const SGPropertyNode* prop,
|
const char* name,
|
||||||
T& result)
|
T& result)
|
||||||
{
|
{
|
||||||
using namespace effect;
|
using namespace effect;
|
||||||
if (!prop)
|
|
||||||
return false;
|
|
||||||
const char* name = prop->getStringValue();
|
|
||||||
if (!name)
|
|
||||||
return false;
|
|
||||||
typename EffectPropertyMap<T>::BMap::iterator itr
|
typename EffectPropertyMap<T>::BMap::iterator itr
|
||||||
= pMap._map.get<from>().find(name);
|
= pMap._map.get<from>().find(name);
|
||||||
if (itr == pMap._map.end()) {
|
if (itr == pMap._map.end()) {
|
||||||
@ -172,6 +172,27 @@ bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||||
|
const std::string& name,
|
||||||
|
T& result)
|
||||||
|
{
|
||||||
|
return findAttr(pMap, name.c_str(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||||
|
const SGPropertyNode* prop,
|
||||||
|
T& result)
|
||||||
|
{
|
||||||
|
if (!prop)
|
||||||
|
return false;
|
||||||
|
const char* name = prop->getStringValue();
|
||||||
|
if (!name)
|
||||||
|
return false;
|
||||||
|
return findAttr(pMap, name, result);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
|
std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
|
||||||
{
|
{
|
||||||
@ -205,6 +226,14 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
|
|||||||
const SGPropertyNode* prop,
|
const SGPropertyNode* prop,
|
||||||
const char* name);
|
const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of a node mentioned in a <use> clause from the global property
|
||||||
|
* tree.
|
||||||
|
* @return empty if prop doesn't contain a <use> clause; otherwise the
|
||||||
|
* mentioned node name.
|
||||||
|
*/
|
||||||
|
std::string getGlobalProperty(const SGPropertyNode* prop);
|
||||||
|
|
||||||
class BuilderException : public sg_exception
|
class BuilderException : public sg_exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -257,5 +286,190 @@ struct InstallAttributeBuilder
|
|||||||
// false, the OSG attribute is not built at all. This is different
|
// false, the OSG attribute is not built at all. This is different
|
||||||
// from any OSG mode settings that might be around.
|
// from any OSG mode settings that might be around.
|
||||||
bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
|
bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
|
||||||
|
|
||||||
|
namespace effect
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bridge between types stored in properties and what OSG wants.
|
||||||
|
*/
|
||||||
|
template<typename T> struct OSGBridge;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct OSGBridge<const T> : public OSGBridge<T>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct OSGBridge<osg::Vec3f>
|
||||||
|
{
|
||||||
|
typedef SGVec3d sg_type;
|
||||||
|
static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct OSGBridge<osg::Vec3d>
|
||||||
|
{
|
||||||
|
typedef SGVec3d sg_type;
|
||||||
|
static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct OSGBridge<osg::Vec4f>
|
||||||
|
{
|
||||||
|
typedef SGVec4d sg_type;
|
||||||
|
static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct OSGBridge<osg::Vec4d>
|
||||||
|
{
|
||||||
|
typedef SGVec4d sg_type;
|
||||||
|
static osg::Vec4d getOsgType(const SGVec4d& val) { return toOsg(val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Obj, typename OSGParam>
|
||||||
|
struct OSGFunctor : public OSGBridge<OSGParam>
|
||||||
|
{
|
||||||
|
OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
|
||||||
|
: _obj(obj), _func(func) {}
|
||||||
|
void operator()(const typename OSGBridge<OSGParam>::sg_type& val) const
|
||||||
|
{
|
||||||
|
((_obj.get())->*_func)(this->getOsgType(val));
|
||||||
|
}
|
||||||
|
osg::ref_ptr<Obj>_obj;
|
||||||
|
void (Obj::*_func)(const OSGParam&);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ObjType, typename OSGParamType>
|
||||||
|
class ScalarChangeListener
|
||||||
|
: public SGPropertyChangeListener, public InitializeWhenAdded,
|
||||||
|
public Effect::Updater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void (ObjType::*setter_type)(const OSGParamType);
|
||||||
|
ScalarChangeListener(ObjType* obj, setter_type setter,
|
||||||
|
const std::string& propName)
|
||||||
|
: _obj(obj), _setter(setter)
|
||||||
|
{
|
||||||
|
_propName = new std::string(propName);
|
||||||
|
}
|
||||||
|
virtual ~ScalarChangeListener()
|
||||||
|
{
|
||||||
|
delete _propName;
|
||||||
|
_propName = 0;
|
||||||
|
}
|
||||||
|
void valueChanged(SGPropertyNode* node)
|
||||||
|
{
|
||||||
|
_obj->*setter(node->getValue<OSGParamType>());
|
||||||
|
}
|
||||||
|
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
|
||||||
|
{
|
||||||
|
SGPropertyNode* listenProp = makeNode(propRoot, *_propName);
|
||||||
|
delete _propName;
|
||||||
|
_propName = 0;
|
||||||
|
if (listenProp)
|
||||||
|
listenProp->addChangeListener(this, true);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<ObjType> _obj;
|
||||||
|
setter_type _setter;
|
||||||
|
std::string* _propName;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Func>
|
||||||
|
class EffectExtendedPropListener : public InitializeWhenAdded,
|
||||||
|
public Effect::Updater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename Itr>
|
||||||
|
EffectExtendedPropListener(const Func& func,
|
||||||
|
const std::string& propName, Itr childNamesBegin,
|
||||||
|
Itr childNamesEnd)
|
||||||
|
: _func(func)
|
||||||
|
{
|
||||||
|
_propName = new std::string(propName);
|
||||||
|
_childNames = new std::vector<std::string>(childNamesBegin,
|
||||||
|
childNamesEnd);
|
||||||
|
}
|
||||||
|
virtual ~EffectExtendedPropListener()
|
||||||
|
{
|
||||||
|
delete _propName;
|
||||||
|
delete _childNames;
|
||||||
|
}
|
||||||
|
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
|
||||||
|
{
|
||||||
|
SGPropertyNode* parent = propRoot->getNode(*_propName, true);
|
||||||
|
_propListener
|
||||||
|
= new ExtendedPropListener<T, Func>(parent, _childNames->begin(),
|
||||||
|
_childNames->end(),
|
||||||
|
_func, true);
|
||||||
|
delete _propName;
|
||||||
|
_propName = 0;
|
||||||
|
delete _childNames;
|
||||||
|
_childNames = 0;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string* _propName;
|
||||||
|
std::vector<std::string>* _childNames;
|
||||||
|
SGSharedPtr<ExtendedPropListener<T, Func> > _propListener;
|
||||||
|
Func _func;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the value and the possible updating of an effect
|
||||||
|
* attribute. If the value is specified directly, set it. Otherwise,
|
||||||
|
* use the <use> tag to look at the parameters. Again, if there is a
|
||||||
|
* value there set it directly. Otherwise, the parameter contains its
|
||||||
|
* own <use> tag referring to a property in the global property tree;
|
||||||
|
* install a change listener that will set the attribute when the
|
||||||
|
* property changes.
|
||||||
|
*/
|
||||||
|
template<typename ObjType, typename OSGParamType>
|
||||||
|
void
|
||||||
|
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
|
||||||
|
void (ObjType::*setter)(const OSGParamType))
|
||||||
|
{
|
||||||
|
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
|
||||||
|
if (!valProp)
|
||||||
|
return;
|
||||||
|
if (valProp->nChildren() == 0) {
|
||||||
|
obj->*setter(valProp->getValue<OSGParamType>());
|
||||||
|
} else {
|
||||||
|
std::string propName = getGlobalProperty(prop);
|
||||||
|
ScalarChangeListener<ObjType, OSGParamType>* listener
|
||||||
|
= new ScalarChangeListener<ObjType, OSGParamType>(obj, setter,
|
||||||
|
propName);
|
||||||
|
effect->addUpdater(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ObjType, typename OSGParamType, typename NameItrType>
|
||||||
|
void
|
||||||
|
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
|
||||||
|
void (ObjType::*setter)(const OSGParamType&),
|
||||||
|
NameItrType nameItr)
|
||||||
|
{
|
||||||
|
typedef typename OSGBridge<OSGParamType>::sg_type sg_type;
|
||||||
|
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
|
||||||
|
if (!valProp)
|
||||||
|
return;
|
||||||
|
if (valProp->nChildren() == 0) {
|
||||||
|
(obj->*setter)(OSGBridge<OSGParamType>
|
||||||
|
::getOsgType(valProp->getValue<sg_type>()));
|
||||||
|
} else {
|
||||||
|
string listenPropName = getGlobalProperty(valProp);
|
||||||
|
if (listenPropName.empty())
|
||||||
|
return;
|
||||||
|
typedef OSGFunctor<ObjType, OSGParamType> Functor;
|
||||||
|
Effect::Updater* listener
|
||||||
|
= new EffectExtendedPropListener<sg_type, Functor>
|
||||||
|
(Functor(obj, setter), listenPropName, nameItr,
|
||||||
|
nameItr + props::NumComponents<sg_type>::num_components);
|
||||||
|
effect->addUpdater(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char* colorFields[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,6 +44,14 @@ EffectGeode::EffectGeode(const EffectGeode& rhs, const osg::CopyOp& copyop) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectGeode::setEffect(Effect* effect)
|
||||||
|
{
|
||||||
|
_effect = effect;
|
||||||
|
if (!_effect)
|
||||||
|
return;
|
||||||
|
addUpdateCallback(new Effect::InitializeCallback);
|
||||||
|
}
|
||||||
|
|
||||||
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
|
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
|
||||||
{
|
{
|
||||||
if (_effect.valid())
|
if (_effect.valid())
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||||
META_Node(simgear,EffectGeode);
|
META_Node(simgear,EffectGeode);
|
||||||
Effect* getEffect() const { return _effect.get(); }
|
Effect* getEffect() const { return _effect.get(); }
|
||||||
void setEffect(Effect* effect) { _effect = effect; }
|
void setEffect(Effect* effect);
|
||||||
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
||||||
virtual void releaseGLObjects(osg::State* = 0) const;
|
virtual void releaseGLObjects(osg::State* = 0) const;
|
||||||
typedef DrawableList::iterator DrawablesIterator;
|
typedef DrawableList::iterator DrawablesIterator;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <osg/TexEnv>
|
#include <osg/TexEnv>
|
||||||
#include <osg/TexEnvCombine>
|
#include <osg/TexEnvCombine>
|
||||||
|
#include <osg/TexGen>
|
||||||
#include <osg/Texture1D>
|
#include <osg/Texture1D>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/Texture3D>
|
#include <osg/Texture3D>
|
||||||
@ -48,6 +49,10 @@ using namespace osg;
|
|||||||
|
|
||||||
using namespace effect;
|
using namespace effect;
|
||||||
|
|
||||||
|
TexEnvCombine* buildTexEnvCombine(Effect* effect,
|
||||||
|
const SGPropertyNode* envProp);
|
||||||
|
TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
|
||||||
|
|
||||||
// Hack to force inclusion of TextureBuilder.cxx in library
|
// Hack to force inclusion of TextureBuilder.cxx in library
|
||||||
osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
|
osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
|
||||||
const SGPropertyNode*props,
|
const SGPropertyNode*props,
|
||||||
@ -134,6 +139,14 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
|
|||||||
if (env)
|
if (env)
|
||||||
pass->setTextureAttributeAndModes(unit, env);
|
pass->setTextureAttributeAndModes(unit, env);
|
||||||
}
|
}
|
||||||
|
const SGPropertyNode* combineProp = prop->getChild("texenv-combine");
|
||||||
|
TexEnvCombine* combiner = 0;
|
||||||
|
if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp))))
|
||||||
|
pass->setTextureAttributeAndModes(unit, combiner);
|
||||||
|
const SGPropertyNode* tgenProp = prop->getChild("texgen");
|
||||||
|
TexGen* tgen = 0;
|
||||||
|
if (tgenProp && (tgen = buildTexGen(effect, tgenProp)))
|
||||||
|
pass->setTextureAttributeAndModes(unit, tgen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallAttributeBuilder call is in Effect.cxx to force this file to
|
// InstallAttributeBuilder call is in Effect.cxx to force this file to
|
||||||
@ -366,6 +379,197 @@ namespace
|
|||||||
TextureBuilder::Registrar installNoise("noise", new NoiseBuilder);
|
TextureBuilder::Registrar installNoise("noise", new NoiseBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EffectNameValue<TexEnvCombine::CombineParam> combineParamInit[] =
|
||||||
|
{
|
||||||
|
{"replace", TexEnvCombine::REPLACE},
|
||||||
|
{"modulate", TexEnvCombine::MODULATE},
|
||||||
|
{"add", TexEnvCombine::ADD},
|
||||||
|
{"add-signed", TexEnvCombine::ADD_SIGNED},
|
||||||
|
{"interpolate", TexEnvCombine::INTERPOLATE},
|
||||||
|
{"subtract", TexEnvCombine::SUBTRACT},
|
||||||
|
{"dot3-rgb", TexEnvCombine::DOT3_RGB},
|
||||||
|
{"dot3-rgba", TexEnvCombine::DOT3_RGBA}
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectPropertyMap<TexEnvCombine::CombineParam> combineParams(combineParamInit);
|
||||||
|
|
||||||
|
EffectNameValue<TexEnvCombine::SourceParam> sourceParamInit[] =
|
||||||
|
{
|
||||||
|
{"constant", TexEnvCombine::CONSTANT},
|
||||||
|
{"primary_color", TexEnvCombine::PRIMARY_COLOR},
|
||||||
|
{"previous", TexEnvCombine::PREVIOUS},
|
||||||
|
{"texture", TexEnvCombine::TEXTURE},
|
||||||
|
{"texture0", TexEnvCombine::TEXTURE0},
|
||||||
|
{"texture1", TexEnvCombine::TEXTURE1},
|
||||||
|
{"texture2", TexEnvCombine::TEXTURE2},
|
||||||
|
{"texture3", TexEnvCombine::TEXTURE3},
|
||||||
|
{"texture4", TexEnvCombine::TEXTURE4},
|
||||||
|
{"texture5", TexEnvCombine::TEXTURE5},
|
||||||
|
{"texture6", TexEnvCombine::TEXTURE6},
|
||||||
|
{"texture7", TexEnvCombine::TEXTURE7}
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectPropertyMap<TexEnvCombine::SourceParam> sourceParams(sourceParamInit);
|
||||||
|
|
||||||
|
EffectNameValue<TexEnvCombine::OperandParam> opParamInit[] =
|
||||||
|
{
|
||||||
|
{"src_color", TexEnvCombine::SRC_COLOR},
|
||||||
|
{"one_minus_src_color", TexEnvCombine::ONE_MINUS_SRC_COLOR},
|
||||||
|
{"src_alpha", TexEnvCombine::SRC_ALPHA},
|
||||||
|
{"one_minus_src_alpha", TexEnvCombine::ONE_MINUS_SRC_ALPHA}
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
|
||||||
|
|
||||||
|
TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
|
||||||
|
{
|
||||||
|
if (!isAttributeActive(effect, envProp))
|
||||||
|
return 0;
|
||||||
|
TexEnvCombine* result = new TexEnvCombine;
|
||||||
|
const SGPropertyNode* p = 0;
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "combine-rgb"))) {
|
||||||
|
TexEnvCombine::CombineParam crgb = TexEnvCombine::MODULATE;
|
||||||
|
findAttr(combineParams, p, crgb);
|
||||||
|
result->setCombine_RGB(crgb);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "combine-alpha"))) {
|
||||||
|
TexEnvCombine::CombineParam calpha = TexEnvCombine::MODULATE;
|
||||||
|
findAttr(combineParams, p, calpha);
|
||||||
|
result->setCombine_RGB(calpha);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source0-rgb"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource0_RGB(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source1-rgb"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource1_RGB(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source2-rgb"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource2_RGB(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source0-alpha"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource0_Alpha(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source1-alpha"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource1_Alpha(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "source2-alpha"))) {
|
||||||
|
TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT;
|
||||||
|
findAttr(sourceParams, p, source);
|
||||||
|
result->setSource2_Alpha(source);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand0-rgb"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand0_RGB(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand1-rgb"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand1_RGB(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand2-rgb"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand2_RGB(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand0-alpha"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand0_Alpha(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand1-alpha"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand1_Alpha(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "operand2-alpha"))) {
|
||||||
|
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||||
|
findAttr(operandParams, p, op);
|
||||||
|
result->setOperand2_Alpha(op);
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "scale-rgb"))) {
|
||||||
|
result->setScale_RGB(p->getValue<float>());
|
||||||
|
}
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "scale-alpha"))) {
|
||||||
|
result->setScale_Alpha(p->getValue<float>());
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if ((p = getEffectPropertyChild(effect, envProp, "constant-color"))) {
|
||||||
|
SGVec4d color = p->getValue<SGVec4d>();
|
||||||
|
result->setConstantColor(toOsg(color));
|
||||||
|
} else if ((p = getEffectPropertyChild(effect, envProp,
|
||||||
|
"light-direction"))) {
|
||||||
|
SGVec3d direction = p->getValue<SGVec3d>();
|
||||||
|
result->setConstantColorAsLightDirection(toOsg(direction));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
const SGPropertyNode* colorNode = envProp->getChild("constant-color");
|
||||||
|
if (colorNode)
|
||||||
|
initFromParameters(effect, colorNode, result,
|
||||||
|
&TexEnvCombine::setConstantColor, colorFields);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectNameValue<TexGen::Mode> tgenModeInit[] =
|
||||||
|
{
|
||||||
|
{ "object-linear", TexGen::OBJECT_LINEAR},
|
||||||
|
{ "eye-linear", TexGen::EYE_LINEAR},
|
||||||
|
{ "sphere-map", TexGen::SPHERE_MAP},
|
||||||
|
{ "normal-map", TexGen::NORMAL_MAP},
|
||||||
|
{ "reflection-map", TexGen::REFLECTION_MAP}
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectPropertyMap<TexGen::Mode> tgenModes(tgenModeInit);
|
||||||
|
|
||||||
|
EffectNameValue<TexGen::Coord> tgenCoordInit[] =
|
||||||
|
{
|
||||||
|
{"s", TexGen::S},
|
||||||
|
{"t", TexGen::T},
|
||||||
|
{"r", TexGen::R},
|
||||||
|
{"q", TexGen::Q}
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectPropertyMap<TexGen::Coord> tgenCoords(tgenCoordInit);
|
||||||
|
|
||||||
|
TexGen* buildTexGen(Effect* effect, const SGPropertyNode* tgenProp)
|
||||||
|
{
|
||||||
|
if (!isAttributeActive(effect, tgenProp))
|
||||||
|
return 0;
|
||||||
|
TexGen* result = new TexGen;
|
||||||
|
const SGPropertyNode* p = 0;
|
||||||
|
TexGen::Mode mode = TexGen::OBJECT_LINEAR;
|
||||||
|
if (findAttr(tgenModes, getEffectPropertyChild(effect, tgenProp, "mode"),
|
||||||
|
mode))
|
||||||
|
result->setMode(mode);
|
||||||
|
const SGPropertyNode* planesNode = tgenProp->getChild("planes");
|
||||||
|
if (planesNode) {
|
||||||
|
for (int i = 0; i < planesNode->nChildren(); ++i) {
|
||||||
|
const SGPropertyNode* planeNode = planesNode->getChild(i);
|
||||||
|
TexGen::Coord coord;
|
||||||
|
if (!findAttr(tgenCoords, planeNode->getName(), coord)) {
|
||||||
|
SG_LOG(SG_INPUT, SG_ALERT, "Unknown TexGen plane "
|
||||||
|
<< planeNode->getName());
|
||||||
|
} else {
|
||||||
|
const SGPropertyNode* realNode
|
||||||
|
= getEffectPropertyNode(effect, planeNode);
|
||||||
|
SGVec4d plane = realNode->getValue<SGVec4d>();
|
||||||
|
result->setPlane(coord, toOsg(plane));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss)
|
bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss)
|
||||||
{
|
{
|
||||||
SGPropertyNode* texUnit = makeChild(paramRoot, "texture");
|
SGPropertyNode* texUnit = makeChild(paramRoot, "texture");
|
||||||
|
@ -170,7 +170,7 @@ Effect* makeEffect(SGPropertyNode* prop,
|
|||||||
const SGPropertyNode* inheritProp = prop->getChild("inherits-from");
|
const SGPropertyNode* inheritProp = prop->getChild("inherits-from");
|
||||||
Effect* parent = 0;
|
Effect* parent = 0;
|
||||||
if (inheritProp) {
|
if (inheritProp) {
|
||||||
parent = makeEffect(inheritProp->getStringValue(), realizeTechniques,
|
parent = makeEffect(inheritProp->getStringValue(), false,
|
||||||
options);
|
options);
|
||||||
if(parent)
|
if(parent)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
# include <simgear_config.h>
|
# include <simgear_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
//yuck
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
#include <osgDB/WriteFile>
|
#include <osgDB/WriteFile>
|
||||||
@ -132,6 +138,45 @@ public:
|
|||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Referenced> mReferenced;
|
osg::ref_ptr<osg::Referenced> mReferenced;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void makeEffectAnimations(PropertyList& animation_nodes,
|
||||||
|
PropertyList& effect_nodes)
|
||||||
|
{
|
||||||
|
for (PropertyList::iterator itr = animation_nodes.begin();
|
||||||
|
itr != animation_nodes.end();
|
||||||
|
++itr) {
|
||||||
|
SGPropertyNode* animProp = itr->ptr();
|
||||||
|
SGPropertyNode* typeProp = animProp->getChild("type");
|
||||||
|
if (!typeProp || strcmp(typeProp->getStringValue(), "shader"))
|
||||||
|
continue;
|
||||||
|
SGPropertyNode* shaderProp = animProp->getChild("shader");
|
||||||
|
if (!shaderProp || strcmp(shaderProp->getStringValue(), "chrome"))
|
||||||
|
continue;
|
||||||
|
*itr = 0;
|
||||||
|
SGPropertyNode* textureProp = animProp->getChild("texture");
|
||||||
|
if (!textureProp)
|
||||||
|
continue;
|
||||||
|
SGPropertyNode_ptr effectProp = new SGPropertyNode();
|
||||||
|
makeChild(effectProp.ptr(), "inherits-from")
|
||||||
|
->setValue("Effects/chrome");
|
||||||
|
SGPropertyNode* paramsProp = makeChild(effectProp.get(), "parameters");
|
||||||
|
makeChild(paramsProp, "chrome-texture")
|
||||||
|
->setValue(textureProp->getStringValue());
|
||||||
|
PropertyList objectNameNodes = animProp->getChildren("object-name");
|
||||||
|
for (PropertyList::iterator objItr = objectNameNodes.begin(),
|
||||||
|
end = objectNameNodes.end();
|
||||||
|
objItr != end;
|
||||||
|
++objItr)
|
||||||
|
effectProp->addChild("object-name")
|
||||||
|
->setStringValue((*objItr)->getStringValue());
|
||||||
|
effect_nodes.push_back(effectProp);
|
||||||
|
}
|
||||||
|
animation_nodes.erase(remove_if(animation_nodes.begin(),
|
||||||
|
animation_nodes.end(),
|
||||||
|
!boost::bind(&SGPropertyNode_ptr::valid,
|
||||||
|
_1)),
|
||||||
|
animation_nodes.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static osg::Node *
|
static osg::Node *
|
||||||
@ -368,13 +413,14 @@ sgLoad3DModel_internal(const string &path,
|
|||||||
options.get()));
|
options.get()));
|
||||||
}
|
}
|
||||||
PropertyList effect_nodes = props->getChildren("effect");
|
PropertyList effect_nodes = props->getChildren("effect");
|
||||||
|
PropertyList animation_nodes = props->getChildren("animation");
|
||||||
|
// Some material animations (eventually all) are actually effects.
|
||||||
|
makeEffectAnimations(animation_nodes, effect_nodes);
|
||||||
{
|
{
|
||||||
ref_ptr<Node> modelWithEffects
|
ref_ptr<Node> modelWithEffects
|
||||||
= instantiateEffects(group.get(), effect_nodes, options.get());
|
= instantiateEffects(group.get(), effect_nodes, options.get());
|
||||||
group = static_cast<Group*>(modelWithEffects.get());
|
group = static_cast<Group*>(modelWithEffects.get());
|
||||||
}
|
}
|
||||||
std::vector<SGPropertyNode_ptr> animation_nodes;
|
|
||||||
animation_nodes = props->getChildren("animation");
|
|
||||||
for (unsigned i = 0; i < animation_nodes.size(); ++i)
|
for (unsigned i = 0; i < animation_nodes.size(); ++i)
|
||||||
/// OSGFIXME: duh, why not only model?????
|
/// OSGFIXME: duh, why not only model?????
|
||||||
SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
|
SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
|
||||||
|
@ -212,7 +212,7 @@ public:
|
|||||||
: _options(options)
|
: _options(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual void apply(osg::Node& node);
|
virtual void apply(osg::Group& node);
|
||||||
virtual void apply(osg::Geode& geode);
|
virtual void apply(osg::Geode& geode);
|
||||||
EffectMap& getEffectMap() { return _effectMap; }
|
EffectMap& getEffectMap() { return _effectMap; }
|
||||||
const EffectMap& getEffectMap() const { return _effectMap; }
|
const EffectMap& getEffectMap() const { return _effectMap; }
|
||||||
@ -227,7 +227,7 @@ protected:
|
|||||||
osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
|
osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
|
||||||
};
|
};
|
||||||
|
|
||||||
void MakeEffectVisitor::apply(osg::Node& node)
|
void MakeEffectVisitor::apply(osg::Group& node)
|
||||||
{
|
{
|
||||||
SGPropertyNode_ptr savedEffectRoot;
|
SGPropertyNode_ptr savedEffectRoot;
|
||||||
const string& nodeName = node.getName();
|
const string& nodeName = node.getName();
|
||||||
|
@ -21,6 +21,7 @@ include_HEADERS = \
|
|||||||
RenderConstants.hxx \
|
RenderConstants.hxx \
|
||||||
SplicingVisitor.hxx \
|
SplicingVisitor.hxx \
|
||||||
StateAttributeFactory.hxx \
|
StateAttributeFactory.hxx \
|
||||||
|
UpdateOnceCallback.hxx \
|
||||||
VectorArrayAdapter.hxx
|
VectorArrayAdapter.hxx
|
||||||
|
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ libsgutil_a_SOURCES = \
|
|||||||
PrimitiveUtils.cxx \
|
PrimitiveUtils.cxx \
|
||||||
SplicingVisitor.cxx \
|
SplicingVisitor.cxx \
|
||||||
StateAttributeFactory.cxx \
|
StateAttributeFactory.cxx \
|
||||||
QuadTreeBuilder.cxx
|
QuadTreeBuilder.cxx \
|
||||||
|
UpdateOnceCallback.cxx
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)
|
INCLUDES = -I$(top_srcdir)
|
||||||
|
39
simgear/scene/util/UpdateOnceCallback.cxx
Normal file
39
simgear/scene/util/UpdateOnceCallback.cxx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// UpdateOnceCallback.hxx
|
||||||
|
//
|
||||||
|
// Copyright (C) 2009 Tim Moore timoore@redhat.com
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Library General Public
|
||||||
|
// License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
// Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "UpdateOnceCallback.hxx"
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
using namespace osg;
|
||||||
|
|
||||||
|
void UpdateOnceCallback::operator()(Node* node, NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
doUpdate(node, nv);
|
||||||
|
node->removeUpdateCallback(this);
|
||||||
|
// The callback could be deleted now.
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateOnceCallback::doUpdate(Node* node, NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
}
|
44
simgear/scene/util/UpdateOnceCallback.hxx
Normal file
44
simgear/scene/util/UpdateOnceCallback.hxx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// UpdateOnceCallback.hxx
|
||||||
|
//
|
||||||
|
// Copyright (C) 2009 Tim Moore timoore@redhat.com
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Library General Public
|
||||||
|
// License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
// Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef SIMGEAR_UPDATEONCECALLBACK_HXX
|
||||||
|
#define SIMGEAR_UPDATEONCECALLBACK_HXX 1
|
||||||
|
#include <osg/NodeCallback>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
class UpdateOnceCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpdateOnceCallback() {}
|
||||||
|
UpdateOnceCallback(const UpdateOnceCallback& nc, const osg::CopyOp& copyop)
|
||||||
|
: osg::NodeCallback(nc, copyop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
META_Object(simgear,UpdateOnceCallback);
|
||||||
|
|
||||||
|
virtual void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
/**
|
||||||
|
* Do not override; use doUpdate instead!
|
||||||
|
*/
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user