Updates to osgFX, from Marco Jez, to map Effect across to being derived
from osg::Group rather than from osg::Node.
This commit is contained in:
@@ -25,11 +25,11 @@ namespace osgFX
|
||||
{
|
||||
|
||||
/**
|
||||
This effect makes surfaces appear bumpy. The child node must use two textures,
|
||||
This effect makes surfaces appear bumpy. Children nodes must use two textures,
|
||||
one for diffuse color and one for the normal map (which can be created
|
||||
from a height map with tools like nVIDIA's normal map generator). Furthermore,
|
||||
tangent-space basis vectors must be created and assigned to each Geometry; this
|
||||
can be done quickly by calling BumpMapping::prepareChild(). Note that both
|
||||
can be done quickly by calling BumpMapping::prepareChildren(). Note that both
|
||||
diffuse and normal map textures must have corresponding UV maps defined in
|
||||
Geometry objects.
|
||||
This effect defines a preferred technique which uses ARB vertex & fragment
|
||||
@@ -46,11 +46,11 @@ namespace osgFX
|
||||
|
||||
"Bump Mapping",
|
||||
|
||||
"This effect makes surfaces appear bumpy. The child node must use two textures, "
|
||||
"This effect makes surfaces appear bumpy. Children nodes must use two textures, "
|
||||
"one for diffuse color and one for the normal map (which can be created "
|
||||
"from a height map with tools like nVIDIA's normal map generator). Furthermore, "
|
||||
"tangent-space basis vectors must be created and assigned to each Geometry; this "
|
||||
"can be done quickly by calling BumpMapping::prepareChild(). Note that both "
|
||||
"can be done quickly by calling BumpMapping::prepareChildren(). Note that both "
|
||||
"diffuse and normal map textures must have corresponding UV maps defined in "
|
||||
"Geometry objects.\n"
|
||||
"This effect defines a preferred technique which uses ARB vertex & fragment "
|
||||
@@ -79,22 +79,22 @@ namespace osgFX
|
||||
/** set the texture unit that contains normal map texture. Default is 0 */
|
||||
inline void setNormalMapTextureUnit(int n);
|
||||
|
||||
/** get the diffuse color texture that overrides the child's texture */
|
||||
/** get the diffuse color texture that overrides children's texture */
|
||||
inline osg::Texture2D *getOverrideDiffuseTexture();
|
||||
|
||||
/** get the const diffuse color texture that overrides the child's texture */
|
||||
/** get the const diffuse color texture that overrides children's texture */
|
||||
inline const osg::Texture2D *getOverrideDiffuseTexture() const;
|
||||
|
||||
/** set the diffuse color texture that overrides the child's texture */
|
||||
/** set the diffuse color texture that overrides children's texture */
|
||||
inline void setOverrideDiffuseTexture(osg::Texture2D *texture);
|
||||
|
||||
/** get the normal map texture that overrides the child's texture */
|
||||
/** get the normal map texture that overrides children's texture */
|
||||
inline osg::Texture2D *getOverrideNormalMapTexture();
|
||||
|
||||
/** get the const normal map texture that overrides the child's texture */
|
||||
/** get the const normal map texture that overrides children's texture */
|
||||
inline const osg::Texture2D *getOverrideNormalMapTexture() const;
|
||||
|
||||
/** set the normal map texture that overrides the child's texture */
|
||||
/** set the normal map texture that overrides children's texture */
|
||||
inline void setOverrideNormalMapTexture(osg::Texture2D *texture);
|
||||
|
||||
/**
|
||||
@@ -106,8 +106,8 @@ namespace osgFX
|
||||
/** prepare a Node for bump lighting, calling prepareGeometry() for each Geometry */
|
||||
void prepareNode(osg::Node *node);
|
||||
|
||||
/** prepare the current child for bump lighting. Actually calls prepareNode(getChild()) */
|
||||
void prepareChild();
|
||||
/** prepare children for bump lighting. Actually calls prepareNode() for each child */
|
||||
void prepareChildren();
|
||||
|
||||
/** set up a demo environment with predefined diffuse and normal maps, as well as texture coordinates */
|
||||
void setUpDemo();
|
||||
|
||||
@@ -52,10 +52,9 @@ namespace osgFX
|
||||
selected either manually, with selectTechnique(), or automatically, in which
|
||||
case the first technique that is supported by all active rendering contexts
|
||||
is chosen.
|
||||
If you are an Effect user, then simply use it as a single-child group.
|
||||
Create an instance of your desired effect, add it to your scene graph (it
|
||||
is a Node) and call its setChild() method to set its child node as you
|
||||
would do with a Group.
|
||||
If you are an Effect user, then simply use it as a node group. Create an
|
||||
instance of your desired effect, add it to your scene graph and call its
|
||||
addChild() method to add a child node as you would do with a Group.
|
||||
If you are an Effect developer, you will have to implement the method
|
||||
define_techniques() to define the different techniques that can be used
|
||||
for obtaining the desired effect. In define_techniques() you will usually
|
||||
@@ -64,7 +63,7 @@ namespace osgFX
|
||||
techniques added first will have higher priority and will be used first as
|
||||
soon as all rendering contexts support it.
|
||||
*/
|
||||
class OSGFX_EXPORT Effect: public osg::Node {
|
||||
class OSGFX_EXPORT Effect: public osg::Group {
|
||||
public:
|
||||
Effect();
|
||||
Effect(const Effect ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY);
|
||||
@@ -95,15 +94,6 @@ namespace osgFX
|
||||
*/
|
||||
inline virtual void setUpDemo() {}
|
||||
|
||||
/** get the const child node */
|
||||
inline const osg::Node *getChild() const;
|
||||
|
||||
/** get the child node */
|
||||
inline osg::Node *getChild();
|
||||
|
||||
/** set the child node */
|
||||
inline void setChild(osg::Node *child);
|
||||
|
||||
/** get the number of techniques defined for this effect */
|
||||
inline int getNumTechniques() const;
|
||||
|
||||
@@ -123,14 +113,16 @@ namespace osgFX
|
||||
/** select a technique or enable automatic detection */
|
||||
inline void selectTechnique(int i = AUTO_DETECT);
|
||||
|
||||
virtual void traverse(osg::NodeVisitor &nv);
|
||||
/** custom traversal */
|
||||
virtual void traverse(osg::NodeVisitor &nv);
|
||||
|
||||
/** default traversal */
|
||||
inline void inherited_traverse(osg::NodeVisitor &nv);
|
||||
|
||||
protected:
|
||||
virtual ~Effect() {}
|
||||
virtual ~Effect();
|
||||
Effect &operator=(const Effect &) { return *this; }
|
||||
|
||||
virtual bool computeBound() const;
|
||||
|
||||
|
||||
/** force rebuilding of techniques on next traversal */
|
||||
inline void dirtyTechniques();
|
||||
|
||||
@@ -144,7 +136,7 @@ namespace osgFX
|
||||
this method.
|
||||
*/
|
||||
virtual bool define_techniques() = 0;
|
||||
|
||||
|
||||
private:
|
||||
friend class Validator;
|
||||
|
||||
@@ -157,11 +149,11 @@ namespace osgFX
|
||||
|
||||
// use int instead of bool to avoid errors
|
||||
mutable osg::buffered_value<int> tech_selected_;
|
||||
|
||||
int global_sel_tech_;
|
||||
|
||||
bool techs_defined_;
|
||||
|
||||
osg::ref_ptr<osg::Node> child_;
|
||||
osg::ref_ptr<osg::Geode> dummy_for_validation_;
|
||||
|
||||
void build_dummy_node();
|
||||
@@ -179,33 +171,6 @@ namespace osgFX
|
||||
enabled_ = v;
|
||||
}
|
||||
|
||||
inline const osg::Node *Effect::getChild() const
|
||||
{
|
||||
return child_.get();
|
||||
}
|
||||
|
||||
inline osg::Node *Effect::getChild()
|
||||
{
|
||||
return child_.get();
|
||||
}
|
||||
|
||||
inline void Effect::setChild(osg::Node *child)
|
||||
{
|
||||
child_ = child;
|
||||
setNumChildrenRequiringUpdateTraversal(0);
|
||||
setNumChildrenWithCullingDisabled(0);
|
||||
setNumChildrenWithOccluderNodes(0);
|
||||
if (child) {
|
||||
if (child->getNumChildrenRequiringUpdateTraversal() > 0 || child->getUpdateCallback())
|
||||
setNumChildrenRequiringUpdateTraversal(1);
|
||||
if (child->getNumChildrenWithCullingDisabled() > 0 || !child->getCullingActive())
|
||||
setNumChildrenWithCullingDisabled(1);
|
||||
if (child->getNumChildrenWithOccluderNodes() > 0 || dynamic_cast<osg::OccluderNode *>(child))
|
||||
setNumChildrenWithOccluderNodes(1);
|
||||
}
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
inline int Effect::getNumTechniques() const
|
||||
{
|
||||
return static_cast<int>(techs_.size());
|
||||
@@ -240,6 +205,12 @@ namespace osgFX
|
||||
{
|
||||
techs_defined_ = false;
|
||||
}
|
||||
|
||||
inline void Effect::inherited_traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
typedef osg::Group inherited;
|
||||
inherited::traverse(nv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
namespace osgFX
|
||||
{
|
||||
|
||||
class Effect;
|
||||
|
||||
/**
|
||||
This is the base class for effect techniques. A technique represents one
|
||||
of the possible ways to implement a special effect. This base class is
|
||||
@@ -79,12 +81,6 @@ namespace osgFX
|
||||
/** get the number of rendering passes defined in this technique */
|
||||
inline int getNumPasses() const;
|
||||
|
||||
/** get the Group object associated to the i-th pass */
|
||||
inline osg::Group *getPassGroup(int i);
|
||||
|
||||
/** get the const Group object associated to the i-th pass */
|
||||
inline const osg::Group *getPassGroup(int i) const;
|
||||
|
||||
/** get the StateSet object associated to the i-th pass */
|
||||
inline osg::StateSet *getPassStateSet(int i);
|
||||
|
||||
@@ -92,11 +88,13 @@ namespace osgFX
|
||||
inline const osg::StateSet *getPassStateSet(int i) const;
|
||||
|
||||
/**
|
||||
traverses the child nodes with multipass if necessary.
|
||||
traverse children with multipass if necessary. By default this method
|
||||
simply calls the protected method traverse_implementation(); you can
|
||||
override it to change the default behavior.
|
||||
Don't call this method directly as it is called by osgFX::Effect
|
||||
*/
|
||||
virtual void accept(osg::NodeVisitor &nv, osg::Node *child);
|
||||
|
||||
inline virtual void traverse(osg::NodeVisitor &nv, Effect *fx);
|
||||
|
||||
protected:
|
||||
Technique(const Technique &): osg::Referenced() {} // copying is nonsense ;)
|
||||
virtual ~Technique() {}
|
||||
@@ -105,82 +103,54 @@ namespace osgFX
|
||||
/** force rebuilding of pass nodes on next traversal */
|
||||
inline void dirtyPasses();
|
||||
|
||||
/** optional: return a node that overrides the child node on a specified pass */
|
||||
inline virtual osg::Node *getOverrideChild(int) { return 0; }
|
||||
|
||||
/** create a new pass node, add it to the technique and associate a StateSet */
|
||||
void addPass(osg::StateSet *ss = 0);
|
||||
|
||||
/**
|
||||
add a new pass to the technique specifying an user-defined pass node.
|
||||
You should call this version of addPass() only when you need to gain direct
|
||||
control over the pass node (i.e. for setting up a cull callback); otherwise
|
||||
please use addPass(StateSet*) and let the class create the pass node for you.
|
||||
*/
|
||||
void addPass(osg::Group *pass);
|
||||
|
||||
/**
|
||||
get the control node which holds the user's subgraph.
|
||||
You may want to do something on it like applying a cull callback.
|
||||
*/
|
||||
inline osg::Group *getControlNode();
|
||||
|
||||
/** get the const control node which holds the user's subgraph */
|
||||
inline const osg::Group *getControlNode() const;
|
||||
|
||||
/** optional: return a node that overrides the child node on a specified pass */
|
||||
inline virtual osg::Node *getOverrideChild(int) { return 0; }
|
||||
|
||||
/**
|
||||
define the rendering passes that make up this technique. You must
|
||||
implement this method in derived classes to add the required passes.
|
||||
*/
|
||||
virtual void define_passes() = 0;
|
||||
|
||||
/**
|
||||
traverse children with multipass if necessary. Don't call this method
|
||||
directly unless you are in a customized version of traverse().
|
||||
*/
|
||||
void traverse_implementation(osg::NodeVisitor &nv, Effect *fx);
|
||||
|
||||
private:
|
||||
bool passes_defined_;
|
||||
|
||||
osg::ref_ptr<osg::Group> control_node_;
|
||||
osg::ref_ptr<osg::Node> prev_child_;
|
||||
typedef std::vector<osg::ref_ptr<osg::StateSet> > Pass_list;
|
||||
Pass_list passes_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline int Technique::getNumPasses() const
|
||||
{
|
||||
return static_cast<int>(control_node_->getNumChildren());
|
||||
}
|
||||
|
||||
inline osg::Group *Technique::getPassGroup(int i)
|
||||
{
|
||||
return static_cast<osg::Group *>(control_node_->getChild(i));
|
||||
}
|
||||
|
||||
inline const osg::Group *Technique::getPassGroup(int i) const
|
||||
{
|
||||
return static_cast<const osg::Group *>(control_node_->getChild(i));
|
||||
return static_cast<int>(passes_.size());
|
||||
}
|
||||
|
||||
inline osg::StateSet *Technique::getPassStateSet(int i)
|
||||
{
|
||||
return control_node_->getChild(i)->getStateSet();
|
||||
return passes_[i].get();
|
||||
}
|
||||
|
||||
inline const osg::StateSet *Technique::getPassStateSet(int i) const
|
||||
{
|
||||
return control_node_->getChild(i)->getStateSet();
|
||||
return passes_[i].get();
|
||||
}
|
||||
|
||||
inline osg::Group *Technique::getControlNode()
|
||||
{
|
||||
return control_node_.get();
|
||||
}
|
||||
|
||||
inline const osg::Group *Technique::getControlNode() const
|
||||
{
|
||||
return control_node_.get();
|
||||
}
|
||||
|
||||
|
||||
inline void Technique::dirtyPasses()
|
||||
{
|
||||
passes_defined_ = false;
|
||||
passes_.clear();
|
||||
}
|
||||
|
||||
inline void Technique::traverse(osg::NodeVisitor &nv, Effect *fx)
|
||||
{
|
||||
traverse_implementation(nv, fx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,22 +34,28 @@ namespace osgFX
|
||||
*/
|
||||
class OSGFX_EXPORT Validator: public osg::StateAttribute {
|
||||
public:
|
||||
enum {
|
||||
VALIDATOR = 0x56616C69
|
||||
};
|
||||
|
||||
Validator();
|
||||
Validator(Effect *effect);
|
||||
Validator(const Validator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_StateAttribute(osgFX, Validator, 0x56616C69);
|
||||
META_StateAttribute(osgFX, Validator, VALIDATOR);
|
||||
|
||||
void apply(osg::State &state) const;
|
||||
|
||||
inline int compare(const osg::StateAttribute &sa) const;
|
||||
|
||||
inline void disable() { effect_ = 0; }
|
||||
|
||||
protected:
|
||||
virtual ~Validator() {}
|
||||
Validator &operator=(const Validator &) { return *this; }
|
||||
|
||||
private:
|
||||
mutable osg::ref_ptr<Effect> effect_;
|
||||
mutable Effect *effect_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
@@ -59,8 +65,8 @@ namespace osgFX
|
||||
const Validator *v = dynamic_cast<const Validator *>(&sa);
|
||||
if (!v) return -1;
|
||||
|
||||
if (effect_.get() < v->effect_.get()) return -1;
|
||||
if (effect_.get() > v->effect_.get()) return 1;
|
||||
if (effect_ < v->effect_) return -1;
|
||||
if (effect_ > v->effect_) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user