Geometry 19.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library 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 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSG_GEOMETRY
#define OSG_GEOMETRY 1

#include <osg/Drawable>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Array>
#include <osg/PrimitiveSet>

namespace osg {


class OSG_EXPORT Geometry : public Drawable
{
    public:

        Geometry();

        /** Copy constructor using CopyOp to manage deep vs shallow copy. */
        Geometry(const Geometry& geometry,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
            
        virtual Object* cloneType() const { return new Geometry(); }
        virtual Object* clone(const CopyOp& copyop) const { return new Geometry(*this,copyop); }        
        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Geometry*>(obj)!=NULL; }
        virtual const char* libraryName() const { return "osg"; }
        virtual const char* className() const { return "Geometry"; }

        virtual Geometry* asGeometry() { return this; }
        virtual const Geometry* asGeometry() const { return this; }

        bool empty() const;

        enum AttributeBinding
        {
            BIND_OFF=0,
            BIND_OVERALL,
            BIND_PER_PRIMITIVE_SET,
            BIND_PER_PRIMITIVE,
            BIND_PER_VERTEX
        };
               
        struct OSG_EXPORT ArrayData
        {
            ArrayData():
                binding(BIND_OFF),
                normalize(GL_FALSE) {}
                
            ArrayData(const ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);

            ArrayData(Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
                array(a),
                indices(0),
                binding(b),
                normalize(n) {}

            ArrayData(Array* a, IndexArray* i, AttributeBinding b, GLboolean n = GL_FALSE):
                array(a),
                indices(i),
                binding(b),
                normalize(n) {}

            ArrayData& operator = (const ArrayData& rhs)
            {
                array = rhs.array;
                indices = rhs.indices;
                binding = rhs.binding;
                normalize = rhs.normalize;
                return *this;
            }
            
            inline bool empty() const { return !array.valid(); } 

            ref_ptr<Array>          array;
            ref_ptr<IndexArray>     indices;
            AttributeBinding        binding;
            GLboolean               normalize;
        };
        
        struct OSG_EXPORT Vec3ArrayData
        {
            Vec3ArrayData():
                binding(BIND_OFF),
                normalize(GL_FALSE) {}
                
            Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);

            Vec3ArrayData(Vec3Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
                array(a),
                indices(0),
                binding(b),
                normalize(n) {}

            Vec3ArrayData(Vec3Array* a, IndexArray* i, AttributeBinding b, GLboolean n = GL_FALSE):
                array(a),
                indices(i),
                binding(b),
                normalize(n) {}

            Vec3ArrayData& operator = (const Vec3ArrayData& rhs)
            {
                array = rhs.array;
                indices = rhs.indices;
                binding = rhs.binding;
                normalize = rhs.normalize;
                return *this;
            }

            inline bool empty() const { return !array.valid(); } 

            ref_ptr<Vec3Array>      array;
            ref_ptr<IndexArray>     indices;
            AttributeBinding        binding;
            GLboolean               normalize;
        };

        /** Static ArrayData which is returned from getTexCoordData(i) const and getVertexAttribData(i) const 
          * when i is out of range.
        */
        static const ArrayData s_InvalidArrayData;
        
        typedef std::vector< ArrayData >  ArrayDataList;
               

        void setVertexArray(Array* array);
        Array* getVertexArray() { return _vertexData.array.get(); }
        const Array* getVertexArray() const  { return _vertexData.array.get(); }

        void setVertexData(const ArrayData& arrayData);
        ArrayData& getVertexData() { return _vertexData; }
        const ArrayData& getVertexData() const { return _vertexData; }
        

        void setNormalBinding(AttributeBinding ab);
        AttributeBinding getNormalBinding() const { return _normalData.binding; }

        void setNormalArray(Array* array);
        Array* getNormalArray() { return _normalData.array.get(); }
        const Array* getNormalArray() const { return _normalData.array.get(); }

        void setNormalData(const ArrayData& arrayData);
        ArrayData& getNormalData() { return _normalData; }
        const ArrayData& getNormalData() const { return _normalData; }

        void setColorBinding(AttributeBinding ab);
        AttributeBinding getColorBinding() const { return _colorData.binding; }

        void setColorArray(Array* array);
        Array* getColorArray() { return _colorData.array.get(); }
        const Array* getColorArray() const { return _colorData.array.get(); }

