]> git.mxchange.org Git - simgear.git/commitdiff
Lauri Peltonen : add the ability to generate tangent vectors for model, terrain or...
authorfredb <fredb>
Sun, 14 Mar 2010 20:04:41 +0000 (20:04 +0000)
committerTim Moore <timoore33@gmail.com>
Tue, 16 Mar 2010 13:27:21 +0000 (14:27 +0100)
simgear/scene/material/Effect.cxx
simgear/scene/material/Effect.hxx
simgear/scene/material/EffectGeode.cxx
simgear/scene/material/EffectGeode.hxx
simgear/scene/material/makeEffect.cxx
simgear/scene/model/model.cxx
simgear/scene/tgdb/SGOceanTile.cxx
simgear/scene/tgdb/obj.cxx

index f2bcbcdc619cbbba615011667e3de8b80a0be6cf..c3976d81039ad9e512dc45115939b9345ed5bcb2 100644 (file)
@@ -98,6 +98,8 @@ Effect::Effect(const Effect& rhs, const CopyOp& copyop)
          itr != end;
          ++itr)
         techniques.push_back(static_cast<Technique*>(copyop(itr->get())));
+
+    generator = rhs.generator;
 }
 
 // Assume that the last technique is always valid.
@@ -110,6 +112,13 @@ StateSet* Effect::getDefaultStateSet()
     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.
 
 Technique* Effect::chooseTechnique(RenderInfo* info)
index 0690db3a76a5f17e36334fafd24429a1b778b2e9..59eea81d8027fe18b4d08276d21df493527e9d01 100644 (file)
@@ -80,6 +80,18 @@ public:
     Effect(const Effect& rhs,
            const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
     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;
     SGPropertyNode_ptr root;
     // Pointer to the parameters node, if it exists
index aff9aebc4469c077f69952db4010199d68a49380..eac2f15646a5c7f4affcc3b3a8ef9dc7334c7af8 100644 (file)
@@ -23,6 +23,7 @@
 #include "Technique.hxx"
 
 #include <osgUtil/CullVisitor>
+#include <osgUtil/TangentSpaceGenerator>
 
 #include <osgDB/Registry>
 #include <osgDB/Input>
@@ -66,6 +67,31 @@ void EffectGeode::releaseGLObjects(osg::State* state) const
     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);
index 93c552a37558b194bd7d70d6182bed8af202136b..515b1a0ac57a8c565ff0a20e26f20e69dd90225a 100644 (file)
@@ -37,6 +37,7 @@ public:
     typedef DrawableList::iterator DrawablesIterator;
     DrawablesIterator drawablesBegin() { return _drawables.begin(); }
     DrawablesIterator drawablesEnd() { return _drawables.end(); }
+    void runGenerators(osg::Geometry *geometry);
 private:
     osg::ref_ptr<Effect> _effect;
 };
index 4ce5841f5d2a0ae303862dc133e6396dca0bb928..dfb7fe97f2a16608d89c9abb8b8fb8f45648e8c9 100644 (file)
@@ -205,8 +205,10 @@ Effect* makeEffect(SGPropertyNode* prop,
                     lock(effectMutex);
                 cache = parent->getCache();
                 itr = cache->find(key);
-                if (itr != cache->end()) 
+                if (itr != cache->end()) {
                     effect = itr->second.get();
+                    effect->generator = parent->generator;  // Copy the generators
+                }
             }
             if (!effect.valid()) {
                 effect = new Effect;
@@ -219,6 +221,7 @@ Effect* makeEffect(SGPropertyNode* prop,
                     = cache->insert(make_pair(key, effect));
                 if (!irslt.second)
                     effect = irslt.first->second;
+                effect->generator = parent->generator;  // Copy the generators
             }
         } else {
             SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " <<
@@ -230,6 +233,21 @@ Effect* makeEffect(SGPropertyNode* prop,
         effect->root = prop;
         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) {
         try {
             OpenThreads::ScopedLock<OpenThreads::ReentrantMutex>
index 1ea486f0d13afc5b1dae4353c449539f77df3d85..41fe9a307f635e2affb1347c856e389d5df5227d 100644 (file)
@@ -274,8 +274,14 @@ void MakeEffectVisitor::apply(osg::Geode& geode)
         ref_ptr<SGSceneUserData> userData = SGSceneUserData::getSceneUserData(&geode);
         if (userData.valid())
             eg->setUserData(new SGSceneUserData(*userData));
-        for (int i = 0; i < geode.getNumDrawables(); ++i)
-            eg->addDrawable(geode.getDrawable(i));
+        for (int i = 0; i < geode.getNumDrawables(); ++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);
 
index 34a0bba788a71f3e73def79a2d30c7e4c448ad53..337a3103e0b2de1025440200a23615e1744f27ad 100644 (file)
@@ -310,6 +310,7 @@ osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
     geode->setName("Ocean tile");
     geode->setEffect(effect);
     geode->addDrawable(geometry);
+    geode->runGenerators(geometry);
 
     osg::MatrixTransform* transform = new osg::MatrixTransform;
     transform->setName("Ocean");
index 74b4a0718be358aa2ab5206d3a10c59d43ab7456..dec3c6c4f5acaa5eb78efc27240f1f1b86090cec 100644 (file)
@@ -382,6 +382,7 @@ struct SGTileGeometryBin {
       if (mat)
         eg->setEffect(mat->get_effect());
       eg->addDrawable(geometry);
+      eg->runGenerators(geometry);  // Generate extra data needed by effect
       if (group)
         group->addChild(eg);
     }