1 /*
2  *
3  * OSG to VRML2 converter for OpenSceneGraph.
4  *
5  * authors :
6  *           Johan Nouvel (johan_nouvel@yahoo.com)
7  *
8  *
9  */
10 
11 #include "ConvertToVRML.h"
12 #include <iostream>
13 #include <string.h>
14 #include <limits>
15 #include <osg/Quat>
16 #include <osg/Geometry>
17 #include <osg/Material>
18 #include <osg/StateSet>
19 #include <osg/TexGen>
20 #include <osg/TexEnv>
21 #include <osg/BoundingSphere>
22 #include <osgDB/WriteFile>
23 #include <osgDB/ReadFile>
24 #include <osgDB/FileNameUtils>
25 #include <osgDB/FileUtils>
26 
27 #include <osg/Image>
28 
29 using namespace std;
30 
31 /////////////////////////////////////////////////////////////////////////
32 //
33 // transformNode
34 //
35 /////////////////////////////////////////////////////////////////////////
transformNode(const osg::Node & root)36 osg::Node* transformNode(const osg::Node& root) {
37 
38   // create a zup to yup OSG Matrix
39   osg::MatrixTransform* ret = new osg::MatrixTransform();
40   osg::Matrix osgToVRMLMat(osg::Matrix(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0));
41 
42   ret->setDataVariance(osg::Object::STATIC);
43   ret->setMatrix(osgToVRMLMat);
44 
45   if (strcmp(root.className(), "MatrixTransform") == 0) {
46     const osg::MatrixTransform& aMat = static_cast<const osg::MatrixTransform&> (root);
47     osg::MatrixTransform* node = new osg::MatrixTransform(aMat);
48     ret->addChild(node);
49   } else if (strcmp(root.className(), "Group") == 0) {
50     const osg::Group& aGroup = static_cast<const osg::Group&> (root);
51     osg::Group* node = new osg::Group(aGroup);
52     ret->addChild(node);
53   } else if (strcmp(root.className(), "PositionAttitudeTransform") == 0) {
54     const osg::PositionAttitudeTransform& aPAT = static_cast<const osg::PositionAttitudeTransform&> (root);
55     osg::PositionAttitudeTransform* node = new osg::PositionAttitudeTransform(aPAT);
56     ret->addChild(node);
57   } else if (strcmp(root.className(), "Geode") == 0) {
58     const osg::Geode& aGeode = static_cast<const osg::Geode&> (root);
59     osg::Geode* node = new osg::Geode(aGeode);
60     ret->addChild(node);
61   } else {
62     osg::notify(osg::ALWAYS) << root.className() << " unsupported" << endl;
63   }
64   if (ret->getNumChildren() > 0) {
65     return ret;
66   }
67   return (NULL);
68 }
69 
70 /////////////////////////////////////////////////////////////////////////
71 //
72 // convertToVRML
73 //
74 /////////////////////////////////////////////////////////////////////////
convertToVRML(const osg::Node & root,const std::string & filename,const osgDB::ReaderWriter::Options * options)75 osgDB::ReaderWriter::WriteResult convertToVRML(const osg::Node& root, const std::string& filename, const osgDB::ReaderWriter::Options* options) {
76 
77   ToVRML toVrml(filename, options);
78 
79   //cout << root.className() << endl;
80   osg::Node* aRoot = transformNode(root);
81 
82   if (aRoot == NULL) {
83     return (osgDB::ReaderWriter::WriteResult(osgDB::ReaderWriter::WriteResult::FILE_NOT_HANDLED));
84   }
85   aRoot->accept(toVrml);
86 
87   return (toVrml.result());
88 }
89 
90 /////////////////////////////////////////////////////////////////////////
91 //
92 // ToVRML
93 //
94 /////////////////////////////////////////////////////////////////////////
ToVRML(const std::string & fileName,const osgDB::ReaderWriter::Options * options)95 ToVRML::ToVRML(const std::string& fileName, const osgDB::ReaderWriter::Options* options) :
96   osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {
97 
98   _fout.open(fileName.c_str(), ios::out);
99 
100   if (!_fout) {
101     _res = osgDB::ReaderWriter::WriteResult::FILE_NOT_HANDLED;
102     return;
103   }
104   _res = osgDB::ReaderWriter::WriteResult::FILE_SAVED;
105 
106   _pathToOutput = osgDB::getFilePath(fileName.c_str());
107   if (_pathToOutput == "") {
108     _pathToOutput = ".";
109   }
110   //std::cout<<" path -"<<_pathToOutput<<"-"<<std::endl;
111 
112   _fout.precision(6);
113   _fout.setf(ios::fixed, ios::floatfield);
114 
115   _strIndent = (char*) malloc(33);
116   for (int i = 0; i < 33; i++) {
117     _strIndent[i] = ' ';
118   }
119   _indent = 0;
120   _strIndent[0] = '\0';
121 
122   //initialize
123   _fout << "#VRML V2.0 utf8\n\n";
124 
125   _textureMode = CONVERT_TEXTURE;
126   _txtUnit = 0;
127 
128   //_convertTextures = true;
129   _pathRelativeToOutput = ".";
130   if (options != NULL) {
131     std::string opt = options->getOptionString();
132     if (opt.find("convertTextures=0") != std::string::npos) {
133       //std::cout << "Read XML stream" << std::endl;
134       _textureMode = COPY_TEXTURE;
135 
136     } else if (opt.find("convertTextures=-1") != std::string::npos) {
137       _textureMode = KEEP_ORIGINAL_TEXTURE;
138 
139     } else if (opt.find("convertTextures=-2") != std::string::npos) {
140       _textureMode = NO_TEXTURE;
141 
142     } else if (opt.find("convertTextures=-3") != std::string::npos) {
143       _textureMode = CONVERT_TEXTURE;
144     }
145 
146     if (opt.find("directoryTextures=") != std::string::npos) {
147       std::string dirOpt = opt;
148       dirOpt.erase(0, dirOpt.find("directoryTextures=") + 18);
149       _pathRelativeToOutput = dirOpt.substr(0, dirOpt.find(' '));
150     }
151 
152     if (opt.find("textureUnit=") != std::string::npos) {
153       std::string dirOpt = opt;
154       dirOpt.erase(0, dirOpt.find("textureUnit=") + 12);
155       _txtUnit = atoi(dirOpt.substr(0, dirOpt.find(' ')).c_str());
156     }
157   }
158 
159   if (_textureMode != NO_TEXTURE) {
160     _defaultImage = new osg::Image();
161     _defaultImage->setFileName(_pathToOutput + "/" + _pathRelativeToOutput + "/default_texture.png");
162     int s = 1;
163     int t = 1;
164     unsigned char *data = new unsigned char[s * t * 3];
165     data[0] = 255;
166     data[1] = 255;
167     data[2] = 255;
168     _defaultImage->setImage(s, t, 0, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE);
169     osgDB::writeImageFile(*(_defaultImage.get()), _defaultImage->getFileName());
170   }
171 }
172 
173 /////////////////////////////////////////////////////////////////////////
174 //
175 // ~ToVRML
176 //
177 /////////////////////////////////////////////////////////////////////////
~ToVRML()178 ToVRML::~ToVRML() {
179   if (_fout) {
180     _fout.close();
181   }
182   free( _strIndent);
183 
184 }
185 
186 /////////////////////////////////////////////////////////////////////////
187 //
188 // indent
189 //
190 /////////////////////////////////////////////////////////////////////////
indent()191 char* ToVRML::indent() {
192   return (_strIndent);
193 }
194 
195 /////////////////////////////////////////////////////////////////////////
196 //
197 // indentM
198 //
199 /////////////////////////////////////////////////////////////////////////
indentM()200 char* ToVRML::indentM() {
201   _strIndent[_indent] = ' ';
202   _indent += 2;
203 
204   if (_indent > 32) {
205     _indent = 32;
206   }
207   _strIndent[_indent] = '\0';
208 
209   return (_strIndent);
210 }
211 
212 /////////////////////////////////////////////////////////////////////////
213 //
214 // indentL
215 //
216 /////////////////////////////////////////////////////////////////////////
indentL()217 char* ToVRML::indentL() {
218   _strIndent[_indent] = ' ';
219   _indent -= 2;
220 
221   if (_indent < 0) {
222     _indent = 0;
223   }
224   _strIndent[_indent] = '\0';
225 
226   return (_strIndent);
227 }
228 
229 /////////////////////////////////////////////////////////////////////////
230 //
231 // apply(osg::Geode)
232 //
233 /////////////////////////////////////////////////////////////////////////
apply(osg::Geode & node)234 void ToVRML::apply(osg::Geode& node) {
235   //cout << "Geode" << endl;
236 
237   pushStateSetStack(node.getStateSet());
238 
239   for (unsigned int i = 0; i < node.getNumDrawables(); i++) {
240     apply(node.getDrawable(i));
241   }
242   popStateSetStack();
243 }
244 
245 /////////////////////////////////////////////////////////////////////////
246 //
247 // apply
248 //
249 /////////////////////////////////////////////////////////////////////////
apply(osg::Drawable * drawable)250 void ToVRML::apply(osg::Drawable* drawable) {
251   // get the drawable type
252   //cout<<"ICI "<<drawable->className()<<endl;
253   pushStateSetStack(drawable->getStateSet());
254 
255   if (strcmp(drawable->className(), "Geometry") == 0) {
256     apply(drawable->asGeometry());
257   } else {
258     osg::notify(osg::ALWAYS) << "Drawable " << drawable->className() << " unsupported" << endl;
259   }
260 
261   popStateSetStack();
262 }
263 
264 /////////////////////////////////////////////////////////////////////////
265 //
266 // apply
267 //
268 /////////////////////////////////////////////////////////////////////////
apply(osg::Geometry * geom)269 void ToVRML::apply(osg::Geometry* geom) {
270 
271   if (geom->containsDeprecatedData()) geom->fixDeprecatedData();
272 
273   // are all primitives faces or line ?
274   GLenum mode;
275   osg::PrimitiveSet::Type type;
276 
277   _fout << indent() << "Shape {\n";
278   indentM();
279   writeAppearance( getCurrentStateSet());
280   indentL();
281 
282   int modePoints = 0;
283   int modeLines = 0;
284   int modeFaces = 0;
285 
286   for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) {
287     mode = geom->getPrimitiveSet(p)->getMode();
288     if (mode == osg::PrimitiveSet::POINTS) {
289       modePoints++;
290 
291     } else if ((mode == osg::PrimitiveSet::LINES) || (mode == osg::PrimitiveSet::LINE_STRIP) || (mode == osg::PrimitiveSet::LINE_LOOP)) {
292       modeLines++;
293 
294     } else if ((mode == osg::PrimitiveSet::TRIANGLES) || (mode == osg::PrimitiveSet::TRIANGLE_STRIP) || (mode == osg::PrimitiveSet::TRIANGLE_FAN) || (mode
295     == osg::PrimitiveSet::QUADS) || (mode == osg::PrimitiveSet::QUAD_STRIP) || (mode == osg::PrimitiveSet::POLYGON)) {
296       modeFaces++;
297     }
298   }
299 
300   //std::cout << "primitives type : Points " << modePoints << " Line " << modeLines << " Face " << modeFaces << std::endl;
301 
302   if (modePoints > 0) {
303     _fout << indentM() << "geometry PointSet {\n";
304     for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) {
305       mode = geom->getPrimitiveSet(p)->getMode();
306       type = geom->getPrimitiveSet(p)->getType();
307       if (mode == osg::PrimitiveSet::POINTS) {
308         osg::notify(osg::WARN) << " osg::PrimitiveSetMode = POINTS not supported by VRML Writer" << std::endl;
309       }
310     }
311   }
312 
313   if (modeLines > 0) {
314     _fout << indentM() << "geometry IndexedLineSet {\n";
315     for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) {
316       mode = geom->getPrimitiveSet(p)->getMode();
317       type = geom->getPrimitiveSet(p)->getType();
318       if ((mode == osg::PrimitiveSet::LINES) || (mode == osg::PrimitiveSet::LINE_STRIP) || (mode == osg::PrimitiveSet::LINE_LOOP)) {
319         osg::notify(osg::WARN) << " osg::PrimitiveSetMode = LINES, LINE_STRIP or LINE_LOOP not supported by VRML Writer" << std::endl;
320       }
321     }
322   }
323 
324   if (modeFaces > 0) {
325     _fout << indentM() << "geometry IndexedFaceSet {\n";
326     _fout << indentM() << "solid FALSE\n";
327     indentL();
328     _fout << indentM() << "coordIndex [\n";
329     indentM();
330 
331     std::vector<int> primitiveSetFaces;
332     int primitiveFaces = 0;
333 
334     for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) {
335       mode = geom->getPrimitiveSet(p)->getMode();
336       type = geom->getPrimitiveSet(p)->getType();
337       if ((mode == osg::PrimitiveSet::TRIANGLES) || (mode == osg::PrimitiveSet::TRIANGLE_STRIP) || (mode == osg::PrimitiveSet::TRIANGLE_FAN) || (mode == osg::PrimitiveSet::QUADS)
338       || (mode == osg::PrimitiveSet::QUAD_STRIP) || (mode == osg::PrimitiveSet::POLYGON)) {
339         if (type == osg::PrimitiveSet::PrimitiveType) {
340           osg::notify(osg::WARN) << "osg::PrimitiveSet::PrimitiveType not supported by VRML Writer" << std::endl;
341 
342         } else if (type == osg::PrimitiveSet::DrawArraysPrimitiveType) {
343           //std::cout << "osg::PrimitiveSet::DrawArraysPrimitiveType" << std::endl;
344           osg::ref_ptr < osg::DrawArrays > dra = dynamic_cast<osg::DrawArrays*> (geom->getPrimitiveSet(p));
345 
346           unsigned int* indices = new unsigned int[dra->getCount()];
347           for (int j = 0; j < dra->getCount(); j++) {
348             indices[j] = dra->getFirst() + j;
349           }
350           writeCoordIndex(mode, indices, dra->getCount(), primitiveSetFaces, primitiveFaces);
351           delete[] indices;
352 
353         } else if (type == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) {
354           //osg::notify(osg::WARN) << " osg::PrimitiveSet::DrawArrayLengthsPrimitiveType not supported by VRML Writer" << std::endl;
355           osg::ref_ptr < osg::DrawArrayLengths > dal = dynamic_cast<osg::DrawArrayLengths*> (geom->getPrimitiveSet(p));
356 
357           //std::cout<<dal->getFirst()<<" "<<dal->getNumPrimitives()<<" "<<   dal->getNumIndices ()<<" "<< dal->getNumInstances()<<std::endl;
358           int first = 0;
359           for (unsigned int prim = dal->getFirst(); prim < dal->getNumPrimitives(); prim++) {
360             //std::cout<<(*dal)[prim]<<std::endl;
361             unsigned int numIndices = (*dal)[prim];
362             unsigned int * indices = new unsigned int[numIndices];
363             for (unsigned int i = 0; i < numIndices; i++) {
364               indices[i] = first + i;
365             }
366 
367             first += (*dal)[prim];
368             // write coorIndex as if wa have an indexed geometry
369             writeCoordIndex(mode, indices, numIndices, primitiveSetFaces, primitiveFaces);
370             delete[] indices;
371           }
372 
373         } else if (type == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) {
374           //std::cout << "osg::PrimitiveSet::DrawElementsUBytePrimitiveType" << std::endl;
375 
376           osg::ref_ptr < osg::DrawElementsUByte > drui = dynamic_cast<osg::DrawElementsUByte*> (geom->getPrimitiveSet(p));
377           const unsigned char * indices = (const unsigned char*) (drui->getDataPointer());
378           writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces);
379 
380         } else if (type == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) {
381           //std::cout << "osg::PrimitiveSet::DrawElementsUShortPrimitiveType" << std::endl;
382 
383           osg::ref_ptr < osg::DrawElementsUShort > drui = dynamic_cast<osg::DrawElementsUShort*> (geom->getPrimitiveSet(p));
384           const unsigned short * indices = (const unsigned short*) (drui->getDataPointer());
385           writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces);
386 
387         } else if (type == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) {
388           //std::cout << "osg::PrimitiveSet::DrawElementsUIntPrimitiveType" << std::endl;
389 
390           osg::ref_ptr < osg::DrawElementsUInt > drui = dynamic_cast<osg::DrawElementsUInt*> (geom->getPrimitiveSet(p));
391           const unsigned int * indices = (const unsigned int*) (drui->getDataPointer());
392           writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces);
393         }
394 
395       }
396 
397     }
398     _fout << indentL() << "]\n";
399     indentL();
400 
401     //write vertex
402     writeCoord((osg::Vec3Array*) (geom->getVertexArray()));
403     //write texture coordinate
404     if (_textureMode != NO_TEXTURE) {
405       writeTexCoord((osg::Vec2Array*) (geom->getTexCoordArray(_txtUnit)), (osg::Vec3Array*) (geom->getVertexArray()));
406     }
407     //write normals
408     writeNormal(geom, primitiveSetFaces, primitiveFaces);
409     //write colors
410     writeColor(geom, primitiveSetFaces, primitiveFaces);
411   }
412 
413   _fout << indent() << "}\n";
414   _fout << indentL() << "}\n";
415 
416 }
417 
418 /////////////////////////////////////////////////////////////////////////
419 //
420 // writeAppearance
421 //
422 /////////////////////////////////////////////////////////////////////////
writeAppearance(osg::StateSet * stateset)423 void ToVRML::writeAppearance(osg::StateSet* stateset) {
424 
425   if (stateset == NULL) {
426     return;
427   }
428 
429   osg::ref_ptr < osg::StateSet > ss = stateset;
430 
431   _fout << indent() << "appearance Appearance {\n";
432   osg::Material* mat = (osg::Material*) (ss->getAttribute(osg::StateAttribute::MATERIAL));
433   osg::Texture2D* tex;
434   if (_textureMode == NO_TEXTURE) {
435     tex = NULL;
436   } else {
437     tex = (osg::Texture2D*) (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXTURE));
438   }
439 
440   if (mat) {
441 
442     bool alreadyLoaded;
443     std::string name;
444     osg::Vec4 ambient, diffuse, specular, emission;
445     float shininess;
446 
447     ambient = mat->getAmbient(osg::Material::FRONT);
448     diffuse = mat->getDiffuse(osg::Material::FRONT);
449     specular = mat->getSpecular(osg::Material::FRONT);
450     shininess = mat->getShininess(osg::Material::FRONT);
451     emission = mat->getEmission(osg::Material::FRONT);
452 
453     float transp = 1 - (ambient[3] + diffuse[3] + specular[3] + emission[3]) / 4.0;
454     if (transp < 0)
455       transp = 0;
456 
457     //if (transp == 0 && tex) {
458     //  if (tex->getImage()->isImageTranslucent()) {
459     //    transp = 0.01;
460     //    mat->setTransparency(osg::Material::FRONT,transp);
461     //  }
462     //}
463 
464     findMaterialName(mat, name, alreadyLoaded);
465     if (alreadyLoaded) {
466       _fout << indentM() << "material USE " << name << "\n";
467       indentL();
468     } else {
469 
470       _fout << indentM() << "material DEF " << name << " Material {\n";
471       //_fout << indentM() << "material Material {\n";
472       _fout << indentM() << "diffuseColor " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n";
473       _fout << indent() << "emissiveColor " << emission[0] << " " << emission[1] << " " << emission[2] << "\n";
474 
475       _fout << indent() << "specularColor " << specular[0] << " " << specular[1] << " " << specular[2] << "\n";
476       _fout << indent() << "shininess " << shininess << "\n";
477       float ambientI = (ambient[0] + ambient[1] + ambient[2]) / 3.0;
478       if (ambientI > 1)
479         ambientI = 1;
480       _fout << indent() << "ambientIntensity " << ambientI << "\n";
481 
482       _fout << indent() << "transparency " << transp << "\n";
483       _fout << indentL() << "}\n";
484       indentL();
485     }
486   }
487 
488   if (tex) {
489     bool alreadyLoaded;
490     std::string name;
491     findTextureName(tex, name, alreadyLoaded);
492     if (alreadyLoaded) {
493       _fout << indentM() << "texture USE " << name << "\n";
494       indentL();
495     } else {
496       _fout << indentM() << "texture DEF " << name << " ImageTexture {\n";
497       std::string texName = tex->getImage()->getFileName();
498       if (_textureMode == COPY_TEXTURE || _textureMode == CONVERT_TEXTURE) {
499         texName = _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(texName);
500 
501       } else if (_textureMode == KEEP_ORIGINAL_TEXTURE) {
502         texName = _pathRelativeToOutput + "/" + texName;
503       }
504       _fout << indentM() << "url [ \"" << texName << "\" ]\n";
505       //std::cout<<"WRAP "<<tex->getWrap(osg::Texture::WRAP_S)<<std::endl;
506       if (tex->getWrap(osg::Texture::WRAP_S) == osg::Texture::REPEAT) {
507         _fout << indent() << "repeatS TRUE\n";
508       } else {
509         _fout << indent() << "repeatS FALSE\n";
510       }
511       if (tex->getWrap(osg::Texture::WRAP_T) == osg::Texture::REPEAT) {
512         _fout << indent() << "repeatT TRUE\n";
513       } else {
514         _fout << indent() << "repeatT FALSE\n";
515       }
516       _fout << indentL() << "}\n";
517       indentL();
518     }
519   }
520 
521   _fout << indent() << "}\n";
522 
523 }
524 
525 /////////////////////////////////////////////////////////////////////////
526 //
527 // apply(osg::Group)
528 //
529 /////////////////////////////////////////////////////////////////////////
apply(osg::Group & node)530 void ToVRML::apply(osg::Group& node) {
531   //cout << "Group" << endl;
532   _fout << indent() << "Group {\n";
533   _fout << indentM() << "children [\n";
534 
535   pushStateSetStack(node.getStateSet());
536 
537   indentM();
538   traverse(node);
539   indentL();
540 
541   popStateSetStack();
542 
543   _fout << indent() << "]\n";
544   _fout << indentL() << "}\n";
545 }
546 
547 /////////////////////////////////////////////////////////////////////////
548 //
549 // apply(osg::MatrixTransform)
550 //
551 /////////////////////////////////////////////////////////////////////////
apply(osg::MatrixTransform & node)552 void ToVRML::apply(osg::MatrixTransform& node) {
553   //cout << "MatrixTransform" << endl;
554   osg::Matrixf mat = node.getMatrix();
555   //   for(int i=0;i<16;i++){
556   //     cout <<mat.ptr()[i]<<" ";
557   //   }
558   //   cout<<endl;
559 
560 
561   osg::Vec3 trans = mat.getTrans();
562   osg::Vec3 scale = mat.getScale();
563   osg::Quat quat;
564   mat.get(quat);
565   double angle;
566   osg::Vec3 axe;
567   quat.getRotate(angle, axe);
568 
569   _fout << indent() << "Transform {\n";
570   _fout << indentM() << "scale " << scale[0] << " " << scale[1] << " " << scale[2] << "\n";
571   //_fout << indentM() << "scale 1 1 1\n";
572   _fout << indent() << "translation " << trans[0] << " " << trans[1] << " " << trans[2] << "\n";
573   _fout << indent() << "rotation " << axe[0] << " " << axe[1] << " " << axe[2] << " " << angle << "\n";
574   _fout << indent() << "children [\n";
575 
576   pushStateSetStack(node.getStateSet());
577 
578   indentM();
579   traverse(node);
580   indentL();
581 
582   popStateSetStack();
583 
584   _fout << indent() << "]\n";
585 
586   _fout << indentL() << "}\n";
587 
588 }
589 
590 /////////////////////////////////////////////////////////////////////////
591 //
592 // apply(osg::PositionAttitudeTransform)
593 //
594 /////////////////////////////////////////////////////////////////////////
apply(osg::PositionAttitudeTransform & node)595 void ToVRML::apply(osg::PositionAttitudeTransform& node) {
596 
597   osg::Vec3 trans = node.getPosition();
598   osg::Vec3 scale = node.getScale();
599   osg::Quat quat = node.getAttitude();
600   double angle;
601   osg::Vec3 axe;
602   quat.getRotate(angle, axe);
603 
604   _fout << indent() << "Transform {\n";
605   _fout << indentM() << "scale " << scale[0] << " " << scale[1] << " " << scale[2] << "\n";
606   //_fout << indentM() << "scale 1 1 1\n";
607   _fout << indent() << "translation " << trans[0] << " " << trans[1] << " " << trans[2] << "\n";
608   _fout << indent() << "rotation " << axe[0] << " " << axe[1] << " " << axe[2] << " " << angle << "\n";
609   _fout << indent() << "children [\n";
610 
611   pushStateSetStack(node.getStateSet());
612 
613   indentM();
614   traverse(node);
615   indentL();
616 
617   popStateSetStack();
618 
619   _fout << indent() << "]\n";
620 
621   _fout << indentL() << "}\n";
622 
623 }
624 
625 ////////////////////////////////////////////////////////////////////////
626 //
627 // apply(osg::Billboard)
628 //
629 /////////////////////////////////////////////////////////////////////////
apply(osg::Billboard & node)630 void ToVRML::apply(osg::Billboard& node) {
631   osg::notify(osg::ALWAYS) << "WARNING : Billboard is changed to Group" << endl;
632   _fout << indent() << "Group {\n";
633   indentM();
634 
635   //osg::Billboard::Mode mode = node.getMode();
636   //const osg::Vec3 axe = node.getAxis();
637   //const osg::Vec3 normal = node.getNormal();
638 
639   //if (mode == osg::Billboard::AXIAL_ROT) {
640   //  _fout << indent() << "axisOfRotation " << axe[0] << " " << axe[1] << " " << axe[2] << "\n";
641   //}
642   //osg::BoundingSphere sph=node.getBound();
643   //_fout << indent() << "bboxCenter "<<sph.center()[0]<<" "<<sph.center()[1]<<" "<<sph.center()[2]<<"\n";
644   //_fout << indent() << "bboxSize "<<sph.radius()<<" "<<sph.radius()<<" "<<sph.radius()<<"\n";
645 
646   _fout << indent() << "children [\n";
647 
648   pushStateSetStack(node.getStateSet());
649 
650   indentM();
651   for (unsigned int i = 0; i < node.getNumDrawables(); i++) {
652     osg::Vec3 trans = node.getPosition(i);
653     _fout << indent() << "Transform {\n";
654     _fout << indentM() << "translation " << trans[0] << " " << trans[1] << " " << trans[2] << "\n";
655     _fout << indent() << "children [\n";
656     indentM();
657     apply(node.getDrawable(i));
658     _fout << indentL() << "]\n";
659     _fout << indentL() << "}\n";
660   }
661 
662   popStateSetStack();
663 
664   _fout << indentL() << "]\n";
665   _fout << indentL() << "}\n";
666 }
667 
668 ////////////////////////////////////////////////////////////////////////
669 //
670 // apply(osg::LOD)
671 //
672 /////////////////////////////////////////////////////////////////////////
apply(osg::LOD & node)673 void ToVRML::apply(osg::LOD& node) {
674   //std::cout << "LOD" << endl;
675   _fout << indent() << "LOD {\n";
676 
677   bool fakeFirst = false;
678   bool fakeLast = false;
679   if (node.getMinRange(0) > 0) {
680     fakeFirst = true;
681   }
682   if (node.getMaxRange(node.getNumRanges() - 1) < std::numeric_limits<float>::max()) {
683     fakeLast = true;
684   }
685 
686   _fout << indentM() << "level [\n";
687   if (fakeFirst) {
688     _fout << indentM() << "Shape {\n";
689     _fout << indent() << "}\n";
690     indentL();
691   }
692   pushStateSetStack(node.getStateSet());
693   indentM();
694   traverse(node);
695   indentL();
696   popStateSetStack();
697 
698   if (fakeLast) {
699     _fout << indentM() << "Shape {\n";
700     _fout << indent() << "}\n";
701     indentL();
702   }
703 
704   _fout << indent() << "]\n";
705 
706   osg::Vec3 center;
707   if (node.getCenterMode() == osg::LOD::USER_DEFINED_CENTER) {
708     center = node.getCenter();
709   } else {
710     center = node.getBound().center();
711   }
712   _fout << indent() << "center " << center[0] << " " << center[1] << " " << center[2] << "\n";
713 
714   _fout << indentM() << "range [";
715   if (fakeFirst) {
716     _fout << indentM() << node.getMinRange(0) << ",";
717   }
718   for (unsigned int i = 0; i < node.getNumRanges(); i++) {
719 
720     _fout << indentM() << node.getMaxRange(i);
721     if (i < node.getNumRanges() - 1) {
722       _fout << ",";
723     }
724   }
725   _fout << "]\n";
726 
727   _fout << indentL() << "}\n";
728 }
729 
730 /////////////////////////////////////////////////////////////////////////
731 //
732 // apply(osg::Node)
733 //
734 /////////////////////////////////////////////////////////////////////////
apply(osg::Node & node)735 void ToVRML::apply(osg::Node& node) {
736   osg::notify(osg::ALWAYS) << node.className() << " not supported" << endl;
737   pushStateSetStack(node.getStateSet());
738   traverse(node);
739   popStateSetStack();
740 }
741 
742 /////////////////////////////////////////////////////////////////////////
743 //
744 // pushStateSetStack
745 //
746 /////////////////////////////////////////////////////////////////////////
pushStateSetStack(osg::StateSet * ss)747 void ToVRML::pushStateSetStack(osg::StateSet* ss) {
748   _stack.push_back(osg::ref_ptr<osg::StateSet>(ss));
749 }
750 
751 /////////////////////////////////////////////////////////////////////////
752 //
753 // popStateSetStack
754 //
755 /////////////////////////////////////////////////////////////////////////
popStateSetStack()756 void ToVRML::popStateSetStack() {
757   if (!_stack.empty()) {
758     _stack.pop_back();
759   }
760 }
761 
762 /////////////////////////////////////////////////////////////////////////
763 //
764 // getCurrentStateSet
765 //
766 /////////////////////////////////////////////////////////////////////////
getCurrentStateSet()767 osg::StateSet* ToVRML::getCurrentStateSet() {
768   // return current StateSet by flatten StateSet stack.
769   // until flatten is done, just return top StateSet
770   if (!_stack.empty()) {
771     osg::StateSet* ssFinal = new osg::StateSet();
772     ssFinal->setGlobalDefaults();
773     //std::cout << "StateSet Stack Size " << _stack.size() << std::endl;
774     for (unsigned int i = 0; i < _stack.size(); i++) {
775       osg::StateSet* ssCur = _stack[i].get();
776       if (ssCur != NULL) {
777         ssFinal->merge(*ssCur);
778       }
779     }
780     return (ssFinal);
781   } else
782     return (NULL);
783 }
784 
785 /////////////////////////////////////////////////////////////////////////
786 //
787 // findMaterialName
788 //
789 /////////////////////////////////////////////////////////////////////////
findMaterialName(osg::Material * mat,std::string & name,bool & alreadyLoaded)790 void ToVRML::findMaterialName(osg::Material* mat, std::string& name, bool& alreadyLoaded) {
791 
792   osg::Vec4 ambient, diffuse, specular, emission;
793   //float shininess;
794   std::map<osg::ref_ptr<osg::Material>, std::string>::iterator it;// = _matMap.find(obj);
795 
796   for (it = _matMap.begin(); it != _matMap.end(); it++) {
797     osg::ref_ptr < osg::Material > matLoaded = it->first;
798     ambient = mat->getAmbient(osg::Material::FRONT);
799     //diffuse = mat->getDiffuse(osg::Material::FRONT);
800     //specular = mat->getSpecular(osg::Material::FRONT);
801     //shininess = mat->getShininess(osg::Material::FRONT);
802     //emission = mat->getEmission(osg::Material::FRONT);
803     //std::cout << "MATERIAL " << ambient[3] << " " << matLoaded->getAmbient(osg::Material::FRONT)[3] << std::endl;
804 
805     if ((matLoaded->getAmbient(osg::Material::FRONT) == mat->getAmbient(osg::Material::FRONT)) && (matLoaded->getDiffuse(osg::Material::FRONT)
806     == mat->getDiffuse(osg::Material::FRONT)) && (matLoaded->getSpecular(osg::Material::FRONT) == mat->getSpecular(osg::Material::FRONT))
807     && (matLoaded->getShininess(osg::Material::FRONT) == mat->getShininess(osg::Material::FRONT)) && (matLoaded->getEmission(osg::Material::FRONT)
808     == mat->getEmission(osg::Material::FRONT))) {
809 
810       name = it->second;
811       alreadyLoaded = true;
812       return;
813     }
814   }
815   std::stringstream ss;
816   ss << "material_" << _matMap.size();
817   name = ss.str();
818   _matMap[mat] = name;
819   alreadyLoaded = false;
820 
821 }
822 
823 /////////////////////////////////////////////////////////////////////////
824 //
825 // findTextureName
826 //
827 /////////////////////////////////////////////////////////////////////////
findTextureName(osg::Texture2D * tex,std::string & name,bool & alreadyLoaded)828 void ToVRML::findTextureName(osg::Texture2D* tex, std::string& name, bool& alreadyLoaded) {
829 
830   //std::cout << "ORI -" << tex->getImage() << "- " << std::endl;
831   if (tex->getImage() == NULL) {
832     tex->setImage(_defaultImage.get());
833   }
834 
835   std::string nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName());
836   std::string nameInput = osgDB::findDataFile(nameOri, NULL);
837   if (nameInput == "") {
838     osg::notify(osg::ALWAYS) << "WARNING: couldn't find texture named: -" << nameOri << "- use default one instead -" << _defaultImage->getFileName() << "-" << std::endl;
839     tex->setImage(_defaultImage.get());
840     nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName());
841     nameInput = osgDB::findDataFile(nameOri, NULL);
842   }
843 
844   std::string nameOutput;
845   std::string::size_type pos = nameInput.find_last_of(".");
846   std::string ext = nameInput.substr(pos, nameInput.length() - pos);
847 
848   osg::ref_ptr < osg::Image > imgIn = osgDB::readRefImageFile(nameInput);
849   if (!imgIn.valid()) {
850     osg::notify(osg::ALWAYS) << "WARNING: couldn't read texture named: -" << nameOri << "- use default one instead -" << _defaultImage->getFileName() << "-" << std::endl;
851     tex->setImage(_defaultImage.get());
852     nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName());
853     nameInput = osgDB::findDataFile(nameOri, NULL);
854     pos = nameInput.find_last_of(".");
855     nameInput.substr(pos, nameInput.length() - pos);
856     imgIn = _defaultImage.get();
857   }
858 
859   //int nbBand = poSrcDS->GetRasterCount();
860   if (_textureMode == KEEP_ORIGINAL_TEXTURE) {
861     nameOutput = nameInput;
862 
863   } else if (_textureMode == COPY_TEXTURE) {
864     nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput);
865 
866   } else if (_textureMode == CONVERT_TEXTURE) {
867     nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput);
868     if (ext != ".png" && ext != ".jpg") {
869       if (imgIn->isImageTranslucent()) {//(nbBand != 1 && nbBand != 3) {
870         nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput.substr(0, pos) + ".png");
871       } else {
872         nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput.substr(0, pos) + ".jpg");
873       }
874     }
875   }
876 
877   std::map<osg::ref_ptr<osg::Texture2D>, std::string>::iterator it;
878   for (it = _texMap.begin(); it != _texMap.end(); it++) {
879     osg::ref_ptr < osg::Texture2D > texLoaded = it->first;
880 
881     if ((nameOutput == texLoaded->getImage()->getFileName()) && (tex->getWrap(osg::Texture::WRAP_S) == texLoaded->getWrap(osg::Texture::WRAP_S))
882     && (tex->getWrap(osg::Texture::WRAP_T) == texLoaded->getWrap(osg::Texture::WRAP_T))) {
883       name = it->second;
884       alreadyLoaded = true;
885       return;
886     }
887   }
888 
889   // first time we see these texture
890   // add it to textureMap
891   std::stringstream ss;
892   ss << "texture2D_" << _texMap.size();
893   name = ss.str();
894   _texMap[tex] = name;
895   alreadyLoaded = false;
896 
897   tex->getImage()->setFileName(nameOutput);
898 
899   if (nameInput == nameOutput) {
900     return;
901   }
902   // else write image file
903 
904   if (_textureMode == CONVERT_TEXTURE) {
905     // convert format (from dds to rgb or rgba, or from rgba to rgb)
906     std::string newName;
907     GLenum type = GL_UNSIGNED_BYTE;
908     GLenum pixelFormat;
909     GLint internalFormat;
910     int nbC;
911     if (imgIn->isImageTranslucent()) {
912       // convert to png if transparency
913       pixelFormat = GL_RGBA;
914       internalFormat = GL_RGBA;
915       nbC = 4;
916     } else {
917       // convert to jpeg if no transparency
918       pixelFormat = GL_RGB;
919       internalFormat = GL_RGB;
920       nbC = 3;
921     }
922     osg::ref_ptr < osg::Image > curImg = tex->getImage();
923     osg::ref_ptr < osg::Image > mmImg = new osg::Image();
924     unsigned char* data = new unsigned char[curImg->s() * curImg->t() * nbC];
925     for (int j = 0; j < curImg->t(); j++) {
926       for (int i = 0; i < curImg->s(); i++) {
927         osg::Vec4 c = curImg->getColor(i, j);
928         data[(i + j * curImg->s()) * nbC] = c[0] * 255;
929         data[(i + j * curImg->s()) * nbC + 1] = c[1] * 255;
930         data[(i + j * curImg->s()) * nbC + 2] = c[2] * 255;
931         if (nbC == 4) {
932           data[(i + j * curImg->s()) * nbC + 3] = c[3] * 255;
933         }
934       }
935     }
936     mmImg->setImage(curImg->s(), curImg->t(), 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE, 1);
937     osgDB::writeImageFile(*(mmImg.get()), nameOutput);
938 
939   } else {
940     // no conversion needed, input and output have the same format, but path to image has changed
941     osgDB::writeImageFile(*(tex->getImage()), nameOutput);
942   }
943 
944 }
945 
946 /////////////////////////////////////////////////////////////////////////
947 //
948 // writeCoordIndex
949 //
950 /////////////////////////////////////////////////////////////////////////
writeCoordIndex(GLenum mode,T * indices,unsigned int number,std::vector<int> & primitiveSetFaces,int & primitiveFaces)951 template<typename T> void ToVRML::writeCoordIndex(GLenum mode, T* indices, unsigned int number, std::vector<int>& primitiveSetFaces, int& primitiveFaces) {
952 
953   int currentFaces = 0;
954   if (mode == osg::PrimitiveSet::TRIANGLES) {
955     //std::cout << "TRIANGLES" << std::endl;
956     for (unsigned int j = 0; j < number; j += 3) {
957       _fout << indent() << indices[j] << "," << indices[j + 1] << "," << indices[j + 2] << ",-1,\n";
958       currentFaces++;
959     }
960     primitiveSetFaces.push_back(currentFaces);
961     primitiveFaces += currentFaces;
962 
963   } else if (mode == osg::PrimitiveSet::TRIANGLE_FAN) {
964     //std::cout << "TRIANGLE FAN" << std::endl;
965     int firstPoint = indices[0];
966     int secondPoint = indices[1];
967     for (unsigned int j = 2; j < number; j++) {
968       _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j] << ",-1,\n";
969       secondPoint = indices[j];
970       currentFaces++;
971     }
972     primitiveSetFaces.push_back(currentFaces);
973     primitiveFaces += currentFaces;
974 
975   } else if (mode == osg::PrimitiveSet::TRIANGLE_STRIP) {
976     //std::cout << "TRIANGLE STRIP" << std::endl;
977     int firstPoint = indices[0];
978     int secondPoint = indices[1];
979     bool changeSecond = false;
980     for (unsigned int j = 2; j < number; j++) {
981       _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j] << ",-1,\n";
982       if (!changeSecond) {
983         firstPoint = indices[j];
984         changeSecond = true;
985       } else {
986         secondPoint = indices[j];
987         changeSecond = false;
988       }
989       currentFaces++;
990     }
991     primitiveSetFaces.push_back(currentFaces);
992     primitiveFaces += currentFaces;
993 
994   } else if (mode == osg::PrimitiveSet::QUADS) {
995     //std::cout << "QUADS" << std::endl;
996     for (unsigned int j = 0; j < number; j += 4) {
997       _fout << indent() << indices[j] << "," << indices[j + 1] << "," << indices[j + 2] << "," << indices[j + 3] << ",-1,\n";
998       currentFaces++;
999     }
1000     primitiveSetFaces.push_back(currentFaces);
1001     primitiveFaces += currentFaces;
1002 
1003   } else if (mode == osg::PrimitiveSet::QUAD_STRIP) {
1004     //std::cout << "QUADS STRIP" << std::endl;
1005     int firstPoint = indices[0];
1006     int secondPoint = indices[1];
1007     for (unsigned int j = 2; j < number; j += 2) {
1008       _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j + 1] << " " << indices[j] << ",-1,\n";
1009       firstPoint = indices[j];
1010       secondPoint = indices[j + 1];
1011       currentFaces++;
1012     }
1013     primitiveSetFaces.push_back(currentFaces);
1014     primitiveFaces += currentFaces;
1015 
1016   } else if (mode == osg::PrimitiveSet::POLYGON) {
1017     //std::cout << "POLYGON" << std::endl;
1018     _fout << indent();
1019     for (unsigned int j = 0; j < number; j++) {
1020       _fout << indices[j] << ",";
1021     }
1022     currentFaces++;
1023     _fout << "-1,\n";
1024     primitiveSetFaces.push_back(currentFaces);
1025     primitiveFaces += currentFaces;
1026 
1027   } else {
1028     osg::notify(osg::ALWAYS) << "Unknown Primitive Set Type : " << mode << std::endl;
1029   }
1030 
1031 }
1032 
1033 /////////////////////////////////////////////////////////////////////////
1034 //
1035 // writeCoord
1036 //
1037 /////////////////////////////////////////////////////////////////////////
writeCoord(osg::Vec3Array * array)1038 void ToVRML::writeCoord(osg::Vec3Array* array) {
1039 
1040   if (array == NULL) {
1041     std::cerr << "Vec3Array is NULL" << std::endl;
1042     return;
1043   }
1044   osg::ref_ptr < osg::Vec3Array > vArray = array;
1045 
1046   _fout << indentM() << "coord Coordinate {\n";
1047   _fout << indentM() << "point [\n";
1048   indentM();
1049   osg::Vec3 xyz;
1050   for (unsigned int j = 0; j < vArray->size(); j++) {
1051     xyz = (*vArray)[j];
1052     _fout << indent() << xyz[0] << " " << xyz[1] << " " << xyz[2] << ",\n";
1053   }
1054   _fout << indentL() << "]\n";
1055   _fout << indentL() << "}\n";
1056   indentL();
1057 }
1058 
1059 /////////////////////////////////////////////////////////////////////////
1060 //
1061 // writeTexCoord
1062 //
1063 /////////////////////////////////////////////////////////////////////////
writeTexCoord(osg::Vec2Array * array,osg::Vec3Array * array2)1064 void ToVRML::writeTexCoord(osg::Vec2Array* array, osg::Vec3Array* array2) {
1065 
1066   osg::ref_ptr < osg::StateSet > ss = getCurrentStateSet();
1067   osg::Texture2D* tex = (osg::Texture2D*) (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXTURE));
1068   if (tex == NULL) {
1069     return;
1070   }
1071 
1072   osg::ref_ptr < osg::TexGen > texGen = dynamic_cast<osg::TexGen*> (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXGEN));
1073   osg::ref_ptr < osg::TexEnv > texEnv = dynamic_cast<osg::TexEnv*> (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXENV));
1074 
1075   osg::Texture::WrapMode wrap_s = tex->getWrap(osg::Texture::WRAP_S);//osg::Texture::REPEAT;
1076   osg::Texture::WrapMode wrap_t = tex->getWrap(osg::Texture::WRAP_T);//osg::Texture::REPEAT;
1077 
1078   if (array != NULL) {
1079     writeUVArray(array, wrap_s, wrap_t);
1080 
1081   } else if (texGen.valid()) {
1082     //std::cout << "TEXGEN" << std::endl;
1083     osg::ref_ptr < osg::Vec2Array > uvArray = buildUVArray(texGen.get(), array2);
1084     if (uvArray.valid()) {
1085       writeUVArray(uvArray.get(), wrap_s, wrap_t);
1086     }
1087 
1088   } else if (texEnv.valid()) {
1089     //std::cout << "TEXENV" << std::endl;
1090     osg::ref_ptr < osg::Vec2Array > uvArray = buildUVArray(texEnv.get(), array2);
1091     if (uvArray.valid()) {
1092       writeUVArray(uvArray.get(), wrap_s, wrap_t);
1093     }
1094   }
1095 }
1096 
1097 /////////////////////////////////////////////////////////////////////////
1098 //
1099 // writeNormal
1100 //
1101 /////////////////////////////////////////////////////////////////////////
writeNormal(osg::Geometry * geom,std::vector<int> & primitiveSetFaces,int nbFaces)1102 void ToVRML::writeNormal(osg::Geometry* geom, std::vector<int>& primitiveSetFaces, int nbFaces) {
1103 
1104   osg::ref_ptr < osg::Vec3Array > nArray = (osg::Vec3Array*) (geom->getNormalArray());
1105   if (!nArray.valid()) {
1106     return;
1107   }
1108 
1109   osg::Array::Binding normalBinding = osg::getBinding(geom->getNormalArray());
1110   if (normalBinding == osg::Array::BIND_PER_VERTEX || normalBinding == osg::Array::BIND_OVERALL) {
1111     _fout << indentM() << "normalPerVertex TRUE \n";
1112   } else {
1113     _fout << indentM() << "normalPerVertex FALSE \n";
1114   }
1115 
1116   _fout << indent() << "normal Normal {\n";
1117   _fout << indentM() << "vector [\n";
1118   indentM();
1119   osg::Vec3 n;
1120 
1121   if (normalBinding == osg::Array::BIND_PER_VERTEX) {
1122     for (unsigned int j = 0; j < (*nArray).size(); j++) {
1123       n = (*nArray)[j];
1124       _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n";
1125     }
1126 
1127   } else if (normalBinding == osg::Array::BIND_OVERALL) {
1128     n = (*nArray)[0];
1129     int size = ((osg::Vec3Array*) (geom->getVertexArray()))->size();
1130     for (int j = 0; j < size; j++) {
1131       _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n";
1132     }
1133 
1134   } else if (normalBinding == osg::Array::BIND_PER_PRIMITIVE_SET) {
1135     for (unsigned int j = 0; j < (*nArray).size(); j++) {
1136       n = (*nArray)[j];
1137       for (int k = 0; k < primitiveSetFaces[j]; k++) {
1138         _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n";
1139       }
1140     }
1141   }
1142 
1143   _fout << indentL() << "]\n";
1144   _fout << indentL() << "}\n";
1145   indentL();
1146 }
1147 
1148 /////////////////////////////////////////////////////////////////////////
1149 //
1150 // writeUVArray
1151 //
1152 /////////////////////////////////////////////////////////////////////////
writeUVArray(osg::Vec2Array * uvArray,osg::Texture::WrapMode wrap_s,osg::Texture::WrapMode wrap_t)1153 void ToVRML::writeUVArray(osg::Vec2Array* uvArray, osg::Texture::WrapMode wrap_s, osg::Texture::WrapMode wrap_t) {
1154 
1155   _fout << indentM() << "texCoord TextureCoordinate {\n";
1156   _fout << indentM() << "point [\n";
1157   indentM();
1158   osg::Vec2 uv;
1159 
1160   for (unsigned int j = 0; j < (*uvArray).size(); j++) {
1161     uv = (*uvArray)[j];
1162     if (wrap_s != osg::Texture::REPEAT) {
1163       // clamp to 0-1
1164       if (uv[0] < 0) {
1165         uv[0] = 0;
1166       } else if (uv[0] > 1) {
1167         uv[0] = 1;
1168       }
1169     }
1170     if (wrap_t != osg::Texture::REPEAT) {
1171       // clamp to 0-1
1172       if (uv[1] < 0) {
1173         uv[1] = 0;
1174       } else if (uv[1] > 1) {
1175         uv[1] = 1;
1176       }
1177     }
1178     _fout << indent() << uv[0] << " " << uv[1] << ",\n";
1179   }
1180   _fout << indentL() << "]\n";
1181   _fout << indentL() << "}\n";
1182   indentL();
1183 }
1184 
1185 /////////////////////////////////////////////////////////////////////////
1186 //
1187 // buildUVArray
1188 //
1189 /////////////////////////////////////////////////////////////////////////
buildUVArray(osg::TexGen * tGen,osg::Vec3Array * array)1190 osg::Vec2Array* ToVRML::buildUVArray(osg::TexGen* tGen, osg::Vec3Array* array) {
1191   osg::ref_ptr < osg::TexGen > texGen = tGen;
1192   osg::ref_ptr < osg::Vec3Array > vArray = array;
1193   osg::Vec2Array* uvRet = NULL;
1194 
1195   osg::TexGen::Mode mode = texGen->getMode();
1196   if (mode == osg::TexGen::OBJECT_LINEAR) {
1197     //std::cout << "I know" << std::endl;
1198 
1199     uvRet = new osg::Vec2Array();
1200     osg::Plane planS = texGen->getPlane(osg::TexGen::S);//, osg::Vec4(1 / rangeS, 0, 0, -(adfGeoTransform[0] / rangeS)));
1201     osg::Plane planT = texGen->getPlane(osg::TexGen::T);//, osg::Vec4(0, 1 / rangeT, 0, -(adfGeoTransform[3] + sy * adfGeoTransform[5]) / rangeT));
1202     osg::Vec4 pS = planS.asVec4();
1203     osg::Vec4 pT = planT.asVec4();
1204     double width, height, xmin, ymin;
1205     width = 1.0 / pS[0];
1206     height = 1.0 / pT[1];
1207     xmin = -width * pS[3];
1208     ymin = -height * pT[3];
1209 
1210     for (unsigned int j = 0; j < vArray->size(); j++) {
1211       osg::Vec3d p = (*vArray)[j];
1212       double x, y;
1213       osg::Vec2 uv;
1214       x = p[0];
1215       y = p[1];
1216       uv[0] = (x - xmin) / width;
1217       uv[1] = (y - ymin) / height;
1218       (*uvRet).push_back(uv);
1219 
1220     }
1221   } else {
1222     osg::notify(osg::ALWAYS) << "Unknown TexGen mode" << std::endl;
1223   }
1224 
1225   return (uvRet);
1226 }
1227 
1228 /////////////////////////////////////////////////////////////////////////
1229 //
1230 // buildUVArray
1231 //
1232 /////////////////////////////////////////////////////////////////////////
buildUVArray(osg::TexEnv * tEnv,osg::Vec3Array * array)1233 osg::Vec2Array* ToVRML::buildUVArray(osg::TexEnv* tEnv, osg::Vec3Array* array) {
1234   osg::ref_ptr < osg::TexEnv > texEnv = tEnv;
1235   osg::Vec2Array* uvRet = NULL;
1236 
1237  // osg::TexEnv::Mode mode = texEnv->getMode();
1238   //if (mode == osg::TexEnv::MODULATE) {
1239   //  std::cout << "I know" << std::endl;
1240   //} else {
1241   osg::notify(osg::ALWAYS) << "Unknown TexEnv mode" << std::endl;
1242   //}
1243   return (uvRet);
1244 }
1245 
1246 /////////////////////////////////////////////////////////////////////////
1247 //
1248 // writeColor
1249 //
1250 /////////////////////////////////////////////////////////////////////////
writeColor(osg::Geometry * geom,std::vector<int> & primitiveSetFaces,int nbFaces)1251 void ToVRML::writeColor(osg::Geometry* geom, std::vector<int>& primitiveSetFaces, int nbFaces) {
1252 
1253   osg::ref_ptr < osg::Vec4Array > cArray = (osg::Vec4Array*) (geom->getColorArray());
1254   if (!cArray.valid()) {
1255     return;
1256   }
1257 
1258   osg::Array::Binding colorBinding = osg::getBinding(geom->getColorArray());
1259   if (colorBinding == osg::Array::BIND_PER_VERTEX || colorBinding == osg::Array::BIND_OVERALL) {
1260     _fout << indentM() << "colorPerVertex TRUE \n";
1261   } else {
1262     _fout << indentM() << "colorPerVertex FALSE \n";
1263   }
1264 
1265   _fout << indent() << "color Color {\n";
1266   _fout << indentM() << "color [\n";
1267   indentM();
1268   osg::Vec4 c;
1269 
1270   if (colorBinding == osg::Array::BIND_PER_VERTEX) {
1271     for (unsigned int j = 0; j < (*cArray).size(); j++) {
1272       c = (*cArray)[j];
1273       _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n";
1274     }
1275 
1276   } else if (colorBinding == osg::Array::BIND_OVERALL) {
1277     c = (*cArray)[0];
1278     int size = ((osg::Vec3Array*) (geom->getVertexArray()))->size();
1279     for (int j = 0; j < size; j++) {
1280       _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n";
1281     }
1282 
1283   } else if (colorBinding == osg::Array::BIND_PER_PRIMITIVE_SET) {
1284     for (unsigned int j = 0; j < (*cArray).size(); j++) {
1285       c = (*cArray)[j];
1286       for (int k = 0; k < primitiveSetFaces[j]; k++) {
1287         _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n";
1288       }
1289     }
1290   }
1291 
1292   _fout << indentL() << "]\n";
1293   _fout << indentL() << "}\n";
1294   indentL();
1295 }
1296