        void setColorData(const ArrayData& arrayData);
        ArrayData& getColorData() { return _colorData; }
        const ArrayData& getColorData() const { return _colorData; }


        void setSecondaryColorBinding(AttributeBinding ab);
        AttributeBinding getSecondaryColorBinding() const { return _secondaryColorData.binding; }

        void setSecondaryColorArray(Array* array);
        Array* getSecondaryColorArray() { return _secondaryColorData.array.get(); }
        const Array* getSecondaryColorArray() const { return _secondaryColorData.array.get(); }

        void setSecondaryColorData(const ArrayData& arrayData);
        ArrayData& getSecondaryColorData() { return _secondaryColorData; }
        const ArrayData& getSecondaryColorData() const { return _secondaryColorData; }


        void setFogCoordBinding(AttributeBinding ab);
        AttributeBinding getFogCoordBinding() const { return _fogCoordData.binding; }

        void setFogCoordArray(Array* array);
        Array* getFogCoordArray() { return _fogCoordData.array.get(); }
        const Array* getFogCoordArray() const { return _fogCoordData.array.get(); }

        void setFogCoordData(const ArrayData& arrayData);
        ArrayData& getFogCoordData() { return _fogCoordData; }
        const ArrayData& getFogCoordData() const { return _fogCoordData; }
        

        void setTexCoordArray(unsigned int unit,Array*);
        Array* getTexCoordArray(unsigned int unit);
        const Array* getTexCoordArray(unsigned int unit) const;

        void setTexCoordData(unsigned int index,const ArrayData& arrayData);
        ArrayData& getTexCoordData(unsigned int index);
        const ArrayData& getTexCoordData(unsigned int index) const;

        unsigned int getNumTexCoordArrays() const {  return static_cast<unsigned int>(_texCoordList.size()); }
        ArrayDataList& getTexCoordArrayList() { return _texCoordList; }
        const ArrayDataList& getTexCoordArrayList() const { return _texCoordList; }



        void setVertexAttribArray(unsigned int index,Array* array);
        Array *getVertexAttribArray(unsigned int index);
        const Array *getVertexAttribArray(unsigned int index) const;

        void setVertexAttribBinding(unsigned int index,AttributeBinding ab);
        AttributeBinding getVertexAttribBinding(unsigned int index) const;

        void setVertexAttribNormalize(unsigned int index,GLboolean norm);
        GLboolean getVertexAttribNormalize(unsigned int index) const;

        void setVertexAttribData(unsigned int index,const ArrayData& arrayData);
        ArrayData& getVertexAttribData(unsigned int index);
        const ArrayData& getVertexAttribData(unsigned int index) const;

        unsigned int getNumVertexAttribArrays() const { return static_cast<unsigned int>(_vertexAttribList.size()); }
        ArrayDataList& getVertexAttribArrayList() { return _vertexAttribList; }
        const ArrayDataList& getVertexAttribArrayList() const { return _vertexAttribList; }



        typedef std::vector< ref_ptr<PrimitiveSet> > PrimitiveSetList;

        void setPrimitiveSetList(const PrimitiveSetList& primitives);
        
        PrimitiveSetList& getPrimitiveSetList() { return _primitives; }
        const PrimitiveSetList& getPrimitiveSetList() const { return _primitives; }

        unsigned int getNumPrimitiveSets() const { return static_cast<unsigned int>(_primitives.size()); }
        PrimitiveSet* getPrimitiveSet(unsigned int pos) { return _primitives[pos].get(); }
        const PrimitiveSet* getPrimitiveSet(unsigned int pos) const { return _primitives[pos].get(); }
        
        /** Add a primitive set to the geometry. */
        bool addPrimitiveSet(PrimitiveSet* primitiveset);
        
        /** Set a primitive set to the specified position in geometry's primitive set list. */
        bool setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset);
        
        /** Insert a primitive set to the specified position in geometry's primitive set list. */
        bool insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset);
        
        /** Remove primitive set(s) from the specified position in geometry's primitive set list. */
        bool removePrimitiveSet(unsigned int i,unsigned int numElementsToRemove=1);

