/* -*-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. */ #if defined(_MSC_VER) #pragma warning( disable : 4786 ) #endif #include #include #include #include using namespace osg; #define DEBUG #define DO_SHADING 1 #define I_ON (1<<4) #define C_ON (1<<3) #define N_ON (1<<2) #define T_ON (1<<1) #define V_ON (1<<0) void GeoSet::set_fast_path( void ) { if( _iaformat != IA_OFF ) { _fast_path = I_ON; } else { if( ( _normal_binding != BIND_PERPRIM) && ( _nindex.null() || _nindex ==_cindex) && ( _color_binding != BIND_PERPRIM) && ( _colindex.null() || _colindex ==_cindex ) && ( _primtype != FLAT_LINE_STRIP ) && ( _primtype != FLAT_TRIANGLE_STRIP ) && ( _primtype != FLAT_TRIANGLE_FAN ) ) _fast_path = V_ON; else { _fast_path = 0; #ifdef DEBUG if( _normal_binding == BIND_PERPRIM ) notify( DEBUG ) << "Geoset - Failed fast path because NORMALS are bound PER_PRIM\n"; if( _nindex.valid() ) notify( DEBUG ) << "Geoset - Failed fast path because NORMAL indeces are specified\n"; if( _color_binding == BIND_PERPRIM ) notify( DEBUG ) << "Geoset - Failed fast path because COLORS are bound PER_PRIM\n"; if( _cindex.valid() ) notify( DEBUG ) << "Geoset - Failed fast path because COLOR indeces are specified\n"; if( _primtype == FLAT_LINE_STRIP ) notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_LINE_STRIP\n"; if ( _primtype == FLAT_TRIANGLE_STRIP ) notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_TRIANGLE_STRIP\n"; if ( _primtype == FLAT_TRIANGLE_FAN ) notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_TRIANGLE_FAN\n"; #endif } if( _fast_path ) { if( _color_binding == BIND_PERVERTEX ) _fast_path |= C_ON; if( _normal_binding == BIND_PERVERTEX ) _fast_path |= N_ON; if( _texture_binding == BIND_PERVERTEX ) _fast_path |= T_ON; } } #ifdef DEBUG notify(INFO) << "GeoSet - fast path = " << _fast_path << "\n"; #endif } void GeoSet::draw_fast_path( State& state ) const { IndexPointer ocindex = _cindex; switch( _fast_path ) { case (I_ON) : _cindex = _iaindex; glInterleavedArrays( (GLenum)_ogliaformat, 0, _iarray ); break; case (V_ON) : state.disableNormalPointer(); state.disableColorPointer(); state.disableTexCoordPointersAboveAndIncluding(0); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glDisableClientState( GL_COLOR_ARRAY ); // glDisableClientState( GL_NORMAL_ARRAY ); // glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (T_ON|V_ON) : state.disableNormalPointer(); state.disableColorPointer(); state.setTexCoordPointer(0, 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); state.disableTexCoordPointersAboveAndIncluding(1); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glDisableClientState( GL_COLOR_ARRAY ); // glDisableClientState( GL_NORMAL_ARRAY ); // glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (N_ON|V_ON) : state.disableColorPointer(); state.disableTexCoordPointersAboveAndIncluding(0); state.setVertexPointer(3, GL_FLOAT, 0,_coords); state.setNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); // glDisableClientState( GL_COLOR_ARRAY ); // glEnableClientState( GL_NORMAL_ARRAY ); // glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); // glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (N_ON|T_ON|V_ON) : state.disableColorPointer(); state.setNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); state.setTexCoordPointer(0, 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); state.disableTexCoordPointersAboveAndIncluding(1); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glDisableClientState( GL_COLOR_ARRAY ); // glEnableClientState( GL_NORMAL_ARRAY ); // glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); // glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (C_ON|V_ON) : state.disableNormalPointer(); state.disableTexCoordPointersAboveAndIncluding(0); state.setColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glEnableClientState( GL_COLOR_ARRAY ); // glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); // glDisableClientState( GL_NORMAL_ARRAY ); // glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (C_ON|T_ON|V_ON) : state.disableNormalPointer(); state.setColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); state.setTexCoordPointer(0, 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); state.disableTexCoordPointersAboveAndIncluding(1); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glEnableClientState( GL_COLOR_ARRAY ); // glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); // glDisableClientState( GL_NORMAL_ARRAY ); // glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (C_ON|N_ON|V_ON) : state.disableTexCoordPointersAboveAndIncluding(0); state.setNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); state.setColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glEnableClientState( GL_COLOR_ARRAY ); // glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); // glEnableClientState( GL_NORMAL_ARRAY ); // glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); // glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; case (C_ON|N_ON|T_ON|V_ON) : state.setNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); state.setColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); state.setTexCoordPointer(0, 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); state.disableTexCoordPointersAboveAndIncluding(1); state.setVertexPointer(3, GL_FLOAT, 0,_coords); // glEnableClientState( GL_COLOR_ARRAY ); // glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); // glEnableClientState( GL_NORMAL_ARRAY ); // glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); // glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); break; } if( _color_binding == BIND_OVERALL ) { if( _colindex.valid() ) glColor4fv( (GLfloat * )&_colors[_colindex[0]] ); else glColor4fv( (GLfloat * )&_colors[0] ); } if( _normal_binding == BIND_OVERALL ) { if( _nindex.valid() ) glNormal3fv( (GLfloat * )&_normals[_nindex[0]] ); else glNormal3fv( (GLfloat * )&_normals[0] ); } if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP, // TRIANGLE_FAN, QUAD_STRIP, POLYGONS { int index = 0; if( _primLengths == (int *)0 ) { notify(WARN) << "GeoSet->draw() : " "Primitive lengths required\n"; return; } for( int i = 0; i < _numprims; i++ ) { if( _cindex.valid() ) { if (_cindex._is_ushort) glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_SHORT, &_cindex._ptr._ushort[index] ); else glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_INT, &_cindex._ptr._uint[index] ); } else glDrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] ); index += _primLengths[i]; } } else // POINTS, LINES, TRIANGLES, QUADS { if( _cindex.valid()) { if (_cindex._is_ushort) glDrawElements( (GLenum)_oglprimtype, _cindex._size, GL_UNSIGNED_SHORT, _cindex._ptr._ushort ); else glDrawElements( (GLenum)_oglprimtype, _cindex._size, GL_UNSIGNED_INT, _cindex._ptr._uint ); } else glDrawArrays( (GLenum)_oglprimtype, 0, _numcoords ); } _cindex = ocindex; } void GeoSet::draw_alternate_path( State& state ) const { if( (_color_binding == BIND_PERVERTEX) && (_colindex.null() || _colindex ==_cindex) && (_flat_shaded_skip == 0) ) { // glEnableClientState( GL_COLOR_ARRAY ); // glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); state.setColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors ); } else { // glDisableClientState( GL_COLOR_ARRAY ); state.disableColorPointer(); if( _color_binding == BIND_OVERALL ) { if( _colindex.valid() ) glColor4fv( (GLfloat *)&_colors[_colindex[0]] ); else glColor4fv( (GLfloat *)&_colors[0] ); } } if( (_normal_binding == BIND_PERVERTEX) && (_nindex.null() || _nindex ==_cindex) && (_flat_shaded_skip == 0) ) { // glEnableClientState( GL_NORMAL_ARRAY ); // glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); state.setNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals ); } else { state.disableNormalPointer(); // glDisableClientState( GL_NORMAL_ARRAY ); if( _normal_binding == BIND_OVERALL ) { if( _nindex.valid() ) glNormal3fv( (GLfloat *)&_normals[_nindex[0]] ); else glNormal3fv( (GLfloat *)&_normals[0] ); } } if( (_texture_binding == BIND_PERVERTEX) && (_tindex.null()) ) { // glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // glTexCoordPointer( 2, GL_FLOAT, 0, _tcoords ); state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, _tcoords ); state.disableTexCoordPointersAboveAndIncluding(1); } else state.disableTexCoordPointersAboveAndIncluding(0); // glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // glEnableClientState( GL_VERTEX_ARRAY ); // glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); state.setVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords ); if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP, // TRIANGLE_FAN, QUAD_STRIP, POLYGONS // FLAT_LINE_STRIP, FLAT_TRIANGLE_STRIP, FLAT_TRIANGLE_FAN { int i, j; int index = 0; int ai = 0; int ci = 0; int ni = 0; int ti = 0; if( _primLengths == (int *)0 ) { notify(WARN) << "GeoSet->draw() : " "Primitive lengths required\n"; return; } if( _flat_shaded_skip ) { #ifdef DO_SHADING glShadeModel( GL_FLAT ); #endif } for( i = 0; i < _numprims; i++ ) { if( _color_binding == BIND_PERPRIM ) { if( _colindex.valid() ) glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] ); else glColor4fv( (GLfloat *)&_colors[ci++] ); } if( _normal_binding == BIND_PERPRIM ) { if( _nindex.valid() ) glNormal3fv( (GLfloat *)&_normals[_nindex[ni++]] ); else glNormal3fv( (GLfloat *)&_normals[ni++] ); } if( _flat_shaded_skip ) { glBegin( (GLenum)_oglprimtype ); for( j = 0; j < _primLengths[i]; j++ ) { if( j >= _flat_shaded_skip ) { if( _color_binding == BIND_PERVERTEX ) { if( (_colindex.valid()) ) glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] ); else glColor4fv( (GLfloat *)&_colors[ci++] ); } if( _normal_binding == BIND_PERVERTEX ) { if(_nindex.valid()) glNormal3fv( (GLfloat *)&_normals[_nindex[ni++]] ); else glNormal3fv( (GLfloat *)&_normals[ni++] ); } } if( _texture_binding == BIND_PERVERTEX ) { if( _tindex.valid() ) glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[ti++]] ); else glTexCoord2fv( (GLfloat *)&_tcoords[ti++] ); } if( _cindex.valid() ) glArrayElement( _cindex[ai++] ); else glArrayElement( ai++ ); } glEnd(); } else if( ((_color_binding == BIND_PERVERTEX ) && (_colindex.valid()) ) || ((_normal_binding == BIND_PERVERTEX ) && (_nindex.valid()) ) || ((_texture_binding == BIND_PERVERTEX ) && (_tindex.valid()) ) ) { glBegin( (GLenum)_oglprimtype ); for( j = 0; j < _primLengths[i]; j++ ) { if( (_color_binding == BIND_PERVERTEX) && (_colindex.valid()) ) glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] ); if( (_normal_binding == BIND_PERVERTEX) && (_nindex.valid()) ) glNormal3fv( (GLfloat *)&_normals[_nindex[ni++]] ); if( (_texture_binding == BIND_PERVERTEX) && (_tindex.valid()) ) glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[ti++]] ); if( _cindex.valid() ) glArrayElement( _cindex[ai++] ); else glArrayElement( ai++ ); } glEnd(); } else { if( _cindex.valid() ) { if (_cindex._is_ushort) glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_SHORT, &_cindex._ptr._ushort[index] ); else glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_INT, &_cindex._ptr._uint[index] ); } else glDrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] ); } index += _primLengths[i]; } if( _flat_shaded_skip ) { #ifdef DO_SHADING glShadeModel( GL_SMOOTH ); #endif } } else // POINTS, LINES, TRIANGLES, QUADS { int i, j; if( _normal_binding == BIND_PERPRIM || _color_binding == BIND_PERPRIM || ((_color_binding == BIND_PERVERTEX ) && (_colindex.valid()) ) || ((_normal_binding == BIND_PERVERTEX ) && (_nindex.valid()) ) || ((_texture_binding == BIND_PERVERTEX ) && (_tindex.valid()) ) ) { glBegin( (GLenum)_oglprimtype ); for( i = 0; i < _numprims; i++ ) { if( _color_binding == BIND_PERPRIM ) { if( _colindex.valid() ) glColor4fv( (GLfloat *)&_colors[_colindex[i]] ); else glColor4fv( (GLfloat *)&_colors[i] ); } if( _normal_binding == BIND_PERPRIM ) { if( _nindex.valid() ) glNormal3fv( (GLfloat *)&_normals[_nindex[i]] ); else glNormal3fv( (GLfloat *)&_normals[i] ); } for( j = 0; j < _primlength; j++ ) { if( (_color_binding == BIND_PERVERTEX) && (_colindex.valid() ) ) glColor4fv( (GLfloat *)&_colors[_colindex[i*_primlength+j]] ); if( (_normal_binding == BIND_PERVERTEX) && (_nindex.valid() ) ) glNormal3fv( (GLfloat *)&_normals[_nindex[i*_primlength+j]] ); if( (_texture_binding == BIND_PERVERTEX) && (_tindex.valid() ) ) glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[i*_primlength+j]] ); if( _cindex.valid()) glArrayElement( _cindex[i*_primlength+j] ); else glArrayElement( i*_primlength+j ); } } glEnd(); } else { if( _cindex.valid()) { if (_cindex._is_ushort) glDrawElements( (GLenum)_oglprimtype, _cindex._size, GL_UNSIGNED_SHORT, _cindex._ptr._ushort ); else glDrawElements( (GLenum)_oglprimtype, _cindex._size, GL_UNSIGNED_INT, _cindex._ptr._uint ); } else glDrawArrays( (GLenum)_oglprimtype, 0, _numcoords ); } } }