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/AttributeDispatchers>
14 #include <osg/State>
15 #include <osg/Drawable>
16 
17 #include <osg/Notify>
18 #include <osg/io_utils>
19 
20 
21 namespace osg
22 {
23 
24 #if defined(OSG_GLES1_AVAILABLE)
glColor4ubv(const GLubyte * c)25 inline void GL_APIENTRY glColor4ubv(const GLubyte* c) { glColor4ub(c[0], c[1], c[2], c[3]); }
glColor3fv(const GLfloat * c)26 inline void GL_APIENTRY glColor3fv(const GLfloat* c) { glColor4f(c[0], c[1], c[2], 1.0f); }
glColor4fv(const GLfloat * c)27 inline void GL_APIENTRY glColor4fv(const GLfloat* c) { glColor4f(c[0], c[1], c[2], c[3]); }
glColor3dv(const GLdouble * c)28 inline void GL_APIENTRY glColor3dv(const GLdouble* c) { glColor4f(c[0], c[1], c[2], 1.0f); }
glColor4dv(const GLdouble * c)29 inline void GL_APIENTRY glColor4dv(const GLdouble* c) { glColor4f(c[0], c[1], c[2], c[3]); }
30 
glNormal3bv(const GLbyte * n)31 inline void GL_APIENTRY glNormal3bv(const GLbyte* n) { const float div = 1.0f/128.0f; glNormal3f(float(n[0])*div, float(n[1])*div, float(n[3])*div); }
glNormal3sv(const GLshort * n)32 inline void GL_APIENTRY glNormal3sv(const GLshort* n) { const float div = 1.0f/32768.0f; glNormal3f(float(n[0])*div, float(n[1])*div, float(n[3])*div); }
glNormal3fv(const GLfloat * n)33 inline void GL_APIENTRY glNormal3fv(const GLfloat* n) { glNormal3f(n[0], n[1], n[3]); }
glNormal3dv(const GLdouble * n)34 inline void GL_APIENTRY glNormal3dv(const GLdouble* n) { glNormal3f(n[0], n[1], n[3]); }
35 #endif
36 
37 template<typename T>
38 class TemplateAttributeDispatch : public AttributeDispatch
39 {
40     public:
41 
42         typedef void (GL_APIENTRY * F) (const T*);
43 
TemplateAttributeDispatch(F functionPtr,unsigned int stride)44         TemplateAttributeDispatch(F functionPtr, unsigned int stride):
45             _functionPtr(functionPtr), _stride(stride), _array(0) {}
46 
assign(const GLvoid * array)47         virtual void assign(const GLvoid* array)
48         {
49             _array = reinterpret_cast<const T*>(array);
50         }
51 
operator ()(unsigned int pos)52         virtual void operator () (unsigned int pos)
53         {
54             _functionPtr(&(_array[pos*_stride]));
55         }
56 
57         F               _functionPtr;
58         unsigned int    _stride;
59         const T*        _array;
60 };
61 
62 
63 template<typename I, typename T>
64 class TemplateTargetAttributeDispatch : public AttributeDispatch
65 {
66     public:
67 
68         typedef void (GL_APIENTRY * F) (I, const T*);
69 
TemplateTargetAttributeDispatch(I target,F functionPtr,unsigned int stride)70         TemplateTargetAttributeDispatch(I target, F functionPtr, unsigned int stride):
71             _functionPtr(functionPtr), _target(target), _stride(stride), _array(0) {}
72 
assign(const GLvoid * array)73         virtual void assign(const GLvoid* array)
74         {
75             _array = reinterpret_cast<const T*>(array);
76         }
77 
operator ()(unsigned int pos)78         virtual void operator () (unsigned int pos)
79         {
80             _functionPtr(_target, &(_array[pos * _stride]));
81         }
82 
83         F                       _functionPtr;
84         I                       _target;
85         unsigned int            _stride;
86         const T*                _array;
87 };
88 
89 
90 class AttributeDispatchMap
91 {
92 public:
93 
AttributeDispatchMap()94     AttributeDispatchMap() {}
95 
96     template<typename T>
assign(Array::Type type,void (GL_APIENTRY * functionPtr)(const T *),unsigned int stride)97     void assign(Array::Type type, void (GL_APIENTRY *functionPtr) (const T*), unsigned int stride)
98     {
99         if ((unsigned int)type >= _attributeDispatchList.size()) _attributeDispatchList.resize(type+1);
100         _attributeDispatchList[type] = functionPtr ? new TemplateAttributeDispatch<T>(functionPtr, stride) : 0;
101     }
102 
103     template<typename I, typename T>
targetAssign(I target,Array::Type type,void (GL_APIENTRY * functionPtr)(I,const T *),unsigned int stride)104     void targetAssign(I target, Array::Type type, void (GL_APIENTRY *functionPtr) (I, const T*), unsigned int stride)
105     {
106         if ((unsigned int)type >= _attributeDispatchList.size()) _attributeDispatchList.resize(type+1);
107         _attributeDispatchList[type] = functionPtr ? new TemplateTargetAttributeDispatch<I,T>(target, functionPtr, stride) : 0;
108     }
109 
dispatcher(const Array * array)110     AttributeDispatch* dispatcher(const Array* array)
111     {
112         // OSG_NOTICE<<"dispatcher("<<array<<")"<<std::endl;
113 
114         if (!array) return 0;
115 
116         Array::Type type = array->getType();
117         AttributeDispatch* dispatcher = 0;
118 
119         // OSG_NOTICE<<"    array->getType()="<<type<<std::endl;
120         // OSG_NOTICE<<"    _attributeDispatchList.size()="<<_attributeDispatchList.size()<<std::endl;
121 
122         if ((unsigned int)type<_attributeDispatchList.size())
123         {
124             dispatcher = _attributeDispatchList[array->getType()].get();
125         }
126 
127         if (dispatcher)
128         {
129             // OSG_NOTICE<<"   returning dispatcher="<<dispatcher<<std::endl;
130             dispatcher->assign(array->getDataPointer());
131             return dispatcher;
132         }
133         else
134         {
135             // OSG_NOTICE<<"   no dispatcher found"<<std::endl;
136             return 0;
137         }
138     }
139 
140     typedef std::vector< ref_ptr<AttributeDispatch> >  AttributeDispatchList;
141     AttributeDispatchList               _attributeDispatchList;
142 };
143 
AttributeDispatchers()144 AttributeDispatchers::AttributeDispatchers():
145     _initialized(false),
146     _state(0),
147     _normalDispatchers(0),
148     _colorDispatchers(0),
149     _secondaryColorDispatchers(0),
150     _fogCoordDispatchers(0),
151     _useVertexAttribAlias(false)
152 {
153 
154 }
155 
~AttributeDispatchers()156 AttributeDispatchers::~AttributeDispatchers()
157 {
158     delete _normalDispatchers;
159     delete _colorDispatchers;
160     delete _secondaryColorDispatchers;
161     delete _fogCoordDispatchers;
162 
163     for(AttributeDispatchMapList::iterator itr = _vertexAttribDispatchers.begin();
164         itr != _vertexAttribDispatchers.end();
165         ++itr)
166     {
167         delete *itr;
168     }
169 }
170 
setState(osg::State * state)171 void AttributeDispatchers::setState(osg::State* state)
172 {
173     _state = state;
174 }
175 
init()176 void AttributeDispatchers::init()
177 {
178     if (_initialized) return;
179 
180     _initialized = true;
181 
182     _normalDispatchers = new AttributeDispatchMap();
183     _colorDispatchers = new AttributeDispatchMap();
184     _secondaryColorDispatchers  = new AttributeDispatchMap();
185     _fogCoordDispatchers = new AttributeDispatchMap();
186 
187 
188 #ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
189     GLExtensions* extensions = _state->get<GLExtensions>();
190 
191     _normalDispatchers->assign<GLbyte>(Array::Vec3bArrayType, glNormal3bv, 3);
192     _normalDispatchers->assign<GLshort>(Array::Vec3sArrayType, glNormal3sv, 3);
193     _normalDispatchers->assign<GLfloat>(Array::Vec3ArrayType, glNormal3fv, 3);
194     _normalDispatchers->assign<GLdouble>(Array::Vec3dArrayType, glNormal3dv, 3);
195 
196     _colorDispatchers->assign<GLubyte>(Array::Vec4ubArrayType, glColor4ubv, 4);
197     _colorDispatchers->assign<GLfloat>(Array::Vec3ArrayType, glColor3fv, 3);
198     _colorDispatchers->assign<GLfloat>(Array::Vec4ArrayType, glColor4fv, 4);
199     _colorDispatchers->assign<GLdouble>(Array::Vec3dArrayType, glColor3dv, 3);
200     _colorDispatchers->assign<GLdouble>(Array::Vec4dArrayType, glColor4dv, 4);
201 
202     _secondaryColorDispatchers->assign<GLfloat>(Array::Vec3ArrayType, extensions->glSecondaryColor3fv, 3);
203 
204     _fogCoordDispatchers->assign<GLfloat>(Array::FloatArrayType, extensions->glFogCoordfv, 1);
205 #endif
206 
207     // pre allocate.
208     _activeDispatchList.resize(5);
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////////////////////////////
212 //
213 //  With inidices
214 //
215 
normalDispatcher(Array * array)216 AttributeDispatch* AttributeDispatchers::normalDispatcher(Array* array)
217 {
218     return _useVertexAttribAlias ?
219            vertexAttribDispatcher(_state->getNormalAlias()._location, array) :
220            _normalDispatchers->dispatcher(array);
221 }
222 
colorDispatcher(Array * array)223 AttributeDispatch* AttributeDispatchers::colorDispatcher(Array* array)
224 {
225     return _useVertexAttribAlias ?
226            vertexAttribDispatcher(_state->getColorAlias()._location, array) :
227            _colorDispatchers->dispatcher(array);
228 }
229 
secondaryColorDispatcher(Array * array)230 AttributeDispatch* AttributeDispatchers::secondaryColorDispatcher(Array* array)
231 {
232     return _useVertexAttribAlias ?
233            vertexAttribDispatcher(_state->getSecondaryColorAlias()._location, array) :
234            _secondaryColorDispatchers->dispatcher(array);
235 }
236 
fogCoordDispatcher(Array * array)237 AttributeDispatch* AttributeDispatchers::fogCoordDispatcher(Array* array)
238 {
239     return _useVertexAttribAlias ?
240            vertexAttribDispatcher(_state->getFogCoordAlias()._location, array) :
241            _fogCoordDispatchers->dispatcher(array);
242 }
243 
vertexAttribDispatcher(unsigned int unit,Array * array)244 AttributeDispatch* AttributeDispatchers::vertexAttribDispatcher(unsigned int unit, Array* array)
245 {
246     if (unit>=_vertexAttribDispatchers.size()) assignVertexAttribDispatchers(unit);
247     return _vertexAttribDispatchers[unit]->dispatcher(array);
248 }
249 
assignVertexAttribDispatchers(unsigned int unit)250 void AttributeDispatchers::assignVertexAttribDispatchers(unsigned int unit)
251 {
252     GLExtensions* extensions = _state->get<GLExtensions>();
253 
254     for(unsigned int i=_vertexAttribDispatchers.size(); i<=unit; ++i)
255     {
256         _vertexAttribDispatchers.push_back(new AttributeDispatchMap());
257         AttributeDispatchMap& vertexAttribDispatcher = *_vertexAttribDispatchers[i];
258         vertexAttribDispatcher.targetAssign<GLuint, GLfloat>(i, Array::FloatArrayType, extensions->glVertexAttrib1fv, 1);
259         vertexAttribDispatcher.targetAssign<GLuint, GLfloat>(i, Array::Vec2ArrayType, extensions->glVertexAttrib2fv, 2);
260         vertexAttribDispatcher.targetAssign<GLuint, GLfloat>(i, Array::Vec3ArrayType, extensions->glVertexAttrib3fv, 3);
261         vertexAttribDispatcher.targetAssign<GLuint, GLfloat>(i, Array::Vec4ArrayType, extensions->glVertexAttrib4fv, 4);
262     }
263 }
264 
reset()265 void AttributeDispatchers::reset()
266 {
267     if (!_initialized) init();
268 
269     _useVertexAttribAlias = false;
270 
271     _activeDispatchList.clear();
272 }
273 
274 }
275