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