Bounds.hx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. package h3d.col;
  2. import hxd.Math;
  3. class Bounds {
  4. public var xMin : Float;
  5. public var xMax : Float;
  6. public var yMin : Float;
  7. public var yMax : Float;
  8. public var zMin : Float;
  9. public var zMax : Float;
  10. public inline function new() {
  11. empty();
  12. }
  13. public function inFrustum( mvp : Matrix ) {
  14. if( testPlane(Plane.frustumLeft(mvp)) < 0 )
  15. return false;
  16. if( testPlane(Plane.frustumRight(mvp)) < 0 )
  17. return false;
  18. if( testPlane(Plane.frustumBottom(mvp)) < 0 )
  19. return false;
  20. if( testPlane(Plane.frustumTop(mvp)) < 0 )
  21. return false;
  22. if( testPlane(Plane.frustumNear(mvp)) < 0 )
  23. return false;
  24. if( testPlane(Plane.frustumFar(mvp)) < 0 )
  25. return false;
  26. return true;
  27. }
  28. inline function testPlane( p : Plane ) {
  29. var a = p.nx;
  30. var b = p.ny;
  31. var c = p.nz;
  32. var dd = a * (xMax + xMin) + b * (yMax + yMin) + c * (zMax + zMin);
  33. if( a < 0 ) a = -a;
  34. if( b < 0 ) b = -b;
  35. if( c < 0 ) c = -c;
  36. var rr = a * (xMax - xMin) + b * (yMax - yMin) + c * (zMax - zMin);
  37. return dd + rr - p.d*2;
  38. }
  39. /**
  40. * Check if the camera model-view-projection Matrix intersects with the Bounds. Returns -1 if outside, 0 if interests and 1 if fully inside.
  41. * @param mvp : the model-view-projection matrix to test against
  42. * @param checkZ : tells if we will check against the near/far plane
  43. */
  44. public function inFrustumDetails( mvp : Matrix, checkZ = true ) {
  45. var ret = 1;
  46. // left
  47. var p = new Plane(mvp._14 + mvp._11, mvp._24 + mvp._21 , mvp._34 + mvp._31, mvp._44 + mvp._41);
  48. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  49. if( m + p.d < 0 )
  50. return -1;
  51. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  52. if( n + p.d < 0 ) ret = 0;
  53. // right
  54. var p = new Plane(mvp._14 - mvp._11, mvp._24 - mvp._21 , mvp._34 - mvp._31, mvp._44 - mvp._41);
  55. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  56. if( m + p.d < 0 )
  57. return -1;
  58. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  59. if( n + p.d < 0 ) ret = 0;
  60. // bottom
  61. var p = new Plane(mvp._14 + mvp._12, mvp._24 + mvp._22 , mvp._34 + mvp._32, mvp._44 + mvp._42);
  62. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  63. if( m + p.d < 0 )
  64. return -1;
  65. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  66. if( n + p.d < 0 ) ret = 0;
  67. // top
  68. var p = new Plane(mvp._14 - mvp._12, mvp._24 - mvp._22 , mvp._34 - mvp._32, mvp._44 - mvp._42);
  69. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  70. if( m + p.d < 0 )
  71. return -1;
  72. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  73. if( n + p.d < 0 ) ret = 0;
  74. if( checkZ ) {
  75. // nea
  76. var p = new Plane(mvp._13, mvp._23, mvp._33, mvp._43);
  77. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  78. if( m + p.d < 0 )
  79. return -1;
  80. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  81. if( n + p.d < 0 ) ret = 0;
  82. var p = new Plane(mvp._14 - mvp._13, mvp._24 - mvp._23, mvp._34 - mvp._33, mvp._44 - mvp._43);
  83. var m = p.nx * (p.nx > 0 ? xMax : xMin) + p.ny * (p.ny > 0 ? yMax : yMin) + p.nz * (p.nz > 0 ? zMax : zMin);
  84. if( m + p.d < 0 )
  85. return -1;
  86. var n = p.nx * (p.nx > 0 ? xMin : xMax) + p.ny * (p.ny > 0 ? yMin : yMax) + p.nz * (p.nz > 0 ? zMin : zMax);
  87. if( n + p.d < 0 ) ret = 0;
  88. }
  89. return ret;
  90. }
  91. public function transform3x4( m : Matrix ) {
  92. var xMin = xMin, yMin = yMin, zMin = zMin, xMax = xMax, yMax = yMax, zMax = zMax;
  93. empty();
  94. var v = new h3d.col.Point();
  95. v.set(xMin, yMin, zMin);
  96. v.transform(m);
  97. addPoint(v);
  98. v.set(xMin, yMin, zMax);
  99. v.transform(m);
  100. addPoint(v);
  101. v.set(xMin, yMax, zMin);
  102. v.transform(m);
  103. addPoint(v);
  104. v.set(xMin, yMax, zMax);
  105. v.transform(m);
  106. addPoint(v);
  107. v.set(xMax, yMin, zMin);
  108. v.transform(m);
  109. addPoint(v);
  110. v.set(xMax, yMin, zMax);
  111. v.transform(m);
  112. addPoint(v);
  113. v.set(xMax, yMax, zMin);
  114. v.transform(m);
  115. addPoint(v);
  116. v.set(xMax, yMax, zMax);
  117. v.transform(m);
  118. addPoint(v);
  119. }
  120. public inline function collide( b : Bounds ) {
  121. return !(xMin > b.xMax || yMin > b.yMax || zMin > b.zMax || xMax < b.xMin || yMax < b.yMin || zMax < b.zMin);
  122. }
  123. public inline function include( p : Point ) {
  124. return p.x >= xMin && p.x < xMax && p.y >= yMin && p.y < yMax && p.z >= zMin && p.z < zMax;
  125. }
  126. public inline function add( b : Bounds ) {
  127. if( b.xMin < xMin ) xMin = b.xMin;
  128. if( b.xMax > xMax ) xMax = b.xMax;
  129. if( b.yMin < yMin ) yMin = b.yMin;
  130. if( b.yMax > yMax ) yMax = b.yMax;
  131. if( b.zMin < zMin ) zMin = b.zMin;
  132. if( b.zMax > zMax ) zMax = b.zMax;
  133. }
  134. public inline function addPoint( p : Point ) {
  135. if( p.x < xMin ) xMin = p.x;
  136. if( p.x > xMax ) xMax = p.x;
  137. if( p.y < yMin ) yMin = p.y;
  138. if( p.y > yMax ) yMax = p.y;
  139. if( p.z < zMin ) zMin = p.z;
  140. if( p.z > zMax ) zMax = p.z;
  141. }
  142. public inline function addPos( x : Float, y : Float, z : Float ) {
  143. if( x < xMin ) xMin = x;
  144. if( x > xMax ) xMax = x;
  145. if( y < yMin ) yMin = y;
  146. if( y > yMax ) yMax = y;
  147. if( z < zMin ) zMin = z;
  148. if( z > zMax ) zMax = z;
  149. }
  150. public function intersection( a : Bounds, b : Bounds ) {
  151. var xMin = Math.max(a.xMin, b.xMin);
  152. var yMin = Math.max(a.yMin, b.yMin);
  153. var zMin = Math.max(a.zMin, b.zMin);
  154. var xMax = Math.max(a.xMax, b.xMax);
  155. var yMax = Math.max(a.yMax, b.yMax);
  156. var zMax = Math.max(a.zMax, b.zMax);
  157. this.xMin = xMin;
  158. this.xMax = xMax;
  159. this.yMin = yMin;
  160. this.yMax = yMax;
  161. this.zMin = zMin;
  162. this.zMax = zMax;
  163. }
  164. public inline function offset( dx : Float, dy : Float, dz : Float ) {
  165. xMin += dx;
  166. xMax += dx;
  167. yMin += dy;
  168. yMax += dy;
  169. zMin += dz;
  170. zMax += dz;
  171. }
  172. public inline function setMin( p : Point ) {
  173. xMin = p.x;
  174. yMin = p.y;
  175. zMin = p.z;
  176. }
  177. public inline function setMax( p : Point ) {
  178. xMax = p.x;
  179. yMax = p.y;
  180. zMax = p.z;
  181. }
  182. public function load( b : Bounds ) {
  183. xMin = b.xMin;
  184. xMax = b.xMax;
  185. yMin = b.yMin;
  186. yMax = b.yMax;
  187. zMin = b.zMin;
  188. zMax = b.zMax;
  189. }
  190. public function scaleCenter( v : Float ) {
  191. var dx = (xMax - xMin) * 0.5 * v;
  192. var dy = (yMax - yMin) * 0.5 * v;
  193. var dz = (zMax - zMin) * 0.5 * v;
  194. var mx = (xMax + xMin) * 0.5;
  195. var my = (yMax + yMin) * 0.5;
  196. var mz = (zMax + zMin) * 0.5;
  197. xMin = mx - dx;
  198. yMin = my - dy;
  199. zMin = mz - dz;
  200. xMax = mx + dx;
  201. yMax = my + dy;
  202. zMax = mz + dz;
  203. }
  204. public inline function getMin() {
  205. return new Point(xMin, yMin, zMin);
  206. }
  207. public inline function getCenter() {
  208. return new Point((xMin + xMax) * 0.5, (yMin + yMax) * 0.5, (zMin + zMax) * 0.5);
  209. }
  210. public inline function getSize() {
  211. return new Point(xMax - xMin, yMax - yMin, zMax - zMin);
  212. }
  213. public inline function getMax() {
  214. return new Point(xMax, yMax, zMax);
  215. }
  216. public inline function empty() {
  217. xMin = 1e20;
  218. xMax = -1e20;
  219. yMin = 1e20;
  220. yMax = -1e20;
  221. zMin = 1e20;
  222. zMax = -1e20;
  223. }
  224. public inline function all() {
  225. xMin = -1e20;
  226. xMax = 1e20;
  227. yMin = -1e20;
  228. yMax = 1e20;
  229. zMin = -1e20;
  230. zMax = 1e20;
  231. }
  232. public inline function clone() {
  233. var b = new Bounds();
  234. b.xMin = xMin;
  235. b.xMax = xMax;
  236. b.yMin = yMin;
  237. b.yMax = yMax;
  238. b.zMin = zMin;
  239. b.zMax = zMax;
  240. return b;
  241. }
  242. public function toString() {
  243. return "{" + getMin() + "," + getMax() + "}";
  244. }
  245. public static inline function fromPoints( min : Point, max : Point ) {
  246. var b = new Bounds();
  247. b.setMin(min);
  248. b.setMax(max);
  249. return b;
  250. }
  251. public static inline function fromValues( x : Float, y : Float, z : Float, dx : Float, dy : Float, dz : Float ) {
  252. var b = new Bounds();
  253. b.xMin = x;
  254. b.yMin = y;
  255. b.zMin = z;
  256. b.xMax = x + dx;
  257. b.yMax = y + dy;
  258. b.zMax = z + dz;
  259. return b;
  260. }
  261. }