9
3

map.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. #include "map.h"
  2. #include "raycast_mesh.h"
  3. #include "../../common/Log.h"
  4. #ifdef WIN32
  5. #include <WinSock2.h>
  6. #include <windows.h>
  7. #endif
  8. #include <algorithm>
  9. #include <map>
  10. #include <memory>
  11. #include <tuple>
  12. #include <vector>
  13. #include <fstream>
  14. struct Map::impl
  15. {
  16. RaycastMesh *rm;
  17. };
  18. ThreadReturnType LoadMapAsync(void* mapToLoad)
  19. {
  20. Map* map = (Map*)mapToLoad;
  21. map->SetMapLoaded(false);
  22. std::string filename = "Maps/";
  23. filename += map->GetFileName();
  24. filename += ".EQ2Map";
  25. if (map->Load(filename))
  26. map->SetMapLoaded(true);
  27. map->SetMapLoading(false);
  28. THREAD_RETURN(NULL);
  29. }
  30. Map::Map(string file, SPGrid* grid) {
  31. CheckMapMutex.SetName(file + "MapMutex");
  32. SetMapLoaded(false);
  33. m_ZoneFile = file;
  34. imp = nullptr;
  35. mGrid = grid;
  36. m_CellSize = CELLSIZEDEFAULT;
  37. }
  38. Map::~Map() {
  39. SetMapLoaded(false);
  40. if(imp) {
  41. imp->rm->release();
  42. safe_delete(imp);
  43. }
  44. }
  45. float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result)
  46. {
  47. if (!IsMapLoaded())
  48. return BEST_Z_INVALID;
  49. if (!imp)
  50. return BEST_Z_INVALID;
  51. glm::vec3 tmp;
  52. if(!result)
  53. result = &tmp;
  54. start.z += 1.0f;//RuleI(Map, FindBestZHeightAdjust);
  55. glm::vec3 from(start.x, start.y, start.z);
  56. glm::vec3 to(start.x, start.y, BEST_Z_INVALID);
  57. float hit_distance;
  58. bool hit = false;
  59. hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
  60. if(hit) {
  61. return result->z;
  62. }
  63. // Find nearest Z above us
  64. to.z = -BEST_Z_INVALID;
  65. hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
  66. if (hit)
  67. {
  68. return result->z;
  69. }
  70. return BEST_Z_INVALID;
  71. }
  72. float Map::FindClosestZ(glm::vec3 &start, glm::vec3 *result) {
  73. if (!IsMapLoaded())
  74. return false;
  75. // Unlike FindBestZ, this method finds the closest Z value above or below the specified point.
  76. //
  77. if (!imp)
  78. return false;
  79. float ClosestZ = BEST_Z_INVALID;
  80. glm::vec3 tmp;
  81. if (!result)
  82. result = &tmp;
  83. glm::vec3 from(start.x, start.y, start.z);
  84. glm::vec3 to(start.x, start.y, BEST_Z_INVALID);
  85. float hit_distance;
  86. bool hit = false;
  87. // first check is below us
  88. hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
  89. if (hit) {
  90. ClosestZ = result->z;
  91. }
  92. // Find nearest Z above us
  93. to.z = -BEST_Z_INVALID;
  94. hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
  95. if (hit) {
  96. if (std::abs(from.z - result->z) < std::abs(ClosestZ - from.z))
  97. return result->z;
  98. }
  99. return ClosestZ;
  100. }
  101. bool Map::LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) {
  102. if (!IsMapLoaded())
  103. return false;
  104. if(!imp)
  105. return false;
  106. return imp->rm->raycast((const RmReal*)&start, (const RmReal*)&end, (RmReal*)result, nullptr, nullptr);
  107. }
  108. bool Map::LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) {
  109. if (!IsMapLoaded())
  110. return false;
  111. if (!imp)
  112. return false;
  113. float z = BEST_Z_INVALID;
  114. glm::vec3 step;
  115. glm::vec3 cur;
  116. cur.x = start.x;
  117. cur.y = start.y;
  118. cur.z = start.z;
  119. step.x = end.x - start.x;
  120. step.y = end.y - start.y;
  121. step.z = end.z - start.z;
  122. float factor = step_mag / sqrt(step.x*step.x + step.y*step.y + step.z*step.z);
  123. step.x *= factor;
  124. step.y *= factor;
  125. step.z *= factor;
  126. int steps = 0;
  127. if (step.x > 0 && step.x < 0.001f)
  128. step.x = 0.001f;
  129. if (step.y > 0 && step.y < 0.001f)
  130. step.y = 0.001f;
  131. if (step.z > 0 && step.z < 0.001f)
  132. step.z = 0.001f;
  133. if (step.x < 0 && step.x > -0.001f)
  134. step.x = -0.001f;
  135. if (step.y < 0 && step.y > -0.001f)
  136. step.y = -0.001f;
  137. if (step.z < 0 && step.z > -0.001f)
  138. step.z = -0.001f;
  139. //while we are not past end
  140. //always do this once, even if start == end.
  141. while(cur.x != end.x || cur.y != end.y || cur.z != end.z)
  142. {
  143. steps++;
  144. glm::vec3 me;
  145. me.x = cur.x;
  146. me.y = cur.y;
  147. me.z = cur.z;
  148. glm::vec3 hit;
  149. float best_z = FindBestZ(me, &hit);
  150. float diff = best_z - z;
  151. diff = diff < 0 ? -diff : diff;
  152. if (z <= BEST_Z_INVALID || best_z <= BEST_Z_INVALID || diff < 12.0)
  153. z = best_z;
  154. else
  155. return true;
  156. //look at current location
  157. if(LineIntersectsZone(start, end, step_mag, result))
  158. {
  159. return true;
  160. }
  161. //move 1 step
  162. if (cur.x != end.x)
  163. cur.x += step.x;
  164. if (cur.y != end.y)
  165. cur.y += step.y;
  166. if (cur.z != end.z)
  167. cur.z += step.z;
  168. //watch for end conditions
  169. if ( (cur.x > end.x && end.x >= start.x) || (cur.x < end.x && end.x <= start.x) || (step.x == 0) ) {
  170. cur.x = end.x;
  171. }
  172. if ( (cur.y > end.y && end.y >= start.y) || (cur.y < end.y && end.y <= start.y) || (step.y == 0) ) {
  173. cur.y = end.y;
  174. }
  175. if ( (cur.z > end.z && end.z >= start.z) || (cur.z < end.z && end.z < start.z) || (step.z == 0) ) {
  176. cur.z = end.z;
  177. }
  178. }
  179. //walked entire line and didnt run into anything...
  180. return false;
  181. }
  182. bool Map::CheckLoS(glm::vec3 myloc, glm::vec3 oloc)
  183. {
  184. if (!IsMapLoaded())
  185. return false;
  186. if(!imp)
  187. return false;
  188. return !imp->rm->raycast((const RmReal*)&myloc, (const RmReal*)&oloc, nullptr, nullptr, nullptr);
  189. }
  190. // returns true if a collision happens
  191. bool Map::DoCollisionCheck(glm::vec3 myloc, glm::vec3 oloc, glm::vec3 &outnorm, float &distance) {
  192. if (!IsMapLoaded())
  193. return false;
  194. if(!imp)
  195. return false;
  196. return imp->rm->raycast((const RmReal*)&myloc, (const RmReal*)&oloc, nullptr, (RmReal *)&outnorm, (RmReal *)&distance);
  197. }
  198. inline bool file_exists(const std::string& name) {
  199. std::ifstream f(name.c_str());
  200. return f.good();
  201. }
  202. Map *Map::LoadMapFile(std::string file, SPGrid* grid) {
  203. std::string filename = "Maps/";
  204. filename += file;
  205. filename += ".EQ2Map";
  206. LogWrite(MAP__INFO, 7, "Map", "Attempting to load Map File [{%s}]", filename.c_str());
  207. auto m = new Map(file, grid);
  208. m->SetMapLoading(true);
  209. #ifdef WIN32
  210. _beginthread(LoadMapAsync, 0, (void*)m);
  211. #else
  212. pthread_t t1;
  213. pthread_create(&t1, NULL, LoadMapAsync, (void*)m);
  214. pthread_detach(t1);
  215. #endif
  216. return m;
  217. }
  218. /**
  219. * @param filename
  220. * @return
  221. */
  222. bool Map::Load(const std::string &filename)
  223. {
  224. FILE *map_file = fopen(filename.c_str(), "rb");
  225. if (map_file) {
  226. LogWrite(MAP__INFO, 7, "Map", "Loading Map File [{%s}]", filename.c_str());
  227. bool loaded_map_file = LoadV2(map_file);
  228. fclose(map_file);
  229. if (loaded_map_file) {
  230. LogWrite(MAP__INFO, 7, "Map", "Loaded Map File [{%s}]", filename.c_str());
  231. }
  232. else {
  233. LogWrite(MAP__ERROR, 7, "Map", "FAILED Loading Map File [{%s}]", filename.c_str());
  234. }
  235. return loaded_map_file;
  236. }
  237. else {
  238. return false;
  239. }
  240. return false;
  241. }
  242. struct ModelEntry
  243. {
  244. struct Poly
  245. {
  246. uint32 v1, v2, v3;
  247. uint8 vis;
  248. };
  249. std::vector<glm::vec3> verts;
  250. std::vector<Poly> polys;
  251. };
  252. bool Map::LoadV2(FILE* f) {
  253. // Read the string for the zone file name this was created for
  254. int8 strSize;
  255. char name[256];
  256. fread(&strSize, sizeof(int8), 1, f);
  257. LogWrite(MAP__DEBUG, 0, "Map", "strSize = %u", strSize);
  258. size_t len = fread(&name, sizeof(char), strSize, f);
  259. name[len] = '\0';
  260. LogWrite(MAP__DEBUG, 0, "Map", "name = %s", name);
  261. string fileName(name);
  262. std::size_t found = fileName.find(m_ZoneFile);
  263. // Make sure file contents are for the correct zone
  264. if (found == std::string::npos) {
  265. fclose(f);
  266. LogWrite(MAP__ERROR, 0, "Map", "Map::LoadV2() map contents (%s) do not match its name (%s).", &name, m_ZoneFile.c_str());
  267. return false;
  268. }
  269. // Read the min bounds
  270. fread(&m_MinX, sizeof(float), 1, f);
  271. fread(&m_MinZ, sizeof(float), 1, f);
  272. // Read the max bounds
  273. fread(&m_MaxX, sizeof(float), 1, f);
  274. fread(&m_MaxZ, sizeof(float), 1, f);
  275. // Calculate how many cells we need
  276. // in both the X and Z direction
  277. float width = m_MaxX - m_MinX;
  278. float height = m_MaxZ - m_MinZ;
  279. m_NumCellsX = ceil(width / m_CellSize);
  280. m_NumCellsZ = ceil(height / m_CellSize);
  281. if (mGrid != nullptr)
  282. mGrid->InitValues(m_MinX, m_MaxX, m_MinZ, m_MaxZ, m_NumCellsX, m_NumCellsZ);
  283. // Read the number of grids
  284. int32 NumGrids;
  285. fread(&NumGrids, sizeof(int32), 1, f);
  286. std::vector<glm::vec3> verts;
  287. std::vector<uint32> indices;
  288. uint32 face_count = 0;
  289. // Loop through the grids loading the face list
  290. for (int32 i = 0; i < NumGrids; i++) {
  291. // Read the grid id
  292. int32 GridID;
  293. fread(&GridID, sizeof(int32), 1, f);
  294. // Read the number of vertices
  295. int32 NumFaces;
  296. fread(&NumFaces, sizeof(int32), 1, f);
  297. face_count += NumFaces;
  298. // Loop through the vertices list reading
  299. // 3 at a time to creat a triangle (face)
  300. for (int32 y = 0; y < NumFaces; ) {
  301. // Each vertex need an x,y,z coordinate and
  302. // we will be reading 3 to create the face
  303. float x1, x2, x3;
  304. float y1, y2, y3;
  305. float z1, z2, z3;
  306. // Read the first vertex
  307. fread(&x1, sizeof(float), 1, f);
  308. fread(&y1, sizeof(float), 1, f);
  309. fread(&z1, sizeof(float), 1, f);
  310. y++;
  311. // Read the second vertex
  312. fread(&x2, sizeof(float), 1, f);
  313. fread(&y2, sizeof(float), 1, f);
  314. fread(&z2, sizeof(float), 1, f);
  315. y++;
  316. // Read the third (final) vertex
  317. fread(&x3, sizeof(float), 1, f);
  318. fread(&y3, sizeof(float), 1, f);
  319. fread(&z3, sizeof(float), 1, f);
  320. y++;
  321. glm::vec3 a(x1, z1, y1);
  322. glm::vec3 b(x2, z2, y2);
  323. glm::vec3 c(x3, z3, y3);
  324. size_t sz = verts.size();
  325. verts.push_back(a);
  326. indices.push_back((uint32)sz);
  327. verts.push_back(b);
  328. indices.push_back((uint32)sz + 1);
  329. verts.push_back(c);
  330. indices.push_back((uint32)sz + 2);
  331. if (mGrid != nullptr)
  332. {
  333. Face* face = new Face;
  334. face->Vertex1[0] = x1;
  335. face->Vertex1[1] = y1;
  336. face->Vertex1[2] = z1;
  337. face->Vertex2[0] = x2;
  338. face->Vertex2[1] = y2;
  339. face->Vertex2[2] = z2;
  340. face->Vertex3[0] = x3;
  341. face->Vertex3[1] = y3;
  342. face->Vertex3[2] = z3;
  343. mGrid->AddFace(face, GridID);
  344. }
  345. }
  346. }
  347. face_count = face_count / 3;
  348. if (imp) {
  349. imp->rm->release();
  350. imp->rm = nullptr;
  351. }
  352. else {
  353. imp = new impl;
  354. }
  355. imp->rm = createRaycastMesh((RmUint32)verts.size(), (const RmReal*)&verts[0], face_count, &indices[0]);
  356. if (!imp->rm) {
  357. delete imp;
  358. imp = nullptr;
  359. return false;
  360. }
  361. return true;
  362. }
  363. void Map::RotateVertex(glm::vec3 &v, float rx, float ry, float rz) {
  364. glm::vec3 nv = v;
  365. nv.y = (std::cos(rx) * v.y) - (std::sin(rx) * v.z);
  366. nv.z = (std::sin(rx) * v.y) + (std::cos(rx) * v.z);
  367. v = nv;
  368. nv.x = (std::cos(ry) * v.x) + (std::sin(ry) * v.z);
  369. nv.z = -(std::sin(ry) * v.x) + (std::cos(ry) * v.z);
  370. v = nv;
  371. nv.x = (std::cos(rz) * v.x) - (std::sin(rz) * v.y);
  372. nv.y = (std::sin(rz) * v.x) + (std::cos(rz) * v.y);
  373. v = nv;
  374. }
  375. void Map::ScaleVertex(glm::vec3 &v, float sx, float sy, float sz) {
  376. v.x = v.x * sx;
  377. v.y = v.y * sy;
  378. v.z = v.z * sz;
  379. }
  380. void Map::TranslateVertex(glm::vec3 &v, float tx, float ty, float tz) {
  381. v.x = v.x + tx;
  382. v.y = v.y + ty;
  383. v.z = v.z + tz;
  384. }