1 // 2 // frustum.h 3 // CubicVR2 4 // 5 // Created by Charles J. Cliffe on 2013-02-22. 6 // Copyright (c) 2013 Charles J. Cliffe. All rights reserved. 7 // 8 9 #ifndef CubicVR2_frustum_h 10 #define CubicVR2_frustum_h 11 12 #include <vector> 13 #include "cubic_types.h" 14 #include "mat4.h" 15 #include "vec3.h" 16 #include "vec4.h" 17 #include "plane.h" 18 19 namespace CubicVR { 20 21 enum frustum_plane { PLANE_LEFT, PLANE_RIGHT, PLANE_TOP, PLANE_BOTTOM, PLANE_NEAR, PLANE_FAR }; 22 23 struct frustum { 24 std::vector<vec4> planes; 25 vec4 sphere; 26 frustumfrustum27 frustum() { 28 planes.resize(6); 29 for (int i = 0; i < 6; ++i) { 30 planes[i] = vec4(0, 0, 0, 0); 31 } //for 32 } //Frustum::Constructor 33 extractfrustum34 void extract(vec3 position, mat4 mvMatrix, mat4 pMatrix) { 35 mat4 comboMatrix = mat4::multiply(pMatrix, mvMatrix, true); 36 37 // Left clipping plane 38 planes[PLANE_LEFT][0] = comboMatrix[3] + comboMatrix[0]; 39 planes[PLANE_LEFT][1] = comboMatrix[7] + comboMatrix[4]; 40 planes[PLANE_LEFT][2] = comboMatrix[11] + comboMatrix[8]; 41 planes[PLANE_LEFT][3] = comboMatrix[15] + comboMatrix[12]; 42 43 // Right clipping plane 44 planes[PLANE_RIGHT][0] = comboMatrix[3] - comboMatrix[0]; 45 planes[PLANE_RIGHT][1] = comboMatrix[7] - comboMatrix[4]; 46 planes[PLANE_RIGHT][2] = comboMatrix[11] - comboMatrix[8]; 47 planes[PLANE_RIGHT][3] = comboMatrix[15] - comboMatrix[12]; 48 49 // Top clipping plane 50 planes[PLANE_TOP][0] = comboMatrix[3] - comboMatrix[1]; 51 planes[PLANE_TOP][1] = comboMatrix[7] - comboMatrix[5]; 52 planes[PLANE_TOP][2] = comboMatrix[11] - comboMatrix[9]; 53 planes[PLANE_TOP][3] = comboMatrix[15] - comboMatrix[13]; 54 55 // Bottom clipping plane 56 planes[PLANE_BOTTOM][0] = comboMatrix[3] + comboMatrix[1]; 57 planes[PLANE_BOTTOM][1] = comboMatrix[7] + comboMatrix[5]; 58 planes[PLANE_BOTTOM][2] = comboMatrix[11] + comboMatrix[9]; 59 planes[PLANE_BOTTOM][3] = comboMatrix[15] + comboMatrix[13]; 60 61 // Near clipping plane 62 planes[PLANE_NEAR][0] = comboMatrix[3] + comboMatrix[2]; 63 planes[PLANE_NEAR][1] = comboMatrix[7] + comboMatrix[6]; 64 planes[PLANE_NEAR][2] = comboMatrix[11] + comboMatrix[10]; 65 planes[PLANE_NEAR][3] = comboMatrix[15] + comboMatrix[14]; 66 67 // Far clipping plane 68 planes[PLANE_FAR][0] = comboMatrix[3] - comboMatrix[2]; 69 planes[PLANE_FAR][1] = comboMatrix[7] - comboMatrix[6]; 70 planes[PLANE_FAR][2] = comboMatrix[11] - comboMatrix[10]; 71 planes[PLANE_FAR][3] = comboMatrix[15] - comboMatrix[14]; 72 73 for (unsigned int i = 0; i < 6; ++i) { 74 planes[i] = vec4::normalize(planes[i]); 75 } 76 77 //Sphere 78 __float fov = 1 / pMatrix[5]; 79 __float znear = -planes[PLANE_NEAR][3]; 80 __float zfar = planes[PLANE_FAR][3]; 81 __float view_length = zfar - znear; 82 __float height = view_length * fov; 83 __float width = height; 84 85 vec3 P(0, 0, znear + view_length * 0.5f); 86 vec3 Q(width, height, znear + view_length); 87 vec3 diff = vec3::subtract(P, Q); 88 __float diff_mag = vec3::length(diff); 89 90 vec3 look_v = vec3(comboMatrix[3], comboMatrix[9], comboMatrix[10]); 91 __float look_mag = vec3::length(look_v); 92 look_v = vec3::multiply(look_v, 1 / look_mag); 93 94 vec3 pos = vec3(position[0], position[1], position[2]); 95 pos = vec3::add(pos, vec3::multiply(look_v, view_length * 0.5f)); 96 pos = vec3::add(pos, vec3::multiply(look_v, 1)); 97 98 sphere = vec4(pos[0], pos[1], pos[2], diff_mag); 99 100 }; //Frustum::extract 101 contains_spherefrustum102 int contains_sphere(vec4 sphere) { 103 104 for (unsigned int i = 0; i < 6; ++i) { 105 vec4 &p = planes[i]; 106 vec3 normal = vec3(p[0], p[1], p[2]); 107 __float distance = vec3::dot(normal, vec3(sphere[0],sphere[1],sphere[2])) + p[3]; 108 109 //OUT 110 if (distance < -sphere[3]) { 111 return -1; 112 } 113 114 //INTERSECT 115 if (fabs(distance) < sphere[3]) { 116 return 0; 117 } 118 119 } //for 120 //IN 121 return 1; 122 }; //Frustum::contains_sphere 123 contains_boxfrustum124 int contains_box(aabb bbox) { 125 int total_in = 0; 126 127 vec3 points[8]; 128 129 points[0] = bbox.min; 130 points[1] = vec3(bbox.min[0], bbox.min[1], bbox.max[2]); 131 points[2] = vec3(bbox.min[0], bbox.max[1], bbox.min[2]); 132 points[3] = vec3(bbox.min[0], bbox.max[1], bbox.max[2]); 133 points[4] = vec3(bbox.max[0], bbox.min[1], bbox.min[2]); 134 points[5] = vec3(bbox.max[0], bbox.min[1], bbox.max[2]); 135 points[6] = vec3(bbox.max[0], bbox.max[1], bbox.min[2]); 136 points[7] = bbox.max; 137 138 for (unsigned int i = 0; i < 6; ++i) { 139 unsigned int in_count = 8; 140 unsigned int point_in = 1; 141 142 for (unsigned int j = 0; j < 8; ++j) { 143 if (plane::classifyPoint(planes[i], points[j]) == -1) { 144 point_in = 0; 145 --in_count; 146 } //if 147 } //for j 148 149 //OUT 150 if (in_count == 0) { 151 return -1; 152 } 153 154 total_in += point_in; 155 } //for i 156 //IN 157 if (total_in == 6) { 158 return 1; 159 } 160 161 return 0; 162 }; //Frustum::contains_box 163 164 }; 165 } 166 167 #endif 168