/*! Visits a SFFieldContainerPtr (or more specific pointer type) during
    preWrite. It creates an element for the pointed to container and
    calls preWrite on it. If the pointed to container is not in the
    root's id set it is added and thus scheduled for writing.

    \param[in] fieldId Id of the field in the container of this element.
 */
void
OSBCommonElement::preWritePtrSingleField(const UInt32 fieldId)
{
    OSG_OSB_LOG(("OSBCommonElement::preWritePtrSingleField: "
            "fieldId: [%u]\n", fieldId));

    OSBRootElement     *root       = editRoot();

    FieldContainerPtrSFieldBase::GetHandlePtr sfPtrField =
        boost::dynamic_pointer_cast<FieldContainerPtrSFieldBase::GetHandle>(
            getContainer()->getField(fieldId));

    if(sfPtrField == NULL || sfPtrField->isValid() == false)
        return;

    FieldContainer *refedFC = (*sfPtrField)->getValue();

    if(refedFC == NULL)
        return;

    UInt32             refedId  = refedFC->getId  ();
    const std::string &typeName = refedFC->getType().getName();

    // only schedule a container once
    if(root->getIdSet().count(refedId) == 0)
    {
        OSBElementBase *elem = OSBElementFactory::the()->acquire(
            typeName, root);

        root->editIdSet      ().insert   (refedId);
        root->editElementList().push_back(elem   );
        elem->setContainer(refedFC);
        elem->preWrite    (refedFC);
    }
}
/*! Reads a MFFieldContainerPtr (or a more specific pointer type) from the
    stream. It has the given \a fieldId in the container it belongs to.

    \param[in] fieldId Id of the field in the container it belongs to.
    \param[in] fieldSize field size
    \return Iterator that points to the PtrFieldInfo structure
    that was created for this field.
 */
OSBCommonElement::PtrFieldListIt
OSBCommonElement::readPtrMultiField(
    const UInt32 fieldId, const UInt32 fieldSize)
{
    OSG_OSB_LOG(("OSBCommonElement::readPtrMultiField: "
            "fieldId: [%u]\n", fieldId));

    UInt32             ptrId;
    UInt32             numElements;
    OSBRootElement    *root        = editRoot();
    BinaryReadHandler *rh          = editRoot()->getReadHandler();

    root->editPtrFieldList().push_back(PtrFieldInfo(getContainer(), fieldId));
    PtrFieldInfo &pfi = root->editPtrFieldList().back();

    rh->getValue(numElements);

    OSG_OSB_LOG(("OSBCommonElement::readPtrMultiField: ptrIds ["));

    for(UInt32 i = 0; i < numElements; ++i)
    {
        rh->getValue(ptrId);
        pfi.editIdStore().push_back(ptrId);

        OSG_OSB_PLOG(("%u ", ptrId));
    }

    OSG_OSB_PLOG(("]\n"));

    return --(root->editPtrFieldList().end());
}
/*! Callback called for each element in an AttachmentMap (this is used by
    preWriteAttachmentMapField).
 */
void OSBCommonElement::handleAttachmentMapElementPreWrite(
    FieldContainer *refedFC)
{
    OSG_OSB_LOG(("OSBCommonElement::handleAttachmentMapElementPreWrite\n"));

    if(refedFC == NULL)
        return;

    Attachment *refedAtt = dynamic_cast<Attachment *>(refedFC);

    // skip attachments marked as 'internal'
    if(refedAtt                              == NULL ||
       refedAtt->getSFInternal()->getValue() == true   )
    {
        return;
    }

    OSBRootElement    *root     = editRoot();
    UInt32             refedId  = refedAtt->getId  ();
    const std::string &typeName = refedAtt->getType().getName();

    // only schedule a container once
    if(root->getIdSet().count(refedId) > 0)
        return;

    OSBElementBase *elem = OSBElementFactory::the()->acquire(typeName, root);

    root->editIdSet      ().insert   (refedId);
    root->editElementList().push_back(elem   );
    elem->setContainer(refedAtt);
    elem->preWrite    (refedAtt);
}
/*! Reads a SFFieldContainerPtr (or a more specific pointer type) from the
    stream. It has the given \a fieldId in the container it belongs to.

    \param[in] fieldId Id of the field in the container it belongs to.

    \return Iterator that points to the PtrFieldInfo structure
    that was created for this field.
 */
