root/OpenSceneGraph/trunk/src/osgPlugins/ive/ImageSequence.cpp @ 13191

Revision 13191, 2.7 kB (checked in by robert, 65 minutes ago)

From Jannik Heller, "I've hit what I believe to be a bug (or at the very least, an unintuitive behaviour) in the osg::Geometry copy constructor. I noticed it when using osg::clone on a Geometry with vertex buffer objects, and the copy flags DEEP_COPY_ARRAYS. To be precise, I add a Geometry to an osgUtil::IncrementalCompileOperation?, then osg::clone the Geometry. I was getting reports from users of random crashes happening.

I believe the offending lines are in the osg::Geometry copy constructor:

if ((copyop.getCopyFlags() & osg::CopyOp::DEEP_COPY_ARRAYS))
{

if (_useVertexBufferObjects)
{

// copying of arrays doesn't set up buffer objects so we'll need to force
// Geometry to assign these, we'll do this by switching off VBO's then renabling them.
setUseVertexBufferObjects(false);
setUseVertexBufferObjects(true);

}

}

Toggling the vertex buffer objects off then on again actually touches not only the arrays controlled by DEEP_COPY_ARRAYS, but also the PrimitiveSets? which are controlled by DEEP_COPY_PRIMITIVES. This means if the user has copyflags of only DEEP_COPY_ARRAYS, we are modifying arrays that belong to the original const Geometry& we are copying from. I believe this shouldn't be allowed to happen because we are using a const& specifier for the original Geometry.

In my case the osgUtil::IncrementalCompileOperation? was trying to compile the geometry, while in the main thread a clone operation toggled the VBO's off and on, a crash ensues.

In the attached patch, you will find a more efficient handling of VBO's in the osg::Geometry copy constructor, so that only the Arrays that were actually deep copied have their VBO assigned, and no changes are made to Arrays that already had a valid VBO assigned. In addition, the DEEP_COPY_PRIMITIVES flag is now honored so that VBO's are set up correctly should a user copy a Geometry with only that flag.
"

  • Property svn:eol-style set to native
Line 
1/**********************************************************************
2 *
3 *    FILE:            Image.cpp
4 *
5 *    DESCRIPTION:    Read/Write osg::Image in binary format to disk.
6 *
7 *    CREATED BY:        Auto generated by iveGenerated
8 *                    and later modified by Rune Schmidt Jensen.
9 *
10 *    HISTORY:        Created 20.3.2003
11 *
12 *    Copyright 2003 VR-C
13 **********************************************************************/
14
15#include "Exception.h"
16#include "ImageSequence.h"
17#include "Object.h"
18
19#include <osg/Notify>
20
21using namespace ive;
22
23void ImageSequence::write(DataOutputStream* out)
24{
25    // Write ImageSequence's identification.
26    out->writeInt(IVEIMAGESEQUENCE);
27    // If the osg class is inherited by any other class we should also write this to file.
28    osg::Object*  obj = dynamic_cast<osg::Object*>(this);
29    if(obj){
30        ((ive::Object*)(obj))->write(out);
31    }
32    else
33        out_THROW_EXCEPTION("ImageSequence::write(): Could not cast this osg::ImageSequence to an osg::Object.");
34    // Write ImageSequence's properties.
35
36
37    out->writeInt(getMode());
38    out->writeDouble(getLength());
39
40    out->writeUInt(getImageDataList().size());
41    for(ImageDataList::iterator itr = getImageDataList().begin();
42        itr != getImageDataList().end();
43        ++itr)
44    {
45        out->writeString(itr->_filename);
46    }
47
48    if (getImageDataList().empty())
49    {
50        out->writeUInt(0);
51    }
52
53}
54
55void ImageSequence::read(DataInputStream* in)
56{
57    // Peek ImageSequence's identification.
58    int id = in->peekInt();
59    if(id == IVEIMAGESEQUENCE){
60        // Read ImageSequence's identification.
61        id = in->readInt();
62        // If the osg class is inherited by any other class we should also read this from file.
63        osg::Object*  obj = dynamic_cast<osg::Object*>(this);
64        if(obj){
65            ((ive::Object*)(obj))->read(in);
66        }
67        else
68            in_THROW_EXCEPTION("ImageSequence::read(): Could not cast this osg::ImageSequence to an osg::Object.");
69        // Read ImageSequence's properties.
70
71
72        setMode((osg::ImageSequence::Mode)(in->readInt()));
73        setLength(in->readDouble());
74
75        unsigned int numFileNames = in->readUInt();
76        if (numFileNames>0)
77        {
78            for(unsigned int i=0; i<numFileNames; ++i)
79            {
80                addImageFile(in->readString());
81            }
82        }
83        else
84        {
85            unsigned int numImages = in->readUInt();
86            for(unsigned int i=0; i<numImages; ++i)
87            {
88                addImage(in->readImage());
89            }
90        }
91
92    }
93    else{
94        in_THROW_EXCEPTION("ImageSequence::read(): Expected ImageSequence identification.");
95    }
96}
Note: See TracBrowser for help on using the browser.