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 
getNumPrimitives() const20 unsigned int PrimitiveSet::getNumPrimitives() const
21 {
22     switch(_mode)
23     {
24         case(POINTS): return getNumIndices();
25         case(LINES): return getNumIndices()/2;
26         case(TRIANGLES): return getNumIndices()/3;
27         case(QUADS): return getNumIndices()/4;
28         case(LINE_STRIP):
29         case(LINE_LOOP):
30         case(TRIANGLE_STRIP):
31         case(TRIANGLE_FAN):
32         case(QUAD_STRIP):
33         case(PATCHES):
34         case(POLYGON): return (getNumIndices()>0) ? 1 : 0;
35     }
36     return 0;
37 }
38 
draw(State & state,bool) const39 void DrawArrays::draw(State& state, bool) const
40 {
41 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
42     GLenum mode = _mode;
43     if (_mode==GL_QUADS)
44     {
45         state.drawQuads(_first, _count, _numInstances);
46         return;
47     }
48     else if (mode==GL_POLYGON)
49     {
50         mode = GL_TRIANGLE_FAN;
51     }
52     else if (mode==GL_QUAD_STRIP)
53     {
54         mode = GL_TRIANGLE_STRIP;
55     }
56 
57     if (_numInstances>=1) state.glDrawArraysInstanced(mode,_first,_count, _numInstances);
58     else glDrawArrays(mode,_first,_count);
59 #else
60     if (_numInstances>=1) state.glDrawArraysInstanced(_mode,_first,_count, _numInstances);
61     else glDrawArrays(_mode,_first,_count);
62 #endif
63 }
64 
accept(PrimitiveFunctor & functor) const65 void DrawArrays::accept(PrimitiveFunctor& functor) const
66 {
67     functor.drawArrays(_mode,_first,_count);
68 }
69 
accept(PrimitiveIndexFunctor & functor) const70 void DrawArrays::accept(PrimitiveIndexFunctor& functor) const
71 {
72     functor.drawArrays(_mode,_first,_count);
73 }
74 
getNumPrimitives() const75 unsigned int DrawArrayLengths::getNumPrimitives() const
76 {
77     switch(_mode)
78     {
79         case(POINTS): return getNumIndices();
80         case(LINES): return getNumIndices()/2;
81         case(TRIANGLES): return getNumIndices()/3;
82         case(QUADS): return getNumIndices()/4;
83         case(LINE_STRIP):
84         case(LINE_LOOP):
85         case(TRIANGLE_STRIP):
86         case(TRIANGLE_FAN):
87         case(QUAD_STRIP):
88         case(PATCHES):
89         case(POLYGON): return size();
90     }
91     return 0;
92 }
93 
draw(State & state,bool) const94 void DrawArrayLengths::draw(State& state, bool) const
95 {
96     GLenum mode = _mode;
97     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
98         if (_mode==GL_QUADS)
99         {
100             GLint first = _first;
101             for(vector_type::const_iterator itr=begin();
102                 itr!=end();
103                 ++itr)
104             {
105                 state.drawQuads(first, *itr, _numInstances);
106                 first += *itr;
107             }
108 
109             return;
110         }
111         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
112         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
113     #endif
114 
115     GLint first = _first;
116     for(vector_type::const_iterator itr=begin();
117         itr!=end();
118         ++itr)
119     {
120         if (_numInstances>=1) state.glDrawArraysInstanced(mode,first,*itr,_numInstances);
121         else glDrawArrays(mode,first,*itr);
122         first += *itr;
123     }
124 
125 }
126 
accept(PrimitiveFunctor & functor) const127 void DrawArrayLengths::accept(PrimitiveFunctor& functor) const
128 {
129     GLint first = _first;
130     for(vector_type::const_iterator itr=begin();
131         itr!=end();
132         ++itr)
133     {
134         functor.drawArrays(_mode,first,*itr);
135         first += *itr;
136     }
137 }
138 
accept(PrimitiveIndexFunctor & functor) const139 void DrawArrayLengths::accept(PrimitiveIndexFunctor& functor) const
140 {
141     GLint first = _first;
142     for(vector_type::const_iterator itr=begin();
143         itr!=end();
144         ++itr)
145     {
146         functor.drawArrays(_mode,first,*itr);
147         first += *itr;
148     }
149 }
150 
getNumIndices() const151 unsigned int DrawArrayLengths::getNumIndices() const
152 {
153     unsigned int count = 0;
154     for(vector_type::const_iterator itr=begin();
155         itr!=end();
156         ++itr)
157     {
158         count += *itr;
159     }
160     return count;
161 }
162 
~DrawElementsUByte()163 DrawElementsUByte::~DrawElementsUByte()
164 {
165     releaseGLObjects();
166 }
167 
draw(State & state,bool useVertexBufferObjects) const168 void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
169 {
170     GLenum mode = _mode;
171     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
172         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
173         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
174     #endif
175 
176     if (useVertexBufferObjects)
177     {
178         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
179         state.bindElementBufferObject(ebo);
180         if (ebo)
181         {
182             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
183             else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
184         }
185         else
186         {
187             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
188             else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, &front());
189         }
190     }
191     else
192     {
193         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, &front(), _numInstances);
194         else glDrawElements(mode, size(), GL_UNSIGNED_BYTE, &front());
195     }
196 }
197 
accept(PrimitiveFunctor & functor) const198 void DrawElementsUByte::accept(PrimitiveFunctor& functor) const
199 {
200     if (!empty()) functor.drawElements(_mode,size(),&front());
201 }
202 
accept(PrimitiveIndexFunctor & functor) const203 void DrawElementsUByte::accept(PrimitiveIndexFunctor& functor) const
204 {
205     if (!empty()) functor.drawElements(_mode,size(),&front());
206 }
207 
offsetIndices(int offset)208 void DrawElementsUByte::offsetIndices(int offset)
209 {
210     for(iterator itr=begin();
211         itr!=end();
212         ++itr)
213     {
214         *itr += offset;
215     }
216 }
217 
218 
~DrawElementsUShort()219 DrawElementsUShort::~DrawElementsUShort()
220 {
221     releaseGLObjects();
222 }
223 
draw(State & state,bool useVertexBufferObjects) const224 void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
225 {
226     GLenum mode = _mode;
227     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
228         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
229         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
230     #endif
231 
232     if (useVertexBufferObjects)
233     {
234         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
235         state.bindElementBufferObject(ebo);
236         if (ebo)
237         {
238             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
239             else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
240         }
241         else
242         {
243             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, &front(), _numInstances);
244             else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, &front());
245         }
246     }
247     else
248     {
249         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_SHORT, &front(), _numInstances);
250         else glDrawElements(mode, size(), GL_UNSIGNED_SHORT, &front());
251     }
252 }
253 
accept(PrimitiveFunctor & functor) const254 void DrawElementsUShort::accept(PrimitiveFunctor& functor) const
255 {
256     if (!empty()) functor.drawElements(_mode,size(),&front());
257 }
258 
accept(PrimitiveIndexFunctor & functor) const259 void DrawElementsUShort::accept(PrimitiveIndexFunctor& functor) const
260 {
261     if (!empty()) functor.drawElements(_mode,size(),&front());
262 }
263 
offsetIndices(int offset)264 void DrawElementsUShort::offsetIndices(int offset)
265 {
266     for(iterator itr=begin();
267         itr!=end();
268         ++itr)
269     {
270         *itr += offset;
271     }
272 }
273 
274 
~DrawElementsUInt()275 DrawElementsUInt::~DrawElementsUInt()
276 {
277     releaseGLObjects();
278 }
279 
draw(State & state,bool useVertexBufferObjects) const280 void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
281 {
282     GLenum mode = _mode;
283     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
284         if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
285         if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
286     #endif
287 
288     if (useVertexBufferObjects)
289     {
290         GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
291         state.bindElementBufferObject(ebo);
292         if (ebo)
293         {
294             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances);
295             else glDrawElements(mode, size(), GL_UNSIGNED_INT, (const GLvoid *)(ebo->getOffset(getBufferIndex())));
296         }
297         else
298         {
299             if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, &front(), _numInstances);
300             else glDrawElements(mode, size(), GL_UNSIGNED_INT, &front());
301         }
302     }
303     else
304     {
305         if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_INT, &front(), _numInstances);
306         else glDrawElements(mode, size(), GL_UNSIGNED_INT, &front());
307     }
308 }
309 
accept(PrimitiveFunctor & functor) const310 void DrawElementsUInt::accept(PrimitiveFunctor& functor) const
311 {
312     if (!empty()) functor.drawElements(_mode,size(),&front());
313 }
314 
accept(PrimitiveIndexFunctor & functor) const315 void DrawElementsUInt::accept(PrimitiveIndexFunctor& functor) const
316 {
317     if (!empty()) functor.drawElements(_mode,size(),&front());
318 }
319 
offsetIndices(int offset)320 void DrawElementsUInt::offsetIndices(int offset)
321 {
322     for(iterator itr=begin();
323         itr!=end();
324         ++itr)
325     {
326         *itr += offset;
327     }
328 }
329