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:
@@ -599,22 +599,23 @@ void BumpMapping::prepareNode(osg::Node *node)
|
||||
node->accept(tv);
|
||||
}
|
||||
|
||||
void BumpMapping::prepareChild()
|
||||
void BumpMapping::prepareChildren()
|
||||
{
|
||||
if (getChild())
|
||||
prepareNode(getChild());
|
||||
for (unsigned i=0; i<getNumChildren(); ++i)
|
||||
prepareNode(getChild(i));
|
||||
}
|
||||
|
||||
void BumpMapping::setUpDemo()
|
||||
{
|
||||
// generate texture coordinates
|
||||
TexCoordGenerator tcg(diffuseunit_, normalunit_);
|
||||
getChild()->accept(tcg);
|
||||
for (unsigned i=0; i<getNumChildren(); ++i)
|
||||
getChild(i)->accept(tcg);
|
||||
|
||||
// set up diffuse texture
|
||||
if (!diffuse_tex_.valid()) {
|
||||
diffuse_tex_ = new osg::Texture2D;
|
||||
diffuse_tex_->setImage(osgDB::readImageFile("whitemetal_diffuse.jpg"));
|
||||
diffuse_tex_->setImage(osgDB::readImageFile("Images/whitemetal_diffuse.jpg"));
|
||||
diffuse_tex_->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
diffuse_tex_->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
diffuse_tex_->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
|
||||
@@ -625,7 +626,7 @@ void BumpMapping::setUpDemo()
|
||||
// set up normal map texture
|
||||
if (!normal_tex_.valid()) {
|
||||
normal_tex_ = new osg::Texture2D;
|
||||
normal_tex_->setImage(osgDB::readImageFile("whitemetal_normal.jpg"));
|
||||
normal_tex_->setImage(osgDB::readImageFile("Images/whitemetal_normal.jpg"));
|
||||
normal_tex_->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
normal_tex_->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
normal_tex_->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
|
||||
@@ -634,7 +635,7 @@ void BumpMapping::setUpDemo()
|
||||
}
|
||||
|
||||
// generate tangent-space basis vector
|
||||
prepareChild();
|
||||
prepareChildren();
|
||||
|
||||
// recreate techniques on next step
|
||||
dirtyTechniques();
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
#include <osg/StateAttribute>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
using namespace osgFX;
|
||||
|
||||
Effect::Effect()
|
||||
: osg::Node(),
|
||||
: osg::Group(),
|
||||
enabled_(true),
|
||||
global_sel_tech_(AUTO_DETECT),
|
||||
techs_defined_(false)
|
||||
@@ -18,56 +20,59 @@ Effect::Effect()
|
||||
}
|
||||
|
||||
Effect::Effect(const Effect ©, const osg::CopyOp ©op)
|
||||
: osg::Node(copy, copyop),
|
||||
: osg::Group(copy, copyop),
|
||||
enabled_(copy.enabled_),
|
||||
global_sel_tech_(copy.global_sel_tech_),
|
||||
techs_defined_(false),
|
||||
child_(static_cast<osg::Node *>(copyop(copy.child_.get())))
|
||||
techs_defined_(false)
|
||||
{
|
||||
build_dummy_node();
|
||||
}
|
||||
|
||||
bool Effect::computeBound() const
|
||||
Effect::~Effect()
|
||||
{
|
||||
_bsphere.init();
|
||||
_bsphere_computed = true;
|
||||
|
||||
if (child_.valid()) {
|
||||
_bsphere.expandBy(child_->getBound());
|
||||
}
|
||||
|
||||
return _bsphere.valid();
|
||||
// disable the validator for safety, so it won't try to access us
|
||||
// even if it stays alive for some reason
|
||||
if (dummy_for_validation_.valid()) {
|
||||
osg::StateSet *ss = dummy_for_validation_->getStateSet();
|
||||
if (ss) {
|
||||
Validator *validator = dynamic_cast<Validator *>(ss->getAttribute(Validator::VALIDATOR));
|
||||
if (validator) {
|
||||
validator->disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
typedef osg::Node Inherited;
|
||||
|
||||
if (!child_.valid()) return;
|
||||
|
||||
// we are not a Group, so children will not notify us when their
|
||||
// bounding box has changed. We need to recompute it at each traversal... :(
|
||||
dirtyBound();
|
||||
|
||||
// if this effect is not enabled, then go for default traversal
|
||||
if (!enabled_) {
|
||||
child_->accept(nv);
|
||||
Inherited::traverse(nv);
|
||||
inherited_traverse(nv);
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure that at least one technique is defined
|
||||
if (!techs_defined_) {
|
||||
|
||||
// clear existing techniques if necessary
|
||||
// clear existing techniques
|
||||
techs_.clear();
|
||||
|
||||
// clear technique selection indices
|
||||
sel_tech_.clear();
|
||||
|
||||
// clear technique selection flags
|
||||
tech_selected_.clear();
|
||||
|
||||
// define new techniques
|
||||
techs_defined_ = define_techniques();
|
||||
|
||||
// check for errors, return on failure
|
||||
if (!techs_defined_) {
|
||||
osg::notify(osg::WARN) << "Warning: osgFX::Effect: could not define techniques for effect " << className() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure that at least one technique has been defined
|
||||
if (techs_.empty()) {
|
||||
osg::notify(osg::WARN) << "Warning: osgFX::Effect: no techniques defined for effect " << className() << std::endl;
|
||||
return;
|
||||
@@ -76,7 +81,11 @@ void Effect::traverse(osg::NodeVisitor &nv)
|
||||
|
||||
Technique *tech = 0;
|
||||
|
||||
if (global_sel_tech_ == AUTO_DETECT) {
|
||||
// if the selection mode is set to AUTO_DETECT then we have to
|
||||
// choose the active technique!
|
||||
if (global_sel_tech_ == AUTO_DETECT) {
|
||||
|
||||
// test whether at least one technique has been selected
|
||||
bool none_selected = true;
|
||||
for (unsigned i=0; i<tech_selected_.size(); ++i) {
|
||||
if (tech_selected_[i] != 0) {
|
||||
@@ -85,11 +94,15 @@ void Effect::traverse(osg::NodeVisitor &nv)
|
||||
}
|
||||
}
|
||||
|
||||
// no techniques selected, traverse a dummy node that
|
||||
// contains the Validator (it will select a technique)
|
||||
if (none_selected) {
|
||||
dummy_for_validation_->accept(nv);
|
||||
}
|
||||
|
||||
int max_index = -1;
|
||||
// find the highest priority technique that could be validated
|
||||
// in all active rendering contexts
|
||||
int max_index = -1;
|
||||
for (unsigned j=0; j<sel_tech_.size(); ++j) {
|
||||
if (tech_selected_[j] != 0) {
|
||||
if (sel_tech_[j] > max_index) {
|
||||
@@ -98,26 +111,28 @@ void Effect::traverse(osg::NodeVisitor &nv)
|
||||
}
|
||||
}
|
||||
|
||||
if (max_index >= 0) {
|
||||
// found a valid technique?
|
||||
if (max_index >= 0) {
|
||||
tech = techs_[max_index].get();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// the active technique was selected manually
|
||||
tech = techs_[global_sel_tech_].get();
|
||||
}
|
||||
|
||||
if (tech) {
|
||||
tech->accept(nv, child_.get());
|
||||
} else {
|
||||
child_->accept(nv);
|
||||
}
|
||||
// if we could find an active technique, then continue with traversal
|
||||
if (tech) {
|
||||
tech->traverse(nv, this);
|
||||
}
|
||||
|
||||
Inherited::traverse(nv);
|
||||
// wow, we're finished! :)
|
||||
}
|
||||
|
||||
void Effect::build_dummy_node()
|
||||
{
|
||||
dummy_for_validation_ = new osg::Geode;
|
||||
dummy_for_validation_ = new osg::Geode;
|
||||
osg::ref_ptr<osg::Geometry> geo = new osg::Geometry;
|
||||
dummy_for_validation_->addDrawable(geo.get());
|
||||
dummy_for_validation_->getOrCreateStateSet()->setAttribute(new Validator(this));
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
#include <osgFX/Technique>
|
||||
#include <osgFX/Effect>
|
||||
|
||||
#include <osg/GLExtensions>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
using namespace osgFX;
|
||||
|
||||
Technique::Technique()
|
||||
: osg::Referenced(),
|
||||
passes_defined_(false),
|
||||
control_node_(new osg::Group)
|
||||
: osg::Referenced()
|
||||
{
|
||||
}
|
||||
|
||||
void Technique::addPass(osg::StateSet *ss)
|
||||
{
|
||||
osg::ref_ptr<osg::Group> pass = new osg::Group;
|
||||
control_node_->addChild(pass.get());
|
||||
|
||||
if (ss) {
|
||||
ss->setRenderBinDetails(static_cast<int>(control_node_->getNumChildren()), "RenderBin");
|
||||
pass->setStateSet(ss);
|
||||
}
|
||||
}
|
||||
|
||||
void Technique::addPass(osg::Group *pass)
|
||||
{
|
||||
control_node_->addChild(pass);
|
||||
if (ss) {
|
||||
passes_.push_back(ss);
|
||||
ss->setRenderBinDetails(static_cast<int>(passes_.size()), "RenderBin");
|
||||
}
|
||||
}
|
||||
|
||||
bool Technique::validate(osg::State &) const
|
||||
@@ -41,39 +34,36 @@ bool Technique::validate(osg::State &) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Technique::accept(osg::NodeVisitor &nv, osg::Node *child)
|
||||
void Technique::traverse_implementation(osg::NodeVisitor &nv, Effect *fx)
|
||||
{
|
||||
// define passes if necessary
|
||||
if (!passes_defined_) {
|
||||
|
||||
// clear existing pass nodes
|
||||
if (control_node_->getNumChildren() > 0) {
|
||||
control_node_->removeChild(0, control_node_->getNumChildren());
|
||||
}
|
||||
|
||||
if (passes_.empty()) {
|
||||
define_passes();
|
||||
passes_defined_ = true;
|
||||
}
|
||||
|
||||
// update pass children if necessary
|
||||
if (child != prev_child_.get()) {
|
||||
for (unsigned i=0; i<control_node_->getNumChildren(); ++i) {
|
||||
osg::Group *pass = dynamic_cast<osg::Group *>(control_node_->getChild(i));
|
||||
if (pass) {
|
||||
if (pass->getNumChildren() > 0) {
|
||||
pass->removeChild(0, pass->getNumChildren());
|
||||
}
|
||||
osg::Node *oc = getOverrideChild(i);
|
||||
if (oc) {
|
||||
pass->addChild(oc);
|
||||
} else {
|
||||
pass->addChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_child_ = child;
|
||||
}
|
||||
// special actions must be taken if the node visitor is actually a CullVisitor
|
||||
osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(&nv);
|
||||
|
||||
// traverse the control node
|
||||
control_node_->accept(nv);
|
||||
// traverse all passes
|
||||
for (int i=0; i<getNumPasses(); ++i) {
|
||||
|
||||
// push the i-th pass' StateSet if necessary
|
||||
if (cv) {
|
||||
cv->pushStateSet(passes_[i].get());
|
||||
}
|
||||
|
||||
// traverse the override node if defined, otherwise
|
||||
// traverse children as a Group would do
|
||||
osg::Node *override = getOverrideChild(i);
|
||||
if (override) {
|
||||
override->accept(nv);
|
||||
} else {
|
||||
fx->inherited_traverse(nv);
|
||||
}
|
||||
|
||||
// pop the StateSet if necessary
|
||||
if (cv) {
|
||||
cv->popStateSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
using namespace osgFX;
|
||||
|
||||
Validator::Validator()
|
||||
: osg::StateAttribute()
|
||||
: osg::StateAttribute(),
|
||||
effect_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,13 +19,13 @@ Validator::Validator(Effect *effect)
|
||||
|
||||
Validator::Validator(const Validator ©, const osg::CopyOp ©op)
|
||||
: osg::StateAttribute(copy, copyop),
|
||||
effect_(static_cast<Effect *>(copyop(copy.effect_.get())))
|
||||
effect_(static_cast<Effect *>(copyop(copy.effect_)))
|
||||
{
|
||||
}
|
||||
|
||||
void Validator::apply(osg::State &state) const
|
||||
{
|
||||
if (!effect_.valid()) return;
|
||||
if (!effect_) return;
|
||||
|
||||
if (effect_->tech_selected_[state.getContextID()] == 0) {
|
||||
Effect::Technique_list::iterator i;
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy AnisotropicLighting_Proxy
|
||||
(
|
||||
new osgFX::AnisotropicLighting,
|
||||
"osgFX::AnisotropicLighting",
|
||||
"Object Node osgFX::Effect osgFX::AnisotropicLighting",
|
||||
"Object Node Group osgFX::Effect osgFX::AnisotropicLighting",
|
||||
AnisotropicLighting_readLocalData,
|
||||
AnisotropicLighting_writeLocalData
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy BumpMapping_Proxy
|
||||
(
|
||||
new osgFX::BumpMapping,
|
||||
"osgFX::BumpMapping",
|
||||
"Object Node osgFX::Effect osgFX::BumpMapping",
|
||||
"Object Node Group osgFX::Effect osgFX::BumpMapping",
|
||||
BumpMapping_readLocalData,
|
||||
BumpMapping_writeLocalData
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy Cartoon_Proxy
|
||||
(
|
||||
new osgFX::Cartoon,
|
||||
"osgFX::Cartoon",
|
||||
"Object Node osgFX::Effect osgFX::Cartoon",
|
||||
"Object Node Group osgFX::Effect osgFX::Cartoon",
|
||||
Cartoon_readLocalData,
|
||||
Cartoon_writeLocalData
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy Effect_Proxy
|
||||
(
|
||||
0,
|
||||
"osgFX::Effect",
|
||||
"Object Node osgFX::Effect",
|
||||
"Object Node Group osgFX::Effect",
|
||||
Effect_readLocalData,
|
||||
Effect_writeLocalData
|
||||
);
|
||||
@@ -46,11 +46,6 @@ bool Effect_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> node = static_cast<osg::Node *>(fr.readObjectOfType(osgDB::type_wrapper<osg::Node>()));
|
||||
if (node.valid()) {
|
||||
myobj.setChild(node.get());
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
@@ -65,7 +60,6 @@ bool Effect_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
} else {
|
||||
fw << myobj.getSelectedTechnique() << "\n";
|
||||
}
|
||||
fw.writeObject(*myobj.getChild());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy Scribe_Proxy
|
||||
(
|
||||
new osgFX::Scribe,
|
||||
"osgFX::Scribe",
|
||||
"Object Node osgFX::Effect osgFX::Scribe",
|
||||
"Object Node Group osgFX::Effect osgFX::Scribe",
|
||||
Scribe_readLocalData,
|
||||
Scribe_writeLocalData
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ osgDB::RegisterDotOsgWrapperProxy SpecularHighlights_Proxy
|
||||
(
|
||||
new osgFX::SpecularHighlights,
|
||||
"osgFX::SpecularHighlights",
|
||||
"Object Node osgFX::Effect osgFX::SpecularHighlights",
|
||||
"Object Node Group osgFX::Effect osgFX::SpecularHighlights",
|
||||
SpecularHighlights_readLocalData,
|
||||
SpecularHighlights_writeLocalData
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user