Planeshift
|
00001 // 00002 // Copyright (c) 2009-2010 Mikko Mononen [email protected] 00003 // 00004 // This software is provided 'as-is', without any express or implied 00005 // warranty. In no event will the authors be held liable for any damages 00006 // arising from the use of this software. 00007 // Permission is granted to anyone to use this software for any purpose, 00008 // including commercial applications, and to alter it and redistribute it 00009 // freely, subject to the following restrictions: 00010 // 1. The origin of this software must not be misrepresented; you must not 00011 // claim that you wrote the original software. If you use this software 00012 // in a product, an acknowledgment in the product documentation would be 00013 // appreciated but is not required. 00014 // 2. Altered source versions must be plainly marked as such, and must not be 00015 // misrepresented as being the original software. 00016 // 3. This notice may not be removed or altered from any source distribution. 00017 // 00018 00019 #ifndef RECAST_H 00020 #define RECAST_H 00021 00023 static const float RC_PI = 3.14159265f; 00024 00027 enum rcLogCategory 00028 { 00029 RC_LOG_PROGRESS = 1, 00030 RC_LOG_WARNING, 00031 RC_LOG_ERROR, 00032 }; 00033 00036 enum rcTimerLabel 00037 { 00039 RC_TIMER_TOTAL, 00041 RC_TIMER_TEMP, 00043 RC_TIMER_RASTERIZE_TRIANGLES, 00045 RC_TIMER_BUILD_COMPACTHEIGHTFIELD, 00047 RC_TIMER_BUILD_CONTOURS, 00049 RC_TIMER_BUILD_CONTOURS_TRACE, 00051 RC_TIMER_BUILD_CONTOURS_SIMPLIFY, 00053 RC_TIMER_FILTER_BORDER, 00055 RC_TIMER_FILTER_WALKABLE, 00057 RC_TIMER_MEDIAN_AREA, 00059 RC_TIMER_FILTER_LOW_OBSTACLES, 00061 RC_TIMER_BUILD_POLYMESH, 00063 RC_TIMER_MERGE_POLYMESH, 00065 RC_TIMER_ERODE_AREA, 00067 RC_TIMER_MARK_BOX_AREA, 00069 RC_TIMER_MARK_CYLINDER_AREA, 00071 RC_TIMER_MARK_CONVEXPOLY_AREA, 00073 RC_TIMER_BUILD_DISTANCEFIELD, 00075 RC_TIMER_BUILD_DISTANCEFIELD_DIST, 00077 RC_TIMER_BUILD_DISTANCEFIELD_BLUR, 00079 RC_TIMER_BUILD_REGIONS, 00081 RC_TIMER_BUILD_REGIONS_WATERSHED, 00083 RC_TIMER_BUILD_REGIONS_EXPAND, 00085 RC_TIMER_BUILD_REGIONS_FLOOD, 00087 RC_TIMER_BUILD_REGIONS_FILTER, 00089 RC_TIMER_BUILD_LAYERS, 00091 RC_TIMER_BUILD_POLYMESHDETAIL, 00093 RC_TIMER_MERGE_POLYMESHDETAIL, 00095 RC_MAX_TIMERS 00096 }; 00097 00101 class rcContext 00102 { 00103 public: 00104 00107 inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {} 00108 virtual ~rcContext() {} 00109 00112 inline void enableLog(bool state) { m_logEnabled = state; } 00113 00115 inline void resetLog() { if (m_logEnabled) doResetLog(); } 00116 00120 void log(const rcLogCategory category, const char* format, ...); 00121 00124 inline void enableTimer(bool state) { m_timerEnabled = state; } 00125 00127 inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } 00128 00131 inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } 00132 00135 inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); } 00136 00140 inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; } 00141 00142 protected: 00143 00145 virtual void doResetLog() {} 00146 00151 virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {} 00152 00154 virtual void doResetTimers() {} 00155 00158 virtual void doStartTimer(const rcTimerLabel /*label*/) {} 00159 00162 virtual void doStopTimer(const rcTimerLabel /*label*/) {} 00163 00167 virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } 00168 00170 bool m_logEnabled; 00171 00173 bool m_timerEnabled; 00174 }; 00175 00178 struct rcConfig 00179 { 00181 int width; 00182 00184 int height; 00185 00187 int tileSize; 00188 00190 int borderSize; 00191 00193 float cs; 00194 00196 float ch; 00197 00199 float bmin[3]; 00200 00202 float bmax[3]; 00203 00205 float walkableSlopeAngle; 00206 00209 int walkableHeight; 00210 00212 int walkableClimb; 00213 00216 int walkableRadius; 00217 00219 int maxEdgeLen; 00220 00223 float maxSimplificationError; 00224 00226 int minRegionArea; 00227 00230 int mergeRegionArea; 00231 00234 int maxVertsPerPoly; 00235 00238 float detailSampleDist; 00239 00242 float detailSampleMaxError; 00243 }; 00244 00246 static const int RC_SPAN_HEIGHT_BITS = 13; 00248 static const int RC_SPAN_MAX_HEIGHT = (1<<RC_SPAN_HEIGHT_BITS)-1; 00249 00252 static const int RC_SPANS_PER_POOL = 2048; 00253 00256 struct rcSpan 00257 { 00258 unsigned int smin : 13; 00259 unsigned int smax : 13; 00260 unsigned int area : 6; 00261 rcSpan* next; 00262 }; 00263 00266 struct rcSpanPool 00267 { 00268 rcSpanPool* next; 00269 rcSpan items[RC_SPANS_PER_POOL]; 00270 }; 00271 00274 struct rcHeightfield 00275 { 00276 int width; 00277 int height; 00278 float bmin[3]; 00279 float bmax[3]; 00280 float cs; 00281 float ch; 00282 rcSpan** spans; 00283 rcSpanPool* pools; 00284 rcSpan* freelist; 00285 }; 00286 00288 struct rcCompactCell 00289 { 00290 unsigned int index : 24; 00291 unsigned int count : 8; 00292 }; 00293 00295 struct rcCompactSpan 00296 { 00297 unsigned short y; 00298 unsigned short reg; 00299 unsigned int con : 24; 00300 unsigned int h : 8; 00301 }; 00302 00305 struct rcCompactHeightfield 00306 { 00307 int width; 00308 int height; 00309 int spanCount; 00310 int walkableHeight; 00311 int walkableClimb; 00312 int borderSize; 00313 unsigned short maxDistance; 00314 unsigned short maxRegions; 00315 float bmin[3]; 00316 float bmax[3]; 00317 float cs; 00318 float ch; 00319 rcCompactCell* cells; 00320 rcCompactSpan* spans; 00321 unsigned short* dist; 00322 unsigned char* areas; 00323 }; 00324 00327 struct rcHeightfieldLayer 00328 { 00329 float bmin[3]; 00330 float bmax[3]; 00331 float cs; 00332 float ch; 00333 int width; 00334 int height; 00335 int minx; 00336 int maxx; 00337 int miny; 00338 int maxy; 00339 int hmin; 00340 int hmax; 00341 unsigned char* heights; 00342 unsigned char* areas; 00343 unsigned char* cons; 00344 }; 00345 00349 struct rcHeightfieldLayerSet 00350 { 00351 rcHeightfieldLayer* layers; 00352 int nlayers; 00353 }; 00354 00356 struct rcContour 00357 { 00358 int* verts; 00359 int nverts; 00360 int* rverts; 00361 int nrverts; 00362 unsigned short reg; 00363 unsigned char area; 00364 }; 00365 00368 struct rcContourSet 00369 { 00370 rcContour* conts; 00371 int nconts; 00372 float bmin[3]; 00373 float bmax[3]; 00374 float cs; 00375 float ch; 00376 int width; 00377 int height; 00378 int borderSize; 00379 }; 00380 00383 struct rcPolyMesh 00384 { 00385 unsigned short* verts; 00386 unsigned short* polys; 00387 unsigned short* regs; 00388 unsigned short* flags; 00389 unsigned char* areas; 00390 int nverts; 00391 int npolys; 00392 int maxpolys; 00393 int nvp; 00394 float bmin[3]; 00395 float bmax[3]; 00396 float cs; 00397 float ch; 00398 int borderSize; 00399 }; 00400 00404 struct rcPolyMeshDetail 00405 { 00406 unsigned int* meshes; 00407 float* verts; 00408 unsigned char* tris; 00409 int nmeshes; 00410 int nverts; 00411 int ntris; 00412 }; 00413 00418 00423 rcHeightfield* rcAllocHeightfield(); 00424 00429 void rcFreeHeightField(rcHeightfield* hf); 00430 00435 rcCompactHeightfield* rcAllocCompactHeightfield(); 00436 00441 void rcFreeCompactHeightfield(rcCompactHeightfield* chf); 00442 00447 rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet(); 00448 00453 void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset); 00454 00459 rcContourSet* rcAllocContourSet(); 00460 00465 void rcFreeContourSet(rcContourSet* cset); 00466 00471 rcPolyMesh* rcAllocPolyMesh(); 00472 00477 void rcFreePolyMesh(rcPolyMesh* pmesh); 00478 00483 rcPolyMeshDetail* rcAllocPolyMeshDetail(); 00484 00489 void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); 00490 00492 00498 static const unsigned short RC_BORDER_REG = 0x8000; 00499 00507 static const int RC_BORDER_VERTEX = 0x10000; 00508 00514 static const int RC_AREA_BORDER = 0x20000; 00515 00518 enum rcBuildContoursFlags 00519 { 00520 RC_CONTOUR_TESS_WALL_EDGES = 0x01, 00521 RC_CONTOUR_TESS_AREA_EDGES = 0x02, 00522 }; 00523 00528 static const int RC_CONTOUR_REG_MASK = 0xffff; 00529 00533 static const unsigned short RC_MESH_NULL_IDX = 0xffff; 00534 00538 static const unsigned char RC_NULL_AREA = 0; 00539 00543 static const unsigned char RC_WALKABLE_AREA = 63; 00544 00547 static const int RC_NOT_CONNECTED = 0x3f; 00548 00551 00555 template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; } 00556 00561 template<class T> inline T rcMin(T a, T b) { return a < b ? a : b; } 00562 00567 template<class T> inline T rcMax(T a, T b) { return a > b ? a : b; } 00568 00572 template<class T> inline T rcAbs(T a) { return a < 0 ? -a : a; } 00573 00577 template<class T> inline T rcSqr(T a) { return a*a; } 00578 00584 template<class T> inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } 00585 00589 float rcSqrt(float x); 00590 00594 00599 inline void rcVcross(float* dest, const float* v1, const float* v2) 00600 { 00601 dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; 00602 dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; 00603 dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; 00604 } 00605 00610 inline float rcVdot(const float* v1, const float* v2) 00611 { 00612 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; 00613 } 00614 00620 inline void rcVmad(float* dest, const float* v1, const float* v2, const float s) 00621 { 00622 dest[0] = v1[0]+v2[0]*s; 00623 dest[1] = v1[1]+v2[1]*s; 00624 dest[2] = v1[2]+v2[2]*s; 00625 } 00626 00631 inline void rcVadd(float* dest, const float* v1, const float* v2) 00632 { 00633 dest[0] = v1[0]+v2[0]; 00634 dest[1] = v1[1]+v2[1]; 00635 dest[2] = v1[2]+v2[2]; 00636 } 00637 00642 inline void rcVsub(float* dest, const float* v1, const float* v2) 00643 { 00644 dest[0] = v1[0]-v2[0]; 00645 dest[1] = v1[1]-v2[1]; 00646 dest[2] = v1[2]-v2[2]; 00647 } 00648 00652 inline void rcVmin(float* mn, const float* v) 00653 { 00654 mn[0] = rcMin(mn[0], v[0]); 00655 mn[1] = rcMin(mn[1], v[1]); 00656 mn[2] = rcMin(mn[2], v[2]); 00657 } 00658 00662 inline void rcVmax(float* mx, const float* v) 00663 { 00664 mx[0] = rcMax(mx[0], v[0]); 00665 mx[1] = rcMax(mx[1], v[1]); 00666 mx[2] = rcMax(mx[2], v[2]); 00667 } 00668 00672 inline void rcVcopy(float* dest, const float* v) 00673 { 00674 dest[0] = v[0]; 00675 dest[1] = v[1]; 00676 dest[2] = v[2]; 00677 } 00678 00683 inline float rcVdist(const float* v1, const float* v2) 00684 { 00685 float dx = v2[0] - v1[0]; 00686 float dy = v2[1] - v1[1]; 00687 float dz = v2[2] - v1[2]; 00688 return rcSqrt(dx*dx + dy*dy + dz*dz); 00689 } 00690 00695 inline float rcVdistSqr(const float* v1, const float* v2) 00696 { 00697 float dx = v2[0] - v1[0]; 00698 float dy = v2[1] - v1[1]; 00699 float dz = v2[2] - v1[2]; 00700 return dx*dx + dy*dy + dz*dz; 00701 } 00702 00705 inline void rcVnormalize(float* v) 00706 { 00707 float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2])); 00708 v[0] *= d; 00709 v[1] *= d; 00710 v[2] *= d; 00711 } 00712 00717 00724 void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax); 00725 00733 void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h); 00734 00745 bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, 00746 const float* bmin, const float* bmax, 00747 float cs, float ch); 00748 00760 void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, 00761 const int* tris, int nt, unsigned char* areas); 00762 00773 void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, 00774 const int* tris, int nt, unsigned char* areas); 00775 00788 void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y, 00789 const unsigned short smin, const unsigned short smax, 00790 const unsigned char area, const int flagMergeThr); 00791 00802 void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, 00803 const unsigned char area, rcHeightfield& solid, 00804 const int flagMergeThr = 1); 00805 00817 void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, 00818 const int* tris, const unsigned char* areas, const int nt, 00819 rcHeightfield& solid, const int flagMergeThr = 1); 00820 00832 void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, 00833 const unsigned short* tris, const unsigned char* areas, const int nt, 00834 rcHeightfield& solid, const int flagMergeThr = 1); 00835 00845 void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, 00846 rcHeightfield& solid, const int flagMergeThr = 1); 00847 00854 void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); 00855 00864 void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, 00865 const int walkableClimb, rcHeightfield& solid); 00866 00873 void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); 00874 00880 int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); 00881 00886 00897 bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, 00898 rcHeightfield& hf, rcCompactHeightfield& chf); 00899 00906 bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); 00907 00913 bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); 00914 00922 void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, 00923 rcCompactHeightfield& chf); 00924 00934 void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, 00935 const float hmin, const float hmax, unsigned char areaId, 00936 rcCompactHeightfield& chf); 00937 00945 int rcOffsetPoly(const float* verts, const int nverts, const float offset, 00946 float* outVerts, const int maxOutVerts); 00947 00956 void rcMarkCylinderArea(rcContext* ctx, const float* pos, 00957 const float r, const float h, unsigned char areaId, 00958 rcCompactHeightfield& chf); 00959 00965 bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); 00966 00978 bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, 00979 const int borderSize, const int minRegionArea, const int mergeRegionArea); 00980 00992 bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, 00993 const int borderSize, const int minRegionArea, const int mergeRegionArea); 00994 00995 01000 inline void rcSetCon(rcCompactSpan& s, int dir, int i) 01001 { 01002 const unsigned int shift = (unsigned int)dir*6; 01003 unsigned int con = s.con; 01004 s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift); 01005 } 01006 01012 inline int rcGetCon(const rcCompactSpan& s, int dir) 01013 { 01014 const unsigned int shift = (unsigned int)dir*6; 01015 return (s.con >> shift) & 0x3f; 01016 } 01017 01022 inline int rcGetDirOffsetX(int dir) 01023 { 01024 const int offset[4] = { -1, 0, 1, 0, }; 01025 return offset[dir&0x03]; 01026 } 01027 01032 inline int rcGetDirOffsetY(int dir) 01033 { 01034 const int offset[4] = { 0, 1, 0, -1 }; 01035 return offset[dir&0x03]; 01036 } 01037 01042 01053 bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, 01054 const int borderSize, const int walkableHeight, 01055 rcHeightfieldLayerSet& lset); 01056 01068 bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, 01069 const float maxError, const int maxEdgeLen, 01070 rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); 01071 01080 bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh); 01081 01089 bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); 01090 01101 bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, 01102 const float sampleDist, const float sampleMaxError, 01103 rcPolyMeshDetail& dmesh); 01104 01111 bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst); 01112 01120 bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); 01121 01123 01124 #endif // RECAST_H 01125 01127 01128 // Due to the large amount of detail documentation for this file, 01129 // the content normally located at the end of the header file has been separated 01130 // out to a file in /Docs/Extern.