]> git.mxchange.org Git - simgear.git/commitdiff
New getPrimitive function.
authorTim Moore <timoore@redhat.com>
Fri, 13 Feb 2009 08:35:50 +0000 (09:35 +0100)
committerTim Moore <timoore@redhat.com>
Fri, 13 Feb 2009 08:40:05 +0000 (09:40 +0100)
This searches for the primitive found in an OSG intersection query.

projects/VC7.1/SimGear.vcproj
simgear/scene/util/Makefile.am
simgear/scene/util/PrimitiveUtils.cxx [new file with mode: 0644]
simgear/scene/util/PrimitiveUtils.hxx [new file with mode: 0644]

index b305088beaa47100b452e6c5e856c293c5f2e3ec..c3370534058e882a8226300c86545efcab288344 100755 (executable)
                        <File
                                RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.hxx">
                        </File>
+                       <File
+                               RelativePath="..\..\simgear\scene\util\PrimitiveUtils.cxx">
+                       </File>
+                       <File
+                               RelativePath="..\..\simgear\scene\util\PrimitiveUtils.hxx">
+                       </File>
+
                        <File
                                RelativePath="..\..\simgear\scene\util\QuadTreeBuilder.cxx">
                        </File>
index 28af3fdc8121e2e8ba9a49563e3d6a7c819248db..567ec69708dbd9c223f6da3c72775e7cc833f43c 100644 (file)
@@ -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 (file)
index 0000000..b2f14c1
--- /dev/null
@@ -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"<<std::endl;
+    }
+
+    virtual void setVertexArray(unsigned int count,const Vec3* vertices)
+    {
+        _vertexArrayPtr = vertices;
+    }
+
+    virtual void setVertexArray(unsigned int,const Vec4* )
+    {
+        notify(WARN)<<"GetPrimitive does not support Vec4* vertex arrays"<<std::endl;
+    }
+
+    virtual void setVertexArray(unsigned int,const Vec2d*)
+    {
+        notify(WARN)<<"GetPrimitive does not support Vec2d* vertex arrays"<<std::endl;
+    }
+
+    virtual void setVertexArray(unsigned int,const Vec3d*)
+    {
+        notify(WARN)<<"GetPrimitive does not support Vec3d* vertex arrays"<<std::endl;
+    }
+
+    virtual void setVertexArray(unsigned int,const Vec4d* )
+    {
+        notify(WARN)<<"GetPrimitive does not support Vec4d* vertex arrays"<<std::endl;
+    }
+    
+    void drawArrays(GLenum mode_, GLint first, GLsizei count)
+    {
+        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[first + primInSet];
+            break;
+        case GL_LINES:
+            result.numVerts = 2;
+            result.vertices[0] = _vertexArrayPtr[first + primInSet * 2];
+            result.vertices[1] = _vertexArrayPtr[first + primInSet * 2 + 1];
+            break;
+        case GL_TRIANGLES:
+            result.numVerts = 3;
+            for (int i = 0; i < 3; ++i)
+                result.vertices[i] = _vertexArrayPtr[first + primInSet * 3 + i];
+            break;
+        case GL_QUADS:
+            result.numVerts = 4;
+            for (int i = 0; i < 4; ++i)
+                result.vertices[i] = _vertexArrayPtr[first + primInSet * 4 + i];
+            break;
+        case GL_LINE_STRIP:
+            result.numVerts = 2;
+            result.vertices[0] = _vertexArrayPtr[first + primInSet];
+            result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
+            break;
+        case GL_LINE_LOOP:
+            result.numVerts = 2;
+            if (primInSet < numPrims - 1) {
+                result.vertices[0] = _vertexArrayPtr[first + primInSet];
+                result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
+            } else {
+                result.vertices[0] = _vertexArrayPtr[first + count - 1];
+                result.vertices[1] = _vertexArrayPtr[first];
+            }
+            break;
+        case GL_TRIANGLE_STRIP:
+            result.numVerts = 3;
+                result.vertices[0] = _vertexArrayPtr[first + primInSet];
+            if (primInSet % 2) {
+                result.vertices[1] = _vertexArrayPtr[first + primInSet + 2];
+                result.vertices[2] = _vertexArrayPtr[first + primInSet + 1];
+            } else {
+                result.vertices[1] = _vertexArrayPtr[first + primInSet + 1];
+                result.vertices[2] = _vertexArrayPtr[first + primInSet + 2];
+            }
+            break;
+        case GL_TRIANGLE_FAN:
+        case GL_POLYGON:
+            result.numVerts = 3;
+            result.vertices[0] = _vertexArrayPtr[first];
+            result.vertices[1] = _vertexArrayPtr[first + 1 + primInSet];
+            result.vertices[2] = _vertexArrayPtr[first + 1 + primInSet + 1];
+            break;
+        case GL_QUAD_STRIP:
+            result.numVerts = 4;
+            result.vertices[0] = _vertexArrayPtr[first + primInSet / 2];
+            result.vertices[1] = _vertexArrayPtr[first + primInSet / 2 + 1];
+            result.vertices[2] = _vertexArrayPtr[first + primInSet / 2 + 3];
+            result.vertices[3] = _vertexArrayPtr[first + primInSet / 2 + 2];
+            break;
+        default:
+            break;
+        }
+        _primitivesSeen += numPrims;        
+    }
+
+    template<class IndexType>
+    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<Vec3>  _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 (file)
index 0000000..f9e1728
--- /dev/null
@@ -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 <osg/Vec3>
+#include <osg/Drawable>
+
+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