1 // -*-c++-*-
2 
3 #include "ConvertFromPerformer.h"
4 
5 #include <osg/Group>
6 #include <osg/MatrixTransform>
7 #include <osg/LOD>
8 #include <osg/Switch>
9 #include <osg/Geode>
10 #include <osg/Billboard>
11 #include <osg/Texture2D>
12 #include <osg/Image>
13 #include <osg/CullFace>
14 #include <osg/TexGen>
15 #include <osg/TexEnv>
16 #include <osg/TexMat>
17 #include <osg/Material>
18 #include <osg/Notify>
19 #include <osg/Geometry>
20 #include <osg/Sequence>
21 #include <osg/ShadeModel>
22 #include <osg/Depth>
23 #include <osg/AlphaFunc>
24 
25 #include <osgDB/FileNameUtils>
26 #include <osgDB/Registry>
27 #include <osgDB/WriteFile>
28 
29 #include <Performer/pf/pfNode.h>
30 #include <Performer/pf/pfGeode.h>
31 #include <Performer/pf/pfBillboard.h>
32 #include <Performer/pf/pfScene.h>
33 #include <Performer/pf/pfGroup.h>
34 #include <Performer/pf/pfDCS.h>
35 #include <Performer/pf/pfSCS.h>
36 #include <Performer/pf/pfLOD.h>
37 #include <Performer/pf/pfSwitch.h>
38 #include <Performer/pf/pfSequence.h>
39 #include <Performer/pr/pfGeoState.h>
40 #include <Performer/pr/pfMaterial.h>
41 #include <Performer/pr/pfTexture.h>
42 
43 #ifdef WIN32
44 #define snprintf _snprintf
45 #endif
46 
47 // Need to undefine these because Performer defines them and it causes a
48 // compiler error in ConvertFromPerformer::visitBillboard.
49 #ifdef   AXIAL_ROT
50 #undef   AXIAL_ROT
51 #endif
52 
53 #ifdef   POINT_ROT_EYE
54 #undef   POINT_ROT_EYE
55 #endif
56 
57 #ifdef   POINT_ROT_WORLD
58 #undef   POINT_ROT_WORLD
59 #endif
60 
61 extern "C"
62 {
63 
64     extern int
pfdStoreFile_osg(pfNode * root,char * fileName)65         pfdStoreFile_osg (pfNode* root, char *fileName)
66     {
67         ConvertFromPerformer converter;
68         osg::Node* node =  converter.convert(root);
69 
70         if (node==NULL) return 0;
71         if (osgDB::writeNodeFile(*node,fileName)) return 1;
72         else return 0;
73     }
74 
75 }
76 
77 
ConvertFromPerformer()78 ConvertFromPerformer::ConvertFromPerformer()
79 {
80     _osgRoot = NULL;
81 
82     _gsetBindMap[PFGS_OFF] = deprecated_osg::Geometry::BIND_OFF;
83     _gsetBindMap[PFGS_OVERALL] = deprecated_osg::Geometry::BIND_OVERALL;
84     _gsetBindMap[PFGS_PER_PRIM] = deprecated_osg::Geometry::BIND_PER_PRIMITIVE;
85     _gsetBindMap[PFGS_PER_VERTEX] = deprecated_osg::Geometry::BIND_PER_VERTEX;
86 
87     _saveImagesAsRGB = false;
88     _saveAbsoluteImagePath = false;
89 }
90 
91 
~ConvertFromPerformer()92 ConvertFromPerformer::~ConvertFromPerformer()
93 {
94 }
95 
96 
convert(pfNode * node)97 osg::Node* ConvertFromPerformer::convert(pfNode* node)
98 {
99     if (node==NULL) return NULL;
100     return visitNode(NULL,node);
101 }
102 
103 
getOsgObject(pfObject * pfObj)104 osg::Object* ConvertFromPerformer::getOsgObject(pfObject* pfObj)
105 {
106     PfObjectToOsgObjectMap::iterator fitr = _pfToOsgMap.find(pfObj);
107     if (fitr != _pfToOsgMap.end())
108     {
109         //         OSG_DEBUG << "Found shared object"<<std::endl;
110         return (*fitr).second;
111     }
112     else return NULL;
113 }
114 
115 
registerPfObjectForOsgObject(pfObject * pfObj,osg::Object * osgObj)116 void ConvertFromPerformer::registerPfObjectForOsgObject(pfObject* pfObj,osg::Object* osgObj)
117 {
118     _pfToOsgMap[pfObj] = osgObj;
119 }
120 
121 
visitNode(osg::Group * osgParent,pfNode * node)122 osg::Node* ConvertFromPerformer::visitNode(osg::Group* osgParent,pfNode* node)
123 {
124     if (node==NULL) return NULL;
125 
126     if      (node->getType()->isDerivedFrom( pfBillboard::getClassType()))  return visitBillboard(osgParent,(pfBillboard*)node);
127     else if (node->getType()->isDerivedFrom( pfGeode::getClassType()))      return visitGeode(osgParent,(pfGeode*)node);
128     else if (node->getType()->isDerivedFrom( pfScene::getClassType()))      return visitScene(osgParent,(pfScene*)node);
129     else if (node->getType()->isDerivedFrom( pfDCS::getClassType()))        return visitDCS(osgParent,(pfDCS*)node);
130     else if (node->getType()->isDerivedFrom( pfSCS::getClassType()))        return visitSCS(osgParent,(pfSCS*)node);
131     else if (node->getType()->isDerivedFrom( pfLOD::getClassType()))        return visitLOD(osgParent,(pfLOD*)node);
132     else if (node->getType()->isDerivedFrom( pfSequence::getClassType()))   return visitSequence(osgParent,(pfSequence*)node);
133     else if (node->getType()->isDerivedFrom( pfSwitch::getClassType()))     return visitSwitch(osgParent,(pfSwitch*)node);
134     else if (node->getType()->isDerivedFrom( pfGroup::getClassType()))      return visitGroup(osgParent,(pfGroup*)node);
135 
136     return NULL;
137 }
138 
139 
visitScene(osg::Group * osgParent,pfScene * scene)140 osg::Node* ConvertFromPerformer::visitScene(osg::Group* osgParent,pfScene* scene)
141 {
142     osg::Group* osgScene = dynamic_cast<osg::Group*>(getOsgObject(scene));
143     if (osgScene)
144     {
145         if (osgParent) osgParent->addChild(osgScene);
146         return osgScene;
147     }
148 
149     osgScene = new osg::Group;
150     if (osgParent) osgParent->addChild(osgScene);
151 
152     registerPfObjectForOsgObject(scene,osgScene);
153 
154     const char* name = scene->getName();
155     if (name) osgScene->setName(name);
156 
157     for(int i=0;i<scene->getNumChildren();++i)
158     {
159         visitNode(osgScene,scene->getChild(i));
160     }
161     return (osg::Node*)osgScene;
162 }
163 
164 
visitGroup(osg::Group * osgParent,pfGroup * group)165 osg::Node* ConvertFromPerformer::visitGroup(osg::Group* osgParent,pfGroup* group)
166 {
167     osg::Group* osgGroup = dynamic_cast<osg::Group*>(getOsgObject(group));
168     if (osgGroup)
169     {
170         if (osgParent) osgParent->addChild(osgGroup);
171         return osgGroup;
172     }
173 
174     osgGroup = new osg::Group;
175     if (osgParent) osgParent->addChild(osgGroup);
176 
177     registerPfObjectForOsgObject(group,osgGroup);
178 
179     const char* name = group->getName();
180     if (name) osgGroup->setName(name);
181 
182     for(int i=0;i<group->getNumChildren();++i)
183     {
184         visitNode(osgGroup,group->getChild(i));
185     }
186     return (osg::Node*)osgGroup;
187 }
188 
189 
visitLOD(osg::Group * osgParent,pfLOD * lod)190 osg::Node* ConvertFromPerformer::visitLOD(osg::Group* osgParent,pfLOD* lod)
191 {
192     osg::LOD* osgLOD = dynamic_cast<osg::LOD*>(getOsgObject(lod));
193     if (osgLOD)
194     {
195         if (osgParent) osgParent->addChild(osgLOD);
196         return osgLOD;
197     }
198 
199     osgLOD = new osg::LOD;
200     if (osgParent) osgParent->addChild(osgLOD);
201 
202     registerPfObjectForOsgObject(lod,osgLOD);
203 
204     const char* name = lod->getName();
205     if (name) osgLOD->setName(name);
206 
207     pfVec3 center;
208     lod->getCenter(center);
209     osg::Vec3 osgCenter(center[0],center[1],center[2]);
210     osgLOD->setCenter(osgCenter);
211 
212     int i;
213     for(i=0;i<lod->getNumRanges()-1;++i)
214     {
215         osgLOD->setRange(i,lod->getRange(i),lod->getRange(i+1));
216     }
217 
218     for(i=0;i<lod->getNumChildren();++i)
219     {
220         visitNode(osgLOD,lod->getChild(i));
221     }
222     return (osg::Node*)osgLOD;
223 
224 }
225 
226 
visitSwitch(osg::Group * osgParent,pfSwitch * switchNode)227 osg::Node* ConvertFromPerformer::visitSwitch(osg::Group* osgParent,pfSwitch* switchNode)
228 {
229     osg::Switch* osgSwitch = dynamic_cast<osg::Switch*>(getOsgObject(switchNode));
230     if (osgSwitch)
231     {
232         if (osgParent) osgParent->addChild(osgSwitch);
233         return osgSwitch;
234     }
235 
236     osgSwitch = new osg::Switch;
237     osgSwitch->setAllChildrenOff();
238     if (osgParent) osgParent->addChild(osgSwitch);
239 
240     registerPfObjectForOsgObject(switchNode,osgSwitch);
241 
242     const char* name = switchNode->getName();
243     if (name) osgSwitch->setName(name);
244 
245     float val = switchNode->getVal();
246     if (val==PFSWITCH_ON)
247     {
248         osgSwitch->setAllChildrenOn();
249     }
250     else if (val==PFSWITCH_OFF)
251     {
252         osgSwitch->setAllChildrenOff();
253     }
254     else
255     {
256         osgSwitch->setSingleChildOn((unsigned int)val);
257     }
258 
259     for(int i=0;i<switchNode->getNumChildren();++i)
260     {
261         visitNode(osgSwitch,switchNode->getChild(i));
262     }
263     return (osg::Node*)osgSwitch;
264 }
265 
266 
visitSequence(osg::Group * osgParent,pfSequence * sequence)267 osg::Node* ConvertFromPerformer::visitSequence(osg::Group* osgParent,
268                                                pfSequence* sequence)
269 {
270 
271     //OSG_WARN<<"Warning : cannot convert pfSequence as no osg::Sequence exists, using osg::Switch instead."<<std::endl;
272 
273     osg::Sequence* osgSequence = dynamic_cast<osg::Sequence*>(getOsgObject(sequence));
274     if (osgSequence)
275     {
276         if (osgParent) osgParent->addChild(osgSequence);
277         return osgSequence;
278     }
279 
280     osgSequence = new osg::Sequence;
281     if (osgParent) osgParent->addChild(osgSequence);
282 
283     registerPfObjectForOsgObject(sequence,osgSequence);
284 
285 #if 0
286     if (sequence->getNumChildren()>0)
287     {
288         // set switch to first child as a 'hack' to prevent all
289         // children being traversed during rendering.  Note,
290         // once osg::Sequence has been implemented this can all
291         // be removed.
292         osgSequence->setValue(0);
293     }
294 #endif
295 
296     // add children
297     for(int i=0;i<sequence->getNumChildren();++i)
298     {
299         //OSG_WARN << "child " << i << " time " << sequence->getTime(i) << std::endl;
300         osgSequence->setTime(i, sequence->getTime(i));
301         visitNode(osgSequence,sequence->getChild(i));
302     }
303 
304     // interval
305     int mode, begin, end;
306     sequence->getInterval(&mode, &begin, &end);
307 
308     //OSG_WARN << "loop " << mode << std::endl;
309     osg::Sequence::LoopMode loopMode = osg::Sequence::LOOP;
310     if (mode == PFSEQ_SWING)
311         loopMode = osg::Sequence::SWING;
312     osgSequence->setInterval(loopMode, begin, end);
313 
314     // duration
315     float speed;
316     int repeat;
317     sequence->getDuration(&speed, &repeat);
318     osgSequence->setDuration(speed, repeat);
319 
320     // mode
321     mode = sequence->getMode();
322 
323     osg::Sequence::SequenceMode seqMode = osg::Sequence::START;
324     switch (mode) {
325     case PFSEQ_STOP:
326         seqMode = osg::Sequence::STOP;
327         break;
328     case PFSEQ_PAUSE:
329         seqMode = osg::Sequence::PAUSE;
330         break;
331     }
332     osgSequence->setMode(seqMode);
333 
334     return (osg::Node*)osgSequence;
335 }
336 
337 
visitDCS(osg::Group * osgParent,pfDCS * dcs)338 osg::Node* ConvertFromPerformer::visitDCS(osg::Group* osgParent,pfDCS* dcs)
339 {
340 
341     osg::MatrixTransform* osgTransform = dynamic_cast<osg::MatrixTransform*>(getOsgObject(dcs));
342     if (osgTransform)
343     {
344         if (osgParent) osgParent->addChild(osgTransform);
345         return osgTransform;
346     }
347 
348     osgTransform = new osg::MatrixTransform;
349     if (osgParent) osgParent->addChild(osgTransform);
350 
351     registerPfObjectForOsgObject(dcs,osgTransform);
352 
353     const char* name = dcs->getName();
354     if (name) osgTransform->setName(name);
355 
356     pfMatrix matrix;
357     dcs->getMat(matrix);
358 
359     osg::Matrix osgMatrix(matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3],
360         matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3],
361         matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3],
362         matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]);
363 
364     osgTransform->setMatrix(osgMatrix);
365 
366     for(int i=0;i<dcs->getNumChildren();++i)
367     {
368         visitNode(osgTransform,dcs->getChild(i));
369     }
370     return (osg::Node*)osgTransform;
371 }
372 
373 
visitSCS(osg::Group * osgParent,pfSCS * scs)374 osg::Node* ConvertFromPerformer::visitSCS(osg::Group* osgParent,pfSCS* scs)
375 {
376     // note the OSG does not currently have a SCS, so use DCS instead.
377     osg::MatrixTransform* osgTransform = dynamic_cast<osg::MatrixTransform*>(getOsgObject(scs));
378     if (osgTransform)
379     {
380         if (osgParent) osgParent->addChild(osgTransform);
381         return osgTransform;
382     }
383 
384     osgTransform = new osg::MatrixTransform;
385     if (osgParent) osgParent->addChild(osgTransform);
386 
387     osgTransform->setDataVariance(osg::Object::STATIC);
388 
389     registerPfObjectForOsgObject(scs,osgTransform);
390 
391     const char* name = scs->getName();
392     if (name) osgTransform->setName(name);
393 
394     pfMatrix matrix;
395     scs->getMat(matrix);
396     osg::Matrix osgMatrix(matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3],
397         matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3],
398         matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3],
399         matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]);
400 
401     osgTransform->setMatrix(osgMatrix);
402 
403     for(int i=0;i<scs->getNumChildren();++i)
404     {
405         visitNode(osgTransform,scs->getChild(i));
406     }
407     return (osg::Node*)osgTransform;
408 }
409 
410 
visitGeode(osg::Group * osgParent,pfGeode * geode)411 osg::Node* ConvertFromPerformer::visitGeode(osg::Group* osgParent,pfGeode* geode)
412 {
413     osg::Geode* osgGeode = dynamic_cast<osg::Geode*>(getOsgObject(geode));
414     if (osgGeode)
415     {
416         if (osgParent) osgParent->addChild(osgGeode);
417         return osgGeode;
418     }
419 
420     osgGeode = new osg::Geode;
421     if (osgParent) osgParent->addChild(osgGeode);
422 
423     registerPfObjectForOsgObject(geode,osgGeode);
424 
425     const char* name = geode->getName();
426     if (name) osgGeode->setName(name);
427 
428     for(int i=0;i<geode->getNumGSets();++i)
429     {
430         visitGeoSet(osgGeode,geode->getGSet(i));
431     }
432 
433     return (osg::Node*)osgGeode;
434 }
435 
436 
visitBillboard(osg::Group * osgParent,pfBillboard * billboard)437 osg::Node* ConvertFromPerformer::visitBillboard(osg::Group* osgParent,pfBillboard* billboard)
438 {
439     //    return NULL;
440 
441     osg::Billboard* osgBillboard = dynamic_cast<osg::Billboard*>(getOsgObject(billboard));
442     if (osgBillboard)
443     {
444         if (osgParent) osgParent->addChild(osgBillboard);
445         return osgBillboard;
446     }
447 
448     osgBillboard = new osg::Billboard;
449     if (osgParent) osgParent->addChild(osgBillboard);
450 
451     registerPfObjectForOsgObject(billboard,osgBillboard);
452 
453     const char* name = billboard->getName();
454     if (name) osgBillboard->setName(name);
455 
456     pfVec3 axis;
457     billboard->getAxis(axis);
458     osgBillboard->setAxis(osg::Vec3(axis[0],axis[1],axis[2]));
459 
460     switch( billboard->getMode( PFBB_ROT ) )
461     {
462     case PFBB_AXIAL_ROT:
463        osgBillboard->setMode( osg::Billboard::AXIAL_ROT );
464        break;
465     case PFBB_POINT_ROT_EYE:
466        osgBillboard->setMode( osg::Billboard::POINT_ROT_EYE );
467        break;
468     case PFBB_POINT_ROT_WORLD:
469        osgBillboard->setMode( osg::Billboard::POINT_ROT_WORLD );
470        break;
471     }
472 
473     for(int i=0;i<billboard->getNumGSets();++i)
474     {
475                                  /* osg::GeoSet* osggset = */
476         visitGeoSet(osgBillboard,billboard->getGSet(i));
477         pfVec3 pos;
478         billboard->getPos(i,pos);
479         osgBillboard->setPosition(i,osg::Vec3(pos[0],pos[1],pos[2]));
480     }
481 
482     return (osg::Node*)osgBillboard;
483 }
484 
485 
getNumVerts(pfGeoSet * gset)486 int ConvertFromPerformer::getNumVerts(pfGeoSet *gset)
487 {
488     int nv;
489     int np;
490     int *lens;
491     int i;
492 
493     np = gset->getNumPrims();
494     nv = 0;
495 
496     switch( gset->getPrimType() )
497     {
498         case PFGS_POINTS :
499             nv = np;
500             break;
501 
502         case PFGS_LINES :
503             nv = 2 * np;
504             break;
505 
506         case PFGS_TRIS :
507             nv = 3 * np;
508             break;
509 
510         case PFGS_QUADS :
511             nv = 4 * np;
512             break;
513 
514         case PFGS_TRISTRIPS :
515         case PFGS_TRIFANS :
516         case PFGS_FLAT_TRISTRIPS :
517         case PFGS_POLYS :
518         case PFGS_LINESTRIPS :
519         case PFGS_FLAT_LINESTRIPS :
520 
521             lens = gset->getPrimLengths();
522             for( i = 0; i < np; i++ )
523                 nv += lens[i];
524             break;
525 
526     }
527 
528     return nv;
529 }
530 
531 
visitGeoSet(osg::Geode * osgGeode,pfGeoSet * geoset)532 osg::Drawable* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* geoset)
533 {
534     if (geoset==NULL) return NULL;
535 
536     osg::Drawable* osgDrawable = dynamic_cast<osg::Drawable*>(getOsgObject(geoset));
537     if (osgDrawable)
538     {
539         if (osgGeode) osgGeode->addDrawable(osgDrawable);
540         return osgDrawable;
541     }
542 
543     // we'll make it easy to convert by using the Performer style osg::GeoSet,
544     // and then convert back to a deprecated_osg::Geometry afterwards.
545     //osg::ref_ptr<osg::GeoSet> geom = new osg::GeoSet;
546     deprecated_osg::Geometry* geom = new deprecated_osg::Geometry;
547 
548     int i;
549 
550     // number of prims
551     int np = geoset->getNumPrims();
552     int *plen = geoset->getPrimLengths();
553 
554     // Number of verticies (may be different than number of coords)
555     int nv = getNumVerts( geoset );
556 
557     int prim = geoset->getPrimType();
558     int flat_shaded_skip_per_primitive=0;
559     if (prim == PFGS_FLAT_LINESTRIPS)       flat_shaded_skip_per_primitive=1;
560     else if (prim == PFGS_FLAT_TRISTRIPS)   flat_shaded_skip_per_primitive=2;
561     else if (prim == PFGS_FLAT_TRIFANS)     flat_shaded_skip_per_primitive=2;
562 
563     int flat_shaded_skip_all_primitives=flat_shaded_skip_per_primitive*np;
564 
565     // create the primitive sets.
566     switch( geoset->getPrimType() )
567     {
568         case PFGS_POINTS :
569             geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,np));
570             break;
571 
572         case PFGS_LINES :
573             geom->addPrimitiveSet(new osg::DrawArrays(GL_LINES,0,2*np));
574             break;
575 
576         case PFGS_TRIS :
577             geom->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES,0,3*np));
578             break;
579 
580         case PFGS_QUADS :
581             geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4*np));
582             break;
583 
584         case PFGS_TRISTRIPS :
585             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_TRIANGLE_STRIP,0,np,plen));
586             break;
587 
588         case PFGS_TRIFANS :
589             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_TRIANGLE_FAN,0,np,plen));
590             break;
591 
592         case PFGS_FLAT_TRISTRIPS :
593             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_TRIANGLE_STRIP,0,np,plen));
594             break;
595 
596         case PFGS_POLYS :
597             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_POLYGON,0,np,plen));
598             break;
599 
600         case PFGS_LINESTRIPS :
601             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_LINE_STRIP,0,np,plen));
602             break;
603 
604         case PFGS_FLAT_LINESTRIPS :
605             geom->addPrimitiveSet(new osg::DrawArrayLengths(GL_LINE_STRIP,0,np,plen));
606             break;
607 
608         default:
609            OSG_INFO << "ConvertFromPerformer::visitGeoSet: Osg can't convert primitive "
610                      << geoset->getPrimType()
611                      << std::endl;
612             break;
613 
614     }
615 
616 
617     pfVec3 *coords;
618     ushort *ilist;
619     geoset->getAttrLists( PFGS_COORD3,  (void **)&coords, &ilist );
620 
621     // copy the vertex coordinates across.
622     if( coords )
623     {
624         // calc the maximum num of vertex from the index list.
625         int cc;
626         if (ilist)
627         {
628             cc = 0;
629             for( i = 0; i < nv; i++ )
630                 if( ilist[i] > cc ) cc = ilist[i];
631             cc++;
632         }
633         else
634             cc = nv;
635 
636         osg::Vec3Array* osg_coords = new osg::Vec3Array(cc);
637         for( i = 0; i < cc; i++ )
638         {
639             (*osg_coords)[i][0] = coords[i][0];
640             (*osg_coords)[i][1] = coords[i][1];
641             (*osg_coords)[i][2] = coords[i][2];
642         }
643 
644         geom->setVertexArray(osg_coords);
645 
646         if(ilist)
647         {
648             geom->setVertexIndices(new osg::UShortArray(nv,ilist));
649         }
650 
651     }
652 
653 
654     pfVec2 *tcoords;
655     geoset->getAttrLists( PFGS_TEXCOORD2,  (void **)&tcoords, &ilist );
656 
657     // copy texture coords
658     if(tcoords)
659     {
660         int bind = geoset->getAttrBind( PFGS_TEXCOORD2 );
661 
662 
663         if (bind==PFGS_PER_VERTEX && bind != PFGS_OFF)
664         {
665             int nn = bind == PFGS_OFF ? 0 :
666                      bind == PFGS_OVERALL ? 1 :
667                      bind == PFGS_PER_PRIM ? geoset->getNumPrims() :
668                      bind == PFGS_PER_VERTEX ? nv : 0;
669 
670             // set the normal binding type.
671             //geom->setTextureBinding(_gsetBindMap[bind]);
672 
673             // calc the maximum num of vertex from the index list.
674             int cc;
675             if (ilist)
676             {
677                 cc = 0;
678                 for( i = 0; i < nv; i++ )
679                     if( ilist[i] > cc ) cc = ilist[i];
680                 cc++;
681             }
682             else
683                 cc = nn;
684 
685             osg::Vec2Array* osg_tcoords = new osg::Vec2Array(cc);
686             for( i = 0; i < cc; i++ )
687             {
688                 (*osg_tcoords)[i][0] = tcoords[i][0];
689                 (*osg_tcoords)[i][1] = tcoords[i][1];
690             }
691 
692             geom->setTexCoordArray(0,osg_tcoords);
693 
694             if(ilist)
695             {
696                 geom->setTexCoordIndices(0,new osg::UShortArray(nn,ilist));
697             }
698         }
699         else
700         {
701             OSG_INFO<<"OSG can't handle non PER_VERTEX tex coord binding at present"<<std::endl;
702         }
703 
704     }
705 
706     pfVec3 *norms;
707     geoset->getAttrLists( PFGS_NORMAL3,  (void **)&norms, &ilist );
708 
709     // copy normals
710     if(norms)
711     {
712         int bind = geoset->getAttrBind( PFGS_NORMAL3 );
713         if (bind==PFGS_PER_VERTEX && flat_shaded_skip_all_primitives!=0)
714         {
715             // handle flat shaded skip of normals.
716             int nn = nv-flat_shaded_skip_all_primitives;
717 
718 
719             if (ilist)
720             {
721                 // calc the maximum num of vertex from the index list.
722                 int cc = 0;
723                 for( i = 0; i < nn; i++ )
724                     if( ilist[i] > cc ) cc = ilist[i];
725                 cc++;
726 
727                 // straight forward mapping of normals across.
728                 osg::Vec3Array* osg_norms = new osg::Vec3Array(cc);
729                 for( i = 0; i < cc; i++ )
730                 {
731                     (*osg_norms)[i][0] = norms[i][0];
732                     (*osg_norms)[i][1] = norms[i][1];
733                     (*osg_norms)[i][2] = norms[i][2];
734                 }
735                 geom->setNormalArray(osg_norms);
736 
737                 // set the normal binding type.
738                 geom->setNormalBinding(_gsetBindMap[bind]);
739 
740                 osg::UShortArray* osg_indices = new osg::UShortArray;
741                 osg_indices->reserve(nv);
742 
743                 int ni=0;
744                 for( i = 0; i < np; ++i)
745                 {
746                     for(int si=0;si<flat_shaded_skip_per_primitive;++si)
747                     {
748                         osg_indices->push_back(ilist[ni]);
749                     }
750                     for( int pi=0; pi < plen[i]-flat_shaded_skip_per_primitive; ++pi)
751                     {
752                         osg_indices->push_back(ilist[ni++]);
753                     }
754                 }
755 
756                 if (ni!=nn)
757                 {
758                     OSG_INFO << "1 ni!=nn"<<std::endl;
759                 }
760 
761                 geom->setNormalIndices(osg_indices);
762 
763 
764             }
765             else
766             {
767                 osg::Vec3Array* osg_norms = new osg::Vec3Array;
768                 osg_norms->reserve(nv);
769 
770                 int ni=0;
771                 for( i = 0; i < np; ++i)
772                 {
773                     for(int si=0;si<flat_shaded_skip_per_primitive;++si)
774                     {
775                         osg_norms->push_back(osg::Vec3(norms[ni][0],norms[ni][1],norms[ni][2]));
776                     }
777                     for( int pi=0; pi < plen[i]-flat_shaded_skip_per_primitive; ++pi)
778                     {
779                         osg_norms->push_back(osg::Vec3(norms[ni][0],norms[ni][1],norms[ni][2]));
780                         ni++;
781                     }
782                 }
783 
784                 geom->setNormalArray(osg_norms);
785             }
786 
787         }
788         else
789         {
790             int nn = bind == PFGS_OFF ? 0 :
791                      bind == PFGS_OVERALL ? 1 :
792                      bind == PFGS_PER_PRIM ? geoset->getNumPrims() :
793                      bind == PFGS_PER_VERTEX ? nv : 0;
794 
795             // calc the maximum num of vertex from the index list.
796             int cc;
797             if (ilist)
798             {
799                 cc = 0;
800                 for( i = 0; i < nn; i++ )
801                     if( ilist[i] > cc ) cc = ilist[i];
802                 cc++;
803             }
804             else
805                 cc = nn;
806 
807             osg::Vec3Array* osg_norms = new osg::Vec3Array(cc);
808             for( i = 0; i < cc; i++ )
809             {
810                 (*osg_norms)[i][0] = norms[i][0];
811                 (*osg_norms)[i][1] = norms[i][1];
812                 (*osg_norms)[i][2] = norms[i][2];
813             }
814             geom->setNormalArray(osg_norms);
815 
816             // set the normal binding type.
817             geom->setNormalBinding(_gsetBindMap[bind]);
818 
819             if(ilist)
820             {
821                 geom->setNormalIndices(new osg::UShortArray(nn,ilist));
822             }
823 
824         }
825     }
826 
827     pfVec4 *colors;
828     geoset->getAttrLists( PFGS_COLOR4,  (void **)&colors, &ilist );
829 
830     // copy color coords
831     if(colors)
832     {
833         int bind = geoset->getAttrBind( PFGS_COLOR4 );
834         if (bind==PFGS_PER_VERTEX && flat_shaded_skip_all_primitives!=0)
835         {
836             // handle flat shaded skip of colours.
837             // handle flat shaded skip of normals.
838             int nn = nv-flat_shaded_skip_all_primitives;
839 
840             if (ilist)
841             {
842                 // calc the maximum num of vertex from the index list.
843                 int cc = 0;
844                 for( i = 0; i < nn; i++ )
845                     if( ilist[i] > cc ) cc = ilist[i];
846                 cc++;
847 
848                 // straight forward mapping of normals across.
849                 osg::Vec4Array* osg_colors = new osg::Vec4Array(cc);
850                 for( i = 0; i < cc; i++ )
851                 {
852                     (*osg_colors)[i][0] = colors[i][0];
853                     (*osg_colors)[i][1] = colors[i][1];
854                     (*osg_colors)[i][2] = colors[i][2];
855                     (*osg_colors)[i][3] = colors[i][3];
856                 }
857                 geom->setColorArray(osg_colors);
858 
859                 // set the color binding type.
860                 geom->setColorBinding(_gsetBindMap[bind]);
861 
862 
863                 osg::UShortArray* osg_indices = new osg::UShortArray;
864                 osg_indices->reserve(nv);
865 
866                 int ni=0;
867                 for( i = 0; i < np; ++i)
868                 {
869                     for(int si=0;si<flat_shaded_skip_per_primitive;++si)
870                     {
871                         osg_indices->push_back(ilist[ni]);
872                     }
873                     for( int pi=0; pi < plen[i]-flat_shaded_skip_per_primitive; ++pi)
874                     {
875                         osg_indices->push_back(ilist[ni++]);
876                     }
877                 }
878 
879                 if (ni!=nn)
880                 {
881                     OSG_INFO << "1 ni!=nn"<<std::endl;
882                 }
883 
884                 geom->setColorIndices(osg_indices);
885 
886 
887             }
888             else
889             {
890                 osg::Vec4Array* osg_colors = new osg::Vec4Array;
891                 osg_colors->reserve(nv);
892 
893                 int ni=0;
894                 for( i = 0; i < np; ++i)
895                 {
896                     for(int si=0;si<flat_shaded_skip_per_primitive;++si)
897                     {
898                         osg_colors->push_back(osg::Vec4(colors[ni][0],colors[ni][1],colors[ni][2],colors[ni][3]));
899                     }
900                     for( int pi=0; pi < plen[i]-flat_shaded_skip_per_primitive; ++pi)
901                     {
902                         osg_colors->push_back(osg::Vec4(colors[ni][0],colors[ni][1],colors[ni][2],colors[ni][3]));
903                         ni++;
904                     }
905                 }
906 
907                 geom->setColorArray(osg_colors);
908 
909                 // set the color binding type.
910                 geom->setColorBinding(_gsetBindMap[bind]);
911             }
912         }
913         else
914         {
915             int nn = bind == PFGS_OFF ? 0 :
916                      bind == PFGS_OVERALL ? 1 :
917                      bind == PFGS_PER_PRIM ? geoset->getNumPrims() :
918                      bind == PFGS_PER_VERTEX ? nv : 0;
919 
920             // calc the maximum num of vertex from the index list.
921             int cc;
922             if (ilist)
923             {
924                 cc = 0;
925                 for( i = 0; i < nn; i++ )
926                     if( ilist[i] > cc ) cc = ilist[i];
927                 cc++;
928             }
929             else
930                 cc = nn;
931 
932             osg::Vec4Array* osg_colors = new osg::Vec4Array(cc);
933             for( i = 0; i < cc; i++ )
934             {
935                 (*osg_colors)[i][0] = colors[i][0];
936                 (*osg_colors)[i][1] = colors[i][1];
937                 (*osg_colors)[i][2] = colors[i][2];
938                 (*osg_colors)[i][3] = colors[i][3];
939             }
940 
941             geom->setColorArray(osg_colors);
942 
943             // set the color binding type.
944             geom->setColorBinding(_gsetBindMap[bind]);
945 
946 
947             if(ilist)
948             {
949                 geom->setColorIndices(new osg::UShortArray(nn,ilist));
950             }
951 
952         }
953     }
954     else
955     {
956     }
957 
958 
959 
960     visitGeoState(geom,geoset->getGState());
961 
962     if (flat_shaded_skip_per_primitive)
963     {
964         osg::StateSet* stateset = geom->getOrCreateStateSet();
965         osg::ShadeModel* shademodel = dynamic_cast<osg::ShadeModel*>(stateset->getAttribute(osg::StateAttribute::SHADEMODEL));
966         if (!shademodel)
967         {
968             shademodel = new osg::ShadeModel;
969             stateset->setAttribute(shademodel);
970         }
971         shademodel->setMode( osg::ShadeModel::FLAT );
972     }
973 
974     osgGeode->addDrawable(geom);
975     registerPfObjectForOsgObject(geoset,geom);
976 
977     return geom;
978 }
979 
980 
visitGeoState(osg::Drawable * osgDrawable,pfGeoState * geostate)981 osg::StateSet* ConvertFromPerformer::visitGeoState(osg::Drawable* osgDrawable,pfGeoState* geostate)
982 {
983     if (geostate==NULL) return NULL;
984 
985     osg::StateSet* osgStateSet = dynamic_cast<osg::StateSet*>(getOsgObject(geostate));
986     if (osgStateSet)
987     {
988         if (osgDrawable) osgDrawable->setStateSet(osgStateSet);
989         return osgStateSet;
990     }
991 
992     osgStateSet = new osg::StateSet;
993     if (osgDrawable) osgDrawable->setStateSet(osgStateSet);
994 
995     registerPfObjectForOsgObject(geostate,osgStateSet);
996 
997     // Don could you fill in some of these blanks???
998     unsigned int inherit = geostate->getInherit();
999     //     OSG_DEBUG << endl << "Inherit = "<<inherit<<std::endl;
1000     //     if (inherit & PFSTATE_TRANSPARENCY) OSG_DEBUG << "Inherit PFSTATE_TRANSPARENCY"<<std::endl;
1001     //     else OSG_DEBUG << "Define PFSTATE_TRANSPARENCY"<<std::endl;
1002     //     if (inherit & PFSTATE_ENTEXTURE) OSG_DEBUG << "Inherit PFSTATE_ENTEXTURE"<<std::endl;
1003     //     else OSG_DEBUG << "Define PFSTATE_ENTEXTURE"<<std::endl;
1004     //     if (inherit & PFSTATE_CULLFACE) OSG_DEBUG << "Inherit PFSTATE_CULLFACE"<<std::endl;
1005     //     else OSG_DEBUG << "Define PFSTATE_CULLFACE"<<std::endl;
1006     //     if (inherit & PFSTATE_ENLIGHTING) OSG_DEBUG << "Inherit PFSTATE_ENLIGHTING"<<std::endl;
1007     //     else OSG_DEBUG << "Define PFSTATE_ENLIGHTING"<<std::endl;
1008     //     if (inherit & PFSTATE_ENFOG) OSG_DEBUG << "Inherit PFSTATE_ENFOG"<<std::endl;
1009     //     else OSG_DEBUG << "Define PFSTATE_ENFOG"<<std::endl;
1010     //     if (inherit & PFSTATE_ENWIREFRAME) OSG_DEBUG << "Inherit PFSTATE_ENWIREFRAME"<<std::endl;
1011     //     else OSG_DEBUG << "Define PFSTATE_ENWIREFRAME"<<std::endl;
1012     //     if (inherit & PFSTATE_ENTEXMAT) OSG_DEBUG << "Inherit PFSTATE_ENTEXMAT"<<std::endl;
1013     //     else OSG_DEBUG << "Define PFSTATE_ENTEXMAT"<<std::endl;
1014     //     if (inherit & PFSTATE_ENTEXGEN) OSG_DEBUG << "Inherit PFSTATE_ENTEXGEN"<<std::endl;
1015     //     else OSG_DEBUG << "Define PFSTATE_ENTEXGEN"<<std::endl;
1016     //
1017     //     if (inherit & PFSTATE_ANTIALIAS) OSG_DEBUG << "Inherit PFSTATE_ANTIALIAS"<<std::endl;
1018     //     else OSG_DEBUG << "Define PFSTATE_ANTIALIAS"<<std::endl;
1019     //     if (inherit & PFSTATE_DECAL) OSG_DEBUG << "Inherit PFSTATE_DECAL"<<std::endl;
1020     //     else OSG_DEBUG << "Define PFSTATE_DECAL"<<std::endl;
1021     //     if (inherit & PFSTATE_ALPHAFUNC) OSG_DEBUG << "Inherit PFSTATE_ALPHAFUNC"<<std::endl;
1022     //     else OSG_DEBUG << "Define PFSTATE_ALPHAFUNC"<<std::endl;
1023     //     if (inherit & PFSTATE_ENCOLORTABLE) OSG_DEBUG << "Inherit PFSTATE_ENCOLORTABLE"<<std::endl;
1024     //     else OSG_DEBUG << "Define PFSTATE_ENCOLORTABLE"<<std::endl;
1025     //     if (inherit & PFSTATE_ENHIGHLIGHTING) OSG_DEBUG << "Inherit PFSTATE_ENHIGHLIGHTING"<<std::endl;
1026     //     else OSG_DEBUG << "Define PFSTATE_ENHIGHLIGHTING"<<std::endl;
1027     //     if (inherit & PFSTATE_ENLPOINTSTATE) OSG_DEBUG << "Inherit PFSTATE_ENLPOINTSTATE"<<std::endl;
1028     //     else OSG_DEBUG << "Define PFSTATE_ENLPOINTSTATE"<<std::endl;
1029     //     if (inherit & PFSTATE_ENTEXLOD) OSG_DEBUG << "Inherit PFSTATE_ENTEXLOD"<<std::endl;
1030     //     else OSG_DEBUG << "Define PFSTATE_ENTEXLOD"<<std::endl;
1031 
1032     if (!(inherit & PFSTATE_ALPHAFUNC)) {
1033         int mode = geostate->getMode(PFSTATE_ALPHAFUNC);
1034         float value = geostate->getVal(PFSTATE_ALPHAREF);
1035         osg::AlphaFunc* aFunc = new osg::AlphaFunc();
1036         switch (mode) {
1037             case PFAF_ALWAYS:
1038                 aFunc->setFunction(osg::AlphaFunc::ALWAYS); //==PFAF_OFF in performer 311
1039                 break;
1040             case PFAF_EQUAL:
1041                 aFunc->setFunction(osg::AlphaFunc::EQUAL);
1042                 break;
1043             case PFAF_GEQUAL:
1044                 aFunc->setFunction(osg::AlphaFunc::GEQUAL);
1045                 break;
1046             case PFAF_GREATER:
1047                 aFunc->setFunction(osg::AlphaFunc::GREATER);
1048                 break;
1049             case PFAF_LEQUAL:
1050                 aFunc->setFunction(osg::AlphaFunc::LEQUAL);
1051                 break;
1052             case PFAF_LESS:
1053                 aFunc->setFunction(osg::AlphaFunc::LESS);
1054                 break;
1055             case PFAF_NEVER:
1056                 aFunc->setFunction(osg::AlphaFunc::NEVER);
1057                 break;
1058             case PFAF_NOTEQUAL:
1059                 aFunc->setFunction(osg::AlphaFunc::NOTEQUAL);
1060                 break;
1061 //            case PFAF_OFF: //==PFAF_ALWAYS
1062 //                break;
1063             default: //warn PFAF not recognized?
1064                 break;
1065         }
1066         aFunc->setReferenceValue(value);
1067         if (mode != PFAF_OFF) {
1068             osgStateSet->setAttributeAndModes(aFunc);
1069         } else {
1070             osgStateSet->setAttributeAndModes(aFunc,osg::StateAttribute::OFF);
1071         }
1072     }
1073 
1074     if (inherit & PFSTATE_TRANSPARENCY) osgStateSet->setMode(GL_BLEND,osg::StateAttribute::INHERIT);
1075     else
1076     {
1077         int mode = geostate->getMode(PFSTATE_TRANSPARENCY);
1078         if (mode & PFTR_NO_OCCLUDE) {
1079             mode &= ~PFTR_NO_OCCLUDE;//remove NO_OCCLUDE bit
1080             osg::Depth* depth = new osg::Depth(osg::Depth::LESS,0.0f,1.0f,false);
1081             osgStateSet->setAttributeAndModes(depth);
1082         }
1083         switch(mode)
1084         {
1085             case(PFTR_FAST):
1086             case(PFTR_HIGH_QUALITY):
1087             case(PFTR_BLEND_ALPHA):
1088             case(PFTR_MS_ALPHA):
1089             case(PFTR_MS_ALPHA_MASK):
1090 //            case(PFTR_NO_OCCLUDE): //this is a bit flag.
1091             case(PFTR_ON):
1092                 osgStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
1093                 osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1094                 break;
1095             case(PFTR_OFF): osgStateSet->setMode(GL_BLEND,osg::StateAttribute::OFF);break;
1096             default:        osgStateSet->setMode(GL_BLEND,osg::StateAttribute::INHERIT);break;
1097         }
1098     }
1099 
1100     if (inherit & PFSTATE_ENTEXTURE) osgStateSet->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::INHERIT);
1101     else
1102     {
1103         int mode = geostate->getMode(PFSTATE_ENTEXTURE);
1104         switch(mode)
1105         {
1106             case(PF_ON):    osgStateSet->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::ON);break;
1107             case(PF_OFF):
1108             default:        osgStateSet->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF);break;
1109         }
1110     }
1111 
1112     if (inherit & PFSTATE_CULLFACE) osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::INHERIT);
1113     else
1114     {
1115         int mode = geostate->getMode(PFSTATE_CULLFACE);
1116         switch(mode)
1117         {
1118             case(PFCF_BACK):
1119             {
1120                 osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
1121                 osg::CullFace *cf = new osg::CullFace;
1122                 cf->setMode(osg::CullFace::BACK);
1123                 osgStateSet->setAttribute(cf);
1124             }
1125             break;
1126 
1127             case(PFCF_FRONT):
1128             {
1129                 osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
1130                 osg::CullFace *cf = new osg::CullFace;
1131                 cf->setMode(osg::CullFace::FRONT);
1132                 osgStateSet->setAttribute(cf);
1133             }
1134             break;
1135             case(PFCF_BOTH):
1136             {
1137                 osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
1138                 osg::CullFace *cf = new osg::CullFace;
1139                 cf->setMode(osg::CullFace::FRONT_AND_BACK);
1140                 osgStateSet->setAttribute(cf);
1141             }
1142             break;
1143             case(PFCF_OFF):
1144             default:        osgStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);break;
1145         }
1146     }
1147 
1148     if (inherit & PFSTATE_ENLIGHTING) osgStateSet->setMode(GL_LIGHTING,osg::StateAttribute::INHERIT);
1149     else
1150     {
1151         int mode = geostate->getMode(PFSTATE_ENLIGHTING);
1152         switch(mode)
1153         {
1154             case(PF_ON):    osgStateSet->setMode(GL_LIGHTING,osg::StateAttribute::ON);break;
1155             case(PF_OFF):
1156             default:        osgStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);break;
1157         }
1158     }
1159 
1160     if (inherit & PFSTATE_ENFOG) osgStateSet->setMode(GL_FOG,osg::StateAttribute::INHERIT);
1161     else
1162     {
1163         int mode = geostate->getMode(PFSTATE_ENFOG);
1164         switch(mode)
1165         {
1166             case(PF_ON):    osgStateSet->setMode(GL_FOG,osg::StateAttribute::ON);break;
1167             case(PF_OFF):
1168             default:        osgStateSet->setMode(GL_FOG,osg::StateAttribute::OFF);break;
1169         }
1170     }
1171 
1172     // not currently supported by OSG
1173     //     if (inherit & PFSTATE_ENWIREFRAME)  osgStateSet->setMode(osg::StateSet::WIREFRAME,osg::StateAttribute::INHERIT);
1174     //     else
1175     //     {
1176     //         int mode = geostate->getMode(PFSTATE_ENWIREFRAME);
1177     //         switch(mode)
1178     //         {
1179     //         case(PF_ON):    osgStateSet->setMode(osg::StateSet::WIREFRAME,osg::StateAttribute::ON);break;
1180     //         case(PF_OFF):
1181     //         default:        osgStateSet->setMode(osg::StateSet::WIREFRAME,osg::StateAttribute::OFF);break;
1182     //         }
1183     //     }
1184 
1185     // redundent in OSG's implementation of texmat mode
1186     //     if (inherit & PFSTATE_ENTEXMAT)  osgStateSet->setMode(osg::StateSet::TEXMAT,osg::StateAttribute::INHERIT);
1187     //     else
1188     //     {
1189     //         int mode = geostate->getMode(PFSTATE_ENTEXMAT);
1190     //         switch(mode)
1191     //         {
1192     //         case(PF_ON):    osgStateSet->setMode(osg::StateSet::TEXMAT,osg::StateAttribute::ON);break;
1193     //         case(PF_OFF):
1194     //         default:        osgStateSet->setMode(osg::StateSet::TEXMAT,osg::StateAttribute::OFF);break;
1195     //         }
1196     //     }
1197 
1198 
1199     // commenting out the following block since the TexGen should be set
1200     // appropriately by the osg::TexGen block below.
1201     //     if (inherit & PFSTATE_ENTEXGEN)  osgStateSet->setMode(osg::StateSet::TEXGEN,osg::StateAttribute::INHERIT);
1202     //     else
1203     //     {
1204     //         int mode = geostate->getMode(PFSTATE_ENTEXGEN);
1205     //         switch(mode)
1206     //         {
1207     //             case(PF_ON):    osgStateSet->setMode(osg::StateSet::TEXGEN,osg::StateAttribute::ON);break;
1208     //             case(PF_OFF):
1209     //             default:        osgStateSet->setMode(osg::StateSet::TEXGEN,osg::StateAttribute::OFF);break;
1210     //         }
1211     //     }
1212     //
1213 
1214 
1215     pfMaterial* front_mat = (pfMaterial*)geostate->getAttr(PFSTATE_FRONTMTL);
1216     pfMaterial* back_mat = (pfMaterial*)geostate->getAttr(PFSTATE_BACKMTL);
1217     visitMaterial(osgStateSet,front_mat,back_mat);
1218 
1219     pfTexture* tex = (pfTexture*)geostate->getAttr(PFSTATE_TEXTURE);
1220     visitTexture(osgStateSet,tex);
1221 
1222     pfTexEnv* texenv = (pfTexEnv*)geostate->getAttr(PFSTATE_TEXENV);
1223 
1224     if(texenv)
1225     {
1226       osg::TexEnv* osgTexEnv = new osg::TexEnv();
1227       int mode = texenv->getMode();
1228 
1229       float r,g,b,a;
1230       texenv->getBlendColor(&r, &g, &b, &a);
1231 
1232       switch(mode)
1233       {
1234           case(PFTE_MODULATE) :
1235               osgTexEnv->setMode(osg::TexEnv::MODULATE);
1236               osgTexEnv->setColor(osg::Vec4(r,g,b,a));
1237               break;
1238           case(PFTE_DECAL) :
1239               osgTexEnv->setMode(osg::TexEnv::DECAL);
1240               osgTexEnv->setColor(osg::Vec4(r,g,b,a));
1241               break;
1242           case(PFTE_BLEND) :
1243               osgTexEnv->setMode(osg::TexEnv::BLEND);
1244               osgTexEnv->setColor(osg::Vec4(r,g,b,a));
1245               break;
1246           case(PFTE_REPLACE) :
1247               osgTexEnv->setMode(osg::TexEnv::REPLACE);
1248               osgTexEnv->setColor(osg::Vec4(r,g,b,a));
1249               break;
1250           case(PFTE_ADD) :
1251               osgTexEnv->setMode(osg::TexEnv::ADD);
1252               osgTexEnv->setColor(osg::Vec4(r,g,b,a));
1253               break;
1254           default:
1255               OSG_WARN << "TexEnv Mode "<<mode<<" not currently supported by the OSG."<<std::endl;
1256               break;
1257       }
1258       osgStateSet->setTextureAttribute(0,osgTexEnv);
1259     }
1260 
1261     pfTexGen* texgen = (pfTexGen*)geostate->getAttr(PFSTATE_TEXGEN);
1262 
1263     if (texgen)
1264     {
1265         osg::TexGen* osgTexGen = new osg::TexGen();
1266         int mode = texgen->getMode(PF_S);
1267 
1268         // should this follow setPlane block be within the following switch?
1269         float x, y, z, d;
1270         texgen->getPlane(PF_S, &x, &y, &z, &d);
1271         osgTexGen->setPlane(osg::TexGen::S, osg::Vec4(x,y,z,d));
1272         texgen->getPlane(PF_T, &x, &y, &z, &d);
1273         osgTexGen->setPlane(osg::TexGen::T, osg::Vec4(x,y,z,d));
1274 
1275         switch(mode)
1276         {
1277             case(PFTG_OBJECT_LINEAR) :
1278                 osgTexGen->setMode(osg::TexGen::OBJECT_LINEAR);
1279                 osgStateSet->setTextureAttribute(0,osgTexGen);
1280                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
1281                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
1282                 break;
1283             case(PFTG_EYE_LINEAR_IDENT) :
1284                 OSG_WARN << "TexGen Mode PFTG_EYE_LINEAR_IDENT not currently supported by the OSG,"<<std::endl;
1285                 OSG_WARN << "       assuming osg::TexGen::EYE_LINEAR."<<std::endl;
1286             case(PFTG_EYE_LINEAR) :
1287                 osgTexGen->setMode(osg::TexGen::EYE_LINEAR);
1288                 osgStateSet->setTextureAttribute(0,osgTexGen);
1289                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
1290                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
1291                 break;
1292             case(PFTG_SPHERE_MAP) :
1293                 osgTexGen->setMode(osg::TexGen::SPHERE_MAP);
1294                 osgStateSet->setTextureAttribute(0,osgTexGen);
1295                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
1296                 osgStateSet->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
1297                 break;
1298             case(PFTG_OFF) :
1299                 osgStateSet->setAssociatedTextureModes(0,osgTexGen,osg::StateAttribute::OFF);
1300                 break;
1301             case(PFTG_OBJECT_DISTANCE_TO_LINE) :
1302                 OSG_WARN << "TexGen Mode PFTG_OBJECT_DISTANCE_TO_LINE not currently supported by the OSG."<<std::endl;
1303                 osgStateSet->setAssociatedTextureModes(0,osgTexGen,osg::StateAttribute::OFF);
1304                 break;
1305             case(PFTG_EYE_DISTANCE_TO_LINE) :
1306                 OSG_WARN << "TexGen Mode PFTG_EYE_DISTANCE_TO_LINE not currently supported by the OSG."<<std::endl;
1307                 osgStateSet->setAssociatedTextureModes(0,osgTexGen,osg::StateAttribute::OFF);
1308                 break;
1309             default:
1310                 OSG_WARN << "TexGen Mode "<<mode<<" not currently supported by the OSG."<<std::endl;
1311                 osgStateSet->setAssociatedTextureModes(0,osgTexGen,osg::StateAttribute::OFF);
1312                 break;
1313         }
1314     }
1315 
1316     pfMatrix* texmat = (pfMatrix*)geostate->getAttr(PFSTATE_TEXMAT);
1317     if (texmat)
1318     {
1319         osg::Matrix osgMatrix((*texmat)[0][0],(*texmat)[0][1],(*texmat)[0][2],(*texmat)[0][3],
1320             (*texmat)[1][0],(*texmat)[1][1],(*texmat)[1][2],(*texmat)[1][3],
1321             (*texmat)[2][0],(*texmat)[2][1],(*texmat)[2][2],(*texmat)[2][3],
1322             (*texmat)[3][0],(*texmat)[3][1],(*texmat)[3][2],(*texmat)[3][3]);
1323 
1324         osg::TexMat* osgTexMat = new osg::TexMat();
1325         osgTexMat->setMatrix(osgMatrix);
1326         osgStateSet->setTextureAttribute(0,osgTexMat);
1327     }
1328 
1329     return osgStateSet;
1330 }
1331 
1332 
visitMaterial(osg::StateSet * osgStateSet,pfMaterial * front_mat,pfMaterial * back_mat)1333 osg::Material* ConvertFromPerformer::visitMaterial(osg::StateSet* osgStateSet,pfMaterial* front_mat,pfMaterial* back_mat)
1334 {
1335     if (front_mat==NULL && back_mat==NULL) return NULL;
1336 
1337     osg::Material* osgMaterial = new osg::Material;
1338     if (osgStateSet) osgStateSet->setAttribute(osgMaterial);
1339 
1340     pfMaterial* material = NULL;
1341     if (front_mat==back_mat) material = front_mat;
1342     else if (back_mat==NULL) material = front_mat;
1343     else if (front_mat==NULL) material = back_mat;
1344 
1345     if (material)                // single materials for front and back.
1346     {
1347 
1348         int colorMode = material->getColorMode(material->getSide());
1349 
1350         switch(colorMode)
1351         {
1352             case(PFMTL_CMODE_AMBIENT_AND_DIFFUSE): osgMaterial->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); break;
1353             case(PFMTL_CMODE_AMBIENT): osgMaterial->setColorMode(osg::Material::AMBIENT); break;
1354             case(PFMTL_CMODE_DIFFUSE): osgMaterial->setColorMode(osg::Material::DIFFUSE); break;
1355             case(PFMTL_CMODE_EMISSION): osgMaterial->setColorMode(osg::Material::EMISSION); break;
1356             case(PFMTL_CMODE_SPECULAR): osgMaterial->setColorMode(osg::Material::SPECULAR); break;
1357             case(PFMTL_CMODE_OFF): osgMaterial->setColorMode(osg::Material::OFF); break;
1358         }
1359 
1360         osgMaterial->setShininess(osg::Material::FRONT_AND_BACK,material->getShininess());
1361 
1362         float a = material->getAlpha();
1363         float r,g,b;
1364 
1365         material->getColor(PFMTL_AMBIENT,&r,&g,&b);
1366         osgMaterial->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(r,g,b,a));
1367 
1368         material->getColor(PFMTL_DIFFUSE,&r,&g,&b);
1369         osgMaterial->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(r,g,b,a));
1370 
1371         material->getColor(PFMTL_EMISSION,&r,&g,&b);
1372         osgMaterial->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(r,g,b,a));
1373 
1374         material->getColor(PFMTL_SPECULAR,&r,&g,&b);
1375         osgMaterial->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(r,g,b,a));
1376     }
1377     else                         // separate materials for front and back.
1378     {
1379 
1380         int colorMode = front_mat->getColorMode(front_mat->getSide());
1381 
1382         switch(colorMode)
1383         {
1384             case(PFMTL_CMODE_AMBIENT_AND_DIFFUSE): osgMaterial->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); break;
1385             case(PFMTL_CMODE_AMBIENT): osgMaterial->setColorMode(osg::Material::AMBIENT); break;
1386             case(PFMTL_CMODE_DIFFUSE): osgMaterial->setColorMode(osg::Material::DIFFUSE); break;
1387             case(PFMTL_CMODE_EMISSION): osgMaterial->setColorMode(osg::Material::EMISSION); break;
1388             case(PFMTL_CMODE_SPECULAR): osgMaterial->setColorMode(osg::Material::SPECULAR); break;
1389             case(PFMTL_CMODE_OFF): osgMaterial->setColorMode(osg::Material::OFF); break;
1390         }
1391 
1392         float a;
1393         float r,g,b;
1394 
1395         // front material
1396         osgMaterial->setShininess(osg::Material::FRONT,front_mat->getShininess());
1397 
1398         a = front_mat->getAlpha();
1399 
1400         front_mat->getColor(PFMTL_AMBIENT,&r,&g,&b);
1401         osgMaterial->setAmbient(osg::Material::FRONT,osg::Vec4(r,g,b,a));
1402 
1403         front_mat->getColor(PFMTL_DIFFUSE,&r,&g,&b);
1404         osgMaterial->setDiffuse(osg::Material::FRONT,osg::Vec4(r,g,b,a));
1405 
1406         front_mat->getColor(PFMTL_EMISSION,&r,&g,&b);
1407         osgMaterial->setEmission(osg::Material::FRONT,osg::Vec4(r,g,b,a));
1408 
1409         front_mat->getColor(PFMTL_SPECULAR,&r,&g,&b);
1410         osgMaterial->setSpecular(osg::Material::FRONT,osg::Vec4(r,g,b,a));
1411 
1412         // back material
1413         osgMaterial->setShininess(osg::Material::BACK,back_mat->getShininess());
1414 
1415         a = back_mat->getAlpha();
1416 
1417         back_mat->getColor(PFMTL_AMBIENT,&r,&g,&b);
1418         osgMaterial->setAmbient(osg::Material::BACK,osg::Vec4(r,g,b,a));
1419 
1420         back_mat->getColor(PFMTL_DIFFUSE,&r,&g,&b);
1421         osgMaterial->setDiffuse(osg::Material::BACK,osg::Vec4(r,g,b,a));
1422 
1423         back_mat->getColor(PFMTL_EMISSION,&r,&g,&b);
1424         osgMaterial->setEmission(osg::Material::BACK,osg::Vec4(r,g,b,a));
1425 
1426         back_mat->getColor(PFMTL_SPECULAR,&r,&g,&b);
1427         osgMaterial->setSpecular(osg::Material::BACK,osg::Vec4(r,g,b,a));
1428 
1429     }
1430 
1431     return osgMaterial;
1432 }
1433 
1434 
getTexfilter(int filter,int pftype)1435 static osg::Texture2D::FilterMode getTexfilter(int filter, int pftype)
1436 {
1437     if (filter == PFTEX_MINFILTER)
1438     {
1439 
1440         if (pftype & PFTEX_LINEAR)
1441             return osg::Texture2D::NEAREST_MIPMAP_LINEAR;
1442         else if (pftype & PFTEX_BILINEAR)
1443             return osg::Texture2D::LINEAR_MIPMAP_NEAREST;
1444         else if (pftype & PFTEX_TRILINEAR)
1445             return osg::Texture2D::LINEAR_MIPMAP_LINEAR;
1446 
1447         return osg::Texture2D::NEAREST_MIPMAP_LINEAR;
1448 
1449     }
1450     else
1451     {
1452         // MAGFILTER
1453 
1454         // not quite sure what is supposed to be interpret the Peformer
1455         // filter modes here so will simple go with OpenGL default.
1456 
1457         return osg::Texture2D::LINEAR;
1458     }
1459 }
1460 
1461 
visitTexture(osg::StateSet * osgStateSet,pfTexture * tex)1462 osg::Texture2D* ConvertFromPerformer::visitTexture(osg::StateSet* osgStateSet,pfTexture* tex)
1463 {
1464     if (tex==NULL) return NULL;
1465 
1466     osg::Texture2D* osgTexture = dynamic_cast<osg::Texture2D*>(getOsgObject(tex));
1467     if (osgTexture) {
1468         if (osgStateSet) osgStateSet->setTextureAttribute(0,osgTexture);
1469         return osgTexture;
1470     }
1471 
1472     osgTexture = new osg::Texture2D;
1473     registerPfObjectForOsgObject(tex, osgTexture);
1474 
1475     if (osgStateSet) osgStateSet->setTextureAttribute(0,osgTexture);
1476 
1477     int repeat_r = tex->getRepeat(PFTEX_WRAP_R);
1478     int repeat_s = tex->getRepeat(PFTEX_WRAP_S);
1479     int repeat_t = tex->getRepeat(PFTEX_WRAP_T);
1480 
1481     if (repeat_r==PFTEX_CLAMP)
1482         osgTexture->setWrap(osg::Texture2D::WRAP_R,osg::Texture2D::CLAMP);
1483     else
1484         osgTexture->setWrap(osg::Texture2D::WRAP_R,osg::Texture2D::REPEAT);
1485 
1486     if (repeat_s==PFTEX_CLAMP)
1487         osgTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP);
1488     else
1489         osgTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
1490 
1491     if (repeat_t==PFTEX_CLAMP)
1492         osgTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP);
1493     else
1494         osgTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
1495 
1496     // filter
1497 #if 1
1498     osgTexture->setFilter(osg::Texture2D::MIN_FILTER,
1499                           getTexfilter(PFTEX_MINFILTER,
1500                                        tex->getFilter(PFTEX_MINFILTER)));
1501     osgTexture->setFilter(osg::Texture2D::MAG_FILTER,
1502                           getTexfilter(PFTEX_MAGFILTER,
1503                                        tex->getFilter(PFTEX_MAGFILTER)));
1504 #endif
1505 
1506     // image
1507     std::string texName = tex->getName();
1508 
1509     if (_saveImagesAsRGB) {
1510         std::string strippedName = osgDB::getStrippedName(texName);
1511 
1512         pfList* imgList = tex->getList();
1513         if (imgList) {
1514             // save image list
1515             char buf[8];
1516             for (int i = 0; i < imgList->getNum(); i++) {
1517                 pfTexture* t = (pfTexture*) imgList->get(i);
1518                 if (t) {
1519                     snprintf(buf, sizeof(buf)-1, "_%04d", i);
1520                     texName = _saveImageDirectory+strippedName+buf+".rgb";
1521                     t->saveFile(texName.c_str());
1522                 }
1523             }
1524         }
1525         else {
1526             // save single image
1527             texName = _saveImageDirectory+strippedName+".rgb";
1528             tex->saveFile(texName.c_str());
1529         }
1530     }
1531 
1532     if (!_saveAbsoluteImagePath) texName = osgDB::getSimpleFileName(texName);
1533 
1534     int s=0;
1535     int t=0;
1536     int r=0;
1537     int comp=0;
1538     unsigned int* imageData = NULL;
1539 
1540     tex->getImage(&imageData,&comp,&s,&t,&r);
1541 
1542     int internalFormat = comp;
1543 
1544     unsigned int pixelFormat =
1545         comp == 1 ? GL_LUMINANCE :
1546         comp == 2 ? GL_LUMINANCE_ALPHA :
1547         comp == 3 ? GL_RGB :
1548         comp == 4 ? GL_RGBA : (GLenum)-1;
1549 
1550     unsigned int dataType = GL_UNSIGNED_BYTE;
1551 
1552     // copy image data
1553     int size = s * t * r * comp;
1554     unsigned char* data = (unsigned char*) malloc(size);
1555     memcpy(data, imageData, size);
1556 
1557     osg::Image* image = new osg::Image;
1558     image->setFileName(texName.c_str());
1559     image->setImage(s,t,r,
1560                     internalFormat,
1561                     pixelFormat,
1562                     dataType,data,
1563                     osg::Image::USE_MALLOC_FREE);
1564 
1565     osgTexture->setImage(image);
1566 
1567     return osgTexture;
1568 }
1569