OpenSceneGraph/src/osg/GeoSet_ogl.cpp

522 lines
20 KiB
C++

/* -*-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 <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 ) 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 );
}
}
}