Advertisement
Guest User

FrustumTest

a guest
Dec 12th, 2013
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.96 KB | None | 0 0
  1. // g++ -std=c++11 FrustumTest.cpp -o FrustumTest -lGL -lglut
  2. /*{
  3.     "cmd": ["g++", "-std=c++11", "$file", "-o", "${file_path}/$file_base_name", "-I/usr/local/include", "-lGL", "-lglut"],
  4.     "selector": "source.c++",
  5.     "variants": [
  6.         {
  7.             "name": "Run",
  8.             "cmd": ["bash", "-c", "'${file_path}/${file_base_name}'"]
  9.         }
  10.     ]
  11. }*/
  12.  
  13. #include <GL/gl.h>
  14. #include <GL/glut.h>
  15. #include <glm/glm.hpp>
  16. #include <glm/ext.hpp>
  17. #include <vector>
  18. #include <cmath>
  19.  
  20. typedef glm::vec4 Plane;
  21. typedef std::vector<glm::vec4> Frustum;
  22.  
  23. Frustum ExtractFrustum(const glm::mat4& source);
  24. std::vector<glm::vec3> GetWorldCorners(const Frustum& frustum);
  25. std::vector<glm::vec3> GetWorldCorners(const glm::mat4& projectionView);
  26. glm::vec3 PlaneIntersection(const Plane& p1, const Plane& p2, const Plane& p3);
  27. void RenderFrustum(const std::vector<glm::vec3>& frustum);
  28.  
  29. void Reshape(int w, int h);
  30. void Render();
  31. void RenderOrigin();
  32. void RenderFrustumRed();
  33. void RenderFrustumGreen();
  34. void RenderFrustumBlue();
  35. void RenderFrustumYellow();
  36.  
  37. int main(int argc, char** argv) {
  38.     glutInit(&argc, argv);
  39.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  40.     glutInitWindowPosition(0,0);
  41.     glutInitWindowSize(800 , 600);
  42.     glutCreateWindow("Frustum Demo");
  43.     Reshape(800, 600);
  44.    
  45.     glutDisplayFunc(Render);
  46.     glutReshapeFunc(Reshape);
  47.        
  48.     glMatrixMode(GL_MODELVIEW);
  49.     glLoadIdentity();
  50.  
  51.     glutPostRedisplay();
  52.     glutMainLoop();
  53. }
  54.  
  55. void Render() {
  56.     glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
  57.     glClear(GL_COLOR_BUFFER_BIT);
  58.  
  59.     glMatrixMode(GL_MODELVIEW);
  60.     glLoadIdentity();
  61.     glm::mat4 glmLookAt = glm::lookAt(glm::vec3(-10.0f, 10.0f, 8.0f),
  62.         glm::vec3(0.0f, 4.0f, 0.0f),  glm::vec3(0.0f, 1.0f, 0.0f));
  63.     glMultMatrixf(glm::value_ptr(glmLookAt));
  64.    
  65.     RenderOrigin();
  66.     RenderFrustumRed();
  67.     RenderFrustumGreen();
  68.     RenderFrustumBlue();
  69.     RenderFrustumYellow();
  70.  
  71.     glutSwapBuffers();
  72.     glutPostRedisplay();
  73. }
  74.  
  75. void RenderFrustumRed() {
  76.     glm::mat4 cameraWorldPos = glm::translate(0.0f, 7.0f, 0.0f);
  77.     glm::mat4 cameraProjection = glm::perspective(60.0f, 0.9235993f, 1.0f, 5.0f);
  78.     glm::mat4 cameraView = cameraWorldPos._inverse();
  79.  
  80.     glm::mat4 viewProjMatrix = cameraProjection;
  81.     Frustum worldFrustum = ExtractFrustum(viewProjMatrix);
  82.     glColor3f(1.0f, 0.0f, 0.0f);
  83.     RenderFrustum(GetWorldCorners(worldFrustum));
  84. }
  85.  
  86. void RenderFrustumGreen() {
  87.     glm::mat4 cameraWorldPos = glm::translate(0.0f, 7.0f, 0.0f);
  88.     glm::mat4 cameraProjection = glm::perspective(60.0f, 0.9235993f, 1.0f, 5.0f);
  89.     glm::mat4 cameraView = cameraWorldPos._inverse();
  90.  
  91.     glm::mat4 viewProjMatrix = cameraProjection * cameraView;
  92.     Frustum worldFrustum = ExtractFrustum(viewProjMatrix);
  93.     glColor3f(0.0f, 1.0f, 0.0f);
  94.     RenderFrustum(GetWorldCorners(worldFrustum));
  95. }
  96.  
  97. void RenderFrustumBlue() {
  98.     glm::mat4 cameraWorldPos = glm::translate(0.0f, 7.0f, 0.0f);
  99.     glm::mat4 cameraProjection = glm::perspective(60.0f, 0.9235993f, 1.0f, 5.0f);
  100.  
  101.     glm::mat4 viewProjMatrix = cameraProjection;
  102.     Frustum worldFrustum = ExtractFrustum(viewProjMatrix);
  103.     std::vector<glm::vec3> corners = GetWorldCorners(worldFrustum);
  104.  
  105.     for (int i = 0, size = corners.size(); i < size; ++i) {
  106.         glm::vec4 vertex = cameraWorldPos * glm::vec4(corners[i], 1.0f);
  107.         corners[i] = glm::vec3(vertex.x, vertex.y, vertex.z);
  108.     }
  109.  
  110.     glColor3f(0.0f, 0.0f, 1.0f);
  111.     RenderFrustum(corners);
  112. }
  113.  
  114. void RenderFrustumYellow() {
  115.     glm::mat4 cameraWorldPos = glm::translate(0.0f, 7.0f, 0.0f);
  116.     glm::mat4 cameraProjection = glm::perspective(60.0f, 0.9235993f, 1.0f, 5.0f);
  117.     glm::mat4 cameraView = cameraWorldPos._inverse();
  118.  
  119.     glm::mat4 viewProjMatrix = cameraProjection * cameraView;
  120.     glColor3f(1.0f, 1.0f, 0.0f);
  121.     RenderFrustum(GetWorldCorners(viewProjMatrix));
  122. }
  123.  
  124. void RenderOrigin() {
  125.     glBegin(GL_LINES);
  126.     glColor3f(1.0f, 0.0f, 0.0f);
  127.     glVertex3f(0.0f, 0.0f, 0.0f);
  128.     glVertex3f(1.0f, 0.0f, 0.0f);
  129.     glColor3f(0.0f, 1.0f, 0.0f);
  130.     glVertex3f(0.0f, 0.0f, 0.0f);
  131.     glVertex3f(0.0f, 1.0f, 0.0f);
  132.     glColor3f(0.0f, 0.0f, 1.0f);
  133.     glVertex3f(0.0f, 0.0f, 0.0f);
  134.     glVertex3f(0.0f, 0.0f, 1.0f);
  135.     glEnd();
  136. }
  137.  
  138. void Reshape(int w, int h) {
  139.     glMatrixMode(GL_PROJECTION);
  140.     glLoadIdentity();
  141.  
  142.     float fov = 60.0f;
  143.     float aspectRatio = ((float)w) / ((float)h);
  144.     float znear = 0.1f;
  145.     float zfar = 1000.0f;
  146.  
  147.     float ymax = znear * tanf(fov * 3.14f / 360.0f);
  148.     float xmax = ymax * aspectRatio;
  149.    
  150.     glFrustum(-xmax, xmax, -ymax, ymax, znear, zfar);
  151.     glMatrixMode(GL_MODELVIEW);
  152. }
  153.  
  154. void RenderFrustum(const std::vector<glm::vec3>& corners) {
  155.     glBegin(GL_LINES);
  156.     for (int i = 0, size = corners.size(); i < size; ++i) {
  157.         for (int j = 0; j < size; ++j) {
  158.             if (i == j) continue;
  159.             glVertex3f(corners[i].x, corners[i].y, corners[i].z);
  160.             glVertex3f(corners[j].x, corners[j].y, corners[j].z);
  161.         }
  162.     }
  163.     glEnd();
  164. }
  165.  
  166. std::vector<glm::vec3> GetWorldCorners(const glm::mat4& projectionView) {
  167.     glm::mat4 inverseProjectionMatrix = glm::inverse(projectionView);
  168.  
  169.     std::vector<glm::vec3> corners; corners.reserve(8);
  170.     for (unsigned x = 0; x < 2; x++)
  171.         for (unsigned y = 0; y < 2; y++)
  172.             for (unsigned z = 0; z < 2; z++) { // I might mess up the order of the frustrum corners here. But the position should be correct
  173.                 glm::vec4 projClipSpacePosition(x*2.0f-1.0f, y*2.0f-1.0f, z*2.0f-1.0f, 1.0f);
  174.                 glm::vec4 projWorldSpacePosition = inverseProjectionMatrix * projClipSpacePosition;
  175.                 corners.push_back(glm::vec3(projWorldSpacePosition.x / projWorldSpacePosition.w,
  176.                                             projWorldSpacePosition.y / projWorldSpacePosition.w,
  177.                                             projWorldSpacePosition.z / projWorldSpacePosition.w));
  178.             }
  179.     return corners;
  180. }
  181.  
  182. std::vector<glm::vec3> GetWorldCorners(const Frustum& frustum) {
  183.     std::vector<glm::vec3> corners; corners.reserve(8);
  184.     corners.push_back(PlaneIntersection(frustum[4], frustum[0], frustum[2]));
  185.     corners.push_back(PlaneIntersection(frustum[4], frustum[0], frustum[3]));
  186.     corners.push_back(PlaneIntersection(frustum[4], frustum[1], frustum[3]));
  187.     corners.push_back(PlaneIntersection(frustum[4], frustum[1], frustum[2]));
  188.     corners.push_back(PlaneIntersection(frustum[5], frustum[1], frustum[2]));
  189.     corners.push_back(PlaneIntersection(frustum[5], frustum[1], frustum[3]));
  190.     corners.push_back(PlaneIntersection(frustum[5], frustum[0], frustum[3]));
  191.     corners.push_back(PlaneIntersection(frustum[5], frustum[0], frustum[2]));
  192.     return corners;
  193. }
  194.  
  195. glm::vec3 PlaneIntersection(const Plane& p1, const Plane& p2, const Plane& p3) {
  196.     // Calculate the determinant of the matrix (i.e | n1 n2 n3 |).
  197.     float det = p1.x * (p2.y * p3.z -
  198.                 p2.z * p3.y) - p2.x *(p1.y * p3.z -
  199.                 p1.z * p3.y) + p3.x * (p1.y * p2.z - p1.z * p2.y);
  200.     // If the determinant is zero, then the planes do not all intersect.
  201.     if (fabs(det) <= 0.0001f)
  202.         return glm::vec3();
  203.     // Create 3 points, one on each plane.
  204.     float p1x = -p1.x * p1.w;
  205.     float p1y = -p1.y * p1.w;
  206.     float p1z = -p1.z * p1.w;
  207.     float p2x = -p2.x * p2.w;
  208.     float p2y = -p2.y * p2.w;
  209.     float p2z = -p2.z * p2.w;
  210.     float p3x = -p3.x * p3.w;
  211.     float p3y = -p3.y * p3.w;
  212.     float p3z = -p3.z * p3.w;
  213.     // Calculate the cross products of the normals.
  214.     float c1x = (p2.y * p3.z) - (p2.z * p3.y);
  215.     float c1y = (p2.z * p3.x) - (p2.x * p3.z);
  216.     float c1z = (p2.x * p3.y) - (p2.y * p3.x);
  217.     float c2x = (p3.y * p1.z) - (p3.z * p1.y);
  218.     float c2y = (p3.z * p1.x) - (p3.x * p1.z);
  219.     float c2z = (p3.x * p1.y) - (p3.y * p1.x);
  220.     float c3x = (p1.y * p2.z) - (p1.z * p2.y);
  221.     float c3y = (p1.z * p2.x) - (p1.x * p2.z);
  222.     float c3z = (p1.x * p2.y) - (p1.y * p2.x);
  223.     // Calculate the point of intersection using the formula:
  224.     // x = (| n1 n2 n3 |)^-1 * [(x1 * n1)(n2 x n3) + (x2 * n2)(n3 x n1) + (x3 * n3)(n1 x n2)]
  225.     float s1 = p1x * p1.x + p1y * p1.y + p1z * p1.z;
  226.     float s2 = p2x * p2.x + p2y * p2.y + p2z * p2.z;
  227.     float s3 = p3x * p3.x + p3y * p3.y + p3z * p3.z;
  228.     float detI = 1.0f / det;
  229.    
  230.     glm::vec3 point;
  231.     point.x = (s1 * c1x + s2 * c2x + s3 * c3x) * detI;
  232.     point.y = (s1 * c1y + s2 * c2y + s3 * c3y) * detI;
  233.     point.z = (s1 * c1z + s2 * c2z + s3 * c3z) * detI;
  234.     return point;
  235. }
  236.  
  237. Frustum ExtractFrustum(const glm::mat4& source) {
  238.     const float* matrix = glm::value_ptr(source);
  239.     Frustum result;
  240.     result.resize(6);
  241.  
  242.     // Left clipping plane
  243.     result[0].x = matrix[3] + matrix[0];
  244.     result[0].y = matrix[7] + matrix[4];
  245.     result[0].z = matrix[11] + matrix[8];
  246.     result[0].w = matrix[15] + matrix[12];
  247.    
  248.     // Right clipping plane
  249.     result[1].x = matrix[3] - matrix[0];
  250.     result[1].y = matrix[7] - matrix[4];
  251.     result[1].z = matrix[11] - matrix[8];
  252.     result[1].w = matrix[15] - matrix[12];
  253.    
  254.     // Top clipping plane
  255.     result[2].x = matrix[3] - matrix[1];
  256.     result[2].y = matrix[7] - matrix[5];
  257.     result[2].z = matrix[11] - matrix[9];
  258.     result[2].w = matrix[15] - matrix[13];
  259.    
  260.     // Bottom clipping plane
  261.     result[3].x = matrix[3] + matrix[1];
  262.     result[3].y = matrix[7] + matrix[5];
  263.     result[3].z = matrix[11] + matrix[9];
  264.     result[3].w = matrix[15] + matrix[13];
  265.    
  266.     // Near clipping plane
  267.     result[4].x = matrix[3] + matrix[2];
  268.     result[4].y = matrix[7] + matrix[6];
  269.     result[4].z = matrix[11] + matrix[10];
  270.     result[4].w = matrix[15] + matrix[14];
  271.    
  272.     // Far clipping plane
  273.     result[5].x = matrix[3] - matrix[2];
  274.     result[5].y = matrix[7] - matrix[6];
  275.     result[5].z = matrix[11] - matrix[10];
  276.     result[5].w = matrix[15] - matrix[14];
  277.    
  278.     for (int i = 0; i < 6; ++i) {
  279.         float mag = sqrtf(result[i].x * result[i].x + result[i].y * result[i].y + result[i].z * result[i].z);
  280.         result[i].x /= mag;
  281.         result[i].y /= mag;
  282.         result[i].z /= mag;
  283.         result[i].w /= mag;
  284.     }
  285.  
  286.     return result;
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement