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 <osgUtil/SceneGraphBuilder>
14
15 #include <osg/Notify>
16 #include <osg/io_utils>
17
18 #include <osg/PrimitiveSet>
19 #include <osg/Texture>
20 #include <osg/AlphaFunc>
21 #include <osg/BlendFunc>
22 #include <osg/LineStipple>
23 #include <osg/Depth>
24 #include <osg/CullFace>
25 #include <osg/FrontFace>
26 #include <osg/LineWidth>
27 #include <osg/Point>
28 #include <osg/PolygonMode>
29 #include <osg/PolygonOffset>
30 #include <osg/PolygonStipple>
31 #include <osg/ShadeModel>
32 #include <osg/ShapeDrawable>
33
34 using namespace osgUtil;
35
SceneGraphBuilder()36 SceneGraphBuilder::SceneGraphBuilder():
37 _statesetAssigned(false),
38 _normalSet(false),
39 _normal(0.0f,0.0f,1.0f),
40 _colorSet(false),
41 _color(1.0f,1.0f,1.0f,1.0f),
42 _maxNumTexCoordComponents(0),
43 _texCoord(0.f,0.0f,0.0f,1.0f),
44 _primitiveMode(0)
45 {
46 }
47
48
49 ///////////////////////////////////////////////////////////////////////////////////////////
50 //
51 // OpenGL 1.0 building methods
52 //
PushMatrix()53 void SceneGraphBuilder::PushMatrix()
54 {
55 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
56 else _matrixStack.push_back(_matrixStack.back());
57 }
58
PopMatrix()59 void SceneGraphBuilder::PopMatrix()
60 {
61 if (!_matrixStack.empty()) _matrixStack.pop_back();
62
63 matrixChanged();
64 }
65
LoadIdentity()66 void SceneGraphBuilder::LoadIdentity()
67 {
68 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
69 _matrixStack.back().makeIdentity();
70
71 matrixChanged();
72 }
73
LoadMatrixd(const GLdouble * m)74 void SceneGraphBuilder::LoadMatrixd(const GLdouble* m)
75 {
76 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
77 _matrixStack.back().set(m);
78
79 matrixChanged();
80 }
81
MultMatrixd(const GLdouble * m)82 void SceneGraphBuilder::MultMatrixd(const GLdouble* m)
83 {
84 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
85 _matrixStack.back().preMult(osg::Matrixd(m));
86
87 matrixChanged();
88 }
89
Translated(GLdouble x,GLdouble y,GLdouble z)90 void SceneGraphBuilder::Translated(GLdouble x, GLdouble y, GLdouble z)
91 {
92 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
93 _matrixStack.back().preMultTranslate(osg::Vec3d(x,y,z));
94
95 matrixChanged();
96 }
97
Scaled(GLdouble x,GLdouble y,GLdouble z)98 void SceneGraphBuilder::Scaled(GLdouble x, GLdouble y, GLdouble z)
99 {
100 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
101 _matrixStack.back().preMultScale(osg::Vec3d(x,y,z));
102
103 matrixChanged();
104 }
105
Rotated(GLdouble angle,GLdouble x,GLdouble y,GLdouble z)106 void SceneGraphBuilder::Rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
107 {
108 if (_matrixStack.empty()) _matrixStack.push_back(osg::Matrixd());
109 _matrixStack.back().preMultRotate(osg::Quat(osg::inDegrees(angle),osg::Vec3d(x,y,z)));
110
111 matrixChanged();
112 }
113
BlendFunc(GLenum srcFactor,GLenum dstFactor)114 void SceneGraphBuilder::BlendFunc(GLenum srcFactor, GLenum dstFactor)
115 {
116 addAttribute(new osg::BlendFunc(srcFactor, dstFactor));
117 }
118
CullFace(GLenum mode)119 void SceneGraphBuilder::CullFace(GLenum mode)
120 {
121 addAttribute(new osg::CullFace(osg::CullFace::Mode(mode)));
122 }
123
DepthFunc(GLenum mode)124 void SceneGraphBuilder::DepthFunc(GLenum mode)
125 {
126 addAttribute(new osg::Depth(osg::Depth::Function(mode)));
127 }
128
FrontFace(GLenum mode)129 void SceneGraphBuilder::FrontFace(GLenum mode)
130 {
131 addAttribute(new osg::FrontFace(osg::FrontFace::Mode(mode)));
132 }
133
LineStipple(GLint factor,GLushort pattern)134 void SceneGraphBuilder::LineStipple(GLint factor, GLushort pattern)
135 {
136 addAttribute(new osg::LineStipple(factor, pattern));
137 }
138
LineWidth(GLfloat lineWidth)139 void SceneGraphBuilder::LineWidth(GLfloat lineWidth)
140 {
141 addAttribute(new osg::LineWidth(lineWidth));
142 }
143
PointSize(GLfloat pointSize)144 void SceneGraphBuilder::PointSize(GLfloat pointSize)
145 {
146 addAttribute(new osg::Point(pointSize));
147 }
148
PolygonMode(GLenum face,GLenum mode)149 void SceneGraphBuilder::PolygonMode(GLenum face, GLenum mode)
150 {
151 addAttribute(new osg::PolygonMode(osg::PolygonMode::Face(face),osg::PolygonMode::Mode(mode)));
152 }
153
PolygonOffset(GLfloat factor,GLfloat units)154 void SceneGraphBuilder::PolygonOffset(GLfloat factor, GLfloat units)
155 {
156 addAttribute(new osg::PolygonOffset(factor,units));
157 }
158
PolygonStipple(const GLubyte * mask)159 void SceneGraphBuilder::PolygonStipple(const GLubyte* mask)
160 {
161 addAttribute(new osg::PolygonStipple(mask));
162 }
163
ShadeModel(GLenum mode)164 void SceneGraphBuilder::ShadeModel(GLenum mode)
165 {
166 addAttribute(new osg::ShadeModel(osg::ShadeModel::Mode(mode)));
167 }
Enable(GLenum mode)168 void SceneGraphBuilder::Enable(GLenum mode)
169 {
170 addMode(mode, true);
171 }
172
Disable(GLenum mode)173 void SceneGraphBuilder::Disable(GLenum mode)
174 {
175 addMode(mode, false);
176 }
177
Color4f(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)178 void SceneGraphBuilder::Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
179 {
180 _normalSet = true;
181 _color.set(red,green,blue,alpha);
182 }
183
Normal3f(GLfloat x,GLfloat y,GLfloat z)184 void SceneGraphBuilder::Normal3f(GLfloat x, GLfloat y, GLfloat z)
185 {
186 _normalSet = true;
187 _normal.set(x,y,z);
188 }
189
TexCoord1f(GLfloat x)190 void SceneGraphBuilder::TexCoord1f(GLfloat x)
191 {
192 _maxNumTexCoordComponents = 1;
193 _texCoord.set(x,0.0f,0.0f,1.0f);
194 }
195
TexCoord2f(GLfloat x,GLfloat y)196 void SceneGraphBuilder::TexCoord2f(GLfloat x, GLfloat y)
197 {
198 _maxNumTexCoordComponents = 2;
199 _texCoord.set(x,y,0.0f,1.0f);
200 }
201
TexCoord3f(GLfloat x,GLfloat y,GLfloat z)202 void SceneGraphBuilder::TexCoord3f(GLfloat x, GLfloat y, GLfloat z)
203 {
204 _maxNumTexCoordComponents = 3;
205 _texCoord.set(x,y,z,1.0);
206 }
207
TexCoord4f(GLfloat x,GLfloat y,GLfloat z,GLfloat w)208 void SceneGraphBuilder::TexCoord4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
209 {
210 _maxNumTexCoordComponents = 4;
211 _texCoord.set(x,y,z,w);
212 }
213
Vertex3f(GLfloat x,GLfloat y,GLfloat z)214 void SceneGraphBuilder::Vertex3f(GLfloat x, GLfloat y, GLfloat z)
215 {
216 osg::Vec3 vertex(x,y,z);
217
218 vertex = vertex * _matrixStack.back();
219
220 if (_vertices.valid()) _vertices->push_back(vertex);
221 if (_normal.valid()) _normals->push_back(_normal);
222 if (_colors.valid()) _colors->push_back(_color);
223 if (_texCoords.valid()) _texCoords->push_back(_texCoord);
224 }
225
Begin(GLenum mode)226 void SceneGraphBuilder::Begin(GLenum mode)
227 {
228 // reset geometry
229 _primitiveMode = mode;
230 _vertices = new osg::Vec3Array;
231
232 _normalSet = false;
233 _normals = new osg::Vec3Array;
234
235 _colorSet = false;
236 _colors = new osg::Vec4Array;
237
238 _maxNumTexCoordComponents = 0;
239 _texCoords = new osg::Vec4Array;
240
241 }
242
End()243 void SceneGraphBuilder::End()
244 {
245 allocateGeometry();
246
247 _geometry->setVertexArray(_vertices.get());
248
249 if (_colorSet)
250 {
251 _geometry->setColorArray(_colors.get(), osg::Array::BIND_PER_VERTEX);
252 }
253 else
254 {
255 osg::Vec4Array* colors = new osg::Vec4Array;
256 colors->push_back(_color);
257
258 _geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
259 }
260
261 if (_normalSet)
262 {
263 _geometry->setNormalArray(_normals.get(), osg::Array::BIND_PER_VERTEX);
264 }
265 else
266 {
267 _geometry->setNormalArray(NULL, osg::Array::BIND_OFF);
268 }
269
270 if (_maxNumTexCoordComponents==1)
271 {
272 // convert Vec4Array into FloatArray
273 osg::FloatArray* texCoords = new osg::FloatArray;
274 for(osg::Vec4Array::iterator itr = _texCoords->begin();
275 itr != _texCoords->end();
276 ++itr)
277 {
278 texCoords->push_back(itr->x());
279 }
280 _geometry->setTexCoordArray(0, texCoords);
281 }
282 if (_maxNumTexCoordComponents==2)
283 {
284 // convert Vec4Array into FloatArray
285 osg::Vec2Array* texCoords = new osg::Vec2Array;
286 for(osg::Vec4Array::iterator itr = _texCoords->begin();
287 itr != _texCoords->end();
288 ++itr)
289 {
290 texCoords->push_back(osg::Vec2(itr->x(),itr->y()));
291 }
292 _geometry->setTexCoordArray(0, texCoords);
293 }
294 if (_maxNumTexCoordComponents==3)
295 {
296 // convert Vec4Array into FloatArray
297 osg::Vec3Array* texCoords = new osg::Vec3Array;
298 for(osg::Vec4Array::iterator itr = _texCoords->begin();
299 itr != _texCoords->end();
300 ++itr)
301 {
302 texCoords->push_back(osg::Vec3(itr->x(),itr->y(), itr->z()));
303 }
304 _geometry->setTexCoordArray(0, texCoords);
305 }
306 else if (_maxNumTexCoordComponents==4)
307 {
308 _geometry->setTexCoordArray(0, _texCoords.get());
309 }
310
311 _geometry->addPrimitiveSet(new osg::DrawArrays(_primitiveMode, 0, _vertices->size()));
312
313 completeGeometry();
314 }
315
316 ///////////////////////////////////////////////////////////////////////////////////////////
317 //
318 // GLU style building methods
319 //
QuadricDrawStyle(GLenum aDrawStyle)320 void SceneGraphBuilder::QuadricDrawStyle(GLenum aDrawStyle)
321 {
322 _quadricState._drawStyle = aDrawStyle;
323 }
324
QuadricNormals(GLenum aNormals)325 void SceneGraphBuilder::QuadricNormals(GLenum aNormals)
326 {
327 _quadricState._normals = aNormals;
328 }
329
QuadricOrientation(GLenum aOrientation)330 void SceneGraphBuilder::QuadricOrientation(GLenum aOrientation)
331 {
332 _quadricState._orientation = aOrientation;
333 }
334
QuadricTexture(GLboolean aTexture)335 void SceneGraphBuilder::QuadricTexture(GLboolean aTexture)
336 {
337 _quadricState._texture = aTexture;
338 }
339
Cylinder(GLfloat aBase,GLfloat aTop,GLfloat aHeight,GLint aSlices,GLint aStacks)340 void SceneGraphBuilder::Cylinder(GLfloat aBase,
341 GLfloat aTop,
342 GLfloat aHeight,
343 GLint aSlices,
344 GLint aStacks)
345 {
346 OSG_NOTICE<<"SceneGraphBuilder::Cylinder("<<aBase<<", "<<aTop<<", "<<aHeight<<", "<<aSlices<<", "<<aStacks<<") not implemented yet"<<std::endl;
347 }
348
Disk(GLfloat,GLfloat outer,GLint slices,GLint)349 void SceneGraphBuilder::Disk(GLfloat /*inner*/,
350 GLfloat outer,
351 GLint slices,
352 GLint /*loops*/)
353 {
354 double angle = 0.0;
355 double delta = 2.0*osg::PI/double(slices-1);
356
357 if (_quadricState._normals!=GLU_NONE) Normal3f(0.0f,0.0f,1.0f);
358
359 switch(_quadricState._drawStyle)
360 {
361 case(GLU_POINT):
362 {
363 Begin(GL_POINTS);
364 if (_quadricState._texture) TexCoord2f(0.5f,0.5f);
365 Vertex3f(0.0f, 0.0f, 0.0f);
366 for(GLint i=0; i<slices; ++i, angle += delta)
367 {
368 if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
369 Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
370 }
371 End();
372 break;
373 }
374 case(GLU_LINE):
375 {
376 Begin(GL_LINE_LOOP);
377 for(GLint i=0; i<slices; ++i, angle += delta)
378 {
379 if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
380 Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
381 }
382 End();
383 break;
384 }
385 case(GLU_FILL):
386 {
387 Begin(GL_TRIANGLE_FAN);
388 if (_quadricState._texture) TexCoord2f(0.5f,0.5f);
389 Vertex3f(0.0f, 0.0f, 0.0f);
390 for(GLint i=0; i<slices; ++i, angle += delta)
391 {
392 if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
393 Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
394 }
395 End();
396 break;
397 }
398 case(GLU_SILHOUETTE):
399 {
400 Begin(GL_LINE_LOOP);
401 for(GLint i=0; i<slices; ++i, angle += delta)
402 {
403 if (_quadricState._texture) TexCoord2f(GLfloat(sin(angle)*0.5+0.5), GLfloat(cos(angle)*0.5+0.5));
404 Vertex3f(outer*GLfloat(sin(angle)), outer*GLfloat(cos(angle)), 0.0f);
405 }
406 End();
407 break;
408 }
409 }
410 }
411
PartialDisk(GLfloat inner,GLfloat outer,GLint slices,GLint loops,GLfloat start,GLfloat sweep)412 void SceneGraphBuilder::PartialDisk(GLfloat inner,
413 GLfloat outer,
414 GLint slices,
415 GLint loops,
416 GLfloat start,
417 GLfloat sweep)
418 {
419 OSG_NOTICE<<"SceneGraphBuilder::PartialDisk("<<inner<<", "<<outer<<", "<<slices<<", "<<loops<<", "<<start<<", "<<sweep<<") not implemented yet."<<std::endl;
420 OSG_NOTICE<<" quadric("<<_quadricState._drawStyle<<", "<<_quadricState._normals<<", "<<_quadricState._orientation<<", "<<_quadricState._texture<<std::endl;
421 }
422
Sphere(GLfloat radius,GLint,GLint)423 void SceneGraphBuilder::Sphere(GLfloat radius,
424 GLint /*slices*/,
425 GLint /*stacks*/)
426 {
427 addShape(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f), radius));
428 }
429
430
431 ///////////////////////////////////////////////////////////////////////////////////////////
432 //
433 // General scene graph building methods
434 //
435
getScene()436 osg::Node* SceneGraphBuilder::getScene()
437 {
438 if (_group.valid() && _group->getNumChildren()>0) return _group.get();
439 else if (_transform.valid() && _transform->getNumChildren()>0) return _transform.get();
440 else if (_geode.valid() && _geode->getNumDrawables()>0) return _geode.get();
441
442 return 0;
443 }
444
takeScene()445 osg::Node* SceneGraphBuilder::takeScene()
446 {
447 osg::ref_ptr<osg::Node> node;
448
449 if (_group.valid() && _group->getNumChildren()>0) node = _group.get();
450 else if (_transform.valid() && _transform->getNumChildren()>0) node = _transform.get();
451 else if (_geode.valid() && _geode->getNumDrawables()>0) node = _geode.get();
452
453 // reset all the pointers to properly release the scene graph
454 _geometry = 0;
455 _geode = 0;
456 _transform = 0;
457 _group = 0;
458
459 return node.release();
460 }
461
matrixChanged()462 void SceneGraphBuilder::matrixChanged()
463 {
464 }
465
addAttribute(osg::StateAttribute * attribute)466 void SceneGraphBuilder::addAttribute(osg::StateAttribute* attribute)
467 {
468 allocateStateSet();
469 _stateset->setAttribute(attribute);
470 }
471
addMode(GLenum mode,bool enabled)472 void SceneGraphBuilder::addMode(GLenum mode, bool enabled)
473 {
474 allocateStateSet();
475 _stateset->setMode(mode, enabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
476 }
477
478
addTextureAttribute(unsigned int unit,osg::StateAttribute * attribute)479 void SceneGraphBuilder::addTextureAttribute(unsigned int unit, osg::StateAttribute* attribute)
480 {
481 allocateStateSet();
482 _stateset->setTextureAttribute(unit, attribute);
483 }
484
addTextureMode(unsigned int unit,GLenum mode,bool enabled)485 void SceneGraphBuilder::addTextureMode(unsigned int unit, GLenum mode, bool enabled)
486 {
487 allocateStateSet();
488 _stateset->setTextureMode(unit, mode, enabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
489 }
490
addShape(osg::Shape * shape)491 void SceneGraphBuilder::addShape(osg::Shape* shape)
492 {
493 osg::ShapeDrawable* sd = new osg::ShapeDrawable(shape);
494 sd->setColor(_color);
495
496 addDrawable(sd);
497 }
498
addDrawable(osg::Drawable * drawable)499 void SceneGraphBuilder::addDrawable(osg::Drawable* drawable)
500 {
501 if (!_geode) _geode = new osg::Geode;
502
503 if (_stateset.valid())
504 {
505 drawable->setStateSet(_stateset.get());
506 _statesetAssigned = true;
507 }
508
509 _geode->addDrawable(drawable);
510 }
511
allocateStateSet()512 void SceneGraphBuilder::allocateStateSet()
513 {
514 if (_statesetAssigned)
515 {
516 _stateset = dynamic_cast<osg::StateSet*>(_stateset->clone(osg::CopyOp::SHALLOW_COPY));
517 _statesetAssigned = false;
518 }
519
520 if (!_stateset) _stateset = new osg::StateSet;
521 }
522
allocateGeometry()523 void SceneGraphBuilder::allocateGeometry()
524 {
525 if (!_geometry)
526 {
527 _geometry = new osg::Geometry;
528 }
529 }
530
completeGeometry()531 void SceneGraphBuilder::completeGeometry()
532 {
533 if (_geometry.valid()) addDrawable(_geometry.get());
534 _geometry = 0;
535 }
536