root/OpenSceneGraph/trunk/src/osgPresentation/AnimationMaterial.cpp @ 13041

Revision 13041, 7.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2 *
3 * This software is open source and may be redistributed and/or modified under
4 * the terms of the GNU General Public License (GPL) version 2.0.
5 * The full license is in LICENSE.txt file included with this distribution,.
6 *
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * include LICENSE.txt for more details.
11*/
12
13#include <osgPresentation/AnimationMaterial>
14
15#include <osg/MatrixTransform>
16#include <osg/PositionAttitudeTransform>
17#include <osg/Notify>
18#include <osg/io_utils>
19
20using namespace osgPresentation;
21
22void AnimationMaterial::insert(double time,osg::Material* material)
23{
24    _timeControlPointMap[time] = material;
25}
26
27bool AnimationMaterial::getMaterial(double time,osg::Material& material) const
28{
29    if (_timeControlPointMap.empty()) return false;
30
31    switch(_loopMode)
32    {
33        case(SWING):
34        {
35            double modulated_time = (time - getFirstTime())/(getPeriod()*2.0);
36            double fraction_part = modulated_time - floor(modulated_time);
37            if (fraction_part>0.5) fraction_part = 1.0-fraction_part;
38
39            time = getFirstTime()+(fraction_part*2.0) * getPeriod();
40            break;
41        }
42        case(LOOP):
43        {
44            double modulated_time = (time - getFirstTime())/getPeriod();
45            double fraction_part = modulated_time - floor(modulated_time);
46            time = getFirstTime()+fraction_part * getPeriod();
47            break;
48        }
49        case(NO_LOOPING):
50            // no need to modulate the time.
51            break;
52    }
53
54
55
56    TimeControlPointMap::const_iterator second = _timeControlPointMap.lower_bound(time);
57    if (second==_timeControlPointMap.begin())
58    {
59        material = *(second->second);
60    }
61    else if (second!=_timeControlPointMap.end())
62    {
63        TimeControlPointMap::const_iterator first = second;
64        --first;
65
66        // we have both a lower bound and the next item.
67
68        // deta_time = second.time - first.time
69        double delta_time = second->first - first->first;
70
71        if (delta_time==0.0)
72            material = *(first->second);
73        else
74        {
75            interpolate(material,(time - first->first)/delta_time, *first->second, *second->second);
76        }
77    }
78    else // (second==_timeControlPointMap.end())
79    {
80        material = *(_timeControlPointMap.rbegin()->second);
81    }
82    return true;
83}
84
85template<class T>
86T interp(float r, const T& lhs, const T& rhs)
87{
88    return lhs*(1.0f-r)+rhs*r;
89}
90
91
92void AnimationMaterial::interpolate(osg::Material& material, float r, const osg::Material& lhs,const osg::Material& rhs) const
93{
94    material.setColorMode(lhs.getColorMode());
95
96    material.setAmbient(osg::Material::FRONT_AND_BACK,interp(r, lhs.getAmbient(osg::Material::FRONT),rhs.getAmbient(osg::Material::FRONT)));
97    if (!material.getAmbientFrontAndBack())
98        material.setAmbient(osg::Material::BACK,interp(r, lhs.getAmbient(osg::Material::BACK),rhs.getAmbient(osg::Material::BACK)));
99
100    material.setDiffuse(osg::Material::FRONT_AND_BACK,interp(r, lhs.getDiffuse(osg::Material::FRONT),rhs.getDiffuse(osg::Material::FRONT)));
101    if (!material.getDiffuseFrontAndBack())
102        material.setDiffuse(osg::Material::BACK,interp(r, lhs.getDiffuse(osg::Material::BACK),rhs.getDiffuse(osg::Material::BACK)));
103
104    material.setSpecular(osg::Material::FRONT_AND_BACK,interp(r, lhs.getSpecular(osg::Material::FRONT),rhs.getSpecular(osg::Material::FRONT)));
105    if (!material.getSpecularFrontAndBack())
106        material.setSpecular(osg::Material::BACK,interp(r, lhs.getSpecular(osg::Material::BACK),rhs.getSpecular(osg::Material::BACK)));
107
108    material.setEmission(osg::Material::FRONT_AND_BACK,interp(r, lhs.getEmission(osg::Material::FRONT),rhs.getEmission(osg::Material::FRONT)));
109    if (!material.getEmissionFrontAndBack())
110        material.setEmission(osg::Material::BACK,interp(r, lhs.getEmission(osg::Material::BACK),rhs.getEmission(osg::Material::BACK)));
111
112    material.setShininess(osg::Material::FRONT_AND_BACK,interp(r, lhs.getShininess(osg::Material::FRONT),rhs.getShininess(osg::Material::FRONT)));
113    if (!material.getShininessFrontAndBack())
114        material.setShininess(osg::Material::BACK,interp(r, lhs.getShininess(osg::Material::BACK),rhs.getShininess(osg::Material::BACK)));
115}
116
117void AnimationMaterial::read(std::istream& in)
118{
119    while (!in.eof())
120    {
121        double time;
122        osg::Vec4 color;
123        in >> time >> color[0] >> color[1] >> color[2] >> color[3];
124        if(!in.eof())
125        {
126            osg::Material* material = new osg::Material;
127            material->setAmbient(osg::Material::FRONT_AND_BACK,color);
128            material->setDiffuse(osg::Material::FRONT_AND_BACK,color);
129            insert(time,material);
130        }
131    }
132}
133
134void AnimationMaterial::write(std::ostream& fout) const
135{
136    const TimeControlPointMap& tcpm = getTimeControlPointMap();
137    for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin();
138        tcpmitr!=tcpm.end();
139        ++tcpmitr)
140    {
141        fout<<tcpmitr->first<<" "<<tcpmitr->second->getDiffuse(osg::Material::FRONT)<<std::endl;
142    }
143}
144
145bool AnimationMaterial::requiresBlending() const
146{
147    const TimeControlPointMap& tcpm = getTimeControlPointMap();
148    for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin();
149        tcpmitr!=tcpm.end();
150        ++tcpmitr)
151    {
152         if ((tcpmitr->second->getDiffuse(osg::Material::FRONT))[3]!=1.0f) return true;
153    }
154    return false;
155}
156
157
158void AnimationMaterialCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
159{
160    if (_animationMaterial.valid() &&
161        nv->getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR &&
162        nv->getFrameStamp())
163    {
164        double time = nv->getFrameStamp()->getReferenceTime();
165        _latestTime = time;
166
167        if (!_pause)
168        {
169            // Only update _firstTime the first time, when its value is still DBL_MAX
170            if (_firstTime==DBL_MAX)
171            {
172                OSG_INFO<<"AnimationMaterialCallback::operator() resetting _firstTime to "<<time<<std::endl;
173                _firstTime = time;
174            }
175            update(*node);
176
177        }
178    }
179
180    // must call any nested node callbacks and continue subgraph traversal.
181    NodeCallback::traverse(node,nv);
182}
183
184double AnimationMaterialCallback::getAnimationTime() const
185{
186    if (_firstTime==DBL_MAX) return 0.0f;
187    else return ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier;
188}
189
190void AnimationMaterialCallback::update(osg::Node& node)
191{
192    osg::StateSet* stateset = node.getOrCreateStateSet();
193    osg::Material* material =
194        dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
195
196    if (!material)
197    {
198        material = new osg::Material;
199        stateset->setAttribute(material,osg::StateAttribute::OVERRIDE);
200    }
201
202    _animationMaterial->getMaterial(getAnimationTime(),*material);
203}
204
205
206void AnimationMaterialCallback::reset()
207{
208#if 1
209    _firstTime = DBL_MAX;
210    _pauseTime = DBL_MAX;
211#else
212    _firstTime = _latestTime;
213    _pauseTime = _latestTime;
214#endif
215}
216
217void AnimationMaterialCallback::setPause(bool pause)
218{
219    if (_pause==pause)
220    {
221        return;
222    }
223
224    _pause = pause;
225
226    if (_firstTime==DBL_MAX) return;
227
228    if (_pause)
229    {
230        _pauseTime = _latestTime;
231    }
232    else
233    {
234        _firstTime += (_latestTime-_pauseTime);
235    }
236}
Note: See TracBrowser for help on using the browser.