DetourTileNavMeshBuilder.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //
  2. // Copyright (c) 2009 Mikko Mononen memon@inside.org
  3. //
  4. // This software is provided 'as-is', without any express or implied
  5. // warranty. In no event will the authors be held liable for any damages
  6. // arising from the use of this software.
  7. // Permission is granted to anyone to use this software for any purpose,
  8. // including commercial applications, and to alter it and redistribute it
  9. // freely, subject to the following restrictions:
  10. // 1. The origin of this software must not be misrepresented; you must not
  11. // claim that you wrote the original software. If you use this software
  12. // in a product, an acknowledgment in the product documentation would be
  13. // appreciated but is not required.
  14. // 2. Altered source versions must be plainly marked as such, and must not be
  15. // misrepresented as being the original software.
  16. // 3. This notice may not be removed or altered from any source distribution.
  17. //
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "DetourTileNavMesh.h"
  23. #include "DetourCommon.h"
  24. bool dtCreateNavMeshTileData(const unsigned short* verts, const int nverts,
  25. const unsigned short* polys, const int npolys, const int nvp,
  26. const unsigned short* dmeshes, const float* dverts, const int ndverts,
  27. const unsigned char* dtris, const int ndtris,
  28. const float* bmin, const float* bmax, float cs, float ch, int tileSize, int walkableClimb,
  29. unsigned char** outData, int* outDataSize)
  30. {
  31. if (nvp != DT_TILE_VERTS_PER_POLYGON)
  32. return false;
  33. if (nverts >= 0xffff)
  34. return false;
  35. if (!nverts)
  36. return false;
  37. if (!npolys)
  38. return false;
  39. if (!dmeshes || !dverts || ! dtris)
  40. return false;
  41. // Find portal edges which are at tile borders.
  42. int nedges = 0;
  43. int nportals = 0;
  44. for (int i = 0; i < npolys; ++i)
  45. {
  46. const unsigned short* p = &polys[i*2*nvp];
  47. for (int j = 0; j < nvp; ++j)
  48. {
  49. if (p[j] == 0xffff) break;
  50. int nj = j+1;
  51. if (nj >= nvp || p[nj] == 0xffff) nj = 0;
  52. const unsigned short* va = &verts[p[j]*3];
  53. const unsigned short* vb = &verts[p[nj]*3];
  54. nedges++;
  55. if (va[0] == tileSize && vb[0] == tileSize)
  56. nportals++; // x+
  57. else if (va[2] == tileSize && vb[2] == tileSize)
  58. nportals++; // z+
  59. else if (va[0] == 0 && vb[0] == 0)
  60. nportals++; // x-
  61. else if (va[2] == 0 && vb[2] == 0)
  62. nportals++; // z-
  63. }
  64. }
  65. const int maxLinks = nedges + nportals*2;
  66. // Find unique detail vertices.
  67. int uniqueDetailVerts = 0;
  68. if (dmeshes)
  69. {
  70. for (int i = 0; i < npolys; ++i)
  71. {
  72. const unsigned short* p = &polys[i*nvp*2];
  73. int ndv = dmeshes[i*4+1];
  74. int nv = 0;
  75. for (int j = 0; j < nvp; ++j)
  76. {
  77. if (p[j] == 0xffff) break;
  78. nv++;
  79. }
  80. ndv -= nv;
  81. uniqueDetailVerts += ndv;
  82. }
  83. }
  84. // Calculate data size
  85. const int headerSize = sizeof(dtTileHeader);
  86. const int vertsSize = sizeof(float)*3*nverts;
  87. const int polysSize = sizeof(dtTilePoly)*npolys;
  88. const int linksSize = sizeof(dtTileLink)*maxLinks;
  89. const int detailMeshesSize = sizeof(dtTilePolyDetail)*npolys;
  90. const int detailVertsSize = sizeof(float)*3*uniqueDetailVerts;
  91. const int detailTrisSize = sizeof(unsigned char)*4*ndtris;
  92. const int dataSize = headerSize + vertsSize + polysSize + linksSize +
  93. detailMeshesSize + detailVertsSize + detailTrisSize;
  94. unsigned char* data = new unsigned char[dataSize];
  95. if (!data)
  96. return false;
  97. memset(data, 0, dataSize);
  98. unsigned char* d = data;
  99. dtTileHeader* header = (dtTileHeader*)d; d += headerSize;
  100. float* navVerts = (float*)d; d += vertsSize;
  101. dtTilePoly* navPolys = (dtTilePoly*)d; d += polysSize;
  102. d += linksSize;
  103. dtTilePolyDetail* navDMeshes = (dtTilePolyDetail*)d; d += detailMeshesSize;
  104. float* navDVerts = (float*)d; d += detailVertsSize;
  105. unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize;
  106. // Store header
  107. header->magic = DT_TILE_NAVMESH_MAGIC;
  108. header->version = DT_TILE_NAVMESH_VERSION;
  109. header->npolys = npolys;
  110. header->nverts = nverts;
  111. header->maxlinks = maxLinks;
  112. header->bmin[0] = bmin[0];
  113. header->bmin[1] = bmin[1];
  114. header->bmin[2] = bmin[2];
  115. header->bmax[0] = bmax[0];
  116. header->bmax[1] = bmax[1];
  117. header->bmax[2] = bmax[2];
  118. header->ndmeshes = npolys;
  119. header->ndverts = uniqueDetailVerts;
  120. header->ndtris = ndtris;
  121. // Store vertices
  122. for (int i = 0; i < nverts; ++i)
  123. {
  124. const unsigned short* iv = &verts[i*3];
  125. float* v = &navVerts[i*3];
  126. v[0] = bmin[0] + iv[0] * cs;
  127. v[1] = bmin[1] + iv[1] * ch;
  128. v[2] = bmin[2] + iv[2] * cs;
  129. }
  130. // Store polygons
  131. const unsigned short* src = polys;
  132. for (int i = 0; i < npolys; ++i)
  133. {
  134. dtTilePoly* p = &navPolys[i];
  135. p->nv = 0;
  136. for (int j = 0; j < nvp; ++j)
  137. {
  138. if (src[j] == 0xffff) break;
  139. p->v[j] = src[j];
  140. p->n[j] = (src[nvp+j]+1) & 0xffff;
  141. p->nv++;
  142. }
  143. src += nvp*2;
  144. }
  145. // Store portal edges.
  146. for (int i = 0; i < npolys; ++i)
  147. {
  148. dtTilePoly* poly = &navPolys[i];
  149. for (int j = 0; j < poly->nv; ++j)
  150. {
  151. int nj = j+1;
  152. if (nj >= poly->nv) nj = 0;
  153. const unsigned short* va = &verts[poly->v[j]*3];
  154. const unsigned short* vb = &verts[poly->v[nj]*3];
  155. if (va[0] == tileSize && vb[0] == tileSize) // x+
  156. poly->n[j] = 0x8000 | 0;
  157. else if (va[2] == tileSize && vb[2] == tileSize) // z+
  158. poly->n[j] = 0x8000 | 1;
  159. else if (va[0] == 0 && vb[0] == 0) // x-
  160. poly->n[j] = 0x8000 | 2;
  161. else if (va[2] == 0 && vb[2] == 0) // z-
  162. poly->n[j] = 0x8000 | 3;
  163. }
  164. }
  165. // Store detail meshes and vertices.
  166. // The nav polygon vertices are stored as the first vertices on each mesh.
  167. // We compress the mesh data by skipping them and using the navmesh coordinates.
  168. unsigned short vbase = 0;
  169. for (int i = 0; i < npolys; ++i)
  170. {
  171. dtTilePolyDetail& dtl = navDMeshes[i];
  172. const int vb = dmeshes[i*4+0];
  173. const int ndv = dmeshes[i*4+1];
  174. const int nv = navPolys[i].nv;
  175. dtl.vbase = vbase;
  176. dtl.nverts = ndv-nv;
  177. dtl.tbase = dmeshes[i*4+2];
  178. dtl.ntris = dmeshes[i*4+3];
  179. // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
  180. if (ndv-nv)
  181. {
  182. memcpy(&navDVerts[vbase*3], &dverts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
  183. vbase += ndv-nv;
  184. }
  185. }
  186. // Store triangles.
  187. memcpy(navDTris, dtris, sizeof(unsigned char)*4*ndtris);
  188. *outData = data;
  189. *outDataSize = dataSize;
  190. return true;
  191. }