Merge branch 'zan/generate'

This commit is contained in:
Tim Moore 2010-03-30 12:04:09 +02:00
commit 3d91a11b95
8 changed files with 77 additions and 3 deletions

View File

@ -98,6 +98,8 @@ Effect::Effect(const Effect& rhs, const CopyOp& copyop)
itr != end; itr != end;
++itr) ++itr)
techniques.push_back(static_cast<Technique*>(copyop(itr->get()))); techniques.push_back(static_cast<Technique*>(copyop(itr->get())));
generator = rhs.generator;
} }
// Assume that the last technique is always valid. // Assume that the last technique is always valid.
@ -110,6 +112,13 @@ StateSet* Effect::getDefaultStateSet()
return pass; return pass;
} }
int Effect::getGenerator(Effect::Generator what) const
{
std::map<Generator,int>::const_iterator it = generator.find(what);
if(it == generator.end()) return -1;
else return it->second;
}
// There should always be a valid technique in an effect. // There should always be a valid technique in an effect.
Technique* Effect::chooseTechnique(RenderInfo* info) Technique* Effect::chooseTechnique(RenderInfo* info)

View File

@ -80,6 +80,18 @@ public:
Effect(const Effect& rhs, Effect(const Effect& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
osg::StateSet* getDefaultStateSet(); osg::StateSet* getDefaultStateSet();
// Define what needs to be generated for this effect
enum Generator
{
NORMAL,
TANGENT,
BINORMAL
};
void setGenerator(Generator what, int where) { generator[what] = where; }
int getGenerator(Generator what) const; // Returns -1 if generator should not be used
std::map<Generator, int> generator; // What is generated into which attribute location
std::vector<osg::ref_ptr<Technique> > techniques; std::vector<osg::ref_ptr<Technique> > techniques;
SGPropertyNode_ptr root; SGPropertyNode_ptr root;
// Pointer to the parameters node, if it exists // Pointer to the parameters node, if it exists

View File

@ -23,6 +23,7 @@
#include "Technique.hxx" #include "Technique.hxx"
#include <osgUtil/CullVisitor> #include <osgUtil/CullVisitor>
#include <osgUtil/TangentSpaceGenerator>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <osgDB/Input> #include <osgDB/Input>
@ -66,6 +67,31 @@ void EffectGeode::releaseGLObjects(osg::State* state) const
Geode::releaseGLObjects(state); 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) bool EffectGeode_writeLocalData(const Object& obj, osgDB::Output& fw)
{ {
const EffectGeode& eg = static_cast<const EffectGeode&>(obj); const EffectGeode& eg = static_cast<const EffectGeode&>(obj);

View File

@ -37,6 +37,7 @@ public:
typedef DrawableList::iterator DrawablesIterator; typedef DrawableList::iterator DrawablesIterator;
DrawablesIterator drawablesBegin() { return _drawables.begin(); } DrawablesIterator drawablesBegin() { return _drawables.begin(); }
DrawablesIterator drawablesEnd() { return _drawables.end(); } DrawablesIterator drawablesEnd() { return _drawables.end(); }
void runGenerators(osg::Geometry *geometry);
private: private:
osg::ref_ptr<Effect> _effect; osg::ref_ptr<Effect> _effect;
}; };

View File

@ -205,8 +205,10 @@ Effect* makeEffect(SGPropertyNode* prop,
lock(effectMutex); lock(effectMutex);
cache = parent->getCache(); cache = parent->getCache();
itr = cache->find(key); itr = cache->find(key);
if (itr != cache->end()) if (itr != cache->end()) {
effect = itr->second.get(); effect = itr->second.get();
effect->generator = parent->generator; // Copy the generators
}
} }
if (!effect.valid()) { if (!effect.valid()) {
effect = new Effect; effect = new Effect;
@ -219,6 +221,7 @@ Effect* makeEffect(SGPropertyNode* prop,
= cache->insert(make_pair(key, effect)); = cache->insert(make_pair(key, effect));
if (!irslt.second) if (!irslt.second)
effect = irslt.first->second; effect = irslt.first->second;
effect->generator = parent->generator; // Copy the generators
} }
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " << SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " <<
@ -230,6 +233,21 @@ Effect* makeEffect(SGPropertyNode* prop,
effect->root = prop; effect->root = prop;
effect->parametersProp = effect->root->getChild("parameters"); effect->parametersProp = effect->root->getChild("parameters");
} }
const SGPropertyNode *generateProp = prop->getChild("generate");
if(generateProp)
{
effect->generator.clear();
// Effect needs some generated properties, like tangent vectors
const SGPropertyNode *parameter = generateProp->getChild("normal");
if(parameter) effect->setGenerator(Effect::NORMAL, parameter->getIntValue());
parameter = generateProp->getChild("tangent");
if(parameter) effect->setGenerator(Effect::TANGENT, parameter->getIntValue());
parameter = generateProp->getChild("binormal");
if(parameter) effect->setGenerator(Effect::BINORMAL, parameter->getIntValue());
}
if (realizeTechniques) { if (realizeTechniques) {
try { try {
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> OpenThreads::ScopedLock<OpenThreads::ReentrantMutex>

View File

@ -274,8 +274,14 @@ void MakeEffectVisitor::apply(osg::Geode& geode)
ref_ptr<SGSceneUserData> userData = SGSceneUserData::getSceneUserData(&geode); ref_ptr<SGSceneUserData> userData = SGSceneUserData::getSceneUserData(&geode);
if (userData.valid()) if (userData.valid())
eg->setUserData(new SGSceneUserData(*userData)); eg->setUserData(new SGSceneUserData(*userData));
for (int i = 0; i < geode.getNumDrawables(); ++i) for (int i = 0; i < geode.getNumDrawables(); ++i) {
eg->addDrawable(geode.getDrawable(i)); osg::Drawable *drawable = geode.getDrawable(i);
eg->addDrawable(drawable);
// Generate tangent vectors etc if needed
osg::Geometry *geom = dynamic_cast<osg::Geometry*>(drawable);
if(geom) eg->runGenerators(geom);
}
} }
pushResultNode(&geode, eg); pushResultNode(&geode, eg);

View File

@ -310,6 +310,7 @@ osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
geode->setName("Ocean tile"); geode->setName("Ocean tile");
geode->setEffect(effect); geode->setEffect(effect);
geode->addDrawable(geometry); geode->addDrawable(geometry);
geode->runGenerators(geometry);
osg::MatrixTransform* transform = new osg::MatrixTransform; osg::MatrixTransform* transform = new osg::MatrixTransform;
transform->setName("Ocean"); transform->setName("Ocean");

View File

@ -382,6 +382,7 @@ struct SGTileGeometryBin {
if (mat) if (mat)
eg->setEffect(mat->get_effect()); eg->setEffect(mat->get_effect());
eg->addDrawable(geometry); eg->addDrawable(geometry);
eg->runGenerators(geometry); // Generate extra data needed by effect
if (group) if (group)
group->addChild(eg); group->addChild(eg);
} }