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/PrimitiveSet>
14 #include <osg/BufferObject>
15 #include <osg/State>
16 #include <osg/Notify>
17 
18 using namespace osg;
19 
20 #define VOA_NOTICE OSG_INFO
21 //#define VOA_NOTICE OSG_NOTICE
22 
23 ////////////////////////////////////////////////////////////////////////////////////////////////////////
24 //
25 // PrimitiveSet
26 //
getNumPrimitives() const27 unsigned int PrimitiveSet::getNumPrimitives() const
28 {
29     switch(_mode)
30     {
31         case(POINTS): return getNumIndices();
32         case(LINES): return getNumIndices()/2;
33         case(TRIANGLES): return getNumIndices()/3;
34         case(QUADS): return getNumIndices()/4;
35         case(LINE_STRIP):
36         case(LINE_LOOP):
37         case(TRIANGLE_STRIP):
38         case(TRIANGLE_FAN):
39         case(QUAD_STRIP):
40         case(PATCHES):
41         case(POLYGON): return (getNumIndices()>0) ? 1 : 0;
42     }
43     return 0;
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////////////////////////////
47 //
48 // DrawArray
49 //
draw(State & state,bool) const50 void DrawArrays::draw(State& state, bool) const
51 {
52 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
53     GLenum mode = _mode;
54     if (_mode==GL_QUADS)
55     {
56         state.drawQuads(_first, _count, _numInstances);
57         return;
58     }
59     else if (mode==GL_POLYGON)
60     {
61         mode = GL_TRIANGLE_FAN;
62     }
63     else if (mode==GL_QUAD_STRIP)
64     {
65         mode = GL_TRIANGLE_STRIP;
66     }
67 
68     if (_numInstances>=1) state.glDrawArraysInstanced(mode,_first,_count, _numInstances);
69     else glDrawArrays(mode,_first,_count);
70 #else
71     if (_numInstances>=1) state.glDrawArraysInstanced(_mode,_first,_count, _numInstances);
72     else glDrawArrays(_mode,_first,_count);
73 #endif
74 }
75 
accept(PrimitiveFunctor & functor) const76 void DrawArrays::accept(PrimitiveFunctor& functor) const
77 {
78     functor.drawArrays(_mode,_first,_count);
79 }
80 
accept(PrimitiveIndexFunctor & functor) const81 void DrawArrays::accept(PrimitiveIndexFunctor& functor) const
82 {
83     functor.drawArrays(_mode,_first,_count);
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////////////////////////////
87 //
88 // DrawArrayLengths
89 //
getNumPrimitives() const90 unsigned int DrawArrayLengths::getNumPrimitives() const
91 {
92     switch(_mode)
93     {
94         case(POINTS): return getNumIndices();
95         case(LINES): return getNumIndices()/2;
96         case(TRIANGLES): return getNumIndices()/3;
97         case(QUADS): return getNumIndices()/4;
98         case(LINE_STRIP):
99         case(LINE_LOOP):
100         case(TRIANGLE_STRIP):
101         case(TRIANGLE_FAN):
102         case(QUAD_STRIP):
103         case(PATCHES):
104         case(POLYGON): return size();
105     }
106     return 0;
107 }
108 
draw(State & state,bool) const109 void DrawArrayLengths::draw(State& state, bool) const
110 {
111     GLenum mode = _mode;
112     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
113         if (_mode==GL_QUADS)
114         {
115             GLint first = _first;
116             for(vector_type::const_iterator itr=begin();
117                 itr!=end();
118                 ++itr)
119             {
120                 state.drawQuads(first, *itr, _numInstances);
121                 first += *itr;
122             }
123 
124             return;
125         }
126         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
127         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
128     #endif
129 
130     GLint first = _first;
131     for(vector_type::const_iterator itr=begin();
132         itr!=end();
133         ++itr)
134     {
135         if (_numInstances>=1) state.glDrawArraysInstanced(mode,first,*itr,_numInstances);
136         else glDrawArrays(mode,first,*itr);
137         first += *itr;
138     }
139 
140 }
141 
accept(PrimitiveFunctor & functor) const142 void DrawArrayLengths::accept(PrimitiveFunctor& functor) const
143 {
144     GLint first = _first;
145     for(vector_type::const_iterator itr=begin();
146         itr!=end();
147         ++itr)
148     {
149         functor.drawArrays(_mode,first,*itr);
150         first += *itr;
151     }
152 }
153 
accept(PrimitiveIndexFunctor & functor) const154 void DrawArrayLengths::accept(PrimitiveIndexFunctor& functor) const
155 {
156     GLint first = _first;
157     for(vector_type::const_iterator itr=begin();
158         itr!=end();
159         ++itr)
160     {
161         functor.drawArrays(_mode,first,*itr);
162         first += *itr;
163     }
164 }
165 
getNumIndices() const166 unsigned int DrawArrayLengths::getNumIndices() const
167 {
168     unsigned int count = 0;
169     for(vector_type::const_iterator itr=begin();
170         itr!=end();
171         ++itr)
172     {
173         count += *itr;
174     }
175     return count;
176 }
177 
178 
179 ////////////////////////////////////////////////////////////////////////////////////////////////////////
180 //
181 // DrawElementsUByte
182 //
~DrawElementsUByte()183 DrawElementsUByte::~DrawElementsUByte()
184 {
185     releaseGLObjects();
186 }
187 
draw(State & state,bool useVertexBufferObjects) const188 void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
189 {
190     GLenum mode = _mode;
191     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
192         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
193         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
194     #endif
195 
196     if (useVertexBufferObjects)
197     {
198         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
199 
200         if (ebo)
201         {
202             state.getCurrentVertexArrayState()->bindElementBufferObject(ebo);
203             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
204             else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
205         }
206         else
207         {
208             state.getCurrentVertexArrayState()->unbindElementBufferObject();
209             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
210             else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, &front());
211         }
212     }
213     else
214     {
215         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
216         else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, &front());
217     }
218 }
219 
accept(PrimitiveFunctor & functor) const220 void DrawElementsUByte::accept(PrimitiveFunctor& functor) const
221 {
222     if (!empty()) functor.drawElements(_mode,size(),&front());
223 }
224 
accept(PrimitiveIndexFunctor & functor) const225 void DrawElementsUByte::accept(PrimitiveIndexFunctor& functor) const
226 {
227     if (!empty()) functor.drawElements(_mode,size(),&front());
228 }
229 
offsetIndices(int offset)230 void DrawElementsUByte::offsetIndices(int offset)
231 {
232     for(iterator itr=begin();
233         itr!=end();
234         ++itr)
235     {
236         *itr += offset;
237     }
238 }
239 
240 
241 ////////////////////////////////////////////////////////////////////////////////////////////////////////
242 //
243 // DrawElementsUShort
244 //
~DrawElementsUShort()245 DrawElementsUShort::~DrawElementsUShort()
246 {
247     releaseGLObjects();
248 }
249 
draw(State & state,bool useVertexBufferObjects) const250 void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
251 {
252     GLenum mode = _mode;
253     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
254         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
255         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
256     #endif
257 
258     if (useVertexBufferObjects)
259     {
260         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
261 
262         if (ebo)
263         {
264             state.getCurrentVertexArrayState()->bindElementBufferObject(ebo);
265             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
266             else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
267         }
268         else
269         {
270             state.getCurrentVertexArrayState()->unbindElementBufferObject();
271             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, &front(), _numInstances);
272             else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, &front());
273         }
274     }
275     else
276     {
277         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, &front(), _numInstances);
278         else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, &front());
279     }
280 }
281 
accept(PrimitiveFunctor & functor) const282 void DrawElementsUShort::accept(PrimitiveFunctor& functor) const
283 {
284     if (!empty()) functor.drawElements(_mode,size(),&front());
285 }
286 
accept(PrimitiveIndexFunctor & functor) const287 void DrawElementsUShort::accept(PrimitiveIndexFunctor& functor) const
288 {
289     if (!empty()) functor.drawElements(_mode,size(),&front());
290 }
291 
offsetIndices(int offset)292 void DrawElementsUShort::offsetIndices(int offset)
293 {
294     for(iterator itr=begin();
295         itr!=end();
296         ++itr)
297     {
298         *itr += offset;
299     }
300 }
301 
302 ////////////////////////////////////////////////////////////////////////////////////////////////////////
303 //
304 // DrawElementsUInt
305 //
~DrawElementsUInt()306 DrawElementsUInt::~DrawElementsUInt()
307 {
308     releaseGLObjects();
309 }
310 
draw(State & state,bool useVertexBufferObjects) const311 void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
312 {
313     GLenum mode = _mode;
314     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
315         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
316         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
317     #endif
318 
319     if (useVertexBufferObjects)
320     {
321         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
322 
323         if (ebo)
324         {
325             state.getCurrentVertexArrayState()->bindElementBufferObject(ebo);
326             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
327             else glDrawElements(mode, size(), GL_UNSIGNED_INT, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
328         }
329         else
330         {
331             state.getCurrentVertexArrayState()->unbindElementBufferObject();
332             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, &front(), _numInstances);
333             else glDrawElements(mode, size(), GL_UNSIGNED_INT, &front());
334         }
335     }
336     else
337     {
338         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, &front(), _numInstances);
339         else glDrawElements(mode, size(), GL_UNSIGNED_INT, &front());
340     }
341 }
342 
accept(PrimitiveFunctor & functor) const343 void DrawElementsUInt::accept(PrimitiveFunctor& functor) const
344 {
345     if (!empty()) functor.drawElements(_mode,size(),&front());
346 }
347 
accept(PrimitiveIndexFunctor & functor) const348 void DrawElementsUInt::accept(PrimitiveIndexFunctor& functor) const
349 {
350     if (!empty()) functor.drawElements(_mode,size(),&front());
351 }
352 
offsetIndices(int offset)353 void DrawElementsUInt::offsetIndices(int offset)
354 {
355     for(iterator itr=begin();
356         itr!=end();
357         ++itr)
358     {
359         *itr += offset;
360     }
361 }
362 
363 ////////////////////////////////////////////////////////////////////////////////////////////////////////
364 //
365 // MultiDrawArrays
366 //
367 #ifdef OSG_HAS_MULTIDRAWARRAYS
draw(osg::State & state,bool) const368 void MultiDrawArrays::draw(osg::State& state, bool) const
369 {
370     // VOA_NOTICE<<"osg::MultiDrawArrays::draw"<<std::endl;
371 
372     GLExtensions* ext = state.get<GLExtensions>();
373     if (ext->glMultiDrawArrays)
374     {
375         GLsizei primcount = osg::minimum(_firsts.size(), _counts.size());
376 
377         ext->glMultiDrawArrays(_mode, &_firsts.front(), &_counts.front(), primcount);
378     }
379 }
380 
accept(PrimitiveFunctor & functor) const381 void MultiDrawArrays::accept(PrimitiveFunctor& functor) const
382 {
383     unsigned int primcount = osg::minimum(_firsts.size(), _counts.size());
384     for(unsigned int i=0; i<primcount; ++i)
385     {
386         functor.drawArrays(_mode, _firsts[i], _counts[i]);
387     }
388 }
389 
accept(PrimitiveIndexFunctor & functor) const390 void MultiDrawArrays::accept(PrimitiveIndexFunctor& functor) const
391 {
392     unsigned int primcount = osg::minimum(_firsts.size(), _counts.size());
393     for(unsigned int i=0; i<primcount; ++i)
394     {
395         functor.drawArrays(_mode, _firsts[i], _counts[i]);
396     }
397 }
398 
getNumIndices() const399 unsigned int MultiDrawArrays::getNumIndices() const
400 {
401     unsigned int total=0;
402     for(Counts::const_iterator itr = _counts.begin(); itr!=_counts.end(); ++itr)
403     {
404         total += *itr;
405     }
406     return total;
407 }
408 
index(unsigned int pos) const409 unsigned int MultiDrawArrays::index(unsigned int pos) const
410 {
411     unsigned int i;
412     for(i=0; i<_counts.size(); ++i)
413     {
414         unsigned int count = _counts[i];
415         if (pos<count) break;
416         pos -= count;
417     }
418     if (i>=_firsts.size()) return 0;
419 
420     return _firsts[i] + pos;
421 }
422 
offsetIndices(int offset)423 void MultiDrawArrays::offsetIndices(int offset)
424 {
425     for(Firsts::iterator itr = _firsts.begin(); itr!=_firsts.end(); ++itr)
426     {
427         *itr += offset;
428     }
429 }
430 
getNumPrimitives() const431 unsigned int MultiDrawArrays::getNumPrimitives() const
432 {
433     switch(_mode)
434     {
435         case(POINTS): return getNumIndices();
436         case(LINES): return getNumIndices()/2;
437         case(TRIANGLES): return getNumIndices()/3;
438         case(QUADS): return getNumIndices()/4;
439         case(LINE_STRIP):
440         case(LINE_LOOP):
441         case(TRIANGLE_STRIP):
442         case(TRIANGLE_FAN):
443         case(QUAD_STRIP):
444         case(PATCHES):
445         case(POLYGON):
446         {
447             unsigned int primcount = osg::minimum(_firsts.size(), _counts.size());
448             return primcount;
449         }
450     }
451     return 0;
452 }
453 
add(GLint first,GLsizei count)454 void MultiDrawArrays::add(GLint first, GLsizei count)
455 {
456     _firsts.push_back(first);
457     _counts.push_back(count);
458 }
459 #endif
460