• API
• FAQ
• Tools
• Trends
• Archive
SHARE
TWEET

# Untitled

a guest Jan 16th, 2014 4 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
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. }
RAW Paste Data
Top