diff --git a/src/osgDB/FileNameUtils.cpp b/src/osgDB/FileNameUtils.cpp index 3bdd411e2..50bd3ad59 100644 --- a/src/osgDB/FileNameUtils.cpp +++ b/src/osgDB/FileNameUtils.cpp @@ -31,9 +31,13 @@ using namespace std; +static const char * const PATH_SEPARATORS = "/\\"; +static unsigned int PATH_SEPARATORS_LEN = 2; + + std::string osgDB::getFilePath(const std::string& fileName) { - std::string::size_type slash = fileName.find_last_of("/\\"); + std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (slash==std::string::npos) return std::string(); else return std::string(fileName, 0, slash); } @@ -41,7 +45,7 @@ std::string osgDB::getFilePath(const std::string& fileName) std::string osgDB::getSimpleFileName(const std::string& fileName) { - std::string::size_type slash = fileName.find_last_of("/\\"); + std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (slash==std::string::npos) return fileName; else return std::string(fileName.begin()+slash+1,fileName.end()); } @@ -50,7 +54,7 @@ std::string osgDB::getSimpleFileName(const std::string& fileName) std::string osgDB::getFileExtension(const std::string& fileName) { std::string::size_type dot = fileName.find_last_of('.'); - std::string::size_type slash = fileName.find_last_of("/\\"); + std::string::size_type slash = fileName.find_last_of(PATH_SEPARATORS); if (dot==std::string::npos || (slash!=std::string::npos && dot slash) + std::string operator*() { - slash = backslash; + if (!valid()) return std::string(); + return std::string(start, stop); } - if (from.empty() || from.length() > to.length()) - return osgDB::getSimpleFileName(to); +protected: + std::string::const_iterator end; ///< End of path string + std::string::const_iterator start; ///< Points to the first char of an element, or ==end() if no more + std::string::const_iterator stop; ///< Points to the separator after 'start', or ==end() - std::string::const_iterator itTo = to.begin(); - for (std::string::const_iterator itFrom = from.begin(); - itFrom != from.end(); ++itFrom, ++itTo) + /// Iterate until 'it' points to something different from a separator + std::string::const_iterator skipSeparators(std::string::const_iterator it) { - char a = tolower(*itFrom), b = tolower(*itTo); - if (a == '\\') a = '/'; - if (b == '\\') b = '/'; - if (a != b || itTo == to.begin() + slash + 1) - { - return osgDB::getSimpleFileName(to); - } + for (; it!=end && std::find_first_of(it, it+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != it+1; ++it) {} + return it; } - while (itTo != to.end() && (*itTo == '\\' || *itTo == '/')) + std::string::const_iterator next(std::string::const_iterator it) { - ++itTo; + return std::find_first_of(it, end, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN); } +}; - return std::string(itTo, to.end()); +/// Gets root part of a path, or an empty string if none found +std::string getPathRoot(const std::string& path) { + // Test for unix root + if (path.empty()) return ""; + if (path[0] == '/') return "/"; + // Now test for Windows root + if (path.length()<2) return ""; + if (path[1] == ':') return path.substr(0, 2); // We should check that path[0] is a letter, but as ':' is invalid in paths in other cases, that's not a problem. + return ""; } -//std::string testA = getPathRelative("C:\\a\\b", "C:\\a/b/d/f"); -//std::string testB = getPathRelative("C:\\a\\d", "C:\\a/b/d/f"); -//std::string testC = getPathRelative("C:\\ab", "C:\\a/b/d/f"); -//std::string testD = getPathRelative("a/d", "a/d"); +std::string osgDB::getPathRelative(const std::string& from, const std::string& to) +{ + // This implementation is not 100% robust, and should be replaced with C++0x "std::path" as soon as possible. + + // Definition: an "element" is a part between slashes. Ex: "/a/b" has two elements ("a" and "b"). + // Algorithm: + // 1. If paths are neither both absolute nor both relative, then we cannot do anything (we need to make them absolute, but need additionnal info on how to make it). Return. + // 2. If both paths are absolute and root isn't the same (for Windows only, as roots are of the type "C:", "D:"), then the operation is impossible. Return. + // 3. Iterate over two paths elements until elements are equal + // 4. For each remaining element in "from", add ".." to result + // 5. For each remaining element in "to", add this element to result + + // 1 & 2 + const std::string root = getPathRoot(from); + if (root != getPathRoot(to)) { + OSG_INFO << "Cannot relativise paths. From=" << from << ", To=" << to << ". Returning 'to' unchanged." << std::endl; + //return to; + return osgDB::getSimpleFileName(to); + } + + // 3 + PathIterator itFrom(from), itTo(to); + // Iterators may point to Windows roots. As we tested they are equal, there is no need to ++itFrom and ++itTo. + // However, if we got an Unix root, we must add it to the result. + std::string res(root == "/" ? "/" : ""); + for(; itFrom.valid() && itTo.valid() && *itFrom==*itTo; ++itFrom, ++itTo) {} + + // 4 + for(; itFrom.valid(); ++itFrom) res += "../"; + + // 5 + for(; itTo.valid(); ++itTo) res += *itTo + "/"; + + // Remove trailing slash before returning + if (!res.empty() && std::find_first_of(res.rbegin(), res.rbegin()+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != res.rbegin()+1) + { + return res.substr(0, res.length()-1); + } + return res; +} + +//using namespace osgDB; +//std::string testA = getPathRelative("C:\\a\\b", "C:\\a/b/d/f"); // d/f +//std::string testB = getPathRelative("C:\\a\\d", "C:\\a/b/d/f"); // ../b/d/f +//std::string testC = getPathRelative("C:\\ab", "C:\\a/b/d/f"); // ../a/b/d/f +//std::string testD = getPathRelative("a/d", "a/d"); // "" +//std::string testE = getPathRelative("a", "a/d"); // ../d +//std::string testF = getPathRelative("C:/a/b", "a/d"); // Precondition fail. Returns d. +//std::string testG = getPathRelative("/a/b", "a/d"); // Precondition fail. Returns d. +//std::string testH = getPathRelative("a/b", "/a/d"); // Precondition fail. Returns d. diff --git a/src/osgPlugins/dae/daeRAnimations.cpp b/src/osgPlugins/dae/daeRAnimations.cpp index 80757ee3c..552560e6e 100644 --- a/src/osgPlugins/dae/daeRAnimations.cpp +++ b/src/osgPlugins/dae/daeRAnimations.cpp @@ -577,7 +577,7 @@ daeReader::ChannelPart* daeReader::processSampler(domChannel* pDomChannel, Sourc { if (!strcmp("TIME", domParams[0]->getName())) { - pOsgTimesArray = sources[input_source].getFloatArray(); + pOsgTimesArray = sources[input_source].getArray(); } else { @@ -688,58 +688,58 @@ daeReader::ChannelPart* daeReader::processSampler(domChannel* pDomChannel, Sourc { case domSourceReader::Float: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getFloatArray(), - sources[output_intangent_source].getFloatArray(), - sources[output_outtangent_source].getFloatArray(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec2: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec2Array(), - sources[output_intangent_source].getVec2Array(), - sources[output_outtangent_source].getVec2Array(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec3: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec3Array(), - sources[output_intangent_source].getVec3Array(), - sources[output_outtangent_source].getVec3Array(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec4: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec4Array(), - sources[output_intangent_source].getVec4Array(), - sources[output_outtangent_source].getVec4Array(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec2d: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec2dArray(), - sources[output_intangent_source].getVec2dArray(), - sources[output_outtangent_source].getVec2dArray(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec3d: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec3dArray(), - sources[output_intangent_source].getVec3dArray(), - sources[output_outtangent_source].getVec3dArray(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Vec4d: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getVec4dArray(), - sources[output_intangent_source].getVec4dArray(), - sources[output_outtangent_source].getVec4dArray(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; case domSourceReader::Matrix: keyframes = makeKeyframes(pOsgTimesArray, - sources[output_source].getMatrixArray(), - sources[output_intangent_source].getMatrixArray(), - sources[output_outtangent_source].getMatrixArray(), + sources[output_source].getArray(), + sources[output_intangent_source].getArray(), + sources[output_outtangent_source].getArray(), interpolationType); break; default: diff --git a/src/osgPlugins/dae/daeRGeometry.cpp b/src/osgPlugins/dae/daeRGeometry.cpp index 0ba50ba25..1eae266fc 100644 --- a/src/osgPlugins/dae/daeRGeometry.cpp +++ b/src/osgPlugins/dae/daeRGeometry.cpp @@ -701,9 +701,56 @@ struct VertexIndices return false; } + /// Templated getter for memebers, used for createGeometryData() + enum ValueType { POSITION, COLOR, NORMAL, TEXCOORD }; + template + inline int get() const; + int position_index, color_index, normal_index, texcoord_indices[MAX_TEXTURE_COORDINATE_SETS]; }; +template<> +inline int VertexIndices::get() const { return position_index; } +template<> +inline int VertexIndices::get() const { return color_index; } +template<> +inline int VertexIndices::get() const { return normal_index; } +template +inline int VertexIndices::get() const { + // TEXCOORD has not to be implemented here as we need compile-time constants for texcoord number + return -1; +} + + +typedef std::map VertexIndicesIndexMap; + +/// Creates a value array, packed in a osg::Geometry::ArrayData, corresponding to indexed values. +template +osg::Geometry::ArrayData createGeometryData(domSourceReader & sourceReader, const VertexIndicesIndexMap & vertexIndicesIndexMap, int texcoordNum=-1) { + const ArrayType * source = sourceReader.getArray(); + if (!source) return osg::Geometry::ArrayData(); + ArrayType * pArray = new ArrayType; + for (VertexIndicesIndexMap::const_iterator it = vertexIndicesIndexMap.begin(), end = vertexIndicesIndexMap.end(); it != end; ++it) { + int index = texcoordNum>=0 ? it->first.texcoord_indices[texcoordNum] : it->first.get(); + if (index>=0 && static_cast(index)size()) pArray->push_back(source->at(index)); + else { + // Invalid data (index out of bounds) + //LOG_WARN << ... + //pArray->push_back(0); + return osg::Geometry::ArrayData(); + } + } + return osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX); +} + + +template +inline osg::Geometry::ArrayData createGeometryData(domSourceReader & sourceReader, const VertexIndicesIndexMap & vertexIndicesIndexMap, bool useDoublePrecision, int texcoordNum=-1) { + if (useDoublePrecision) return createGeometryData(sourceReader, vertexIndicesIndexMap); + else return createGeometryData(sourceReader, vertexIndicesIndexMap); +} + + void daeReader::resolveMeshArrays(const domP_Array& domPArray, const domInputLocalOffset_Array& inputs, const domMesh* pDomMesh, osg::Geometry* geometry, SourceMap &sources, @@ -735,7 +782,6 @@ void daeReader::resolveMeshArrays(const domP_Array& domPArray, } ++stride; - typedef std::map VertexIndicesIndexMap; VertexIndicesIndexMap vertexIndicesIndexMap; for (size_t j = 0; j < domPArray.getCount(); ++j) @@ -794,99 +840,35 @@ void daeReader::resolveMeshArrays(const domP_Array& domPArray, } } -// Local defines to make te code a bit more readable -// Sukender: This is not a very clean way to code, I know, but else the code is unmaintanable. -#define FOREACH_INDEX for (VertexIndicesIndexMap::const_iterator it = vertexIndicesIndexMap.begin(), end = vertexIndicesIndexMap.end(); it != end; ++it) -//#define FOREACH_INDEX for (VertexIndicesIndexMap::const_iterator it = vertexIndicesIndexMap.begin(); it != vertexIndicesIndexMap.end(); ++it) -#define ENSURE_VECTOR_SIZE(arrayName, text) if (arrayName) { \ - if (arrayName->size() > nbVertices) OSG_NOTIFY(osg::NOTICE) << "More " #text " coordinates than vertices found. Result may not be what expected." << std::endl; \ - if (arrayName->size() < nbVertices) { \ - OSG_NOTIFY(osg::WARN) << "Less " #text " coordinates than vertices found. Skipping " #text " components." << std::endl; \ - arrayName = NULL; \ - } \ - } \ -/**/ const bool readDoubleVertices = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_VERTEX) != 0; const bool readDoubleColors = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_COLOR) != 0; const bool readDoubleNormals = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_NORMAL) != 0; const bool readDoubleTexcoords = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0; - unsigned int nbVertices(0); - // TODO Factorize code below! + // Vertices { - if (!readDoubleVertices) + osg::Geometry::ArrayData arrayData( createGeometryData(sources[position_source], vertexIndicesIndexMap, readDoubleVertices) ); + if (arrayData.array.valid()) { - const osg::Vec3Array * source = sources[position_source].getVec3Array(); - if (source) - { - nbVertices = source->size(); - osg::Vec3Array* pArray = new osg::Vec3Array; - FOREACH_INDEX pArray->push_back(source->at(it->first.position_index)); - geometry->setVertexData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } - } - else - { - const osg::Vec3dArray* source = sources[position_source].getVec3dArray(); - if (source) - { - nbVertices = source->size(); - osg::Vec3dArray* pArray = new osg::Vec3dArray; - FOREACH_INDEX pArray->push_back(source->at(it->first.position_index)); - geometry->setVertexData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } + geometry->setVertexData(arrayData); } } if (color_source) { - if (!readDoubleColors) + osg::Geometry::ArrayData arrayData( createGeometryData(sources[color_source], vertexIndicesIndexMap, readDoubleColors) ); + if (arrayData.array.valid()) { - const osg::Vec4Array * colorSource = sources[color_source].getVec4Array(); - ENSURE_VECTOR_SIZE(colorSource, color) - if (colorSource) - { - osg::Vec4Array* pArray = new osg::Vec4Array; - FOREACH_INDEX pArray->push_back(colorSource->at(it->first.color_index)); - geometry->setColorData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } - } - else - { - const osg::Vec4dArray* colorSource = sources[color_source].getVec4dArray(); - ENSURE_VECTOR_SIZE(colorSource, color) - if (colorSource) - { - osg::Vec4dArray* pArray = new osg::Vec4dArray; - FOREACH_INDEX pArray->push_back(colorSource->at(it->first.color_index)); - geometry->setColorData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } + geometry->setColorData(arrayData); } } if (normal_source) { - if (!readDoubleNormals) + osg::Geometry::ArrayData arrayData( createGeometryData(sources[normal_source], vertexIndicesIndexMap, readDoubleNormals) ); + if (arrayData.array.valid()) { - const osg::Vec3Array * normalSource = sources[normal_source].getVec3Array(); - ENSURE_VECTOR_SIZE(normalSource, normal) - if (normalSource) - { - osg::Vec3Array* pArray = new osg::Vec3Array; - FOREACH_INDEX pArray->push_back(normalSource->at(it->first.normal_index)); - geometry->setNormalData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } - } - else - { - const osg::Vec3dArray* normalSource = sources[normal_source].getVec3dArray(); - ENSURE_VECTOR_SIZE(normalSource, normal) - if (normalSource) - { - osg::Vec3dArray* pArray = new osg::Vec3dArray; - FOREACH_INDEX pArray->push_back(normalSource->at(it->first.normal_index)); - geometry->setNormalData(osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); - } + geometry->setNormalData(arrayData); } } @@ -894,57 +876,20 @@ void daeReader::resolveMeshArrays(const domP_Array& domPArray, { if (daeElement* texcoord_source = texcoord_sources[texcoord_set]) { - osg::Array* pArray = NULL; - if (!readDoubleTexcoords) + // 2D Texcoords + osg::Geometry::ArrayData arrayData( createGeometryData(sources[texcoord_source], vertexIndicesIndexMap, readDoubleTexcoords, texcoord_set) ); + if (arrayData.array.valid()) { - const osg::Vec2Array * tcSource2f = sources[texcoord_source].getVec2Array(); - const osg::Vec3Array * tcSource3f = sources[texcoord_source].getVec3Array(); - if (tcSource2f) - { - ENSURE_VECTOR_SIZE(tcSource2f, texture) - if (tcSource2f) - { - osg::Vec2Array* pVec2Array = new osg::Vec2Array; - pArray = pVec2Array; - FOREACH_INDEX pVec2Array->push_back(tcSource2f->at(it->first.texcoord_indices[texcoord_set])); - } - } - else if (tcSource3f) - { - ENSURE_VECTOR_SIZE(tcSource3f, texture) - if (tcSource3f) { - osg::Vec3Array* pVec3Array = new osg::Vec3Array; - pArray = pVec3Array; - FOREACH_INDEX pVec3Array->push_back(tcSource3f->at(it->first.texcoord_indices[texcoord_set])); - } - } + geometry->setTexCoordData(texcoord_set, arrayData); } else { - const osg::Vec2dArray* tcSource2d = sources[texcoord_source].getVec2dArray(); - const osg::Vec3dArray* tcSource3d = sources[texcoord_source].getVec3dArray(); - if (tcSource2d) + // 3D Textcoords + osg::Geometry::ArrayData arrayData( createGeometryData(sources[texcoord_source], vertexIndicesIndexMap, readDoubleTexcoords, texcoord_set) ); + if (arrayData.array.valid()) { - ENSURE_VECTOR_SIZE(tcSource2d, texture) - if (tcSource2d) { - osg::Vec2dArray* pVec2Array = new osg::Vec2dArray; - pArray = pVec2Array; - FOREACH_INDEX pVec2Array->push_back(tcSource2d->at(it->first.texcoord_indices[texcoord_set])); - } + geometry->setTexCoordData(texcoord_set, arrayData); } - else if (tcSource3d) - { - ENSURE_VECTOR_SIZE(tcSource3d, texture) - if (tcSource3d) { - osg::Vec3dArray* pVec3Array = new osg::Vec3dArray; - pArray = pVec3Array; - FOREACH_INDEX pVec3Array->push_back(tcSource3d->at(it->first.texcoord_indices[texcoord_set])); - } - } - } - if (pArray) - { - geometry->setTexCoordData(texcoord_set, osg::Geometry::ArrayData(pArray, osg::Geometry::BIND_PER_VERTEX)); } } } diff --git a/src/osgPlugins/dae/daeWGeometry.cpp b/src/osgPlugins/dae/daeWGeometry.cpp index 39145792f..dce7c3606 100644 --- a/src/osgPlugins/dae/daeWGeometry.cpp +++ b/src/osgPlugins/dae/daeWGeometry.cpp @@ -556,7 +556,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st // RS BUG // getNumTexCoordArrays may return larger number - // where getTexCoordArray(0) may have a BIND_OFF and an empty arrat + // where getTexCoordArray(0) may have a BIND_OFF and an empty array std::vector texcoords; for ( unsigned int i = 0; i < geom->getNumTexCoordArrays(); i++ ) { diff --git a/src/osgPlugins/dae/daeWMaterials.cpp b/src/osgPlugins/dae/daeWMaterials.cpp index 0e2bde8aa..3b77433e5 100644 --- a/src/osgPlugins/dae/daeWMaterials.cpp +++ b/src/osgPlugins/dae/daeWMaterials.cpp @@ -106,7 +106,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa std::string fileURI; if (m_linkOrignialTextures) { - // We link to orignial images. + // We link to orignial images (not the ones in memory). fileURI = osgDB::findDataFile(osgimg->getFileName()); if (fileURI=="" && m_ForceTexture) { @@ -115,10 +115,14 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa } else { - // We do not link to orignial images. Then must ensure to write the image. + // We do not link to orignial images but to the ones in memory. Then must ensure to write the images. // Following code block is borrowed from FBX's WriterNodeVisitor::Material::Material(). ImageSet::iterator it = _imageSet.find(osgimg); - if (it == _imageSet.end()) + if (it != _imageSet.end()) + { + fileURI = it->second; + } + else { fileURI = osgDB::getRealPath(osgDB::convertFileNameToNativeStyle(osgimg->getFileName())); std::string destPath; @@ -155,7 +159,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa assert(!destPath.empty()); // Else the implementation is to be fixed assert(!relativePath.empty()); // ditto fileURI = relativePath; - it = _imageSet.insert(ImageSet::value_type(osgimg, relativePath)).first; + it = _imageSet.insert(ImageSet::value_type(osgimg, fileURI)).first; _imageFilenameSet.insert(destPath); } // (end of code borrowed from FBX) diff --git a/src/osgPlugins/dae/domSourceReader.h b/src/osgPlugins/dae/domSourceReader.h index 02f212837..846dfb4b5 100644 --- a/src/osgPlugins/dae/domSourceReader.h +++ b/src/osgPlugins/dae/domSourceReader.h @@ -23,7 +23,7 @@ namespace osgDAE { /** @class domSourceReader -Converts a source to an OSG vector array as soon as you call a getter, so calling simple precision version \c getVec3Array() will force getVec3dArray() to return NULL, and vice-versa (for a Vec3 array in the example). +Converts a source to an OSG vector array as soon as you call a getter, so calling simple precision version \c getArray() will force getArray() to return NULL, and vice-versa (for a Vec3 array in the example). @brief Convert sources from DAE to OSG arrays */ class domSourceReader @@ -38,21 +38,24 @@ public: ArrayType getArrayType(bool enableDoublePrecision) const { if (srcInit) const_cast(this)->convert(enableDoublePrecision); return m_array_type; }; - osg::FloatArray* getFloatArray() { if (srcInit) convert(false); return m_float_array.get(); }; - - osg::Vec2Array* getVec2Array() { if (srcInit) convert(false); return m_vec2_array.get(); }; - - osg::Vec3Array* getVec3Array() { if (srcInit) convert(false); return m_vec3_array.get(); }; - - osg::Vec4Array* getVec4Array() { if (srcInit) convert(false); return m_vec4_array.get(); }; - - osg::Vec2dArray* getVec2dArray() { if (srcInit) convert(true); return m_vec2d_array.get(); }; - - osg::Vec3dArray* getVec3dArray() { if (srcInit) convert(true); return m_vec3d_array.get(); }; - - osg::Vec4dArray* getVec4dArray() { if (srcInit) convert(true); return m_vec4d_array.get(); }; - - osg::MatrixfArray* getMatrixArray() { if (srcInit) convert(false); return m_matrix_array.get(); }; + template + inline OsgArrayType * getArray(); + template <> + inline osg::FloatArray* domSourceReader::getArray() { if (srcInit) convert(false); return m_float_array.get(); }; + template <> + inline osg::Vec2Array* domSourceReader::getArray() { if (srcInit) convert(false); return m_vec2_array.get(); }; + template <> + inline osg::Vec3Array* domSourceReader::getArray() { if (srcInit) convert(false); return m_vec3_array.get(); }; + template <> + inline osg::Vec4Array* domSourceReader::getArray() { if (srcInit) convert(false); return m_vec4_array.get(); }; + template <> + inline osg::Vec2dArray* domSourceReader::getArray() { if (srcInit) convert(true); return m_vec2d_array.get(); }; + template <> + inline osg::Vec3dArray* domSourceReader::getArray() { if (srcInit) convert(true); return m_vec3d_array.get(); }; + template <> + inline osg::Vec4dArray* domSourceReader::getArray() { if (srcInit) convert(true); return m_vec4d_array.get(); }; + template <> + inline osg::MatrixfArray* domSourceReader::getArray() { if (srcInit) convert(false); return m_matrix_array.get(); }; int getCount(bool enableDoublePrecision) const { if (srcInit) const_cast(this)->convert(enableDoublePrecision); return m_count; };