OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WGEGeodeUtils.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <string>
26 
27 #include <osg/Array>
28 #include <osg/Geode>
29 #include <osg/Geometry>
30 #include <osg/LineWidth>
31 #include <osg/MatrixTransform>
32 #include <osg/ShapeDrawable>
33 #include <osg/Vec3>
34 #include <osg/LightModel>
35 #include <osg/Material>
36 
37 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
38 #include "../common/WPathHelper.h"
39 #include "../common/math/WMath.h"
40 #include "WGESubdividedPlane.h"
41 #include "WGEGeodeUtils.h"
42 #include "WGEGeometryUtils.h"
43 #include "WGEUtils.h"
44 #include "WGEGroupNode.h"
45 #include "shaders/WGEShader.h"
46 #include "widgets/labeling/WGELabel.h"
47 
48 osg::ref_ptr< osg::Geode > wge::generateBoundingBoxGeode( const WBoundingBox& bb, const WColor& color )
49 {
50  const WBoundingBox::vec_type& pos1 = bb.getMin();
51  const WBoundingBox::vec_type& pos2 = bb.getMax();
52 
53  WAssert( pos1[0] <= pos2[0] && pos1[1] <= pos2[1] && pos1[2] <= pos2[2], "pos1 does not seem to be the frontLowerLeft corner of the BB!" );
54  using osg::ref_ptr;
55  ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
56  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
57  ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
58 
59  vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos1[2] ) );
60  vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos1[2] ) );
61  vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos1[2] ) );
62  vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos1[2] ) );
63  vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos1[2] ) );
64  vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos2[2] ) );
65  vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos2[2] ) );
66  vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos2[2] ) );
67  vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos2[2] ) );
68  vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos2[2] ) );
69 
70  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() ) );
71 
72  vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos1[2] ) );
73  vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos2[2] ) );
74  vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos1[2] ) );
75  vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos2[2] ) );
76  vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos1[2] ) );
77  vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos2[2] ) );
78 
79  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, vertices->size() - 6, 6 ) );
80 
81  geometry->setVertexArray( vertices );
82  colors->push_back( color );
83  geometry->setColorArray( colors );
84  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
85  osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
86  geode->addDrawable( geometry );
87 
88  // disable light for this geode as lines can't be lit properly
89  osg::StateSet* state = geode->getOrCreateStateSet();
90  state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
91 
92  return geode;
93 }
94 
95 osg::ref_ptr< osg::Geometry > wge::createUnitCube( const WColor& color )
96 {
97  // create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
98  osg::ref_ptr< osg::Geometry > cube = new osg::Geometry();
99  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
100  osg::ref_ptr< osg::Vec3Array > normals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
101  osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
102 
103  // front face
104  vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
105  vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
106  vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
107  vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
108  normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
109 
110  // back face
111  vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
112  vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
113  vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
114  vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
115  normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
116 
117  // left
118  vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
119  vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
120  vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
121  vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
122  normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
123 
124  // right
125  vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
126  vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
127  vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
128  vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
129  normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
130 
131  // bottom
132  vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
133  vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
134  vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
135  vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
136  normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
137 
138  // top
139  vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
140  vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
141  vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
142  vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
143  normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
144 
145  // set it up and set arrays
146  cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, vertices->size() ) );
147  cube->setVertexArray( vertices );
148 
149  // set 3D texture coordinates here.
150  cube->setTexCoordArray( 0, vertices );
151 
152  // set normals
153  cube->setNormalArray( normals );
154  cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
155 
156  // finally, the colors
157  colors->push_back( color );
158  cube->setColorArray( colors );
159  cube->setColorBinding( osg::Geometry::BIND_OVERALL );
160 
161  return cube;
162 }
163 
164 osg::ref_ptr< osg::Geometry > wge::createUnitCubeAsLines( const WColor& color )
165 {
166  // create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
167  osg::ref_ptr< osg::Geometry > cube = new osg::Geometry();
168  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
169  osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
170 
171  vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
172  vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
173  vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
174  vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
175  vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
176  vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
177  vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
178  vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
179  vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
180  vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
181 
182  cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() ) );
183 
184  vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
185  vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
186  vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
187  vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
188  vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
189  vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
190 
191  cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, vertices->size() - 6, 6 ) );
192 
193  // set it up and set arrays
194  cube->setVertexArray( vertices );
195 
196  // set 3D texture coordinates here.
197  cube->setTexCoordArray( 0, vertices );
198 
199  // finally, the colors
200  colors->push_back( color );
201  cube->setColorArray( colors );
202  cube->setColorBinding( osg::Geometry::BIND_OVERALL );
203 
204  return cube;
205 }
206 
207 osg::ref_ptr< osg::Node > wge::generateSolidBoundingBoxNode( const WBoundingBox& bb, const WColor& color, bool threeDTexCoords )
208 {
209  WAssert( bb.valid(), "Invalid bounding box!" );
210 
211  // create a uni cube
212  osg::ref_ptr< osg::Geode > cube = new osg::Geode();
213  cube->setName( "Solid Bounding Box" );
214  if( threeDTexCoords )
215  {
216  cube->addDrawable( createUnitCube( color ) );
217  }
218  else
219  {
220  osg::ref_ptr< osg::ShapeDrawable > cubeDrawable = new osg::ShapeDrawable( new osg::Box( osg::Vec3( 0.5, 0.5, 0.5 ), 1.0 ) );
221  cubeDrawable->setColor( color );
222  cube->addDrawable( cubeDrawable );
223  }
224 
225  // transform the cube to match the bbox
226  osg::Matrixd transformM;
227  osg::Matrixd scaleM;
228  transformM.makeTranslate( bb.getMin() );
229  scaleM.makeScale( bb.getMax() - bb.getMin() );
230 
231  // apply transformation to bbox
232  osg::ref_ptr< osg::MatrixTransform > transform = new osg::MatrixTransform();
233  transform->setMatrix( scaleM * transformM );
234  transform->addChild( cube );
235 
236  // we do not need light
237  osg::StateSet* state = cube->getOrCreateStateSet();
238  state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
239 
240  return transform;
241 }
242 
243 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometry( WTriangleMesh::SPtr mesh,
244  const WColor& defaultColor,
245  bool includeNormals,
246  bool lighting,
247  bool useMeshColor )
248 {
249  osg::ref_ptr< osg::Geometry> geometry( new osg::Geometry );
250  geometry->setVertexArray( mesh->getVertexArray() );
251 
252  osg::DrawElementsUInt* surfaceElement;
253 
254  surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
255 
256  std::vector< size_t > tris = mesh->getTriangles();
257  surfaceElement->reserve( tris.size() );
258 
259  for( unsigned int vertId = 0; vertId < tris.size(); ++vertId )
260  {
261  surfaceElement->push_back( tris[vertId] );
262  }
263  geometry->addPrimitiveSet( surfaceElement );
264 
265  // add the mesh colors
266  if( mesh->getVertexColorArray() && useMeshColor )
267  {
268  geometry->setColorArray( mesh->getVertexColorArray() );
269  geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
270  }
271  else
272  {
273  osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
274  colors->push_back( defaultColor );
275  geometry->setColorArray( colors );
276  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
277  }
278 
279  // ------------------------------------------------
280  // normals
281  if( includeNormals )
282  {
283  geometry->setNormalArray( mesh->getVertexNormalArray() );
284  geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
285 
286  if( lighting )
287  {
288  // if normals are specified, we also setup a default lighting.
289  osg::StateSet* state = geometry->getOrCreateStateSet();
290  osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
291  lightModel->setTwoSided( true );
292  state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
293  state->setMode( GL_BLEND, osg::StateAttribute::ON );
294  {
295  osg::ref_ptr< osg::Material > material = new osg::Material();
296  material->setDiffuse( osg::Material::FRONT, osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
297  material->setSpecular( osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
298  material->setAmbient( osg::Material::FRONT, osg::Vec4( 0.1, 0.1, 0.1, 1.0 ) );
299  material->setEmission( osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
300  material->setShininess( osg::Material::FRONT, 25.0 );
301  state->setAttribute( material );
302  }
303  }
304  }
305 
306  // enable VBO
307  geometry->setUseDisplayList( false );
308  geometry->setUseVertexBufferObjects( true );
309 
310  return geometry;
311 }
312 
313 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometry( WTriangleMesh::SPtr mesh, const WColoredVertices& colorMap, const WColor& defaultColor,
314  bool includeNormals, bool lighting )
315 {
316  osg::Geometry* geometry = convertToOsgGeometry( mesh, defaultColor, includeNormals, lighting, false );
317 
318  // ------------------------------------------------
319  // colors
320  osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
321  for( size_t i = 0; i < mesh->vertSize(); ++i )
322  {
323  colors->push_back( defaultColor );
324  }
325  for( std::map< size_t, WColor >::const_iterator vc = colorMap.getData().begin(); vc != colorMap.getData().end(); ++vc )
326  {
327  // ATTENTION: the colormap might not be available and hence an old one, but the new mesh might have triggered the update
328  if( vc->first < colors->size() )
329  {
330  colors->at( vc->first ) = vc->second;
331  }
332  }
333 
334  geometry->setColorArray( colors );
335  geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
336 
337  return geometry;
338 }
339 
340 osg::ref_ptr< osg::Geode > wge::generateLineStripGeode( const WLine& line, const float thickness, const WColor& color )
341 {
342  using osg::ref_ptr;
343  ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
344  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
345  ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
346 
347  for( size_t i = 1; i < line.size(); ++i )
348  {
349  vertices->push_back( osg::Vec3( line[i-1][0], line[i-1][1], line[i-1][2] ) );
350  colors->push_back( wge::getRGBAColorFromDirection( line[i-1], line[i] ) );
351  }
352  vertices->push_back( osg::Vec3( line.back()[0], line.back()[1], line.back()[2] ) );
353  colors->push_back( colors->back() );
354 
355  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, line.size() ) );
356  geometry->setVertexArray( vertices );
357 
358  if( color != WColor( 0, 0, 0, 0 ) )
359  {
360  colors->clear();
361  colors->push_back( color );
362  geometry->setColorArray( colors );
363  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
364  }
365  else
366  {
367  geometry->setColorArray( colors );
368  geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
369  }
370 
371  // line width
372  osg::StateSet* stateset = geometry->getOrCreateStateSet();
373  stateset->setAttributeAndModes( new osg::LineWidth( thickness ), osg::StateAttribute::ON );
374  stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
375 
376  osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
377  geode->addDrawable( geometry );
378  return geode;
379 }
380 
381 osg::ref_ptr< osg::PositionAttitudeTransform > wge::addLabel( osg::Vec3 position, std::string text )
382 {
383  osg::ref_ptr< osgText::Text > label = osg::ref_ptr< osgText::Text >( new osgText::Text() );
384  osg::ref_ptr< osg::Geode > labelGeode = osg::ref_ptr< osg::Geode >( new osg::Geode() );
385 
386  labelGeode->addDrawable( label );
387 
388  // setup font
389  label->setFont( WPathHelper::getAllFonts().Default.file_string() );
390  label->setBackdropType( osgText::Text::OUTLINE );
391  label->setCharacterSize( 6 );
392 
393  label->setText( text );
394  label->setAxisAlignment( osgText::Text::SCREEN );
395  label->setDrawMode( osgText::Text::TEXT );
396  label->setAlignment( osgText::Text::CENTER_TOP );
397  label->setPosition( osg::Vec3( 0.0, 0.0, 0.0 ) );
398  label->setColor( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
399 
400  osg::ref_ptr< osg::PositionAttitudeTransform > labelXform =
401  osg::ref_ptr< osg::PositionAttitudeTransform >( new osg::PositionAttitudeTransform() );
402  labelXform->setPosition( position );
403 
404  labelXform->addChild( labelGeode );
405 
406  return labelXform;
407 }
408 
409 osg::ref_ptr< osg::PositionAttitudeTransform > wge::vector2label( osg::Vec3 position )
410 {
411  std::string label = "(" + boost::lexical_cast< std::string >( position[0] ) + "," +
412  boost::lexical_cast< std::string >( position[1] ) + "," + boost::lexical_cast< std::string >( position[2] ) + ")";
413  return ( addLabel( position, label ) );
414 }
415 
416 osg::ref_ptr< osg::Geode > wge::genFinitePlane( double xSize, double ySize, const WPlane& p, const WColor& color, bool border )
417 {
418  using osg::ref_ptr;
419  ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
420  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
421  ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
422 
423  colors->push_back( color );
424 
425  vertices->push_back( p.getPointInPlane( xSize, ySize ) );
426  vertices->push_back( p.getPointInPlane( -xSize, ySize ) );
427  vertices->push_back( p.getPointInPlane( -xSize, -ySize ) );
428  vertices->push_back( p.getPointInPlane( xSize, -ySize ) );
429 
430  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
431  geometry->setVertexArray( vertices );
432  geometry->setColorArray( colors );
433  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
434 
435  osg::StateSet* stateset = new osg::StateSet;
436  stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
437  geometry->setStateSet( stateset );
438 
439  osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
440  geode->addDrawable( geometry );
441 
442  if( border )
443  {
444  vertices->push_back( vertices->front() );
445  ref_ptr< osg::Geometry > borderGeom = ref_ptr< osg::Geometry >( new osg::Geometry );
446  borderGeom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, 4 ) );
447  borderGeom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 3, 2 ) );
448  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
449  colors->push_back( inverseColor( color ) );
450  borderGeom->setColorArray( colors );
451  borderGeom->setColorBinding( osg::Geometry::BIND_OVERALL );
452  borderGeom->setVertexArray( vertices );
453  geode->addDrawable( borderGeom );
454  }
455  return geode;
456 }
457 
458 osg::ref_ptr< osg::Geode > wge::genFinitePlane( osg::Vec3 const& base, osg::Vec3 const& a, osg::Vec3 const& b )
459 {
460  // the stuff needed by the OSG to create a geometry instance
461  osg::ref_ptr< osg::Vec3Array > vertices = new osg::Vec3Array;
462  osg::ref_ptr< osg::Vec3Array > texcoords0 = new osg::Vec3Array;
463  osg::ref_ptr< osg::Vec3Array > normals = new osg::Vec3Array;
464  osg::ref_ptr< osg::Vec4Array > colors = new osg::Vec4Array;
465 
466  osg::Vec3 aPlusB = a + b;
467 
468  vertices->push_back( base );
469  vertices->push_back( base + a );
470  vertices->push_back( base + aPlusB );
471  vertices->push_back( base + b );
472 
473  osg::Vec3 aCrossB = a ^ b;
474  aCrossB.normalize();
475  osg::Vec3 aNorm = a;
476  aNorm.normalize();
477  osg::Vec3 bNorm = b;
478  bNorm.normalize();
479 
480  normals->push_back( aCrossB );
481  colors->push_back( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
482  texcoords0->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
483  texcoords0->push_back( aNorm );
484  texcoords0->push_back( aNorm + bNorm );
485  texcoords0->push_back( bNorm );
486 
487  // put it all together
488  osg::ref_ptr< osg::Geometry > geometry = new osg::Geometry();
489  geometry->setVertexArray( vertices );
490  geometry->setTexCoordArray( 0, texcoords0 );
491  geometry->setNormalBinding( osg::Geometry::BIND_OVERALL );
492  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
493  geometry->setNormalArray( normals );
494  geometry->setColorArray( colors );
495  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
496 
497  osg::ref_ptr< osg::Geode > geode = new osg::Geode();
498  geode->addDrawable( geometry );
499  return geode;
500 }
501 
502 osg::ref_ptr< WGESubdividedPlane > wge::genUnitSubdividedPlane( size_t resX, size_t resY, double spacing )
503 {
504  WAssert( resX > 0 && resY > 0, "A Plane with no quad is not supported, use another datatype for that!" );
505  double dx = ( resX > 1 ? 1.0 / ( resX - 1 ) : 1.0 );
506  double dy = ( resY > 1 ? 1.0 / ( resY - 1 ) : 1.0 );
507 
508  size_t numQuads = resX * resY;
509 
510  using osg::ref_ptr;
511  ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array( numQuads * 4 ) );
512  ref_ptr< osg::Vec3Array > centers = ref_ptr< osg::Vec3Array >( new osg::Vec3Array( numQuads ) );
513  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array( numQuads ) );
514 
515  for( size_t yQuad = 0; yQuad < resY; ++yQuad )
516  {
517  for( size_t xQuad = 0; xQuad < resX; ++xQuad )
518  {
519  size_t qIndex = yQuad * resX + xQuad;
520  size_t vIndex = qIndex * 4; // since there are 4 corners
521  vertices->at( vIndex ) = osg::Vec3( xQuad * dx + spacing, yQuad * dy + spacing, 0.0 );
522  vertices->at( vIndex + 1 ) = osg::Vec3( xQuad * dx + dx - spacing, yQuad * dy + spacing, 0.0 );
523  vertices->at( vIndex + 2 ) = osg::Vec3( xQuad * dx + dx - spacing, yQuad * dy + dy - spacing, 0.0 );
524  vertices->at( vIndex + 3 ) = osg::Vec3( xQuad * dx + spacing, yQuad * dy + dy - spacing, 0.0 );
525  centers->at( qIndex ) = osg::Vec3( xQuad * dx + dx / 2.0, yQuad * dy + dy / 2.0, 0.0 );
526  colors->at( qIndex ) = osg::Vec4( 0.1 + static_cast< double >( qIndex ) / numQuads * 0.6,
527  0.1 + static_cast< double >( qIndex ) / numQuads * 0.6,
528  1.0, 1.0 );
529  }
530  }
531 
532  ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
533  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, vertices->size() ) );
534  geometry->setVertexArray( vertices );
535  geometry->setColorArray( colors );
536  geometry->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE );
537 
538  ref_ptr< osg::Vec3Array > normals = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
539  normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
540  geometry->setNormalArray( normals );
541  geometry->setNormalBinding( osg::Geometry::BIND_OVERALL );
542  osg::ref_ptr< WGESubdividedPlane > geode = osg::ref_ptr< WGESubdividedPlane >( new WGESubdividedPlane );
543  geode->addDrawable( geometry );
544  geode->setCenterArray( centers );
545 
546  // we need to disable light, since the order of the vertices may be wrong and with lighting you won't see anything but black surfaces
547  osg::StateSet* state = geode->getOrCreateStateSet();
548  state->setMode( GL_BLEND, osg::StateAttribute::ON );
549  state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
550 
551  return geode;
552 }
553 
554 osg::ref_ptr< osg::Group > wge::creatCoordinateSystem(
555  osg::Vec3 middle,
556  double sizeX,
557  double sizeY,
558  double sizeZ
559 )
560 {
561  osg::ref_ptr< WGEGroupNode >groupNode = new WGEGroupNode();
562  osg::ref_ptr< WGEShader > shaderCoordinateSystem( new WGEShader( "WGECoordinateSystem" ) );
563 
564  osg::ref_ptr< osg::Geode > graphX( new osg::Geode );
565  osg::ref_ptr< osg::Geode > graphY( new osg::Geode );
566  osg::ref_ptr< osg::Geode > graphZ( new osg::Geode );
567 
568  osg::ref_ptr< osg::Geode > graphXCylinder( new osg::Geode );
569  osg::ref_ptr< osg::Geode > graphYCylinder( new osg::Geode );
570  osg::ref_ptr< osg::Geode > graphZCylinder( new osg::Geode );
571 
572  // X
573  osg::ref_ptr< osg::ShapeDrawable > cylinderX = new osg::ShapeDrawable( new osg::Cylinder(
574  middle, 1, sizeX + ( sizeX * 0.5 )
575  ) );
576  osg::ref_ptr< osg::ShapeDrawable > cylinderXEnd = new osg::ShapeDrawable( new osg::Cylinder(
577  osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeX + ( sizeX * 0.5 ) ) / 2.0 ), 1.0, 1.0
578  ) );
579  osg::ref_ptr< osg::ShapeDrawable > coneX = new osg::ShapeDrawable( new osg::Cone(
580  osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeX + ( sizeX * 0.5 ) ) / 2.0 ), 2.0, 5.0
581  ) );
582  cylinderXEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
583  graphXCylinder->addDrawable( cylinderX );
584  graphX->addDrawable( coneX );
585  graphX->addDrawable( cylinderXEnd );
586 
587  osg::ref_ptr< osg::Material > matX = new osg::Material();
588  matX->setDiffuse( osg::Material::FRONT, WColor( 1.0, 0.0, 0.0, 1.0 ) );
589  cylinderX->getOrCreateStateSet()->setAttribute( matX, osg::StateAttribute::ON );
590  coneX->getOrCreateStateSet()->setAttribute( matX, osg::StateAttribute::ON );
591 
592  // Y
593  osg::ref_ptr< osg::ShapeDrawable > cylinderY = new osg::ShapeDrawable( new osg::Cylinder(
594  middle, 1, sizeY + ( sizeY * 0.5 )
595  ) );
596  osg::ref_ptr< osg::ShapeDrawable > cylinderYEnd = new osg::ShapeDrawable( new osg::Cylinder(
597  osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeY + ( sizeY * 0.5 ) ) / 2.0 ), 1.0, 1.0
598  ) );
599  osg::ref_ptr< osg::ShapeDrawable > coneY = new osg::ShapeDrawable( new osg::Cone(
600  osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeY + ( sizeY * 0.5 ) ) / 2.0 ), 2.0, 5.0
601  ) );
602  cylinderYEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
603 
604  graphYCylinder->addDrawable( cylinderY );
605  graphY->addDrawable( coneY );
606  graphY->addDrawable( cylinderYEnd );
607 
608  osg::ref_ptr< osg::Material > matY = new osg::Material();
609  matY->setDiffuse( osg::Material::FRONT, WColor( 0.0, 1.0, 0.0, 1.0 ) );
610  cylinderY->getOrCreateStateSet()->setAttribute( matY, osg::StateAttribute::ON );
611  coneY->getOrCreateStateSet()->setAttribute( matY, osg::StateAttribute::ON );
612 
613 
614  // Z
615  osg::ref_ptr< osg::ShapeDrawable > cylinderZ = new osg::ShapeDrawable( new osg::Cylinder(
616  middle, 1, sizeZ + ( sizeZ * 0.5 )
617  ) );
618  osg::ref_ptr< osg::ShapeDrawable > cylinderZEnd = new osg::ShapeDrawable( new osg::Cylinder(
619  osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 ), 1.0, 1.0
620  ) );
621  osg::ref_ptr< osg::ShapeDrawable > coneZ = new osg::ShapeDrawable( new osg::Cone(
622  osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 ), 2.0, 5.0
623  ) );
624  cylinderZEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
625 
626  graphZCylinder->addDrawable( cylinderZ );
627  graphZ->addDrawable( coneZ );
628  graphZ->addDrawable( cylinderZEnd );
629 
630  osg::ref_ptr< osg::Material > matZ = new osg::Material();
631  matZ->setDiffuse( osg::Material::FRONT, WColor( 0.0, 0.0, 1.0, 1.0 ) );
632  cylinderZ->getOrCreateStateSet()->setAttribute( matZ, osg::StateAttribute::ON );
633  coneZ->getOrCreateStateSet()->setAttribute( matZ, osg::StateAttribute::ON );
634 
635  shaderCoordinateSystem->apply( graphXCylinder );
636  shaderCoordinateSystem->apply( graphYCylinder );
637  shaderCoordinateSystem->apply( graphZCylinder );
638 
639  osg::ref_ptr< WGELabel > graphXLabel = new WGELabel();
640  graphXLabel->setText( "X" );
641  graphXLabel->setCharacterSize( 10 );
642  graphXLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeX + ( sizeX * 0.5 ) ) / 2.0 + 5.0 ) );
643  graphXLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
644  graphX->addDrawable( graphXLabel );
645 
646  osg::ref_ptr< WGELabel > graphYLabel = new WGELabel();
647  graphYLabel->setText( "Y" );
648  graphYLabel->setCharacterSize( 10 );
649  graphYLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeY + ( sizeY * 0.5 ) ) / 2.0 + 5.0 ) );
650  graphYLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
651  graphY->addDrawable( graphYLabel );
652 
653  osg::ref_ptr< WGELabel > graphZLabel = new WGELabel();
654  graphZLabel->setText( "Z" );
655  graphZLabel->setCharacterSize( 10 );
656  graphZLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 + 5.0 ) );
657  graphZLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
658  graphZ->addDrawable( graphZLabel );
659 
660 
661  osg::ref_ptr< osg::MatrixTransform > graphXTransform = new osg::MatrixTransform();
662  graphXTransform->addChild( graphX );
663  graphXTransform->addChild( graphXCylinder );
664  osg::ref_ptr< osg::MatrixTransform > graphYTransform = new osg::MatrixTransform();
665  graphYTransform->addChild( graphY );
666  graphYTransform->addChild( graphYCylinder );
667  osg::ref_ptr< osg::MatrixTransform > graphZTransform = new osg::MatrixTransform();
668  graphZTransform->addChild( graphZ );
669  graphZTransform->addChild( graphZCylinder );
670 
671  osg::Matrixd matrixTranslateTo0 = osg::Matrixd::translate( -middle.x(), -middle.y(), -middle.z() );
672  osg::Matrixd matrixTranslateFrom0 = osg::Matrixd::translate( middle.x(), middle.y(), middle.z() );
673 
674  graphXTransform->setMatrix( matrixTranslateTo0 * osg::Matrixd::rotate(
675  90.0 * piDouble / 180.0,
676  osg::Vec3f( 0.0, 1.0, 0.0 ) ) * matrixTranslateFrom0
677  );
678  graphYTransform->setMatrix( matrixTranslateTo0 * osg::Matrixd::rotate(
679  -90.0 * piDouble / 180.0,
680  osg::Vec3f( 1.0, 0.0, 0.0 ) ) * matrixTranslateFrom0
681  );
682 
683  groupNode->insert( graphXTransform );
684  groupNode->insert( graphYTransform );
685  groupNode->insert( graphZTransform );
686 
687  return groupNode;
688 }