OSBCommonElement::PtrFieldListIt
OSBCommonElement::readPtrSingleField(const UInt32 fieldId)
{
    OSG_OSB_LOG(("OSBCommonElement::readPtrSingleField: "
            "fieldId: [%u]\n", fieldId));

    OSBRootElement *root  = editRoot();
    UInt32          ptrId;

    root->getReadHandler()->getValue(ptrId);
    
    OSG_OSB_LOG(("OSBCommonElement::readPtrSingleField: ptrId [%u]\n", ptrId));

    root->editPtrFieldList().push_back(PtrFieldInfo(getContainer(), fieldId));
    root->editPtrFieldList().back().editIdStore().push_back(ptrId);

    return --(root->editPtrFieldList().end());
}
/*! Visits a MFFieldContainerPtr (or more specific pointer type) during
    preWrite. It creates elements for the pointed to containers and
    calls preWrite on them. If the pointed to containers are not in the
    root's id set they are added and thus scheduled for writing.

    \param[in] fieldId Id of the field in the container of this element.
 */
void
OSBCommonElement::preWritePtrMultiField(const UInt32 fieldId)
{
    OSG_OSB_LOG(("OSBCommonElement::preWritePtrMultiField: "
            "fieldId: [%u]\n", fieldId));

    OSBRootElement           *root       = editRoot();

    FieldContainerPtrMFieldBase::GetHandlePtr mfPtrField =
        boost::dynamic_pointer_cast<FieldContainerPtrMFieldBase::GetHandle>(
            getContainer()->getField(fieldId));

    if(mfPtrField == NULL || mfPtrField->isValid() == false)
        return;

    FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
        (*mfPtrField)->begin();

    FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
        (*mfPtrField)->end  ();

    for(; fieldIt != fieldEnd; ++fieldIt)
    {
        FieldContainer *refedFC = *fieldIt;

        if(refedFC == NULL)
            continue;

        UInt32             refedId  = refedFC->getId  ();
        const std::string &typeName = refedFC->getType().getName();

        // only schedule a container once
        if(root->getIdSet().count(refedId) > 0)
            continue;

        OSBElementBase *elem = OSBElementFactory::the()->acquire(
            typeName, root);

        root->editIdSet      ().insert   (refedId);
        root->editElementList().push_back(elem   );
        elem->setContainer(refedFC);
        elem->preWrite    (refedFC);
    }
}
/*! Callback called for each element in a map field (this is used by
    preWriteMapField).
 */
void OSBCommonElement::handleMapElementPreWrite(FieldContainer *refedFC)
{
    if(refedFC == NULL)
        return;

    OSBRootElement    *root      = editRoot();
    UInt32             refedId  = refedFC->getId  ();
    const std::string &typeName = refedFC->getType().getName();

    // only schedule a container once
    if(root->getIdSet().count(refedId) > 0)
        return;

    OSBElementBase *elem = OSBElementFactory::the()->acquire(typeName, root);

    root->editIdSet      ().insert   (refedId);
    root->editElementList().push_back(elem   );
    elem->setContainer(refedFC);
    elem->preWrite    (refedFC);
}
/*! Reads from \a inStream which must provide access to an ".osb" file.

    \param[in] inStream Stream to read data from.
    \param[in] optionStr String that holds the options for the read operation.

    \return On success a pointer to the container read from the file.
     NULL otherwise.
 */
