root/OpenSceneGraph/trunk/src/osgText/FadeText.cpp @ 13041

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
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
11 * OpenSceneGraph Public License for more details.
12*/
13
14
15#include <osgText/FadeText>
16#include <osg/Notify>
17#include <osg/io_utils>
18#include <OpenThreads/Mutex>
19#include <OpenThreads/ScopedLock>
20
21using namespace osgText;
22
23struct FadeTextData : public osg::Referenced
24{
25    FadeTextData(FadeText* fadeText=0):
26        _fadeText(fadeText),
27        _visible(true) {}
28
29    bool operator < (const FadeTextData& rhs) const
30    {
31        return _fadeText < rhs._fadeText;
32    }
33
34    double getNearestZ() const
35    {
36        double nearestZ = _vertices[0].z();
37        if (nearestZ < _vertices[1].z()) nearestZ = _vertices[1].z();
38        if (nearestZ < _vertices[2].z()) nearestZ = _vertices[2].z();
39        if (nearestZ < _vertices[3].z()) nearestZ = _vertices[3].z();
40
41        // OSG_NOTICE<<"getNearestZ()="<<_fadeText->getText().createUTF8EncodedString()<<" "<<nearestZ<<std::endl;
42
43        return nearestZ;
44    }
45
46    FadeText*   _fadeText;
47    osg::Vec3d   _vertices[4];
48    bool        _visible;
49};
50
51struct FadeTextPolytopeData : public FadeTextData, public osg::Polytope
52{
53    FadeTextPolytopeData(FadeTextData& fadeTextData):
54        FadeTextData(fadeTextData)
55    {
56        _referenceVertexList.push_back(_vertices[0]);
57        _referenceVertexList.push_back(_vertices[1]);
58        _referenceVertexList.push_back(_vertices[2]);
59        _referenceVertexList.push_back(_vertices[3]);
60    }
61
62    void addEdgePlane(const osg::Vec3& corner, const osg::Vec3& edge)
63    {
64        osg::Vec3 normal( edge.y(), -edge.x(), 0.0f);
65        normal.normalize();
66
67        add(osg::Plane(normal, corner));
68    }
69
70    void buildPolytope()
71    {
72        osg::Vec3d edge01 = _vertices[1] - _vertices[0];
73        osg::Vec3d edge12 = _vertices[2] - _vertices[1];
74
75        osg::Vec3d normalFrontFace = edge01 ^ edge12;
76        bool needToFlip = normalFrontFace.z()>0.0f;
77
78        normalFrontFace.normalize();
79        add(osg::Plane(normalFrontFace, _vertices[0]));
80
81        add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[0], _vertices[1]));
82        add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[1], _vertices[2]));
83        add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[2], _vertices[3]));
84        add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[3], _vertices[0]));
85
86#if 0
87        OSG_NOTICE<<" normalFrontFace = "<<normalFrontFace<<std::endl;
88        OSG_NOTICE<<" edge01 = "<<edge01<<std::endl;
89        OSG_NOTICE<<" edge12 = "<<edge12<<std::endl;
90        OSG_NOTICE<<" _vertices[0]= "<<_vertices[0]<<std::endl;
91        OSG_NOTICE<<" _vertices[1]= "<<_vertices[1]<<std::endl;
92        OSG_NOTICE<<" _vertices[2]= "<<_vertices[2]<<std::endl;
93        OSG_NOTICE<<" _vertices[3]= "<<_vertices[3]<<std::endl;
94#endif
95
96        if (needToFlip) flip();
97
98#if 0
99        OSG_NOTICE<<"   plane 0 "<< _planeList[0]<<std::endl;
100        OSG_NOTICE<<"   plane 1 "<< _planeList[1]<<std::endl;
101        OSG_NOTICE<<"   plane 2 "<< _planeList[2]<<std::endl;
102        OSG_NOTICE<<"   plane 3 "<< _planeList[3]<<std::endl;
103        OSG_NOTICE<<"   plane 4 "<< _planeList[4]<<std::endl;
104#endif
105
106    }
107
108    inline bool contains(const std::vector<osg::Vec3>& vertices)
109    {
110        for(std::vector<osg::Vec3>::const_iterator itr = vertices.begin();
111            itr != vertices.end();
112            ++itr)
113        {
114            if (osg::Polytope::contains(*itr))
115            {
116                return true;
117            }
118        }
119        return false;
120    }
121
122};
123
124struct FadeTextUserData : public osg::Referenced
125{
126    FadeTextUserData():
127        _frameNumber(0) {}
128
129    typedef std::list<FadeTextData> FadeTextList;
130    unsigned int _frameNumber;
131    FadeTextList _fadeTextInView;
132};
133
134struct GlobalFadeText : public osg::Referenced
135{
136    typedef std::set< osg::ref_ptr<FadeTextUserData> > UserDataSet;
137    typedef std::set<FadeText*> FadeTextSet;
138    typedef std::multimap<double, osg::ref_ptr<FadeTextPolytopeData> > FadeTextPolytopeMap;
139    typedef std::map<osg::View*, UserDataSet> ViewUserDataMap;
140    typedef std::map<osg::View*, FadeTextSet > ViewFadeTextMap;
141
142    GlobalFadeText():
143        _frameNumber(0xffffffff)
144    {
145    }
146
147
148    FadeTextUserData* createNewFadeTextUserData(osg::View* view)
149    {
150        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
151
152        FadeTextUserData* userData = new FadeTextUserData;
153
154        if (!userData)
155        {
156            OSG_NOTICE<<"Memory error, unable to create FadeTextUserData."<<std::endl;
157            return 0;
158        }
159
160        _viewMap[view].insert(userData);
161
162        return userData;
163    }
164
165
166    void update(unsigned int frameNumber)
167    {
168        _frameNumber = frameNumber;
169
170        for(GlobalFadeText::ViewUserDataMap::iterator vitr = _viewMap.begin();
171            vitr != _viewMap.end();
172            ++vitr)
173        {
174
175            osg::View* view = vitr->first;
176
177            FadeTextSet& fadeTextSet = _viewFadeTextMap[view];
178            fadeTextSet.clear();
179
180            FadeTextPolytopeMap fadeTextPolytopeMap;
181
182            for(GlobalFadeText::UserDataSet::iterator uitr = vitr->second.begin();
183                uitr != vitr->second.end();
184                ++uitr)
185            {
186                FadeTextUserData* userData = uitr->get();
187
188                int frameDelta = frameNumber - userData->_frameNumber;
189                if (frameDelta<=1)
190                {
191                    for(FadeTextUserData::FadeTextList::iterator fitr = userData->_fadeTextInView.begin();
192                        fitr != userData->_fadeTextInView.end();
193                        ++fitr)
194                    {
195                        FadeTextData& fadeTextData = *fitr;
196                        if (fadeTextSet.count(fadeTextData._fadeText)==0)
197                        {
198                            fadeTextSet.insert(fadeTextData._fadeText);
199                            fadeTextPolytopeMap.insert(FadeTextPolytopeMap::value_type(
200                                -fadeTextData.getNearestZ(), new FadeTextPolytopeData(fadeTextData)));
201                        }
202                    }
203                }
204            }
205
206            // for each FadeTexPoltopeData
207            //    create polytopes
208            //    test against all FTPD's later in the list
209            //       test all control points on FTPD against each plane of the current polytope
210            //       if all control points removed or outside then discard FTPD and make FT visible = false;
211
212            FadeTextPolytopeMap::iterator outer_itr = fadeTextPolytopeMap.begin();
213            while (outer_itr != fadeTextPolytopeMap.end())
214            {
215                FadeTextPolytopeMap::iterator inner_itr = outer_itr;
216                ++inner_itr;
217
218                if (inner_itr == fadeTextPolytopeMap.end()) break;
219
220                FadeTextPolytopeData& outer_ftpm = *(outer_itr->second);
221                outer_ftpm.buildPolytope();
222
223                // OSG_NOTICE<<"Outer z "<<outer_ftpm.getNearestZ()<<std::endl;
224
225                while(inner_itr != fadeTextPolytopeMap.end())
226                {
227                    FadeTextPolytopeData& inner_ftpm = *(inner_itr->second);
228
229                    // OSG_NOTICE<<"Inner z "<<inner_ftpm.getNearestZ()<<std::endl;
230
231                    if (outer_ftpm.contains(inner_ftpm.getReferenceVertexList()))
232                    {
233                        FadeTextPolytopeMap::iterator erase_itr = inner_itr;
234                        // move to next ftpm
235                        ++inner_itr;
236
237                        fadeTextSet.erase(inner_ftpm._fadeText);
238
239                        // need to remove inner_ftpm as its occluded.
240                        fadeTextPolytopeMap.erase(erase_itr);
241
242                    }
243                    else
244                    {
245                        // move to next ftpm
246                        ++inner_itr;
247                    }
248                }
249
250                ++outer_itr;
251
252            }
253        }
254    }
255
256    inline void updateIfRequired(unsigned int frameNumber)
257    {
258        if (_frameNumber!=frameNumber) update(frameNumber);
259    }
260
261    unsigned int _frameNumber;
262    OpenThreads::Mutex _mutex;
263    ViewUserDataMap _viewMap;
264    ViewFadeTextMap _viewFadeTextMap;
265};
266
267GlobalFadeText* getGlobalFadeText()
268{
269    static osg::ref_ptr<GlobalFadeText> s_globalFadeText = new GlobalFadeText;
270    return s_globalFadeText.get();
271}
272
273struct FadeText::FadeTextUpdateCallback : public osg::Drawable::UpdateCallback
274{
275    FadeTextData _ftd;
276
277    virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
278    {
279        osgText::FadeText* fadeText = dynamic_cast<osgText::FadeText*>(drawable);
280        if (!fadeText) return;
281
282        unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber();
283
284        GlobalFadeText* gft = getGlobalFadeText();
285        gft->updateIfRequired(frameNumber);
286
287        osgText::FadeText::ViewBlendColourMap& vbcm = fadeText->getViewBlendColourMap();
288
289        _ftd._fadeText = fadeText;
290
291        float fadeSpeed = fadeText->getFadeSpeed();
292
293        GlobalFadeText::ViewFadeTextMap& vftm = gft->_viewFadeTextMap;
294        for(GlobalFadeText::ViewFadeTextMap::iterator itr = vftm.begin();
295            itr != vftm.end();
296            ++itr)
297        {
298            osg::View* view = itr->first;
299            GlobalFadeText::FadeTextSet& fadeTextSet = itr->second;
300            bool visible = fadeTextSet.count(fadeText)!=0;
301
302            osg::Vec4& tec = vbcm[view];
303            tec[0] = 1.0f;
304            tec[1] = 1.0f;
305            tec[2] = 1.0f;
306            if (visible)
307            {
308                if (tec[3]<1.0f)
309                {
310                    tec[3] += fadeSpeed;
311                    if (tec[3]>1.0f) tec[3] = 1.0f;
312                }
313
314            }
315            else
316            {
317                if (tec[3]>0.0f)
318                {
319                    tec[3] -= fadeSpeed;
320                    if (tec[3]<0.0f) tec[3] = 0.0f;
321                }
322            }
323        }
324
325    }
326};
327
328
329FadeText::FadeText()
330{
331    init();
332}
333
334FadeText::FadeText(const Text& text,const osg::CopyOp& copyop):
335    Text(text,copyop)
336{
337    init();
338}
339
340void FadeText::init()
341{
342    setDataVariance(osg::Object::DYNAMIC);
343
344    _fadeSpeed = 0.01f;
345    setUpdateCallback(new FadeTextUpdateCallback());
346}
347
348
349
350void FadeText::drawImplementation(osg::RenderInfo& renderInfo) const
351{
352
353    osg::State& state = *renderInfo.getState();
354
355    ViewBlendColourMap::iterator itr = _viewBlendColourMap.find(renderInfo.getView());
356    if (itr != _viewBlendColourMap.end())
357    {
358        Text::drawImplementation(*renderInfo.getState(), itr->second );
359    }
360    else
361    {
362        Text::drawImplementation(*renderInfo.getState(), osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
363    }
364
365
366    // now pass on new details
367
368    FadeTextUserData* userData = dynamic_cast<FadeTextUserData*>(renderInfo.getUserData());
369    if (!userData)
370    {
371        if (renderInfo.getUserData())
372        {
373            OSG_NOTICE<<"Warning user data not of supported type."<<std::endl;
374            return;
375        }
376
377        userData = getGlobalFadeText()->createNewFadeTextUserData(renderInfo.getView());
378
379        if (!userData)
380        {
381            OSG_NOTICE<<"Memory error, unable to create FadeTextUserData."<<std::endl;
382            return;
383        }
384
385        renderInfo.setUserData(userData);
386    }
387
388    unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
389    if (frameNumber != userData->_frameNumber)
390    {
391        // new frame so must reset UserData structure.
392        userData->_frameNumber = frameNumber;
393        userData->_fadeTextInView.clear();
394    }
395
396
397
398    osgText::Text::AutoTransformCache& atc = _autoTransformCache[renderInfo.getContextID()];
399
400    osg::Matrix lmv = atc._matrix;
401    lmv.postMult(state.getModelViewMatrix());
402
403    if (renderInfo.getView() && renderInfo.getView()->getCamera())
404    {
405        // move from camera into the view space.
406        lmv.postMult(state.getInitialInverseViewMatrix());
407        lmv.postMult(renderInfo.getView()->getCamera()->getViewMatrix());
408    }
409
410    FadeTextData ftd(const_cast<osgText::FadeText*>(this));
411
412    ftd._vertices[0].set(osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv);
413    ftd._vertices[1].set(osg::Vec3d(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv);
414    ftd._vertices[2].set(osg::Vec3d(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv);
415    ftd._vertices[3].set(osg::Vec3d(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv);
416
417    userData->_fadeTextInView.push_back(ftd);
418
419}
Note: See TracBrowser for help on using the browser.