root/OpenSceneGraph/trunk/src/osgSim/ImpostorSprite.cpp @ 13041

Revision 13041, 8.0 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#if defined(_MSC_VER)
14    #pragma warning( disable : 4786 )
15#endif
16
17#include <stdio.h>
18#include <math.h>
19#include <float.h>
20
21#include <osg/Geometry>
22#include <osg/Texture2D>
23#include <osg/TexEnv>
24#include <osg/AlphaFunc>
25#include <osg/Notify>
26
27#include <osgSim/ImpostorSprite>
28
29using namespace osg;
30using namespace osgSim;
31
32ImpostorSprite::ImpostorSprite():
33    _parent(0),
34    _ism(0),
35    _previous(0),
36    _next(0),
37    _lastFrameUsed(osg::UNINITIALIZED_FRAME_NUMBER),
38    _texture(0),
39    _s(0),
40    _t(0)
41{
42    // don't use display list since we will be updating the geometry.
43    setUseDisplayList(false);
44    _color.set(1.0f, 1.0f, 1.0f, 1.0f );
45}
46
47ImpostorSprite::ImpostorSprite(const ImpostorSprite&):
48    osg::Drawable(),
49    _parent(0),
50    _ism(0),
51    _previous(0),
52    _next(0),
53    _lastFrameUsed(osg::UNINITIALIZED_FRAME_NUMBER),
54    _texture(0),
55    _s(0),
56    _t(0)
57{
58    setUseDisplayList(false);
59    _color.set(1.0f, 1.0f, 1.0f, 1.0f );
60}
61
62ImpostorSprite::~ImpostorSprite()
63{
64    if (_ism)
65    {
66        _ism->remove(this);
67    }
68}
69
70float ImpostorSprite::calcPixelError(const osg::Matrix& MVPW) const
71{
72    // find the maximum screen space pixel error between the control coords and the quad coners.
73    float max_error_sqrd = 0.0f;
74
75    for(int i=0;i<4;++i)
76    {
77
78        osg::Vec3 projected_coord = _coords[i]*MVPW;
79        osg::Vec3 projected_control = _controlcoords[i]*MVPW;
80
81        float dx = (projected_coord.x()-projected_control.x());
82        float dy = (projected_coord.y()-projected_control.y());
83
84        float error_sqrd = dx*dx+dy*dy;
85
86        if (error_sqrd > max_error_sqrd) max_error_sqrd = error_sqrd;
87
88    }
89
90    return sqrtf(max_error_sqrd);
91}
92void ImpostorSprite::drawImplementation(osg::RenderInfo& renderInfo) const
93{
94    osg::GLBeginEndAdapter& gl = (renderInfo.getState()->getGLBeginEndAdapter());
95
96    // when the tex env is set to REPLACE, and the
97    // texture is set up correctly the color has no effect.
98    gl.Color4fv( _color.ptr() );
99
100    gl.Begin( GL_QUADS );
101
102    gl.TexCoord2fv( (GLfloat *)&_texcoords[0] );
103    gl.Vertex3fv( (GLfloat *)&_coords[0] );
104
105    gl.TexCoord2fv( (GLfloat *)&_texcoords[1] );
106    gl.Vertex3fv( (GLfloat *)&_coords[1] );
107
108    gl.TexCoord2fv( (GLfloat *)&_texcoords[2] );
109    gl.Vertex3fv( (GLfloat *)&_coords[2] );
110
111    gl.TexCoord2fv( (GLfloat *)&_texcoords[3] );
112    gl.Vertex3fv( (GLfloat *)&_coords[3] );
113
114    gl.End();
115}
116
117osg::BoundingBox ImpostorSprite::computeBound() const
118{
119    osg::BoundingBox bbox;
120    bbox.expandBy(_coords[0]);
121    bbox.expandBy(_coords[1]);
122    bbox.expandBy(_coords[2]);
123    bbox.expandBy(_coords[3]);
124
125    if (!bbox.valid())
126    {
127        OSG_WARN << "******* ImpostorSprite::computeBound() problem"<<std::endl;
128    }
129
130    return bbox;
131}
132
133void ImpostorSprite::setTexture(osg::Texture2D* tex,int s,int t)
134{
135    _texture = tex;
136    _s = s;
137    _t = t;
138}
139
140
141void ImpostorSprite::accept(AttributeFunctor& af)
142{
143    af.apply(VERTICES,4,_coords);
144    af.apply(TEXTURE_COORDS_0,4,_texcoords);
145}
146
147void ImpostorSprite::accept(ConstAttributeFunctor& af) const
148{
149    af.apply(VERTICES,4,_coords);
150    af.apply(TEXTURE_COORDS_0,4,_texcoords);
151}
152
153void ImpostorSprite::accept(osg::PrimitiveFunctor& functor) const
154{
155    functor.setVertexArray(4,_coords);
156    functor.drawArrays( GL_QUADS, 0, 4);
157
158}
159
160
161///////////////////////////////////////////////////////////////////////////
162// Helper class for managing the reuse of ImpostorSprite resources.
163///////////////////////////////////////////////////////////////////////////
164
165ImpostorSpriteManager::ImpostorSpriteManager():
166    _first(NULL),
167    _last(NULL)
168{
169    _texenv = new osg::TexEnv;
170    _texenv->setMode(osg::TexEnv::REPLACE);
171
172    _alphafunc = new osg::AlphaFunc;
173    _alphafunc->setFunction( osg::AlphaFunc::GREATER, 0.000f );
174
175    _reuseStateSetIndex = 0;
176}
177
178
179ImpostorSpriteManager::~ImpostorSpriteManager()
180{
181    while (_first)
182    {
183        ImpostorSprite* next = _first->_next;
184        _first->_ism = NULL;
185        _first->_previous = NULL;
186        _first->_next = NULL;
187        _first = next;
188    }
189
190}
191
192void ImpostorSpriteManager::push_back(ImpostorSprite* is)
193{
194    if (is==NULL || is==_last) return;
195
196    // remove entry for exisiting position in linked list
197    // if it is already inserted.
198    if (is->_previous)
199    {
200        (is->_previous)->_next = is->_next;
201    }
202
203    if (is->_next)
204    {
205        (is->_next)->_previous = is->_previous;
206    }
207
208    if (_first==is) _first = is->_next;
209
210    if (empty())
211    {
212        _first = is;
213        _last = is;
214        is->_ism = this;
215        is->_previous = NULL;
216        is->_next = NULL;
217    }
218    else
219    {
220
221        // now add the element into the list.
222        ImpostorSprite* previous_last = _last;
223        previous_last->_next = is;
224        _last = is;
225        _last->_ism = this;
226        _last->_previous = previous_last;
227        _last->_next = NULL;
228    }
229}
230
231void ImpostorSpriteManager::remove(ImpostorSprite* is)
232{
233    if (is==NULL) return;
234
235    // remove entry for exisiting position in linked list
236    // if it is already inserted.
237    if (is->_previous)
238    {
239        (is->_previous)->_next = is->_next;
240    }
241
242    if (is->_next)
243    {
244        (is->_next)->_previous = is->_previous;
245    }
246
247    if (_first==is) _first = is->_next;
248    if (_last==is) _last = is->_previous;
249}
250
251ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,unsigned int frameNumber)
252{
253    if (!empty())
254    {
255
256        // search for a valid impostor to reuse.
257        ImpostorSprite* curr = _first;
258        while (curr)
259        {
260            if (curr->getLastFrameUsed()<=frameNumber &&
261                curr->s()==s &&
262                curr->t()==t)
263            {
264                push_back(curr);
265                return curr;
266            }
267            else
268            {
269                curr = curr->_next;
270            }
271        }
272
273    }
274
275    // creating new impostor sprite.
276
277
278    osg::StateSet* stateset = new osg::StateSet;
279
280    stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
281    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
282    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
283
284    stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
285
286    stateset->setAttributeAndModes( _alphafunc.get(), osg::StateAttribute::ON );
287
288    osg::Texture2D* texture = new osg::Texture2D;
289    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
290    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
291
292    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
293    stateset->setTextureAttribute(0,_texenv.get());
294
295/*
296    TexEnv* texenv = new TexEnv;
297    texenv->setMode(TexEnv::REPLACE);
298    stateset->setAttribute(texenv);
299
300    AlphaFunc* alphafunc = new osg::AlphaFunc;
301    alphafunc->setFunction( osg::AlphaFunc::GREATER, 0.000f );
302    stateset->setAttributeAndModes( alphafunc, osg::StateAttribute::ON );
303*/
304
305
306    //    stateset->setMode( GL_ALPHA_TEST, osg::StateAttribute::OFF );
307
308    ImpostorSprite* is = new ImpostorSprite;
309    is->setStateSet(stateset);
310    is->setTexture(texture,s,t);
311
312    push_back(is);
313
314    return is;
315
316}
317
318osg::StateSet* ImpostorSpriteManager::createOrReuseStateSet()
319{
320    if (_reuseStateSetIndex<_stateSetList.size())
321    {
322        return _stateSetList[_reuseStateSetIndex++].get();
323    }
324    _stateSetList.push_back(new osg::StateSet);
325    _reuseStateSetIndex=_stateSetList.size();
326    return _stateSetList.back().get();
327}
328
329void ImpostorSpriteManager::reset()
330{
331    _reuseStateSetIndex = 0;
332}
Note: See TracBrowser for help on using the browser.