]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/PrimitiveCollector.cxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / model / PrimitiveCollector.cxx
1 // Copyright (C) 2008 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include "PrimitiveCollector.hxx"
23
24 #include <simgear/scene/util/OsgMath.hxx>
25
26 namespace simgear {
27
28 PrimitiveCollector::PrimitiveCollector() :
29     _mode(0)
30 {
31 }
32
33 PrimitiveCollector::~PrimitiveCollector()
34 {
35 }
36     
37 void
38 PrimitiveCollector::swap(PrimitiveCollector& primitiveFunctor)
39 {
40     _vertices.swap(primitiveFunctor._vertices);
41     std::swap(_mode, primitiveFunctor._mode);
42 }
43
44 void
45 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec2* vertices)
46 {
47     _vertices.resize(0);
48     _vertices.reserve(count);
49     for (unsigned i = 0; i < count; ++i)
50         addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], 0));
51 }
52     
53 void
54 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec3* vertices)
55 {
56     _vertices.resize(0);
57     _vertices.reserve(count);
58     for (unsigned i = 0; i < count; ++i)
59         addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], vertices[i][2]));
60 }
61
62 void
63 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec4* vertices)
64 {
65     _vertices.resize(0);
66     _vertices.reserve(count);
67     for (unsigned i = 0; i < count; ++i)
68         addVertex(osg::Vec4d(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]));
69 }
70
71 void
72 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec2d* vertices)
73 {
74     _vertices.resize(0);
75     _vertices.reserve(count);
76     for (unsigned i = 0; i < count; ++i)
77         addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], 0));
78 }
79
80 void
81 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec3d* vertices)
82 {
83     _vertices.resize(0);
84     _vertices.reserve(count);
85     for (unsigned i = 0; i < count; ++i)
86         addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], vertices[i][2]));
87 }
88
89 void
90 PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec4d* vertices) 
91 {
92     _vertices.resize(0);
93     _vertices.reserve(count);
94     for (unsigned i = 0; i < count; ++i)
95         addVertex(osg::Vec4d(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]));
96 }
97
98 void
99 PrimitiveCollector::drawArrays(GLenum mode, GLint first, GLsizei count)
100 {
101     if (_vertices.empty() || count <= 0)
102         return;
103
104     GLsizei end = first + count;
105     switch(mode) {
106     case (GL_TRIANGLES):
107         for (GLsizei i = first; i < end - 2; i += 3) {
108             addTriangle(i, i + 1, i + 2);
109         }
110         break;
111
112     case (GL_TRIANGLE_STRIP):
113         for (GLsizei i = first; i < end - 2; ++i) {
114             addTriangle(i, i + 1, i + 2);
115         }
116         break;
117
118     case (GL_QUADS):
119         for (GLsizei i = first; i < end - 3; i += 4) {
120             addQuad(i, i + 1, i + 2, i + 3);
121         }
122         break;
123
124     case (GL_QUAD_STRIP):
125         for (GLsizei i = first; i < end - 3; i += 2) {
126             addQuad(i, i + 1, i + 2, i + 3);
127         }
128         break;
129
130     case (GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
131     case (GL_TRIANGLE_FAN):
132         for (GLsizei i = first; i < end - 2; ++i) {
133             addTriangle(first, i + 1, i + 2);
134         }
135     break;
136
137     case (GL_POINTS):
138         for (GLsizei i = first; i < end; ++i) {
139             addPoint(i);
140         }
141         break;
142
143     case (GL_LINES):
144         for (GLsizei i = first; i < end - 1; i += 2) {
145             addLine(i, i + 1);
146         }
147         break;
148
149     case (GL_LINE_STRIP):
150         for (GLsizei i = first; i < end - 1; ++i) {
151             addLine(i, i + 1);
152         }
153         break;
154
155     case (GL_LINE_LOOP):
156         for (GLsizei i = first; i < end - 1; ++i) {
157             addLine(i, i + 1);
158         }
159         addLine(end - 1, first);
160         break;
161
162     default:
163         break;
164     }
165 }
166   
167 template<typename index_type>
168 void
169 PrimitiveCollector::drawElementsTemplate(GLenum mode, GLsizei count, const index_type* indices)
170 {
171     if (_vertices.empty() || indices == 0 || count <= 0)
172         return;
173     
174     switch(mode) {
175     case (GL_TRIANGLES):
176         for (GLsizei i = 0; i < count - 2; i += 3) {
177             addTriangle(indices[i], indices[i + 1], indices[i + 2]);
178         }
179         break;
180
181     case (GL_TRIANGLE_STRIP):
182         for (GLsizei i = 0; i < count - 2; ++i) {
183             addTriangle(indices[i], indices[i + 1], indices[i + 2]);
184         }
185         break;
186
187     case (GL_QUADS):
188         for (GLsizei i = 0; i < count - 3; i += 4) {
189             addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
190         }
191         break;
192
193     case (GL_QUAD_STRIP):
194         for (GLsizei i = 0; i < count - 3; i += 2) {
195             addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
196         }
197         break;
198
199     case (GL_POLYGON):
200     case (GL_TRIANGLE_FAN):
201         for (GLsizei i = 0; i < count - 2; ++i) {
202             addTriangle(indices[0], indices[i + 1], indices[i + 2]);
203         }
204     break;
205
206     case (GL_POINTS):
207         for(GLsizei i = 0; i < count; ++i) {
208             addPoint(indices[i]);
209         }
210         break;
211
212     case (GL_LINES):
213         for (GLsizei i = 0; i < count - 1; i += 2) {
214             addLine(indices[i], indices[i + 1]);
215         }
216         break;
217
218     case (GL_LINE_STRIP):
219         for (GLsizei i = 0; i < count - 1; ++i) {
220             addLine(indices[i], indices[i + 1]);
221         }
222         break;
223
224     case (GL_LINE_LOOP):
225         for (GLsizei i = 0; i < count - 1; ++i) {
226             addLine(indices[i], indices[i + 1]);
227         }
228         addLine(indices[count - 1], indices[0]);
229         break;
230
231     default:
232         break;
233     }
234 }
235
236 void
237 PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
238 {
239     drawElementsTemplate(mode, count, indices);
240 }
241
242 void PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLushort* indices)
243 {
244     drawElementsTemplate(mode, count, indices);
245 }
246
247 void
248 PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLuint* indices)
249 {
250     drawElementsTemplate(mode, count, indices);
251 }
252
253 void
254 PrimitiveCollector::begin(GLenum mode)
255 {
256     _mode = mode;
257     _vertices.resize(0);
258 }
259
260 void
261 PrimitiveCollector::vertex(const osg::Vec2& v)
262 {
263     addVertex(osg::Vec3d(v[0], v[1], 0));
264 }
265
266 void
267 PrimitiveCollector::vertex(const osg::Vec3& v)
268 {
269     addVertex(osg::Vec3d(v[0], v[1], v[2]));
270 }
271
272 void
273 PrimitiveCollector::vertex(const osg::Vec4& v)
274 {
275     addVertex(osg::Vec4d(v[0], v[1], v[2], v[3]));
276 }
277
278 void
279 PrimitiveCollector::vertex(float x, float y)
280 {
281     addVertex(osg::Vec3d(x, y, 0));
282 }
283
284 void
285 PrimitiveCollector::vertex(float x, float y, float z)
286 {
287     addVertex(osg::Vec3d(x, y, z));
288 }
289
290 void
291 PrimitiveCollector::vertex(float x, float y, float z, float w)
292 {
293     addVertex(osg::Vec4d(x, y, z, w));
294 }
295
296 void
297 PrimitiveCollector::end()
298 {
299     if (_vertices.empty())
300         return;
301
302     drawArrays(_mode, 0, _vertices.size());
303 }
304
305 void
306 PrimitiveCollector::addVertex(const osg::Vec3d& v)
307 {
308     _vertices.push_back(v);
309 }
310
311 void
312 PrimitiveCollector::addVertex(const osg::Vec4d& v)
313 {
314     _vertices.push_back(osg::Vec3d(v[0]/v[3], v[1]/v[3], v[2]/v[3]));
315 }
316
317 void
318 PrimitiveCollector::addPoint(unsigned i1)
319 {
320     if (_vertices.size() <= i1)
321         return;
322     addPoint(_vertices[i1]);
323 }
324
325 void
326 PrimitiveCollector::addLine(unsigned i1, unsigned i2)
327 {
328     size_t size = _vertices.size();
329     if (size <= i1 || size <= i2)
330         return;
331     addLine(_vertices[i1], _vertices[i2]);
332 }
333
334 void
335 PrimitiveCollector::addTriangle(unsigned i1, unsigned i2, unsigned i3)
336 {
337     size_t size = _vertices.size();
338     if (size <= i1 || size <= i2 || size <= i3)
339         return;
340     addTriangle(_vertices[i1], _vertices[i2], _vertices[i3]);
341 }
342
343 void
344 PrimitiveCollector::addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4)
345 {
346     addTriangle(i1, i2, i3);
347     addTriangle(i1, i3, i4);
348 }
349
350 }