root/OpenSceneGraph/trunk/src/osg/State.cpp @ 10926

Revision 10926, 46.8 kB (checked in by robert, 4 years ago)

From Lilith Bryant, "As discussed previously on the users list. Fixes the redundant calls to
glActiveTexture on every State::apply after more than one texunits have been
used.

This is against 2.9.6 (I think SVN head is the same)

Quick Synopsis:

New functions:

State::applyModeOnTexUnit
State::applyAttributeOnTexUnit
State::applyModeMapOnTexUnit
State::applyAttributeMapOnTexUnit
State::applyModeListOnTexUnit
State::applyAttributeListOnTexUnit

All copies of the normal versions, but they also set the active tex unit if
absolutely necessary (i.e. only if they call something OpenGL).

State::apply (*2)
State::applyTextureAttribute

Changed to call the above functions and no longer call setActiveTextureUnit
themselves.

State::setActiveTextureUnit

Made inline, so the benefit of having applyModeOnTexUnit (etc) inline
is retained.
"

  • 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#include <osg/State>
14#include <osg/Texture>
15#include <osg/Notify>
16#include <osg/GLU>
17#include <osg/GLExtensions>
18#include <osg/ApplicationUsage>
19
20#include <sstream>
21
22#ifndef GL_MAX_TEXTURE_COORDS
23#define GL_MAX_TEXTURE_COORDS 0x8871
24#endif
25
26#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
27#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
28#endif
29
30#ifndef GL_MAX_TEXTURE_UNITS
31#define GL_MAX_TEXTURE_UNITS 0x84E2
32#endif
33
34using namespace std;
35using namespace osg;
36
37static ApplicationUsageProxy State_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_ERROR_CHECKING <type>","ONCE_PER_ATTRIBUTE | ON | on enables fine grained checking,  ONCE_PER_FRAME enables coarse grained checking");
38
39State::State():
40    Referenced(true)
41{
42    _graphicsContext = 0;
43    _contextID = 0;
44    _identity = new osg::RefMatrix(); // default RefMatrix constructs to identity.
45    _initialViewMatrix = _identity;
46    _projection = _identity;
47    _modelView = _identity;
48
49    #if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
50        _useModelViewAndProjectionUniforms = true;
51        _useVertexAttributeAliasing = true;
52    #else   
53        _useModelViewAndProjectionUniforms = false;
54        _useVertexAttributeAliasing = false;
55    #endif
56   
57    _modelViewMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewMatrix");
58    _projectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ProjectionMatrix");
59    _modelViewProjectionMatrixUniform = new Uniform(Uniform::FLOAT_MAT4,"osg_ModelViewProjectionMatrix");
60    _normalMatrixUniform = new Uniform(Uniform::FLOAT_MAT3,"osg_NormalMatrix");
61
62    bool compactAliasing = true;
63    if (compactAliasing)
64    {
65        setUpVertexAttribAlias(_vertexAlias,0, "gl_Vertex","osg_Vertex","attribute vec4 ");
66        setUpVertexAttribAlias(_normalAlias, 1, "gl_Normal","osg_Normal","attribute vec3 ");
67        setUpVertexAttribAlias(_colorAlias, 2, "gl_Color","osg_Color","attribute vec4 ");
68
69        _texCoordAliasList.resize(5);
70        for(unsigned int i=0; i<_texCoordAliasList.size(); i++)
71        {
72            std::stringstream gl_MultiTexCoord;
73            std::stringstream osg_MultiTexCoord;
74            gl_MultiTexCoord<<"gl_MultiTexCoord"<<i;
75            osg_MultiTexCoord<<"osg_MultiTexCoord"<<i;
76
77            setUpVertexAttribAlias(_texCoordAliasList[i], 3+i, gl_MultiTexCoord.str(), osg_MultiTexCoord.str(), "attribute vec4 ");
78        }
79
80        setUpVertexAttribAlias(_secondaryColorAlias, 6, "gl_SecondaryColor","osg_SecondaryColor","attribute vec4 ");
81        setUpVertexAttribAlias(_fogCoordAlias, 7, "gl_FogCoord","osg_FogCoord","attribute float ");
82
83    }
84    else
85    {
86        setUpVertexAttribAlias(_vertexAlias,0, "gl_Vertex","osg_Vertex","attribute vec4 ");
87        setUpVertexAttribAlias(_normalAlias, 2, "gl_Normal","osg_Normal","attribute vec3 ");
88        setUpVertexAttribAlias(_colorAlias, 3, "gl_Color","osg_Color","attribute vec4 ");
89        setUpVertexAttribAlias(_secondaryColorAlias, 4, "gl_SecondaryColor","osg_SecondaryColor","attribute vec4 ");
90        setUpVertexAttribAlias(_fogCoordAlias, 5, "gl_FogCoord","osg_FogCoord","attribute float ");
91
92        _texCoordAliasList.resize(8);
93        for(unsigned int i=0; i<_texCoordAliasList.size(); i++)
94        {
95            std::stringstream gl_MultiTexCoord;
96            std::stringstream osg_MultiTexCoord;
97            gl_MultiTexCoord<<"gl_MultiTexCoord"<<i;
98            osg_MultiTexCoord<<"osg_MultiTexCoord"<<i;
99
100            setUpVertexAttribAlias(_texCoordAliasList[i], 8+i, gl_MultiTexCoord.str(), osg_MultiTexCoord.str(), "attribute vec4 ");
101        }
102    }
103
104    _abortRenderingPtr = false;   
105
106    _checkGLErrors = ONCE_PER_FRAME;
107
108    const char* str = getenv("OSG_GL_ERROR_CHECKING");
109    if (str && (strcmp(str,"ONCE_PER_ATTRIBUTE")==0 || strcmp(str,"ON")==0 || strcmp(str,"on")==0))
110    {
111        _checkGLErrors = ONCE_PER_ATTRIBUTE;
112    }
113
114    _currentActiveTextureUnit=0;
115    _currentClientActiveTextureUnit=0;
116
117    _currentVBO = 0;
118    _currentEBO = 0;
119    _currentPBO = 0;
120
121    _isSecondaryColorSupportResolved = false;
122    _isSecondaryColorSupported = false;
123
124    _isFogCoordSupportResolved = false;
125    _isFogCoordSupported = false;
126
127    _isVertexBufferObjectSupportResolved = false;
128    _isVertexBufferObjectSupported = false;
129   
130    _lastAppliedProgramObject = 0;
131
132    _extensionProcsInitialized = false;
133    _glClientActiveTexture = 0;
134    _glActiveTexture = 0;
135    _glFogCoordPointer = 0;
136    _glSecondaryColorPointer = 0;
137    _glVertexAttribPointer = 0;
138    _glEnableVertexAttribArray = 0;
139    _glDisableVertexAttribArray = 0;
140    _glDrawArraysInstanced = 0;
141    _glDrawElementsInstanced = 0;
142
143    _dynamicObjectCount  = 0;
144
145    _glMaxTextureCoords = 1;
146    _glMaxTextureUnits = 1;
147
148    _maxTexturePoolSize = 0;
149    _maxBufferObjectPoolSize = 0;
150
151    _glBeginEndAdapter.setState(this);
152    _arrayDispatchers.setState(this);
153}
154
155State::~State()
156{
157    //_texCoordArrayList.clear();
158
159    //_vertexAttribArrayList.clear();
160
161    // osg::notify(osg::NOTICE)<<"State::~State()"<<this<<std::endl;
162    for(AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.begin();
163        itr != _appliedProgramObjectSet.end();
164        ++itr)
165    {
166        (*itr)->removeObserver(this);
167    }
168}
169
170void State::objectDeleted(void* object)
171{
172    const Program::PerContextProgram* ppcp = reinterpret_cast<const Program::PerContextProgram*>(object);
173    AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.find(ppcp);
174    if (itr != _appliedProgramObjectSet.end())
175    {
176        // osg::notify(osg::NOTICE)<<"Removing _appliedProgramObjectSet entry "<<ppcp<<std::endl;
177        _appliedProgramObjectSet.erase(itr);
178    }
179}
180
181void State::reset()
182{
183
184#if 1
185    for(ModeMap::iterator mitr=_modeMap.begin();
186        mitr!=_modeMap.end();
187        ++mitr)
188    {
189        ModeStack& ms = mitr->second;
190        ms.valueVec.clear();
191        ms.last_applied_value = !ms.global_default_value;
192        ms.changed = true;
193    }       
194#else
195    _modeMap.clear();
196#endif
197
198    _modeMap[GL_DEPTH_TEST].global_default_value = true;
199    _modeMap[GL_DEPTH_TEST].changed = true;
200   
201    // go through all active StateAttribute's, setting to change to force update,
202    // the idea is to leave only the global defaults left.
203    for(AttributeMap::iterator aitr=_attributeMap.begin();
204        aitr!=_attributeMap.end();
205        ++aitr)
206    {
207        AttributeStack& as = aitr->second;
208        as.attributeVec.clear();
209        as.last_applied_attribute = NULL;
210        as.changed = true;
211    }
212   
213    // we can do a straight clear, we arn't interested in GL_DEPTH_TEST defaults in texture modes.
214    for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
215        tmmItr!=_textureModeMapList.end();
216        ++tmmItr)
217    {
218        tmmItr->clear();
219    }
220
221    // empty all the texture attributes as per normal attributes, leaving only the global defaults left.
222    for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
223        tamItr!=_textureAttributeMapList.end();
224        ++tamItr)
225    {
226        AttributeMap& attributeMap = *tamItr;
227        // go through all active StateAttribute's, setting to change to force update.
228        for(AttributeMap::iterator aitr=attributeMap.begin();
229            aitr!=attributeMap.end();
230            ++aitr)
231        {
232            AttributeStack& as = aitr->second;
233            as.attributeVec.clear();
234            as.last_applied_attribute = NULL;
235            as.changed = true;
236        }
237    }
238
239    _stateStateStack.clear();
240   
241    _modelView = _identity;
242    _projection = _identity;
243   
244    dirtyAllVertexArrays();
245   
246#if 0
247    // reset active texture unit values and call OpenGL
248    // note, this OpenGL op precludes the use of State::reset() without a
249    // valid graphics context, therefore the new implementation below
250    // is preferred.
251    setActiveTextureUnit(0);
252#else
253    // reset active texture unit values without calling OpenGL
254    _currentActiveTextureUnit = 0;
255    _currentClientActiveTextureUnit = 0;
256#endif
257   
258    _lastAppliedProgramObject = 0;
259
260    for(AppliedProgramObjectSet::iterator apitr=_appliedProgramObjectSet.begin();
261        apitr!=_appliedProgramObjectSet.end();
262        ++apitr)
263    {
264        (*apitr)->resetAppliedUniforms();
265        (*apitr)->removeObserver(this);
266    }
267   
268    _appliedProgramObjectSet.clear();
269   
270   
271    // what about uniforms??? need to clear them too...
272    // go through all active Unfirom's, setting to change to force update,
273    // the idea is to leave only the global defaults left.
274    for(UniformMap::iterator uitr=_uniformMap.begin();
275        uitr!=_uniformMap.end();
276        ++uitr)
277    {
278        UniformStack& us = uitr->second;
279        us.uniformVec.clear();
280    }
281
282}
283
284void State::setInitialViewMatrix(const osg::RefMatrix* matrix)
285{
286    if (matrix) _initialViewMatrix = matrix;
287    else _initialViewMatrix = _identity;
288
289    _initialInverseViewMatrix.invert(*_initialViewMatrix);
290}
291
292void State::setMaxTexturePoolSize(unsigned int size)
293{
294    _maxTexturePoolSize = size;
295    osg::Texture::getTextureObjectManager(getContextID())->setMaxTexturePoolSize(size);
296    osg::notify(osg::INFO)<<"osg::State::_maxTexturePoolSize="<<_maxTexturePoolSize<<std::endl;
297}
298
299void State::setMaxBufferObjectPoolSize(unsigned int size)
300{
301    _maxBufferObjectPoolSize = size;
302    osg::GLBufferObjectManager::getGLBufferObjectManager(getContextID())->setMaxGLBufferObjectPoolSize(_maxBufferObjectPoolSize);
303    osg::notify(osg::INFO)<<"osg::State::_maxBufferObjectPoolSize="<<_maxBufferObjectPoolSize<<std::endl;
304}
305
306void State::pushStateSet(const StateSet* dstate)
307{
308
309    _stateStateStack.push_back(dstate);
310    if (dstate)
311    {
312
313        pushModeList(_modeMap,dstate->getModeList());
314
315        // iterator through texture modes.       
316        unsigned int unit;
317        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
318        for(unit=0;unit<ds_textureModeList.size();++unit)
319        {
320            pushModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
321        }
322
323        pushAttributeList(_attributeMap,dstate->getAttributeList());
324
325        // iterator through texture attributes.
326        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
327        for(unit=0;unit<ds_textureAttributeList.size();++unit)
328        {
329            pushAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
330        }
331
332        pushUniformList(_uniformMap,dstate->getUniformList());
333    }
334
335    // osg::notify(osg::NOTICE)<<"State::pushStateSet()"<<_stateStateStack.size()<<std::endl;
336}
337
338void State::popAllStateSets()
339{
340    // osg::notify(osg::NOTICE)<<"State::popAllStateSets()"<<_stateStateStack.size()<<std::endl;
341
342    while (!_stateStateStack.empty()) popStateSet();
343   
344    applyProjectionMatrix(0);
345    applyModelViewMatrix(0);
346   
347    _lastAppliedProgramObject = 0;
348}
349
350void State::popStateSet()
351{
352    // osg::notify(osg::NOTICE)<<"State::popStateSet()"<<_stateStateStack.size()<<std::endl;
353
354    if (_stateStateStack.empty()) return;
355   
356   
357    const StateSet* dstate = _stateStateStack.back();
358
359    if (dstate)
360    {
361
362        popModeList(_modeMap,dstate->getModeList());
363
364        // iterator through texture modes.       
365        unsigned int unit;
366        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
367        for(unit=0;unit<ds_textureModeList.size();++unit)
368        {
369            popModeList(getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
370        }
371
372        popAttributeList(_attributeMap,dstate->getAttributeList());
373
374        // iterator through texture attributes.
375        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
376        for(unit=0;unit<ds_textureAttributeList.size();++unit)
377        {
378            popAttributeList(getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
379        }
380
381        popUniformList(_uniformMap,dstate->getUniformList());
382
383    }
384   
385    // remove the top draw state from the stack.
386    _stateStateStack.pop_back();
387}
388
389void State::insertStateSet(unsigned int pos,const StateSet* dstate)
390{
391    StateSetStack tempStack;
392   
393    // first pop the StateSet above the position we need to insert at
394    while (_stateStateStack.size()>pos)
395    {
396        tempStack.push_back(_stateStateStack.back());
397        popStateSet();
398    }
399
400    // push our new stateset
401    pushStateSet(dstate);
402   
403    // push back the original ones
404    for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
405        itr != tempStack.rend();
406        ++itr)
407    {
408        pushStateSet(*itr);
409    }
410
411}
412
413void State::removeStateSet(unsigned int pos)
414{
415    if (pos >= _stateStateStack.size())
416    {
417        osg::notify(osg::NOTICE)<<"Warning: State::removeStateSet("<<pos<<") out of range"<<std::endl;
418        return;
419    }
420   
421    // record the StateSet above the one we intend to remove
422    StateSetStack tempStack;
423    while (_stateStateStack.size()-1>pos)
424    {
425        tempStack.push_back(_stateStateStack.back());
426        popStateSet();
427    }
428
429    // remove the intended StateSet as well   
430    popStateSet();
431
432    // push back the original ones that were above the remove StateSet
433    for(StateSetStack::reverse_iterator itr = tempStack.rbegin();
434        itr != tempStack.rend();
435        ++itr)
436    {
437        pushStateSet(*itr);
438    }
439}
440
441void State::captureCurrentState(StateSet& stateset) const
442{
443    // empty the stateset first.
444    stateset.clear();
445   
446    for(ModeMap::const_iterator mitr=_modeMap.begin();
447        mitr!=_modeMap.end();
448        ++mitr)
449    {
450        // note GLMode = mitr->first
451        const ModeStack& ms = mitr->second;
452        if (!ms.valueVec.empty())
453        {
454            stateset.setMode(mitr->first,ms.valueVec.back());
455        }
456    }       
457
458    for(AttributeMap::const_iterator aitr=_attributeMap.begin();
459        aitr!=_attributeMap.end();
460        ++aitr)
461    {
462        const AttributeStack& as = aitr->second;
463        if (!as.attributeVec.empty())
464        {
465            stateset.setAttribute(const_cast<StateAttribute*>(as.attributeVec.back().first));
466        }
467    }       
468
469}
470
471// revert to using maximum for consistency, maximum should be defined by STLport on VS.
472// // visual studio 6.0 doesn't appear to define maximum?!? So do our own here..
473// template<class T>
474// T mymax(const T& a,const T& b)
475// {
476//     return (((a) > (b)) ? (a) : (b));
477// }
478
479void State::apply(const StateSet* dstate)
480{
481    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply(StateSet*)");
482
483    // equivalent to:
484    //pushStateSet(dstate);
485    //apply();
486    //popStateSet();
487    //return;
488
489    if (dstate)
490    {
491
492        applyModeList(_modeMap,dstate->getModeList());
493        applyAttributeList(_attributeMap,dstate->getAttributeList());
494
495        const StateSet::TextureModeList& ds_textureModeList = dstate->getTextureModeList();
496        const StateSet::TextureAttributeList& ds_textureAttributeList = dstate->getTextureAttributeList();
497
498        unsigned int unit;
499        unsigned int unitMax = maximum(static_cast<unsigned int>(ds_textureModeList.size()),static_cast<unsigned int>(ds_textureAttributeList.size()));
500        unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureModeMapList.size()));
501        unitMax = maximum(static_cast<unsigned int>(unitMax),static_cast<unsigned int>(_textureAttributeMapList.size()));
502        for(unit=0;unit<unitMax;++unit)
503        {
504            if (unit<ds_textureModeList.size()) applyModeListOnTexUnit(unit,getOrCreateTextureModeMap(unit),ds_textureModeList[unit]);
505            else if (unit<_textureModeMapList.size()) applyModeMapOnTexUnit(unit,_textureModeMapList[unit]);
506
507            if (unit<ds_textureAttributeList.size()) applyAttributeListOnTexUnit(unit,getOrCreateTextureAttributeMap(unit),ds_textureAttributeList[unit]);
508            else if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]);
509        }
510
511        applyUniformList(_uniformMap,dstate->getUniformList());
512    }
513    else
514    {
515        // no incoming stateset, so simply apply state.
516        apply();
517    }
518
519    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply(StateSet*)");
520}
521
522void State::apply()
523{
524
525    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("start of State::apply()");
526
527    // go through all active OpenGL modes, enabling/disable where
528    // appropriate.
529    applyModeMap(_modeMap);
530
531    // go through all active StateAttribute's, applying where appropriate.
532    applyAttributeMap(_attributeMap);
533       
534    unsigned int unit;
535    unsigned int unitMax = maximum(_textureModeMapList.size(),_textureAttributeMapList.size());
536    for(unit=0;unit<unitMax;++unit)
537    {
538        if (unit<_textureModeMapList.size()) applyModeMapOnTexUnit(unit,_textureModeMapList[unit]);
539        if (unit<_textureAttributeMapList.size()) applyAttributeMapOnTexUnit(unit,_textureAttributeMapList[unit]);
540    }
541
542    applyUniformMap(_uniformMap);
543
544    if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors("end of State::apply()");
545}
546
547void State::haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
548{
549    haveAppliedMode(_modeMap,mode,value);
550}
551
552void State::haveAppliedMode(StateAttribute::GLMode mode)
553{
554    haveAppliedMode(_modeMap,mode);
555}
556
557void State::haveAppliedAttribute(const StateAttribute* attribute)
558{
559    haveAppliedAttribute(_attributeMap,attribute);
560}
561
562void State::haveAppliedAttribute(StateAttribute::Type type, unsigned int member)
563{
564    haveAppliedAttribute(_attributeMap,type,member);
565}
566
567bool State::getLastAppliedMode(StateAttribute::GLMode mode) const
568{
569    return getLastAppliedMode(_modeMap,mode);
570}
571
572const StateAttribute* State::getLastAppliedAttribute(StateAttribute::Type type, unsigned int member) const
573{
574    return getLastAppliedAttribute(_attributeMap,type,member);
575}
576
577
578void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
579{
580    haveAppliedMode(getOrCreateTextureModeMap(unit),mode,value);
581}
582
583void State::haveAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode)
584{
585    haveAppliedMode(getOrCreateTextureModeMap(unit),mode);
586}
587
588void State::haveAppliedTextureAttribute(unsigned int unit,const StateAttribute* attribute)
589{
590    haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),attribute);
591}
592
593void State::haveAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member)
594{
595    haveAppliedAttribute(getOrCreateTextureAttributeMap(unit),type,member);
596}
597
598bool State::getLastAppliedTextureMode(unsigned int unit,StateAttribute::GLMode mode) const
599{
600    if (unit>=_textureModeMapList.size()) return false;
601    return getLastAppliedMode(_textureModeMapList[unit],mode);
602}
603
604const StateAttribute* State::getLastAppliedTextureAttribute(unsigned int unit,StateAttribute::Type type, unsigned int member) const
605{
606    if (unit>=_textureAttributeMapList.size()) return false;
607    return getLastAppliedAttribute(_textureAttributeMapList[unit],type,member);
608}
609
610
611void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value)
612{
613    ModeStack& ms = modeMap[mode];
614
615    ms.last_applied_value = value & StateAttribute::ON;
616
617    // will need to disable this mode on next apply so set it to changed.
618    ms.changed = true;   
619}
620
621/** mode has been set externally, update state to reflect this setting.*/
622void State::haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode)
623{
624    ModeStack& ms = modeMap[mode];
625
626    // don't know what last applied value is can't apply it.
627    // assume that it has changed by toggle the value of last_applied_value.
628    ms.last_applied_value = !ms.last_applied_value;
629
630    // will need to disable this mode on next apply so set it to changed.
631    ms.changed = true;   
632}
633
634/** attribute has been applied externally, update state to reflect this setting.*/
635void State::haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute)
636{
637    if (attribute)
638    {
639        AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
640
641        as.last_applied_attribute = attribute;
642
643        // will need to update this attribute on next apply so set it to changed.
644        as.changed = true;
645    }
646}
647
648void State::haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member)
649{
650   
651    AttributeMap::iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
652    if (itr!=attributeMap.end())
653    {
654        AttributeStack& as = itr->second;
655        as.last_applied_attribute = 0L;
656
657        // will need to update this attribute on next apply so set it to changed.
658        as.changed = true;
659    }
660}
661
662bool State::getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const
663{
664    ModeMap::const_iterator itr = modeMap.find(mode);
665    if (itr!=modeMap.end())
666    {
667        const ModeStack& ms = itr->second;
668        return ms.last_applied_value;
669    }
670    else
671    {
672        return false;
673    }
674}
675
676const StateAttribute* State::getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const
677{
678    AttributeMap::const_iterator itr = attributeMap.find(StateAttribute::TypeMemberPair(type,member));
679    if (itr!=attributeMap.end())
680    {
681        const AttributeStack& as = itr->second;
682        return as.last_applied_attribute;
683    }
684    else
685    {
686        return NULL;
687    }
688}
689
690void State::dirtyAllModes()
691{
692    for(ModeMap::iterator mitr=_modeMap.begin();
693        mitr!=_modeMap.end();
694        ++mitr)
695    {
696        ModeStack& ms = mitr->second;
697        ms.last_applied_value = !ms.last_applied_value;
698        ms.changed = true;   
699
700    }       
701
702    for(TextureModeMapList::iterator tmmItr=_textureModeMapList.begin();
703        tmmItr!=_textureModeMapList.end();
704        ++tmmItr)
705    {
706        for(ModeMap::iterator mitr=tmmItr->begin();
707            mitr!=tmmItr->end();
708            ++mitr)
709        {
710            ModeStack& ms = mitr->second;
711            ms.last_applied_value = !ms.last_applied_value;
712            ms.changed = true;   
713
714        }       
715    }
716}
717
718void State::dirtyAllAttributes()
719{
720    for(AttributeMap::iterator aitr=_attributeMap.begin();
721        aitr!=_attributeMap.end();
722        ++aitr)
723    {
724        AttributeStack& as = aitr->second;
725        as.last_applied_attribute = 0;
726        as.changed = true;
727    }
728   
729
730    for(TextureAttributeMapList::iterator tamItr=_textureAttributeMapList.begin();
731        tamItr!=_textureAttributeMapList.end();
732        ++tamItr)
733    {
734        AttributeMap& attributeMap = *tamItr;
735        for(AttributeMap::iterator aitr=attributeMap.begin();
736            aitr!=attributeMap.end();
737            ++aitr)
738        {
739            AttributeStack& as = aitr->second;
740            as.last_applied_attribute = 0;
741            as.changed = true;
742        }
743    }
744
745}
746
747
748Polytope State::getViewFrustum() const
749{
750    Polytope cv;
751    cv.setToUnitFrustum();
752    cv.transformProvidingInverse((*_modelView)*(*_projection));
753    return cv;
754}
755
756
757
758void State::disableAllVertexArrays()
759{
760    disableVertexPointer();
761    disableTexCoordPointersAboveAndIncluding(0);
762    disableVertexAttribPointersAboveAndIncluding(0);
763    disableColorPointer();
764    disableFogCoordPointer();
765    disableNormalPointer();
766    disableSecondaryColorPointer();
767}
768
769void State::dirtyAllVertexArrays()
770{
771    dirtyVertexPointer();
772    dirtyTexCoordPointersAboveAndIncluding(0);
773    dirtyVertexAttribPointersAboveAndIncluding(0);
774    dirtyColorPointer();
775    dirtyFogCoordPointer();
776    dirtyNormalPointer();
777    dirtySecondaryColorPointer();
778}
779
780void State::setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer)
781{
782    disableAllVertexArrays();
783
784#if defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
785    glInterleavedArrays( format, stride, pointer);
786#else
787    osg::notify(osg::NOTICE)<<"Warning: State::setInterleavedArrays(..) not implemented."<<std::endl;   
788#endif
789
790    // the crude way, assume that all arrays have been effected so dirty them and
791    // disable them...
792    dirtyAllVertexArrays();
793}
794
795void State::initializeExtensionProcs()
796{
797    if (_extensionProcsInitialized) return;
798
799    setGLExtensionFuncPtr(_glClientActiveTexture,"glClientActiveTexture","glClientActiveTextureARB");
800    setGLExtensionFuncPtr(_glActiveTexture, "glActiveTexture","glActiveTextureARB");
801    setGLExtensionFuncPtr(_glFogCoordPointer, "glFogCoordPointer","glFogCoordPointerEXT");
802    setGLExtensionFuncPtr(_glSecondaryColorPointer, "glSecondaryColorPointer","glSecondaryColorPointerEXT");
803    setGLExtensionFuncPtr(_glVertexAttribPointer, "glVertexAttribPointer","glVertexAttribPointerARB");
804    setGLExtensionFuncPtr(_glEnableVertexAttribArray, "glEnableVertexAttribArray","glEnableVertexAttribArrayARB");
805    setGLExtensionFuncPtr(_glMultiTexCoord4f, "glMultiTexCoord4f","glMultiTexCoord4fARB");
806    setGLExtensionFuncPtr(_glVertexAttrib4f, "glVertexAttrib4f");
807    setGLExtensionFuncPtr(_glVertexAttrib4fv, "glVertexAttrib4fv");
808    setGLExtensionFuncPtr(_glDisableVertexAttribArray, "glDisableVertexAttribArray","glDisableVertexAttribArrayARB");
809    setGLExtensionFuncPtr(_glBindBuffer, "glBindBuffer","glBindBufferARB");
810
811    setGLExtensionFuncPtr(_glDrawArraysInstanced, "glDrawArraysInstanced","glDrawArraysInstancedARB","glDrawArraysInstancedEXT");
812    setGLExtensionFuncPtr(_glDrawElementsInstanced, "glDrawElementsInstanced","glDrawElementsInstancedARB","glDrawElementsInstancedEXT");
813
814    if ( osg::getGLVersionNumber() >= 2.0 || osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_shader") )
815    {
816        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&_glMaxTextureUnits);
817        glGetIntegerv(GL_MAX_TEXTURE_COORDS,&_glMaxTextureCoords);
818    }
819    else if ( osg::getGLVersionNumber() >= 1.3 ||
820                                 osg::isGLExtensionSupported(_contextID,"GL_ARB_multitexture") ||
821                                 osg::isGLExtensionSupported(_contextID,"GL_EXT_multitexture") )
822    {
823        GLint maxTextureUnits;
824        glGetIntegerv(GL_MAX_TEXTURE_UNITS,&maxTextureUnits);
825        _glMaxTextureUnits = maxTextureUnits;
826        _glMaxTextureCoords = maxTextureUnits;
827    }
828    else
829    {
830        _glMaxTextureUnits = 1;
831        _glMaxTextureCoords = 1;
832    }
833
834    _extensionProcsInitialized = true;
835}
836
837bool State::setClientActiveTextureUnit( unsigned int unit )
838{
839    if (unit!=_currentClientActiveTextureUnit)
840    {
841        if (_glClientActiveTexture && unit < (unsigned int)_glMaxTextureCoords)
842        {
843            _glClientActiveTexture(GL_TEXTURE0+unit);
844            _currentClientActiveTextureUnit = unit;
845        }
846        else
847        {
848            return unit==0;
849        }
850    }
851    return true;
852}
853
854void State::setFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
855{
856#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
857    if (_useVertexAttributeAliasing)
858    {
859        setVertexAttribPointer(_fogCoordAlias._location, 1, type, GL_FALSE, stride, ptr);
860    }
861    else
862    {
863        if (_glFogCoordPointer)
864        {
865
866            if (!_fogArray._enabled || _fogArray._dirty)
867            {
868                _fogArray._enabled = true;
869                glEnableClientState(GL_FOG_COORDINATE_ARRAY);
870            }
871            //if (_fogArray._pointer!=ptr || _fogArray._dirty)
872            {
873                _fogArray._pointer=ptr;
874                _glFogCoordPointer( type, stride, ptr );
875            }
876            _fogArray._lazy_disable = false;
877            _fogArray._dirty = false;
878        }
879    }
880#else
881        setVertexAttribPointer(_fogCoordAlias._location, 1, type, GL_FALSE, stride, ptr);
882#endif
883}
884
885void State::setSecondaryColorPointer( GLint size, GLenum type,
886                                      GLsizei stride, const GLvoid *ptr )
887{
888#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
889    if (_useVertexAttributeAliasing)
890    {
891        setVertexAttribPointer(_secondaryColorAlias._location, size, type, GL_FALSE, stride, ptr);
892    }
893    else
894    {
895        if (_glSecondaryColorPointer)
896        {
897            if (!_secondaryColorArray._enabled || _secondaryColorArray._dirty)
898            {
899                _secondaryColorArray._enabled = true;
900                glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
901            }
902            //if (_secondaryColorArray._pointer!=ptr || _secondaryColorArray._dirty)
903            {
904                _secondaryColorArray._pointer=ptr;
905                _glSecondaryColorPointer( size, type, stride, ptr );
906            }
907            _secondaryColorArray._lazy_disable = false;
908            _secondaryColorArray._dirty = false;
909        }
910    }
911#else
912        setVertexAttribPointer(_secondaryColorAlias._location, size, type, GL_FALSE, stride, ptr);
913#endif
914}
915
916/** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..);
917* note, only updates values that change.*/
918void State::setVertexAttribPointer( unsigned int index,
919                                      GLint size, GLenum type, GLboolean normalized,
920                                    GLsizei stride, const GLvoid *ptr )
921{
922    if (_glVertexAttribPointer)
923    {
924        // osg::notify(osg::NOTICE)<<"State::setVertexAttribPointer("<<index<<",...)"<<std::endl;
925
926        if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1);
927        EnabledArrayPair& eap = _vertexAttribArrayList[index];
928
929        if (!eap._enabled || eap._dirty)
930        {
931            eap._enabled = true;
932            // osg::notify(osg::NOTICE)<<"    _glEnableVertexAttribArray( "<<index<<" )"<<std::endl;
933            _glEnableVertexAttribArray( index );
934        }
935        //if (eap._pointer != ptr || eap._normalized!=normalized || eap._dirty)
936        {
937            // osg::notify(osg::NOTICE)<<"    _glVertexAttribPointer( "<<index<<" )"<<std::endl;
938            _glVertexAttribPointer( index, size, type, normalized, stride, ptr );
939            eap._pointer = ptr;
940            eap._normalized = normalized;
941        }
942        eap._lazy_disable = false;
943        eap._dirty = false;
944    }
945}     
946
947/** wrapper around DisableVertexAttribArrayARB(index);
948* note, only updates values that change.*/
949void State::disableVertexAttribPointer( unsigned int index )
950{
951    if (_glDisableVertexAttribArray)
952    {
953        if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1);
954        EnabledArrayPair& eap = _vertexAttribArrayList[index];
955
956        if (eap._enabled || eap._dirty)
957        {
958            eap._enabled = false;
959            eap._dirty = false;
960            // osg::notify(osg::NOTICE)<<"    _glDisableVertexAttribArray( "<<index<<" )"<<std::endl;
961            _glDisableVertexAttribArray( index );
962        }
963    }
964}       
965
966void State::disableVertexAttribPointersAboveAndIncluding( unsigned int index )
967{
968    if (_glDisableVertexAttribArray)
969    {
970        while (index<_vertexAttribArrayList.size())
971        {
972            EnabledArrayPair& eap = _vertexAttribArrayList[index];
973            if (eap._enabled || eap._dirty)
974            {
975                eap._enabled = false;
976                eap._dirty = false;
977                // osg::notify(osg::NOTICE)<<"    State::disableVertexAttribPointersAboveAndIncluding(): _glDisableVertexAttribArray( "<<index<<" )"<<std::endl;
978                _glDisableVertexAttribArray( index );
979            }
980            ++index;
981        }
982    }
983}
984
985void State::lazyDisablingOfVertexAttributes()
986{
987    // osg::notify(osg::NOTICE)<<"lazyDisablingOfVertexAttributes()"<<std::endl;
988    if (!_useVertexAttributeAliasing)
989    {
990        _vertexArray._lazy_disable = true;
991        _normalArray._lazy_disable = true;
992        _colorArray._lazy_disable = true;
993        _secondaryColorArray._lazy_disable = true;
994        _fogArray._lazy_disable = true;
995        for(EnabledTexCoordArrayList::iterator itr = _texCoordArrayList.begin();
996            itr != _texCoordArrayList.end();
997            ++itr)
998        {
999            itr->_lazy_disable = true;
1000        }
1001    }
1002
1003    for(EnabledVertexAttribArrayList::iterator itr = _vertexAttribArrayList.begin();
1004        itr != _vertexAttribArrayList.end();
1005        ++itr)
1006    {
1007        itr->_lazy_disable = true;
1008    }
1009}
1010
1011void State::applyDisablingOfVertexAttributes()
1012{
1013    //osg::notify(osg::NOTICE)<<"start of applyDisablingOfVertexAttributes()"<<std::endl;
1014    if (!_useVertexAttributeAliasing)
1015    {
1016        if (_vertexArray._lazy_disable) disableVertexPointer();
1017        if (_normalArray._lazy_disable) disableNormalPointer();
1018        if (_colorArray._lazy_disable) disableColorPointer();
1019        if (_secondaryColorArray._lazy_disable) disableSecondaryColorPointer();
1020        if (_fogArray._lazy_disable) disableFogCoordPointer();
1021        for(unsigned int i=0; i<_texCoordArrayList.size(); ++i)
1022        {
1023            if (_texCoordArrayList[i]._lazy_disable) disableTexCoordPointer(i);
1024        }
1025    }
1026    for(unsigned int i=0; i<_vertexAttribArrayList.size(); ++i)
1027    {
1028        if (_vertexAttribArrayList[i]._lazy_disable) disableVertexAttribPointer(i);
1029    }
1030    // osg::notify(osg::NOTICE)<<"end of applyDisablingOfVertexAttributes()"<<std::endl;
1031}
1032
1033
1034bool State::computeSecondaryColorSupported() const
1035{
1036    _isSecondaryColorSupportResolved = true;
1037    _isSecondaryColorSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_secondary_color");
1038    return _isSecondaryColorSupported;
1039}
1040
1041bool State::computeFogCoordSupported() const
1042{
1043    _isFogCoordSupportResolved = true;
1044    _isFogCoordSupported = osg::isGLExtensionSupported(_contextID,"GL_EXT_fog_coord");
1045    return _isFogCoordSupported;
1046}
1047
1048bool State::computeVertexBufferObjectSupported() const
1049{
1050    _isVertexBufferObjectSupportResolved = true;
1051    _isVertexBufferObjectSupported = OSG_GLES2_FEATURES || OSG_GL3_FEATURES || osg::isGLExtensionSupported(_contextID,"GL_ARB_vertex_buffer_object");
1052    return _isVertexBufferObjectSupported;
1053}
1054
1055bool State::checkGLErrors(const char* str) const
1056{
1057    GLenum errorNo = glGetError();
1058    if (errorNo!=GL_NO_ERROR)
1059    {
1060#ifdef OSG_GLU_AVAILABLE
1061        const char* error = (char*)gluErrorString(errorNo);
1062        if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '" << error<<"'";
1063        else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
1064#else
1065            switch(errorNo)
1066            {
1067                case(GL_INVALID_ENUM):
1068                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_ENUM";
1069                    break;
1070                case(GL_INVALID_VALUE):
1071                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_VALUE";
1072                    break;
1073                case(GL_INVALID_OPERATION):
1074                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_OPERATION";
1075                    break;
1076                case(GL_OUT_OF_MEMORY):
1077                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_OUT_OF_MEMORY";
1078                    break;
1079                default:
1080                    osg::notify(WARN)<<"Warning: detected OpenGL error number 0x" << std::hex << errorNo << std::dec;
1081                    break;
1082            }
1083#endif
1084        if (str) osg::notify(WARN)<<" at "<<str<< std::endl;
1085        else     osg::notify(WARN)<<" in osg::State."<< std::endl;
1086
1087        return true;
1088    }
1089    return false;
1090}
1091
1092bool State::checkGLErrors(StateAttribute::GLMode mode) const
1093{
1094    GLenum errorNo = glGetError();
1095    if (errorNo!=GL_NO_ERROR)
1096    {
1097        #ifdef OSG_GLU_AVAILABLE
1098            const char* error = (char*)gluErrorString(errorNo);
1099            if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1100            else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1101        #else
1102            switch(errorNo)
1103            {
1104                case(GL_INVALID_ENUM):
1105                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_ENUM after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1106                    break;
1107                case(GL_INVALID_VALUE):
1108                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_VALUE after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1109                    break;
1110                case(GL_INVALID_OPERATION):
1111                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_OPERATION after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1112                    break;
1113                case(GL_OUT_OF_MEMORY):
1114                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_OUT_OF_MEMORY after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1115                    break;
1116                default:
1117                    osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying GLMode 0x"<<hex<<mode<<dec<< std::endl;
1118                    break;
1119            }
1120        #endif
1121        return true;
1122    }
1123    return false;
1124}
1125
1126bool State::checkGLErrors(const StateAttribute* attribute) const
1127{
1128    GLenum errorNo = glGetError();
1129    if (errorNo!=GL_NO_ERROR)
1130    {
1131        #ifdef OSG_GLU_AVAILABLE
1132            const char* error = (char*)gluErrorString(errorNo);
1133            if (error) osg::notify(WARN)<<"Warning: detected OpenGL error '"<< error <<"' after applying attribute "<<attribute->className()<<" "<<attribute<< std::endl;
1134            else       osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1135        #else
1136            switch(errorNo)
1137            {
1138                case(GL_INVALID_ENUM):
1139                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_ENUM after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1140                    break;
1141                case(GL_INVALID_VALUE):
1142                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_VALUE after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1143                    break;
1144                case(GL_INVALID_OPERATION):
1145                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_INVALID_OPERATION after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1146                    break;
1147                case(GL_OUT_OF_MEMORY):
1148                    osg::notify(WARN)<<"Warning: detected OpenGL error GL_OUT_OF_MEMORY after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1149                    break;
1150                default:
1151                    osg::notify(WARN)<<"Warning: detected OpenGL error number 0x"<< std::hex << errorNo <<" after applying attribute "<<attribute->className()<<" "<<attribute<< std::dec << std::endl;
1152                    break;
1153            }
1154        #endif
1155
1156        return true;
1157    }
1158    return false;
1159}
1160
1161
1162void State::applyModelViewAndProjectionUniformsIfRequired()
1163{
1164    if (!_lastAppliedProgramObject) return;
1165
1166    if (_modelViewMatrixUniform.valid()) _lastAppliedProgramObject->apply(*_modelViewMatrixUniform);
1167    if (_projectionMatrixUniform) _lastAppliedProgramObject->apply(*_projectionMatrixUniform);
1168    if (_modelViewProjectionMatrixUniform) _lastAppliedProgramObject->apply(*_modelViewProjectionMatrixUniform);
1169    if (_normalMatrixUniform) _lastAppliedProgramObject->apply(*_normalMatrixUniform);
1170}
1171
1172namespace State_Utils
1173{
1174    bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
1175    {
1176        bool replacedStr = false;
1177        std::string::size_type pos = 0;
1178        while((pos=str.find(original_phrase, pos))!=std::string::npos)
1179        {
1180            std::string::size_type endOfPhrasePos = pos+original_phrase.size();
1181            if (endOfPhrasePos<str.size())
1182            {
1183                char c = str[endOfPhrasePos];
1184                if ((c>='0' && c<='9') ||
1185                    (c>='a' && c<='z') ||
1186                    (c>='A' && c<='Z'))
1187                {
1188                    pos = endOfPhrasePos;
1189                    continue;
1190                }
1191            }
1192
1193            replacedStr = true;
1194            str.replace(pos, original_phrase.size(), new_phrase);
1195        }
1196        return replacedStr;
1197    }
1198
1199    void replaceAndInsertDeclaration(std::string& source, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix)
1200    {
1201        if (replace(source, originalStr, newStr))
1202        {
1203            source.insert(0, declarationPrefix + newStr + std::string(";\n"));
1204        }
1205    }
1206}
1207
1208bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
1209{
1210    osg::notify(osg::NOTICE)<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
1211
1212    osg::notify(osg::NOTICE)<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
1213
1214    // replace ftransform as it only works with built-ins
1215    State_Utils::replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex");
1216
1217    State_Utils::replaceAndInsertDeclaration(source, "gl_Normal", "osg_Normal", "attribute vec3 ");
1218    State_Utils::replaceAndInsertDeclaration(source, "gl_Vertex", "osg_Vertex", "attribute vec4 ");
1219    State_Utils::replaceAndInsertDeclaration(source, "gl_Color", "osg_Color", "attribute vec4 ");
1220    State_Utils::replaceAndInsertDeclaration(source, "gl_SecondaryColor", "osg_SecondaryColor", "attribute vec4 ");
1221    State_Utils::replaceAndInsertDeclaration(source, "gl_FogCoord", "osg_FogCoord", "attribute float ");
1222
1223    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord0", "osg_MultiTexCoord0", "attribute vec4 ");
1224    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord1", "osg_MultiTexCoord1", "attribute vec4 ");
1225    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord2", "osg_MultiTexCoord2", "attribute vec4 ");
1226    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord3", "osg_MultiTexCoord3", "attribute vec4 ");
1227    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord4", "osg_MultiTexCoord4", "attribute vec4 ");
1228    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord5", "osg_MultiTexCoord5", "attribute vec4 ");
1229    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord6", "osg_MultiTexCoord6", "attribute vec4 ");
1230    State_Utils::replaceAndInsertDeclaration(source, "gl_MultiTexCoord7", "osg_MultiTexCoord7", "attribute vec4 ");
1231
1232    // replace built in uniform
1233    State_Utils::replaceAndInsertDeclaration(source, "gl_ModelViewMatrix", "osg_ModelViewMatrix", "uniform mat4 ");
1234    State_Utils::replaceAndInsertDeclaration(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform mat4 ");
1235    State_Utils::replaceAndInsertDeclaration(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform mat4 ");
1236    State_Utils::replaceAndInsertDeclaration(source, "gl_NormalMatrix", "osg_NormalMatrix", "uniform mat3 ");
1237
1238    osg::notify(osg::NOTICE)<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
1239
1240    return true;
1241}
1242
1243void State::setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration)
1244{
1245    alias = VertexAttribAlias(location, glName, osgName, declaration);
1246    _attributeBindingList[osgName] = location;
1247}
1248
1249void State::applyProjectionMatrix(const osg::RefMatrix* matrix)
1250{
1251    if (_projection!=matrix)
1252    {
1253        if (matrix)
1254        {
1255            _projection=matrix;
1256        }
1257        else
1258        {
1259            _projection=_identity;
1260        }
1261
1262        if (_useModelViewAndProjectionUniforms)
1263        {
1264            if (_projectionMatrixUniform.valid()) _projectionMatrixUniform->set(*_projection);
1265            updateModelViewAndProjectionMatrixUniforms();
1266        }
1267#ifdef OSG_GL_MATRICES_AVAILABLE
1268        glMatrixMode( GL_PROJECTION );
1269            glLoadMatrix(_projection->ptr());
1270        glMatrixMode( GL_MODELVIEW );
1271#endif
1272    }
1273}
1274
1275void State::applyModelViewMatrix(const osg::RefMatrix* matrix)
1276{
1277    if (_modelView!=matrix)
1278    {
1279        if (matrix)
1280        {
1281            _modelView=matrix;
1282        }
1283        else
1284        {
1285            _modelView=_identity;
1286        }
1287
1288        if (_useModelViewAndProjectionUniforms)
1289        {
1290            if (_modelViewMatrixUniform.valid()) _modelViewMatrixUniform->set(*_modelView);
1291            updateModelViewAndProjectionMatrixUniforms();
1292        }
1293
1294#ifdef OSG_GL_MATRICES_AVAILABLE
1295        glLoadMatrix(_modelView->ptr());
1296#endif
1297    }
1298}
1299
1300#include <osg/io_utils>
1301
1302void State::updateModelViewAndProjectionMatrixUniforms()
1303{
1304    if (_modelViewProjectionMatrixUniform.valid()) _modelViewProjectionMatrixUniform->set((*_modelView) * (*_projection));
1305    if (_normalMatrixUniform.valid())
1306    {
1307        Matrix mv(*_modelView);
1308        mv.setTrans(0.0, 0.0, 0.0);
1309
1310        Matrix matrix;
1311        matrix.invert(mv);
1312
1313        Matrix3 normalMatrix(matrix(0,0), matrix(1,0), matrix(2,0),
1314                             matrix(0,1), matrix(1,1), matrix(2,1),
1315                             matrix(0,2), matrix(1,2), matrix(2,2));
1316
1317        _normalMatrixUniform->set(normalMatrix);
1318    }
1319}
1320
1321void State::drawQuads(GLint first, GLsizei count, GLsizei primCount)
1322{
1323    // osg::notify(osg::NOTICE)<<"State::drawQuads("<<first<<", "<<count<<")"<<std::endl;
1324   
1325    unsigned int array = first % 4;
1326    unsigned int offsetFirst = ((first-array) / 4) * 6;
1327    unsigned int numQuads = (count/4);
1328    unsigned int numIndices = numQuads * 6;
1329    unsigned int endOfIndices = offsetFirst+numIndices;
1330    Indices& indices = _quadIndices[array];
1331    if (endOfIndices>65536)
1332    {
1333        osg::notify(osg::NOTICE)<<"Warning: State::drawQuads("<<first<<", "<<count<<") too large handle in remapping to ushort glDrawElements."<<std::endl;
1334        endOfIndices = 65536;
1335    }
1336   
1337    if (endOfIndices >= indices.size())
1338    {
1339        // we need to expand the _indexArray to be big enough to cope with all the quads required.
1340        unsigned int numExistingQuads = indices.size()/6;
1341        unsigned int numRequiredQuads = endOfIndices/6;
1342        indices.reserve(endOfIndices);
1343        for(unsigned int i=numExistingQuads; i<numRequiredQuads; ++i)
1344        {
1345            unsigned int base = i*4 + array;
1346            indices.push_back(base);
1347            indices.push_back(base+1);
1348            indices.push_back(base+3);
1349           
1350            indices.push_back(base+1);
1351            indices.push_back(base+2);
1352            indices.push_back(base+3);
1353           
1354            // osg::notify(osg::NOTICE)<<"   adding quad indices ("<<base<<")"<<std::endl;
1355        }
1356    }
1357
1358    // if (array!=0) return;
1359
1360    // osg::notify(osg::NOTICE)<<"  glDrawElements(GL_TRIANGLES, "<<numIndices<<", GL_UNSIGNED_SHORT, "<<&(indices[base])<<")"<<std::endl;
1361    glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, &(indices[offsetFirst]), primCount);
1362}
Note: See TracBrowser for help on using the browser.