        /** Get the index number of a primitive set, return a value between
          * 0 and getNumPrimitiveSet()-1 if found, if not found then return getNumPrimitiveSet().
          * When checking for a valid find value use if ((value=geometry->getPrimitiveSetIndex(primitive))!=geometry.getNumPrimitiveSet())
        */
        unsigned int getPrimitiveSetIndex(const PrimitiveSet* primitiveset) const;



        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setVertexIndices(IndexArray* array);
        IndexArray* getVertexIndices() { return _vertexData.indices.get(); }
        const IndexArray* getVertexIndices() const  { return _vertexData.indices.get(); }
     
        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setNormalIndices(IndexArray* array);
        IndexArray* getNormalIndices() { return _normalData.indices.get(); }
        const IndexArray* getNormalIndices() const { return _normalData.indices.get(); }

        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setColorIndices(IndexArray* array);
        IndexArray* getColorIndices() { return _colorData.indices.get(); }
        const IndexArray* getColorIndices() const { return _colorData.indices.get(); }

        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setSecondaryColorIndices(IndexArray* array);
        IndexArray* getSecondaryColorIndices() { return _secondaryColorData.indices.get(); }
        const IndexArray* getSecondaryColorIndices() const { return _secondaryColorData.indices.get(); }

        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setFogCoordIndices(IndexArray* array);
        IndexArray* getFogCoordIndices() { return _fogCoordData.indices.get(); }
        const IndexArray* getFogCoordIndices() const { return _fogCoordData.indices.get(); }

        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setTexCoordIndices(unsigned int unit,IndexArray*);
        IndexArray* getTexCoordIndices(unsigned int unit);
        const IndexArray* getTexCoordIndices(unsigned int unit) const;

        /** deprecated - forces OpenGL slow path, just kept for backwards compatibility.*/
        void setVertexAttribIndices(unsigned int index,IndexArray* array);
        IndexArray* getVertexAttribIndices(unsigned int index);
        const IndexArray* getVertexAttribIndices(unsigned int index) const;




        /** When set to true, ignore the setUseDisplayList() settings, and hints to the drawImplementation 
            method to use OpenGL vertex buffer objects for rendering.*/
        virtual void setUseVertexBufferObjects(bool flag);

        /** Force a recompile on next draw() of any OpenGL display list associated with this geoset.*/
        virtual void dirtyDisplayList();


        /** Resize any per context GLObject buffers to specified size. */
        virtual void resizeGLObjectBuffers(unsigned int maxSize);

        /** If State is non-zero, this function releases OpenGL objects for
          * the specified graphics context. Otherwise, releases OpenGL objects
          * for all graphics contexts. */
        virtual void releaseGLObjects(State* state=0) const;

        typedef std::vector<osg::Array*>  ArrayList;
        bool getArrayList(ArrayList& arrayList) const;

        typedef std::vector<osg::DrawElements*>  DrawElementsList;
        bool getDrawElementsList(DrawElementsList& drawElementsList) const;

        osg::VertexBufferObject* getOrCreateVertexBufferObject();

        osg::ElementBufferObject* getOrCreateElementBufferObject();


        /** Set whether fast paths should be used when supported. */
        void setFastPathHint(bool on) {  _fastPathHint = on; }

        /** Get whether fast paths should be used when supported. */
        bool getFastPathHint() const { return _fastPathHint; }


        /** Return true if OpenGL fast paths will be used with drawing this Geometry.
          * Fast paths directly use vertex arrays, and glDrawArrays/glDrawElements so have low CPU overhead.
          * With Slow paths the osg::Geometry::drawImplementation has to dynamically assemble OpenGL
          * compatible vertex arrays from the osg::Geometry arrays data and then dispatch these to OpenGL,
          * so have higher CPU overhead than the Fast paths.
          * Use of per primitive bindings or per vertex indexed arrays will drop the rendering path off the fast path.
        */
        inline bool areFastPathsUsed() const
        {
            if (_internalOptimizedGeometry.valid())
                return _internalOptimizedGeometry->areFastPathsUsed();
            else
                return _fastPath && _fastPathHint;
        }

        bool computeFastPathsUsed();

        bool verifyBindings() const;

        void computeCorrectBindingsAndArraySizes();

        /** check whether the arrays, indices, bindings and primitives all match correctly, return false is .*/
        bool verifyArrays(std::ostream& out) const;

