OpenSceneGraph/src/osg/GeoSet_ogl.cpp
Robert Osfield db892e6bfe Added State::disableTexCoordPointersAboveAndIncluding( unit ) method so that
all unsed texture units can be turned off simply within Drawables such
as Geometry and GeoSet. This can be used to prevent bleed of arrays from
one object to the next - which can cause crashes.
2002-07-15 10:03:59 +00:00

510 lines
19 KiB
C++

#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <stdio.h>
#include <osg/GL>
#include <osg/GeoSet>
#include <osg/Notify>
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 )
{
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 )
{
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 );
}
}
}