TRACE.C 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // trace.c
  2. #include "light.h"
  3. typedef struct tnode_s
  4. {
  5. int type;
  6. vec3_t normal;
  7. float dist;
  8. int children[2];
  9. int pad;
  10. } tnode_t;
  11. tnode_t *tnodes, *tnode_p;
  12. /*
  13. ==============
  14. MakeTnode
  15. Converts the disk node structure into the efficient tracing structure
  16. ==============
  17. */
  18. void MakeTnode (int nodenum)
  19. {
  20. tnode_t *t;
  21. dplane_t *plane;
  22. int i;
  23. dnode_t *node;
  24. t = tnode_p++;
  25. node = dnodes + nodenum;
  26. plane = dplanes + node->planenum;
  27. t->type = plane->type;
  28. VectorCopy (plane->normal, t->normal);
  29. t->dist = plane->dist;
  30. for (i=0 ; i<2 ; i++)
  31. {
  32. if (node->children[i] < 0)
  33. t->children[i] = dleafs[-node->children[i] - 1].contents;
  34. else
  35. {
  36. t->children[i] = tnode_p - tnodes;
  37. MakeTnode (node->children[i]);
  38. }
  39. }
  40. }
  41. /*
  42. =============
  43. MakeTnodes
  44. Loads the node structure out of a .bsp file to be used for light occlusion
  45. =============
  46. */
  47. void MakeTnodes (dmodel_t *bm)
  48. {
  49. tnode_p = tnodes = malloc(numnodes * sizeof(tnode_t));
  50. MakeTnode (0);
  51. }
  52. /*
  53. ==============================================================================
  54. LINE TRACING
  55. The major lighting operation is a point to point visibility test, performed
  56. by recursive subdivision of the line by the BSP tree.
  57. ==============================================================================
  58. */
  59. typedef struct
  60. {
  61. vec3_t backpt;
  62. int side;
  63. int node;
  64. } tracestack_t;
  65. /*
  66. ==============
  67. TestLine
  68. ==============
  69. */
  70. qboolean TestLine (vec3_t start, vec3_t stop)
  71. {
  72. int node;
  73. float front, back;
  74. tracestack_t *tstack_p;
  75. int side;
  76. float frontx,fronty, frontz, backx, backy, backz;
  77. tracestack_t tracestack[64];
  78. tnode_t *tnode;
  79. frontx = start[0];
  80. fronty = start[1];
  81. frontz = start[2];
  82. backx = stop[0];
  83. backy = stop[1];
  84. backz = stop[2];
  85. tstack_p = tracestack;
  86. node = 0;
  87. while (1)
  88. {
  89. while (node < 0 && node != CONTENTS_SOLID)
  90. {
  91. // pop up the stack for a back side
  92. tstack_p--;
  93. if (tstack_p < tracestack)
  94. return true;
  95. node = tstack_p->node;
  96. // set the hit point for this plane
  97. frontx = backx;
  98. fronty = backy;
  99. frontz = backz;
  100. // go down the back side
  101. backx = tstack_p->backpt[0];
  102. backy = tstack_p->backpt[1];
  103. backz = tstack_p->backpt[2];
  104. node = tnodes[tstack_p->node].children[!tstack_p->side];
  105. }
  106. if (node == CONTENTS_SOLID)
  107. return false; // DONE!
  108. tnode = &tnodes[node];
  109. switch (tnode->type)
  110. {
  111. case PLANE_X:
  112. front = frontx - tnode->dist;
  113. back = backx - tnode->dist;
  114. break;
  115. case PLANE_Y:
  116. front = fronty - tnode->dist;
  117. back = backy - tnode->dist;
  118. break;
  119. case PLANE_Z:
  120. front = frontz - tnode->dist;
  121. back = backz - tnode->dist;
  122. break;
  123. default:
  124. front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
  125. back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
  126. break;
  127. }
  128. if (front > -ON_EPSILON && back > -ON_EPSILON)
  129. // if (front > 0 && back > 0)
  130. {
  131. node = tnode->children[0];
  132. continue;
  133. }
  134. if (front < ON_EPSILON && back < ON_EPSILON)
  135. // if (front <= 0 && back <= 0)
  136. {
  137. node = tnode->children[1];
  138. continue;
  139. }
  140. side = front < 0;
  141. front = front / (front-back);
  142. tstack_p->node = node;
  143. tstack_p->side = side;
  144. tstack_p->backpt[0] = backx;
  145. tstack_p->backpt[1] = backy;
  146. tstack_p->backpt[2] = backz;
  147. tstack_p++;
  148. backx = frontx + front*(backx-frontx);
  149. backy = fronty + front*(backy-fronty);
  150. backz = frontz + front*(backz-frontz);
  151. node = tnode->children[side];
  152. }
  153. }