2001-09-20 05:19:47 +08:00
|
|
|
#include <osg/GL>
|
2001-10-04 05:44:07 +08:00
|
|
|
#include <osg/GLU>
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
#include <osg/Notify>
|
|
|
|
#include <osgUtil/Tesselator>
|
|
|
|
|
|
|
|
using namespace osg;
|
|
|
|
using namespace osgUtil;
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
static Tesselator* s_currentTesselator=0;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
Tesselator::Tesselator()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
_tobj = 0;
|
|
|
|
_errorCode = 0;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
Tesselator::~Tesselator()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj) gluDeleteTess(_tobj);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::beginTesselation()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
reset();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
if (!_tobj) _tobj = gluNewTess();
|
|
|
|
|
|
|
|
gluTessCallback(_tobj, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK*)()) vertexCallback);
|
|
|
|
gluTessCallback(_tobj, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK*)()) beginCallback);
|
|
|
|
gluTessCallback(_tobj, GLU_TESS_END_DATA, (GLvoid (CALLBACK*)()) endCallback);
|
|
|
|
gluTessCallback(_tobj, GLU_TESS_COMBINE, (GLvoid (CALLBACK*)()) combineCallback);
|
|
|
|
gluTessCallback(_tobj, GLU_TESS_ERROR_DATA, (GLvoid (CALLBACK*)()) errorCallback);
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
gluTessBeginPolygon(_tobj,this);
|
|
|
|
|
|
|
|
s_currentTesselator = this;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tesselator::beginContour()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj)
|
2002-06-24 05:43:46 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
gluTessBeginContour(_tobj);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
|
|
|
|
void Tesselator::addVertex(osg::Vec3* vertex)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
Vec3d* data = new Vec3d;
|
|
|
|
_coordData.push_back(data);
|
|
|
|
(*data)._v[0]=(*vertex)[0];
|
|
|
|
(*data)._v[1]=(*vertex)[1];
|
|
|
|
(*data)._v[2]=(*vertex)[2];
|
|
|
|
gluTessVertex(_tobj,data->_v,vertex);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::endContour()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj)
|
|
|
|
{
|
|
|
|
gluTessEndContour(_tobj);
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::endTesselation()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
gluTessEndPolygon(_tobj);
|
|
|
|
gluDeleteTess(_tobj);
|
|
|
|
_tobj = 0;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_errorCode!=0)
|
|
|
|
{
|
|
|
|
const GLubyte *estring = gluErrorString((GLenum)_errorCode);
|
|
|
|
osg::notify(osg::WARN)<<"Tessellation Error: "<<estring<< std::endl;
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::reset()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (_tobj)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
gluDeleteTess(_tobj);
|
|
|
|
_tobj = 0;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
_primList.clear();
|
|
|
|
_coordData.clear();
|
|
|
|
_errorCode = 0;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::retesselatePolygons(osg::Geometry& geom)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
Vec3Array* vertices = geom.getVertexArray();
|
|
|
|
if (!vertices || vertices->empty() || geom.getPrimitiveList().empty()) return;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
int noPrimitiveAtStart = geom.getPrimitiveList().size();
|
|
|
|
for(int primNo=0;primNo<noPrimitiveAtStart;++primNo)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
osg::Primitive* primitive = geom.getPrimitiveList()[primNo].get();
|
|
|
|
if (primitive->getMode()==osg::Primitive::POLYGON)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
beginTesselation();
|
|
|
|
beginContour();
|
|
|
|
|
|
|
|
switch(primitive->getType())
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
case(osg::Primitive::DrawArraysPrimitiveType):
|
|
|
|
{
|
|
|
|
osg::DrawArrays* drawArray = static_cast<osg::DrawArrays*>(primitive);
|
|
|
|
unsigned int first = drawArray->getFirst();
|
|
|
|
unsigned int last = first+drawArray->getCount();
|
|
|
|
for(unsigned int i=first;i<last;++i)
|
|
|
|
{
|
|
|
|
addVertex(&((*vertices)[i]));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-07-07 22:40:41 +08:00
|
|
|
case(osg::Primitive::DrawElementsUBytePrimitiveType):
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-07-07 22:40:41 +08:00
|
|
|
osg::DrawElementsUByte* drawElements = static_cast<osg::DrawElementsUByte*>(primitive);
|
|
|
|
for(osg::DrawElementsUByte::iterator indexItr=drawElements->begin();
|
2002-06-29 06:42:02 +08:00
|
|
|
indexItr!=drawElements->end();
|
|
|
|
++indexItr)
|
|
|
|
{
|
|
|
|
addVertex(&((*vertices)[*indexItr]));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-07-07 22:40:41 +08:00
|
|
|
case(osg::Primitive::DrawElementsUShortPrimitiveType):
|
2002-06-29 06:42:02 +08:00
|
|
|
{
|
2002-07-07 22:40:41 +08:00
|
|
|
osg::DrawElementsUShort* drawElements = static_cast<osg::DrawElementsUShort*>(primitive);
|
|
|
|
for(osg::DrawElementsUShort::iterator indexItr=drawElements->begin();
|
2002-06-29 06:42:02 +08:00
|
|
|
indexItr!=drawElements->end();
|
|
|
|
++indexItr)
|
|
|
|
{
|
|
|
|
addVertex(&((*vertices)[*indexItr]));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-07-07 22:40:41 +08:00
|
|
|
case(osg::Primitive::DrawElementsUIntPrimitiveType):
|
2002-06-29 06:42:02 +08:00
|
|
|
{
|
2002-07-07 22:40:41 +08:00
|
|
|
osg::DrawElementsUInt* drawElements = static_cast<osg::DrawElementsUInt*>(primitive);
|
|
|
|
for(osg::DrawElementsUInt::iterator indexItr=drawElements->begin();
|
2002-06-29 06:42:02 +08:00
|
|
|
indexItr!=drawElements->end();
|
|
|
|
++indexItr)
|
|
|
|
{
|
|
|
|
addVertex(&((*vertices)[*indexItr]));
|
|
|
|
}
|
|
|
|
break;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-07-14 05:17:40 +08:00
|
|
|
default:
|
|
|
|
break;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
|
|
|
|
endContour();
|
|
|
|
endTesselation();
|
|
|
|
|
|
|
|
Vec3* vbase = &(vertices->front());
|
|
|
|
Vec3* vtop = &(vertices->back());
|
|
|
|
|
|
|
|
for(PrimList::iterator primItr=_primList.begin();
|
|
|
|
primItr!=_primList.end();
|
|
|
|
++primItr)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
Prim* prim = primItr->get();
|
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode);
|
2002-06-29 06:42:02 +08:00
|
|
|
for(Prim::VecList::iterator vitr=prim->_vertices.begin();
|
|
|
|
vitr!=prim->_vertices.end();
|
|
|
|
++vitr)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
if (*vitr<vbase || *vitr>vtop)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
// new vertex.
|
|
|
|
std::cout<<"Ooohhh we're getting funky, extra vertices need to be inserted"<<std::endl;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
// old vertex.
|
|
|
|
unsigned int i=*vitr-vbase;
|
|
|
|
elements->push_back(i);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
|
|
|
|
if (primItr==_primList.begin())
|
|
|
|
{
|
|
|
|
// first new primitive so overwrite the previous polygon.
|
|
|
|
geom.getPrimitiveList()[primNo] = elements;
|
|
|
|
}
|
|
|
|
else
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-06-29 06:42:02 +08:00
|
|
|
// subsequence primtives add to the back of the primitive list.
|
|
|
|
geom.addPrimitive(elements);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-06-29 06:42:02 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-29 06:42:02 +08:00
|
|
|
void Tesselator::begin(GLenum mode)
|
|
|
|
{
|
|
|
|
_primList.push_back(new Prim(mode));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tesselator::vertex(osg::Vec3* vertex)
|
|
|
|
{
|
|
|
|
if (!_primList.empty())
|
|
|
|
{
|
|
|
|
Prim* prim = _primList.back().get();
|
|
|
|
prim->_vertices.push_back(vertex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tesselator::combine(osg::Vec3* vertex)
|
|
|
|
{
|
|
|
|
if (!_primList.empty())
|
|
|
|
{
|
|
|
|
Prim* prim = _primList.back().get();
|
|
|
|
prim->_vertices.push_back(vertex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tesselator::end()
|
|
|
|
{
|
|
|
|
// no need to do anything right now...
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tesselator::error(GLenum errorCode)
|
|
|
|
{
|
|
|
|
_errorCode = errorCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK Tesselator::beginCallback(GLenum which, void* userData)
|
|
|
|
{
|
|
|
|
((Tesselator*)userData)->begin(which);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK Tesselator::endCallback(void* userData)
|
|
|
|
{
|
|
|
|
((Tesselator*)userData)->end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK Tesselator::vertexCallback(GLvoid *data, void* userData)
|
|
|
|
{
|
|
|
|
((Tesselator*)userData)->vertex((Vec3*)data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK Tesselator::combineCallback(GLdouble coords[3], void* /*vertex_data*/[4],
|
|
|
|
GLfloat /*weight*/[4], void** outData,
|
|
|
|
void* userData)
|
|
|
|
{
|
|
|
|
Vec3* newData = new osg::Vec3(coords[0],coords[2],coords[3]);
|
|
|
|
*outData = newData;
|
|
|
|
//((Tesselator*)userData)->combine(newData);
|
|
|
|
s_currentTesselator->combine(newData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK Tesselator::errorCallback(GLenum errorCode, void* userData)
|
|
|
|
{
|
|
|
|
((Tesselator*)userData)->error(errorCode);
|
|
|
|
}
|