fixed: OSB loader check index property has useVBO set if the geometry uses useVAO...
[opensg.git] / Source / System / FileIO / OSB / OSGOSBRootElement.cpp
blob3210d3b346268e6dc9e813e4e717c0fd102f7b0e
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2007 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 "OSGOSBRootElement.h"
41 #include "OSGOSBElementFactory.h"
42 #include "OSGContainerPtrFuncs.h"
44 #include "OSGAttachmentContainer.h"
45 #include "OSGAttachment.h"
46 #include "OSGFieldContainerSFields.h"
48 OSG_USING_NAMESPACE
50 /*-------------------------------------------------------------------------*/
51 /* OSBRootElement */
52 /*-------------------------------------------------------------------------*/
54 /*! \class OSG::OSBRootElement
55 The root element is different from the other elements for it is not
56 responsible for loading a certain type of FieldContainer but instead holds
57 the shared state of the OSB IO subsystem. All elements (including the
58 root element itself) have a pointer to it and can access the shared state
59 through it.
62 /*-------------------------------------------------------------------------*/
63 /* Static members */
65 OSBElementRegistrationHelper<OSBRootElement>
66 OSBRootElement::_regHelper =
67 OSBElementRegistrationHelper<OSBRootElement>("RootElement");
69 /*-------------------------------------------------------------------------*/
70 /* Constructor */
72 /*! Constructor.
74 OSBRootElement::OSBRootElement(OSBRootElement * /* root */)
75 : Inherited(this, Inherited::OSGOSBHeaderVersion200)
77 // nothing to do.
80 /*-------------------------------------------------------------------------*/
81 /* Destructor */
83 /*! Destructor.
85 OSBRootElement::~OSBRootElement(void)
87 // nothing to do.
90 /*-------------------------------------------------------------------------*/
91 /* Reading */
93 /*! Initializes this root element for a read operation from \a inStream.
94 This must be called before OSBRootElement::read(const std::string&).
96 \param[in] inStream Stream to read data from.
98 void
99 OSBRootElement::initialiseRead(std::istream &inStream)
101 _readHandler = new BinaryReadHandler(inStream);
103 _elements .clear();
104 _readIdMap .clear();
105 _readPtrFields.clear();
108 /*! Performs clean up tasks after a read operation. This must be called after
109 OSBRootElement::postRead(void).
111 void
112 OSBRootElement::terminateRead(void)
114 ElementListIt eI = editElementList().begin();
115 ElementListIt eE = editElementList().end ();
117 for(; eI != eE; ++eI)
119 OSBElementFactory::the()->release(*eI);
122 _elements .clear();
123 _readIdMap .clear();
124 _readPtrFields.clear();
126 delete _readHandler;
127 _readHandler = 0;
130 /*! Reads from the stream set by a preceding call to initialiseRead. Since the
131 root element is the first one created it reads the file header and
132 creates the elements to read the data following the header.
134 \param[in] typeName The argument is ignored.
136 void
137 OSBRootElement::read(const std::string &/*typeName*/)
139 OSG_OSB_LOG(("OSBRootElement::read\n"));
141 BinaryReadHandler *rh = getReadHandler();
142 std::string headerMarker;
144 rh->getValue(headerMarker);
146 if(headerMarker == OSGOSB_HEADER_ID_1)
148 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
149 OSGOSBHeaderVersion100));
150 setHeaderVersion(OSGOSBHeaderVersion100);
152 else if(headerMarker == OSGOSB_HEADER_ID_2)
154 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
155 OSGOSBHeaderVersion200));
156 setHeaderVersion(OSGOSBHeaderVersion200);
158 // else if(headerMarker == OSGOSB_HEADER_ID_201)
159 // {
160 // OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
161 // OSGOSBHeaderVersion201));
162 // setHeaderVersion(OSGOSBHeaderVersion201);
163 // }
164 else
166 FWARNING(("OSBRootElement::read: Unrecognized file header, could not "
167 "load file.\n"));
168 return;
171 std::string headerName;
172 rh->getValue(headerName);
173 std::string headerOptions;
174 rh->getValue(headerOptions);
175 UInt64 fileSize;
176 rh->getValue(fileSize);
178 OSG_OSB_LOG(("OSBRootElement::read: headerName: [%s]\n",
179 headerName.c_str()));
180 OSG_OSB_LOG(("OSBRootElement::read: headerOptions: [%s]\n",
181 headerOptions.c_str()));
182 OSG_OSB_LOG(("OSBRootElement::read: fileSize: [%" PRISize "]\n",
183 fileSize));
185 std::string fcTypeName;
186 UInt32 fcIdFile; // id used in the file
187 UInt32 fcIdSystem; // id used in the system
188 OSBElementBase *elem;
190 while(true)
192 if(!readFieldContainerHeader(fcTypeName, fcIdFile))
193 break;
195 OSG_OSB_LOG(("OSBRootElement::read: fcTypeName [%s] fcIdFile: [%u]\n",
196 fcTypeName.c_str(), fcIdFile));
198 elem = OSBElementFactory::the()->acquire(fcTypeName, this);
199 elem->setFCIdFile(fcIdFile );
200 elem->read (fcTypeName);
202 if(elem->getContainer() != NULL)
204 fcIdSystem = elem->getContainer()->getId();
206 OSG_OSB_LOG(("OSBRootElement::read: fcIdFile: [%u] fcIdSystem: [%u]\n",
207 fcIdFile, fcIdSystem));
209 editIdMap().insert(
210 FieldContainerIdMap::value_type(fcIdFile, fcIdSystem));
212 if(getContainer() == NULL)
214 setContainer(elem->getContainer());
217 editElementList().push_back(elem );
218 editIdElemMap ().insert (std::make_pair(fcIdFile, elem));
223 /*! Performs post processing for all elements created during the previous
224 call to read.
225 Specifically all these elements have their postRead function called and
226 afterwards pointer field remapping is performed. This process fills all
227 fields that hold pointers to FieldContainers with the correct values.
229 void
230 OSBRootElement::postRead(void)
232 OSG_OSB_LOG(("OSBRootElement::postRead\n"));
234 ElementListConstIt elemIt = getElementList().begin();
235 ElementListConstIt elemEnd = getElementList().end ();
237 for(; elemIt != elemEnd; ++elemIt)
239 (*elemIt)->postRead();
242 dumpIdMap();
244 PtrFieldListConstIt ptrFieldIt = getPtrFieldList().begin();
245 PtrFieldListConstIt ptrFieldEnd = getPtrFieldList().end ();
247 for(; ptrFieldIt != ptrFieldEnd; ++ptrFieldIt)
249 mapPtrField(*ptrFieldIt);
252 this->postMap();
255 void OSBRootElement::postMap(void)
257 OSG_OSB_LOG(("OSBRootElement::postMap\n"));
259 ElementListConstIt elemIt = getElementList().begin();
260 ElementListConstIt elemEnd = getElementList().end ();
262 for(; elemIt != elemEnd; ++elemIt)
264 (*elemIt)->postMap();
268 /*-------------------------------------------------------------------------*/
269 /* Writing */
271 /*! Initializes this root element for a write operation to \a outStream.
272 This must be called before
273 OSBRootElement::preWrite(const FieldContainerPtr&).
275 \param[in] outStream Stream to write data to.
277 void
278 OSBRootElement::initialiseWrite(std::ostream &outStream)
280 _writeHandler = new BinaryWriteHandler(outStream);
282 _writeFCList.clear();
283 _writeIdSet .clear();
286 /*! Performs clean up tasks after a write operation. This must be called after
287 OSBRootElement::write(void).
289 void
290 OSBRootElement::terminateWrite(void)
292 ElementListIt eI = editElementList().begin();
293 ElementListIt eE = editElementList().end ();
295 for(; eI != eE; ++eI)
297 OSBElementFactory::the()->release(*eI);
300 _elements .clear();
301 _writeFCList.clear();
302 _writeIdSet .clear();
304 _writeHandler->flush();
306 delete _writeHandler;
307 _writeHandler = 0;
310 /*! Collects all containers that are reachable from \a fc and schedules them
311 for writing. For each container an approriate element is created and
312 its preWrite method is called, thus recursively discovering all reachable
313 containers.
315 \param[in] fc FieldContainer that is inspected for reachable containers.
317 void
318 OSBRootElement::preWrite(FieldContainer * const fc)
320 OSG_OSB_LOG(("OSBRootElement::preWrite\n"));
322 if(fc == NULL)
323 return;
325 const std::string &typeName = fc->getType().getName();
326 OSBElementBase *elem = OSBElementFactory::the()->acquire(
327 typeName, this);
329 editElementList().push_back(elem);
330 elem->setContainer(fc );
331 elem->setFCIdFile (fc->getId());
332 elem->preWrite (fc );
335 /*! Writes the containers collected with the previous call to preWrite to the
336 stream set by initialiseWrite.
337 First the file header is written, then for each element created during
338 preWrite the write function is called.
340 void
341 OSBRootElement::write(void)
343 OSG_OSB_LOG(("OSBRootElement::write\n"));
345 BinaryWriteHandler *wh = getWriteHandler();
347 wh->putValue(OSGOSB_HEADER_ID_2 ); // version
348 wh->putValue(std::string("") ); // name
349 wh->putValue(std::string("") ); // options
350 wh->putValue(static_cast<UInt64>(0)); // size
352 ElementListConstIt elemIt = getElementList().begin();
353 ElementListConstIt elemEnd = getElementList().end ();
355 for(; elemIt != elemEnd; ++elemIt)
357 writeFieldContainerHeader((*elemIt)->getContainer());
358 (*elemIt)->write();
362 /*-------------------------------------------------------------------------*/
363 /* Helper methods */
365 /*! Fills the "pointer field" described by \a ptrField with the correct
366 pointers.
368 \param[in] ptrField Field to fill.
370 void
371 OSBRootElement::mapPtrField(const PtrFieldInfo &ptrField)
373 OSG_OSB_LOG(("OSBRootElement::mapPtrField\n"));
375 PtrFieldInfo::PtrIdStoreConstIt idIt = ptrField.beginIdStore();
376 PtrFieldInfo::PtrIdStoreConstIt idEnd = ptrField.endIdStore ();
378 PtrFieldInfo::BindingStoreConstIt bindingIt = ptrField.beginBindingStore();
379 PtrFieldInfo::BindingStoreConstIt bindingEnd = ptrField.endBindingStore ();
381 const FieldContainerIdMap &idMap = getIdMap();
382 FieldContainerIdMapConstIt idMapIt;
383 FieldContainerIdMapConstIt idMapEnd = idMap.end();
385 if(bindingIt != bindingEnd)
387 if(ptrField.getHandledField() == true)
389 FieldContainer *fieldCon = ptrField.getContainer();
390 UInt32 fieldId = ptrField.getFieldId();
392 EditFieldHandlePtr fHandle = fieldCon->editField(fieldId);
394 EditMapFieldHandlePtr sfMapField =
395 boost::dynamic_pointer_cast<EditMapFieldHandle>(fHandle);
397 if(sfMapField == NULL || sfMapField->isValid() == false)
398 return;
400 sfMapField->fillFrom(ptrField.getBindingStore(),
401 ptrField.getIdStore (),
402 idMap);
404 else
406 Attachment *att = NULL;
407 AttachmentContainer *attCon =
408 dynamic_cast<AttachmentContainer *>(ptrField.getContainer());
410 for(; (idIt != idEnd) && (bindingIt != bindingEnd); ++idIt,
411 ++bindingIt)
413 if(*idIt != 0)
415 idMapIt = idMap.find(*idIt);
417 if(idMapIt != idMapEnd)
419 att = dynamic_cast<Attachment *>(
420 FieldContainerFactory::the()->getContainer(
421 idMapIt->second));
423 else
425 FWARNING(("OSBRootElement::mapPtrField: could not find "
426 "FieldContainer with id [%u]\n", *idIt));
427 att = NULL;
430 else
432 att = NULL;
435 if(att != NULL)
437 OSG_OSB_LOG(("OSBRootElement::mapPtrField: adding "
438 "attchment [%u] [%u]\n",
439 att->getType().getGroupId(), *bindingIt));
442 attCon->addAttachment(att, *bindingIt);
446 else
448 FieldContainer *fc = NULL;
449 FieldContainer *fieldCon = ptrField.getContainer();
450 UInt32 fieldId = ptrField.getFieldId();
452 EditFieldHandlePtr fHandle = fieldCon->editField(fieldId);
454 FieldContainerPtrSFieldBase::EditHandlePtr pSFHandle =
455 boost::dynamic_pointer_cast<
456 FieldContainerPtrSFieldBase::EditHandle>(fHandle);
458 FieldContainerPtrMFieldBase::EditHandlePtr pMFHandle =
459 boost::dynamic_pointer_cast<
460 FieldContainerPtrMFieldBase::EditHandle>(fHandle);
462 for(; idIt != idEnd; ++idIt)
464 if(*idIt != 0)
466 idMapIt = idMap.find(*idIt);
468 if(idMapIt != idMapEnd)
470 fc = FieldContainerFactory::the()->getContainer(
471 idMapIt->second);
473 else
475 FWARNING(("OSBRootElement::mapPtrField: could not find "
476 "FieldContainer with (file) id [%u]\n", *idIt));
477 fc = NULL;
480 else
482 fc = NULL;
485 if(pSFHandle != NULL && pSFHandle->isValid())
487 pSFHandle->set(fc);
489 else if(pMFHandle != NULL && pMFHandle->isValid())
491 pMFHandle->add(fc);
493 else
495 FWARNING(("OSBRootElement::mapPtrField: FieldHandles invalid, "
496 "can not set pointer - target fc [%u][%s] "
497 "fieldId [%u][%s] file id [%u] system id [%u]\n",
498 (fc != NULL ? fc->getId() : 0),
499 (fc != NULL ? fc->getType().getCName() : ""),
500 fieldId,
501 (fc != NULL ?
502 fc->getType().getFieldDesc(fieldId)->getCName() : ""),
503 *idIt,
504 (idMapIt != idMapEnd ? idMapIt->second : 0) ));
510 /*! Prints the map showing the relation between FieldContainer ids in the file
511 and the system, which is used by mapPtrField to fill in the right pointers.
513 void
514 OSBRootElement::dumpIdMap(void) const
516 OSG_OSB_LOG(("OSBRootElement::dumpIdMap\n"));
518 FieldContainerIdMapConstIt mapIt = getIdMap().begin();
519 FieldContainerIdMapConstIt mapEnd = getIdMap().end ();
521 for(; mapIt != mapEnd; ++mapIt)
523 OSG_OSB_LOG((" file id %u -> %u system id\n", mapIt->first, mapIt->second));