        bool suitableForOptimization() const;

        void copyToAndOptimize(Geometry& target);


        bool containsSharedArrays() const;
        
        void duplicateSharedArrays();
        

        void computeInternalOptimizedGeometry();

        void removeInternalOptimizedGeometry() { _internalOptimizedGeometry = 0; }

        void setInternalOptimizedGeometry(osg::Geometry* geometry) { _internalOptimizedGeometry = geometry; }

        osg::Geometry* getInternalOptimizedGeometry() { return _internalOptimizedGeometry.get(); }

        const osg::Geometry* getInternalOptimizedGeometry() const { return _internalOptimizedGeometry.get(); }


        /** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable.
          * This size is used a hint for reuse of deleted display lists/vertex buffer objects. */
        virtual unsigned int getGLObjectSizeHint() const;

        /** Immediately compile this \c Drawable into an OpenGL Display List/VertexBufferObjects.
          * @note Operation is ignored if \c _useDisplayList is \c false or VertexBufferObjects are not used.
        */
        virtual void compileGLObjects(RenderInfo& renderInfo) const;

        /** Draw Geometry directly ignoring an OpenGL display list which could be attached.
          * This is the internal draw method which does the drawing itself,
          * and is the method to override when deriving from Geometry for user-drawn objects.
        */
        virtual void drawImplementation(RenderInfo& renderInfo) const;

        /** Return true, osg::Geometry does support accept(Drawable::AttributeFunctor&). */
        virtual bool supports(const Drawable::AttributeFunctor&) const { return true; }

        /** Accept an Drawable::AttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */
        virtual void accept(Drawable::AttributeFunctor& af);

        /** Return true, osg::Geometry does support accept(Drawable::ConstAttributeFunctor&). */
        virtual bool supports(const Drawable::ConstAttributeFunctor&) const { return true; }

        /** Accept a Drawable::ConstAttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */
        virtual void accept(Drawable::ConstAttributeFunctor& af) const;

        /** Return true, osg::Geometry does support accept(PrimitiveFunctor&). */
        virtual bool supports(const PrimitiveFunctor&) const { return true; }

        /** Accept a PrimitiveFunctor and call its methods to tell it about the internal primitives that this Drawable has. */
        virtual void accept(PrimitiveFunctor& pf) const;

        /** Return true, osg::Geometry does support accept(PrimitiveIndexFunctor&). */
        virtual bool supports(const PrimitiveIndexFunctor&) const { return true; }

        /** Accept a PrimitiveFunctor and call its methods to tell it about the internal primitives that this Drawable has. */
        virtual void accept(PrimitiveIndexFunctor& pf) const;


    protected:

        Geometry& operator = (const Geometry&) { return *this;}

        virtual ~Geometry();
       
        bool verifyBindings(const ArrayData& arrayData) const;
        bool verifyBindings(const Vec3ArrayData& arrayData) const;
        
        void computeCorrectBindingsAndArraySizes(ArrayData& arrayData,const char* arrayName);
        void computeCorrectBindingsAndArraySizes(Vec3ArrayData& arrayData,const char* arrayName);
        
        void addVertexBufferObjectIfRequired(osg::Array* array);
        void addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet);
        

        PrimitiveSetList                _primitives;
        ArrayData                       _vertexData;
        ArrayData                       _normalData;
        ArrayData                       _colorData;
        ArrayData                       _secondaryColorData;
        ArrayData                       _fogCoordData;
        ArrayDataList                   _texCoordList;
        ArrayDataList                   _vertexAttribList;

        mutable bool                    _fastPath;
        bool                            _fastPathHint;

        ref_ptr<Geometry>               _internalOptimizedGeometry;
};

/** Convenience function to be used for creating quad geometry with texture coords.
  * Tex coords go from left bottom (l,b) to right top (r,t).
*/
extern OSG_EXPORT Geometry* createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t);

/** Convenience function to be used for creating quad geometry with texture coords.
  * Tex coords go from bottom left (0,0) to top right (s,t).
*/
inline Geometry* createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float s=1.0f, float t=1.0f)
{
    return createTexturedQuadGeometry(corner,widthVec,heightVec, 0.0f, 0.0f, s, t);
}


}

#endif