1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2009 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
43 #include "OSGColladaGeometry.h"
45 #if defined(OSG_WITH_COLLADA) || defined(OSG_DO_DOC)
47 #include "OSGColladaLog.h"
48 #include "OSGColladaGlobal.h"
49 #include "OSGColladaInstanceGeometry.h"
50 #include "OSGColladaInstanceEffect.h"
51 #include "OSGColladaNode.h"
52 #include "OSGColladaSource.h"
53 #include "OSGColladaExtraHandler.h"
54 #include "OSGColladaHandlerFactory.h"
57 #include "OSGTypedGeoVectorProperty.h"
58 #include "OSGTypedGeoIntegralProperty.h"
59 #include "OSGNameAttachment.h"
60 #include "OSGPrimeMaterial.h"
62 #include <dom/domGeometry.h>
63 #include <dom/domMesh.h>
64 #include <dom/domSource.h>
65 #include <dom/domLines.h>
66 #include <dom/domLinestrips.h>
67 #include <dom/domPolygons.h>
68 #include <dom/domPolylist.h>
69 #include <dom/domTriangles.h>
70 #include <dom/domTrifans.h>
71 #include <dom/domTristrips.h>
75 ColladaInstInfoTransitPtr
76 ColladaGeometry::ColladaGeometryInstInfo::create(
77 ColladaNode
*colInstParent
, ColladaInstanceGeometry
*colInst
,
80 OSG_ASSERT(colInstParent
!= NULL
);
81 OSG_ASSERT(colInst
!= NULL
);
83 return ColladaInstInfoTransitPtr(
84 new ColladaGeometryInstInfo(colInstParent
, colInst
, parentN
));
88 ColladaGeometry::ColladaGeometryInstInfo::process(void)
90 Node
*geoInstN
= dynamic_cast<Node
*>(
91 getColInst()->getTargetElem()->createInstance(this));
93 getParentNode()->addChild(geoInstN
);
96 ColladaGeometry::ColladaGeometryInstInfo::ColladaGeometryInstInfo(
97 ColladaNode
*colInstParent
, ColladaInstanceGeometry
*colInst
,
100 : Inherited(colInstParent
, colInst
)
101 , _parentN (parentN
)
105 ColladaGeometry::ColladaGeometryInstInfo::~ColladaGeometryInstInfo(void)
109 /*---------------------------------------------------------------------------*/
111 ColladaGeometry::PropInfo::PropInfo(void)
118 ColladaGeometry::PropInfo::PropInfo(const PropInfo
&source
)
119 : _semantic(source
._semantic
)
121 , _prop (source
._prop
)
125 /*---------------------------------------------------------------------------*/
127 ColladaElementRegistrationHelper
ColladaGeometry::_regHelper(
128 &ColladaGeometry::create
, "geometry");
130 ColladaElementTransitPtr
131 ColladaGeometry::create(daeElement
*elem
, ColladaGlobal
*global
)
133 return ColladaElementTransitPtr(new ColladaGeometry(elem
, global
));
137 ColladaGeometry::setDoubleSided(bool value
)
139 _doubleSided
= value
;
143 ColladaGeometry::read(ColladaElement
*colElemParent
)
145 domGeometryRef geometry
= getDOMElementAs
<domGeometry
>();
146 domMeshRef mesh
= geometry
->getMesh();
148 OSG_COLLADA_LOG(("ColladaGeometry::read id [%s]\n",
153 SWARNING
<< "ColladaGeometry::read: No <mesh>" << std::endl
;
159 const domExtra_Array
&extras
= geometry
->getExtra_array();
161 if(extras
.getCount() != 0 && _extraHandlers
.size() != 0)
163 for(UInt32 i
= 0; i
< extras
.getCount(); ++i
)
165 ExtraHandlerStoreIt ehIt
= _extraHandlers
.begin();
166 ExtraHandlerStoreConstIt ehEnd
= _extraHandlers
.end ();
168 for(; ehIt
!= ehEnd
; ++ehIt
)
170 (*ehIt
)->readGeometryExtraElements(this, extras
[i
]);
178 ColladaGeometry::createInstance(ColladaInstInfo
*colInstInfo
)
180 typedef ColladaInstanceGeometry::MaterialMap ColMaterialMap
;
181 typedef ColladaInstanceGeometry::MaterialMapConstIt ColMaterialMapConstIt
;
183 domGeometryRef geometry
= getDOMElementAs
<domGeometry
>();
184 NodeUnrecPtr groupN
= makeCoredNode
<Group
>();
186 OSG_COLLADA_LOG(("ColladaGeometry::createInstance id [%s]\n",
189 if(getGlobal()->getOptions()->getCreateNameAttachments() == true &&
190 geometry
->getName() != NULL
)
192 setName(groupN
, geometry
->getName());
195 ColladaInstanceGeometryRefPtr colInstGeo
=
196 dynamic_cast<ColladaInstanceGeometry
*>(colInstInfo
->getColInst());
197 const ColMaterialMap
&matMap
=
198 colInstGeo
->getMaterialMap();
200 // iterate over all parts of geometry
201 GeoStoreIt gsIt
= _geoStore
.begin();
202 GeoStoreIt gsEnd
= _geoStore
.end ();
204 for(; gsIt
!= gsEnd
; ++gsIt
)
206 OSG_ASSERT(gsIt
->_propStore
.size() == gsIt
->_indexStore
.size());
208 // find the material associated with the geometry's material symbol
209 ColMaterialMapConstIt mmIt
= matMap
.find(gsIt
->_matSymbol
);
210 std::string matTarget
;
212 if(mmIt
!= matMap
.end())
214 matTarget
= mmIt
->second
->getTarget();
217 // check if the geometry was already used with that material
219 GeometryUnrecPtr geo
= NULL
;
220 InstanceMapConstIt instIt
= gsIt
->_instMap
.find(matTarget
);
222 if(instIt
!= gsIt
->_instMap
.end())
226 geo
= dynamic_pointer_cast
<Geometry
>(
227 getInstStore()[instIt
->second
]);
229 getGlobal()->getStatCollector()->getElem(
230 ColladaGlobal::statNGeometryUsed
)->inc();
234 // create new geometry
236 geo
= Geometry::create();
238 getGlobal()->getStatCollector()->getElem(
239 ColladaGlobal::statNGeometryCreated
)->inc();
241 geo
->setLengths(gsIt
->_lengths
);
242 geo
->setTypes (gsIt
->_types
);
244 handleBindMaterial(*gsIt
, geo
, colInstGeo
);
246 // record the instantiation of the geometry with the
247 // material for reuse
248 gsIt
->_instMap
.insert(
249 InstanceMap::value_type(matTarget
, UInt32(getInstStore().size())));
251 editInstStore().push_back(geo
);
254 NodeUnrecPtr geoN
= makeNodeFor(geo
);
256 groupN
->addChild(geoN
);
259 // if there is only one child remove the group
260 if(groupN
->getNChildren() == 1)
262 Node
*geoN
= groupN
->getChild(0);
264 groupN
->setCore(geoN
->getCore());
265 geoN
->setCore(NULL
);
267 groupN
->clearChildren();
270 // store the generated group node
271 editInstStore().push_back(groupN
);
276 ColladaGeometry::ColladaGeometry(daeElement
*elem
, ColladaGlobal
*global
)
277 : Inherited (elem
, global
)
280 , _doubleSided (false)
283 ColladaHandlerFactory::the()->createExtraHandlers(_extraHandlers
);
286 ColladaGeometry::~ColladaGeometry(void)
288 _extraHandlers
.clear();
292 ColladaGeometry::readMesh(domMesh
*mesh
)
294 readSources(mesh
->getSource_array());
296 const domLines_Array
&linesArray
= mesh
->getLines_array();
298 for(UInt32 i
= 0; i
< linesArray
.getCount(); ++i
)
300 readLines(mesh
, linesArray
[i
]);
303 const domLinestrips_Array
&lineStripsArray
= mesh
->getLinestrips_array();
305 for(UInt32 i
= 0; i
< lineStripsArray
.getCount(); ++i
)
307 readLineStrips(mesh
, lineStripsArray
[i
]);
310 const domPolygons_Array
&polygonsArray
= mesh
->getPolygons_array();
312 for(UInt32 i
= 0; i
< polygonsArray
.getCount(); ++i
)
314 readPolygons(mesh
, polygonsArray
[i
]);
316 const domPolylist_Array
&polyListArray
= mesh
->getPolylist_array();
318 for(UInt32 i
= 0; i
< polyListArray
.getCount(); ++i
)
320 readPolyList(mesh
, polyListArray
[i
]);
323 const domTriangles_Array
&triArray
= mesh
->getTriangles_array();
325 for(UInt32 i
= 0; i
< triArray
.getCount(); ++i
)
327 readTriangles(mesh
, triArray
[i
]);
330 const domTrifans_Array
&triFansArray
= mesh
->getTrifans_array();
332 for(UInt32 i
= 0; i
< triFansArray
.getCount(); ++i
)
334 readTriFans(mesh
, triFansArray
[i
]);
337 const domTristrips_Array
&triStripsArray
= mesh
->getTristrips_array();
339 for(UInt32 i
= 0; i
< triStripsArray
.getCount(); ++i
)
341 readTriStrips(mesh
, triStripsArray
[i
]);
346 ColladaGeometry::readSources(const domSource_Array
&sources
)
348 for(UInt32 i
= 0; i
< sources
.getCount(); ++i
)
350 ColladaSourceRefPtr colSource
=
351 getUserDataAs
<ColladaSource
>(sources
[i
]);
353 if(colSource
== NULL
)
355 colSource
= dynamic_pointer_cast
<ColladaSource
>(
356 ColladaElementFactory::the()->create(sources
[i
], getGlobal()));
358 colSource
->read(this);
362 SourceMap::value_type(sources
[i
]->getId(), colSource
));
367 ColladaGeometry::readLines(domMesh
*mesh
, domLines
*lines
)
369 OSG_COLLADA_LOG(("ColladaGeometry::readLines\n"));
371 const domInputLocal_Array
&vertInputs
=
372 mesh
->getVertices()->getInput_array();
373 const domInputLocalOffset_Array
&inputs
=
374 lines
->getInput_array();
377 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
378 lines
->getMaterial(), idxStore
);
380 const domListOfUInts
&pList
= lines
->getP()->getValue();
384 for(UInt32 i
= 0; i
< pList
.getCount(); ++i
)
386 idxStore
[currIdx
]->push_back(pList
[i
]);
390 if(currIdx
== idxStore
.size())
397 OSG_COLLADA_LOG(("ColladaGeometry::readLines: material symbol [%s] "
399 (lines
->getMaterial() != NULL
? lines
->getMaterial() : ""),
402 _geoStore
[geoIdx
]._types
->push_back(GL_LINES
);
403 _geoStore
[geoIdx
]._lengths
->push_back(length
);
405 // remove empty geometry
408 SWARNING
<< "ColladaGeometry::readLines: Empty <lines> with material ["
409 << (lines
->getMaterial() != NULL
? lines
->getMaterial() : "")
410 << "]." << std::endl
;
412 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
417 ColladaGeometry::readLineStrips(domMesh
*mesh
, domLinestrips
*lineStrips
)
419 OSG_COLLADA_LOG(("ColladaGeometry::readLineStrips\n"));
421 const domInputLocal_Array
&vertInputs
=
422 mesh
->getVertices()->getInput_array();
423 const domInputLocalOffset_Array
&inputs
=
424 lineStrips
->getInput_array();
427 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
428 lineStrips
->getMaterial(), idxStore
);
430 const domP_Array
&pArray
= lineStrips
->getP_array();
435 for(UInt32 i
= 0; i
< pArray
.getCount(); ++i
)
437 const domListOfUInts
&pList
= pArray
[i
]->getValue();
439 for(UInt32 j
= 0; j
< pList
.getCount(); ++j
)
441 idxStore
[currIdx
]->push_back(pList
[j
]);
445 if(currIdx
== idxStore
.size())
452 // only add non-empty line strip
455 _geoStore
[geoIdx
]._types
->push_back(GL_LINE_STRIP
);
456 _geoStore
[geoIdx
]._lengths
->push_back(length
);
463 OSG_COLLADA_LOG(("ColladaGeometry::readLineStrips: material symbol [%s] "
464 "vertices [%d] strips [%" PRIUSize
"]\n",
465 (lineStrips
->getMaterial() != NULL
?
466 lineStrips
->getMaterial() : ""),
468 _geoStore
[geoIdx
]._lengths
->size()));
470 // remove empty geometry
473 SWARNING
<< "ColladaGeometry::readLineStrips: Empty <linestrips> "
475 << (lineStrips
->getMaterial() != NULL
?
476 lineStrips
->getMaterial() : "")
477 << "]." << std::endl
;
479 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
484 ColladaGeometry::readPolygons(domMesh
*mesh
, domPolygons
*polygons
)
486 OSG_COLLADA_LOG(("ColladaGeometry::readPolygons\n"));
488 const domInputLocal_Array
&vertInputs
=
489 mesh
->getVertices()->getInput_array();
490 const domInputLocalOffset_Array
&inputs
=
491 polygons
->getInput_array();
494 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
495 polygons
->getMaterial(), idxStore
);
497 const domP_Array
&pArray
= polygons
->getP_array();
502 for(UInt32 i
= 0; i
< pArray
.getCount(); ++i
)
504 const domListOfUInts
&pList
= pArray
[i
]->getValue();
506 for(UInt32 j
= 0; j
< pList
.getCount(); ++j
)
508 idxStore
[currIdx
]->push_back(pList
[j
]);
512 if(currIdx
== idxStore
.size())
519 // only add non-empty polygon
522 _geoStore
[geoIdx
]._types
->push_back(GL_POLYGON
);
523 _geoStore
[geoIdx
]._lengths
->push_back(length
);
530 const domPolygons::domPh_Array
&phArray
= polygons
->getPh_array();
534 for(UInt32 i
= 0; i
< phArray
.getCount(); ++i
)
536 // we only get the <p> elements (polygons) and skip the <h> elements
539 const domListOfUInts
&pList
= phArray
[i
]->getP()->getValue();
541 for(UInt32 j
= 0; j
< pList
.getCount(); ++j
)
543 idxStore
[currIdx
]->push_back(pList
[j
]);
547 if(currIdx
== idxStore
.size())
554 // only add non-empty polygon
557 _geoStore
[geoIdx
]._types
->push_back(GL_POLYGON
);
558 _geoStore
[geoIdx
]._lengths
->push_back(length
);
564 if(phArray
[i
]->getH_array().getCount() > 0)
566 SWARNING
<< "ColladaGeometry::readPolygon: Ignoring ["
567 << phArray
[i
]->getH_array().getCount()
568 << "] holes in polygon." << std::endl
;
572 OSG_COLLADA_LOG(("ColladaGeometry::readPolygons: material symbol [%s] "
573 "vertices [%d] polygons [%" PRIUSize
"]\n",
574 (polygons
->getMaterial() != NULL
?
575 polygons
->getMaterial() : ""), verts
,
576 _geoStore
[geoIdx
]._lengths
->size()));
578 // remove empty geometry
581 SWARNING
<< "ColladaGeometry::readPolygons: Empty <polygons> "
583 << (polygons
->getMaterial() != NULL
?
584 polygons
->getMaterial() : "")
585 << "]." << std::endl
;
587 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
592 ColladaGeometry::readPolyList(domMesh
*mesh
, domPolylist
*polyList
)
594 OSG_COLLADA_LOG(("ColladaGeometry::readPolyList\n"));
596 const domInputLocal_Array
&vertInputs
=
597 mesh
->getVertices()->getInput_array();
598 const domInputLocalOffset_Array
&inputs
=
599 polyList
->getInput_array();
601 if(polyList
->getVcount() == NULL
)
603 SWARNING
<< "ColladaGeometry::readPolyList: Empty <vcount> "
610 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
611 polyList
->getMaterial(), idxStore
);
613 const domListOfUInts
&pList
= polyList
->getP ()->getValue();
614 const domListOfUInts
&vList
= polyList
->getVcount()->getValue();
618 bool useQuads
= true;
620 std::vector
<bool> vIdxValid
;
622 vIdxValid
.resize(idxStore
.size(), true);
624 // check if all polys are quads
625 for(UInt32 i
= 0; i
< vList
.getCount(); ++i
)
634 OSG_COLLADA_LOG(("ColladaGeometry::readPolyList: useQuads [%d]\n",
639 for(UInt32 i
= 0; i
< 4 * vList
.getCount(); ++i
)
641 for(UInt32 k
= 0; k
< idxStore
.size(); ++k
)
643 idxStore
[k
]->push_back(pList
[currIdx
]);
645 if(pList
[currIdx
] == domUint(-1))
647 vIdxValid
[k
] = false;
654 // only add non-empty quads
655 if(vList
.getCount() > 0)
657 _geoStore
[geoIdx
]._types
->push_back(GL_QUADS
);
658 _geoStore
[geoIdx
]._lengths
->push_back(4 * vList
.getCount());
661 verts
+= 4 * UInt32(vList
.getCount());
662 prims
+= UInt32(vList
.getCount());
666 for(UInt32 i
= 0; i
< vList
.getCount(); ++i
)
668 for(UInt32 j
= 0; j
< vList
[i
]; ++j
)
670 for(UInt32 k
= 0; k
< idxStore
.size(); ++k
)
672 idxStore
[k
]->push_back(pList
[currIdx
]);
674 if(pList
[currIdx
] == domUint(-1))
676 vIdxValid
[k
] = false;
683 // only add non-empty polygons
686 _geoStore
[geoIdx
]._types
->push_back(GL_POLYGON
);
687 _geoStore
[geoIdx
]._lengths
->push_back(vList
[i
] );
695 this->validateIndices(geoIdx
, vIdxValid
, idxStore
);
697 OSG_COLLADA_LOG(("ColladaGeometry::readPolyList: material symbol [%s] "
698 "vertices [%d] %s [%d]\n",
699 (polyList
->getMaterial() != NULL
?
700 polyList
->getMaterial() : ""),
702 (useQuads
== true ? "quads" : "polygons"), prims
));
704 // remove empty geometry
707 SWARNING
<< "ColladaGeometry::readPolyList: Empty <polylist> "
709 << (polyList
->getMaterial() != NULL
?
710 polyList
->getMaterial() : "")
711 << "]." << std::endl
;
713 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
717 void ColladaGeometry::validateIndices( UInt32 geoIdx
,
718 const std::vector
<bool> &vIdxValid
,
719 const IndexStore idxStore
)
721 if(getGlobal()->getOptions()->getTryMergeInvalidIndices() == false)
723 for(SizeT i
= 0; i
< vIdxValid
.size(); ++i
)
725 if(vIdxValid
[i
] == false)
726 idxStore
[i
]->clear();
733 typedef std::pair
<GeoIntegralProperty
*,
734 GeoIntegralPropertyUnrecPtr
*> IndexPair
;
736 std::vector
<IndexPair
> vIdxPairs
;
738 bool hasInvalidIndices
= false;
739 bool bMergable
= true;
741 for(SizeT i
= 0; i
< vIdxValid
.size(); ++i
)
743 if(vIdxValid
[i
] == false)
748 static_cast<GeoIntegralPropertyUnrecPtr
*>(NULL
)));
750 if(vIdxPairs
[0].first
->size() != idxStore
[i
]->size())
755 hasInvalidIndices
= true;
759 if(hasInvalidIndices
== false)
762 if(bMergable
== false)
764 for(SizeT i
= 0; i
< vIdxValid
.size(); ++i
)
766 if(vIdxValid
[i
] == false)
767 idxStore
[i
]->clear();
774 for(SizeT i
= 0; i
< vIdxPairs
.size(); ++i
)
776 for(SizeT j
= 0; j
< _geoStore
[geoIdx
]._indexStore
.size(); ++j
)
778 if(vIdxPairs
[i
].first
== _geoStore
[geoIdx
]._indexStore
[j
])
780 vIdxPairs
[i
].second
= &_geoStore
[geoIdx
]._indexStore
[j
];
786 GeoUInt32PropertyUnrecPtr pMergedIdx
= GeoUInt32Property::create();
788 pMergedIdx
->resize(vIdxPairs
[0].first
->size());
790 bool bMergeSucceeded
= true;
792 for(SizeT i
= 0; i
< pMergedIdx
->size(); ++i
)
794 UInt32 iVal
= UInt32(domUint(-1));
796 for(SizeT j
= 0; j
< vIdxPairs
.size(); ++j
)
798 if(vIdxPairs
[j
].first
->getValue(i
) != UInt32(-1))
800 if(iVal
== UInt32(-1))
802 iVal
= vIdxPairs
[j
].first
->getValue(i
);
806 if(iVal
!= vIdxPairs
[j
].first
->getValue(i
))
808 bMergeSucceeded
= false;
814 if(iVal
== UInt32(-1))
816 bMergeSucceeded
= false;
820 pMergedIdx
->setValue(iVal
, i
);
823 if(bMergeSucceeded
== false)
827 if(bMergeSucceeded
== true)
829 for(SizeT i
= 0; i
< vIdxPairs
.size(); ++i
)
831 (*(vIdxPairs
[i
].second
)) = pMergedIdx
;
837 for(SizeT i
= 0; i
< vIdxValid
.size(); ++i
)
839 if(vIdxValid
[i
] == false)
840 idxStore
[i
]->clear();
845 ColladaGeometry::readTriangles(domMesh
*mesh
, domTriangles
*triangles
)
847 OSG_COLLADA_LOG(("ColladaGeometry::readTriangles\n"));
849 const domInputLocal_Array
&vertInputs
=
850 mesh
->getVertices()->getInput_array();
851 const domInputLocalOffset_Array
&inputs
=
852 triangles
->getInput_array();
855 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
856 triangles
->getMaterial(), idxStore
);
858 const domListOfUInts
&pList
= triangles
->getP()->getValue();
862 std::vector
<bool> vIdxValid
;
864 vIdxValid
.resize(idxStore
.size(), true);
866 for(UInt32 i
= 0; i
< pList
.getCount(); ++i
)
868 domUint uiIdx
= pList
[i
];
870 if(uiIdx
== domUint(-1))
872 vIdxValid
[currIdx
] = false;
875 idxStore
[currIdx
]->push_back(uiIdx
);
879 if(currIdx
== idxStore
.size())
886 this->validateIndices(geoIdx
, vIdxValid
, idxStore
);
888 _geoStore
[geoIdx
]._types
->push_back(GL_TRIANGLES
);
889 _geoStore
[geoIdx
]._lengths
->push_back(length
);
891 OSG_COLLADA_LOG(("ColladaGeometry::readTriangles: material symbol [%s] "
892 "vertices [%d] triangles [%d]\n",
893 (triangles
->getMaterial() != NULL
?
894 triangles
->getMaterial() : ""),
899 SWARNING
<< "ColladaGeometry::readTriangles: Empty <triangles> "
901 << (triangles
->getMaterial() != NULL
?
902 triangles
->getMaterial() : "")
903 << "]." << std::endl
;
905 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
910 ColladaGeometry::readTriFans(domMesh
*mesh
, domTrifans
*triFans
)
912 OSG_COLLADA_LOG(("ColladaGeometry::readTriFans\n"));
914 const domInputLocal_Array
&vertInputs
=
915 mesh
->getVertices()->getInput_array();
916 const domInputLocalOffset_Array
&inputs
=
917 triFans
->getInput_array();
920 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
921 triFans
->getMaterial(), idxStore
);
923 const domP_Array
&pArray
= triFans
->getP_array();
928 for(UInt32 i
= 0; i
< pArray
.getCount(); ++i
)
930 const domListOfUInts
&pList
= pArray
[i
]->getValue();
932 for(UInt32 j
= 0; j
< pList
.getCount(); ++j
)
934 idxStore
[currIdx
]->push_back(pList
[j
]);
938 if(currIdx
== idxStore
.size())
945 // only add non-empty tri fans
948 _geoStore
[geoIdx
]._types
->push_back(GL_TRIANGLE_FAN
);
949 _geoStore
[geoIdx
]._lengths
->push_back(length
);
956 OSG_COLLADA_LOG(("ColladaGeometry::readTriFans: material symbol [%s] "
957 "vertices [%d] fans [%" PRIUSize
"]\n",
958 (triFans
->getMaterial() != NULL
?
959 triFans
->getMaterial() : ""),
961 _geoStore
[geoIdx
]._lengths
->size()));
963 // remove empty geometry
966 SWARNING
<< "ColladaGeometry::readTriFans: Empty <trifans> "
968 << (triFans
->getMaterial() != NULL
?
969 triFans
->getMaterial() : "")
970 << "]." << std::endl
;
972 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
977 ColladaGeometry::readTriStrips(domMesh
*mesh
, domTristrips
*triStrips
)
979 OSG_COLLADA_LOG(("ColladaGeometry::readTriStrips\n"));
981 const domInputLocal_Array
&vertInputs
=
982 mesh
->getVertices()->getInput_array();
983 const domInputLocalOffset_Array
&inputs
=
984 triStrips
->getInput_array();
987 UInt32 geoIdx
= setupGeometry(vertInputs
, inputs
,
988 triStrips
->getMaterial(), idxStore
);
990 const domP_Array
&pArray
= triStrips
->getP_array();
995 for(UInt32 i
= 0; i
< pArray
.getCount(); ++i
)
997 const domListOfUInts
&pList
= pArray
[i
]->getValue();
999 for(UInt32 j
= 0; j
< pList
.getCount(); ++j
)
1001 idxStore
[currIdx
]->push_back(pList
[j
]);
1005 if(currIdx
== idxStore
.size())
1012 // only add non-empty tri strip
1015 _geoStore
[geoIdx
]._types
->push_back(GL_TRIANGLE_STRIP
);
1016 _geoStore
[geoIdx
]._lengths
->push_back(length
);
1023 OSG_COLLADA_LOG(("ColladaGeometry::readTriStrips: material symbol [%s] "
1024 "vertices [%d] strips [%" PRIUSize
"]\n",
1025 (triStrips
->getMaterial() != NULL
?
1026 triStrips
->getMaterial() : ""),
1028 _geoStore
[geoIdx
]._lengths
->size()));
1030 // remove empty geometry
1033 SWARNING
<< "ColladaGeometry::readTriStrips: Empty <tristrips> "
1034 << "with material ["
1035 << (triStrips
->getMaterial() != NULL
?
1036 triStrips
->getMaterial() : "")
1037 << "]." << std::endl
;
1039 _geoStore
.erase(_geoStore
.begin() + geoIdx
);
1044 ColladaGeometry::mapSemantic(
1045 const std::string
&semantic
, UInt32 set
, UInt32 geoIdx
)
1047 UInt32 propIdx
= Geometry::MaxAttribs
;
1049 if(semantic
== "POSITION")
1051 propIdx
= Geometry::PositionsIndex
;
1053 else if(semantic
== "NORMAL")
1055 propIdx
= Geometry::NormalsIndex
;
1057 else if(semantic
== "TEXCOORD")
1059 if(set
<= Geometry::TexCoords7Index
)
1061 propIdx
= Geometry::TexCoordsIndex
+ set
;
1065 SWARNING
<< "ColladaGeometry::mapSemantic: TEXCOORD semantic has "
1066 << "out of range set [" << set
<< "]"
1070 else if(semantic
== "TANGENT")
1072 propIdx
= Geometry::TexCoords6Index
;
1074 else if(semantic
== "BINORMAL")
1076 propIdx
= Geometry::TexCoords7Index
;
1080 OSG_COLLADA_LOG(("ColladaGeometry::mapSemantic: Unknown semantic [%s] "
1081 "set [%d]\n", semantic
.c_str(), set
));
1084 OSG_COLLADA_LOG(("ColladaGeometry::mapSemantic: semantic [%s] "
1085 "set [%d] -> propIdx [%d]\n",
1086 semantic
.c_str(), set
, propIdx
));
1092 ColladaGeometry::setupProperty(
1093 UInt32 geoIdx
, UInt32 propIdx
, const std::string
&semantic
, UInt32 set
,
1094 const std::string
&sourceId
, GeoIntegralProperty
*idxProp
)
1097 _geoStore
[geoIdx
]._propStore
.resize(
1098 osgMax
<UInt32
>(UInt32(_geoStore
[geoIdx
]._propStore
.size()),
1101 _geoStore
[geoIdx
]._indexStore
.resize(
1102 osgMax
<UInt32
>(UInt32(_geoStore
[geoIdx
]._indexStore
.size()),
1106 // set index for the property
1107 _geoStore
[geoIdx
]._indexStore
[propIdx
] = idxProp
;
1109 // get property from source
1110 SourceMapConstIt smIt
= _sourceMap
.find(sourceId
);
1111 GeoVectorProperty
*prop
= NULL
;
1113 if(smIt
!= _sourceMap
.end())
1115 prop
= smIt
->second
->getProperty(semantic
);
1119 SFATAL
<< "ColladaGeometry::setupProperty: "
1120 << "No <source> with id [" << sourceId
<< "] found."
1125 _geoStore
[geoIdx
]._propStore
[propIdx
]._semantic
= semantic
;
1126 _geoStore
[geoIdx
]._propStore
[propIdx
]._set
= set
;
1127 _geoStore
[geoIdx
]._propStore
[propIdx
]._prop
= prop
;
1131 ColladaGeometry::setupGeometry(const domInputLocal_Array
&vertInputs
,
1132 const domInputLocalOffset_Array
&inputs
,
1134 IndexStore
&idxStore
)
1136 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry\n"));
1138 typedef std::vector
<UInt32
> UnhandledStore
;
1139 typedef UnhandledStore::const_iterator UnhandledStoreConstIt
;
1141 Int32 vertInputIndex
= -1; // <input> with sem "VERTEX"
1142 UnhandledStore unhandledVertInputs
;
1143 UnhandledStore unhandledInputs
;
1145 UInt32 geoIdx
= UInt32(_geoStore
.size());
1146 _geoStore
.push_back(GeoInfo());
1148 if(matSymbol
!= NULL
)
1150 _geoStore
[geoIdx
]._matSymbol
= matSymbol
;
1154 SWARNING
<< "ColladaGeometry::setupGeometry: "
1155 << "Found empty material symbol." << std::endl
;
1158 for(UInt32 i
= 0; i
< inputs
.getCount(); ++i
)
1160 std::string semantic
= inputs
[i
]->getSemantic();
1161 UInt32 set
= inputs
[i
]->getSet ();
1162 UInt32 offset
= inputs
[i
]->getOffset ();
1163 std::string sourceId
= inputs
[i
]->getSource ().id();
1165 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: input [%d] "
1166 "semantic [%s] set [%d] offset [%d] - source [%s]\n",
1167 i
, semantic
.c_str(), set
, offset
, sourceId
.c_str()));
1169 if(semantic
== "VERTEX")
1171 // handle <input> tag with semantic "VERTEX"
1172 // by processing vertInputs, i.e. the <vertices> tag
1176 // all vertInputs use the same index - with the offset from the
1177 // <input> with semantic == VERTEX
1178 if(offset
>= idxStore
.size() || idxStore
[offset
] == NULL
)
1180 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: "
1181 "new index property for offset [%d]\n",
1186 osgMax
<UInt32
>(offset
+ 1, UInt32(idxStore
.size())), NULL
);
1187 idxStore
[offset
] = GeoUInt32Property::create();
1190 for(UInt32 j
= 0; j
< vertInputs
.getCount(); ++j
)
1192 semantic
= vertInputs
[j
]->getSemantic();
1193 sourceId
= vertInputs
[j
]->getSource ().id();
1195 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: vertices [%d] "
1196 "semantic [%s] - source [%s]\n",
1197 j
, semantic
.c_str(), sourceId
.c_str()));
1199 UInt32 propIdx
= mapSemantic(semantic
, 0, geoIdx
);
1201 if(propIdx
== Geometry::MaxAttribs
)
1203 unhandledVertInputs
.push_back(j
);
1207 setupProperty(geoIdx
, propIdx
, semantic
, set
, sourceId
,
1214 // handle regular <input> tags
1216 if(offset
>= idxStore
.size() || idxStore
[offset
] == NULL
)
1218 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: "
1219 "new index property for offset [%d]\n",
1223 idxStore
.resize(osgMax
<UInt32
>(offset
+ 1,
1224 UInt32(idxStore
.size())), NULL
);
1226 idxStore
[offset
] = GeoUInt32Property::create();
1229 UInt32 propIdx
= mapSemantic(semantic
, set
, geoIdx
);
1231 if(propIdx
== Geometry::MaxAttribs
)
1233 unhandledInputs
.push_back(i
);
1237 setupProperty(geoIdx
, propIdx
, semantic
, set
, sourceId
,
1243 // some <inputs> could not be handled above because their
1244 // semantic was not recognized.
1245 // after everything else is set put them into free attribute
1246 // slots, starting at Geometry::TexCoordsIndex
1248 UnhandledStoreConstIt uhIt
= unhandledVertInputs
.begin();
1249 UnhandledStoreConstIt uhEnd
= unhandledVertInputs
.end ();
1251 for(; uhIt
!= uhEnd
; ++uhIt
)
1253 std::string semantic
= vertInputs
[*uhIt
]->getSemantic();
1254 UInt32 set
= inputs
[vertInputIndex
]->getSet ();
1255 UInt32 offset
= inputs
[vertInputIndex
]->getOffset ();
1256 std::string sourceId
= vertInputs
[*uhIt
]->getSource ().id();
1258 UInt32 propIdx
= findFreePropertyIndex(geoIdx
);
1260 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: unhandled vertex "
1261 " <input> [%d] semantic [%s] set [%d] offset [%d] - "
1262 "source [%s] mapped to propIdx [%d]\n",
1263 *uhIt
, semantic
.c_str(), set
, offset
, sourceId
.c_str(),
1266 setupProperty(geoIdx
, propIdx
, semantic
, set
, sourceId
,
1270 uhIt
= unhandledInputs
.begin();
1271 uhEnd
= unhandledInputs
.end ();
1273 for(; uhIt
!= uhEnd
; ++uhIt
)
1275 std::string semantic
= inputs
[*uhIt
]->getSemantic();
1276 UInt32 set
= inputs
[*uhIt
]->getSet ();
1277 UInt32 offset
= inputs
[*uhIt
]->getOffset ();
1278 std::string sourceId
= inputs
[*uhIt
]->getSource ().id();
1280 UInt32 propIdx
= findFreePropertyIndex(geoIdx
);
1282 OSG_COLLADA_LOG(("ColladaGeometry::setupGeometry: unhandled <input> "
1283 "[%d] semantic [%s] set [%d] offset [%d] - "
1284 "source [%s] mapped to propIdx [%d]\n",
1285 *uhIt
, semantic
.c_str(), set
, offset
, sourceId
.c_str(),
1288 setupProperty(geoIdx
, propIdx
, semantic
, set
, sourceId
,
1293 // check for holes in idxStore - which is not supported
1294 IndexStoreConstIt idxIt
= idxStore
.begin();
1295 IndexStoreConstIt idxEnd
= idxStore
.end ();
1297 for(UInt32 i
= 0; idxIt
!= idxEnd
; ++idxIt
, ++i
)
1301 SWARNING
<< "ColladaGeometry::setupGeometry: idxStore contains "
1302 << "hole at [" << i
<< "]" << std::endl
;
1307 _geoStore
[geoIdx
]._lengths
= GeoUInt32Property::create();
1308 _geoStore
[geoIdx
]._types
= GeoUInt8Property ::create();
1314 ColladaGeometry::handleBindMaterial(
1315 const GeoInfo
&geoInfo
, Geometry
*geo
, ColladaInstanceGeometry
*colInstGeo
)
1317 typedef ColladaInstanceGeometry::MaterialMap ColMaterialMap
;
1318 typedef ColladaInstanceGeometry::MaterialMapConstIt ColMaterialMapConstIt
;
1320 const ColMaterialMap
&matMap
= colInstGeo
->getMaterialMap();
1321 ColMaterialMapConstIt mmIt
= matMap
.find(geoInfo
._matSymbol
);
1322 Material
*material
= NULL
;
1323 ColladaInstanceMaterial
*colInstMat
= NULL
;
1324 ColladaInstanceEffect
*colInstEffect
= NULL
;
1326 if(mmIt
!= matMap
.end())
1328 colInstMat
= mmIt
->second
;
1330 OSG_ASSERT(colInstMat
!= NULL
);
1331 OSG_ASSERT(colInstMat
->getTargetElem() != NULL
);
1333 ColladaInstInfoRefPtr colInstInfo
=
1334 ColladaMaterial::ColladaMaterialInstInfo::create(this, colInstMat
);
1337 colInstMat
->getTargetElem()->createInstance(colInstInfo
);
1338 colInstEffect
= colInstMat
->getInstanceEffect();
1342 SWARNING
<< "ColladaGeometry::handleBindMaterial: No material found "
1343 << "for symbol [" << geoInfo
._matSymbol
<< "]."
1346 geo
->setMaterial(getDefaultMaterial());
1350 const BindStore
&bindStore
= colInstMat
->getBindStore ();
1351 const BindVertexStore
&bindVertexStore
= colInstMat
->getBindVertexStore();
1353 PropStoreConstIt psIt
= geoInfo
._propStore
.begin();
1354 PropStoreConstIt psEnd
= geoInfo
._propStore
.end ();
1355 IndexStoreConstIt isIt
= geoInfo
._indexStore
.begin();
1356 IndexStoreConstIt isEnd
= geoInfo
._indexStore
.end ();
1358 // for every property in geoInfo we need to check if it gets remapped by a
1359 // <bind> or <bind_vertex_input>
1361 for(UInt32 i
= 0; psIt
!= psEnd
&& isIt
!= isEnd
; ++psIt
, ++isIt
, ++i
)
1363 if(psIt
->_prop
== NULL
|| *isIt
== NULL
|| (*isIt
)->size() == 0)
1366 bool handledProperty
= false;
1367 UInt32 bindOffset
= 0;
1368 UInt32 bindVertexOffset
= 0;
1370 const BindInfo
*bi
= findBind (bindStore
,
1373 const BindVertexInfo
*bvi
= findBindVertex(bindVertexStore
,
1378 // there may be multiple consumers for a property, keep looping
1379 // until no more consumers are found
1380 while(bi
!= NULL
|| bvi
!= NULL
)
1382 UInt32 mappedProp
= i
;
1384 if(bi
!= NULL
&& bvi
!= NULL
)
1386 // is it a problem if there is a <bind> AND a
1387 // <bind_vertex_input> for the same property ??
1389 SWARNING
<< "ColladaGeometry::handleBindMaterial: "
1390 << "Found <bind> AND <bind_vertex_input> for "
1391 << "semantic [" << bi
->semantic
1392 << "] target/inSemantic [" << bi
->target
<< "/"
1393 << bvi
->inSemantic
<< "] inSet [" << bvi
->inSet
1394 << "]" << std::endl
;
1399 if(colInstEffect
->findTC(bi
->target
, mappedProp
) == true)
1401 OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
1402 "Resolved <bind> semantic [%s] "
1403 "target [%s] to property [%d]\n",
1404 bi
->semantic
.c_str(), bi
->target
.c_str(),
1407 geo
->setProperty( psIt
->_prop
, mappedProp
);
1408 geo
->setIndex (*isIt
, mappedProp
);
1410 handledProperty
= true;
1414 SWARNING
<< "ColladaGeometry::handleBindMaterial: "
1415 << "Failed to resolve <bind> semantic ["
1416 << bi
->semantic
<< "] target [" << bi
->target
1417 << "]." << std::endl
;
1420 else if(bvi
!= NULL
)
1422 if(colInstEffect
->findTC(bvi
->semantic
, mappedProp
) == true)
1424 OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
1425 "Resolved <bind_vertex_input> "
1426 "inSemantic [%s] inSet [%d] semantic [%s] "
1427 "to property [%d]\n",
1428 bvi
->inSemantic
.c_str(), bvi
->inSet
,
1429 bvi
->semantic
.c_str(), mappedProp
));
1431 geo
->setProperty( psIt
->_prop
, mappedProp
);
1432 geo
->setIndex (*isIt
, mappedProp
);
1433 handledProperty
= true;
1437 SWARNING
<< "ColladaGeometry::handleBindMaterial: "
1438 << "Failed to resolve <bind_vertex_input> "
1440 << bvi
->inSemantic
<< "] inSet [" << bvi
->inSet
1441 << "] semantic [" << bvi
->semantic
1442 << "]." << std::endl
;
1446 // find next consumers if any
1450 bi
= findBind (bindStore
, psIt
->_semantic
,
1452 bvi
= findBindVertex(bindVertexStore
, psIt
->_semantic
,
1453 psIt
->_set
, bindVertexOffset
);
1456 // Check for autodesk implicit channel mappings
1457 if(handledProperty
== false)
1459 std::string szChannel
;
1463 case Geometry::TexCoordsIndex
:
1464 szChannel
= "CHANNEL0";
1466 case Geometry::TexCoords1Index
:
1467 szChannel
= "CHANNEL1";
1469 case Geometry::TexCoords2Index
:
1470 szChannel
= "CHANNEL2";
1472 case Geometry::TexCoords3Index
:
1473 szChannel
= "CHANNEL3";
1475 case Geometry::TexCoords4Index
:
1476 szChannel
= "CHANNEL4";
1478 case Geometry::TexCoords5Index
:
1479 szChannel
= "CHANNEL5";
1481 case Geometry::TexCoords6Index
:
1482 szChannel
= "CHANNEL6";
1484 case Geometry::TexCoords7Index
:
1485 szChannel
= "CHANNEL7";
1492 if(szChannel
.empty() == false)
1494 UInt32 mappedProp
= i
;
1496 if(colInstEffect
->findTC(szChannel
, mappedProp
) == true)
1498 OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
1499 "Resolved autodesk implicit semantic [%s] "
1500 "to property [%d]\n",
1504 geo
->setProperty( psIt
->_prop
, mappedProp
);
1505 geo
->setIndex (*isIt
, mappedProp
);
1507 handledProperty
= true;
1512 // if the property is not remapped by <bind> or <bind_vertex_input>
1513 // we just put it at the location it received at read time
1514 // this is for properties that are not of interest to the material
1515 // directly (e.g. positions, normals)
1516 if(handledProperty
== false)
1518 OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
1519 "Setting property [%d] (semantic [%s] set [%d]) "
1520 "without <bind>/<bind_vertex_input> mapping.\n",
1521 i
, psIt
->_semantic
.c_str(), psIt
->_set
));
1523 geo
->setProperty( psIt
->_prop
, i
);
1524 geo
->setIndex (*isIt
, i
);
1528 // Clean up the texcood property indices by ensuring that if we have at
1529 // least one texture coordinate property, that it is assigned to the first
1530 // texture coordinate slot. This should be a safe assumption since we are
1531 // in the common profile.
1533 GeoVectorProperty
*tex_coord0
= geo
->getProperty(Geometry::TexCoordsIndex
);
1535 if(NULL
== tex_coord0
)
1538 for(UInt16 idx
= Geometry::TexCoords1Index
;
1539 idx
<= Geometry::TexCoords7Index
;
1542 GeoVectorProperty
*tex_coord
= geo
->getProperty(idx
);
1544 if (NULL
!= tex_coord
)
1547 ("ColladaGeometry::handleBindMaterial: "
1548 "Manual switch texture coords from [%d] to [%d].\n",
1550 Geometry::TexCoordsIndex
));
1552 geo
->setProperty(tex_coord
, Geometry::TexCoordsIndex
);
1553 geo
->setProperty(NULL
, idx
);
1555 GeoIntegralProperty
*index
= geo
->getIndex(idx
);
1557 geo
->setIndex(index
, Geometry::TexCoordsIndex
);
1558 geo
->setIndex(NULL
, idx
);
1565 if(material
!= NULL
)
1567 geo
->setMaterial(material
);
1571 SWARNING
<< "ColladaGeometry::handleBindMaterial: No material created "
1572 << "for symbol [" << geoInfo
._matSymbol
<< "]."
1575 geo
->setMaterial(getDefaultMaterial());
1579 /*! Returns a <bind> (actually a BindInfo built from a <bind>)
1580 that has the given \a semantic. The search starts at the given \a offset to
1581 allow multiple <bind> with the same semantic to be found.
1583 const ColladaGeometry::BindInfo
*
1584 ColladaGeometry::findBind(
1585 const BindStore
&store
, const std::string
&semantic
, UInt32
&offset
)
1587 const BindInfo
*retVal
= NULL
;
1589 for(UInt32 i
= offset
; i
< store
.size(); ++i
)
1591 if(store
[i
].semantic
== semantic
)
1602 /*! Returns a <bind_vertex_input> (actually a BindVertexInfo built from
1603 a <bind_vertex_input>) that has the given \a inSemantic and \a inSet.
1604 The search starts at the given \a offset to allow
1605 multiple <bind_vertex_input> with the same inSemantic/inSet to be
1608 const ColladaGeometry::BindVertexInfo
*
1609 ColladaGeometry::findBindVertex(
1610 const BindVertexStore
&store
, const std::string
&inSemantic
,
1611 UInt32 inSet
, UInt32
&offset
)
1613 const BindVertexInfo
*retVal
= NULL
;
1615 for(UInt32 i
= offset
; i
< store
.size(); ++i
)
1617 if(store
[i
].inSemantic
== inSemantic
&&
1618 store
[i
].inSet
== inSet
)
1629 ColladaGeometry::findFreePropertyIndex(UInt32 geoIdx
)
1631 // find an unused property
1632 UInt16 retVal
= osgMax
<UInt16
>(UInt16(_geoStore
[geoIdx
]._propStore
.size()),
1633 Geometry::TexCoordsIndex
);
1635 for(UInt16 i
= Geometry::TexCoordsIndex
;
1636 i
< _geoStore
[geoIdx
]._propStore
.size(); ++i
)
1638 if(_geoStore
[geoIdx
]._propStore
[i
]._prop
== NULL
)
1650 #endif // OSG_WITH_COLLADA