// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
#include "EffectGeode.hxx"
#include "Effect.hxx"
#include "Technique.hxx"
#include <osgUtil/CullVisitor>
+#include <osgUtil/TangentSpaceGenerator>
+
+#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);
+}
+
+EffectGeode::EffectGeode(const EffectGeode& rhs, const osg::CopyOp& copyop) :
+ Geode(rhs, copyop),
+ _effect(static_cast<Effect*>(copyop(rhs._effect.get())))
+{
+}
+
+void EffectGeode::setEffect(Effect* effect)
+{
+ _effect = effect;
+ if (!_effect)
return;
- }
- for (DrawablesIterator beginItr = _drawables.begin();
- beginItr != _drawables.end();
- beginItr = technique->processDrawables(beginItr, _drawables.end(), cv,
- isCullingActive()))
- ;
+ addUpdateCallback(new Effect::InitializeCallback);
}
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
Geode::releaseGLObjects(state);
}
+// Generates tangent space vectors or other data from geom, as defined by effect
+void EffectGeode::runGenerators(osg::Geometry *geometry)
+{
+ if(geometry && _effect.valid()) {
+ // Generate tangent vectors for the geometry
+ osg::ref_ptr<osgUtil::TangentSpaceGenerator> tsg = new osgUtil::TangentSpaceGenerator;
+
+ // Generating only tangent vector should be enough
+ // since the binormal is a cross product of normal and tangent
+ // This saves a bit of memory & memory bandwidth!
+ int n = _effect->getGenerator(Effect::TANGENT);
+ tsg->generate(geometry, 0); // 0 is normal_unit, but I have no idea what that is!
+ if (n != -1 && !geometry->getVertexAttribArray(n))
+ geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getTangentArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
+
+ n = _effect->getGenerator(Effect::BINORMAL);
+ if (n != -1 && !geometry->getVertexAttribArray(n))
+ geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getBinormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
+
+ n = _effect->getGenerator(Effect::NORMAL);
+ if (n != -1 && !geometry->getVertexAttribArray(n))
+ geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getNormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
+ }
+}
+
+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
+ );
+}
}