fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / OSB / OSGOSBGeometryElement.cpp
blobc306520c0c3ca6c61f5830a3360d804cbb2aa90a
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2006 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
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"
50 OSG_USING_NAMESPACE
52 /*-------------------------------------------------------------------------*/
53 /* OSBGeometryElement */
54 /*-------------------------------------------------------------------------*/
56 /*-------------------------------------------------------------------------*/
57 /* Static members */
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 /*-------------------------------------------------------------------------*/
93 /* Constructor */
95 OSBGeometryElement::OSBGeometryElement(OSBRootElement *root)
96 : Inherited (root, OSGOSBHeaderVersion200),
97 _indexMapping ( ),
98 _indicesId (0 ),
99 _indices (NULL ),
100 _indices16Bit (false ),
101 _indicesPacked(false ),
102 _version (OSGOSBHeaderVersion200 )
106 /*-------------------------------------------------------------------------*/
107 /* Destructor */
109 OSBGeometryElement::~OSBGeometryElement(void)
113 /*-------------------------------------------------------------------------*/
114 /* Reading */
116 void
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()));
135 readFields("", "");
137 else if(_version >= OSGOSBHeaderVersion100)
139 readV100();
143 void
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"));
156 postMapV200();
158 // postRead v2.0 Geometry - nothing to do.
160 else if(_version >= OSGOSBHeaderVersion100)
162 postReadV100();
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"));
178 postMapV200();
180 else if(_version >= OSGOSBHeaderVersion100)
182 // postMap v1.0 Geometry - nothing to do.
186 /*-------------------------------------------------------------------------*/
187 /* Writing */
189 void
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()));
214 continue;
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)
226 continue;
228 FieldContainerPtrMFieldBase::const_iterator fieldIt =
229 (*fP)->begin();
231 FieldContainerPtrMFieldBase::const_iterator fieldEnd =
232 (*fP)->end ();
234 for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
236 FieldContainer *refedFC = *fieldIt;
238 if(refedFC == NULL)
239 continue;
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)
246 continue;
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)
282 continue;
284 FieldContainerPtrMFieldBase::const_iterator fieldIt =
285 (*fP)->begin();
286 FieldContainerPtrMFieldBase::const_iterator fieldEnd =
287 (*fP)->end ();
289 for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
291 FieldContainer *refedFC = *fieldIt;
293 if(refedFC == NULL)
294 continue;
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)
301 continue;
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);
323 else
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);
343 void
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 */
359 void
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();
369 setContainer(geo);
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);
386 while(true)
388 std::string fieldName;
389 std::string fieldTypeName;
390 UInt32 fieldSize;
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()));
397 break;
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")
417 UInt32 positionsId;
418 rh->getValue(positionsId);
419 propFieldPFI.editIdStore()[Geometry::PositionsIndex] = positionsId;
421 else if(fieldName == "normals")
423 UInt32 normalsId;
424 rh->getValue(normalsId);
425 propFieldPFI.editIdStore()[Geometry::NormalsIndex] = normalsId;
427 else if(fieldName == "colors")
429 UInt32 colorsId;
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] =
438 secondaryColorsId;
440 else if(fieldName == "texCoords")
442 UInt32 texCoordsId;
443 rh->getValue(texCoordsId);
444 propFieldPFI.editIdStore()[Geometry::TexCoordsIndex] =
445 texCoordsId;
447 else if(fieldName == "texCoords1")
449 UInt32 texCoordsId1;
450 rh->getValue(texCoordsId1);
451 propFieldPFI.editIdStore()[Geometry::TexCoords1Index] =
452 texCoordsId1;
454 else if(fieldName == "texCoords2")
456 UInt32 texCoordsId2;
457 rh->getValue(texCoordsId2);
458 propFieldPFI.editIdStore()[Geometry::TexCoords2Index] =
459 texCoordsId2;
461 else if(fieldName == "texCoords3")
463 UInt32 texCoordsId3;
464 rh->getValue(texCoordsId3);
465 propFieldPFI.editIdStore()[Geometry::TexCoords3Index] =
466 texCoordsId3;
468 else if(fieldName == "texCoords4")
470 UInt32 texCoordsId4;
471 rh->getValue(texCoordsId4);
472 propFieldPFI.editIdStore()[Geometry::TexCoords4Index] =
473 texCoordsId4;
475 else if(fieldName == "texCoords5")
477 UInt32 texCoordsId5;
478 rh->getValue(texCoordsId5);
479 propFieldPFI.editIdStore()[Geometry::TexCoords5Index] =
480 texCoordsId5;
482 else if(fieldName == "texCoords6")
484 UInt32 texCoordsId6;
485 rh->getValue(texCoordsId6);
486 propFieldPFI.editIdStore()[Geometry::TexCoords6Index] =
487 texCoordsId6;
489 else if(fieldName == "texCoords7")
491 UInt32 texCoordsId7;
492 rh->getValue(texCoordsId7);
493 propFieldPFI.editIdStore()[Geometry::TexCoords7Index] =
494 texCoordsId7;
496 else if(fieldName == "pindices")
498 UInt32 maxValue;
499 UInt32 propSize;
500 UInt32 byteSize;
502 _indicesPacked = true;
504 gh.readPackedIntegralPropertyHeader(rh, maxValue,
505 propSize, byteSize);
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;
519 else
521 GeoUInt16PropertyUnrecPtr ui16Indices =
522 GeoUInt16Property::create();
523 gh.readPackedIntegralProperty(rh, ui16Indices, maxValue,
524 propSize, byteSize );
526 _indices16Bit = true;
527 _indices = ui16Indices;
530 else
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();
546 UInt8 resolution;
547 Real32 minValue;
548 Real32 maxValue;
549 UInt32 propSize;
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();
563 UInt8 resolution;
564 Real32 minValue;
565 Real32 maxValue;
566 UInt32 propSize;
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();
581 UInt8 resolution;
582 Real32 minValue;
583 Real32 maxValue;
584 UInt32 propSize;
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);
594 else
596 // 1.x Geometry has _sfVbo, it can be skipped
598 readFieldContent(fieldName, fieldTypeName, fieldSize,
599 "'vbo'", ptrFieldIt );
604 void
605 OSBGeometryElement::postReadV100(void)
607 OSG_OSB_LOG(("OSBGeometryElement::postReadV100\n"));
609 OSBRootElement *root = editRoot();
610 Geometry *geo =
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" ));
619 if(_indicesPacked)
621 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
622 "Converting packed indices.\n" ));
623 geo->setIndices(_indices);
625 else
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);
647 else
649 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
650 "Converting multi index.\n" ));
652 OSBGeometryHelper gh;
654 if(_indicesPacked)
656 OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
657 "Converting packed indices.\n" ));
659 // create 16 bit or 32 bit indices
660 if(_indices16Bit)
662 GeoUInt16Property *ui16Indices =
663 dynamic_pointer_cast<GeoUInt16Property>(_indices);
665 gh.splitMultiIndex<GeoUInt16Property *>(
666 _indexMapping, ui16Indices, geo);
668 else
670 GeoUInt32Property *ui32Indices =
671 dynamic_pointer_cast<GeoUInt32Property>(_indices);
673 gh.splitMultiIndex<GeoUInt32Property *>(
674 _indexMapping, ui32Indices, geo);
677 else
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));
690 else
692 FWARNING(("OSBGeometryElement::postReadV100: "
693 "Could not find indices property.\n"));
694 return;
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)
719 Geometry *geo =
720 dynamic_cast<Geometry*>(getContainer());
722 if(geo == NULL)
723 return;
725 if(geo->getUseVAO() == false)
726 return;
728 GeoPumpGroup::PropertyCharacteristics prop =
729 GeoPumpGroup::characterizeGeometry(geo);
731 if(((prop & (GeoPumpGroup::SingleIndexed)) == 0x0000))
733 return;
736 GeoProperty *pIndexProp = geo->getIndex(Geometry::PositionsIndex);
738 if(pIndexProp == NULL)
739 return;
741 pIndexProp->setUseVBO(true);