1 // Copyright (C) 2008  Timothy Moore timoore@redhat.com
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 
17 #ifdef HAVE_CONFIG_H
18 #  include <simgear_config.h>
19 #endif
20 
21 #include "EffectGeode.hxx"
22 #include "Effect.hxx"
23 #include "Technique.hxx"
24 
25 #include <osg/Version>
26 
27 #include <osgUtil/CullVisitor>
28 #include <osgUtil/TangentSpaceGenerator>
29 
30 #include <osgDB/Registry>
31 #include <osgDB/Input>
32 #include <osgDB/ParameterOutput>
33 
34 namespace simgear
35 {
36 
37 using namespace osg;
38 using namespace osgUtil;
39 
EffectGeode()40 EffectGeode::EffectGeode()
41 {
42 }
43 
EffectGeode(const EffectGeode & rhs,const osg::CopyOp & copyop)44 EffectGeode::EffectGeode(const EffectGeode& rhs, const osg::CopyOp& copyop) :
45     Geode(rhs, copyop),
46     _effect(static_cast<Effect*>(copyop(rhs._effect.get())))
47 {
48 }
49 
setEffect(Effect * effect)50 void EffectGeode::setEffect(Effect* effect)
51 {
52     _effect = effect;
53     if (!_effect)
54         return;
55     addUpdateCallback(new Effect::InitializeCallback);
56 }
57 
resizeGLObjectBuffers(unsigned int maxSize)58 void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
59 {
60     if (_effect.valid())
61         _effect->resizeGLObjectBuffers(maxSize);
62     Geode::resizeGLObjectBuffers(maxSize);
63 }
64 
releaseGLObjects(osg::State * state) const65 void EffectGeode::releaseGLObjects(osg::State* state) const
66 {
67     if (_effect.valid())
68         _effect->releaseGLObjects(state);
69     Geode::releaseGLObjects(state);
70 }
71 
72 // Generates tangent space vectors or other data from geom, as defined by effect
runGenerators(osg::Geometry * geometry)73 void EffectGeode::runGenerators(osg::Geometry *geometry)
74 {
75       if(geometry && _effect.valid()) {
76         // Generate tangent vectors for the geometry
77         osg::ref_ptr<osgUtil::TangentSpaceGenerator> tsg = new osgUtil::TangentSpaceGenerator;
78 
79         // Generating only tangent vector should be enough
80         // since the binormal is a cross product of normal and tangent
81         // This saves a bit of memory & memory bandwidth!
82         int n = _effect->getGenerator(Effect::TANGENT);
83         tsg->generate(geometry, 0);  // 0 is normal_unit, but I have no idea what that is!
84         if (n != -1 && !geometry->getVertexAttribArray(n))
85 #if OSG_MIN_VERSION_REQUIRED(3,1,8)
86           geometry->setVertexAttribArray(n, tsg->getTangentArray(), osg::Array::BIND_PER_VERTEX);
87 #else
88           geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getTangentArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
89 #endif
90 
91         n = _effect->getGenerator(Effect::BINORMAL);
92         if (n != -1 && !geometry->getVertexAttribArray(n))
93 #if OSG_MIN_VERSION_REQUIRED(3,1,8)
94           geometry->setVertexAttribArray(n, tsg->getBinormalArray(), osg::Array::BIND_PER_VERTEX);
95 #else
96           geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getBinormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
97 #endif
98 
99         n = _effect->getGenerator(Effect::NORMAL);
100         if (n != -1 && !geometry->getVertexAttribArray(n))
101 #if OSG_MIN_VERSION_REQUIRED(3,1,8)
102           geometry->setVertexAttribArray(n, tsg->getNormalArray(), osg::Array::BIND_PER_VERTEX);
103 #else
104           geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getNormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE));
105 #endif
106     }
107 }
108 
EffectGeode_writeLocalData(const Object & obj,osgDB::Output & fw)109 bool EffectGeode_writeLocalData(const Object& obj, osgDB::Output& fw)
110 {
111     const EffectGeode& eg = static_cast<const EffectGeode&>(obj);
112 
113     if (eg.getEffect()) {
114         fw.indent() << "effect\n";
115         fw.writeObject(*eg.getEffect());
116     }
117 
118     return true;
119 }
120 
121 namespace
122 {
123 osgDB::RegisterDotOsgWrapperProxy effectGeodeProxy
124 (
125     new EffectGeode,
126     "simgear::EffectGeode",
127     "Object Node Geode simgear::EffectGeode",
128     0,
129     &EffectGeode_writeLocalData
130     );
131 }
132 }
133