Advertisement
Guest User

Untitled

a guest
Jan 16th, 2014
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.19 KB | None | 0 0
  1. package com.voxel.engine.core.Utils;
  2.  
  3. import org.lwjgl.BufferUtils;
  4. import org.lwjgl.util.vector.Vector3f;
  5.  
  6. import java.nio.FloatBuffer;
  7.  
  8. import static org.lwjgl.opengl.GL11.*;
  9.  
  10. /**
  11. * Created with IntelliJ IDEA.
  12. * User: Toby's PC
  13. * Date: 14/01/14
  14. * Time: 19:37
  15. * To change this template use File | Settings | File Templates.
  16. */
  17. public class Frustum {
  18.  
  19. // We create an enum of the sides so we don't have to call each side 0 or 1.
  20. // This way it makes it more understandable and readable when dealing with frustum sides.
  21. public static final int RIGHT = 0; // The RIGHT side of the frustum
  22. public static final int LEFT = 1; // The LEFT side of the frustum
  23. public static final int BOTTOM = 2; // The BOTTOM side of the frustum
  24. public static final int TOP = 3; // The TOP side of the frustum
  25. public static final int BACK = 4; // The BACK side of the frustum
  26. public static final int FRONT = 5; // The FRONT side of the frustum
  27.  
  28. // Like above, instead of saying a number for the ABC and D of the plane, we
  29. // want to be more descriptive.
  30. public static final int A = 0; // The X value of the plane's normal
  31. public static final int B = 1; // The Y value of the plane's normal
  32. public static final int C = 2; // The Z value of the plane's normal
  33. public static final int D = 3; // The distance the plane is from the origin
  34.  
  35. // This holds the A B C and D values for each side of our frustum.
  36. float[][] m_Frustum = new float[6][4];
  37.  
  38. /** FloatBuffer to get ModelView matrix. **/
  39. FloatBuffer modl_b;
  40.  
  41. /** FloatBuffer to get Projection matrix. **/
  42. FloatBuffer proj_b;
  43.  
  44. ///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  45. /////
  46. ///// This normalizes a plane (A side) from a given frustum.
  47. /////
  48. ///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  49.  
  50. public void normalizePlane(float[][] frustum, int side)
  51. {
  52. // Here we calculate the magnitude of the normal to the plane (point A B C)
  53. // Remember that (A, B, C) is that same thing as the normal's (X, Y, Z).
  54. // To calculate magnitude you use the equation: magnitude = sqrt( x^2 + y^2 + z^2)
  55. float magnitude = (float)Math.sqrt( frustum[side][A] * frustum[side][A] +
  56. frustum[side][B] * frustum[side][B] + frustum[side][C] * frustum[side][C] );
  57.  
  58. // Then we divide the plane's values by it's magnitude.
  59. // This makes it easier to work with.
  60. frustum[side][A] /= magnitude;
  61. frustum[side][B] /= magnitude;
  62. frustum[side][C] /= magnitude;
  63. frustum[side][D] /= magnitude;
  64. }
  65.  
  66.  
  67.  
  68. ///////////////////////////////// CALCULATE FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  69. /////
  70. ///// This extracts our frustum from the projection and modelview matrix.
  71. /////
  72. ///////////////////////////////// CALCULATE FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  73.  
  74. public void calculateFrustum()
  75. {
  76. float[] proj = new float[16]; // This will hold our projection matrix
  77. float[] modl = new float[16]; // This will hold our modelview matrix
  78. float[] clip = new float[16]; // This will hold the clipping planes
  79.  
  80.  
  81. // glGetFloat() is used to extract information about our OpenGL world.
  82. // Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
  83. // It then stores the matrix into an array of [16].
  84. proj_b.rewind();
  85. glGetFloat(GL_PROJECTION_MATRIX, proj_b);
  86. proj_b.rewind();
  87. proj_b.get(proj);
  88.  
  89. // By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
  90. // This also stores it in an array of [16].
  91. modl_b.rewind();
  92. glGetFloat(GL_MODELVIEW_MATRIX, modl_b);
  93. modl_b.rewind();
  94. modl_b.get(modl);
  95.  
  96. // Now that we have our modelview and projection matrix, if we combine these 2 matrices,
  97. // it will give us our clipping planes. To combine 2 matrices, we multiply them.
  98.  
  99. clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
  100. clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
  101. clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
  102. clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
  103.  
  104. clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
  105. clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
  106. clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
  107. clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
  108.  
  109. clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
  110. clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
  111. clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
  112. clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
  113.  
  114. clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
  115. clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
  116. clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
  117. clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
  118.  
  119. // Now we actually want to get the sides of the frustum. To do this we take
  120. // the clipping planes we received above and extract the sides from them.
  121.  
  122. // This will extract the RIGHT side of the frustum
  123. m_Frustum[RIGHT][A] = clip[ 3] - clip[ 0];
  124. m_Frustum[RIGHT][B] = clip[ 7] - clip[ 4];
  125. m_Frustum[RIGHT][C] = clip[11] - clip[ 8];
  126. m_Frustum[RIGHT][D] = clip[15] - clip[12];
  127.  
  128. // Now that we have a normal (A,B,C) and a distance (D) to the plane,
  129. // we want to normalize that normal and distance.
  130.  
  131. // Normalize the RIGHT side
  132. normalizePlane(m_Frustum, RIGHT);
  133.  
  134. // This will extract the LEFT side of the frustum
  135. m_Frustum[LEFT][A] = clip[ 3] + clip[ 0];
  136. m_Frustum[LEFT][B] = clip[ 7] + clip[ 4];
  137. m_Frustum[LEFT][C] = clip[11] + clip[ 8];
  138. m_Frustum[LEFT][D] = clip[15] + clip[12];
  139.  
  140. // Normalize the LEFT side
  141. normalizePlane(m_Frustum, LEFT);
  142.  
  143. // This will extract the BOTTOM side of the frustum
  144. m_Frustum[BOTTOM][A] = clip[ 3] + clip[ 1];
  145. m_Frustum[BOTTOM][B] = clip[ 7] + clip[ 5];
  146. m_Frustum[BOTTOM][C] = clip[11] + clip[ 9];
  147. m_Frustum[BOTTOM][D] = clip[15] + clip[13];
  148.  
  149. // Normalize the BOTTOM side
  150. normalizePlane(m_Frustum, BOTTOM);
  151.  
  152. // This will extract the TOP side of the frustum
  153. m_Frustum[TOP][A] = clip[ 3] - clip[ 1];
  154. m_Frustum[TOP][B] = clip[ 7] - clip[ 5];
  155. m_Frustum[TOP][C] = clip[11] - clip[ 9];
  156. m_Frustum[TOP][D] = clip[15] - clip[13];
  157.  
  158. // Normalize the TOP side
  159. normalizePlane(m_Frustum, TOP);
  160.  
  161. // This will extract the BACK side of the frustum
  162. m_Frustum[BACK][A] = clip[ 3] - clip[ 2];
  163. m_Frustum[BACK][B] = clip[ 7] - clip[ 6];
  164. m_Frustum[BACK][C] = clip[11] - clip[10];
  165. m_Frustum[BACK][D] = clip[15] - clip[14];
  166.  
  167. // Normalize the BACK side
  168. normalizePlane(m_Frustum, BACK);
  169.  
  170. // This will extract the FRONT side of the frustum
  171. m_Frustum[FRONT][A] = clip[ 3] + clip[ 2];
  172. m_Frustum[FRONT][B] = clip[ 7] + clip[ 6];
  173. m_Frustum[FRONT][C] = clip[11] + clip[10];
  174. m_Frustum[FRONT][D] = clip[15] + clip[14];
  175.  
  176. // Normalize the FRONT side
  177. normalizePlane(m_Frustum, FRONT);
  178. }
  179.  
  180. // The code below will allow us to make checks within the frustum. For example,
  181. // if we want to see if a point, a sphere, or a cube lies inside of the frustum.
  182. // Because all of our planes point INWARDS (The normals are all pointing inside the frustum)
  183. // we then can assume that if a point is in FRONT of all of the planes, it's inside.
  184.  
  185. ///////////////////////////////// POINT IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  186. /////
  187. ///// This determines if a point is inside of the frustum
  188. /////
  189. ///////////////////////////////// POINT IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  190.  
  191. public boolean pointInFrustum( float x, float y, float z )
  192. {
  193. // Go through all the sides of the frustum
  194. for(int i = 0; i < 6; i++ )
  195. {
  196. // Calculate the plane equation and check if the point is behind a side of the frustum
  197. if(m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= 0)
  198. {
  199. // The point was behind a side, so it ISN'T in the frustum
  200. return false;
  201. }
  202. }
  203.  
  204. // The point was inside of the frustum (In front of ALL the sides of the frustum)
  205. return true;
  206. }
  207.  
  208.  
  209.  
  210. ///////////////////////////////// SPHERE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  211. /////
  212. ///// This determines if a sphere is inside of our frustum by it's center and radius.
  213. /////
  214. ///////////////////////////////// SPHERE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  215.  
  216. public boolean sphereInFrustum( float x, float y, float z, float radius )
  217. {
  218. // Go through all the sides of the frustum
  219. for(int i = 0; i < 6; i++ )
  220. {
  221. // If the center of the sphere is farther away from the plane than the radius
  222. if( m_Frustum[i][A] * x + m_Frustum[i][B] * y + m_Frustum[i][C] * z + m_Frustum[i][D] <= -radius )
  223. {
  224. // The distance was greater than the radius so the sphere is outside of the frustum
  225. return false;
  226. }
  227. }
  228.  
  229. // The sphere was inside of the frustum!
  230. return true;
  231. }
  232.  
  233.  
  234. public boolean cubeInFrustum(Vector3f center, float size )
  235. {
  236. return cubeInFrustum( center.x, center.y, center.z, size );
  237. }
  238.  
  239. ///////////////////////////////// CUBE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  240. /////
  241. ///// This determines if a cube is in or around our frustum by it's center and 1/2 it's length
  242. /////
  243. ///////////////////////////////// CUBE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
  244.  
  245. public boolean cubeInFrustum( float x, float y, float z, float size )
  246. {
  247. // This test is a bit more work, but not too much more complicated.
  248. // Basically, what is going on is, that we are given the center of the cube,
  249. // and half the length. Think of it like a radius. Then we checking each point
  250. // in the cube and seeing if it is inside the frustum. If a point is found in front
  251. // of a side, then we skip to the next side. If we get to a plane that does NOT have
  252. // a point in front of it, then it will return false.
  253.  
  254. // *Note* - This will sometimes say that a cube is inside the frustum when it isn't.
  255. // This happens when all the corners of the bounding box are not behind any one plane.
  256. // This is rare and shouldn't effect the overall rendering speed.
  257.  
  258. for(int i = 0; i < 6; i++ )
  259. {
  260. if(m_Frustum[i][A] * (x - size) + m_Frustum[i][B] * (y - size) + m_Frustum[i][C] * (z - size) + m_Frustum[i][D] > 0)
  261. continue;
  262. if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y - size) + m_Frustum[i][C] * (z - size) + m_Frustum[i][D] > 0)
  263. continue;
  264. if(m_Frustum[i][A] * (x - size) + m_Frustum[i][B] * (y + size) + m_Frustum[i][C] * (z - size) + m_Frustum[i][D] > 0)
  265. continue;
  266. if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y + size) + m_Frustum[i][C] * (z - size) + m_Frustum[i][D] > 0)
  267. continue;
  268. if(m_Frustum[i][A] * (x - size) + m_Frustum[i][B] * (y - size) + m_Frustum[i][C] * (z + size) + m_Frustum[i][D] > 0)
  269. continue;
  270. if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y - size) + m_Frustum[i][C] * (z + size) + m_Frustum[i][D] > 0)
  271. continue;
  272. if(m_Frustum[i][A] * (x - size) + m_Frustum[i][B] * (y + size) + m_Frustum[i][C] * (z + size) + m_Frustum[i][D] > 0)
  273. continue;
  274. if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y + size) + m_Frustum[i][C] * (z + size) + m_Frustum[i][D] > 0)
  275. continue;
  276.  
  277. // If we get here, it isn't in the frustum
  278. return false;
  279. }
  280.  
  281. return true;
  282. }
  283.  
  284.  
  285.  
  286. /** Frustum constructor.
  287. */
  288.  
  289. public Frustum()
  290. {
  291. modl_b = BufferUtils.createFloatBuffer(16);
  292. proj_b = BufferUtils.createFloatBuffer(16);
  293. }
  294.  
  295. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement