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
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012