/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include using namespace osg; #if 1 class DrawVertex { public: DrawVertex(const Array* vertices,const IndexArray* indices): _vertices(vertices), _indices(indices) { _verticesType = _vertices?_vertices->getType():Array::ArrayType; _indicesType = _indices?_indices->getType():Array::ArrayType; } 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; } } inline void operator () (unsigned int pos) { if (_indices) pos = index(pos); switch(_verticesType) { case(Array::Vec3ArrayType): apply((*(static_cast(_vertices)))[pos]); break; case(Array::Vec2ArrayType): apply((*(static_cast(_vertices)))[pos]); break; case(Array::Vec4ArrayType): apply((*(static_cast(_vertices)))[pos]); break; default: break; } } inline void apply(const Vec2& v) { glVertex2fv(v.ptr()); } inline void apply(const Vec3& v) { glVertex3fv(v.ptr()); } inline void apply(const Vec4& v) { glVertex4fv(v.ptr()); } const Array* _vertices; const IndexArray* _indices; Array::Type _verticesType; Array::Type _indicesType; }; #else class DrawVertex : public osg::ConstValueVisitor { public: DrawVertex(const Array* vertices,const IndexArray* indices): _vertices(vertices), _indices(indices) {} inline void operator () (unsigned int pos) { if (_indices) _vertices->accept(_indices->index(pos),*this); else _vertices->accept(pos,*this); } virtual void apply(const Vec2& v) { glVertex2fv(v.ptr()); } virtual void apply(const Vec3& v) { glVertex3fv(v.ptr()); } virtual void apply(const Vec4& v) { glVertex4fv(v.ptr()); } const Array* _vertices; const IndexArray* _indices; }; #endif class DrawNormal { public: DrawNormal(const Vec3Array* normals,const IndexArray* indices): _normals(normals), _indices(indices) {} void operator () (unsigned int pos) { if (_indices) glNormal3fv((*_normals)[_indices->index(pos)].ptr()); else glNormal3fv((*_normals)[pos].ptr()); } const Vec3Array* _normals; const IndexArray* _indices; }; #if 1 class DrawColor { public: DrawColor(const Array* colors,const IndexArray* indices): _colors(colors), _indices(indices) { _colorsType = _colors?_colors->getType():Array::ArrayType; _indicesType = _indices?_indices->getType():Array::ArrayType; } 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; } } inline void operator () (unsigned int pos) { if (_indices) pos = index(pos); switch(_colorsType) { case(Array::Vec4ArrayType): apply((*static_cast(_colors))[pos]); break; case(Array::UByte4ArrayType): apply((*static_cast(_colors))[pos]); break; case(Array::Vec3ArrayType): apply((*static_cast(_colors))[pos]); break; default: break; } } inline void apply(const UByte4& v) { glColor4ubv(v.ptr()); } inline void apply(const Vec3& v) { glColor3fv(v.ptr()); } inline void apply(const Vec4& v) { glColor4fv(v.ptr()); } const Array* _colors; const IndexArray* _indices; Array::Type _colorsType; Array::Type _indicesType; }; #else class DrawColor : public osg::ConstValueVisitor { public: DrawColor(const Array* colors,const IndexArray* indices): _colors(colors), _indices(indices) {} inline void operator () (unsigned int pos) { if (_indices) _colors->accept(_indices->index(pos),*this); else _colors->accept(pos,*this); } virtual void apply(const UByte4& v) { glColor4ubv(v.ptr()); } virtual void apply(const Vec3& v) { glColor3fv(v.ptr()); } virtual void apply(const Vec4& v) { glColor4fv(v.ptr()); } const Array* _colors; const IndexArray* _indices; }; #endif class DrawVertexAttrib : public osg::Referenced, public osg::ConstValueVisitor { public: DrawVertexAttrib(const Drawable::Extensions * extensions,unsigned int index,GLboolean normalized,const Array* attribcoords,const IndexArray* indices): _index(index), _normalized(normalized), _extensions(extensions), _attribcoords(attribcoords), _indices(indices) {;} inline void operator () (unsigned int pos) { if (_indices) _attribcoords->accept(_indices->index(pos),*this); else _attribcoords->accept(pos,*this); } virtual void apply(const GLshort& s) { _extensions->glVertexAttrib1s( _index, s ); } virtual void apply(const GLfloat& f) { _extensions->glVertexAttrib1f( _index, f ); } virtual void apply(const UByte4& v) { if( _normalized ) { _extensions->glVertexAttrib4Nubv( _index, v.ptr() ); } else { _extensions->glVertexAttrib4ubv( _index, v.ptr() ); } } virtual void apply(const Vec2& v) { _extensions->glVertexAttrib2fv( _index, v.ptr() ); } virtual void apply(const Vec3& v) { _extensions->glVertexAttrib3fv( _index, v.ptr() ); } virtual void apply(const Vec4& v) { _extensions->glVertexAttrib4fv( _index, v.ptr() ); } unsigned int _index; GLboolean _normalized; const Drawable::Extensions* _extensions; const Array* _attribcoords; const IndexArray* _indices; }; class DrawTexCoord : public osg::Referenced, public osg::ConstValueVisitor { public: DrawTexCoord(const Array* texcoords,const IndexArray* indices): _texcoords(texcoords), _indices(indices) {} inline void operator () (unsigned int pos) { if (_indices) _texcoords->accept(_indices->index(pos),*this); else _texcoords->accept(pos,*this); } virtual void apply(const GLfloat& v){ glTexCoord1f(v); } virtual void apply(const Vec2& v) { glTexCoord2fv(v.ptr()); } virtual void apply(const Vec3& v) { glTexCoord3fv(v.ptr()); } virtual void apply(const Vec4& v) { glTexCoord4fv(v.ptr()); } const Array* _texcoords; const IndexArray* _indices; }; class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor { public: DrawMultiTexCoord(GLenum target,const Array* texcoords,const IndexArray* indices, const Drawable::Extensions * extensions): _target(target), _texcoords(texcoords), _indices(indices), _extensions(extensions) {} inline void operator () (unsigned int pos) { if (_indices) _texcoords->accept(_indices->index(pos),*this); else _texcoords->accept(pos,*this); } virtual void apply(const GLfloat& v){ _extensions->glMultiTexCoord1f(_target,v); } virtual void apply(const Vec2& v) { _extensions->glMultiTexCoord2fv(_target,v.ptr()); } virtual void apply(const Vec3& v) { _extensions->glMultiTexCoord3fv(_target,v.ptr()); } virtual void apply(const Vec4& v) { _extensions->glMultiTexCoord4fv(_target,v.ptr()); } GLenum _target; const Array* _texcoords; const IndexArray* _indices; const Drawable::Extensions * _extensions; }; class DrawSecondaryColor : public osg::ConstValueVisitor { public: DrawSecondaryColor(const Array* colors,const IndexArray* indices, const Drawable::Extensions * extensions): _colors(colors), _indices(indices), _extensions(extensions) {} inline void operator () (unsigned int pos) { if (_indices) _colors->accept(_indices->index(pos),*this); else _colors->accept(pos,*this); } virtual void apply(const UByte4& v) { _extensions->glSecondaryColor3ubv(v.ptr()); } virtual void apply(const Vec3& v) { _extensions->glSecondaryColor3fv(v.ptr()); } virtual void apply(const Vec4& v) { _extensions->glSecondaryColor3fv(v.ptr()); } const Array* _colors; const IndexArray* _indices; const Drawable::Extensions * _extensions; }; class DrawFogCoord : public osg::ConstValueVisitor { public: DrawFogCoord(const Array* fogcoords,const IndexArray* indices,const Drawable::Extensions * extensions): _fogcoords(fogcoords), _indices(indices), _extensions(extensions) {} inline void operator () (unsigned int pos) { if (_indices) _fogcoords->accept(_indices->index(pos),*this); else _fogcoords->accept(pos,*this); } virtual void apply(const GLfloat& v) { _extensions->glFogCoordfv(&v); } const Array* _fogcoords; const IndexArray* _indices; const Drawable::Extensions * _extensions; }; Geometry::Geometry() { _normalBinding = BIND_OFF; _colorBinding = BIND_OFF; _secondaryColorBinding = BIND_OFF; _fogCoordBinding = BIND_OFF; _fastPath = false; _fastPathHint = true; } Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): Drawable(geometry,copyop), #ifdef COMPILE_POSSIBLE_NEW_ARRAY_METHODS _attributeList(geometry._attributeList), #endif _vertexArray((copyop(geometry._vertexArray.get()))), _vertexIndices(dynamic_cast(copyop(geometry._vertexIndices.get()))), _normalBinding(geometry._normalBinding), _normalArray(dynamic_cast(copyop(geometry._normalArray.get()))), _normalIndices(dynamic_cast(copyop(geometry._normalIndices.get()))), _colorBinding(geometry._colorBinding), _colorArray(copyop(geometry._colorArray.get())), _colorIndices(dynamic_cast(copyop(geometry._colorIndices.get()))), _secondaryColorBinding(geometry._secondaryColorBinding), _secondaryColorArray(copyop(geometry._secondaryColorArray.get())), _secondaryColorIndices(dynamic_cast(copyop(geometry._secondaryColorIndices.get()))), _fogCoordBinding(geometry._fogCoordBinding), _fogCoordArray(dynamic_cast(copyop(geometry._fogCoordArray.get()))), _fogCoordIndices(dynamic_cast(copyop(geometry._fogCoordIndices.get()))), _fastPath(geometry._fastPath), _fastPathHint(geometry._fastPathHint) { for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin(); pitr!=geometry._primitives.end(); ++pitr) { PrimitiveSet* primitive = copyop(pitr->get()); if (primitive) _primitives.push_back(primitive); } for(TexCoordArrayList::const_iterator titr=geometry._texCoordList.begin(); titr!=geometry._texCoordList.end(); ++titr) { _texCoordList.push_back(*titr); } for(VertexAttribArrayList::const_iterator vitr=geometry._vertexAttribList.begin(); vitr!=geometry._vertexAttribList.end(); ++vitr) { _vertexAttribList.push_back(*vitr); } } Geometry::~Geometry() { // no need to delete, all automatically handled by ref_ptr :-) } void Geometry::setTexCoordArray(unsigned int unit,Array* array) { if (_texCoordList.size()<=unit) _texCoordList.resize(unit+1); _texCoordList[unit].first = array; dirtyDisplayList(); } Array* Geometry::getTexCoordArray(unsigned int unit) { if (unit<_texCoordList.size()) return _texCoordList[unit].first.get(); else return 0; } const Array* Geometry::getTexCoordArray(unsigned int unit) const { if (unit<_texCoordList.size()) return _texCoordList[unit].first.get(); else return 0; } void Geometry::setTexCoordIndices(unsigned int unit,IndexArray* array) { if (_texCoordList.size()<=unit) _texCoordList.resize(unit+1); _texCoordList[unit].second = array; dirtyDisplayList(); } IndexArray* Geometry::getTexCoordIndices(unsigned int unit) { if (unit<_texCoordList.size()) return _texCoordList[unit].second.get(); else return 0; } const IndexArray* Geometry::getTexCoordIndices(unsigned int unit) const { if (unit<_texCoordList.size()) return _texCoordList[unit].second.get(); else return 0; } #ifdef COMPILE_POSSIBLE_NEW_ARRAY_METHODS void Geometry::setArray(AttributeType type,Array* array) { if (_attributeList.size()<=type) _attributeList.resize(type+1); _attributeList[type]._array = array; dirtyDisplayList(); } Array* Geometry::getArray(AttributeType type) { if (type<_attributeList.size()) return _attributeList[type]._array.get(); else return 0; } const Array* Geometry::getArray(AttributeType type) const { if (type<_attributeList.size()) return _attributeList[type]._array.get(); else return 0; } void Geometry::setIndices(AttributeType type,IndexArray* array) { if (_attributeList.size()<=type) _attributeList.resize(type+1); _attributeList[type]._indices = array; dirtyDisplayList(); } IndexArray* Geometry::getIndices(AttributeType type) { if (type<_attributeList.size()) return _attributeList[type]._indices.get(); else return 0; } const IndexArray* Geometry::getIndices(AttributeType type) const { if (type<_attributeList.size()) return _attributeList[type]._indices.get(); else return 0; } void Geometry::setNormalize(AttributeType type,GLboolean normalize) { if (_attributeList.size()<=type) _attributeList.resize(type+1); _attributeList[type]._normalize = normalize; dirtyDisplayList(); } GLboolean Geometry::getNormalize(AttributeType type) const { if (type<_attributeList.size()) return _attributeList[type]._normalize; else return GL_FALSE; } void Geometry::setBinding(AttributeType type,AttributeBinding binding) { if (_attributeList.size()<=type) _attributeList.resize(type+1); _attributeList[type]._binding = binding; dirtyDisplayList(); } Geometry::AttributeBinding Geometry::getBinding(AttributeType type) const { if (type<_attributeList.size()) return _attributeList[type]._binding; else return BIND_OFF; } #endif void Geometry::setVertexAttribArray(unsigned int index,GLboolean normalize,Array* array,AttributeBinding ab) { if (_vertexAttribList.size()<=index) { _vertexAttribList.resize(index+1); _vertexAttribBindingList.resize(index+1); } _vertexAttribList[index].first = normalize; _vertexAttribList[index].second.first = array; if( index == 0 ) { // Force bind per vertex _vertexAttribBindingList[index] = BIND_PER_VERTEX; } else { _vertexAttribBindingList[index] = ab; } computeFastPathsUsed(); dirtyDisplayList(); } Array *Geometry::getVertexAttribArray(unsigned int index) { if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.first.get(); else return 0; } const Array *Geometry::getVertexAttribArray(unsigned int index) const { if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.first.get(); else return 0; } bool Geometry::getVertexAttribBinding(unsigned int index, AttributeBinding& ab) const { // AttributeBinding value goes in ab // return true if index is valid, false otherwise if (index<_vertexAttribBindingList.size()) { ab = _vertexAttribBindingList[index]; return true; } else { return false; } } bool Geometry::getVertexAttribNormalize(unsigned int index, GLboolean &ret) const { // normalized value goes in ret // return true if index is valid, false otherwise if (index<_vertexAttribList.size()) { ret = _vertexAttribList[index].first; return true; } else { return false; } } void Geometry::setVertexAttribIndices(unsigned int index,IndexArray* array) { if (_vertexAttribList.size()<=index) _vertexAttribList.resize(index+1); _vertexAttribList[index].second.second = array; dirtyDisplayList(); } IndexArray* Geometry::getVertexAttribIndices(unsigned int index) { if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.second.get(); else return 0; } const IndexArray* Geometry::getVertexAttribIndices(unsigned int index) const { if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.second.get(); else return 0; } bool Geometry::addPrimitiveSet(PrimitiveSet* primitiveset) { if (primitiveset) { _primitives.push_back(primitiveset); dirtyDisplayList(); dirtyBound(); return true; } notify(WARN)<<"Warning: invalid index i or primitiveset passed to osg::Geometry::addPrimitiveSet(i,primitiveset), ignoring call."<0) { if (i+numElementsToRemove<=_primitives.size()) { _primitives.erase(_primitives.begin()+i,_primitives.begin()+i+numElementsToRemove); } else { // asking to delete too many elements, report a warning, and delete to // the end of the primitive list. notify(WARN)<<"Warning: osg::Geometry::removePrimitiveSet(i,numElementsToRemove) has been asked to remove more elements than are available,"<empty() || (_normalIndices.valid() && _normalIndices->getNumElements()==0) ) { // switch off if not supported or have a valid data. _normalBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // set up colours.. // if (!_colorArray.valid() || _colorArray->getNumElements()==0 || (_colorIndices.valid() && _colorIndices->getNumElements()==0) ) { // switch off if not supported or have a valid data. _colorBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up secondary color if required. // if (!_secondaryColorArray.valid() || _secondaryColorArray->getNumElements()==0 || (_secondaryColorIndices.valid() && _secondaryColorIndices->getNumElements()==0) ) { // switch off if not supported or have a valid data. _secondaryColorBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up fog coord if required. // if (!_fogCoordArray.valid() || _fogCoordArray->getNumElements()==0 || (_fogCoordIndices.valid() && _fogCoordIndices->getNumElements()==0) ) { // switch off if not supported or have a valid data. _fogCoordBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up vertex attrib if required. // for( unsigned int va = 0; va < _vertexAttribList.size(); ++va ) { const Array * array = _vertexAttribList[va].second.first.get(); const IndexArray * idxArray = _vertexAttribList[va].second.second.get(); if (!array || array->getNumElements()==0 || (idxArray && idxArray->getNumElements()==0) ) { // switch off if not supported or have a valid data. _vertexAttribBindingList[va] = BIND_OFF; } } */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // check to see if fast path can be used. // _fastPath = true; if (_vertexIndices.valid()) _fastPath = false; else if (_normalBinding==BIND_PER_PRIMITIVE || (_normalBinding==BIND_PER_VERTEX && _normalIndices.valid())) _fastPath = false; else if (_colorBinding==BIND_PER_PRIMITIVE || (_colorBinding==BIND_PER_VERTEX && _colorIndices.valid())) _fastPath = false; else if (_secondaryColorBinding==BIND_PER_PRIMITIVE || (_secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorIndices.valid())) _fastPath = false; else if (_fogCoordBinding==BIND_PER_PRIMITIVE || (_fogCoordBinding==BIND_PER_VERTEX && _fogCoordIndices.valid())) _fastPath = false; else { for( unsigned int va = 0; va < _vertexAttribBindingList.size(); ++va ) { if (_vertexAttribBindingList[va]==BIND_PER_PRIMITIVE) { _fastPath = false; break; } else { const Array * array = _vertexAttribList[va].second.first.get(); const IndexArray * idxArray = _vertexAttribList[va].second.second.get(); if( _vertexAttribBindingList[va]==BIND_PER_VERTEX && array && array->getNumElements()>0 && idxArray && idxArray->getNumElements()>0 ) { _fastPath = false; break; } } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up tex coords if required. // for(unsigned int unit=0;unit!=_texCoordList.size();++unit) { const ArrayPair& texcoordPair = _texCoordList[unit]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) { if (texcoordPair.second->getNumElements()>0) { _fastPath = false; break; } } } } _supportsVertexBufferObjects = _fastPath; //_supportsVertexBufferObjects = false; //_useVertexBufferObjects = false; return _fastPath; } void Geometry::drawImplementation(State& state) const { if (_internalOptimizedGeometry.valid()) { _internalOptimizedGeometry->drawImplementation(state); return; } const Extensions* extensions = getExtensions(state.getContextID(),true); if( !( ( _vertexArray.valid() && _vertexArray->getNumElements() != 0 ) || ( _vertexAttribList.size() > 0 && _vertexAttribList[0].second.first.valid() && _vertexAttribList[0].second.first->getNumElements() != 0 ) ) ) { return; } if( ( _vertexIndices.valid() && _vertexIndices->getNumElements() == 0 ) || ( _vertexAttribList.size() > 0 && _vertexAttribList[0].second.second.valid() && _vertexAttribList[0].second.second->getNumElements() == 0 ) ) { return; } DrawNormal drawNormal(_normalArray.get(),_normalIndices.get()); DrawColor drawColor(_colorArray.get(),_colorIndices.get()); DrawSecondaryColor drawSecondaryColor(_secondaryColorArray.get(),_secondaryColorIndices.get(),extensions); DrawFogCoord drawFogCoord(_fogCoordArray.get(),_fogCoordIndices.get(),extensions); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up secondary color if required. // AttributeBinding secondaryColorBinding = _secondaryColorBinding; if (secondaryColorBinding!=BIND_OFF && !extensions->isSecondaryColorSupported()) { // switch off if not supported or have a valid data. secondaryColorBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up fog coord if required. // AttributeBinding fogCoordBinding = _fogCoordBinding; if (fogCoordBinding!=BIND_OFF && !extensions->isFogCoordSupported()) { // switch off if not supported or have a valid data. fogCoordBinding = BIND_OFF; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up vertex attrib if required. // if(!extensions->isVertexProgramSupported()) { for( unsigned int va = 0; va < _vertexAttribBindingList.size(); ++va ) { if (_vertexAttribBindingList[va]!=BIND_OFF) { _vertexAttribBindingList[va] = BIND_OFF; } } } unsigned int normalIndex = 0; unsigned int colorIndex = 0; unsigned int secondaryColorIndex = 0; unsigned int fogCoordIndex = 0; unsigned int vertexAttribIndex = 0; #if USE_DEFAULT_NORMAL // if no values are defined for normal and color provide some defaults... if (_normalBinding==BIND_OFF) glNormal3f(0.0f,0.0f,1.0f); #endif #if USE_DEFAULT_COLOUR if (_colorBinding==BIND_OFF) glColor4f(1.0f,1.0f,1.0f,1.0f); #endif typedef std::vector< ref_ptr > DrawVertexAttribList; typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap; DrawVertexAttribMap drawVertexAttribMap; bool handleVertexAttributes = (!_vertexAttribList.empty() && extensions->isVertexProgramSupported()); bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported(); if (areFastPathsUsed()) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // fast path. // if (usingVertexBufferObjects) { // // Vertex Buffer Object path for defining vertex arrays. // GLuint& buffer = _vboList[state.getContextID()]; if (!buffer) { //std::cout << "creating VertexBuffer "<glGenBuffers(1, &buffer); extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,buffer); //std::cout << " gen VertexBuffer "<getTotalDataSize(); _normalOffset = totalSize; if (_normalArray.valid()) totalSize += _normalArray->getTotalDataSize(); _colorOffset = totalSize; if (_colorArray.valid()) totalSize += _colorArray->getTotalDataSize(); _secondaryColorOffset = totalSize; if (_secondaryColorArray.valid()) totalSize += _secondaryColorArray->getTotalDataSize(); _fogCoordOffset = totalSize; if (_fogCoordArray.valid()) totalSize += _fogCoordArray->getTotalDataSize(); unsigned int unit; for(unit=0;unit<_texCoordList.size();++unit) { _texCoordList[unit].offset = totalSize; const Array* array = _texCoordList[unit].first.get(); if (array) totalSize += array->getTotalDataSize(); } if( handleVertexAttributes ) { unsigned int index; for( index = 0; index < _vertexAttribList.size(); ++index ) { _texCoordList[unit].offset = totalSize; const Array* array = _vertexAttribList[index].second.first.get(); const AttributeBinding ab = _vertexAttribBindingList[index]; if( ab == BIND_PER_VERTEX && array ) { totalSize += array->getTotalDataSize(); } } } // allocated the buffer space, but leave the copy to be done per vertex array below extensions->glBufferData(GL_ARRAY_BUFFER_ARB,totalSize, 0, GL_STATIC_DRAW_ARB); //std::cout << " Created VertexBuffer "<glBindBuffer(GL_ARRAY_BUFFER_ARB,buffer); if( _vertexArray.valid() ) state.setVertexPointer(_vertexArray->getDataSize(),_vertexArray->getDataType(),0,(const GLvoid*)_vertexOffset); else state.disableVertexPointer(); if (_normalBinding==BIND_PER_VERTEX) state.setNormalPointer(GL_FLOAT,0,(const GLvoid*)_normalOffset); else state.disableNormalPointer(); if (_colorBinding==BIND_PER_VERTEX) state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,(const GLvoid*)_colorOffset); else state.disableColorPointer(); if (secondaryColorBinding==BIND_PER_VERTEX) state.setSecondaryColorPointer(_secondaryColorArray->getDataSize(),_secondaryColorArray->getDataType(),0,(const GLvoid*)_secondaryColorOffset); else state.disableSecondaryColorPointer(); if (fogCoordBinding==BIND_PER_VERTEX) state.setFogCoordPointer(GL_FLOAT,0,(const GLvoid*)_fogCoordOffset); else state.disableFogCoordPointer(); unsigned int unit; for(unit=0;unit<_texCoordList.size();++unit) { const Array* array = _texCoordList[unit].first.get(); if (array) state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,(const GLvoid*)_texCoordList[unit].offset); else state.disableTexCoordPointer(unit); } state.disableTexCoordPointersAboveAndIncluding(unit); if( handleVertexAttributes ) { unsigned int index; for( index = 0; index < _vertexAttribList.size(); ++index ) { const Array* array = _vertexAttribList[index].second.first.get(); const AttributeBinding ab = _vertexAttribBindingList[index]; if( ab == BIND_PER_VERTEX && array ) { state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), _vertexAttribList[index].first, 0, (const GLvoid*)_vertexAttribList[index].second.offset ); } else { if( array ) { const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); if( indexArray && indexArray->getNumElements() > 0 ) { drawVertexAttribMap[ab].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); } else { drawVertexAttribMap[ab].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); } } state.disableVertexAttribPointer( index ); } } state.disableVertexAttribPointersAboveAndIncluding( index ); } } else { //std::cout << "none VertexBuffer path"<getDataSize(),_vertexArray->getDataType(),0,_vertexArray->getDataPointer()); else state.disableVertexPointer(); if (_normalBinding==BIND_PER_VERTEX) state.setNormalPointer(GL_FLOAT,0,_normalArray->getDataPointer()); else state.disableNormalPointer(); if (_colorBinding==BIND_PER_VERTEX) state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,_colorArray->getDataPointer()); else state.disableColorPointer(); if (secondaryColorBinding==BIND_PER_VERTEX) state.setSecondaryColorPointer(_secondaryColorArray->getDataSize(),_secondaryColorArray->getDataType(),0,_secondaryColorArray->getDataPointer()); else state.disableSecondaryColorPointer(); if (fogCoordBinding==BIND_PER_VERTEX) state.setFogCoordPointer(GL_FLOAT,0,_fogCoordArray->getDataPointer()); else state.disableFogCoordPointer(); unsigned int unit; for(unit=0;unit<_texCoordList.size();++unit) { const Array* array = _texCoordList[unit].first.get(); if (array) state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer()); else state.disableTexCoordPointer(unit); } state.disableTexCoordPointersAboveAndIncluding(unit); if( handleVertexAttributes ) { unsigned int index; for( index = 0; index < _vertexAttribList.size(); ++index ) { const Array* array = _vertexAttribList[index].second.first.get(); const AttributeBinding ab = _vertexAttribBindingList[index]; if( ab == BIND_PER_VERTEX && array ) { state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), _vertexAttribList[index].first, 0, array->getDataPointer() ); } else { if( array ) { const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); if( indexArray && indexArray->getNumElements() > 0 ) { drawVertexAttribMap[ab].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); } else { drawVertexAttribMap[ab].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); } } state.disableVertexAttribPointer( index ); } } state.disableVertexAttribPointersAboveAndIncluding( index ); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // pass the overall binding values onto OpenGL. // if (_normalBinding==BIND_OVERALL) drawNormal(normalIndex++); if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // draw the primitives themselves. // for(PrimitiveSetList::const_iterator itr=_primitives.begin(); itr!=_primitives.end(); ++itr) { if (_normalBinding==BIND_PER_PRIMITIVE_SET) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } (*itr)->draw(); } if (usingVertexBufferObjects) { extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); } } else { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // slow path. // typedef std::vector< ref_ptr > DrawTexCoordList; DrawTexCoordList drawTexCoordList; drawTexCoordList.reserve(_texCoordList.size()); // fallback if multitexturing not supported. ref_ptr drawTextCoord; if (extensions->isMultiTexSupported()) { // multitexture supported.. for(unsigned int unit=0;unit!=_texCoordList.size();++unit) { const ArrayPair& texcoordPair = _texCoordList[unit]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) { if (texcoordPair.second->getNumElements()>0) { drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordPair.first.get(),texcoordPair.second.get(), extensions)); } } else { drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordPair.first.get(),0, extensions)); } } } } else { if (!_texCoordList.empty()) { const ArrayPair& texcoordPair = _texCoordList[0]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) { if (texcoordPair.second->getNumElements()>0) { drawTextCoord = new DrawTexCoord(texcoordPair.first.get(),texcoordPair.second.get()); } } else { drawTextCoord = new DrawTexCoord(texcoordPair.first.get(),0); } } } } if(handleVertexAttributes) { unsigned int index; for( index = 1; index < _vertexAttribList.size(); ++index ) { const Array* array = _vertexAttribList[index].second.first.get(); if( array && array->getNumElements() > 0 ) { const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); if( indexArray && indexArray->getNumElements() > 0 ) { drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); } else { drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); } } } } // disable all the vertex arrays in the slow path as we are // sending everything using glVertex etc. state.disableAllVertexArrays(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // pass the overall binding values onto OpenGL. // if (_normalBinding==BIND_OVERALL) drawNormal(normalIndex++); if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } // set up vertex functor. DrawVertex drawVertex(_vertexArray.get(),_vertexIndices.get()); bool useVertexAttrib = _vertexAttribList.size() > 0 && _vertexAttribList[0].second.first.valid() && _vertexAttribList[0].second.first->getNumElements(); ref_ptr drawVertexAttribZero; if( useVertexAttrib ) { drawVertexAttribZero = new DrawVertexAttrib(extensions,0, _vertexAttribList[0].first,_vertexAttribList[0].second.first.get(), _vertexAttribList[0].second.second.get()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // draw the primitives themselves. // for(PrimitiveSetList::const_iterator itr=_primitives.begin(); itr!=_primitives.end(); ++itr) { if (_normalBinding==BIND_PER_PRIMITIVE_SET) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } const PrimitiveSet* primitiveset = itr->get(); GLenum mode=primitiveset->getMode(); unsigned int primLength; switch(mode) { case(GL_POINTS): primLength=1; break; case(GL_LINES): primLength=2; break; case(GL_TRIANGLES): primLength=3; break; case(GL_QUADS): primLength=4; break; default: primLength=0; break; // compute later when =0. } // draw primtives by the more flexible "slow" path, // sending OpenGL glBegin/glVertex.../glEnd(). switch(primitiveset->getType()) { case(PrimitiveSet::DrawArraysPrimitiveType): { if (primLength==0) primLength=primitiveset->getNumIndices(); const DrawArrays* drawArray = static_cast(primitiveset); glBegin(mode); unsigned int primCount=0; unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount(); for(unsigned int vindex=drawArray->getFirst(); vindex(primitiveset); unsigned int vindex=drawArrayLengths->getFirst(); for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin(); primItr!=drawArrayLengths->end(); ++primItr) { unsigned int localPrimLength; if (primLength==0) localPrimLength=*primItr; else localPrimLength=primLength; glBegin(mode); for(GLsizei primCount=0;primCount<*primItr;++primCount) { if ((primCount%localPrimLength)==0) { if (_normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } } if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); ++texItr) { (*(*texItr))(vindex); } if (drawTextCoord.valid()) (*drawTextCoord)(vindex); if( useVertexAttrib ) { (*drawVertexAttribZero)(vindex); } else { drawVertex(vindex); } ++vindex; } glEnd(); } break; } case(PrimitiveSet::DrawElementsUBytePrimitiveType): { if (primLength==0) primLength=primitiveset->getNumIndices(); const DrawElementsUByte* drawElements = static_cast(primitiveset); glBegin(mode); unsigned int primCount=0; for(DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) { if ((primCount%primLength)==0) { if (_normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } } unsigned int vindex=*primItr; if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); if ( extensions->isVertexProgramSupported() ) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); ++texItr) { (*(*texItr))(vindex); } if (drawTextCoord.valid()) (*drawTextCoord)(vindex); if( useVertexAttrib ) { (*drawVertexAttribZero)(vindex); } else { drawVertex(vindex); } } glEnd(); break; } case(PrimitiveSet::DrawElementsUShortPrimitiveType): { if (primLength==0) primLength=primitiveset->getNumIndices(); const DrawElementsUShort* drawElements = static_cast(primitiveset); glBegin(mode); unsigned int primCount=0; for(DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) { if ((primCount%primLength)==0) { if (_normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } } unsigned int vindex=*primItr; if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); ++texItr) { (*(*texItr))(vindex); } if (drawTextCoord.valid()) (*drawTextCoord)(vindex); if( useVertexAttrib ) { (*drawVertexAttribZero)(vindex); } else { drawVertex(vindex); } } glEnd(); break; } case(PrimitiveSet::DrawElementsUIntPrimitiveType): { if (primLength==0) primLength=primitiveset->getNumIndices(); const DrawElementsUInt* drawElements = static_cast(primitiveset); glBegin(mode); unsigned int primCount=0; for(DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) { if ((primCount%primLength)==0) { if (_normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); if ( extensions->isVertexProgramSupported() ) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } } unsigned int vindex=*primItr; if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); if ( extensions->isVertexProgramSupported() ) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; for( unsigned int i = 0; i < list.size(); ++i ) { ( *( list[i] ) )(vertexAttribIndex++); } } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); ++texItr) { (*(*texItr))(vindex); } if (drawTextCoord.valid()) (*drawTextCoord)(vindex); if( useVertexAttrib ) { (*drawVertexAttribZero)(vindex); } else { drawVertex(vindex); } } glEnd(); break; } default: { break; } } } } } class AttrbuteFunctorArrayVisitor : public ArrayVisitor { public: AttrbuteFunctorArrayVisitor(Drawable::AttributeFunctor& af): _af(af) {} virtual ~AttrbuteFunctorArrayVisitor() {} virtual void apply(ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(UByte4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } inline void applyArray(Drawable::AttributeType type,Array* array) { if (array) { _type = type; array->accept(*this); } } Drawable::AttributeFunctor& _af; Drawable::AttributeType _type; }; void Geometry::accept(AttributeFunctor& af) { AttrbuteFunctorArrayVisitor afav(af); afav.applyArray(VERTICES,_vertexArray.get()); afav.applyArray(NORMALS,_normalArray.get()); afav.applyArray(COLORS,_colorArray.get()); for(unsigned unit=0;unit<_texCoordList.size();++unit) { afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].first.get()); } } class ConstAttrbuteFunctorArrayVisitor : public ConstArrayVisitor { public: ConstAttrbuteFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af): _af(af) {} virtual ~ConstAttrbuteFunctorArrayVisitor() {} virtual void apply(const ByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const ShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const IntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const UByteArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const UShortArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const UIntArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const UByte4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const FloatArray& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const Vec2Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const Vec3Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } virtual void apply(const Vec4Array& array) { if (!array.empty()) _af.apply(_type,array.size(),&(array.front())); } inline void applyArray(Drawable::AttributeType type,const Array* array) { if (array) { _type = type; array->accept(*this); } } Drawable::ConstAttributeFunctor& _af; Drawable::AttributeType _type; }; void Geometry::accept(ConstAttributeFunctor& af) const { ConstAttrbuteFunctorArrayVisitor afav(af); afav.applyArray(VERTICES,_vertexArray.get()); afav.applyArray(NORMALS,_normalArray.get()); afav.applyArray(COLORS,_colorArray.get()); for(unsigned unit=0;unit<_texCoordList.size();++unit) { afav.applyArray((AttributeType)(TEXTURE_COORDS_0+unit),_texCoordList[unit].first.get()); } } void Geometry::accept(PrimitiveFunctor& functor) const { if (!_vertexArray.valid() || _vertexArray->getNumElements()==0) return; if (!_vertexIndices.valid()) { switch(_vertexArray->getType()) { case(Array::Vec2ArrayType): functor.setVertexArray(_vertexArray->getNumElements(),static_cast(_vertexArray->getDataPointer())); break; case(Array::Vec3ArrayType): functor.setVertexArray(_vertexArray->getNumElements(),static_cast(_vertexArray->getDataPointer())); break; case(Array::Vec4ArrayType): functor.setVertexArray(_vertexArray->getNumElements(),static_cast(_vertexArray->getDataPointer())); break; default: notify(WARN)<<"Warning: Geometry::accept(PrimtiveFunctor&) cannot handle Vertex Array type"<<_vertexArray->getType()<accept(functor); } } else { const Vec2Array* vec2Array = 0; const Vec3Array* vec3Array = 0; const Vec4Array* vec4Array = 0; Array::Type type = _vertexArray->getType(); switch(type) { case(Array::Vec2ArrayType): vec2Array = static_cast(_vertexArray.get()); break; case(Array::Vec3ArrayType): vec3Array = static_cast(_vertexArray.get()); break; case(Array::Vec4ArrayType): vec4Array = static_cast(_vertexArray.get()); break; default: notify(WARN)<<"Warning: Geometry::accept(PrimtiveFunctor&) cannot handle Vertex Array type"<<_vertexArray->getType()<get(); GLenum mode=primitiveset->getMode(); switch(primitiveset->getType()) { case(PrimitiveSet::DrawArraysPrimitiveType): { const DrawArrays* drawArray = static_cast(primitiveset); functor.begin(mode); unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount(); for(unsigned int vindex=drawArray->getFirst(); vindexindex(vindex)]); break; case(Array::Vec3ArrayType): functor.vertex((*vec3Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec4ArrayType): functor.vertex((*vec4Array)[_vertexIndices->index(vindex)]); break; default: break; } } functor.end(); break; } case(PrimitiveSet::DrawArrayLengthsPrimitiveType): { const DrawArrayLengths* drawArrayLengths = static_cast(primitiveset); unsigned int vindex=drawArrayLengths->getFirst(); for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin(); primItr!=drawArrayLengths->end(); ++primItr) { functor.begin(mode); for(GLsizei primCount=0;primCount<*primItr;++primCount) { switch(type) { case(Array::Vec2ArrayType): functor.vertex((*vec2Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec3ArrayType): functor.vertex((*vec3Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec4ArrayType): functor.vertex((*vec4Array)[_vertexIndices->index(vindex)]); break; default: break; } ++vindex; } functor.end(); } break; } case(PrimitiveSet::DrawElementsUBytePrimitiveType): { const DrawElementsUByte* drawElements = static_cast(primitiveset); functor.begin(mode); unsigned int primCount=0; for(DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) { unsigned int vindex=*primItr; switch(type) { case(Array::Vec2ArrayType): functor.vertex((*vec2Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec3ArrayType): functor.vertex((*vec3Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec4ArrayType): functor.vertex((*vec4Array)[_vertexIndices->index(vindex)]); break; default: break; } } functor.end(); break; } case(PrimitiveSet::DrawElementsUShortPrimitiveType): { const DrawElementsUShort* drawElements = static_cast(primitiveset); functor.begin(mode); for(DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primItr) { unsigned int vindex=*primItr; switch(type) { case(Array::Vec2ArrayType): functor.vertex((*vec2Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec3ArrayType): functor.vertex((*vec3Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec4ArrayType): functor.vertex((*vec4Array)[_vertexIndices->index(vindex)]); break; default: break; } } functor.end(); break; } case(PrimitiveSet::DrawElementsUIntPrimitiveType): { const DrawElementsUInt* drawElements = static_cast(primitiveset); functor.begin(mode); for(DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primItr) { unsigned int vindex=*primItr; switch(type) { case(Array::Vec2ArrayType): functor.vertex((*vec2Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec3ArrayType): functor.vertex((*vec3Array)[_vertexIndices->index(vindex)]); break; case(Array::Vec4ArrayType): functor.vertex((*vec4Array)[_vertexIndices->index(vindex)]); break; default: break; } } functor.end(); break; } default: { break; } } } } return; } bool Geometry::verifyBindings() const { switch(_normalBinding) { case(BIND_OFF): if (_normalArray.valid() && _normalArray->getNumElements()>0) return false; break; case(BIND_OVERALL): if (!_normalArray.valid()) return false; if (_normalArray->getNumElements()!=1) return false; break; case(BIND_PER_PRIMITIVE_SET): if (!_normalArray.valid()) return false; if (_normalArray->getNumElements()!=_primitives.size()) return false; break; case(BIND_PER_PRIMITIVE): if (!_normalArray.valid()) return false; break; case(BIND_PER_VERTEX): if (_vertexArray.valid()) { if (!_normalArray.valid()) return false; if (_normalArray->getNumElements()!=_vertexArray->getNumElements()) return false; } else if (_normalArray.valid() && _normalArray->getNumElements()==0) return false; break; } switch(_colorBinding) { case(BIND_OFF): if (_colorArray.valid() && _colorArray->getNumElements()>0) return false; break; case(BIND_OVERALL): if (!_colorArray.valid()) return false; if (_colorArray->getNumElements()!=1) return false; break; case(BIND_PER_PRIMITIVE_SET): if (!_colorArray.valid()) return false; if (_colorArray->getNumElements()!=_primitives.size()) return false; break; case(BIND_PER_PRIMITIVE): if (!_colorArray.valid()) return false; break; case(BIND_PER_VERTEX): if (_vertexArray.valid()) { if (!_colorArray.valid()) return false; if (_colorArray->getNumElements()!=_vertexArray->getNumElements()) return false; } else if (_colorArray.valid() && _colorArray->getNumElements()==0) return false; break; } for(TexCoordArrayList::const_iterator itr=_texCoordList.begin(); itr!=_texCoordList.end(); ++itr) { const Array* array = itr->first.get(); if (_vertexArray.valid()) { if (array && array->getNumElements()!=_vertexArray->getNumElements()) return false; } else if (array && array->getNumElements()==0) return false; } return true; } void Geometry::computeCorrectBindingsAndArraySizes() { if (verifyBindings()) return; if (!_vertexArray.valid() || _vertexArray->getNumElements()==0) { // no vertex array so switch everything off. _vertexArray = 0; _colorArray = 0; _colorBinding = BIND_OFF; _normalArray = 0; _normalBinding = BIND_OFF; _texCoordList.clear(); notify(INFO)<<"Info: remove redundent attribute arrays from empty osg::Geometry"<getNumElements()==0) { _normalArray = 0; _normalBinding = BIND_OFF; } else if (_normalArray->getNumElements()>1) { // trim the array down to 1 element long. _normalArray->erase(_normalArray->begin()+1,_normalArray->end()); } break; case(BIND_PER_PRIMITIVE_SET): if (!_normalArray.valid()) { _normalBinding = BIND_OFF; } else if (_normalArray->getNumElements()<_primitives.size()) { _normalArray = 0; _normalBinding = BIND_OFF; } else if (_normalArray->getNumElements()>_primitives.size()) { // trim the array down to size of the number of primitives. _normalArray->erase(_normalArray->begin()+_primitives.size(),_normalArray->end()); } break; case(BIND_PER_PRIMITIVE): break; case(BIND_PER_VERTEX): if (!_normalArray.valid()) { _normalBinding = BIND_OFF; } else if (_normalArray->getNumElements()<_vertexArray->getNumElements()) { _normalArray = 0; _normalBinding = BIND_OFF; } else if (_normalArray->getNumElements()>_vertexArray->getNumElements()) { // trim the array down to size of the number of primitives. _normalArray->erase(_normalArray->begin()+_vertexArray->getNumElements(),_normalArray->end()); } break; } // TODO colours and tex coords. } class ExpandIndexedArray : public osg::ConstArrayVisitor { public: ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray): _indices(indices), _targetArray(targetArray) {} template T* create(const T& array,const I& indices) { T* newArray = 0; // if source array type and target array type are equal if (_targetArray && _targetArray->getType()==array.getType()) { // reuse exisiting target array newArray = static_cast(_targetArray); if (newArray->size()!=indices.size()) { // make sure its the right size newArray->resize(indices.size()); } } else { // else create a new array. newArray = new T(indices.size()); } for(unsigned int i=0;i T* 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; } } 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); } virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); } virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); } virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); } virtual void apply(const osg::UByte4Array& array) { _targetArray = create(array); } virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); } virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); } virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); } virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); } const osg::IndexArray& _indices; osg::Array* _targetArray; }; bool Geometry::suitableForOptimization() const { bool hasIndices = false; if (getVertexIndices()) hasIndices = true; if (getNormalIndices()) hasIndices = true; if (getColorIndices()) hasIndices = true; if (getSecondaryColorIndices()) hasIndices = true; if (getFogCoordIndices()) hasIndices = true; for(unsigned int ti=0;tiaccept(eia); target.setVertexArray(eia._targetArray); target.setVertexIndices(0); } else if (getVertexArray()) { target.setVertexArray(getVertexArray()); } target.setNormalBinding(getNormalBinding()); if (getNormalIndices()) { ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray()); getNormalArray()->accept(eia); target.setNormalArray(dynamic_cast(eia._targetArray)); target.setNormalIndices(0); } else if (getNormalArray()) { target.setNormalArray(getNormalArray()); } target.setColorBinding(getColorBinding()); if (getColorIndices()) { ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray()); getColorArray()->accept(eia); target.setColorArray(eia._targetArray); target.setColorIndices(0); } else if (getColorArray()) { target.setColorArray(getColorArray()); } target.setSecondaryColorBinding(getSecondaryColorBinding()); if (getSecondaryColorIndices()) { ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray()); getSecondaryColorArray()->accept(eia); target.setSecondaryColorArray(eia._targetArray); target.setSecondaryColorIndices(0); } else if (getSecondaryColorArray()) { target.setSecondaryColorArray(getSecondaryColorArray()); } target.setFogCoordBinding(getFogCoordBinding()); if (getFogCoordIndices()) { ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray()); getFogCoordArray()->accept(eia); target.setFogCoordArray(eia._targetArray); target.setFogCoordIndices(0); } else if (getFogCoordArray()) { target.setFogCoordArray(getFogCoordArray()); } for(unsigned int ti=0;tiaccept(eia); target.setTexCoordArray(ti,eia._targetArray); target.setTexCoordIndices(ti,0); } else if (getTexCoordArray(ti)) { target.setTexCoordArray(ti,getTexCoordArray(ti)); } } for(unsigned int vi=0;viaccept(eia); getVertexAttribNormalize(vi,normalize); target.setVertexAttribArray(vi,normalize,eia._targetArray,vab); target.setVertexAttribIndices(vi,0); } else if (getVertexAttribArray(vi)) { GLboolean normalize; getVertexAttribNormalize(vi,normalize); target.setVertexAttribArray(vi,normalize,getVertexAttribArray(vi),vab); } } } void Geometry::computeInternalOptimizedGeometry() { if (suitableForOptimization()) { if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry; copyToAndOptimize(*_internalOptimizedGeometry); } } Geometry* osg::createTexturedQuadGeometry(const osg::Vec3& corner,const osg::Vec3& widthVec,const osg::Vec3& heightVec) { Geometry* geom = new Geometry; Vec3Array* coords = new Vec3Array(4); (*coords)[0] = corner+heightVec; (*coords)[1] = corner; (*coords)[2] = corner+widthVec; (*coords)[3] = corner+widthVec+heightVec; geom->setVertexArray(coords); Vec2Array* tcoords = new Vec2Array(4); (*tcoords)[0].set(0.0f,1.0f); (*tcoords)[1].set(0.0f,0.0f); (*tcoords)[2].set(1.0f,0.0f); (*tcoords)[3].set(1.0f,1.0f); geom->setTexCoordArray(0,tcoords); osg::Vec4Array* colours = new osg::Vec4Array(1); (*colours)[0].set(1.0f,1.0f,1.0,1.0f); geom->setColorArray(colours); geom->setColorBinding(Geometry::BIND_OVERALL); osg::Vec3Array* normals = new osg::Vec3Array(1); (*normals)[0] = widthVec^heightVec; (*normals)[0].normalize(); geom->setNormalArray(normals); geom->setNormalBinding(Geometry::BIND_OVERALL); geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4)); return geom; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// // experimental templated rendering code, please ignore... // will move to osg::Geometry once complete. // Robert Osfield, August 2003. #if 0 struct DrawAttributeArrays { virtual bool valid() const = 0; virtual void set(osg::Geometry* geometry) = 0; virtual unsigned int draw(unsigned int index, unsigned int count) const = 0; }; struct V3 { V3():_array(0) {} bool valid() const { return _array!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getVertexArray(); if (array && array->getType()==osg::Array::Vec3ArrayType) { osg::Vec3Array* vec3array = static_cast(array); if (!vec3array->empty()) _array = &(vec3array->front()); } } inline void draw(unsigned int index) const { glVertex3fv(_array[index].ptr()); } osg::Vec3* _array; }; struct V3USI { V3USI():_array(0),_indices(0) {} bool valid() const { return _array!=0 && _indices!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getVertexArray(); if (array && array->getType()==osg::Array::Vec3ArrayType) { osg::Vec3Array* vec3array = static_cast(array); if (!vec3array->empty()) _array = &(vec3array->front()); } _indices = 0; osg::IndexArray* indices = geometry->getVertexIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushort3array = static_cast(array); if (!ushort3array->empty()) _indices = &(ushort3array->front()); } } inline void draw(unsigned int index) const { glVertex3fv(_array[_indices[index]].ptr()); } osg::Vec3* _array; unsigned short* _indices; }; ////////////////////////////// struct N3 { N3():_array(0) {} bool valid() const { return _array!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getVertexArray(); if (array && array->getType()==osg::Array::Vec3ArrayType) { osg::Vec3Array* vec3array = static_cast(array); if (!vec3array->empty()) _array = &(vec3array->front()); } } inline void draw(unsigned int index) const { glNormal3fv(_array[index].ptr()); } osg::Vec3* _array; }; struct N3USI { N3USI():_array(0),_indices(0) {} bool valid() const { return _array!=0 && _indices!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getVertexArray(); if (array && array->getType()==osg::Array::Vec3ArrayType) { osg::Vec3Array* vec3array = static_cast(array); if (!vec3array->empty()) _array = &(vec3array->front()); } _indices = 0; osg::IndexArray* indices = geometry->getVertexIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushortarray = static_cast(array); if (!ushortarray->empty()) _indices = &(ushortarray->front()); } } inline void draw(unsigned int index) const { glNormal3fv(_array[_indices[index]].ptr()); } osg::Vec3* _array; unsigned short* _indices; }; ////////////////////////////// struct C4 { C4():_array(0) {} bool valid() const { return _array!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getColorArray(); if (array && array->getType()==osg::Array::Vec4ArrayType) { osg::Vec4Array* vec4array = static_cast(array); if (!vec4array->empty()) _array = &(vec4array->front()); } } inline void draw(unsigned int index) const { glVertex3fv(_array[index].ptr()); } osg::Vec4* _array; }; struct C4USI { C4USI():_array(0),_indices(0) {} bool valid() const { return _array!=0 && _indices!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getColorArray(); if (array && array->getType()==osg::Array::Vec4ArrayType) { osg::Vec4Array* vec4array = static_cast(array); if (!vec4array->empty()) _array = &(vec4array->front()); } _indices = 0; osg::IndexArray* indices = geometry->getColorIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushortarray = static_cast(array); if (!ushortarray->empty()) _indices = &(ushortarray->front()); } } inline void draw(unsigned int index) const { glColor4fv(_array[_indices[index]].ptr()); } osg::Vec4* _array; unsigned short* _indices; }; ////////////////////////////// struct T2 { T2():_array(0) {} bool valid() const { return _array!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getTexCoordArray(0); if (array && array->getType()==osg::Array::Vec2ArrayType) { osg::Vec2Array* vec2array = static_cast(array); if (!vec2array->empty()) _array = &(vec2array->front()); } } inline void draw(unsigned int index) const { glTexCoord2fv(_array[index].ptr()); } osg::Vec2* _array; }; struct T2USI { T2USI():_array(0),_indices(0) {} bool valid() const { return _array!=0 && _indices!=0; } void set(osg::Geometry* geometry) { _array = 0; osg::Array* array = geometry->getTexCoordArray(0); if (array && array->getType()==osg::Array::Vec2ArrayType) { osg::Vec2Array* vec2array = static_cast(array); if (!vec2array->empty()) _array = &(vec2array->front()); } _indices = 0; osg::IndexArray* indices = geometry->getTexCoordIndices(0); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushortarray = static_cast(array); if (!ushortarray->empty()) _indices = &(ushortarray->front()); } } inline void draw(unsigned int index) const { glTexCoord2fv(_array[_indices[index]].ptr()); } osg::Vec2* _array; unsigned short* _indices; }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template < class T1 > struct DrawAttributeArrays_T : public DrawAttributeArrays { DrawAttributeArrays_T(osg::Geometry* geometry) { } virtual bool valid() const { return _t1.valid(); } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TT : public DrawAttributeArrays { DrawAttributeArrays_TT() { } virtual bool valid() const { return _t1.valid() && _t2.valid(); } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TTT : public DrawAttributeArrays { DrawAttributeArrays_TTT() { } virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid(); } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); _t3.set(geometry); } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TTTT : public DrawAttributeArrays { DrawAttributeArrays_TTTT() { } virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid(); } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); _t3.set(geometry); _t4.set(geometry); } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TT_USI : public DrawAttributeArrays { DrawAttributeArrays_TT_USI() { } virtual bool valid() const { return _t1.valid() && _t2.valid() && _indices!=0; } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); _indices = 0; osg::IndexArray* indices = geometry->getVertexIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushort3array = static_cast(array); if (!ushort3array->empty()) _indices = &(ushort3array->front()); } } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TTT_USI : public DrawAttributeArrays { DrawAttributeArrays_TTT_USI() { } virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _indices!=0; } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); _t3.set(geometry); _indices = 0; osg::IndexArray* indices = geometry->getVertexIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushort3array = static_cast(array); if (!ushort3array->empty()) _indices = &(ushort3array->front()); } } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i struct DrawAttributeArrays_TTTT_USI : public DrawAttributeArrays { DrawAttributeArrays_TTTT_USI() { } virtual bool valid() const { return _t1.valid() && _t2.valid() && _t3.valid() && _t4.valid() && _indices!=0; } virtual void set(osg::Geometry* geometry) { _t1.set(geometry); _t2.set(geometry); _t3.set(geometry); _t4.set(geometry); _indices = 0; osg::IndexArray* indices = geometry->getVertexIndices(); if (indices && indices->getType()==osg::Array::UShortArrayType) { osg::UShortArray* ushort3array = static_cast(array); if (!ushort3array->empty()) _indices = &(ushort3array->front()); } } virtual unsigned int draw(unsigned int index, unsigned int count) const { for(unsigned int i=0;i DrawAttributeArrays_V3; typedef DrawAttributeArrays_T DrawAttributeArrays_V3i; // Two attributes x 15 typedef DrawAttributeArrays_TT DrawAttributeArrays_N3V3; typedef DrawAttributeArrays_TT DrawAttributeArrays_N3iV3; typedef DrawAttributeArrays_TT DrawAttributeArrays_N3V3i; typedef DrawAttributeArrays_TT DrawAttributeArrays_N3iV3i; typedef DrawAttributeArrays_TT_USI DrawAttributeArrays_N3V3_i; typedef DrawAttributeArrays_TT DrawAttributeArrays_C4V3; typedef DrawAttributeArrays_TT DrawAttributeArrays_C4iV3; typedef DrawAttributeArrays_TT DrawAttributeArrays_C4V3i; typedef DrawAttributeArrays_TT DrawAttributeArrays_C4iV3i; typedef DrawAttributeArrays_TT_USI DrawAttributeArrays_C4V3_i; typedef DrawAttributeArrays_TT DrawAttributeArrays_T2V3; typedef DrawAttributeArrays_TT DrawAttributeArrays_T2iV3; typedef DrawAttributeArrays_TT DrawAttributeArrays_T2V3i; typedef DrawAttributeArrays_TT DrawAttributeArrays_T2iV3i; typedef DrawAttributeArrays_TT_USI DrawAttributeArrays_T2V3_i; // Three attributes x 27 typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4N3V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4iN3V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4N3iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4iN3iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4N3V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4iN3V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4N3iV3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_C4iN3iV3i; typedef DrawAttributeArrays_TTT_USI DrawAttributeArrays_C4N3V3_i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2N3V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iN3V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iN3iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2N3iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2N3V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iN3V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iN3iV3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2N3iV3i; typedef DrawAttributeArrays_TTT_USI DrawAttributeArrays_T2N3V3_i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2C4V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iC4V3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2C4iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iC4iV3; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2C4V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iC4V3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2C4iV3i; typedef DrawAttributeArrays_TTT DrawAttributeArrays_T2iC4iV3i; typedef DrawAttributeArrays_TTT_USI DrawAttributeArrays_T2C4V3_t; // Four attributes x 17 typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4N3V3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4N3V3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4iN3V3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4iN3V3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4N3iV3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4N3iV3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4iN3iV3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4iN3iV3; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4N3V3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4N3V3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4iN3V3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4iN3V3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4N3iV3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4N3iV3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2C4iN3iV3i; typedef DrawAttributeArrays_TTTT DrawAttributeArrays_T2iC4iN3iV3i; typedef DrawAttributeArrays_TTTT_USI DrawAttributeArrays_T2C4N3V3_i; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif