Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ThreeDOutOpenSceneGraph.cpp
1 #include "ThreeDOutOpenSceneGraph.hh"
2 
3 #ifdef _WIN64
4 # undef GL_VERSION_2_1
5 #endif
6 #include <osg/Version>
7 #include <osgDB/WriteFile>
8 #include <osg/Group>
9 #include <osg/Geode>
10 #include <osg/Geometry>
11 #include <osg/Texture2D>
12 #include <osg/TexEnv>
13 #include <osg/MatrixTransform>
14 #include <osg/Billboard>
15 #include <osg/ShapeDrawable>
16 #include <osg/Point>
17 #include <osg/LineWidth>
18 #include <osg/LineStipple>
19 
20 
21 
22 
23 
24 // #include <osg/Sequence>
25 // #include <osg/PolygonMode>
26 // #include <osg/io_utils>
27 
28 #include <osgText/Font>
29 #include <osgText/Text>
30 
31 
32 
33 
34 #include <Base/Common/FileHandling.hh>
35 #include <Base/Image/ImageIO.hh>
36 #include "OpenSceneGraphHelper.hh"
37 #ifdef WIN32
38 #include <cctype>
39 #include <algorithm>
40 #endif
41 using namespace BIAS;
42 using namespace std;
43 
46  : ThreeDOut(params)
47 {
48  TexImgExtension_ = "tif";
49  NewDebugLevel("D_TDOOSG_MatrixTransform");
50 }
51 
54 {}
55 
57 OpenSceneGraphOut(const std::string &filename) const
58 {
59  //clean file name
60  std::string dir;
61  std::string base;
62  std::string suffix, fname;
63  FileHandling::SplitName(filename,dir,base,suffix);
64 
65  bool savetextures=true;
66 
67  if (suffix==".ive")
68  {
69  savetextures = false;
70  }
71 
73  if(GetSceneGraph_(sg,savetextures,filename)!=0)
74  {
75  BIASERR("GetSceneGraph failed!");
76  return(-1);
77  }
78 
79  if (suffix==""){
80  suffix = ".osg";
81  fname = dir+base+suffix;
82  } else {
83  fname = filename;
84  }
85 
86  osg::Node *myNode = sg.get();
87  std::transform( suffix.begin(), suffix.end(),
88  suffix.begin(), (int (*)(int))std::tolower );
89  BCDOUT(D_TDOOSG_MatrixTransform, "saving suffix: "<<suffix<< endl);
91  if (suffix==".wrl"){
92  BCDOUT(D_TDOOSG_MatrixTransform, "found vrml file, adding matrix "
93  <<"transform for compensation\n");
94  // osg wrl export automatically adds a transform node (rotation around
95  // x-axis). This needs to be compensated
96  mt = new osg::MatrixTransform( osg::Matrix(1, 0, 0, 0,
97  0, 0, 1, 0,
98  0, -1, 0, 0,
99  0, 0, 0, 1 ));
100  mt->addChild(sg.get());
101  mt->setName(sg->getName());
102  myNode = mt.get();
103  }
104 
105  osgDB::writeNodeFile(*myNode, fname);
106 
107  return 0;
108 }
109 
111 GetOpenSceneGraph(osg::ref_ptr<osg::Group>& sg, bool exporttextures) const
112 {
113  return(GetSceneGraph_(sg,
114  exporttextures, /*don't export textures to disc*/
115  "ThreeDOut2OSG" ));
116 }
117 
119  bool exporttextures,
120  const std::string &filename ) const
121 {
122  //sg = new osg::Group();
123 
124  //set root transform node
125  sg = new osg::MatrixTransform; //create transform node which is also a group
126  sg->setName("RootTransform");
127 
128  osg::Node *newNode;
129 
130  AddOSGPMatrix_(sg);
131  AddOSGPoints_(sg);
132  AddOSGLines_(sg);
133  AddOSGEllipsoids_(sg);
134  AddOSGTexts_(sg);
135  // graph filename is used for texture filename generation
136  AddOSGImage_(sg,exporttextures,filename);
137  newNode = AddOSGIndexedFaceSets_(exporttextures,filename);
138  if (newNode != NULL) sg->addChild(newNode);
139  return(0);
140 }
141 
142 
143 
144 osg::Node* ThreeDOutOpenSceneGraph::
145 AddOSGIndexedFaceSets_(bool exportTextures,
146  std::string graphfilename) const
147 {
148  if(mapIndexedFaceSet_.empty()) return NULL;
149 
150  //loop through indexed face sets
151  osg::MatrixTransform* mTrans =
152  new osg::MatrixTransform;
153  mTrans->setName("IndexedFaceSetsTransform");
154 
155  unsigned int texcount=0;
156 
157  map<unsigned int, IndexedFaceSet>::const_iterator it;
158  for(it=mapIndexedFaceSet_.begin(); it!=mapIndexedFaceSet_.end(); it++ )
159  {
160  //add geometry node for every face set
161  //add drawable for every face set
162  osg::Geode* mGeode = new osg::Geode();
163 #if OPENSCENEGRAPH_MAJOR_VERSION < 3 || (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION <= 1)
164  osg::Geometry* mGeometry = new osg::Geometry();
165 #else
166  deprecated_osg::Geometry* mGeometry = new deprecated_osg::Geometry();
167 #endif
168  mGeode->addDrawable(mGeometry);
169  //rootNode->addChild(mGeode);
170 
171  osg::MatrixTransform* mObjTrans =
172  new osg::MatrixTransform;
173  mObjTrans->setName(it->second.name+"Transform");
174  mTrans->addChild(mObjTrans);
175  mObjTrans->addChild(mGeode);
176  mGeode->setName(it->second.name);
177 
178  //copy vertices:
179  //create new vertex array
180  const unsigned int vertNumb = it->second.vertexSet.size();
181  osg::Vec3Array* vertices = new osg::Vec3Array(vertNumb);
182  //loop through vertices
183  for(unsigned int vt = 0; vt < vertNumb; vt++)
184  {
185  //set vertices
186  const BIAS::Vector3<double> &vertexBIAS = it->second.vertexSet[vt];
187  (*vertices)[vt].set(vertexBIAS[0],vertexBIAS[1],vertexBIAS[2]);
188  }
189  //attach vertex array to
190  mGeometry->setVertexArray(vertices);
191 
192  //set texture coordinates
193  if (it->second.useTexture) {
194  unsigned int texCoordNumb = it->second.texCoordSet.size();
195  if(texCoordNumb!= vertNumb)
196  {
197  BIASWARN("Number of texture coordinates does not match vertex number.");
198  }
199 
200  osg::Vec2Array* texCoords = new osg::Vec2Array(texCoordNumb);
201  for(unsigned int tc=0; tc<texCoordNumb; tc++)
202  {
203  BIAS::Vector2<float> texCoordBIAS = it->second.texCoordSet[tc];
204  (*texCoords)[tc].set(texCoordBIAS[0],texCoordBIAS[1]);
205  }
206  mGeometry->setTexCoordArray(0,texCoords);
207  }
208 
209  //set faces:
210  //loop through faces
211  const unsigned int faceNumb = it->second.faceIndices.size();
212 
213  osg::DrawElementsUInt* drawTriangleElmtsU=NULL;
214  osg::DrawElementsUInt* drawQuadsElmtsU=NULL;
215 
216  for(unsigned int fc = 0; fc<faceNumb ; fc++)
217  {
218  // get number of indices of actual face
219  // this number might vary from face to face although most likely triangles
220  // and quads will occure.
221  unsigned int indexNum = it->second.faceIndices[fc].Size();
222  osg::DrawElementsUInt* actualFace;
223  switch(indexNum)
224  {
225  case 3:
226  //use for all triangles the same "index buffer"
227  if(drawTriangleElmtsU==NULL)
228  {
229  drawTriangleElmtsU =
230  new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
231  mGeometry->addPrimitiveSet(drawTriangleElmtsU);
232  }
233  actualFace = drawTriangleElmtsU;
234  break;
235  case 4:
236  if(drawQuadsElmtsU==NULL)
237  {
238  drawQuadsElmtsU =
239  new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS);
240  mGeometry->addPrimitiveSet(drawQuadsElmtsU);
241  }
242  actualFace = drawQuadsElmtsU;
243  break;
244  default:
245  actualFace =
246  new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON);
247  mGeometry->addPrimitiveSet(actualFace);
248  }
249  //loop through indices
250  for(unsigned int ix = 0; ix<indexNum; ix++)
251  {
252  //bias stores face indices as int
253  int idx = (it->second.faceIndices[fc])[ix];
254  BIASASSERT(idx>=0);
255  actualFace->push_back((unsigned int) idx);
256  }
257  }
258 
259  // set colors
260  if (it->second.useColoredVertices) {
261  if (it->second.vertexColorSet.size() > 0) {
262  osg::Vec4Array* colours = new osg::Vec4Array();
263  colours->reserve(it->second.vertexColorSet.size());
264 
265  for (size_t colourCount = 0;
266  colourCount < it->second.vertexColorSet.size();
267  ++colourCount) {
268  const Vector4<unsigned char> &colour
269  = it->second.vertexColorSet[colourCount];
270  colours->push_back(osg::Vec4(float(colour[0]) / 255.0f,
271  float(colour[1]) / 255.0f,
272  float(colour[2]) / 255.0f,
273  float(colour[3]) / 255.0f));
274  }
275 
276  mGeometry->setColorArray(colours);
277 #if OPENSCENEGRAPH_MAJOR_VERSION < 3 || (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION <= 1)
278  mGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
279 #else
280  mGeometry->setColorBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);
281 #endif
282  }
283  }
284 
285  // set normals
286  if (it->second.useNormals && it->second.NormalArray) {
287  osg::Vec3Array* normals = new osg::Vec3Array();
288  normals->reserve(it->second.vertexSet.size());
289 
290  for (size_t normalCount = 0;
291  normalCount < it->second.vertexSet.size();
292  ++normalCount) {
293  const size_t offset = normalCount * 3;
294 
295  normals->push_back(osg::Vec3(it->second.NormalArray[offset],
296  it->second.NormalArray[offset + 1],
297  it->second.NormalArray[offset + 2]));
298  }
299 
300  mGeometry->setNormalArray(normals);
301 #if OPENSCENEGRAPH_MAJOR_VERSION < 3 || (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION <= 1)
302  mGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
303 #else
304  mGeometry->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);
305 #endif
306  }
307 
308  //set and save texture
309  if (it->second.useTexture) {
310  osg::Image* mImage = new osg::Image;
311  //mImage->setAllocationMode(osg::Image::NO_DELETE);
312  string tmptexfilename = GenerateFilename_(graphfilename,
313  it->second.name,
314  texcount);
315 
316  // image data copying to the osgimage could be avoided for 3-4 channel
317  // images if the scene graph is exported to disk only.
318  // in this case the flag BIASimageToOSGimage_ could be set to "false".
319  // the bias::image could be saved using bias:ImageIO.
320  // this however will fail for 1 or 2 channel images at the moment thus
321  // the osg::image export routines are used which requires memcpy.
322  if(OpenSceneGraphHelper::BIASimageToOSGimage(it->second.texture,mImage,true /*!exportTextures*/))
323  {
324  if(exportTextures)
325  {
326  if(!osgDB::writeImageFile(*mImage,tmptexfilename))
327  {
328  BIASWARN("could not save texture.");
329  }
330  mImage->setFileName(tmptexfilename);
331  }
332  osg::ref_ptr< osg::Texture2D > mTex2D = new osg::Texture2D;
333  mTex2D->setImage( mImage );
334 
335  osg::StateSet *ss = new osg::StateSet;
336  ss->setTextureAttributeAndModes(0, mTex2D.get());
337 
338  //disable modulation of texture and vertex colors
339  //because the bias meshes have no vertex color data.
340  osg::TexEnv *txenv = new osg::TexEnv(osg::TexEnv::REPLACE);
341  ss->setTextureAttribute(0, txenv);
342 
343  //delete image after creating opengl texture - is this needed in our case?
344  //mTex2D->setUnRefImageDataAfterApply(true);
345  mGeode->setStateSet(ss);
346  } //biasimage export
347  texcount++;
348  }
349  }
350  return mTrans;
351 }
352 
353 std::string ThreeDOutOpenSceneGraph::
354 GenerateFilename_(std::string graphfilename,std::string subname,
355  unsigned int texnumber) const
356 {
357 
358  std::string dir;
359  std::string base;
360  std::string suffix;
361 
362  FileHandling::SplitName(graphfilename,dir,base,suffix);
363 
364  //add texcounter to subname
365  std::stringstream sstr;
366  sstr << setfill ('0')<< setw(3) << texnumber;
367  return(dir+base+subname+sstr.str()+"."+TexImgExtension_);
368 }
369 
370 
371 
374 {
375  if(mapLines_.empty())return;
376  //add transform node
377  osg::MatrixTransform* mTrans = new osg::MatrixTransform;
378  mTrans->setName("LineSetTransform");
379  rootNode->addChild(mTrans);
380 
381  //geometry node
382  osg::Geode* mGeode = new osg::Geode;
383  mGeode->setName("Lines");
384 
385  //create geometry class as drawable geometry to geometry node
386 #if OPENSCENEGRAPH_MAJOR_VERSION < 3 || (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION <= 1)
387  osg::Geometry* mGeometry = new osg::Geometry;
388 #else
389  deprecated_osg::Geometry* mGeometry = new deprecated_osg::Geometry;
390 #endif
391  mGeode->addDrawable(mGeometry);
392  mTrans->addChild(mGeode);
393 
394  osg::Vec3Array* vertices = new osg::Vec3Array;
395  osg::Vec4ubArray* colors = new osg::Vec4ubArray;
396 
397  if (Params_.LineWidth < 1) return ;
398 
399  osg::StateSet* ss = new osg::StateSet;
400  osg::LineWidth* lw = new osg::LineWidth;
401  ss->setAttribute(lw);
402  //disable lighting for points
403  ss->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED
404  | osg::StateAttribute::OFF );
405  lw->setWidth((float)Params_.LineWidth);
406  //FIXME line stipple doesn't seem to work...
408  {
409  osg::LineStipple* ls = new osg::LineStipple;
410  ls->setPattern(0x0f0f); //set 00001111 00001111 as line pattern
411  ls->setFactor(5);
412  ss->setAttributeAndModes(ls);
413  }
414  mGeode->setStateSet(ss);
415 
416  map<unsigned int, Line3DData>::const_iterator it;
417  for (it=mapLines_.begin(); it!=mapLines_.end(); it++)
418  {
419  Vector3<double> pt1 = it->second.Start;
420  Vector3<double> pt2 = it->second.End;
421  RGBAuc col = it->second.Color;
422  vertices->push_back(osg::Vec3(pt1[0], pt1[1], pt1[2]));
423  vertices->push_back(osg::Vec3(pt2[0], pt2[1], pt2[2]));
424  //bias threedout lines have only on color
425  colors->push_back(osg::Vec4ub(col[0],col[1],col[2],col[3]));
426  }
427 
428  mGeometry->setVertexArray(vertices);
429  mGeometry->setColorArray(colors);
430 #if OPENSCENEGRAPH_MAJOR_VERSION < 3 || (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION <= 1)
431  mGeometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
432 #else
433  mGeometry->setColorBinding(deprecated_osg::Geometry::BIND_PER_PRIMITIVE);
434 #endif
435  mGeometry->addPrimitiveSet(
436  new osg::DrawArrays(osg::DrawArrays::LINES,0,mapLines_.size()*2));
437 
438 }
439 
442  bool camEllipsoids) const
443 {
444  // transform node
445  osg::ref_ptr<osg::MatrixTransform> mTrans = new osg::MatrixTransform;
446  const std::map<unsigned int, Ellipsoid3DData>* actualElipsoidMap;
447  if(camEllipsoids)
448  {
449  mTrans->setName("CamEllipsoidSetTransform");
450  actualElipsoidMap = &mapCamEllipsoids_;
451  }
452  else
453  {
454  mTrans->setName("EllipsoidSetTransform");
455  actualElipsoidMap = &mapEllipsoids_;
456  }
457 
458  if(actualElipsoidMap->empty())
459  {
460  return;
461  }
462 
463  rootNode->addChild(mTrans);
464 
465  map<unsigned int, Ellipsoid3DData>::const_iterator it;
466  for(it=actualElipsoidMap->begin(); it!=actualElipsoidMap->end(); it++)
467  {
468  //create transform node for every ellipsoid
469  osg::MatrixTransform* mTransEllip =
470  new osg::MatrixTransform;
471  mTrans->addChild(mTransEllip);
472  osg::Matrixd transf;
473  osg::Matrixd transl;
474  osg::Matrixd rota; //makeRotate
475  osg::Matrixd scale;
476  //first scale to ellipsoid shape
477  scale.makeScale(it->second.s0 * Params_.EllipsoidScale,
478  it->second.s1 * Params_.EllipsoidScale,
479  it->second.s2 * Params_.EllipsoidScale);
480  rota.makeRotate(it->second.dAngle,
481  it->second.RotAxis[0],
482  it->second.RotAxis[1],
483  it->second.RotAxis[2]
484  );
485  transl.makeTranslate(it->second.C[0],it->second.C[1],it->second.C[2]);
486 
487  transf = scale*rota*transl;
488  mTransEllip->setMatrix(transf);
489 
490  osg::Geode* mGeode;
491  osg::Sphere* mSphere = new osg::Sphere(osg::Vec3(0,0,0),1.0);
492  osg::ShapeDrawable* sphereDrawable = new osg::ShapeDrawable(mSphere);
493  sphereDrawable->setColor(osg::Vec4(it->second.Color[0],
494  it->second.Color[1],
495  it->second.Color[2],
496  it->second.Color[3]));
497  mGeode = new osg::Geode();
498  mGeode->addDrawable(sphereDrawable);
499  mTransEllip->addChild(mGeode);
500  }
501 }
502 
503 
506 {
507  if(mapPoints_.empty()) return ;
508  // transform node
509  osg::MatrixTransform* mTrans =
510  new osg::MatrixTransform;
511  mTrans->setName("PointSetTransform");
512  rootNode->addChild(mTrans);
513 
514  //geometry node
515  osg::ref_ptr<osg::Geode> mGeode = new osg::Geode;
516  mGeode->setName("Points");
517  mGeode->setCullingActive(false);
518 
519  //create geometry class as drawable geometry to geometry node
520  osg::ref_ptr<osg::Geometry> mGeometry = new osg::Geometry;
521  mGeode->addDrawable(mGeometry);
522  mTrans->addChild(mGeode);
523 
524 
525  osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
526  osg::ref_ptr<osg::Point> p = new osg::Point;
527  // dont set the the attribute to allow client program (glutGLviewer) to set this itself, fkellner FIXME
528  // ss->setAttribute(p);
529  p->setSize(Params_.PointSize);
530  mGeode->setStateSet(ss);
531 
532  //disable lighting for points
533  ss->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED
534  | osg::StateAttribute::OFF );
535  //TODO implement different pointstyles like pointsprite
536  if(Params_.PointStyle != Point)
537  {
538  BIASWARN("unsupported PointDrawingStyle.");
539  }
540  // now add internally cached stuff from ThreeDOut
541  //create vertex and color arrays for point data
542  osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
543  osg::ref_ptr<osg::Vec4ubArray> colors = new osg::Vec4ubArray;
544  //loop through point data and store it in geometry class
545  map<unsigned int, BIAS::Point3DData>::const_iterator it;
546  for (it=mapPoints_.begin(); it!=mapPoints_.end(); it++)
547  {
548  Vector3<double> pt = it->second.Point;
549  RGBAuc col = it->second.Color;
550  vertices->push_back(osg::Vec3(pt[0], pt[1], pt[2]));
551  colors->push_back(osg::Vec4ub(col[0],col[1],col[2],col[3]));
552  // colors->push_back(osg::Vec4(((float)col[0]/255.0f),((float)col[1]/255.0f),((float)col[2]/255.0f),((float)col[3]/255.0f)));
553  }
554  mGeometry->setVertexArray(vertices);
555  mGeometry->setColorArray(colors);
556  mGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
557  mGeometry->addPrimitiveSet(
558  new osg::DrawArrays(osg::DrawArrays::POINTS,0,mapPoints_.size()));
559 }
560 
561 
562 
563 
564 
567 {
568  if(mapPMatrices_.empty())return;
569  if (Params_.CameraScale<=0.0) return;
571  new osg::MatrixTransform;
572  mTrans->setName("CameraSetTransform");
573  rootNode->addChild(mTrans.get());
574  osg::Geode* mGeode = new osg::Geode;
575  mGeode->setName("Cameras");
576  mTrans->addChild(mGeode);
577 
578  osg::ref_ptr<osg::Group> transgroup = mTrans.get();
579  AddOSGEllipsoids_(transgroup,true);
580 
581  unsigned int idxOffset=0;
582 
583 
584  // create state set for point parameters
585  osg::StateSet* ss = new osg::StateSet;
586  osg::Point* p = new osg::Point;
587  // dont set the the attribute to allow client program (glutGLviewer) to set this itself, fkellner FIXME
588  //ss->setAttribute(p);
589  p->setSize(Params_.PointSize);
590 
591  //set line width
592  osg::LineWidth* lw = new osg::LineWidth;
593  // dont set the the attribute to allow client program (glutGLviewer) to set this itself, fkellner FIXME
594  //ss->setAttribute(lw);
595  //disable lighting for points
596  ss->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED
597  | osg::StateAttribute::OFF );
598  lw->setWidth((float)Params_.LineWidth);
599  mGeode->setStateSet(ss);
601  {
602  osg::LineStipple* ls = new osg::LineStipple;
603  ls->setPattern(0x0f0f); //set 00001111 00001111 as line pattern
604  ls->setFactor(128);
605  ss->setAttributeAndModes(ls);
606  }
607 
608 
609  map<unsigned int, PMatrix3DData>::const_iterator it;
610  for (it=mapPMatrices_.begin(); it!=mapPMatrices_.end(); it++)
611  {
612  //create geometry class as drawable geometry to geometry node
613  osg::Geometry* mGeometry = new osg::Geometry;
614  mGeode->addDrawable(mGeometry);
615  osg::DrawElementsUInt* drawElmtsU=NULL;
616 
618  {
619  drawElmtsU = new osg::DrawElementsUInt(osg::PrimitiveSet::LINES);
620  }
621  else
622  {
623  drawElmtsU = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
624  }
625 
626  //create index set for points
627  osg::DrawElementsUInt* drawElmtsPointsU=
628  new osg::DrawElementsUInt(osg::PrimitiveSet::POINTS);
629 
630  const PMatrix3DData *i = &(it->second);
631  mGeometry->setName(i->name);
632 
633  //the camera center is needed in all render cases
634  osg::Vec3Array* vertices = new osg::Vec3Array;
635  osg::Vec4ubArray* colors = new osg::Vec4ubArray;
636 
637  osg::Vec3 vC = osg::Vec3(i->C[0],i->C[1],i->C[2]);
638  vertices->push_back(vC) ;//center has index 0
639  RGBAuc col = i->Color;
640  // color for the point
641  colors->push_back(osg::Vec4ub(col[0],col[1],col[2],col[3]));
642  // color for the line strip/triangles etc.
643  colors->push_back(osg::Vec4ub(col[0],col[1],col[2],col[3]));
644  idxOffset = 1;
645 
646  drawElmtsPointsU->push_back(0); //add center as point
647 
648  //add the pyramid vertices to vertex list
650  {
651 
652  osg::Vec3 vUR = osg::Vec3(i->UR[0],i->UR[1],i->UR[2]);
653  osg::Vec3 vUL = osg::Vec3(i->UL[0],i->UL[1],i->UL[2]);
654  osg::Vec3 vLL = osg::Vec3(i->LL[0],i->LL[1],i->LL[2]);
655  osg::Vec3 vLR = osg::Vec3(i->LR[0],i->LR[1],i->LR[2]);
656 
657  //scaling : move to 0,0,0, Params_.CameraScale, move back to center
658  vUR = ((vUR - vC) * Params_.CameraScale) + vC ;
659  vUL = ((vUL - vC) * Params_.CameraScale) + vC ;
660  vLL = ((vLL - vC) * Params_.CameraScale) + vC ;
661  vLR = ((vLR - vC) * Params_.CameraScale) + vC ;
662 
663  vertices->push_back(vUR);//1
664  vertices->push_back(vUL);//2
665  vertices->push_back(vLL);//3
666  vertices->push_back(vLR);//4
667  idxOffset = 5;
668 
669  // add sphere at top letf image corner
670  osg::ref_ptr<osg::MatrixTransform> mTrans = new osg::MatrixTransform();
671  osg::Matrixd identitymat;
672  identitymat.makeIdentity();
673  mTrans->setMatrix(identitymat);
674  rootNode->addChild(mTrans);
675  osg::Geode* mGeode;
676  osg::Sphere* mSphere = new osg::Sphere(osg::Vec3(vUL[0],vUL[1],vUL[2]),
677  Params_.CameraScale/100.0);
678  osg::TessellationHints *fewfaces = new osg::TessellationHints;
679  fewfaces->setTargetNumFaces(4);
680  fewfaces->setTessellationMode(osg::TessellationHints::USE_TARGET_NUM_FACES);
681 
682 
683  osg::ShapeDrawable* sphereDrawable = new osg::ShapeDrawable(mSphere,fewfaces);
684  sphereDrawable->setColor(osg::Vec4f(float(col[0]),
685  float(col[1]),
686  float(col[2]),
687  float(col[3])));
688 
689  mGeode = new osg::Geode();
690  mGeode->addDrawable(sphereDrawable);
691  mTrans->addChild(mGeode);
692 
693  }
694 
695  switch (Params_.CameraStyle)
696  {
698  case PyramidMesh:
700  {
701  //draw lines of pyramid
702  //add line indices
703  drawElmtsU->push_back(0);drawElmtsU->push_back(1);
704  drawElmtsU->push_back(0);drawElmtsU->push_back(2);
705  drawElmtsU->push_back(0);drawElmtsU->push_back(3);
706  drawElmtsU->push_back(0);drawElmtsU->push_back(4);
707  drawElmtsU->push_back(1);drawElmtsU->push_back(2);
708  drawElmtsU->push_back(2);drawElmtsU->push_back(3);
709  drawElmtsU->push_back(3);drawElmtsU->push_back(4);
710  drawElmtsU->push_back(4);drawElmtsU->push_back(1);
711  //draw no arrow? break!
712  if (Params_.CameraStyle==PyramidMesh) break; //no point for mesh...
713  }
714  case Arrow:
715  {
716  if (Params_.LineWidth < 1) break;
717  //draw arrow
720  {
721  osg::Vec3 vPP = osg::Vec3(i->PP[0],i->PP[1],i->PP[2]);
722  vertices->push_back(vPP); //idxOffset + 0;
723  osg::Vec3 vUPC = osg::Vec3(i->C[0] ,i->C[1] ,i->C[2])+
724  osg::Vec3(i->Up[0],i->Up[1],i->Up[2]);
725  vertices->push_back(vUPC);
726  drawElmtsU->push_back(0);drawElmtsU->push_back(idxOffset);
727  drawElmtsU->push_back(0);drawElmtsU->push_back(idxOffset+1);
728  }
729  break;
730  }
731  case PyramidSolid:
732  {
733  drawElmtsU->push_back(0);drawElmtsU->push_back(1);
734  drawElmtsU->push_back(2);
735  drawElmtsU->push_back(0);drawElmtsU->push_back(3);
736  drawElmtsU->push_back(4);
737  drawElmtsU->push_back(0);drawElmtsU->push_back(4);
738  drawElmtsU->push_back(1);
739  drawElmtsU->push_back(0);drawElmtsU->push_back(2);
740  drawElmtsU->push_back(3);
741  drawElmtsU->push_back(1);drawElmtsU->push_back(3);
742  drawElmtsU->push_back(2);
743  drawElmtsU->push_back(1);drawElmtsU->push_back(4);
744  drawElmtsU->push_back(3);
745  break;
746  }
747  default:
748  {
749  BIASERR("unexpected pmatrix draw style");
750  BIASABORT;
751  }
752  } //switch
753  mGeometry->setVertexArray(vertices);
754  mGeometry->setColorArray(colors);
755  mGeometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
756  mGeometry->addPrimitiveSet(drawElmtsPointsU);
757  mGeometry->addPrimitiveSet(drawElmtsU);
758  } //loop through pmatrices
759 }
760 
761 
764  bool exportTextures,
765  std::string graphfilename) const
766 {
767  if(mapImages_.empty())return;
768  //billboarding in osg?
769  //http://www.openscenegraph.org/documentation/NPSTutorials/osgBillboard.htm
770  //http://www.openscenegraph.org/documentation/OpenSceneGraphReferenceDocs/a01041.html
771  unsigned int texcount=0;
772  map<unsigned int, Image3DData>::const_iterator it;
773  for (it = mapImages_.begin(); it!=mapImages_.end(); it++)
774  {
775 
776  osg::Geometry* mGeometry = new osg::Geometry();
777  osg::Geode* mGeode = 0;
778  osg::Billboard* mBB = 0;
779  if(it->second.BillBoard)
780  {
781  // set billboard rotation
782  mBB = new osg::Billboard();
783  rootNode->addChild(mBB);
784  mBB->setMode(osg::Billboard::AXIAL_ROT); //POINT_ROT_EYE POINT_ROT_WORLD
785  mBB->setAxis(osg::Vec3(0.0f,1.0f,0.0f));
786  mBB->setNormal(osg::Vec3(0.0f,0.0f,1.0f));
787 
788  rootNode->addChild(mBB);
789  mBB->setName(it->second.name);
790  }
791  else // not a billboard
792  {
793  mGeode = new osg::Geode();
794  mGeode->addDrawable(mGeometry);
795  rootNode->addChild(mGeode);
796  mGeode->setName(it->second.name);
797  }
798 
799  //create new vertex array
800  osg::Vec3Array* vertices = new osg::Vec3Array(4);
801  if(!it->second.BillBoard)
802  {
803  (*vertices)[0].set(it->second.UL[0],it->second.UL[1],it->second.UL[2]);
804  (*vertices)[1].set(it->second.LL[0],it->second.LL[1],it->second.LL[2]);
805  (*vertices)[2].set(it->second.LR[0],it->second.LR[1],it->second.LR[2]);
806  (*vertices)[3].set(it->second.UR[0],it->second.UR[1],it->second.UR[2]);
807  }
808  else
809  {
810  //adjust vertices for billboard usage
811  BIAS::Vector3<double> bbcenter = it->second.UL + it->second.LR ;
812  bbcenter.MultIP(0.5); //get center of image
813 
814  (*vertices)[0].set(it->second.UL[0]-bbcenter[0],
815  it->second.UL[1]-bbcenter[1],
816  it->second.UL[2]-bbcenter[2]);
817  (*vertices)[1].set(it->second.LL[0]-bbcenter[0],
818  it->second.LL[1]-bbcenter[1]
819  ,it->second.LL[2]-bbcenter[2]);
820  (*vertices)[2].set(it->second.LR[0]-bbcenter[0],
821  it->second.LR[1]-bbcenter[1],
822  it->second.LR[2]-bbcenter[2]);
823  (*vertices)[3].set(it->second.UR[0]-bbcenter[0],
824  it->second.UR[1]-bbcenter[1],
825  it->second.UR[2]-bbcenter[2]);
826  /* To help place billboards there is an overload to
827  osg::Geode's addGeometry method. This method takes two arguments:
828  a drawable instance and an osg::Vec3 instance for position.*/
829  mBB->addDrawable( mGeometry, osg::Vec3(bbcenter[0],
830  bbcenter[1],
831  bbcenter[2]));
832  }
833  //attach vertex array to
834  mGeometry->setVertexArray(vertices);
835 
836  osg::DrawElementsUInt* actualFace;
837  actualFace = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS);
838  mGeometry->addPrimitiveSet(actualFace);
839  actualFace->push_back((unsigned int) 0);
840  actualFace->push_back((unsigned int) 1);
841  actualFace->push_back((unsigned int) 2);
842  actualFace->push_back((unsigned int) 3);
843 
844  //texture coordinates
845  osg::Vec2Array* texCoords = new osg::Vec2Array(4);
846  (*texCoords)[0].set(0,1);
847  (*texCoords)[1].set(0,0);
848  (*texCoords)[2].set(1,0);
849  (*texCoords)[3].set(1,1);
850  mGeometry->setTexCoordArray(0,texCoords);
851 
852  //texture
853  //set and save texture
854  osg::Image* mImage = new osg::Image;
855  string tmptexfilename = GenerateFilename_(graphfilename,
856  string("img")+it->second.name,texcount);
857 
858  osg::StateSet *ss = new osg::StateSet;
859 
860  if(OpenSceneGraphHelper::BIASimageToOSGimage(it->second.ImageData,mImage,!exportTextures))
861  {
862  if(exportTextures)
863  {
864  if(ImageIO::Save(tmptexfilename,it->second.ImageData)==-1)
865  {
866  BIASWARN("could not save texture.");
867  }
868  }
869  mImage->setFileName(tmptexfilename);
870  osg::ref_ptr< osg::Texture2D > mTex2D = new osg::Texture2D;
871  mTex2D->setImage( mImage );
872 
873 
874  ss->setTextureAttributeAndModes(0, mTex2D.get());
875  //disable modulation of texture and vertex colors
876  //because the bias meshes have no vertex color data.
877  osg::TexEnv *txenv = new osg::TexEnv(osg::TexEnv::REPLACE);
878  ss->setTextureAttribute(0, txenv);
879  }
880  if(it->second.BillBoard)
881  {
882  mBB->setStateSet(ss);
883  }
884  else
885  {
886  mGeode->setStateSet(ss);
887  }
888  texcount++;
889  }//for
890 
891 }
892 
893 
895 
896  if(mapTexts_.empty()) return ;
897  // transform node
898  osg::MatrixTransform* mTrans = new osg::MatrixTransform;
899  mTrans->setName("TextTransform");
900  rootNode->addChild(mTrans);
901 
902  //loop through text data
903  map<unsigned int, BIAS::Text3DData>::const_iterator it;
904  for (it=mapTexts_.begin(); it!=mapTexts_.end(); it++) {
905 
906  osg::ref_ptr<osg::Geode> mGeode = new osg::Geode;
907  mGeode->setName("Text");
908  mGeode->setCullingActive(false);
909  mTrans->addChild(mGeode);
910 
911  osgText::Text* text4 = new osgText::Text;
912  text4->setFont("fonts/times.ttf");
913 
914  if (it->second.Size>0.0)
915  text4->setCharacterSize(it->second.Size);
916  else {
917  double thesize = -1.0 * it->second.Size;
918  if (thesize<5) thesize = 5;
919  text4->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
920  text4->setCharacterSize(thesize);
921  }
922  text4->setPosition(osg::Vec3(it->second.Position[0],
923  it->second.Position[1],
924  it->second.Position[2]));
925 
926 
927 
928  if (it->second.Direction.NormL2()>0.0) {
929  Quaternion<double> q = it->second.Direction;
930  /*
931  Vector3<double> dir
932  dir.Normalize();
933  cout<<"dir is "<<dir<<endl;
934  RMatrix R;
935 
936  Vector3<double> ydir(0.0,1.0,0.0), zdir(0.0,0.0,1.0);
937  if (fabs(dir.ScalarProduct(ydir) < fabs(dir.ScalarProduct(zdir)))) {
938  cout<<"y is more orthogonal to x than z is"<<endl;
939  zdir = dir.CrossProduct(ydir);
940  zdir.Normalize();
941  ydir = zdir.CrossProduct(dir);
942  } else {
943  cout<<"z is more orthogonal to x than y is"<<endl;
944  ydir = zdir.CrossProduct(dir);
945  ydir.Normalize();
946  zdir = dir.CrossProduct(ydir);
947  }
948  for (unsigned int i=0; i<3; i++) {
949  R[i][0] = dir[i];
950  R[i][1] = ydir[i];
951  R[i][2] = zdir[i];
952  }
953  cout<<"R is "<<R<<" with RTR = "<<R*R.Transpose()<<endl;
954  Quaternion<double> q;
955  R.GetQuaternion(q);
956  */
957  text4->setRotation(osg::Quat(q[0], q[1], q[2], q[3]));
958  } else {
959  text4->setAxisAlignment(osgText::Text::SCREEN);
960  text4->setAlignment(osgText::Text::CENTER_CENTER);
961  }
962  // text4->setAxisAlignment(osgText::Text::XZ_PLANE);
963  // reproduce outline bounding box compute problem with backdrop on.
964  text4->setBackdropType(osgText::Text::OUTLINE);
965  //text4->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
966 
967  text4->setColor(osg::Vec4(float(it->second.Color[0])/255.0, float(it->second.Color[1])/255.0,
968  float(it->second.Color[2])/255.0,float(it->second.Color[3])/255.0));
969  text4->setText(it->second.Text);
970  mGeode->addDrawable(text4);
971 
972  }
973 }
974 
975 
976 
977 
978 
979 
980 
981 
982 
983 
984 
985 
int GetSceneGraph_(osg::ref_ptr< osg::Group > &sg, bool exporttextures, const std::string &filename) const
osg::Node * AddOSGIndexedFaceSets_(bool exporttextures, std::string graphfilename) const
create one transform (IndexedFaceSets), add another transform for each indexed face set...
std::map< unsigned int, Text3DData > mapTexts_
map of all point structures
Definition: ThreeDOut.hh:999
std::map< unsigned int, Image3DData > mapImages_
map of all image structures
Definition: ThreeDOut.hh:989
int OpenSceneGraphOut(const std::string &filename) const
save ThreeDOut object as OpenSceneGraph saves an Open Scene Graph and the needed textures ...
Unified output of 3D entities via OpenGL or VRML.
Definition: ThreeDOut.hh:349
BIAS::Vector3< double > LL
lower left corner of image plane in wcs
std::string GenerateFilename_(std::string graphfilename, std::string subname, unsigned int texnumber) const
ThreeDOutParameters Params_
holds the params set by constructor or SetParams
Definition: ThreeDOut.hh:981
configuration struct for drawing styles of various 3d objects
Definition: ThreeDOut.hh:309
ThreeDOutOpenSceneGraph(const BIAS::ThreeDOutParameters &params=BIAS::ThreeDOutParameters())
BIAS::RGBAuc Color
RGBA color+opacity, 255=opaque, 0=transp.
std::map< unsigned int, Line3DData > mapLines_
map of all line structures
Definition: ThreeDOut.hh:1004
stores important data for drawing a camera
std::map< unsigned int, Point3DData > mapPoints_
map of all point structures
Definition: ThreeDOut.hh:994
CameraDrawingStyle CameraStyle
Definition: ThreeDOut.hh:313
void AddOSGLines_(osg::ref_ptr< osg::Group > &Rootnode) const
BIAS::Vector3< double > UL
upper left corner of image plane in wcs
class Vec3f Vec3
void AddOSGImage_(osg::ref_ptr< osg::Group > &Rootnode, bool exportTextures, std::string graphfilename) const
static void SplitName(const std::string &fullname, std::string &dir, std::string &base, std::string &suffix)
Split full path into:
class Matrixd Matrix
LineDrawingStyle LineStyle
Definition: ThreeDOut.hh:314
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
Definition: Debug.hh:474
static bool BIASimageToOSGimage(const BIAS::Image< unsigned char > &in, osg::Image *out, bool copydata)
conversion function
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
BIAS::Vector3< double > UR
upper right corner of image plane in wcs
void AddOSGPMatrix_(osg::ref_ptr< osg::Group > &rootNode) const
void AddOSGPoints_(osg::ref_ptr< osg::Group > &Rootnode) const
void MultIP(const T &scalar)
Definition: Vector3.hh:327
std::map< unsigned int, IndexedFaceSet > mapIndexedFaceSet_
Definition: ThreeDOut.hh:1018
BIAS::Vector3< double > PP
principle point in wcs
BIAS::Vector3< double > Up
Up-Vector (V)
PointDrawingStyle PointStyle
Definition: ThreeDOut.hh:312
std::map< unsigned int, PMatrix3DData > mapPMatrices_
the cameras are saved in a vector for efficiency reasons
Definition: ThreeDOut.hh:984
std::map< unsigned int, Ellipsoid3DData > mapCamEllipsoids_
map of all ellipsoid structures
Definition: ThreeDOut.hh:1014
void AddOSGTexts_(osg::ref_ptr< osg::Group > &Rootnode) const
BIAS::Vector3< double > C
camera center in wcs
BIAS::Vector3< double > LR
lower right corner of image plane in wcs
void AddOSGEllipsoids_(osg::ref_ptr< osg::Group > &rootNode, bool camEllipsoids=false) const
int GetOpenSceneGraph(osg::ref_ptr< osg::Group > &sg, bool exporttextures=false) const
Get ThreeDOut object as OpenSceneGraph structure.
std::map< unsigned int, Ellipsoid3DData > mapEllipsoids_
map of all ellipsoid structures
Definition: ThreeDOut.hh:1009