any reference to these in the distribution across to using unsigned char, unsigned short etc. This has been done to keep the OSG code more opaque to what types are.
643 lines
24 KiB
C++
643 lines
24 KiB
C++
#include <osg/GeoSet>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "AreaGeoSetTriangulator.h"
|
|
|
|
namespace dx {
|
|
|
|
class AreaGeoSetTriangulator
|
|
// Used to convert area primitive GeoSets into TRIANGLE Geosets.
|
|
// Efficiently collects the various data arrays, which GeoSet can't do.
|
|
{
|
|
protected:
|
|
std::vector< unsigned int > _cindex;
|
|
std::vector< unsigned int > _nindex;
|
|
std::vector< unsigned int > _colindex;
|
|
std::vector< unsigned int > _tindex;
|
|
const osg::GeoSet &_area_geoset;
|
|
|
|
public:
|
|
AreaGeoSetTriangulator( const osg::GeoSet &area_geoset );
|
|
|
|
void operator() ( unsigned int v1, unsigned int v2, unsigned int v3,
|
|
unsigned int prim_index, unsigned int prim_tri_index,
|
|
unsigned int v1_geoset, unsigned int v2_geoset,
|
|
unsigned int v3_geoset );
|
|
// Passed triangles as primitives are triangulated
|
|
|
|
osg::GeoSet *BuildGeoSet();
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
AreaGeoSetTriangulator::AreaGeoSetTriangulator( const osg::GeoSet &area_geoset)
|
|
: _area_geoset(area_geoset)
|
|
{
|
|
// Check type
|
|
switch ( area_geoset.getPrimType() ) {
|
|
case osg::GeoSet::TRIANGLE_STRIP:
|
|
case osg::GeoSet::FLAT_TRIANGLE_STRIP:
|
|
case osg::GeoSet::TRIANGLES:
|
|
case osg::GeoSet::QUAD_STRIP:
|
|
case osg::GeoSet::QUADS:
|
|
case osg::GeoSet::TRIANGLE_FAN:
|
|
case osg::GeoSet::FLAT_TRIANGLE_FAN:
|
|
case osg::GeoSet::POLYGON:
|
|
break;
|
|
default:
|
|
fprintf( stderr,
|
|
"Invalid primitive type passed to AreaGeoSetTriangulator\n" );
|
|
exit(1);
|
|
}
|
|
|
|
// NOTE: _coords, _normals, _colors, and _tcoords are maintained
|
|
// from the original geoset. The new geoset will always have
|
|
// indexed coords/normals/colors/tcoords (to save space).
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void AreaGeoSetTriangulator::operator() (
|
|
unsigned int v1, unsigned int v2, unsigned int v3,
|
|
unsigned int prim_index, unsigned int prim_tri_index,
|
|
unsigned int v1_geoset, unsigned int v2_geoset,
|
|
unsigned int v3_geoset )
|
|
// Passed triangles as primitives are triangulated from the original
|
|
// GeoSet. Note that the v? params are indicies into the Coord array,
|
|
// whereas the v?_geoset params are vertex numbers relative to the
|
|
// entire "area GeoSet" (which are different when the coords are
|
|
// indexed). The latter is needed to look up colors/normals/tcoords).
|
|
{
|
|
osg::GeoSet::BindingType binding;
|
|
osg::GeoSet::PrimitiveType primtype = _area_geoset.getPrimType();
|
|
int area_is_flatprim = ( primtype == osg::GeoSet::FLAT_TRIANGLE_STRIP ||
|
|
primtype == osg::GeoSet::FLAT_TRIANGLE_FAN );
|
|
|
|
// Store the triangle coord indicies
|
|
_cindex.push_back( v1 );
|
|
_cindex.push_back( v2 );
|
|
_cindex.push_back( v3 );
|
|
|
|
int index;
|
|
const osg::GeoSet::IndexPointer *ip;
|
|
|
|
// Store normals (as needed)
|
|
if ( _area_geoset.getNumNormals() ) {
|
|
ip = &_area_geoset.getNormalIndices();
|
|
|
|
// Grrr... FLAT_ primitives lie about binding type... like Performer
|
|
binding = _area_geoset.getNormalBinding();
|
|
if ( area_is_flatprim && binding == osg::GeoSet::BIND_PERVERTEX )
|
|
binding = osg::GeoSet::BIND_PERPRIM;
|
|
|
|
switch ( binding ) {
|
|
|
|
case osg::GeoSet::BIND_OVERALL : // Only once
|
|
if ( prim_index == 0 && prim_tri_index == 0 ) {
|
|
index = ip->valid() ? (*ip)[0] : 0;
|
|
_nindex.push_back( index );
|
|
break;
|
|
}
|
|
|
|
case osg::GeoSet::BIND_PERPRIM : // Once per tri
|
|
index = ip->valid() ? (*ip)[prim_index] : prim_index;
|
|
_nindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_PERVERTEX : // Each vertex
|
|
index = ip->valid() ? (*ip)[v1_geoset] : v1_geoset;
|
|
_nindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v2_geoset] : v2_geoset;
|
|
_nindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v3_geoset] : v3_geoset;
|
|
_nindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_OFF:
|
|
case osg::GeoSet::BIND_DEFAULT:
|
|
// Nonsensical cases
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Store colors (as needed)
|
|
if ( _area_geoset.getNumColors() ) {
|
|
ip = &_area_geoset.getColorIndices();
|
|
|
|
// Grrr... FLAT_ primitives lie about binding type... like Performer
|
|
binding = _area_geoset.getColorBinding();
|
|
if ( area_is_flatprim && binding == osg::GeoSet::BIND_PERVERTEX )
|
|
binding = osg::GeoSet::BIND_PERPRIM;
|
|
|
|
switch ( binding ) {
|
|
|
|
case osg::GeoSet::BIND_OVERALL : // Only once
|
|
if ( prim_index == 0 && prim_tri_index == 0 ) {
|
|
index = ip->valid() ? (*ip)[0] : 0;
|
|
_colindex.push_back( index );
|
|
break;
|
|
}
|
|
|
|
case osg::GeoSet::BIND_PERPRIM : // Once per tri
|
|
index = ip->valid() ? (*ip)[prim_index] : prim_index;
|
|
_colindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_PERVERTEX : // Each vertex
|
|
index = ip->valid() ? (*ip)[v1_geoset] : v1_geoset;
|
|
_colindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v2_geoset] : v2_geoset;
|
|
_colindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v3_geoset] : v3_geoset;
|
|
_colindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_OFF:
|
|
case osg::GeoSet::BIND_DEFAULT:
|
|
// Nonsensical cases
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Store tcoords (as needed)
|
|
if ( _area_geoset.getNumTextureCoords() ) {
|
|
ip = &_area_geoset.getTextureIndices();
|
|
|
|
switch ( _area_geoset.getTextureBinding() ) {
|
|
|
|
case osg::GeoSet::BIND_OVERALL : // Only once
|
|
if ( prim_index == 0 && prim_tri_index == 0 ) {
|
|
index = ip->valid() ? (*ip)[0] : 0;
|
|
_tindex.push_back( index );
|
|
break;
|
|
}
|
|
|
|
case osg::GeoSet::BIND_PERPRIM : // Once per tri
|
|
index = ip->valid() ? (*ip)[prim_index] : prim_index;
|
|
_tindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_PERVERTEX : // Each vertex
|
|
index = ip->valid() ? (*ip)[v1_geoset] : v1_geoset;
|
|
_tindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v2_geoset] : v2_geoset;
|
|
_tindex.push_back( index );
|
|
index = ip->valid() ? (*ip)[v3_geoset] : v3_geoset;
|
|
_tindex.push_back( index );
|
|
break;
|
|
|
|
case osg::GeoSet::BIND_OFF:
|
|
case osg::GeoSet::BIND_DEFAULT:
|
|
// Nonsensical cases
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Shamelessly lifted from the GeoSet header and adapted for our uses
|
|
// This is the same except that: 1) it passes the coordinate indices
|
|
// to the op function insted of the Vec3s, and 2) it passes an original
|
|
// primitive index and "triangle-in-primitive" index to the op function,
|
|
// 3) it also passes the absolute vertex numbers in the primitive so they
|
|
// can be used to look up normals/colors/tcoords, and 4) fixes some
|
|
// problems with vertex ordering which caused FRONT/BACK confusion with
|
|
// normals and lighting.
|
|
// With this, we can construct a new TRIANGLE GeoSet from any area GeoSet.
|
|
|
|
/** Template function for iterating through a GeoSet operating on triangles
|
|
with templated functor. Function automatically decomposes quads and polygons
|
|
into sub triangles which are passed onto functor.*/
|
|
|
|
template<class T>
|
|
void for_each_triangle2(const osg::GeoSet& gset,T& op)
|
|
{
|
|
switch(gset.getPrimType())
|
|
{
|
|
case(osg::GeoSet::TRIANGLE_STRIP):
|
|
case(osg::GeoSet::FLAT_TRIANGLE_STRIP):
|
|
{
|
|
if (gset.getCoordIndices().valid())
|
|
{
|
|
if (gset.getCoordIndices()._is_ushort)
|
|
{
|
|
unsigned short* base = gset.getCoordIndices()._ptr._ushort;
|
|
unsigned short* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
unsigned short* iend = iptr+primLength;
|
|
int tri=0;
|
|
for(int j = 2; j < primLength; j++ )
|
|
{
|
|
if( !(j%2) )
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,tri++,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
else
|
|
op(*(iptr),*(iptr+2),*(iptr+1),i,tri++,
|
|
iptr-base,(iptr+2)-base,(iptr+1)-base);
|
|
++iptr;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GLuint* base = gset.getCoordIndices()._ptr._uint;
|
|
GLuint* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
GLuint* iend = iptr+primLength;
|
|
int tri=0;
|
|
for(int j = 2; j < primLength; j++ )
|
|
{
|
|
if( !(j%2) )
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,tri++,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
else
|
|
op(*(iptr),*(iptr+2),*(iptr+1),i,tri++,
|
|
iptr-base,(iptr+2)-base,(iptr+1)-base);
|
|
++iptr;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int cindex = 0;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
unsigned int cindex_end = cindex+primLength;
|
|
int tri=0;
|
|
for(int j = 2; j < primLength; j++ )
|
|
{
|
|
if( !(j%2) )
|
|
op(cindex,cindex+1,cindex+2,i,tri++,
|
|
cindex,cindex+1,cindex+2);
|
|
else
|
|
op(cindex,cindex+2,cindex+1,i,tri++,
|
|
cindex,cindex+2,cindex+1);
|
|
++cindex;
|
|
}
|
|
cindex = cindex_end;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case(osg::GeoSet::TRIANGLES):
|
|
{
|
|
|
|
if (gset.getCoordIndices().valid())
|
|
{
|
|
if (gset.getCoordIndices()._is_ushort)
|
|
{
|
|
unsigned short* base = gset.getCoordIndices()._ptr._ushort;
|
|
unsigned short* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,0,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
iptr+=3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GLuint* base = gset.getCoordIndices()._ptr._uint;
|
|
GLuint* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,0,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
iptr+=3;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int cindex = 0;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(cindex,cindex+1,cindex+2,i,0,
|
|
cindex,cindex+1,cindex+2);
|
|
cindex+=3;
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
case(osg::GeoSet::QUAD_STRIP):
|
|
{
|
|
if (gset.getCoordIndices().valid())
|
|
{
|
|
if (gset.getCoordIndices()._is_ushort)
|
|
{
|
|
unsigned short* base = gset.getCoordIndices()._ptr._ushort;
|
|
unsigned short* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
unsigned short* iend = iptr+primLength;
|
|
int tri=0;
|
|
for(int j = 3; j < primLength; j+=2 )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,tri++,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
// rhh FIXME: FIXED 1st vert offset
|
|
op(*(iptr+1),*(iptr+3),*(iptr+2),i,tri++,
|
|
(iptr+1)-base,(iptr+3)-base,(iptr+2)-base);
|
|
iptr+=2;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GLuint* base = gset.getCoordIndices()._ptr._uint;
|
|
GLuint* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
GLuint* iend = iptr+primLength;
|
|
int tri=0;
|
|
for(int j = 3; j < primLength; j+=2 )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,tri++,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
op(*(iptr+1),*(iptr+3),*(iptr+2),i,tri++,
|
|
(iptr+1)-base,(iptr+3)-base,(iptr+2)-base);
|
|
iptr+=2;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int cindex = 0;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
unsigned int cindex_end = cindex+primLength;
|
|
int tri=0;
|
|
for(int j = 3; j < primLength; j+=2 )
|
|
{
|
|
op(cindex,cindex+1,cindex+2,i,tri++,
|
|
cindex,cindex+1,cindex+2);
|
|
op(cindex+1,cindex+3,cindex+2,i,tri++,
|
|
cindex+1,cindex+3,cindex+2);
|
|
cindex+=2;
|
|
}
|
|
cindex = cindex_end;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case(osg::GeoSet::QUADS):
|
|
{
|
|
if (gset.getCoordIndices().valid())
|
|
{
|
|
if (gset.getCoordIndices()._is_ushort)
|
|
{
|
|
unsigned short* base = gset.getCoordIndices()._ptr._ushort;
|
|
unsigned short* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,0,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
// rhh FIXME: FIXED 2nd & 3rd vert offset
|
|
op(*(iptr),*(iptr+2),*(iptr+3),i,1,
|
|
iptr-base,(iptr+2)-base,(iptr+3)-base);
|
|
iptr+=4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GLuint* base = gset.getCoordIndices()._ptr._uint;
|
|
GLuint* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(*(iptr),*(iptr+1),*(iptr+2),i,0,
|
|
iptr-base,(iptr+1)-base,(iptr+2)-base);
|
|
op(*(iptr),*(iptr+2),*(iptr+3),i,1,
|
|
iptr-base,(iptr+2)-base,(iptr+3)-base);
|
|
iptr+=4;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int cindex = 0;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
op(cindex,cindex+1,cindex+2,i,0,
|
|
cindex,cindex+1,cindex+2);
|
|
op(cindex,cindex+2,cindex+3,i,1,
|
|
cindex,cindex+2,cindex+3);
|
|
cindex+=4;
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
case(osg::GeoSet::TRIANGLE_FAN):
|
|
case(osg::GeoSet::FLAT_TRIANGLE_FAN): // FIXME: rhh added
|
|
case(osg::GeoSet::POLYGON):
|
|
{
|
|
if (gset.getCoordIndices().valid())
|
|
{
|
|
if (gset.getCoordIndices()._is_ushort)
|
|
{
|
|
unsigned short* base = gset.getCoordIndices()._ptr._ushort;
|
|
unsigned short* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
int tri=0;
|
|
if (primLength>0)
|
|
{
|
|
unsigned short *start = iptr;
|
|
unsigned short* iend = iptr+primLength;
|
|
++iptr;
|
|
for(int j = 2; j < primLength; ++j )
|
|
{
|
|
op(*start,*(iptr),*(iptr+1),i,tri++,
|
|
start-base, iptr-base,(iptr+1)-base);
|
|
++iptr;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GLuint* base = gset.getCoordIndices()._ptr._uint;
|
|
GLuint* iptr = base;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
int tri=0;
|
|
if (primLength>0)
|
|
{
|
|
GLuint *start = iptr;
|
|
GLuint* iend = iptr+primLength;
|
|
++iptr;
|
|
for(int j = 2; j < primLength; ++j )
|
|
{
|
|
op(*start,*(iptr),*(iptr+1),i,tri++,
|
|
start-base, iptr-base,(iptr+1)-base);
|
|
++iptr;
|
|
}
|
|
iptr=iend;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int cindex = 0;
|
|
const int numPrim = gset.getNumPrims();
|
|
for(int i=0; i<numPrim; ++i )
|
|
{
|
|
const int primLength = gset.getPrimLengths()[i];
|
|
int tri=0;
|
|
if (primLength>0)
|
|
{
|
|
unsigned int cindex_start = cindex;
|
|
unsigned int cindex_end = cindex+primLength;
|
|
++cindex;
|
|
for(int j = 2; j < primLength; ++j)
|
|
{
|
|
op(cindex_start,cindex,cindex+1,i,tri++,
|
|
cindex_start,cindex,cindex+1);
|
|
++cindex;
|
|
}
|
|
cindex = cindex_end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
osg::GeoSet *AreaGeoSetTriangulator::BuildGeoSet()
|
|
// After a triangulation pass, generate a valid TRIANGLE GeoSet containing
|
|
// the resulting triangles (w/ colors, normals, and tcoords).
|
|
{
|
|
int num_tris = _cindex.size() / 3;
|
|
|
|
osg::GeoSet *res = new osg::GeoSet;
|
|
res->setPrimType( osg::GeoSet::TRIANGLES );
|
|
res->setNumPrims( num_tris );
|
|
|
|
// First, dup all of the data arrays -- they haven't changed
|
|
// NOTE: We generate fresh arrays for the new GeoSet to be compatible
|
|
// with the delete [] behavior of the default GeoSet
|
|
// AttributeDeleteFunctor, which is invoked in GeoSet::~GeoSet.
|
|
|
|
osg::Vec3 *new_coords = 0;
|
|
osg::Vec3 *new_normals = 0;
|
|
osg::Vec4 *new_colors = 0;
|
|
osg::Vec2 *new_tcoords = 0;
|
|
|
|
const osg::Vec3 *coords = _area_geoset.getCoords();
|
|
const osg::Vec3 *normals = _area_geoset.getNormals();
|
|
const osg::Vec4 *colors = _area_geoset.getColors();
|
|
const osg::Vec2 *tcoords = _area_geoset.getTextureCoords();
|
|
|
|
if ( coords )
|
|
new_coords = new osg::Vec3[ _area_geoset.getNumCoords() ];
|
|
if ( normals )
|
|
new_normals = new osg::Vec3[ _area_geoset.getNumNormals() ];
|
|
if ( colors )
|
|
new_colors = new osg::Vec4[ _area_geoset.getNumColors() ];
|
|
if ( tcoords )
|
|
new_tcoords = new osg::Vec2[ _area_geoset.getNumTextureCoords() ];
|
|
|
|
memcpy( new_coords, coords,
|
|
sizeof(osg::Vec3) * _area_geoset.getNumCoords() );
|
|
memcpy( new_normals, normals,
|
|
sizeof(osg::Vec3) * _area_geoset.getNumNormals() );
|
|
memcpy( new_colors, colors,
|
|
sizeof(osg::Vec4) * _area_geoset.getNumColors() );
|
|
memcpy( new_tcoords, tcoords,
|
|
sizeof(osg::Vec2) * _area_geoset.getNumTextureCoords() );
|
|
|
|
// Now generate the index arrays
|
|
GLuint *new_cindex = 0;
|
|
GLuint *new_nindex = 0;
|
|
GLuint *new_colindex = 0;
|
|
GLuint *new_tindex = 0;
|
|
|
|
if ( _cindex.size() ) new_cindex = new GLuint[ _cindex.size() ];
|
|
if ( _nindex.size() ) new_nindex = new GLuint[ _nindex.size() ];
|
|
if ( _colindex.size() ) new_colindex = new GLuint[ _colindex.size() ];
|
|
if ( _tindex.size() ) new_tindex = new GLuint[ _tindex.size() ];
|
|
|
|
memcpy( new_cindex , &_cindex [0], sizeof(GLuint) * _cindex.size() );
|
|
memcpy( new_nindex , &_nindex [0], sizeof(GLuint) * _nindex.size() );
|
|
memcpy( new_colindex, &_colindex[0], sizeof(GLuint) * _colindex.size() );
|
|
memcpy( new_tindex , &_tindex [0], sizeof(GLuint) * _tindex.size() );
|
|
|
|
res->setCoords ( new_coords , new_cindex );
|
|
res->setNormals( new_normals, new_nindex );
|
|
res->setColors ( new_colors , new_colindex );
|
|
res->setTextureCoords( new_tcoords, new_tindex );
|
|
|
|
// And finally, set the normal/color/tcoord binding
|
|
// (Grrr... FLAT_ primitives lie about binding type... like Performer)
|
|
osg::GeoSet::BindingType nbinding = _area_geoset.getNormalBinding();
|
|
osg::GeoSet::BindingType cbinding = _area_geoset.getColorBinding();
|
|
if ( _area_geoset.getPrimType() == osg::GeoSet::FLAT_TRIANGLE_STRIP ||
|
|
_area_geoset.getPrimType() == osg::GeoSet::FLAT_TRIANGLE_FAN ) {
|
|
if ( nbinding == osg::GeoSet::BIND_PERVERTEX )
|
|
nbinding = osg::GeoSet::BIND_PERPRIM;
|
|
if ( cbinding == osg::GeoSet::BIND_PERVERTEX )
|
|
cbinding = osg::GeoSet::BIND_PERPRIM;
|
|
}
|
|
|
|
res->setNormalBinding ( nbinding );
|
|
res->setColorBinding ( cbinding );
|
|
res->setTextureBinding( _area_geoset.getTextureBinding() );
|
|
|
|
return res;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
osg::GeoSet *TriangulateAreaGeoSet( const osg::GeoSet &geoset )
|
|
// The strategy here is to generate new coord/normal/color/tcoord index
|
|
// arrays as we bust up the primitives into triangles. The data arrays
|
|
// don't change between the old and new geoset.
|
|
{
|
|
geoset.computeNumVerts(); // Update # coords/# normals from index arrays
|
|
|
|
AreaGeoSetTriangulator triangulator( geoset );
|
|
for_each_triangle2( geoset, triangulator );
|
|
return triangulator.BuildGeoSet();
|
|
}
|
|
|
|
}; // namespace dx
|