diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ef63dfb7b..e517e7784 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -78,6 +78,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgslice) ADD_SUBDIRECTORY(osgspacewarp) ADD_SUBDIRECTORY(osgspheresegment) + ADD_SUBDIRECTORY(osgsharedarray) ADD_SUBDIRECTORY(osgspotlight) ADD_SUBDIRECTORY(osgstereoimage) ADD_SUBDIRECTORY(osgteapot) diff --git a/examples/osgsharedarray/CMakeLists.txt b/examples/osgsharedarray/CMakeLists.txt new file mode 100644 index 000000000..3c5af6861 --- /dev/null +++ b/examples/osgsharedarray/CMakeLists.txt @@ -0,0 +1,7 @@ +#this file is automatically generated + + +SET(TARGET_SRC osgsharedarray.cpp ) +SET(TARGET_EXTERNAL_LIBRARIES ${OPENGL_LIBRARIES} ) +#### end var setup ### +SETUP_EXAMPLE(osgsharedarray) diff --git a/examples/osgsharedarray/osgsharedarray.cpp b/examples/osgsharedarray/osgsharedarray.cpp new file mode 100644 index 000000000..b33bc03e5 --- /dev/null +++ b/examples/osgsharedarray/osgsharedarray.cpp @@ -0,0 +1,246 @@ +/* OpenSceneGraph example, osgsharedarray. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include +#include +#include +#include + +/** This class is an example of how to create your own subclass of osg::Array. This + * is useful if your application has data in its own form of storage and you don't + * want to make another copy into one of the predefined osg::Array classes. + * + * @note This is not really intended to be a useful subclass of osg::Array. It + * doesn't do anything smart about memory management. It is simply intended as + * an example you can follow to create your own subclasses of osg::Array for + * your application's storage requirements. + */ +class MyArray : public osg::Array { +public: + /** Default ctor. Creates an empty array. */ + MyArray() : + osg::Array(osg::Array::Vec3ArrayType,3,GL_FLOAT), + _numElements(0), + _ptr(NULL) { + } + + /** "Normal" ctor. + * + * @param no The number of elements in the array. + * @param ptr Pointer to the data. This class just keeps that + * pointer. It doesn't manage the memory. + */ + MyArray(unsigned int no, osg::Vec3* ptr) : + osg::Array(osg::Array::Vec3ArrayType,3,GL_FLOAT), + _numElements(no), + _ptr(ptr) { + } + + /** Copy ctor. */ + MyArray(const MyArray& other, const osg::CopyOp& copyop) : + osg::Array(osg::Array::Vec3ArrayType,3,GL_FLOAT), + _numElements(other._numElements), + _ptr(other._ptr) { + } + + /** What type of object would clone return? */ + virtual Object* cloneType() const { + return new MyArray(); + } + + /** Create a copy of the object. */ + virtual osg::Object* clone(const osg::CopyOp& copyop) const { + return new MyArray(*this,copyop); + } + + /** Accept method for ArrayVisitors. + * + * @note This will end up in ArrayVisitor::apply(osg::Array&). + */ + virtual void accept(osg::ArrayVisitor& av) { + av.apply(*this); + } + + /** Const accept method for ArrayVisitors. + * + * @note This will end up in ConstArrayVisitor::apply(const osg::Array&). + */ + virtual void accept(osg::ConstArrayVisitor& cav) const { + cav.apply(*this); + } + + /** Accept method for ValueVisitors. */ + virtual void accept(unsigned int index, osg::ValueVisitor& vv) { + vv.apply(_ptr[index]); + } + + /** Const accept method for ValueVisitors. */ + virtual void accept(unsigned int index, osg::ConstValueVisitor& cvv) const { + cvv.apply(_ptr[index]); + } + + /** Compare method. + * Return -1 if lhs element is less than rhs element, 0 if equal, + * 1 if lhs element is greater than rhs element. + */ + virtual int compare(unsigned int lhs,unsigned int rhs) const { + const osg::Vec3& elem_lhs = _ptr[lhs]; + const osg::Vec3& elem_rhs = _ptr[rhs]; + if (elem_lhs geom(new osg::Geometry()); + + // add vertices using MyArray class + unsigned int numVertices = sizeof(myVertices)/sizeof(myVertices[0]); + geom->setVertexArray(new MyArray(numVertices,const_cast(&myVertices[0]))); + + // add normals + unsigned int numNormals = sizeof(myNormals)/sizeof(myNormals[0]); + geom->setNormalArray(new osg::Vec3Array(numNormals,const_cast(&myNormals[0]))); + geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); + + // add colors + unsigned int numColors = sizeof(myColors)/sizeof(myColors[0]); + osg::Vec4Array* normal_array = new osg::Vec4Array(numColors,const_cast(&myColors[0])); + geom->setColorArray(normal_array); + geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); + + // add PrimitiveSet + unsigned int numIndices = sizeof(myIndices)/sizeof(myIndices[0]); + geom->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS, + numIndices, + const_cast(myIndices))); + + // Changing these flags will tickle different cases in + // Geometry::drawImplementation. They should all work fine + // with the shared array. Setting VertexIndices will hit + // some other cases. + geom->setUseVertexBufferObjects(false); + geom->setUseDisplayList(false); + geom->setFastPathHint(false); + + geode->addDrawable( geom.get() ); + + return geode; +} + +int main(int , char **) +{ + // construct the viewer. + osgViewer::Viewer viewer; + + // add model to viewer. + viewer.setSceneData( createGeometry() ); + + // create the windows and run the threads. + return viewer.run(); +} diff --git a/include/osg/Array b/include/osg/Array index 7d6f10616..58063d42b 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -229,6 +229,8 @@ class TemplateArray : public Array, public std::vector virtual unsigned int getTotalDataSize() const { return this->size()*sizeof(T); } virtual unsigned int getNumElements() const { return this->size(); } + typedef T ElementDataType; // expose T + protected: virtual ~TemplateArray() {} @@ -315,6 +317,8 @@ class TemplateIndexArray : public IndexArray, public std::vector virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } + typedef T ElementDataType; // expose T + protected: virtual ~TemplateIndexArray() {} diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 608595dc6..b93a3a30c 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -33,15 +33,13 @@ class DrawVertex inline unsigned int index(unsigned int pos) { - switch(_indicesType) + if (_indices) { - case(Array::ByteArrayType): return (*static_cast(_indices))[pos]; - case(Array::ShortArrayType): return (*static_cast(_indices))[pos]; - case(Array::IntArrayType): return (*static_cast(_indices))[pos]; - case(Array::UByteArrayType): return (*static_cast(_indices))[pos]; - case(Array::UShortArrayType): return (*static_cast(_indices))[pos]; - case(Array::UIntArrayType): return (*static_cast(_indices))[pos]; - default: return 0; + return _indices->index(pos); + } + else + { + return 0; } } @@ -52,22 +50,22 @@ class DrawVertex switch(_verticesType) { case(Array::Vec3ArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; case(Array::Vec2ArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; case(Array::Vec4ArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; case(Array::Vec3dArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; case(Array::Vec2dArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; case(Array::Vec4dArrayType): - apply((*(static_cast(_vertices)))[pos]); + apply(static_cast(_vertices->getDataPointer())[pos]); break; default: break; @@ -105,39 +103,53 @@ class DrawNormal { case (Array::Vec3ArrayType): { - const Vec3Array& normals = *static_cast(_normals); + const Vec3* normals(static_cast(_normals->getDataPointer())); if (_indices) glNormal3fv(normals[_indices->index(pos)].ptr()); else glNormal3fv(normals[pos].ptr()); } break; case (Array::Vec3sArrayType): { - const Vec3sArray& normals = *static_cast(_normals); + const Vec3s* normals(static_cast(_normals->getDataPointer())); if (_indices) glNormal3sv(normals[_indices->index(pos)].ptr()); else glNormal3sv(normals[pos].ptr()); } break; case (Array::Vec4sArrayType): { - const Vec4sArray& normals = *static_cast(_normals); + const Vec4s* normals(static_cast(_normals->getDataPointer())); if (_indices) glNormal3sv(normals[_indices->index(pos)].ptr()); else glNormal3sv(normals[pos].ptr()); } break; case (Array::Vec3bArrayType): { - const Vec3bArray& normals = *static_cast(_normals); + const Vec3b* normals(static_cast(_normals->getDataPointer())); if (_indices) glNormal3bv((const GLbyte*)normals[_indices->index(pos)].ptr()); else glNormal3bv((const GLbyte*)normals[pos].ptr()); } break; case (Array::Vec4bArrayType): { - const Vec4bArray& normals = *static_cast(_normals); + const Vec4b* normals(static_cast(_normals->getDataPointer())); if (_indices) glNormal3bv((const GLbyte*)normals[_indices->index(pos)].ptr()); else glNormal3bv((const GLbyte*)normals[pos].ptr()); } break; + case (Array::Vec3dArrayType): + { + const Vec3d* normals(static_cast(_normals->getDataPointer())); + if (_indices) glNormal3dv(normals[_indices->index(pos)].ptr()); + else glNormal3dv(normals[pos].ptr()); + } + break; + case (Array::Vec4dArrayType): + { + const Vec4d* normals(static_cast(_normals->getDataPointer())); + if (_indices) glNormal3dv(normals[_indices->index(pos)].ptr()); + else glNormal3dv(normals[pos].ptr()); + } + break; default: break; @@ -163,15 +175,11 @@ class DrawColor inline unsigned int index(unsigned int pos) { - switch(_indicesType) - { - case(Array::ByteArrayType): return (*static_cast(_indices))[pos]; - case(Array::ShortArrayType): return (*static_cast(_indices))[pos]; - case(Array::IntArrayType): return (*static_cast(_indices))[pos]; - case(Array::UByteArrayType): return (*static_cast(_indices))[pos]; - case(Array::UShortArrayType): return (*static_cast(_indices))[pos]; - case(Array::UIntArrayType): return (*static_cast(_indices))[pos]; - default: return 0; + if (_indices) { + return _indices->index(pos); + } + else { + return 0; } } @@ -182,13 +190,19 @@ class DrawColor switch(_colorsType) { case(Array::Vec4ArrayType): - apply((*static_cast(_colors))[pos]); + apply(static_cast(_colors->getDataPointer())[pos]); break; case(Array::Vec4ubArrayType): - apply((*static_cast(_colors))[pos]); + apply(static_cast(_colors->getDataPointer())[pos]); break; case(Array::Vec3ArrayType): - apply((*static_cast(_colors))[pos]); + apply(static_cast(_colors->getDataPointer())[pos]); + break; + case(Array::Vec3dArrayType): + apply(static_cast(_colors->getDataPointer())[pos]); + break; + case(Array::Vec4dArrayType): + apply(static_cast(_colors->getDataPointer())[pos]); break; default: break; @@ -2220,32 +2234,32 @@ void Geometry::accept(PrimitiveFunctor& functor) const } else { - const Vec2Array* vec2Array = 0; - const Vec3Array* vec3Array = 0; - const Vec4Array* vec4Array = 0; - const Vec2dArray* vec2dArray = 0; - const Vec3dArray* vec3dArray = 0; - const Vec4dArray* vec4dArray = 0; + const Vec2* vec2Array = 0; + const Vec3* vec3Array = 0; + const Vec4* vec4Array = 0; + const Vec2d* vec2dArray = 0; + const Vec3d* vec3dArray = 0; + const Vec4d* vec4dArray = 0; Array::Type type = _vertexData.array->getType(); switch(type) { case(Array::Vec2ArrayType): - vec2Array = static_cast(_vertexData.array.get()); + vec2Array = static_cast(_vertexData.array->getDataPointer()); break; case(Array::Vec3ArrayType): - vec3Array = static_cast(_vertexData.array.get()); + vec3Array = static_cast(_vertexData.array->getDataPointer()); break; case(Array::Vec4ArrayType): - vec4Array = static_cast(_vertexData.array.get()); + vec4Array = static_cast(_vertexData.array->getDataPointer()); break; case(Array::Vec2dArrayType): - vec2dArray = static_cast(_vertexData.array.get()); + vec2dArray = static_cast(_vertexData.array->getDataPointer()); break; case(Array::Vec3dArrayType): - vec3dArray = static_cast(_vertexData.array.get()); + vec3dArray = static_cast(_vertexData.array->getDataPointer()); break; case(Array::Vec4dArrayType): - vec4dArray = static_cast(_vertexData.array.get()); + vec4dArray = static_cast(_vertexData.array->getDataPointer()); break; default: notify(WARN)<<"Warning: Geometry::accept(PrimitiveFunctor&) cannot handle Vertex Array type"<<_vertexData.array->getType()<index(vindex)]); + functor.vertex(vec2Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec3ArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec4ArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec2dArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec3dArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec4dArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]); break; default: break; @@ -2317,22 +2331,22 @@ void Geometry::accept(PrimitiveFunctor& functor) const switch(type) { case(Array::Vec2ArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec3ArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec4ArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec2dArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec3dArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec4dArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]); break; default: break; @@ -2359,22 +2373,22 @@ void Geometry::accept(PrimitiveFunctor& functor) const switch(type) { case(Array::Vec2ArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec3ArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec4ArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec2dArrayType): - functor.vertex((*vec2dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec3dArrayType): - functor.vertex((*vec3dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec4dArrayType): - functor.vertex((*vec4dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]); break; default: break; @@ -2397,22 +2411,22 @@ void Geometry::accept(PrimitiveFunctor& functor) const switch(type) { case(Array::Vec2ArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec3ArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec4ArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec2dArrayType): - functor.vertex((*vec2dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec3dArrayType): - functor.vertex((*vec3dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec4dArrayType): - functor.vertex((*vec4dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]); break; default: break; @@ -2435,22 +2449,22 @@ void Geometry::accept(PrimitiveFunctor& functor) const switch(type) { case(Array::Vec2ArrayType): - functor.vertex((*vec2Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec3ArrayType): - functor.vertex((*vec3Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec4ArrayType): - functor.vertex((*vec4Array)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4Array[_vertexData.indices->index(vindex)]); break; case(Array::Vec2dArrayType): - functor.vertex((*vec2dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec2dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec3dArrayType): - functor.vertex((*vec3dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec3dArray[_vertexData.indices->index(vindex)]); break; case(Array::Vec4dArrayType): - functor.vertex((*vec4dArray)[_vertexData.indices->index(vindex)]); + functor.vertex(vec4dArray[_vertexData.indices->index(vindex)]); break; default: break; @@ -2889,8 +2903,11 @@ class ExpandIndexedArray : public osg::ConstArrayVisitor virtual ~ExpandIndexedArray() {} + // Create when both of the arrays are predefined templated classes. We + // can do some optimizations in this case that aren't possible in the general + // case. template - T* create(const T& array,const I& indices) + T* create_inline(const T& array,const I& indices) { T* newArray = 0; @@ -2919,22 +2936,84 @@ class ExpandIndexedArray : public osg::ConstArrayVisitor return newArray; } + // Create when one of the arrays isn't one of the predefined templated classes. The + // template parameter is the type of the array that will get created. This is always + // one of the predefined classes. We could call clone to get one of the same type as + // the input array, but the interface of the osg::Array class doesn't include a way + // to set an element. template - T* create(const T& array) + osg::Array* create_noinline(const osg::Array& array, const osg::IndexArray& indices) { + T* newArray = 0; + typedef typename T::ElementDataType EDT; + + unsigned int num_indices = indices.getNumElements(); + newArray = new T(num_indices); + + const EDT* src = static_cast(array.getDataPointer()); + + for(unsigned int i=0;i(array,indices); + case(osg::Array::ShortArrayType): return create_noinline(array,indices); + case(osg::Array::IntArrayType): return create_noinline(array,indices); + case(osg::Array::UByteArrayType): return create_noinline(array,indices); + case(osg::Array::UShortArrayType): return create_noinline(array,indices); + case(osg::Array::UIntArrayType): return create_noinline(array,indices); + case(osg::Array::Vec4ubArrayType): return create_noinline(array,indices); + case(osg::Array::FloatArrayType): return create_noinline(array,indices); + case(osg::Array::Vec2ArrayType): return create_noinline(array,indices); + case(osg::Array::Vec3ArrayType): return create_noinline(array,indices); + case(osg::Array::Vec4ArrayType): return create_noinline(array,indices); + case(osg::Array::Vec2dArrayType): return create_noinline(array,indices); + case(osg::Array::Vec3dArrayType): return create_noinline(array,indices); + case(osg::Array::Vec4dArrayType): return create_noinline(array,indices); + default: + return NULL; + } + } + + template + osg::Array* create(const TA& array, const osg::IndexArray& indices) { + // We know that indices.getType returned the same thing as TI, but + // we need to determine whether it is really an instance of TI, or + // perhaps another subclass of osg::Array that contains the same + // type of data. + const TI* ba(dynamic_cast(&indices)); + if (ba != NULL) { + return create_inline(array,*ba); + } + else { + return create_noinline(array, _indices); + } + } + + template + osg::Array* create(const T& array) { switch(_indices.getType()) { - case(osg::Array::ByteArrayType): return create(array,static_cast(_indices)); - case(osg::Array::ShortArrayType): return create(array,static_cast(_indices)); - case(osg::Array::IntArrayType): return create(array,static_cast(_indices)); - case(osg::Array::UByteArrayType): return create(array,static_cast(_indices)); - case(osg::Array::UShortArrayType): return create(array,static_cast(_indices)); - case(osg::Array::UIntArrayType): return create(array,static_cast(_indices)); - default: return 0; + case(osg::Array::ByteArrayType): return create(array, _indices); + case(osg::Array::ShortArrayType): return create(array, _indices); + case(osg::Array::IntArrayType): return create(array, _indices); + case(osg::Array::UByteArrayType): return create(array, _indices); + case(osg::Array::UShortArrayType): return create(array, _indices); + case(osg::Array::UIntArrayType): return create(array, _indices); + default: + return create_noinline(array, _indices); } } + // applys for the predefined classes go through 1-arg create to do indexing virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); } virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); } virtual void apply(const osg::IntArray& array) { _targetArray = create(array); } @@ -2947,6 +3026,9 @@ class ExpandIndexedArray : public osg::ConstArrayVisitor virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); } virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); } + // other subclasses of osg::Array end up here + virtual void apply(const osg::Array& array) { _targetArray = create_noinline(array, _indices); } + const osg::IndexArray& _indices; osg::Array* _targetArray; }; diff --git a/src/osgDB/FileNameUtils.cpp b/src/osgDB/FileNameUtils.cpp index 9647882b5..e60f3d155 100644 --- a/src/osgDB/FileNameUtils.cpp +++ b/src/osgDB/FileNameUtils.cpp @@ -14,6 +14,7 @@ #include #include +#include #ifdef WIN32 #include @@ -238,9 +239,34 @@ std::string osgDB::concatPaths(const std::string& left, const std::string& right std::string osgDB::getRealPath(const std::string& path) { #if defined(WIN32) && !defined(__CYGWIN__) - TCHAR retbuf[MAX_PATH + sizeof(TCHAR)]; - GetFullPathName(path.c_str(), sizeof(retbuf), retbuf, 0); - return std::string(retbuf); + // Not unicode compatible should give an error if UNICODE defined + char retbuf[MAX_PATH + 1]; + char tempbuf1[MAX_PATH + 1]; + GetFullPathName(path.c_str(), sizeof(retbuf), retbuf, NULL); + // Force drive letter to upper case + if ((retbuf[1] == ':') && islower(retbuf[0])) + retbuf[0] = _toupper(retbuf[0]); + if (fileExists(std::string(retbuf))) + { + // Canonicalise the full path + GetShortPathName(retbuf, tempbuf1, sizeof(tempbuf1)); + GetLongPathName(tempbuf1, retbuf, sizeof(retbuf)); + return std::string(retbuf); + } + else + { + // Canonicalise the directories + std::string FilePath = getFilePath(retbuf); + char tempbuf2[MAX_PATH + 1]; + if (0 == GetShortPathName(FilePath.c_str(), tempbuf1, sizeof(tempbuf1))) + return std::string(retbuf); + if (0 == GetLongPathName(tempbuf1, tempbuf2, sizeof(tempbuf2))) + return std::string(retbuf); + FilePath = std::string(tempbuf2); + FilePath.append("\\"); + FilePath.append(getSimpleFileName(std::string(retbuf))); + return FilePath; + } #else char resolved_path[PATH_MAX]; char* result = realpath(path.c_str(), resolved_path);