region_map_v1.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include "region_map_v1.h"
  2. #include "../../common/Log.h"
  3. RegionMapV1::RegionMapV1() {
  4. }
  5. RegionMapV1::~RegionMapV1() {
  6. map<Region_Node*, ZBSP_Node*>::const_iterator itr;
  7. int region_num = 0;
  8. for (itr = Regions.begin(); itr != Regions.end();)
  9. {
  10. Region_Node* node = itr->first;
  11. ZBSP_Node* bsp_node = itr->second;
  12. map<Region_Node*, ZBSP_Node*>::const_iterator deleteItr = itr;
  13. itr++;
  14. Regions.erase(deleteItr);
  15. safe_delete(node);
  16. safe_delete_array(bsp_node);
  17. }
  18. Regions.clear();
  19. }
  20. WaterRegionType RegionMapV1::ReturnRegionType(const glm::vec3& location, float belowY) const {
  21. return BSPReturnRegionType(1, glm::vec3(location.y, location.x + 0.5f, location.z));
  22. }
  23. bool RegionMapV1::InWater(const glm::vec3& location, float belowY) const {
  24. return ReturnRegionType(location, belowY) == RegionTypeWater;
  25. }
  26. bool RegionMapV1::InLava(const glm::vec3& location) const {
  27. return ReturnRegionType(location) == RegionTypeLava;
  28. }
  29. bool RegionMapV1::InLiquid(const glm::vec3& location) const {
  30. return InWater(location) || InLava(location);
  31. }
  32. bool RegionMapV1::InPvP(const glm::vec3& location) const {
  33. return ReturnRegionType(location) == RegionTypePVP;
  34. }
  35. bool RegionMapV1::InZoneLine(const glm::vec3& location) const {
  36. return ReturnRegionType(location) == RegionTypeZoneLine;
  37. }
  38. bool RegionMapV1::Load(FILE* fp) {
  39. uint32 region_size;
  40. if (fread(&region_size, sizeof(region_size), 1, fp) != 1) {
  41. return false;
  42. }
  43. LogWrite(REGION__DEBUG, 0, "RegionMap", "region count = %u", region_size);
  44. for (int i = 0; i < region_size; i++)
  45. {
  46. uint32 region_num;
  47. if (fread(&region_num, sizeof(region_num), 1, fp) != 1) {
  48. return false;
  49. }
  50. uint32 region_type;
  51. if (fread(&region_type, sizeof(region_type), 1, fp) != 1) {
  52. return false;
  53. }
  54. float x, y, z, dist;
  55. if (fread(&x, sizeof(x), 1, fp) != 1) {
  56. return false;
  57. }
  58. if (fread(&y, sizeof(y), 1, fp) != 1) {
  59. return false;
  60. }
  61. if (fread(&z, sizeof(z), 1, fp) != 1) {
  62. return false;
  63. }
  64. if (fread(&dist, sizeof(dist), 1, fp) != 1) {
  65. return false;
  66. }
  67. uint32 bsp_tree_size;
  68. if (fread(&bsp_tree_size, sizeof(bsp_tree_size), 1, fp) != 1) {
  69. return false;
  70. }
  71. LogWrite(REGION__DEBUG, 0, "RegionMap", "region x,y,z,dist = %f, %f, %f, %f, region bsp tree size: %u", x, y, z, dist, bsp_tree_size);
  72. ZBSP_Node* BSP_Root = new ZBSP_Node[bsp_tree_size];
  73. if (fread(BSP_Root, sizeof(ZBSP_Node), bsp_tree_size, fp) != bsp_tree_size) {
  74. LogWrite(REGION__ERROR, 0, "RegionMap", "Failed to load region.");
  75. return false;
  76. }
  77. Region_Node* tmpNode = new Region_Node;
  78. tmpNode->x = x;
  79. tmpNode->y = y;
  80. tmpNode->z = z;
  81. tmpNode->dist = dist;
  82. tmpNode->region_type = region_type;
  83. Regions.insert(make_pair(tmpNode, BSP_Root));
  84. }
  85. fclose(fp);
  86. LogWrite(REGION__DEBUG, 0, "RegionMap", "completed load!");
  87. return true;
  88. }
  89. WaterRegionType RegionMapV1::BSPReturnRegionType(int32 node_number, const glm::vec3& location) const {
  90. map<Region_Node*, ZBSP_Node*>::const_iterator itr;
  91. int region_num = 0;
  92. for (itr = Regions.begin(); itr != Regions.end(); itr++)
  93. {
  94. Region_Node* node = itr->first;
  95. ZBSP_Node* BSP_Root = itr->second;
  96. float x1 = node->x - location.x;
  97. float y1 = node->y - location.y;
  98. float z1 = node->z - location.z;
  99. float dist = sqrt(x1 * x1 + y1 * y1 + z1 * z1);
  100. #ifdef REGIONDEBUG
  101. printf("Region %i (%i) dist %f / node dist %f. NodeXYZ: %f %f %f, XYZ: %f %f %f.\n", region_num, node->region_type, dist, node->dist, node->x, node->y, node->z, location.x, location.y, location.z);
  102. #endif
  103. if (dist <= node->dist)
  104. {
  105. ZBSP_Node* BSP_Root = itr->second;
  106. const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
  107. WaterRegionType regionType = RegionTypeUntagged;
  108. if (node->region_type == ClassWaterRegion)
  109. regionType = BSPReturnRegionWaterRegion(node, BSP_Root, node_number, location, dist);
  110. else
  111. regionType = BSPReturnRegionTypeNode(node, BSP_Root, node_number, location, dist);
  112. if (regionType != RegionTypeNormal)
  113. return regionType;
  114. }
  115. region_num++;
  116. }
  117. return(RegionTypeNormal);
  118. }
  119. WaterRegionType RegionMapV1::BSPReturnRegionTypeNode(const Region_Node* region_node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode) const {
  120. const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
  121. float distance;
  122. #ifdef REGIONDEBUG
  123. printf("left = %u, right %u\n", current_node->left, current_node->right);
  124. #endif
  125. if (region_node->region_type == ClassWaterRegion2)
  126. {
  127. distance = (location.x * current_node->normal[0]) +
  128. (location.y * current_node->normal[1]) +
  129. (location.z * current_node->normal[2]) +
  130. current_node->splitdistance;
  131. }
  132. else {
  133. distance = (location.x * current_node->normal[0]) +
  134. (location.y * current_node->normal[1]) +
  135. (location.z * current_node->normal[2]) -
  136. current_node->splitdistance;
  137. }
  138. float absDistance = distance;
  139. if (absDistance < 0.0f)
  140. absDistance *= -1.0f;
  141. float absSplitDist = current_node->splitdistance;
  142. if (absSplitDist < 0.0f)
  143. absSplitDist *= -1.0f;
  144. #ifdef REGIONDEBUG
  145. printf("distance = %f, normals: %f %f %f, location: %f %f %f, split distance: %f\n", distance, current_node->left, current_node->right, current_node->normal[0], current_node->normal[1], current_node->normal[2],
  146. location.x, location.y, location.z, current_node->splitdistance);
  147. #endif
  148. if ((current_node->left == -2) &&
  149. (current_node->right == -1 || current_node->right == -2)) {
  150. if (region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2)
  151. {
  152. if ( region_node->region_type == ClassWaterOcean && current_node->right == -1 &&
  153. current_node->normal[1] >= 0.9f && distance > 0 )
  154. return RegionTypeWater;
  155. else
  156. return EstablishDistanceAtAngle(region_node, current_node, distance, absDistance, absSplitDist, true);
  157. }
  158. else
  159. {
  160. if (distance > 0)
  161. return(RegionTypeWater);
  162. else
  163. return RegionTypeNormal;
  164. }
  165. }
  166. else if ((region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2) && current_node->normal[1] != 1.0f && current_node->normal[1] != -1.0f)
  167. {
  168. float fraction = abs(current_node->normal[0] * current_node->normal[2]);
  169. float diff = distToNode / region_node->dist;
  170. if (distance > 0)
  171. diff = distance * diff;
  172. #ifdef REGIONDEBUG
  173. printf("Diff: %f (%f + %f), fraction %f\n", diff, distToNode, distance, fraction);
  174. #endif
  175. if ((abs(diff) / 2.0f) > (absSplitDist * (1.0f / fraction)) * 2.0f)
  176. return RegionTypeNormal;
  177. }
  178. if (distance == 0.0f) {
  179. return(RegionTypeNormal);
  180. }
  181. if (distance > 0.0f) {
  182. #ifdef REGIONDEBUG
  183. printf("to left node %i\n", current_node->left);
  184. #endif
  185. if (current_node->left == -2)
  186. {
  187. switch(region_node->region_type)
  188. {
  189. case ClassWaterVolume:
  190. case ClassWaterOcean:
  191. return RegionTypeWater;
  192. break;
  193. case ClassWaterOcean2:
  194. return EstablishDistanceAtAngle(region_node, current_node, distance, absDistance, absSplitDist, false);
  195. break;
  196. case ClassWaterCavern:
  197. return EstablishDistanceAtAngle(region_node, current_node, distance, absDistance, absSplitDist, true);
  198. break;
  199. default:
  200. return RegionTypeNormal;
  201. break;
  202. }
  203. }
  204. else if (current_node->left == -1) {
  205. return(RegionTypeNormal);
  206. }
  207. return BSPReturnRegionTypeNode(region_node, BSP_Root, current_node->left + 1, location, distToNode);
  208. }
  209. #ifdef REGIONDEBUG
  210. printf("to right node %i, sign bit %i\n", current_node->right, signbit(current_node->normal[1]));
  211. #endif
  212. if (current_node->right == -1) {
  213. if (region_node->region_type == ClassWaterOcean2 && signbit(current_node->normal[1]) == 0 && absDistance < absSplitDist)
  214. return RegionTypeWater;
  215. else if ((region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2) &&
  216. (current_node->normal[1] > 0.0f && distance < 0.0f && absDistance < absSplitDist))
  217. {
  218. return(RegionTypeWater);
  219. }
  220. return(RegionTypeNormal);
  221. }
  222. return BSPReturnRegionTypeNode(region_node, BSP_Root, current_node->right + 1, location, distToNode);
  223. }
  224. WaterRegionType RegionMapV1::BSPReturnRegionWaterRegion(const Region_Node* region_node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode) const {
  225. const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
  226. float distance;
  227. #ifdef REGIONDEBUG
  228. printf("left = %u, right %u\n", current_node->left, current_node->right);
  229. #endif
  230. distance = (location.x * current_node->normal[0]) +
  231. (location.y * current_node->normal[1]) +
  232. (location.z * current_node->normal[2]) -
  233. current_node->splitdistance;
  234. #ifdef REGIONDEBUG
  235. printf("distance = %f, normals: %f %f %f, location: %f %f %f, split distance: %f\n", distance, current_node->left, current_node->right, current_node->normal[0], current_node->normal[1], current_node->normal[2],
  236. location.x, location.y, location.z, current_node->splitdistance);
  237. #endif
  238. if (distance > 0.0f) {
  239. #ifdef REGIONDEBUG
  240. printf("to left node %i\n", current_node->left);
  241. #endif
  242. if (current_node->left == -1) {
  243. return(RegionTypeNormal);
  244. }
  245. else if (current_node->left == -2) {
  246. return(RegionTypeWater);
  247. }
  248. return BSPReturnRegionWaterRegion(region_node, BSP_Root, current_node->left + 1, location, distToNode);
  249. }
  250. #ifdef REGIONDEBUG
  251. printf("to right node %i, sign bit %i\n", current_node->right, signbit(current_node->normal[1]));
  252. #endif
  253. if (current_node->right == -1) {
  254. return(RegionTypeNormal);
  255. }
  256. return BSPReturnRegionWaterRegion(region_node, BSP_Root, current_node->right + 1, location, distToNode);
  257. }
  258. WaterRegionType RegionMapV1::EstablishDistanceAtAngle(const Region_Node* region_node, const ZBSP_Node* current_node, float distance, float absDistance, float absSplitDist, bool checkEdgedAngle) const {
  259. float fraction = abs(current_node->normal[0] * current_node->normal[2]);
  260. #ifdef REGIONDEBUG
  261. printf("Distcheck: %f < %f\n", absDistance, absSplitDist);
  262. #endif
  263. if (absDistance < absSplitDist &&
  264. (current_node->normal[0] >= 1.0f || current_node->normal[0] <= -1.0f ||
  265. (current_node->normal[1] >= .9f && distance < 0.0f) ||
  266. (current_node->normal[1] <= -.9f && distance > 0.0f)))
  267. {
  268. return RegionTypeWater;
  269. }
  270. else if (fraction > 0.0f && (region_node->region_type == ClassWaterOcean2 || checkEdgedAngle))
  271. {
  272. if (current_node->normal[2] >= 1.0f || current_node->normal[2] <= -1.0f)
  273. return RegionTypeNormal;
  274. else if (current_node->normal[1] == 0.0f && (current_node->normal[0] < -0.5f || current_node->normal[0] > 0.5f) &&
  275. ((abs(absDistance * current_node->normal[0]) / 2.0f) < ((abs(absSplitDist * (1.0f / fraction))))))
  276. {
  277. return RegionTypeWater;
  278. }
  279. else if (current_node->normal[1] == 0.0f && (current_node->normal[2] < -0.5f || current_node->normal[2] > 0.5f) &&
  280. ((abs(absDistance * current_node->normal[2]) / 2.0f) < ((abs(absSplitDist * (1.0f / fraction))))))
  281. {
  282. return RegionTypeWater;
  283. }
  284. }
  285. return RegionTypeNormal;
  286. }