map.cpp 9.9 KB

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