]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGLightAnimation.cxx
bad681c31485bfe84196af7446da41099fd4ec2b
[simgear.git] / simgear / scene / model / SGLightAnimation.cxx
1 // Copyright (C) 2011 Frederic Bouvier (fredfgfs01@free.fr)
2 //
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.
7 //
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.
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
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include "animation.hxx"
23 #include "ConditionNode.hxx"
24
25 #include <osg/Geometry>
26 #include <osg/MatrixTransform>
27 #include <simgear/scene/material/EffectGeode.hxx>
28 #include <boost/scoped_array.hpp>
29
30 SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
31                                    SGPropertyNode* modelRoot) :
32     SGAnimation(configNode, modelRoot)
33 {
34 }
35
36 osg::Group*
37 SGLightAnimation::createAnimationGroup(osg::Group& parent)
38 {
39     osg::MatrixTransform* grp = new osg::MatrixTransform;
40     osg::Vec3 position( getConfig()->getDoubleValue("position/x-m"),
41                         getConfig()->getDoubleValue("position/y-m"),
42                         getConfig()->getDoubleValue("position/z-m") );
43     grp->setMatrix(osg::Matrix::translate(position));
44   parent.addChild(grp);
45   grp->setNodeMask( simgear::MODELLIGHT_BIT );
46   return grp;
47 }
48
49 void
50 SGLightAnimation::install(osg::Node& node)
51 {
52   SGAnimation::install(node);
53
54   std::string light_type = getConfig()->getStringValue("light-type");
55   if (light_type == "spot") {
56     osg::Vec3 axis( getConfig()->getDoubleValue("axis/x"),
57                     getConfig()->getDoubleValue("axis/y"),
58                     getConfig()->getDoubleValue("axis/z") );
59     double l = axis.length();
60     if (l < 0.001) return;
61     axis /= l;
62
63     osg::Vec3 p1(  axis.z(), axis.x(), axis.y() ),
64               p2 = axis ^ p1;
65     p1 = p2 ^ axis;
66
67     float n = getConfig()->getFloatValue("near-m"),
68           f = getConfig()->getFloatValue("far-m"),
69           a1 = getConfig()->getFloatValue("angle-inner-deg"),
70           a2 = getConfig()->getFloatValue("angle-outer-deg"),
71           r1 = n * tan( a2 * SG_DEGREES_TO_RADIANS ),
72           r2 = f * tan( a2 * SG_DEGREES_TO_RADIANS );
73
74     osg::Geometry* cone = new osg::Geometry;
75 cone->setUseDisplayList(false);
76     osg::Vec3Array* vertices = new osg::Vec3Array(36);
77     (*vertices)[0] = osg::Vec3(0.0,0.0,0.0);
78     for (int i=0; i<16; ++i) {
79       (*vertices)[16-i]    = axis*f + p1*r2*cos( i * 2 * M_PI / 16 ) + p2*r2*sin( i * 2 * M_PI / 16 );
80     }
81     (*vertices)[17] = (*vertices)[1];
82
83     // Bottom
84     (*vertices)[18] = axis*f;
85     for (int i=0; i<16; ++i) {
86       (*vertices)[19+i]    = axis*f + p1*r2*cos( i * 2 * M_PI / 16 ) + p2*r2*sin( i * 2 * M_PI / 16 );
87     }
88     (*vertices)[35] = (*vertices)[19];
89
90     osg::Vec4Array* colours = new osg::Vec4Array(1);
91     (*colours)[0].set(  getConfig()->getFloatValue("color/red"),
92                         getConfig()->getFloatValue("color/green"),
93                         getConfig()->getFloatValue("color/blue"),
94                         1.0f);
95     cone->setColorArray(colours);
96     cone->setColorBinding(osg::Geometry::BIND_OVERALL);
97
98     osg::Vec3Array* normals = new osg::Vec3Array(1);
99     (*normals)[0] = axis;
100     cone->setNormalArray(normals);
101     cone->setNormalBinding(osg::Geometry::BIND_OVERALL);
102
103     cone->setVertexArray(vertices);
104     cone->addPrimitiveSet( new osg::DrawArrays( GL_TRIANGLE_FAN, 0, 18 ) );
105     cone->addPrimitiveSet( new osg::DrawArrays( GL_TRIANGLE_FAN, 18, 18 ) );
106
107     simgear::EffectGeode* geode = new simgear::EffectGeode;
108     geode->addDrawable( cone );
109
110     node.asGroup()->addChild( geode );
111     simgear::Effect *effect = simgear::makeEffect("Effects/light-spot", true);
112     if (effect) {
113       effect->parametersProp->setFloatValue("inner-angle",getConfig()->getFloatValue("angle-inner-deg"));
114       effect->parametersProp->setFloatValue("outer-angle",getConfig()->getFloatValue("angle-outer-deg"));
115       geode->setEffect(effect);
116     }
117   }
118 }