#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Group>
-#include <osg/MatrixTransform>
#include <osg/PagedLOD>
#include <osg/Transform>
#include <osg/TriangleFunctor>
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
virtual void drawArrays(GLenum mode, GLint first, GLsizei count)
{
- if (_vertices.empty() || count==0)
+ if (_vertices.empty() || count <= 0)
return;
+ GLsizei end = first + count;
switch(mode) {
case (GL_TRIANGLES):
- for (GLsizei i = first; i < first + count; i += 3) {
+ for (GLsizei i = first; i < end - 2; i += 3) {
addTriangle(i, i + 1, i + 2);
}
break;
case (GL_TRIANGLE_STRIP):
- for (GLsizei i = 0; i < count; i += 3) {
- if (i%2)
- addTriangle(first + i, first + i + 2, first + i + 1);
- else
- addTriangle(first + i, first + i + 1, first + i + 2);
+ for (GLsizei i = first; i < end - 2; ++i) {
+ addTriangle(i, i + 1, i + 2);
}
break;
case (GL_QUADS):
- for (GLsizei i = first; i < first + count; i += 4) {
+ for (GLsizei i = first; i < end - 3; i += 4) {
addQuad(i, i + 1, i + 2, i + 3);
}
break;
case (GL_QUAD_STRIP):
- for (GLsizei i = 0; i < count - 2; i += 2) {
- if (i%4)
- addQuad(first + i + 1, first + i, i + 3, first + i + 2);
- else
- addQuad(first + i, first + i + 1, first + i + 2, first + i + 3);
+ for (GLsizei i = first; i < end - 3; i += 2) {
+ addQuad(i, i + 1, i + 2, i + 3);
}
break;
case (GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case (GL_TRIANGLE_FAN):
- for (GLsizei i = first + 2; i < first + count; ++i) {
- addTriangle(first, i - 1, i);
+ for (GLsizei i = first; i < end - 2; ++i) {
+ addTriangle(first, i + 1, i + 2);
}
break;
case (GL_POINTS):
- for (GLsizei i = 0; i < count; ++i) {
- addPoint(first + i);
+ for (GLsizei i = first; i < end; ++i) {
+ addPoint(i);
}
break;
case (GL_LINES):
- for (GLsizei i = first; i < first + count; i += 2) {
+ for (GLsizei i = first; i < end - 1; i += 2) {
addLine(i, i + 1);
}
break;
case (GL_LINE_STRIP):
- for (GLsizei i = first; i < first + count; ++i) {
+ for (GLsizei i = first; i < end - 1; ++i) {
addLine(i, i + 1);
}
break;
case (GL_LINE_LOOP):
- for (GLsizei i = first; i < first + count; ++i) {
+ for (GLsizei i = first; i < end - 1; ++i) {
addLine(i, i + 1);
}
- addLine(first + count - 1, first);
+ addLine(end - 1, first);
break;
default:
void drawElementsTemplate(GLenum mode, GLsizei count,
const index_type* indices)
{
- if (_vertices.empty() || indices == 0 || count == 0)
+ if (_vertices.empty() || indices == 0 || count <= 0)
return;
switch(mode) {
case (GL_TRIANGLES):
- for (GLsizei i = 0; i < count; i += 3) {
+ for (GLsizei i = 0; i < count - 2; i += 3) {
addTriangle(indices[i], indices[i + 1], indices[i + 2]);
}
break;
case (GL_TRIANGLE_STRIP):
- for (GLsizei i = 2; i < count; ++i) {
- if (i%2)
- addTriangle(indices[i - 2], indices[i], indices[i - 1]);
- else
- addTriangle(indices[i - 2], indices[i - 1], indices[i]);
+ for (GLsizei i = 0; i < count - 2; ++i) {
+ addTriangle(indices[i], indices[i + 1], indices[i + 2]);
}
break;
case (GL_QUADS):
- for (GLsizei i = 0; i < count; i += 4) {
+ for (GLsizei i = 0; i < count - 3; i += 4) {
addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
}
break;
case (GL_QUAD_STRIP):
- for (GLsizei i = 3; i < count; i += 2) {
- if (i%4)
- addQuad(indices[i - 2], indices[i - 3], indices[i], indices[i - 1]);
- else
- addQuad(indices[i - 3], indices[i - 2], indices[i - 1], indices[i]);
+ for (GLsizei i = 0; i < count - 3; i += 2) {
+ addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
}
break;
case (GL_POLYGON):
case (GL_TRIANGLE_FAN):
- for (GLsizei i = 2; i < count; ++i) {
- addTriangle(indices[0], indices[i - 1], indices[i]);
+ for (GLsizei i = 0; i < count - 2; ++i) {
+ addTriangle(indices[0], indices[i + 1], indices[i + 2]);
}
break;
break;
case (GL_LINES):
- for (GLsizei i = 0; i < count; i += 2) {
+ for (GLsizei i = 0; i < count - 1; i += 2) {
addLine(indices[i], indices[i + 1]);
}
break;
case (GL_LINE_STRIP):
- for (GLsizei i = 0; i < count; ++i) {
+ for (GLsizei i = 0; i < count - 1; ++i) {
addLine(indices[i], indices[i + 1]);
}
break;
case (GL_LINE_LOOP):
- for (GLsizei i = 0; i < count; ++i) {
+ for (GLsizei i = 0; i < count - 1; ++i) {
addLine(indices[i], indices[i + 1]);
}
addLine(indices[count - 1], indices[0]);
// virtual void end() = 0;
// };
- BoundingVolumeBuildVisitor() :
- osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
+ BoundingVolumeBuildVisitor(bool dumpIntoLeafs) :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+ _dumpIntoLeafs(dumpIntoLeafs)
{
setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
}
{
}
- const SGMaterial* pushMaterial(osg::StateSet* stateSet)
+ const SGMaterial* pushMaterial(Effect* effect)
{
const SGMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
- const SGMaterial* material = SGMaterialLib::findMaterial(stateSet);
+ const SGMaterial* material = SGMaterialLib::findMaterial(effect);
if (material)
_primitiveFunctor.setCurrentMaterial(material);
return oldMaterial;
void fillWith(osg::Drawable* drawable)
{
- const SGMaterial* oldMaterial = pushMaterial(drawable->getStateSet());
drawable->accept(_primitiveFunctor);
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
}
virtual void apply(osg::Geode& geode)
{
- const SGMaterial* oldMaterial = pushMaterial(geode.getStateSet());
+ if (hasBoundingVolumeTree(geode))
+ return;
+
+ const SGMaterial* oldMaterial = 0;
- if (!hasBoundingVolumeTree(geode))
+ EffectGeode *eg = dynamic_cast<EffectGeode*>(&geode);
+ if (eg)
+ oldMaterial = pushMaterial(eg->getEffect());
+
+ bool flushHere = getNodePath().size() <= 1 || _dumpIntoLeafs;
+ if (flushHere) {
+ // push the current active primitive list
+ PFunctor previousPrimitives;
+ _primitiveFunctor.swap(previousPrimitives);
+
+ // walk the children
for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
fillWith(geode.getDrawable(i));
- // Flush the bounding volume tree if we reached the topmost group
- if (getNodePath().size() <= 1)
+ // Flush the bounding volume tree if we reached the topmost group
addBoundingVolumeTreeToNode(geode);
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+
+ // pop the current active primitive list
+ _primitiveFunctor.swap(previousPrimitives);
+ } else {
+ for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
+ fillWith(geode.getDrawable(i));
+ }
+ if (eg)
+ _primitiveFunctor.setCurrentMaterial(oldMaterial);
}
virtual void apply(osg::Group& group)
- {
- // Note that we do not need to push the already collected list of
- // primitives, since we are now in the topmost node ...
-
- const SGMaterial* oldMaterial = pushMaterial(group.getStateSet());
+ { traverseAndCollect(group); }
- if (!hasBoundingVolumeTree(group))
- traverse(group);
+ virtual void apply(osg::Transform& transform)
+ { traverseAndDump(transform); }
- // Flush the bounding volume tree if we reached the topmost group
- if (getNodePath().size() <= 1)
- addBoundingVolumeTreeToNode(group);
+ virtual void apply(osg::PagedLOD&)
+ {
+ // Do nothing. In this case we get called by the loading process anyway
+ }
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+ virtual void apply(osg::Camera& camera)
+ {
+ if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+ return;
+ traverseAndDump(camera);
}
- virtual void apply(osg::Transform& transform)
+ void traverseAndDump(osg::Node& node)
{
+ if (hasBoundingVolumeTree(node))
+ return;
+
// push the current active primitive list
PFunctor previousPrimitives;
_primitiveFunctor.swap(previousPrimitives);
- const SGMaterial* oldMaterial = pushMaterial(transform.getStateSet());
-
// walk the children
- if (!hasBoundingVolumeTree(transform))
- traverse(transform);
+ traverse(node);
// We know whenever we see a transform, we need to flush the
// collected bounding volume tree since these transforms are not
// handled by the plain leafs.
- addBoundingVolumeTreeToNode(transform);
-
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+ addBoundingVolumeTreeToNode(node);
// pop the current active primitive list
_primitiveFunctor.swap(previousPrimitives);
}
- virtual void apply(osg::PagedLOD&)
+ void traverseAndCollect(osg::Node& node)
{
- // Do nothing. In this case we get called by the loading process anyway
- }
+ // Already been here??
+ if (hasBoundingVolumeTree(node))
+ return;
- virtual void apply(osg::Camera& camera)
- {
- if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+ // Force a flush of the bvtree if we are in the topmost node.
+ if (getNodePath().size() <= 1) {
+ traverseAndDump(node);
return;
- apply(static_cast<osg::Transform&>(camera));
+ }
+
+ // Note that we do not need to push the already collected list of
+ // primitives, since we are now in the topmost node ...
+
+ // walk the children
+ traverse(node);
}
void addBoundingVolumeTreeToNode(osg::Node& node)
private:
PFunctor _primitiveFunctor;
+ bool _dumpIntoLeafs;
};
}