1 // Copyright (C) 2011 Frederic Bouvier (fredfgfs01@free.fr)
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
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.
19 # include <simgear_config.h>
22 #include <boost/lexical_cast.hpp>
24 #include "animation.hxx"
25 #include "ConditionNode.hxx"
27 #include <osg/Geometry>
28 #include <osg/MatrixTransform>
29 #include <simgear/scene/material/EffectGeode.hxx>
30 #include <boost/scoped_array.hpp>
31 #include <simgear/scene/util/CopyOp.hxx>
33 typedef std::map<string, osg::ref_ptr<simgear::Effect> > EffectMap;
34 static EffectMap lightEffectMap;
36 #define GET_COLOR_VALUE(n) \
37 SGVec4d( getConfig()->getDoubleValue(n "/r"), \
38 getConfig()->getDoubleValue(n "/g"), \
39 getConfig()->getDoubleValue(n "/b"), \
40 getConfig()->getDoubleValue(n "/a") )
42 SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
43 SGPropertyNode* modelRoot,
44 const string &path, int i) :
45 SGAnimation(configNode, modelRoot)
47 _light_type = getConfig()->getStringValue("light-type");
48 _position = SGVec3d( getConfig()->getDoubleValue("position/x"), getConfig()->getDoubleValue("position/y"), getConfig()->getDoubleValue("position/z") );
49 _direction = SGVec3d( getConfig()->getDoubleValue("direction/x"), getConfig()->getDoubleValue("direction/y"), getConfig()->getDoubleValue("direction/z") );
50 double l = length(_direction);
51 if (l > 0.001) _direction /= l;
52 _ambient = GET_COLOR_VALUE("ambient");
53 _diffuse = GET_COLOR_VALUE("diffuse");
54 _specular = GET_COLOR_VALUE("specular");
55 _attenuation = SGVec3d( getConfig()->getDoubleValue("attenuation/c"), getConfig()->getDoubleValue("attenuation/l"), getConfig()->getDoubleValue("attenuation/q") );
56 _exponent = getConfig()->getDoubleValue("exponent");
57 _cutoff = getConfig()->getDoubleValue("cutoff");
58 _near = getConfig()->getDoubleValue("near-m");
59 _far = getConfig()->getDoubleValue("far-m");
60 _key = path + ";" + boost::lexical_cast<string>( i );
64 SGLightAnimation::createAnimationGroup(osg::Group& parent)
66 osg::Group* grp = new osg::Group;
68 grp->setNodeMask( simgear::MODELLIGHT_BIT );
73 SGLightAnimation::install(osg::Node& node)
75 SGAnimation::install(node);
77 if (_light_type == "spot") {
79 simgear::Effect* effect = 0;
80 EffectMap::iterator iter = lightEffectMap.find(_key);
81 if (iter == lightEffectMap.end()) {
82 SGPropertyNode_ptr effectProp = new SGPropertyNode;
83 makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot");
84 SGPropertyNode* params = makeChild(effectProp, "parameters");
85 params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0));
86 params->getNode("light-spot/direction",true)->setValue(SGVec4d(_direction.x(),_direction.y(),_direction.z(),0.0));
87 params->getNode("light-spot/ambient",true)->setValue(_ambient);
88 params->getNode("light-spot/diffuse",true)->setValue(_diffuse);
89 params->getNode("light-spot/specular",true)->setValue(_specular);
90 params->getNode("light-spot/attenuation",true)->setValue(_attenuation);
91 params->getNode("light-spot/exponent",true)->setValue(_exponent);
92 params->getNode("light-spot/cutoff",true)->setValue(_cutoff);
93 params->getNode("light-spot/cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) );
94 params->getNode("light-spot/near",true)->setValue(_near);
95 params->getNode("light-spot/far",true)->setValue(_far);
97 effect = simgear::makeEffect(effectProp, true);
98 lightEffectMap.insert(EffectMap::value_type(_key, effect));
100 effect = iter->second.get();
103 node.setNodeMask( simgear::MODELLIGHT_BIT );
104 simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>(&node);
106 osg::Group* grp = node.asGroup();
108 for (size_t i=0; i<grp->getNumChildren(); ++i) {
109 geode = dynamic_cast<simgear::EffectGeode*>(grp->getChild(i));
111 geode->setEffect(effect);
116 else if (_light_type == "point") {
118 simgear::Effect* effect = 0;
119 EffectMap::iterator iter = lightEffectMap.find(_key);
120 if (iter == lightEffectMap.end()) {
121 SGPropertyNode_ptr effectProp = new SGPropertyNode;
122 makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-point");
123 SGPropertyNode* params = makeChild(effectProp, "parameters");
124 params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0));
125 params->getNode("light-spot/ambient",true)->setValue(_ambient);
126 params->getNode("light-spot/diffuse",true)->setValue(_diffuse);
127 params->getNode("light-spot/specular",true)->setValue(_specular);
128 params->getNode("light-spot/attenuation",true)->setValue(_attenuation);
129 params->getNode("light-spot/near",true)->setValue(_near);
130 params->getNode("light-spot/far",true)->setValue(_far);
132 effect = simgear::makeEffect(effectProp, true);
133 lightEffectMap.insert(EffectMap::value_type(_key, effect));
135 effect = iter->second.get();
138 node.setNodeMask( simgear::MODELLIGHT_BIT );
139 simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>(&node);
141 osg::Group* grp = node.asGroup();
143 for (size_t i=0; i<grp->getNumChildren(); ++i) {
144 geode = dynamic_cast<simgear::EffectGeode*>(grp->getChild(i));
146 geode->setEffect(effect);