From 950f51909c50066342dab39673e2df2f1eb74c31 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 13 Feb 2009 09:35:50 +0100 Subject: [PATCH] New getPrimitive function. This searches for the primitive found in an OSG intersection query. --- projects/VC7.1/SimGear.vcproj | 7 + simgear/scene/util/Makefile.am | 2 + simgear/scene/util/PrimitiveUtils.cxx | 323 ++++++++++++++++++++++++++ simgear/scene/util/PrimitiveUtils.hxx | 43 ++++ 4 files changed, 375 insertions(+) create mode 100644 simgear/scene/util/PrimitiveUtils.cxx create mode 100644 simgear/scene/util/PrimitiveUtils.hxx diff --git a/projects/VC7.1/SimGear.vcproj b/projects/VC7.1/SimGear.vcproj index b305088b..c3370534 100755 --- a/projects/VC7.1/SimGear.vcproj +++ b/projects/VC7.1/SimGear.vcproj @@ -1136,6 +1136,13 @@ + + + + + diff --git a/simgear/scene/util/Makefile.am b/simgear/scene/util/Makefile.am index 28af3fdc..567ec697 100644 --- a/simgear/scene/util/Makefile.am +++ b/simgear/scene/util/Makefile.am @@ -15,6 +15,7 @@ include_HEADERS = \ SGTextureStateAttributeVisitor.hxx \ SGUpdateVisitor.hxx \ NodeAndDrawableVisitor.hxx \ + PrimitiveUtils.hxx \ QuadTreeBuilder.hxx \ RenderConstants.hxx \ StateAttributeFactory.hxx \ @@ -28,6 +29,7 @@ libsgutil_a_SOURCES = \ SGStateAttributeVisitor.cxx \ SGTextureStateAttributeVisitor.cxx \ NodeAndDrawableVisitor.cxx \ + PrimitiveUtils.cxx \ StateAttributeFactory.cxx \ QuadTreeBuilder.cxx diff --git a/simgear/scene/util/PrimitiveUtils.cxx b/simgear/scene/util/PrimitiveUtils.cxx new file mode 100644 index 00000000..b2f14c1c --- /dev/null +++ b/simgear/scene/util/PrimitiveUtils.cxx @@ -0,0 +1,323 @@ +/* -*-c++-*- + * + * Copyright (C) 2009 Tim Moore + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "PrimitiveUtils.hxx" + +using namespace osg; + +namespace +{ +class GetPrimitive : public PrimitiveFunctor +{ +public: + simgear::Primitive result; + GetPrimitive(unsigned int primitiveIndex) + : _primitiveIndex(primitiveIndex), _primitivesSeen(0), + _vertexArrayPtr(0), _modeCache(0) + { + result.numVerts = 0; + } + + virtual void setVertexArray(unsigned int,const Vec2*) + { + notify(WARN)<<"GetPrimitive does not support Vec2* vertex arrays"< + void drawElementsTemplate(GLenum mode_, GLsizei count, + const IndexType* indices) + { + if (_primitiveIndex < _primitivesSeen) { + return; + } + int numPrims = getNumPrims(mode_, count); + if (_primitivesSeen + numPrims < _primitiveIndex) { + _primitivesSeen += numPrims; + return; + } + int primInSet = _primitiveIndex - _primitivesSeen; + switch (mode_) { + case GL_POINTS: + result.numVerts = 1; + result.vertices[0] = _vertexArrayPtr[indices[primInSet]]; + break; + case GL_LINES: + result.numVerts = 2; + result.vertices[0] = _vertexArrayPtr[indices[primInSet * 2]]; + result.vertices[1] = _vertexArrayPtr[indices[primInSet * 2 + 1]]; + break; + case GL_TRIANGLES: + result.numVerts = 3; + for (int i = 0; i < 3; ++i) + result.vertices[i] = _vertexArrayPtr[indices[primInSet * 3 + i]]; + break; + case GL_QUADS: + result.numVerts = 4; + for (int i = 0; i < 4; ++i) + result.vertices[i] = _vertexArrayPtr[indices[primInSet * 4 + i]]; + break; + case GL_LINE_STRIP: + result.numVerts = 2; + result.vertices[0] = _vertexArrayPtr[indices[primInSet]]; + result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]]; + break; + case GL_LINE_LOOP: + result.numVerts = 2; + if (primInSet < numPrims - 1) { + result.vertices[0] = _vertexArrayPtr[indices[primInSet]]; + result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]]; + } else { + result.vertices[0] = _vertexArrayPtr[indices[count - 1]]; + result.vertices[1] = _vertexArrayPtr[indices[0]]; + } + break; + case GL_TRIANGLE_STRIP: + result.numVerts = 3; + result.vertices[0] = _vertexArrayPtr[indices[primInSet]]; + if (primInSet % 2) { + result.vertices[1] = _vertexArrayPtr[indices[primInSet + 2]]; + result.vertices[2] = _vertexArrayPtr[indices[primInSet + 1]]; + } else { + result.vertices[1] = _vertexArrayPtr[indices[primInSet + 1]]; + result.vertices[2] = _vertexArrayPtr[indices[primInSet + 2]]; + } + break; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + result.numVerts = 3; + result.vertices[0] = _vertexArrayPtr[indices[0]]; + result.vertices[1] = _vertexArrayPtr[indices[1 + primInSet]]; + result.vertices[2] = _vertexArrayPtr[indices[1 + primInSet + 1]]; + break; + case GL_QUAD_STRIP: + result.numVerts = 4; + result.vertices[0] = _vertexArrayPtr[indices[primInSet / 2]]; + result.vertices[1] = _vertexArrayPtr[indices[primInSet / 2 + 1]]; + result.vertices[2] = _vertexArrayPtr[indices[primInSet / 2 + 3]]; + result.vertices[3] = _vertexArrayPtr[indices[primInSet / 2 + 2]]; + break; + default: + break; + } + _primitivesSeen += numPrims; + } + + void drawElements(GLenum mode_, GLsizei count, const GLubyte* indices) + { + drawElementsTemplate(mode_, count, indices); + } + + void drawElements(GLenum mode_, GLsizei count, const GLushort* indices) + { + drawElementsTemplate(mode_, count, indices); + } + + void drawElements(GLenum mode_,GLsizei count,const GLuint* indices) + { + drawElementsTemplate(mode_, count, indices); + } + + virtual void begin(GLenum mode) + { + _modeCache = mode; + _vertexCache.clear(); + } + + void vertex(const Vec2& vert) + { + _vertexCache.push_back(osg::Vec3(vert[0],vert[1],0.0f)); + } + void vertex(const Vec3& vert) + { + _vertexCache.push_back(vert); + } + void vertex(const Vec4& vert) + { + _vertexCache.push_back(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); + } + void vertex(float x,float y) + { + _vertexCache.push_back(osg::Vec3(x,y,0.0f)); + } + void vertex(float x,float y,float z) + { + _vertexCache.push_back(osg::Vec3(x,y,z)); + } + void vertex(float x,float y,float z,float w) + { + _vertexCache.push_back(osg::Vec3(x,y,z)/w); + + } + + void end() + { + if (!_vertexCache.empty()) { + const Vec3* oldVert = _vertexArrayPtr; + setVertexArray(_vertexCache.size(), &_vertexCache.front()); + drawArrays(_modeCache, 0, _vertexCache.size()); + _vertexArrayPtr = oldVert; + } + } + +protected: + int getNumPrims(GLenum mode, int count) + { + switch (mode) { + case GL_POINTS: + return count; + case GL_LINES: + return count / 2; + case GL_TRIANGLES: + return count / 3; + case GL_QUADS: + return count / 4; + case GL_LINE_STRIP: + return count - 1; + case GL_LINE_LOOP: + return count; + case GL_TRIANGLE_STRIP: + return count - 2; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + return count - 2; + case GL_QUAD_STRIP: + return (count - 2) / 2; + } + } + unsigned _primitiveIndex; + unsigned _primitivesSeen; + const Vec3* _vertexArrayPtr; + GLenum _modeCache; + std::vector _vertexCache; +}; +} + +namespace simgear +{ +Primitive getPrimitive(Drawable* drawable, unsigned primitiveIndex) +{ + GetPrimitive getPrim(primitiveIndex); + drawable->accept(getPrim); + return getPrim.result; +} +} diff --git a/simgear/scene/util/PrimitiveUtils.hxx b/simgear/scene/util/PrimitiveUtils.hxx new file mode 100644 index 00000000..f9e1728c --- /dev/null +++ b/simgear/scene/util/PrimitiveUtils.hxx @@ -0,0 +1,43 @@ +/* -*-c++-*- + * + * Copyright (C) 2009 Tim Moore + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#ifndef SIMGEAR_PRIMITIVEUTILS_HXX +#define SIMGEAR_PRIMITIVEUTILS_HXX 1 + +#include +#include + +namespace simgear +{ +struct Primitive +{ + int numVerts; + osg::Vec3 vertices[4]; +}; + +/** + * Given a drawable and a primitive index (as returned from OSG + * intersection queries), get the coordinates of the primitives + * vertices. + */ +Primitive getPrimitive(osg::Drawable* drawable, unsigned primitiveIndex); +} +#endif