OgreProgressiveMesh.h

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright (c) 2000-2012 Torus Knot Software Ltd
00008 
00009 Permission is hereby granted, free of charge, to any person obtaining a copy
00010 of this software and associated documentation files (the "Software"), to deal
00011 in the Software without restriction, including without limitation the rights
00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013 copies of the Software, and to permit persons to whom the Software is
00014 furnished to do so, subject to the following conditions:
00015 
00016 The above copyright notice and this permission notice shall be included in
00017 all copies or substantial portions of the Software.
00018 
00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025 THE SOFTWARE.
00026 -----------------------------------------------------------------------------
00027 */
00028 // The underlying algorithms in this class are based heavily on:
00029 /*
00030  *  Progressive Mesh type Polygon Reduction Algorithm
00031  *  by Stan Melax (c) 1998
00032  */
00033 
00034 #ifndef __ProgressiveMesh_H_
00035 #define __ProgressiveMesh_H_
00036 
00037 #include "OgrePrerequisites.h"
00038 #include "OgreVector3.h"
00039 #include "OgreVector2.h"
00040 #include "OgreHardwareVertexBuffer.h"
00041 #include "OgreHardwareIndexBuffer.h"
00042 #include "OgreRenderOperation.h"
00043 #include "OgreSmallVector.h"
00044 
00045 namespace Ogre {
00046 
00053     class Mesh;
00054     class SubMesh;
00055     
00056     class _OgreExport BitArray
00057     {
00058     public:
00059         BitArray()                  : bits_ptr(NULL) {}
00060         BitArray(int bits_count)    : bits_ptr(NULL) { resize(bits_count); }
00061         BitArray& operator=(const BitArray& ba) { bits = ba.bits; bits_ptr = bits.size() > 0 ? &bits.front() : NULL; return *this; }
00062         
00063         bool getBit(size_t i) const { return bits_ptr[i >> 3] & bit_mask[i & 7]; }
00064         void setBit(size_t i)       { bits_ptr[i >> 3] |= bit_mask[i & 7]; }
00065         void clearBit(size_t i)     { bits_ptr[i >> 3] &= ~bit_mask[i & 7]; }
00066         void clearAllBits()         { memset(bits_ptr, 0, bits.size()); }
00067         
00068         bool empty() const          { return bits.empty(); }
00069         void resize(size_t bits_count)
00070         {       
00071             bits.resize((bits_count + 7) / 8);
00072             bits_ptr = bits.size() > 0 ? &bits.front() : NULL;
00073             clearAllBits();
00074         }
00075         
00076         size_t getBitsCount() const
00077         {
00078             size_t count = 0;
00079             for(unsigned char *ptr = bits_ptr, *end_ptr = bits_ptr + bits.size(); ptr != end_ptr; ++ptr)
00080             {
00081                 const unsigned char b = *ptr;
00082                 count += bit_count[b & 0xF] + bit_count[b >> 4];
00083             }
00084             return count;
00085         }
00086         
00087     private:
00088         unsigned char*              bits_ptr;       // it`s so performance critical, so we place raw data pointer before all other members
00089         vector<unsigned char>::type bits;
00090         
00091         const static unsigned char  bit_mask[8];    // = { 1, 2, 4, 8, 16, 32, 64, 128 };
00092         const static unsigned char  bit_count[16];  // = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
00093     };
00094     
00108     class _OgreExport ProgressiveMesh : public ProgMeshAlloc
00109     {
00110     public:
00111         typedef vector<Real>::type LodValueList;
00112         
00114         enum VertexReductionQuota
00115         {
00117             VRQ_CONSTANT,
00119             VRQ_PROPORTIONAL,
00122             VRQ_ERROR_COST
00123         };
00124 
00125         
00151         static bool generateLodLevels(Mesh* pMesh, const LodValueList& lodValues,
00152                                       VertexReductionQuota reductionMethod, Real reductionValue);
00153 
00164         static MeshPtr generateSimplifiedMesh(const String& name, const String& groupName, Mesh* inMesh,
00165                                               bool dropOriginalGeometry, const LodValueList& lodValues,
00166                                               VertexReductionQuota reductionMethod, Real reductionValue,
00167                                               size_t* removedVertexDuplicatesCount);
00168     protected:
00169         typedef vector<ProgressiveMesh*>::type ProgressiveMeshList;
00170 
00172         static void initializeProgressiveMeshList(ProgressiveMeshList& pmList, Mesh* pMesh);
00173 
00175         static void freeProgressiveMeshList(ProgressiveMeshList* pmList);
00176 
00184         ProgressiveMesh(SubMesh* pSubMesh);
00185         virtual ~ProgressiveMesh();
00186 
00202         virtual void addExtraVertexPositionBuffer(const VertexData* vertexData);
00203 
00212         static bool build(ProgressiveMeshList& pmInList,
00213                           const LodStrategy *lodStrategy, const LodValueList& lodValues,
00214                           VertexReductionQuota quota, Real reductionValue = 0.5f);
00215                         
00216     protected:
00218         SubMesh* mSubMesh;
00219         
00220         VertexData *mVertexData;
00221         IndexData *mIndexData;
00222 
00223         vector<IndexData*>::type mLodFaceList;
00224         
00225         size_t mRemovedVertexDuplicatesCount;   
00226         size_t mCurrNumIndexes;
00227         float mInvSquaredBoundBoxDiagonal;
00228         int mVertexComponentFlags;  
00229 
00230         // Internal classes
00231         class PMTriangle;
00232         class PMVertex;
00233         struct vertexLess;
00234 
00235     public: // VC6 hack
00236 
00239         class _OgrePrivate PMFaceVertex {
00240         public:
00241             size_t realIndex;
00242             PMVertex* commonVertex;
00243         };
00244 
00245     protected:
00246 
00248         class _OgrePrivate PMTriangle {
00249         public:
00250             PMTriangle();
00251             void setDetails(size_t index, PMFaceVertex *v0, PMFaceVertex *v1, PMFaceVertex *v2);
00252             void computeNormal(void);
00253             void replaceVertex(PMFaceVertex *vold, PMFaceVertex *vnew);
00254             bool hasCommonVertex(PMVertex *v) const;
00255             bool hasFaceVertex(PMFaceVertex *v) const;
00256             PMFaceVertex* getFaceVertexFromCommon(PMVertex* commonVert);
00257             void notifyRemoved(void);
00258 
00259             PMFaceVertex*   vertex[3];  // the 3 points that make this tri
00260             Vector3         normal;     // unit vector orthogonal to this face
00261             Real            area;
00262             bool            removed;    // true if this tri is now removed
00263             size_t          index;
00264         };
00265 
00272         class _OgrePrivate PMVertex {
00273         public:
00274             enum BorderStatus { BS_UNKNOWN = 0, BS_NOT_BORDER, BS_BORDER };
00275             typedef SmallVector<PMVertex *, 8> NeighborList;
00276             typedef SmallVector<PMTriangle *, 8> FaceList;
00277 
00278         public:
00279             PMVertex() : mBorderStatus(BS_UNKNOWN), removed(false) {}
00280 
00281             void setDetails(size_t index, const Vector3& pos, const Vector3& normal, const Vector2& uv);
00282         
00283             bool isNearEnough(PMVertex* other) const;
00284             void removeIfNonNeighbor(PMVertex *n);
00285             void initBorderStatus(void);
00286             bool isManifoldEdgeWith(PMVertex* v); // is edge this->src a manifold edge?
00287             void notifyRemoved(void);
00288             void calculateNormal();
00289         
00290             Vector3 position;  // location of point in euclidean space
00291             Vector3 normal;
00292             Vector2 uv;
00293             
00294             size_t index;       // place of vertex in original list
00295 
00296             BorderStatus mBorderStatus;         
00297             bool      removed;   // true if this vert is now removed
00298             bool      toBeRemoved; // debug
00299 
00300             Real collapseCost;  // cached cost of collapsing edge
00301             PMVertex * collapseTo; // candidate vertex for collapse
00302             
00303             NeighborList neighbor; // adjacent vertices
00304             FaceList face;     // adjacent triangles
00305         };
00306         
00307         typedef vector<PMTriangle>::type TriangleList;
00308         typedef vector<PMFaceVertex>::type FaceVertexList;
00309         typedef vector<PMVertex>::type CommonVertexList;
00310         typedef std::pair<Real, unsigned int> CostIndexPair;
00311         typedef vector<CostIndexPair>::type WorstCostList;
00312 
00314         struct PMWorkingData
00315         {
00316             TriangleList mTriList; 
00317             FaceVertexList mFaceVertList; // The vertex details referenced by the triangles
00318             CommonVertexList mVertList; // The master list of common vertices
00319         };
00320 
00321         typedef vector<PMWorkingData>::type WorkingDataList;
00323         WorkingDataList mWorkingData;
00324 
00326         WorstCostList   mWorstCosts;        // sorted by cost, but some of entries are invalidated, so check invalidCostMask
00327         BitArray        mInvalidCostMask;   // indexed by vertex index
00328         size_t          mInvalidCostCount;
00329         size_t          mWorstCostsSize;
00330         size_t          mNextWorstCostHint; // getNextCollapser() uses it to reduce complexity from O(n^2) to O(n)
00331             
00333         mutable PMVertex::FaceList mEdgeAdjacentSides;
00334 
00336         void addWorkingData(const VertexData* vertexData, const IndexData* indexData);
00337         void mergeWorkingDataBorders();
00338         
00340         void initialiseEdgeCollapseCosts(void);
00342         Real computeEdgeCollapseCost(PMVertex *src, PMVertex *dest) const;
00344         bool collapseInvertsNormals(PMVertex *src, PMVertex *dest) const;
00346         Real computeEdgeCostAtVertexForBuffer(PMVertex* v);
00348         Real computeEdgeCostAtVertex(size_t vertIndex);
00350         void computeAllCosts(void);
00351 
00353         static size_t getInvalidCostCount(ProgressiveMesh::ProgressiveMeshList& pmList);
00354         static bool recomputeInvalidCosts(ProgressiveMeshList& pmInList);
00355         void recomputeInvalidCosts();
00356         void sortIndexesByCost();
00357         static int cmpByCost(const void* p1, const void* p2); // comparator for mWorstCosts sorting
00358         
00360         static void getNextCollapser(ProgressiveMeshList& pmList, ProgressiveMesh*& pm, CostIndexPair*& bestCollapser);
00361         CostIndexPair* getNextCollapser();
00362         
00364         void bakeNewLOD(IndexData* pData);
00366         static void bakeLodUsage(Mesh* pMesh, LodStrategy *lodStrategy, const LodValueList& lodValues, bool skipFirstLodLevel = false);
00367 
00374         void collapse(PMVertex *collapser);
00375 
00377         typedef std::pair<unsigned, PMVertex*> IndexVertexPair;
00379         static void bakeSimplifiedMesh(Mesh* destMesh, Mesh* srcMesh, ProgressiveMeshList& pmList, bool dropFirstLodLevel = false);
00381         static void createSimplifiedVertexData(vector<IndexVertexPair>::type& usedVertices, VertexData* inVData, VertexData*& outVData, AxisAlignedBox& aabox);
00383         static void createIndexMap(vector<IndexVertexPair>::type& usedVertices, unsigned allVertexCount, vector<unsigned>::type& indexMap);
00384         
00386         void dumpContents(const String& log);
00387     };
00388             
00389     template <typename T> struct HardwareBufferLockGuard
00390     {
00391         HardwareBufferLockGuard(const T& p, HardwareBuffer::LockOptions options)
00392         : pBuf(p)
00393         {
00394             pData = pBuf->lock(options);
00395         }
00396         HardwareBufferLockGuard(const T& p, size_t offset, size_t length, HardwareBuffer::LockOptions options)
00397         : pBuf(p)
00398         {
00399             pData = pBuf->lock(offset, length, options);
00400         }       
00401         ~HardwareBufferLockGuard()
00402         {
00403             pBuf->unlock();
00404         }
00405         const T& pBuf;
00406         void* pData;
00407     };
00408     
00409     typedef HardwareBufferLockGuard<HardwareVertexBufferSharedPtr> VertexBufferLockGuard;
00410     typedef HardwareBufferLockGuard<HardwareIndexBufferSharedPtr> IndexBufferLockGuard;
00411     
00414 }
00415 
00416 #endif 

Copyright © 2012 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012