trace.cpp 3.3 KB

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