FieldContainerTransitPtr
OSBDriver::readFC(      std::istream              &inStream,
                  const IOFileTypeBase::OptionSet &options  )
{
    FieldContainerTransitPtr  retVal;
    OSBRootElement           *root   = dynamic_cast<OSBRootElement *>(
        OSBElementFactory::the()->acquire("RootElement", 0));

    root->initialiseRead(inStream);
    root->editOptions   (        ).init(options);

    root->read    ("");
    root->postRead(  );

    retVal = root->getContainer();

    root->terminateRead();

    OSBElementFactory::the()->release(root);

    return retVal;
}
bool
OSBDriver::writeFC(      FieldContainer * const     fc,
                         std::ostream              &outStream,
                   const IOFileTypeBase::OptionSet &options   )
{
   OSBRootElement *root = dynamic_cast<OSBRootElement *>(
        OSBElementFactory::the()->acquire("RootElement", 0));

    root->initialiseWrite(outStream);
    root->editOptions    (         ).init(options);

    root->preWrite(fc);
    root->write   (  );

    root->terminateWrite();

    OSBElementFactory::the()->release(root);

    return true;
}
void
OSBTextureChunkElement::postRead(void)
{
    OSG_OSB_LOG(("OSBTextureChunkElement::postRead:\n"));
    OSBRootElement *pRoot = editRoot();

    // for the id remapping TexEnv needs an id that is not used in the file
    UInt32 texEnvIdFile = pRoot->getIdMap().rbegin()->first;
    while(pRoot->getIdMap().find(texEnvIdFile) != pRoot->getIdMap().end())
    {
        ++texEnvIdFile;
    }
    
    // add mapping entry for TexEnv
    pRoot->editIdMap()[texEnvIdFile] = _pTexEnv->getId();
    
    PtrFieldListIt ptrFieldIt  = pRoot->editPtrFieldList().begin();
    PtrFieldListIt ptrFieldEnd = pRoot->editPtrFieldList().end  ();

    for(; ptrFieldIt != ptrFieldEnd; ++ptrFieldIt)
    {
        ChunkMaterial *chkMat =
            dynamic_cast<ChunkMaterial *>(ptrFieldIt->getContainer());

        if(chkMat != NULL)
        {
            // OSBChunkMaterialElement takes care of handling the two chunks
            // replacing TextureChunk
            continue;
        }
        else
        {
            UInt32 numIds  = ptrFieldIt->getIdStore     ().size();
            UInt32 numBind = ptrFieldIt->getBindingStore().size();

            if(numBind > 0)
            {
                // TextureChunk is pointed to from an attachment map
                for(UInt32 i = 0; (i < numIds) && (i < numBind); ++i)
                {
                    if(ptrFieldIt->getIdStore()[i] == getFCIdFile())
                    {
                        // insert a pointer to TexEnv right after the TexObj
                        ptrFieldIt->editIdStore().insert(
                            ptrFieldIt->editIdStore().begin() + i + 1,
                            texEnvIdFile                              );

                        // duplicate the binding of the TexObj
                        ptrFieldIt->editBindingStore().insert(
                            ptrFieldIt->editBindingStore().begin() + i + 1,
                            ptrFieldIt->getBindingStore()[i]               );

                        ++numIds;
                        ++numBind;
                    }
                }
            }
            else
            {
                for(UInt32 i = 0; i < numIds; ++i)
                {
                    if(ptrFieldIt->getIdStore()[i] == getFCIdFile())
                    {
                        // insert a pointer to TexEnv right after the TexObj
                        ptrFieldIt->editIdStore().insert(
                            ptrFieldIt->editIdStore().begin() + i + 1,
                            texEnvIdFile                              );

                        ++numIds;
                    }
                }
            }
        }
    }
}
Esempio n. 10
0
void
OSBGeometryElement::postReadV100(void)
{
    OSG_OSB_LOG(("OSBGeometryElement::postReadV100\n"));

    OSBRootElement  *root             = editRoot();
    Geometry        *geo              =
        dynamic_cast<Geometry*>(getContainer());
    UInt32           indexMappingSize = UInt32(_indexMapping.size());

    if(indexMappingSize <= 1)
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting single index.\n"          ));

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));
            geo->setIndices(_indices);
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting non-packed indices.\n"    ));

            // indices stored in container with id _indicesId
            // create PtrFieldInfo structure to set all entries of field
            // "propIndices" to the container with id _indicesId

            FieldDescriptionBase *indFieldDesc =
                geo->getFieldDescription("propIndices");
            UInt32                indFieldId   = indFieldDesc->getFieldId();

            root->editPtrFieldList().push_back(PtrFieldInfo(geo, indFieldId));
            PtrFieldInfo &indFieldPFI = root->editPtrFieldList().back();

            for(UInt32 i = 0; i < Geometry::MaxAttribs; ++i)
            {
                indFieldPFI.editIdStore().push_back(_indicesId);
            }
        }
    }
    else
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting multi index.\n"          ));

        OSBGeometryHelper gh;

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));

            // create 16 bit or 32 bit indices
            if(_indices16Bit)
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                         "Converting non-packed indices.\n"    ));

            FieldContainerIdMapConstIt mapIt =
                root->getIdMap().find(_indicesId);

            if(mapIt != root->getIdMap().end())
            {
                _indices = dynamic_cast<GeoIntegralProperty *>(
                    FieldContainerFactory::the()->getContainer(mapIt->second));
            }
            else
            {
                FWARNING(("OSBGeometryElement::postReadV100: "
                          "Could not find indices property.\n"));
                return;
            }

            if(_indices->getFormatSize() == sizeof(UInt16))
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else if(_indices->getFormatSize() == sizeof(UInt32))
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
    }
}
Esempio n. 11
0
void
OSBGeometryElement::readV100(void)
{
    OSG_OSB_LOG(("OSBGeometryElement::readV100:\n"));

    OSBRootElement    *root = editRoot();
    BinaryReadHandler *rh   = editRoot()->getReadHandler();
    OSBGeometryHelper  gh;

    GeometryUnrecPtr geo = Geometry::create();
    setContainer(geo);

    // The "properties" mfield can be thought of the unification of the
    // "positions", "normals", etc sfields of the 1.x Geometry.
    // For the conversion the PtrFieldInfo structure for the "properties"
    // mfield is filled with the corresponding ids of the sfields from the
    // file. The remapping after postRead will fill in the right pointers.

    FieldDescriptionBase *propFieldDesc =
        geo->getFieldDescription("properties");
    UInt32                propFieldId   = propFieldDesc->getFieldId();

    root->editPtrFieldList().push_back(PtrFieldInfo(geo, propFieldId));
    PtrFieldInfo &propFieldPFI = root->editPtrFieldList().back();

    propFieldPFI.editIdStore().resize(Geometry::MaxAttribs);

    while(true)
    {
        std::string    fieldName;
        std::string    fieldTypeName;
        UInt32         fieldSize;
        PtrFieldListIt ptrFieldIt;

        if(!readFieldHeader("", fieldName, fieldTypeName, fieldSize))
        {
            OSG_OSB_LOG(("OSBGeometryElement::readV100: "
                    "Reading stopped at field: [%s].\n", fieldName.c_str()));
            break;
        }

        if(fieldName == "indexMapping")
        {
            // read into temporary field
            MField<UInt16> indexMappingField;
            indexMappingField.copyFromBin(*rh);

            // copy to member for use in postRead
            indexMappingField.getValues().swap(_indexMapping);
        }
        else if(fieldName == "indices")
        {
            // read container id of indices property
            // postRead will handle the conversion of multi indices
            rh->getValue(_indicesId);
        }
        else if(fieldName == "positions")
        {
            UInt32 positionsId;
            rh->getValue(positionsId);
            propFieldPFI.editIdStore()[Geometry::PositionsIndex] = positionsId;
        }
        else if(fieldName == "normals")
        {
            UInt32 normalsId;
            rh->getValue(normalsId);
            propFieldPFI.editIdStore()[Geometry::NormalsIndex] = normalsId;
        }
        else if(fieldName == "colors")
        {
            UInt32 colorsId;
            rh->getValue(colorsId);
            propFieldPFI.editIdStore()[Geometry::ColorsIndex] = colorsId;
        }
        else if(fieldName == "secondaryColors")
        {
            UInt32 secondaryColorsId;
            rh->getValue(secondaryColorsId);
            propFieldPFI.editIdStore()[Geometry::SecondaryColorsIndex] =
                secondaryColorsId;
        }
        else if(fieldName == "texCoords")
        {
            UInt32 texCoordsId;
            rh->getValue(texCoordsId);
            propFieldPFI.editIdStore()[Geometry::TexCoordsIndex] =
                texCoordsId;
        }
        else if(fieldName == "texCoords1")
        {
            UInt32 texCoordsId1;
            rh->getValue(texCoordsId1);
            propFieldPFI.editIdStore()[Geometry::TexCoords1Index] =
                texCoordsId1;
        }
        else if(fieldName == "texCoords2")
        {
            UInt32 texCoordsId2;
            rh->getValue(texCoordsId2);
            propFieldPFI.editIdStore()[Geometry::TexCoords2Index] =
                texCoordsId2;
        }
        else if(fieldName == "texCoords3")
        {
            UInt32 texCoordsId3;
            rh->getValue(texCoordsId3);
            propFieldPFI.editIdStore()[Geometry::TexCoords3Index] =
                texCoordsId3;
        }
        else if(fieldName == "texCoords4")
        {
            UInt32 texCoordsId4;
            rh->getValue(texCoordsId4);
            propFieldPFI.editIdStore()[Geometry::TexCoords4Index] =
                texCoordsId4;
        }
        else if(fieldName == "texCoords5")
        {
            UInt32 texCoordsId5;
            rh->getValue(texCoordsId5);
            propFieldPFI.editIdStore()[Geometry::TexCoords5Index] =
                texCoordsId5;
        }
        else if(fieldName == "texCoords6")
        {
            UInt32 texCoordsId6;
            rh->getValue(texCoordsId6);
            propFieldPFI.editIdStore()[Geometry::TexCoords6Index] =
                texCoordsId6;
        }
        else if(fieldName == "texCoords7")
        {
            UInt32 texCoordsId7;
            rh->getValue(texCoordsId7);
            propFieldPFI.editIdStore()[Geometry::TexCoords7Index] =
                texCoordsId7;
        }
        else if(fieldName == "pindices")
        {
            UInt32 maxValue;
            UInt32 propSize;
            UInt32 byteSize;

            _indicesPacked = true;

            gh.readPackedIntegralPropertyHeader(rh, maxValue,
                                                propSize, byteSize);

            if(root->getOptions().unpack16BitIndices())
            {
                if(maxValue > TypeTraits<UInt16>::getMax())
                {
                    GeoUInt32PropertyUnrecPtr ui32Indices =
                        GeoUInt32Property::create();
                    gh.readPackedIntegralProperty(rh, ui32Indices, maxValue,
                                                  propSize, byteSize        );

                    _indices16Bit = false;
                    _indices      = ui32Indices;
                }
                else
                {
                    GeoUInt16PropertyUnrecPtr ui16Indices =
                        GeoUInt16Property::create();
                    gh.readPackedIntegralProperty(rh, ui16Indices, maxValue,
                                                  propSize, byteSize        );

                    _indices16Bit = true;
                    _indices      = ui16Indices;
                }
            }
            else
            {
                GeoUInt32PropertyUnrecPtr ui32Indices =
                    GeoUInt32Property::create();
                gh.readPackedIntegralProperty(rh, ui32Indices, maxValue,
                                              propSize, byteSize        );

                _indices16Bit = false;
                _indices      = ui32Indices;
            }
        }
        else if(fieldName == "qpositions")
        {
            // Quantized positions are stored inside the geometry object, not
            // in the geo-property. They are always of type Pnt3f.
            GeoPnt3fPropertyUnrecPtr propPos    = GeoPnt3fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(rh, resolution, minValue,
                                                 maxValue, propSize       );
            gh.readQuantizedVectorProperty(rh, propPos, fieldSize, resolution,
                                           minValue, maxValue, propSize       );

            geo->setProperty(propPos, Geometry::PositionsIndex);
        }
        else if(fieldName == "qnormals")
        {
            // Quantized normals are stored inside the geometry object, not
            // in the geo-property. They are always of type Vec3f.
            GeoVec3fPropertyUnrecPtr propNorm   = GeoVec3fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(
                rh, resolution, minValue, maxValue, propSize);
            gh.readQuantizedVectorProperty(
                rh, propNorm, fieldSize, resolution,
                minValue, maxValue, propSize        );

            geo->setProperty(propNorm, Geometry::NormalsIndex);
        }
        else if(fieldName == "qtexCoords")
        {
            // Quantized texCoords are stored inside the geometry object, not
            // in the geo-property. They are always of type Vec2f.
            GeoVec2fPropertyUnrecPtr propTexCoords = GeoVec2fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(
                rh, resolution, minValue, maxValue, propSize);
            gh.readQuantizedVectorProperty(
                rh, propTexCoords, fieldSize, resolution,
                minValue, maxValue, propSize             );

            geo->setProperty(propTexCoords, Geometry::NormalsIndex);
        }
        else
        {
            // 1.x Geometry has _sfVbo, it can be skipped

            readFieldContent(fieldName, fieldTypeName, fieldSize,
                             "'vbo'", ptrFieldIt                      );
        }
    }
}
Esempio n. 12
0
void
OSBGeometryElement::preWrite(FieldContainer * const fc)
{
    OSG_OSB_LOG(("OSBGeometryElement::preWrite\n"));

    OSBRootElement *root       = editRoot();
    UInt32          fieldCount = fc->getType().getNumFieldDescs();

    UInt8 quanResPositions = root->getOptions().quantizePositions();
    UInt8 quanResNormals   = root->getOptions().quantizeNormals  ();
    UInt8 quanResTexCoords = root->getOptions().quantizeTexCoords();
    bool  packIndices      = root->getOptions().packIndices      ();

    // go through all fields and find those refering to other FCs
    for(UInt32 fieldId = 1; fieldId <= fieldCount; ++fieldId)
    {
        const FieldDescriptionBase *fieldDesc = fc->getFieldDescription(fieldId);
        const FieldType            &fieldType = fieldDesc->getFieldType();
        const std::string          &fieldName = fieldDesc->getName     ();

        // skip internal fields
        if(fieldDesc->isInternal())
        {
            OSG_OSB_LOG(("OSBGeometryElement::preWrite: "
                    "Skipping internal field: [%s]\n", fieldName.c_str()));
            continue;
        }

        if(fieldName == "properties")
        {
            // "properties" might be quantized
            FieldContainerPtrMFieldBase::GetHandlePtr fP =
                boost::dynamic_pointer_cast<
                    FieldContainerPtrMFieldBase::GetHandle>(
                        getContainer()->getField(fieldId));

            if(fP == NULL || fP->isValid() == false)
                continue;

            FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
                (*fP)->begin();

            FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
                (*fP)->end  ();

            for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
            {
                FieldContainer *refedFC = *fieldIt;

                if(refedFC == NULL)
                    continue;

                      UInt32      refedId  = refedFC->getId  ();
                const std::string typeName = refedFC->getType().getName();

                // only schedule a container once
                if(root->getIdSet().count(refedId) > 0)
                    continue;

                OSBElementBase              *elem     =
                    OSBElementFactory::the()->acquire(typeName, root);
                OSBGeoVectorPropertyElement *propElem =
                    dynamic_cast<OSBGeoVectorPropertyElement *>(elem);

                if((propElem != 0) && (i == Geometry::PositionsIndex))
                {
                    propElem->setQuantizeResolution(quanResPositions);
                }
                else if((propElem != 0) && (i == Geometry::NormalsIndex))
                {
                    propElem->setQuantizeResolution(quanResNormals);
                }
                else if((propElem != 0) && (i >= Geometry::TexCoordsIndex) &&
                        (i <= Geometry::TexCoords7Index)                     )
                {
                    propElem->setQuantizeResolution(quanResTexCoords);
                }

                root->editIdSet      ().insert   (refedId);
                root->editElementList().push_back(elem   );
                elem->setContainer(refedFC);
                elem->preWrite    (refedFC);
            }
        }
        else if(fieldName == "propIndices")
        {
            // "propIndices" might be packed
            FieldContainerPtrMFieldBase::GetHandlePtr fP =
                boost::dynamic_pointer_cast<
                    FieldContainerPtrMFieldBase::GetHandle>(
                        getContainer()->getField(fieldId));

            if(fP == NULL || fP->isValid() == false)
                continue;

            FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
                (*fP)->begin();
            FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
                (*fP)->end  ();

            for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
            {
                FieldContainer *refedFC = *fieldIt;

                if(refedFC == NULL)
                    continue;

                      UInt32      refedId  = refedFC->getId  ();
                const std::string typeName = refedFC->getType().getName();

                // only schedule a container once
                if(root->getIdSet().count(refedId) > 0)
                    continue;

                OSBElementBase                *elem     =
                    OSBElementFactory::the()->acquire(typeName, root);
                OSBGeoIntegralPropertyElement *propElem =
                    dynamic_cast<OSBGeoIntegralPropertyElement *>(elem);

                if((propElem != 0) && (packIndices == true))
                {
                    propElem->setPackData(true);
                }

                root->editIdSet      ().insert   (refedId);
                root->editElementList().push_back(elem   );
                elem->setContainer(refedFC);
                elem->preWrite    (refedFC);
            }
        }
        else if(fieldName == "attachments")
        {
            preWriteAttachmentMapField(fieldId);
        }
        else
        {
            // check if field refers to another FC, i.e. its a field holding
            // FieldContainerPtr or an FieldContainerAttachmentMap
            if(fieldType.getContentType().isDerivedFrom(
                FieldTraits<FieldContainer *>::getType()) == true)
            {
                if(fieldType.getCardinality() == FieldType::SingleField)
                {
                    preWritePtrSingleField(fieldId);
                }
                else if(fieldType.getCardinality() == FieldType::MultiField)
                {
                    preWritePtrMultiField(fieldId);
                }
            }
        }
    }
}
/*! Reads a SFFieldContainerAttachmentPtrMap from the stream. It has the
    given \a fieldId in the container it belongs to and size \a fieldSize.

    \param[in] fieldId Id of the field in the container it belongs to.
    \param[in] fieldSize Size in byte of the field.

    \return Iterator that points to the PtrFieldInfo structure
    that was created for this field.
 */
