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]) != 0; }
    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         Real 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
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sun Sep 2 2012 07:27:22