2002-06-21 03:54:08 +08:00
|
|
|
#include <osg/Geometry>
|
2002-07-18 08:53:03 +08:00
|
|
|
#include <osg/Notify>
|
2002-06-21 03:54:08 +08:00
|
|
|
|
|
|
|
using namespace osg;
|
|
|
|
|
|
|
|
Geometry::Geometry()
|
|
|
|
{
|
2002-06-24 05:43:46 +08:00
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
_colorBinding = BIND_OFF;
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
|
|
|
|
Drawable(geometry,copyop),
|
2002-07-26 05:50:08 +08:00
|
|
|
_vertexArray(dynamic_cast<Vec3Array*>(copyop(geometry._vertexArray.get()))),
|
2002-06-22 00:45:45 +08:00
|
|
|
_normalBinding(geometry._normalBinding),
|
2002-07-26 05:50:08 +08:00
|
|
|
_normalArray(dynamic_cast<Vec3Array*>(copyop(geometry._normalArray.get()))),
|
2002-06-22 00:45:45 +08:00
|
|
|
_colorBinding(geometry._colorBinding),
|
2002-07-26 05:50:08 +08:00
|
|
|
_colorArray(copyop(geometry._colorArray.get()))
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-07-26 05:50:08 +08:00
|
|
|
for(PrimitiveList::const_iterator pitr=geometry._primitives.begin();
|
|
|
|
pitr!=geometry._primitives.end();
|
|
|
|
++pitr)
|
|
|
|
{
|
|
|
|
Primitive* primitive = copyop(pitr->get());
|
|
|
|
if (primitive) _primitives.push_back(primitive);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(TexCoordArrayList::const_iterator titr=geometry._texCoordList.begin();
|
|
|
|
titr!=geometry._texCoordList.end();
|
|
|
|
++titr)
|
|
|
|
{
|
|
|
|
_texCoordList.push_back(copyop(titr->get()));
|
|
|
|
}
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Geometry::~Geometry()
|
|
|
|
{
|
|
|
|
// no need to delete, all automatically handled by ref_ptr :-)
|
|
|
|
}
|
|
|
|
|
2002-06-27 21:15:34 +08:00
|
|
|
void Geometry::setTexCoordArray(unsigned int unit,Array* array)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-22 00:45:45 +08:00
|
|
|
if (_texCoordList.size()<=unit)
|
|
|
|
_texCoordList.resize(unit+1,0);
|
2002-06-21 03:54:08 +08:00
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
_texCoordList[unit] = array;
|
2002-06-26 04:27:51 +08:00
|
|
|
|
|
|
|
dirtyDisplayList();
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
2002-06-27 21:15:34 +08:00
|
|
|
Array* Geometry::getTexCoordArray(unsigned int unit)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-22 00:45:45 +08:00
|
|
|
if (unit<_texCoordList.size()) return _texCoordList[unit].get();
|
2002-06-21 03:54:08 +08:00
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
|
2002-07-18 08:53:03 +08:00
|
|
|
const Array* Geometry::getTexCoordArray(unsigned int unit) const
|
|
|
|
{
|
|
|
|
if (unit<_texCoordList.size()) return _texCoordList[unit].get();
|
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
void Geometry::drawImmediateMode(State& state)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-22 00:45:45 +08:00
|
|
|
if (!_vertexArray.valid()) return;
|
|
|
|
|
|
|
|
// set up the vertex arrays.
|
2002-07-18 08:53:03 +08:00
|
|
|
state.setVertexPointer(3,GL_FLOAT,0,_vertexArray->getDataPointer());
|
2002-06-22 00:45:45 +08:00
|
|
|
|
|
|
|
// set up texture coordinates.
|
2002-07-15 18:03:59 +08:00
|
|
|
unsigned int i;
|
|
|
|
for(i=0;i<_texCoordList.size();++i)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-27 21:15:34 +08:00
|
|
|
Array* array = _texCoordList[i].get();
|
2002-06-22 00:45:45 +08:00
|
|
|
if (array)
|
2002-07-18 08:53:03 +08:00
|
|
|
state.setTexCoordPointer(i,array->getDataSize(),array->getDataType(),0,array->getDataPointer());
|
2002-06-22 00:45:45 +08:00
|
|
|
else
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableTexCoordPointer(i);
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
2002-07-15 18:03:59 +08:00
|
|
|
state.disableTexCoordPointersAboveAndIncluding(i);
|
2002-06-22 00:45:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
// set up normals.
|
|
|
|
Vec3* normalPointer = 0;
|
|
|
|
if (_normalArray.valid() && !_normalArray->empty()) normalPointer = &(_normalArray->front());
|
2002-06-21 03:54:08 +08:00
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
switch (_normalBinding)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_OFF):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableNormalPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_OVERALL):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableNormalPointer();
|
2002-06-24 05:43:46 +08:00
|
|
|
if (normalPointer) glNormal3fv(reinterpret_cast<const GLfloat*>(normalPointer));
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_PER_PRIMITIVE):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableNormalPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_PER_VERTEX):
|
2002-07-07 22:40:41 +08:00
|
|
|
if (normalPointer) state.setNormalPointer(GL_FLOAT,0,normalPointer);
|
2002-07-14 05:17:40 +08:00
|
|
|
else state.disableNormalPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
// set up colors, complicated by the fact that the color array
|
|
|
|
// might be bound in 4 different ways, and be represented as 3 different data types -
|
|
|
|
// Vec3, Vec4 or UByte4 Arrays.
|
|
|
|
const unsigned char* colorPointer = 0;
|
|
|
|
unsigned int colorStride = 0;
|
2002-06-27 21:15:34 +08:00
|
|
|
Array::Type colorType = Array::ArrayType;
|
2002-06-22 00:45:45 +08:00
|
|
|
if (_colorArray.valid())
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-27 21:15:34 +08:00
|
|
|
colorType = _colorArray->getType();
|
2002-06-22 00:45:45 +08:00
|
|
|
switch(colorType)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::UByte4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
{
|
2002-07-18 08:53:03 +08:00
|
|
|
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
|
2002-06-22 00:45:45 +08:00
|
|
|
colorStride = 4;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec3ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
{
|
2002-07-18 08:53:03 +08:00
|
|
|
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
|
2002-06-22 00:45:45 +08:00
|
|
|
colorStride = 12;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
{
|
2002-07-18 08:53:03 +08:00
|
|
|
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
|
2002-06-22 00:45:45 +08:00
|
|
|
colorStride = 16;
|
|
|
|
break;
|
|
|
|
}
|
2002-07-14 05:17:40 +08:00
|
|
|
default:
|
|
|
|
break;
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
switch (_colorBinding)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_OFF):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableColorPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_OVERALL):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableColorPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
if (colorPointer)
|
|
|
|
{
|
|
|
|
switch(colorType)
|
|
|
|
{
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::UByte4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor4ubv(reinterpret_cast<const GLubyte*>(colorPointer));
|
|
|
|
break;
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec3ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor3fv(reinterpret_cast<const GLfloat*>(colorPointer));
|
|
|
|
break;
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor4fv(reinterpret_cast<const GLfloat*>(colorPointer));
|
|
|
|
break;
|
2002-07-14 05:17:40 +08:00
|
|
|
default:
|
|
|
|
break;
|
2002-06-22 00:45:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_PER_PRIMITIVE):
|
2002-07-07 22:40:41 +08:00
|
|
|
state.disableColorPointer();
|
2002-06-22 00:45:45 +08:00
|
|
|
break;
|
2002-06-24 05:43:46 +08:00
|
|
|
case(BIND_PER_VERTEX):
|
2002-07-18 08:53:03 +08:00
|
|
|
if (colorPointer) state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,colorPointer);
|
2002-07-14 05:17:40 +08:00
|
|
|
else state.disableColorPointer();
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
// draw the primitives themselves.
|
|
|
|
for(PrimitiveList::iterator itr=_primitives.begin();
|
|
|
|
itr!=_primitives.end();
|
|
|
|
++itr)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-24 05:43:46 +08:00
|
|
|
if (_normalBinding==BIND_PER_PRIMITIVE)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-06-22 00:45:45 +08:00
|
|
|
glNormal3fv((const GLfloat *)normalPointer++);
|
|
|
|
}
|
|
|
|
|
2002-06-24 05:43:46 +08:00
|
|
|
if (_colorBinding==BIND_PER_PRIMITIVE)
|
2002-06-22 00:45:45 +08:00
|
|
|
{
|
|
|
|
switch(colorType)
|
|
|
|
{
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::UByte4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor4ubv(reinterpret_cast<const GLubyte*>(colorPointer));
|
|
|
|
break;
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec3ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor3fv(reinterpret_cast<const GLfloat*>(colorPointer));
|
|
|
|
break;
|
2002-06-27 21:15:34 +08:00
|
|
|
case(Array::Vec4ArrayType):
|
2002-06-22 00:45:45 +08:00
|
|
|
glColor4fv(reinterpret_cast<const GLfloat*>(colorPointer));
|
|
|
|
break;
|
2002-07-14 05:17:40 +08:00
|
|
|
default:
|
|
|
|
break;
|
2002-06-22 00:45:45 +08:00
|
|
|
}
|
|
|
|
colorPointer += colorStride;
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
2002-06-22 00:45:45 +08:00
|
|
|
(*itr)->draw();
|
|
|
|
}
|
2002-06-21 03:54:08 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-18 23:36:14 +08:00
|
|
|
void Geometry::accept(AttributeFunctor& af)
|
2002-06-21 03:54:08 +08:00
|
|
|
{
|
2002-07-18 23:36:14 +08:00
|
|
|
if (_vertexArray.valid() && !_vertexArray->empty())
|
2002-06-28 04:29:32 +08:00
|
|
|
{
|
2002-07-18 23:36:14 +08:00
|
|
|
af.apply(VERTICES,_vertexArray->size(),&(_vertexArray->front()));
|
2002-06-28 04:29:32 +08:00
|
|
|
}
|
|
|
|
|
2002-07-18 23:36:14 +08:00
|
|
|
if (_normalArray.valid() && !_normalArray->empty())
|
2002-06-28 04:29:32 +08:00
|
|
|
{
|
2002-07-18 23:36:14 +08:00
|
|
|
af.apply(NORMALS,_normalArray->size(),&(_normalArray->front()));
|
2002-06-28 04:29:32 +08:00
|
|
|
}
|
2002-07-18 23:36:14 +08:00
|
|
|
// need to add other attriubtes
|
2002-06-21 03:54:08 +08:00
|
|
|
}
|
|
|
|
|
2002-07-18 23:36:14 +08:00
|
|
|
void Geometry::accept(PrimitiveFunctor& functor)
|
2002-06-26 04:27:51 +08:00
|
|
|
{
|
|
|
|
if (!_vertexArray.valid() || _vertexArray->empty()) return;
|
|
|
|
|
|
|
|
functor.setVertexArray(_vertexArray->size(),&(_vertexArray->front()));
|
|
|
|
|
|
|
|
for(PrimitiveList::iterator itr=_primitives.begin();
|
|
|
|
itr!=_primitives.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2002-07-18 23:36:14 +08:00
|
|
|
(*itr)->accept(functor);
|
2002-06-26 04:27:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-07-19 06:35:54 +08:00
|
|
|
// just use the base Drawable's PrimitiveFunctor based implementation.
|
|
|
|
// const bool Geometry::computeBound() const
|
|
|
|
// {
|
|
|
|
// _bbox.init();
|
|
|
|
//
|
|
|
|
// const Vec3Array* coords = dynamic_cast<const Vec3Array*>(_vertexArray.get());
|
|
|
|
// if (coords)
|
|
|
|
// {
|
|
|
|
// for(Vec3Array::const_iterator itr=coords->begin();
|
|
|
|
// itr!=coords->end();
|
|
|
|
// ++itr)
|
|
|
|
// {
|
|
|
|
// _bbox.expandBy(*itr);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// _bbox_computed = true;
|
|
|
|
//
|
|
|
|
// return _bbox.valid();
|
|
|
|
// }
|
2002-06-21 03:54:08 +08:00
|
|
|
|
2002-07-18 08:53:03 +08:00
|
|
|
bool Geometry::verifyBindings() const
|
|
|
|
{
|
|
|
|
switch(_normalBinding)
|
|
|
|
{
|
|
|
|
case(BIND_OFF):
|
|
|
|
if (_normalArray.valid() && _normalArray->getNumElements()>0) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_OVERALL):
|
|
|
|
if (!_normalArray.valid()) return false;
|
|
|
|
if (_normalArray->getNumElements()!=1) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_PER_PRIMITIVE):
|
|
|
|
if (!_normalArray.valid()) return false;
|
|
|
|
if (_normalArray->getNumElements()!=_primitives.size()) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_PER_VERTEX):
|
|
|
|
if (_vertexArray.valid())
|
|
|
|
{
|
|
|
|
if (!_normalArray.valid()) return false;
|
|
|
|
if (_normalArray->getNumElements()!=_vertexArray->getNumElements()) return false;
|
|
|
|
}
|
|
|
|
else if (_normalArray.valid() && _normalArray->getNumElements()>0) return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(_colorBinding)
|
|
|
|
{
|
|
|
|
case(BIND_OFF):
|
|
|
|
if (_colorArray.valid() && _colorArray->getNumElements()>0) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_OVERALL):
|
|
|
|
if (!_colorArray.valid()) return false;
|
|
|
|
if (_colorArray->getNumElements()!=1) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_PER_PRIMITIVE):
|
|
|
|
if (!_colorArray.valid()) return false;
|
|
|
|
if (_colorArray->getNumElements()!=_primitives.size()) return false;
|
|
|
|
break;
|
|
|
|
case(BIND_PER_VERTEX):
|
|
|
|
if (_vertexArray.valid())
|
|
|
|
{
|
|
|
|
if (!_colorArray.valid()) return false;
|
|
|
|
if (_colorArray->getNumElements()!=_vertexArray->getNumElements()) return false;
|
|
|
|
}
|
|
|
|
else if (_colorArray.valid() && _colorArray->getNumElements()>0) return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(TexCoordArrayList::const_iterator itr=_texCoordList.begin();
|
|
|
|
itr!=_texCoordList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
const Array* array = itr->get();
|
|
|
|
if (_vertexArray.valid())
|
|
|
|
{
|
|
|
|
if (array && array->getNumElements()!=_vertexArray->getNumElements()) return false;
|
|
|
|
}
|
|
|
|
else if (array && array->getNumElements()>0) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Geometry::computeCorrectBindingsAndArraySizes()
|
|
|
|
{
|
|
|
|
if (verifyBindings()) return;
|
|
|
|
|
|
|
|
if (!_vertexArray.valid() || _vertexArray->empty())
|
|
|
|
{
|
|
|
|
// no vertex array so switch everything off.
|
|
|
|
|
|
|
|
_vertexArray = 0;
|
|
|
|
|
|
|
|
_colorArray = 0;
|
|
|
|
_colorBinding = BIND_OFF;
|
|
|
|
|
|
|
|
_normalArray = 0;
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
|
|
|
|
_texCoordList.clear();
|
|
|
|
|
|
|
|
notify(INFO)<<"Info: remove redundent attribute arrays from empty osg::Geometry"<<std::endl;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(_normalBinding)
|
|
|
|
{
|
|
|
|
case(BIND_OFF):
|
|
|
|
if (_normalArray.valid()) _normalArray = 0;
|
|
|
|
break;
|
|
|
|
case(BIND_OVERALL):
|
|
|
|
if (!_normalArray.valid())
|
|
|
|
{
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()==0)
|
|
|
|
{
|
|
|
|
_normalArray = 0;
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()>1)
|
|
|
|
{
|
|
|
|
// trim the array down to 1 element long.
|
|
|
|
_normalArray->erase(_normalArray->begin()+1,_normalArray->end());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case(BIND_PER_PRIMITIVE):
|
|
|
|
if (!_normalArray.valid())
|
|
|
|
{
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()<_primitives.size())
|
|
|
|
{
|
|
|
|
_normalArray = 0;
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()>_primitives.size())
|
|
|
|
{
|
|
|
|
// trim the array down to size of the number of primitives.
|
|
|
|
_normalArray->erase(_normalArray->begin()+_primitives.size(),_normalArray->end());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case(BIND_PER_VERTEX):
|
|
|
|
if (!_normalArray.valid())
|
|
|
|
{
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()<_vertexArray->getNumElements())
|
|
|
|
{
|
|
|
|
_normalArray = 0;
|
|
|
|
_normalBinding = BIND_OFF;
|
|
|
|
}
|
|
|
|
else if (_normalArray->getNumElements()>_vertexArray->getNumElements())
|
|
|
|
{
|
|
|
|
// trim the array down to size of the number of primitives.
|
|
|
|
_normalArray->erase(_normalArray->begin()+_vertexArray->getNumElements(),_normalArray->end());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO colours and tex coords.
|
|
|
|
|
|
|
|
}
|