OSBCommonElement::PtrFieldListIt
OSBCommonElement::readAttachmentMapField(
    const UInt32 fieldId, const UInt32 fieldSize)
{
    OSG_OSB_LOG(("OSBCommonElement::readAttachmentMapField: "
            "fieldId: [%u]\n", fieldId));

    bool               hasBindingInfo = false;
    UInt32             ptrId;
    UInt32             numElements;
    OSBRootElement    *root           = editRoot();
    BinaryReadHandler *rh             = editRoot()->getReadHandler();

    root->editPtrFieldList().push_back(PtrFieldInfo(getContainer(), fieldId));

    PtrFieldInfo &pfi = root->editPtrFieldList().back();

    rh->getValue(numElements);

    // keep these ordered from highest to lowest version
    if(root->getHeaderVersion() >= OSGOSBHeaderVersion200)
    {
        if(root->getHeaderVersion() > OSGOSBHeaderVersion200)
        {
            FINFO(("OSBCommonElement::readAttachmentMapField: "
                   "Unknown header version, trying to read as latest.\n"));
        }
    
        hasBindingInfo = true;
    }
    else if(root->getHeaderVersion() >= OSGOSBHeaderVersion100)
    {
        // distinguish format with or without binding info
        if(fieldSize == (sizeof(UInt32) + numElements * sizeof(UInt32)))
        {
            hasBindingInfo = false;
        }
        else
        {
            hasBindingInfo = true;
        }
    }

    if(hasBindingInfo == true)
    {
        OSG_OSB_LOG(("OSBCommonElement::readAttachmentMapField: "
                "reading [%u] attachments with binding info.\n", numElements));
    
        EditMapFieldHandlePtr sfMapField =
            boost::dynamic_pointer_cast<EditMapFieldHandle>(
                getContainer()->editField(fieldId));

        if(sfMapField == NULL || sfMapField->isValid() == false)
            return --(root->editPtrFieldList().end());

        pfi.setHandledField(sfMapField->loadFromBin(rh,
                                                    numElements,
                                                    hasBindingInfo,
                                                    pfi.editBindingStore(),
                                                    pfi.editIdStore     ()));
#if 0
        for(UInt32 i = 0; i < numElements; ++i)
        {
            rh->getValue(binding);
            rh->getValue(ptrId  );

            OSG_OSB_LOG(("OSBCommonElement::readAttachmentMapField: "
                    "attachment [%u], binding [%u], id [%u].\n",
                    i, binding, ptrId));

            pfi.editBindingStore().push_back(binding);
            pfi.editIdStore     ().push_back(ptrId  );
        }
#endif
    }
    else
    {
        OSG_OSB_LOG(("OSBCommonElement::readAttachmentMapField: "
                "reading [%u] attachments without binding info.\n", 
                numElements));
    
        for(UInt32 i = 0; i < numElements; ++i)
        {
            rh->getValue(ptrId);
            
            OSG_OSB_LOG(("OSBCommonElement::readAttachmentMapField: "
                    "attachment [%u], id [%u].\n", i, ptrId));
                    
            pfi.editBindingStore().push_back(0    );
            pfi.editIdStore     ().push_back(ptrId);
        }
    }

    return --(root->editPtrFieldList().end());
}