1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2006 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 #include "OSGOSBGeometryElement.h"
41 #include "OSGOSBGeometryHelper.h"
42 #include "OSGOSBRootElement.h"
43 #include "OSGOSBGeoIntegralPropertyElement.h"
44 #include "OSGOSBGeoVectorPropertyElement.h"
45 #include "OSGTypedGeoIntegralProperty.h"
46 #include "OSGTypedGeoVectorProperty.h"
47 #include "OSGGeometry.h"
48 #include "OSGGeoPumpGroup.h"
52 /*-------------------------------------------------------------------------*/
53 /* OSBGeometryElement */
54 /*-------------------------------------------------------------------------*/
56 /*-------------------------------------------------------------------------*/
59 OSBElementRegistrationHelper
<OSBGeometryElement
>
60 OSBGeometryElement::_regHelper
=
61 OSBElementRegistrationHelper
<OSBGeometryElement
>("Geometry");
63 /*! Constants for the OpenSG 1.x index mapping.
64 These values must match those used in the OpenSG 1.x Geometry class.
66 const UInt16
OSBGeometryElement::MapPosition
= 1;
67 const UInt16
OSBGeometryElement::MapNormal
=
68 OSBGeometryElement::MapPosition
<< 1;
69 const UInt16
OSBGeometryElement::MapColor
=
70 OSBGeometryElement::MapNormal
<< 1;
71 const UInt16
OSBGeometryElement::MapSecondaryColor
=
72 OSBGeometryElement::MapColor
<< 1;
73 const UInt16
OSBGeometryElement::MapTexCoords
=
74 OSBGeometryElement::MapSecondaryColor
<< 1;
75 const UInt16
OSBGeometryElement::MapTexCoords1
=
76 OSBGeometryElement::MapTexCoords
<< 1;
77 const UInt16
OSBGeometryElement::MapTexCoords2
=
78 OSBGeometryElement::MapTexCoords1
<< 1;
79 const UInt16
OSBGeometryElement::MapTexCoords3
=
80 OSBGeometryElement::MapTexCoords2
<< 1;
81 const UInt16
OSBGeometryElement::MapTexCoords4
=
82 OSBGeometryElement::MapTexCoords3
<< 1;
83 const UInt16
OSBGeometryElement::MapTexCoords5
=
84 OSBGeometryElement::MapTexCoords4
<< 1;
85 const UInt16
OSBGeometryElement::MapTexCoords6
=
86 OSBGeometryElement::MapTexCoords5
<< 1;
87 const UInt16
OSBGeometryElement::MapTexCoords7
=
88 OSBGeometryElement::MapTexCoords6
<< 1;
89 const UInt16
OSBGeometryElement::MapEmpty
=
90 OSBGeometryElement::MapTexCoords7
<< 1;
92 /*-------------------------------------------------------------------------*/
95 OSBGeometryElement::OSBGeometryElement(OSBRootElement
*root
)
96 : Inherited (root
, OSGOSBHeaderVersion200
),
100 _indices16Bit (false ),
101 _indicesPacked(false ),
102 _version (OSGOSBHeaderVersion200
)
106 /*-------------------------------------------------------------------------*/
109 OSBGeometryElement::~OSBGeometryElement(void)
113 /*-------------------------------------------------------------------------*/
117 OSBGeometryElement::read(const std::string
&typeName
)
119 OSG_OSB_LOG(("OSBGeometryElement::read: [%s]\n", typeName
.c_str()));
121 BinaryReadHandler
*rh
= editRoot()->getReadHandler();
123 rh
->getValue(_version
);
124 OSG_OSB_LOG(("OSBGeometryElement::read: version: [%u]\n", _version
));
126 if(_version
>= OSGOSBHeaderVersion200
)
128 if(_version
> OSGOSBHeaderVersion200
)
130 FINFO(("OSBGeometryElement::read: "
131 "Unknown version, trying to read as latest.\n"));
134 setContainer(GeometryUnrecPtr(Geometry::create()));
137 else if(_version
>= OSGOSBHeaderVersion100
)
144 OSBGeometryElement::postRead(void)
146 OSG_OSB_LOG(("OSBGeometryElement::postRead:\n"));
148 if(_version
>= OSGOSBHeaderVersion200
)
150 if(_version
> OSGOSBHeaderVersion200
)
152 FINFO(("OSBGeometryElement::postRead: "
153 "Unknown version, trying to process as latest.\n"));
158 // postRead v2.0 Geometry - nothing to do.
160 else if(_version
>= OSGOSBHeaderVersion100
)
166 void OSBGeometryElement::postMap(void)
168 OSG_OSB_LOG(("OSBGeometryElement::postMap:\n"));
170 if(_version
>= OSGOSBHeaderVersion200
)
172 if(_version
> OSGOSBHeaderVersion200
)
174 FINFO(("OSBGeometryElement::postMap: "
175 "Unknown version, trying to process as latest.\n"));
180 else if(_version
>= OSGOSBHeaderVersion100
)
182 // postMap v1.0 Geometry - nothing to do.
186 /*-------------------------------------------------------------------------*/
190 OSBGeometryElement::preWrite(FieldContainer
* const fc
)
192 OSG_OSB_LOG(("OSBGeometryElement::preWrite\n"));
194 OSBRootElement
*root
= editRoot();
195 UInt32 fieldCount
= fc
->getType().getNumFieldDescs();
197 UInt8 quanResPositions
= root
->getOptions().quantizePositions();
198 UInt8 quanResNormals
= root
->getOptions().quantizeNormals ();
199 UInt8 quanResTexCoords
= root
->getOptions().quantizeTexCoords();
200 bool packIndices
= root
->getOptions().packIndices ();
202 // go through all fields and find those refering to other FCs
203 for(UInt32 fieldId
= 1; fieldId
<= fieldCount
; ++fieldId
)
205 const FieldDescriptionBase
*fieldDesc
= fc
->getFieldDescription(fieldId
);
206 const FieldType
&fieldType
= fieldDesc
->getFieldType();
207 const std::string
&fieldName
= fieldDesc
->getName ();
209 // skip internal fields
210 if(fieldDesc
->isInternal())
212 OSG_OSB_LOG(("OSBGeometryElement::preWrite: "
213 "Skipping internal field: [%s]\n", fieldName
.c_str()));
217 if(fieldName
== "properties")
219 // "properties" might be quantized
220 FieldContainerPtrMFieldBase::GetHandlePtr fP
=
221 boost::dynamic_pointer_cast
<
222 FieldContainerPtrMFieldBase::GetHandle
>(
223 getContainer()->getField(fieldId
));
225 if(fP
== NULL
|| fP
->isValid() == false)
228 FieldContainerPtrMFieldBase::const_iterator fieldIt
=
231 FieldContainerPtrMFieldBase::const_iterator fieldEnd
=
234 for(UInt32 i
= 0; fieldIt
!= fieldEnd
; ++fieldIt
, ++i
)
236 FieldContainer
*refedFC
= *fieldIt
;
241 UInt32 refedId
= refedFC
->getId ();
242 const std::string typeName
= refedFC
->getType().getName();
244 // only schedule a container once
245 if(root
->getIdSet().count(refedId
) > 0)
248 OSBElementBase
*elem
=
249 OSBElementFactory::the()->acquire(typeName
, root
);
250 OSBGeoVectorPropertyElement
*propElem
=
251 dynamic_cast<OSBGeoVectorPropertyElement
*>(elem
);
253 if((propElem
!= 0) && (i
== Geometry::PositionsIndex
))
255 propElem
->setQuantizeResolution(quanResPositions
);
257 else if((propElem
!= 0) && (i
== Geometry::NormalsIndex
))
259 propElem
->setQuantizeResolution(quanResNormals
);
261 else if((propElem
!= 0) && (i
>= Geometry::TexCoordsIndex
) &&
262 (i
<= Geometry::TexCoords7Index
) )
264 propElem
->setQuantizeResolution(quanResTexCoords
);
267 root
->editIdSet ().insert (refedId
);
268 root
->editElementList().push_back(elem
);
269 elem
->setContainer(refedFC
);
270 elem
->preWrite (refedFC
);
273 else if(fieldName
== "propIndices")
275 // "propIndices" might be packed
276 FieldContainerPtrMFieldBase::GetHandlePtr fP
=
277 boost::dynamic_pointer_cast
<
278 FieldContainerPtrMFieldBase::GetHandle
>(
279 getContainer()->getField(fieldId
));
281 if(fP
== NULL
|| fP
->isValid() == false)
284 FieldContainerPtrMFieldBase::const_iterator fieldIt
=
286 FieldContainerPtrMFieldBase::const_iterator fieldEnd
=
289 for(UInt32 i
= 0; fieldIt
!= fieldEnd
; ++fieldIt
, ++i
)
291 FieldContainer
*refedFC
= *fieldIt
;
296 UInt32 refedId
= refedFC
->getId ();
297 const std::string typeName
= refedFC
->getType().getName();
299 // only schedule a container once
300 if(root
->getIdSet().count(refedId
) > 0)
303 OSBElementBase
*elem
=
304 OSBElementFactory::the()->acquire(typeName
, root
);
305 OSBGeoIntegralPropertyElement
*propElem
=
306 dynamic_cast<OSBGeoIntegralPropertyElement
*>(elem
);
308 if((propElem
!= 0) && (packIndices
== true))
310 propElem
->setPackData(true);
313 root
->editIdSet ().insert (refedId
);
314 root
->editElementList().push_back(elem
);
315 elem
->setContainer(refedFC
);
316 elem
->preWrite (refedFC
);
319 else if(fieldName
== "attachments")
321 preWriteAttachmentMapField(fieldId
);
325 // check if field refers to another FC, i.e. its a field holding
326 // FieldContainerPtr or an FieldContainerAttachmentMap
327 if(fieldType
.getContentType().isDerivedFrom(
328 FieldTraits
<FieldContainer
*>::getType()) == true)
330 if(fieldType
.getCardinality() == FieldType::SingleField
)
332 preWritePtrSingleField(fieldId
);
334 else if(fieldType
.getCardinality() == FieldType::MultiField
)
336 preWritePtrMultiField(fieldId
);
344 OSBGeometryElement::write(void)
346 OSG_OSB_LOG(("OSBGeometryElement::write\n"));
348 BinaryWriteHandler
*wh
= editRoot()->getWriteHandler();
350 // wh->putValue(getFCPtrType(getContainer()));
351 wh
->putValue(getVersion());
353 writeFields("", true);
356 /*-------------------------------------------------------------------------*/
357 /* Reading Helper Functions */
360 OSBGeometryElement::readV100(void)
362 OSG_OSB_LOG(("OSBGeometryElement::readV100:\n"));
364 OSBRootElement
*root
= editRoot();
365 BinaryReadHandler
*rh
= editRoot()->getReadHandler();
366 OSBGeometryHelper gh
;
368 GeometryUnrecPtr geo
= Geometry::create();
371 // The "properties" mfield can be thought of the unification of the
372 // "positions", "normals", etc sfields of the 1.x Geometry.
373 // For the conversion the PtrFieldInfo structure for the "properties"
374 // mfield is filled with the corresponding ids of the sfields from the
375 // file. The remapping after postRead will fill in the right pointers.
377 FieldDescriptionBase
*propFieldDesc
=
378 geo
->getFieldDescription("properties");
379 UInt32 propFieldId
= propFieldDesc
->getFieldId();
381 root
->editPtrFieldList().push_back(PtrFieldInfo(geo
, propFieldId
));
382 PtrFieldInfo
&propFieldPFI
= root
->editPtrFieldList().back();
384 propFieldPFI
.editIdStore().resize(Geometry::MaxAttribs
);
388 std::string fieldName
;
389 std::string fieldTypeName
;
391 PtrFieldListIt ptrFieldIt
;
393 if(!readFieldHeader("", fieldName
, fieldTypeName
, fieldSize
))
395 OSG_OSB_LOG(("OSBGeometryElement::readV100: "
396 "Reading stopped at field: [%s].\n", fieldName
.c_str()));
400 if(fieldName
== "indexMapping")
402 // read into temporary field
403 MField
<UInt16
> indexMappingField
;
404 indexMappingField
.copyFromBin(*rh
);
406 // copy to member for use in postRead
407 indexMappingField
.getValues().swap(_indexMapping
);
409 else if(fieldName
== "indices")
411 // read container id of indices property
412 // postRead will handle the conversion of multi indices
413 rh
->getValue(_indicesId
);
415 else if(fieldName
== "positions")
418 rh
->getValue(positionsId
);
419 propFieldPFI
.editIdStore()[Geometry::PositionsIndex
] = positionsId
;
421 else if(fieldName
== "normals")
424 rh
->getValue(normalsId
);
425 propFieldPFI
.editIdStore()[Geometry::NormalsIndex
] = normalsId
;
427 else if(fieldName
== "colors")
430 rh
->getValue(colorsId
);
431 propFieldPFI
.editIdStore()[Geometry::ColorsIndex
] = colorsId
;
433 else if(fieldName
== "secondaryColors")
435 UInt32 secondaryColorsId
;
436 rh
->getValue(secondaryColorsId
);
437 propFieldPFI
.editIdStore()[Geometry::SecondaryColorsIndex
] =
440 else if(fieldName
== "texCoords")
443 rh
->getValue(texCoordsId
);
444 propFieldPFI
.editIdStore()[Geometry::TexCoordsIndex
] =
447 else if(fieldName
== "texCoords1")
450 rh
->getValue(texCoordsId1
);
451 propFieldPFI
.editIdStore()[Geometry::TexCoords1Index
] =
454 else if(fieldName
== "texCoords2")
457 rh
->getValue(texCoordsId2
);
458 propFieldPFI
.editIdStore()[Geometry::TexCoords2Index
] =
461 else if(fieldName
== "texCoords3")
464 rh
->getValue(texCoordsId3
);
465 propFieldPFI
.editIdStore()[Geometry::TexCoords3Index
] =
468 else if(fieldName
== "texCoords4")
471 rh
->getValue(texCoordsId4
);
472 propFieldPFI
.editIdStore()[Geometry::TexCoords4Index
] =
475 else if(fieldName
== "texCoords5")
478 rh
->getValue(texCoordsId5
);
479 propFieldPFI
.editIdStore()[Geometry::TexCoords5Index
] =
482 else if(fieldName
== "texCoords6")
485 rh
->getValue(texCoordsId6
);
486 propFieldPFI
.editIdStore()[Geometry::TexCoords6Index
] =
489 else if(fieldName
== "texCoords7")
492 rh
->getValue(texCoordsId7
);
493 propFieldPFI
.editIdStore()[Geometry::TexCoords7Index
] =
496 else if(fieldName
== "pindices")
502 _indicesPacked
= true;
504 gh
.readPackedIntegralPropertyHeader(rh
, maxValue
,
507 if(root
->getOptions().unpack16BitIndices())
509 if(maxValue
> TypeTraits
<UInt16
>::getMax())
511 GeoUInt32PropertyUnrecPtr ui32Indices
=
512 GeoUInt32Property::create();
513 gh
.readPackedIntegralProperty(rh
, ui32Indices
, maxValue
,
514 propSize
, byteSize
);
516 _indices16Bit
= false;
517 _indices
= ui32Indices
;
521 GeoUInt16PropertyUnrecPtr ui16Indices
=
522 GeoUInt16Property::create();
523 gh
.readPackedIntegralProperty(rh
, ui16Indices
, maxValue
,
524 propSize
, byteSize
);
526 _indices16Bit
= true;
527 _indices
= ui16Indices
;
532 GeoUInt32PropertyUnrecPtr ui32Indices
=
533 GeoUInt32Property::create();
534 gh
.readPackedIntegralProperty(rh
, ui32Indices
, maxValue
,
535 propSize
, byteSize
);
537 _indices16Bit
= false;
538 _indices
= ui32Indices
;
541 else if(fieldName
== "qpositions")
543 // Quantized positions are stored inside the geometry object, not
544 // in the geo-property. They are always of type Pnt3f.
545 GeoPnt3fPropertyUnrecPtr propPos
= GeoPnt3fProperty::create();
551 gh
.readQuantizedVectorPropertyHeader(rh
, resolution
, minValue
,
552 maxValue
, propSize
);
553 gh
.readQuantizedVectorProperty(rh
, propPos
, fieldSize
, resolution
,
554 minValue
, maxValue
, propSize
);
556 geo
->setProperty(propPos
, Geometry::PositionsIndex
);
558 else if(fieldName
== "qnormals")
560 // Quantized normals are stored inside the geometry object, not
561 // in the geo-property. They are always of type Vec3f.
562 GeoVec3fPropertyUnrecPtr propNorm
= GeoVec3fProperty::create();
568 gh
.readQuantizedVectorPropertyHeader(
569 rh
, resolution
, minValue
, maxValue
, propSize
);
570 gh
.readQuantizedVectorProperty(
571 rh
, propNorm
, fieldSize
, resolution
,
572 minValue
, maxValue
, propSize
);
574 geo
->setProperty(propNorm
, Geometry::NormalsIndex
);
576 else if(fieldName
== "qtexCoords")
578 // Quantized texCoords are stored inside the geometry object, not
579 // in the geo-property. They are always of type Vec2f.
580 GeoVec2fPropertyUnrecPtr propTexCoords
= GeoVec2fProperty::create();
586 gh
.readQuantizedVectorPropertyHeader(
587 rh
, resolution
, minValue
, maxValue
, propSize
);
588 gh
.readQuantizedVectorProperty(
589 rh
, propTexCoords
, fieldSize
, resolution
,
590 minValue
, maxValue
, propSize
);
592 geo
->setProperty(propTexCoords
, Geometry::NormalsIndex
);
596 // 1.x Geometry has _sfVbo, it can be skipped
598 readFieldContent(fieldName
, fieldTypeName
, fieldSize
,
599 "'vbo'", ptrFieldIt
);
605 OSBGeometryElement::postReadV100(void)
607 OSG_OSB_LOG(("OSBGeometryElement::postReadV100\n"));
609 OSBRootElement
*root
= editRoot();
611 dynamic_cast<Geometry
*>(getContainer());
612 UInt32 indexMappingSize
= UInt32(_indexMapping
.size());
614 if(indexMappingSize
<= 1)
616 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
617 "Converting single index.\n" ));
621 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
622 "Converting packed indices.\n" ));
623 geo
->setIndices(_indices
);
627 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
628 "Converting non-packed indices.\n" ));
630 // indices stored in container with id _indicesId
631 // create PtrFieldInfo structure to set all entries of field
632 // "propIndices" to the container with id _indicesId
634 FieldDescriptionBase
*indFieldDesc
=
635 geo
->getFieldDescription("propIndices");
636 UInt32 indFieldId
= indFieldDesc
->getFieldId();
638 root
->editPtrFieldList().push_back(PtrFieldInfo(geo
, indFieldId
));
639 PtrFieldInfo
&indFieldPFI
= root
->editPtrFieldList().back();
641 for(UInt32 i
= 0; i
< Geometry::MaxAttribs
; ++i
)
643 indFieldPFI
.editIdStore().push_back(_indicesId
);
649 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
650 "Converting multi index.\n" ));
652 OSBGeometryHelper gh
;
656 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
657 "Converting packed indices.\n" ));
659 // create 16 bit or 32 bit indices
662 GeoUInt16Property
*ui16Indices
=
663 dynamic_pointer_cast
<GeoUInt16Property
>(_indices
);
665 gh
.splitMultiIndex
<GeoUInt16Property
*>(
666 _indexMapping
, ui16Indices
, geo
);
670 GeoUInt32Property
*ui32Indices
=
671 dynamic_pointer_cast
<GeoUInt32Property
>(_indices
);
673 gh
.splitMultiIndex
<GeoUInt32Property
*>(
674 _indexMapping
, ui32Indices
, geo
);
679 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
680 "Converting non-packed indices.\n" ));
682 FieldContainerIdMapConstIt mapIt
=
683 root
->getIdMap().find(_indicesId
);
685 if(mapIt
!= root
->getIdMap().end())
687 _indices
= dynamic_cast<GeoIntegralProperty
*>(
688 FieldContainerFactory::the()->getContainer(mapIt
->second
));
692 FWARNING(("OSBGeometryElement::postReadV100: "
693 "Could not find indices property.\n"));
697 if(_indices
->getFormatSize() == sizeof(UInt16
))
699 GeoUInt16Property
*ui16Indices
=
700 dynamic_pointer_cast
<GeoUInt16Property
>(_indices
);
702 gh
.splitMultiIndex
<GeoUInt16Property
*>(
703 _indexMapping
, ui16Indices
, geo
);
705 else if(_indices
->getFormatSize() == sizeof(UInt32
))
707 GeoUInt32Property
*ui32Indices
=
708 dynamic_pointer_cast
<GeoUInt32Property
>(_indices
);
710 gh
.splitMultiIndex
<GeoUInt32Property
*>(
711 _indexMapping
, ui32Indices
, geo
);
717 void OSBGeometryElement::postMapV200(void)
720 dynamic_cast<Geometry
*>(getContainer());
725 if(geo
->getUseVAO() == false)
728 GeoPumpGroup::PropertyCharacteristics prop
=
729 GeoPumpGroup::characterizeGeometry(geo
);
731 if(((prop
& (GeoPumpGroup::SingleIndexed
)) == 0x0000))
736 GeoProperty
*pIndexProp
= geo
->getIndex(Geometry::PositionsIndex
);
738 if(pIndexProp
== NULL
)
741 pIndexProp
->setUseVBO(true);