trace.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "cmdlib.h"
  2. #include "mathlib.h"
  3. #include "bspfile.h"
  4. #include "log.h" //--vluzacn
  5. // #define ON_EPSILON 0.001
  6. typedef struct tnode_s
  7. {
  8. planetypes type;
  9. vec3_t normal;
  10. float dist;
  11. int children[2];
  12. int pad;
  13. } tnode_t;
  14. static tnode_t* tnodes;
  15. static tnode_t* tnode_p;
  16. /*
  17. * ==============
  18. * MakeTnode
  19. *
  20. * Converts the disk node structure into the efficient tracing structure
  21. * ==============
  22. */
  23. static void MakeTnode(const int nodenum)
  24. {
  25. tnode_t* t;
  26. dplane_t* plane;
  27. int i;
  28. dnode_t* node;
  29. t = tnode_p++;
  30. node = g_dnodes + nodenum;
  31. plane = g_dplanes + node->planenum;
  32. t->type = plane->type;
  33. VectorCopy(plane->normal, t->normal);
  34. #ifdef ZHLT_PLANETYPE_FIX //debug
  35. if (plane->normal[(plane->type)%3] < 0)
  36. if (plane->type < 3)
  37. Warning ("MakeTnode: negative plane");
  38. else
  39. Developer (DEVELOPER_LEVEL_MESSAGE, "Warning: MakeTnode: negative plane\n");
  40. #endif
  41. t->dist = plane->dist;
  42. for (i = 0; i < 2; i++)
  43. {
  44. if (node->children[i] < 0)
  45. t->children[i] = g_dleafs[-node->children[i] - 1].contents;
  46. else
  47. {
  48. t->children[i] = tnode_p - tnodes;
  49. MakeTnode(node->children[i]);
  50. }
  51. }
  52. }
  53. /*
  54. * =============
  55. * MakeTnodes
  56. *
  57. * Loads the node structure out of a .bsp file to be used for light occlusion
  58. * =============
  59. */
  60. void MakeTnodes(dmodel_t* /*bm*/)
  61. {
  62. // 32 byte align the structs
  63. tnodes = (tnode_t*)calloc((g_numnodes + 1), sizeof(tnode_t));
  64. #if SIZEOF_CHARP == 8
  65. tnodes = (tnode_t*)(((long long)tnodes + 31) & ~31);
  66. #else
  67. tnodes = (tnode_t*)(((int)tnodes + 31) & ~31);
  68. #endif
  69. tnode_p = tnodes;
  70. MakeTnode(0);
  71. }
  72. //==========================================================
  73. int TestLine_r(const int node, const vec3_t start, const vec3_t stop)
  74. {
  75. tnode_t* tnode;
  76. float front, back;
  77. vec3_t mid;
  78. float frac;
  79. int side;
  80. int r;
  81. if ( (node == CONTENTS_SOLID)
  82. || (node == CONTENTS_SKY )
  83. /*|| (node == CONTENTS_NULL ) */
  84. )
  85. return node;
  86. if (node < 0)
  87. return CONTENTS_EMPTY;
  88. tnode = &tnodes[node];
  89. switch (tnode->type)
  90. {
  91. case plane_x:
  92. front = start[0] - tnode->dist;
  93. back = stop[0] - tnode->dist;
  94. break;
  95. case plane_y:
  96. front = start[1] - tnode->dist;
  97. back = stop[1] - tnode->dist;
  98. break;
  99. case plane_z:
  100. front = start[2] - tnode->dist;
  101. back = stop[2] - tnode->dist;
  102. break;
  103. default:
  104. front = (start[0] * tnode->normal[0] + start[1] * tnode->normal[1] + start[2] * tnode->normal[2]) - tnode->dist;
  105. back = (stop[0] * tnode->normal[0] + stop[1] * tnode->normal[1] + stop[2] * tnode->normal[2]) - tnode->dist;
  106. break;
  107. }
  108. if (front >= -ON_EPSILON && back >= -ON_EPSILON)
  109. return TestLine_r(tnode->children[0], start, stop);
  110. if (front < ON_EPSILON && back < ON_EPSILON)
  111. return TestLine_r(tnode->children[1], start, stop);
  112. side = front < 0;
  113. frac = front / (front - back);
  114. mid[0] = start[0] + (stop[0] - start[0]) * frac;
  115. mid[1] = start[1] + (stop[1] - start[1]) * frac;
  116. mid[2] = start[2] + (stop[2] - start[2]) * frac;
  117. r = TestLine_r(tnode->children[side], start, mid);
  118. if (r != CONTENTS_EMPTY)
  119. return r;
  120. return TestLine_r(tnode->children[!side], mid, stop);
  121. }
  122. int TestLine(const vec3_t start, const vec3_t stop)
  123. {
  124. return TestLine_r(0, start, stop);
  125. }