/inc/cryengine/CryCommon/AABBSV.h

https://github.com/samneirinck/awesomium-ce3 · C Header · 331 lines · 220 code · 46 blank · 65 comment · 55 complexity · c66d84eecbcc294406badf50e233c4b6 MD5 · raw file

  1. //////////////////////////////////////////////////////////////////////
  2. //
  3. // Crytek CryENGINE Source code
  4. //
  5. // File:AABBSV.h
  6. // Description: shadow volume AABB functionality for overlap testings
  7. //
  8. // History:
  9. // -Feb 15,2004:Created by Michael Glueck, code provided by Ivo Herzeg
  10. //
  11. //////////////////////////////////////////////////////////////////////
  12. #ifndef AABBSV_H
  13. #define AABBSV_H
  14. #if _MSC_VER > 1000
  15. # pragma once
  16. #endif
  17. #include "Cry_Geo.h"
  18. struct Shadowvolume
  19. {
  20. uint32 sideamount;
  21. uint32 nplanes;
  22. Plane oplanes[10];
  23. };
  24. namespace NAABB_SV
  25. {
  26. //***************************************************************************************
  27. //***************************************************************************************
  28. //*** Calculate a ShadowVolume using an AABB and a point-light ***
  29. //***************************************************************************************
  30. //*** The planes of the AABB facing away from the point-light are the far-planes ***
  31. //*** of the ShadowVolume. There can be 3-6 far-planes. ***
  32. //***************************************************************************************
  33. void AABB_ReceiverShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume &sv);
  34. //***************************************************************************************
  35. //***************************************************************************************
  36. //*** Calculate a ShadowVolume using an AABB and a point-light ***
  37. //***************************************************************************************
  38. //*** The planes of the AABB facing the point-light are the near-planes of the ***
  39. //*** the ShadowVolume. There can be 1-3 near-planes. ***
  40. //*** The far-plane is defined by lightrange. ***
  41. //***************************************************************************************
  42. void AABB_ShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume &sv, f32 lightrange);
  43. //***************************************************************************************
  44. //*** this is the "fast" version to check if an AABB is overlapping a shadowvolume ***
  45. //***************************************************************************************
  46. bool Is_AABB_In_ShadowVolume( const Shadowvolume &sv, const AABB& Receiver );
  47. //***************************************************************************************
  48. //*** this is the "hierarchical" check ***
  49. //***************************************************************************************
  50. char Is_AABB_In_ShadowVolume_hierarchical( const Shadowvolume &sv, const AABB& Receiver );
  51. }
  52. inline void NAABB_SV::AABB_ReceiverShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume &sv)
  53. {
  54. sv.sideamount=0;
  55. sv.nplanes=0;
  56. //------------------------------------------------------------------------------
  57. //-- check if PointLight is in front of any occluder plane or inside occluder --
  58. //------------------------------------------------------------------------------
  59. uint32 front=0;
  60. if (PointLight.x<Occluder.min.x) front|=0x01;
  61. if (PointLight.x>Occluder.max.x) front|=0x02;
  62. if (PointLight.y<Occluder.min.y) front|=0x04;
  63. if (PointLight.y>Occluder.max.y) front|=0x08;
  64. if (PointLight.z<Occluder.min.z) front|=0x10;
  65. if (PointLight.z>Occluder.max.z) front|=0x20;
  66. sv.sideamount = BoxSides[(front<<3)+7];
  67. uint32 back = front^0x3f;
  68. if (back&0x01) { sv.oplanes[sv.nplanes].SetPlane(Vec3(-1,+0,+0),Occluder.min); sv.nplanes++; }
  69. if (back&0x02) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+1,+0,+0),Occluder.max); sv.nplanes++; }
  70. if (back&0x04) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,-1,+0),Occluder.min); sv.nplanes++; }
  71. if (back&0x08) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+1,+0),Occluder.max); sv.nplanes++; }
  72. if (back&0x10) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+0,-1),Occluder.min); sv.nplanes++; }
  73. if (back&0x20) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+0,+1),Occluder.max); sv.nplanes++; }
  74. if (front==0) return; //light is inside occluder
  75. //all 8 vertices of a AABB
  76. Vec3 o[8] =
  77. {
  78. Vec3(Occluder.min.x,Occluder.min.y,Occluder.min.z),
  79. Vec3(Occluder.max.x,Occluder.min.y,Occluder.min.z),
  80. Vec3(Occluder.min.x,Occluder.max.y,Occluder.min.z),
  81. Vec3(Occluder.max.x,Occluder.max.y,Occluder.min.z),
  82. Vec3(Occluder.min.x,Occluder.min.y,Occluder.max.z),
  83. Vec3(Occluder.max.x,Occluder.min.y,Occluder.max.z),
  84. Vec3(Occluder.min.x,Occluder.max.y,Occluder.max.z),
  85. Vec3(Occluder.max.x,Occluder.max.y,Occluder.max.z)
  86. };
  87. //---------------------------------------------------------------------
  88. //--- find the silhouette-vertices of the occluder-AABB ---
  89. //---------------------------------------------------------------------
  90. uint32 p0 = BoxSides[(front<<3)+0];
  91. uint32 p1 = BoxSides[(front<<3)+1];
  92. uint32 p2 = BoxSides[(front<<3)+2];
  93. uint32 p3 = BoxSides[(front<<3)+3];
  94. uint32 p4 = BoxSides[(front<<3)+4];
  95. uint32 p5 = BoxSides[(front<<3)+5];
  96. float a;
  97. if(sv.sideamount==4)
  98. {
  99. //sv.oplanes[sv.nplanes+0] = Plane::CreatePlane( o[p0],o[p1], PointLight );
  100. //sv.oplanes[sv.nplanes+1] = Plane::CreatePlane( o[p1],o[p2], PointLight );
  101. //sv.oplanes[sv.nplanes+2] = Plane::CreatePlane( o[p2],o[p3], PointLight );
  102. //sv.oplanes[sv.nplanes+3] = Plane::CreatePlane( o[p3],o[p0], PointLight );
  103. sv.sideamount=0;
  104. a=(o[p1]-o[p0])|(o[p0]-PointLight);
  105. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p0],o[p1], PointLight ); sv.sideamount++; }
  106. a=(o[p2]-o[p1])|(o[p1]-PointLight);
  107. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p1],o[p2], PointLight ); sv.sideamount++; }
  108. a=(o[p3]-o[p2])|(o[p2]-PointLight);
  109. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p2],o[p3], PointLight ); sv.sideamount++; }
  110. a=(o[p0]-o[p3])|(o[p3]-PointLight);
  111. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p3],o[p0], PointLight ); sv.sideamount++; }
  112. }
  113. if(sv.sideamount==6)
  114. {
  115. //sv.oplanes[sv.nplanes+0] = Plane::CreatePlane( o[p0],o[p1], PointLight );
  116. //sv.oplanes[sv.nplanes+1] = Plane::CreatePlane( o[p1],o[p2], PointLight );
  117. //sv.oplanes[sv.nplanes+2] = Plane::CreatePlane( o[p2],o[p3], PointLight );
  118. //sv.oplanes[sv.nplanes+3] = Plane::CreatePlane( o[p3],o[p4], PointLight );
  119. //sv.oplanes[sv.nplanes+4] = Plane::CreatePlane( o[p4],o[p5], PointLight );
  120. //sv.oplanes[sv.nplanes+5] = Plane::CreatePlane( o[p5],o[p0], PointLight );
  121. sv.sideamount=0;
  122. a=(o[p1]-o[p0])|(o[p0]-PointLight);
  123. assert(sv.nplanes+sv.sideamount<10);
  124. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p0],o[p1], PointLight ); sv.sideamount++; }
  125. a=(o[p2]-o[p1])|(o[p1]-PointLight);
  126. assert(sv.nplanes+sv.sideamount<10);
  127. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p1],o[p2], PointLight ); sv.sideamount++; }
  128. a=(o[p3]-o[p2])|(o[p2]-PointLight);
  129. assert(sv.nplanes+sv.sideamount<10);
  130. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p2],o[p3], PointLight ); sv.sideamount++; }
  131. a=(o[p4]-o[p3])|(o[p3]-PointLight);
  132. assert(sv.nplanes+sv.sideamount<10);
  133. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p3],o[p4], PointLight ); sv.sideamount++; }
  134. a=(o[p5]-o[p4])|(o[p4]-PointLight);
  135. assert(sv.nplanes+sv.sideamount<10);
  136. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p4],o[p5], PointLight ); sv.sideamount++; }
  137. a=(o[p0]-o[p5])|(o[p5]-PointLight);
  138. assert(sv.nplanes+sv.sideamount<10);
  139. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p5],o[p0], PointLight ); sv.sideamount++; }
  140. }
  141. }
  142. inline void NAABB_SV::AABB_ShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume &sv, f32 lightrange)
  143. {
  144. sv.sideamount=0;
  145. sv.nplanes=0;
  146. //------------------------------------------------------------------------------
  147. //-- check if PointLight is in front of any occluder plane or inside occluder --
  148. //------------------------------------------------------------------------------
  149. uint32 front=0;
  150. if (PointLight.x<Occluder.min.x) front|=0x01;
  151. if (PointLight.x>Occluder.max.x) front|=0x02;
  152. if (PointLight.y<Occluder.min.y) front|=0x04;
  153. if (PointLight.y>Occluder.max.y) front|=0x08;
  154. if (PointLight.z<Occluder.min.z) front|=0x10;
  155. if (PointLight.z>Occluder.max.z) front|=0x20;
  156. if (front==0) return; //light is inside occluder
  157. sv.sideamount = BoxSides[(front<<3)+7];
  158. if (front&0x01) { sv.oplanes[sv.nplanes].SetPlane(Vec3(-1,+0,+0),Occluder.min); sv.nplanes++; }
  159. if (front&0x02) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+1,+0,+0),Occluder.max); sv.nplanes++; }
  160. if (front&0x04) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,-1,+0),Occluder.min); sv.nplanes++; }
  161. if (front&0x08) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+1,+0),Occluder.max); sv.nplanes++; }
  162. if (front&0x10) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+0,-1),Occluder.min); sv.nplanes++; }
  163. if (front&0x20) { sv.oplanes[sv.nplanes].SetPlane(Vec3(+0,+0,+1),Occluder.max); sv.nplanes++; }
  164. //all 8 vertices of a AABB
  165. Vec3 o[8] =
  166. {
  167. Vec3(Occluder.min.x,Occluder.min.y,Occluder.min.z),
  168. Vec3(Occluder.max.x,Occluder.min.y,Occluder.min.z),
  169. Vec3(Occluder.min.x,Occluder.max.y,Occluder.min.z),
  170. Vec3(Occluder.max.x,Occluder.max.y,Occluder.min.z),
  171. Vec3(Occluder.min.x,Occluder.min.y,Occluder.max.z),
  172. Vec3(Occluder.max.x,Occluder.min.y,Occluder.max.z),
  173. Vec3(Occluder.min.x,Occluder.max.y,Occluder.max.z),
  174. Vec3(Occluder.max.x,Occluder.max.y,Occluder.max.z)
  175. };
  176. //---------------------------------------------------------------------
  177. //--- find the silhouette-vertices of the occluder-AABB ---
  178. //---------------------------------------------------------------------
  179. uint32 p0 = BoxSides[(front<<3)+0];
  180. uint32 p1 = BoxSides[(front<<3)+1];
  181. uint32 p2 = BoxSides[(front<<3)+2];
  182. uint32 p3 = BoxSides[(front<<3)+3];
  183. uint32 p4 = BoxSides[(front<<3)+4];
  184. uint32 p5 = BoxSides[(front<<3)+5];
  185. //the new center-position in world-space
  186. Vec3 MiddleOfOccluder = (Occluder.max+Occluder.min)*0.5f;
  187. sv.oplanes[sv.nplanes] = Plane::CreatePlane( (MiddleOfOccluder-PointLight).GetNormalized() , (MiddleOfOccluder-PointLight).GetNormalized()*lightrange+PointLight );
  188. sv.nplanes++;
  189. float a;
  190. if(sv.sideamount==4)
  191. {
  192. sv.sideamount=0;
  193. a=(o[p1]-o[p0])|(o[p0]-PointLight);
  194. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p0],o[p1], PointLight ); sv.sideamount++; }
  195. a=(o[p2]-o[p1])|(o[p1]-PointLight);
  196. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p1],o[p2], PointLight ); sv.sideamount++; }
  197. a=(o[p3]-o[p2])|(o[p2]-PointLight);
  198. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p2],o[p3], PointLight ); sv.sideamount++; }
  199. a=(o[p0]-o[p3])|(o[p3]-PointLight);
  200. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p3],o[p0], PointLight ); sv.sideamount++; }
  201. }
  202. if(sv.sideamount==6)
  203. {
  204. sv.sideamount=0;
  205. a=(o[p1]-o[p0])|(o[p0]-PointLight);
  206. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p0],o[p1], PointLight ); sv.sideamount++; }
  207. a=(o[p2]-o[p1])|(o[p1]-PointLight);
  208. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p1],o[p2], PointLight ); sv.sideamount++; }
  209. a=(o[p3]-o[p2])|(o[p2]-PointLight);
  210. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p2],o[p3], PointLight ); sv.sideamount++; }
  211. a=(o[p4]-o[p3])|(o[p3]-PointLight);
  212. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p3],o[p4], PointLight ); sv.sideamount++; }
  213. a=(o[p5]-o[p4])|(o[p4]-PointLight);
  214. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p4],o[p5], PointLight ); sv.sideamount++; }
  215. a=(o[p0]-o[p5])|(o[p5]-PointLight);
  216. if (a) { sv.oplanes[sv.nplanes+sv.sideamount] = Plane::CreatePlane( o[p5],o[p0], PointLight ); sv.sideamount++; }
  217. }
  218. }
  219. inline bool NAABB_SV::Is_AABB_In_ShadowVolume( const Shadowvolume &sv, const AABB& Receiver )
  220. {
  221. uint32 pa=sv.sideamount+sv.nplanes;
  222. f32 d;
  223. const Vec3* pAABB=&Receiver.min;
  224. union f32_u
  225. {
  226. float floatVal;
  227. uint32 uintVal;
  228. };
  229. //------------------------------------------------------------------------------
  230. //---- check if receiver-AABB is in front of any of these planes ------
  231. //------------------------------------------------------------------------------
  232. for (uint32 x=0; x<pa; x++)
  233. {
  234. d=sv.oplanes[x].d;
  235. //avoid breaking strict aliasing rules
  236. f32_u ux; ux.floatVal = sv.oplanes[x].n.x;
  237. f32_u uy; uy.floatVal = sv.oplanes[x].n.y;
  238. f32_u uz; uz.floatVal = sv.oplanes[x].n.z;
  239. const uint32 bitX = ux.uintVal>>31;
  240. const uint32 bitY = uy.uintVal>>31;
  241. const uint32 bitZ = uz.uintVal>>31;
  242. d += sv.oplanes[x].n.x * pAABB[bitX].x;
  243. d += sv.oplanes[x].n.y * pAABB[bitY].y;
  244. d += sv.oplanes[x].n.z * pAABB[bitZ].z;
  245. if (d>0) return CULL_EXCLUSION;
  246. }
  247. return CULL_OVERLAP;
  248. }
  249. inline char NAABB_SV::Is_AABB_In_ShadowVolume_hierarchical( const Shadowvolume &sv, const AABB& Receiver )
  250. {
  251. uint32 pa=sv.sideamount+sv.nplanes;
  252. const Vec3* pAABB=&Receiver.min;
  253. f32 dot1,dot2;
  254. uint32 notOverlap = 0x80000000; // will be reset to 0 if there's at least one overlapping
  255. union f32_u
  256. {
  257. float floatVal;
  258. uint32 uintVal;
  259. };
  260. //------------------------------------------------------------------------------
  261. //---- check if receiver-AABB is in front of any of these planes ------
  262. //------------------------------------------------------------------------------
  263. for (uint32 x=0; x<pa; x++)
  264. {
  265. dot1=dot2=sv.oplanes[x].d;
  266. //avoid breaking strict aliasing rules
  267. f32_u ux; ux.floatVal = sv.oplanes[x].n.x;
  268. f32_u uy; uy.floatVal = sv.oplanes[x].n.y;
  269. f32_u uz; uz.floatVal = sv.oplanes[x].n.z;
  270. const uint32 bitX = ux.uintVal>>31;
  271. const uint32 bitY = uy.uintVal>>31;
  272. const uint32 bitZ = uz.uintVal>>31;
  273. dot1 += sv.oplanes[x].n.x * pAABB[0+bitX].x;
  274. dot2 += sv.oplanes[x].n.x * pAABB[1-bitX].x;
  275. dot1 += sv.oplanes[x].n.y * pAABB[0+bitY].y;
  276. dot2 += sv.oplanes[x].n.y * pAABB[1-bitY].y;
  277. dot1 += sv.oplanes[x].n.z * pAABB[0+bitZ].z;
  278. dot2 += sv.oplanes[x].n.z * pAABB[1-bitZ].z;
  279. PREFAST_SUPPRESS_WARNING(6001) f32_u d; d.floatVal = dot1; if ( !(d.uintVal&0x80000000) ) return CULL_EXCLUSION;
  280. PREFAST_SUPPRESS_WARNING(6001) f32_u d2; d.floatVal = dot2; notOverlap &= d2.uintVal;
  281. }
  282. if (notOverlap) return CULL_INCLUSION;
  283. return CULL_OVERLAP;
  284. }
  285. #endif