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