#pragma once #include "vec.h" #include "mat.h" namespace cgv { namespace math { ///creates a 3x3 scale matrix template const mat scale_33(const T &sx, const T &sy, const T &sz) { mat m(3, 3); m(0, 0) = sx; m(0, 1) = 0; m(0, 2) = 0; m(1, 0) = 0; m(1, 1) = sy; m(1, 2) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = sz; return m; } ///creates a 3x3 uniform scale matrix template const mat scale_33(const T &s) { mat m(3, 3); m(0, 0) = s; m(0, 1) = 0; m(0, 2) = 0; m(1, 0) = 0; m(1, 1) = s; m(1, 2) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = s; return m; } ///creates a 3x3 rotation matrix around the x axis, the angle is in degree template const mat rotatex_33(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(3, 3); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(1, 0) = 0; m(1, 1) = (T)cos((double)angler); m(1, 2) = -(T)sin((double)angler); m(2, 0) = 0; m(2, 1) = (T)sin((double)angler); m(2, 2) = (T)cos((double)angler); return m; } ///creates a 3x3 rotation matrix around the y axis, the angle is in degree template const mat rotatey_33(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(3, 3); m(0, 0) = (T)cos((double)angler); m(0, 1) = 0; m(0, 2) = (T)sin((double)angler); m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(2, 0) = -(T)sin((double)angler); m(2, 1) = 0; m(2, 2) = (T)cos((double)angler); return m; } ///creates a 3x3 rotation matrix around the z axis, the angle is in degree template const mat rotatez_33(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(3, 3); m(0, 0) = (T)cos((double)angler); m(0, 1) = -(T)sin((double)angler); m(0, 2) = 0; m(1, 0) = (T)sin((double)angler); m(1, 1) = (T)cos((double)angler); m(1, 2) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; return m; } ///creates a 2x2 rotation matrix around the z axis, the angle is in degree template const mat rotate_22(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(2, 2); m(0, 0) = (T)cos((double)angler); m(0, 1) = -(T)sin((double)angler); m(1, 0) = (T)sin((double)angler); m(1, 1) = (T)cos((double)angler); return m; } template const mat rotate_33(const T &dirx, const T &diry, const T &dirz, const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(3, 3); T rcos = cos(angler); T rsin = sin(angler); m(0, 0) = rcos + dirx * dirx * ((T)1 - rcos); m(0, 1) = -dirz * rsin + diry * dirx * ((T)1 - rcos); m(0, 2) = diry * rsin + dirz * dirx * ((T)1 - rcos); m(1, 0) = dirz * rsin + dirx * diry * ((T)1 - rcos); m(1, 1) = rcos + diry * diry * ((T)1 - rcos); m(1, 2) = -dirx * rsin + dirz * diry * ((T)1 - rcos); m(2, 0) = -diry * rsin + dirx * dirz * ((T)1 - rcos); m(2, 1) = dirx * rsin + diry * dirz * ((T)1 - rcos); m(2, 2) = rcos + dirz * dirz * ((T)1 - rcos); return m; } ///creates a 3x3 euler rotation matrix from yaw, pitch and roll given in degree template const mat rotate_euler_33(const T &yaw, const T &pitch, const T &roll) { T yawd = (T)(yaw * 3.14159 / 180.0); T pitchd = (T)(pitch * 3.14159 / 180.0); T rolld = (T)(roll * 3.14159 / 180.0); T cosy = (T)cos(yawd); T siny = (T)sin(yawd); T cosp = (T)cos(pitchd); T sinp = (T)sin(pitchd); T cosr = (T)cos(rolld); T sinr = (T)sin(rolld); mat m(3, 3); m(0, 0) = cosr * cosy - sinr * sinp * siny; m(0, 1) = -sinr * cosp; m(0, 2) = cosr * siny + sinr * sinp * cosy; m(1, 0) = sinr * cosy + cosr * sinp * siny; m(1, 1) = cosr * cosp; m(1, 2) = sinr * siny - cosr * sinp * cosy; m(2, 0) = -cosp * siny; m(2, 1) = sinp; m(2, 2) = cosp * cosy; return m; } template const mat star(const vec &v) { mat m(3, 3); m(0, 0) = 0; m(0, 1) = -v(2); m(0, 2) = v(1); m(1, 0) = v(2); m(1, 1) = 0; m(1, 2) = -v(0); m(2, 0) = -v(1); m(2, 1) = v(0); m(2, 2) = 0; return m; } ///creates a 3x3 rotation matrix from a rodrigues vector template const mat rotate_rodrigues_33(const vec &r) { T theta = length(r); if (theta == 0) return identity(3); vec rn = r / theta; T cos_theta = cos(theta); T sin_theta = sin(theta); return cos_theta * identity(3) + ((T)1 - cos_theta) * dyad(rn, rn) + sin_theta * star(rn); } template const mat rotate_rodrigues_33(const T &rx, const T &ry, const T &rz) { vec r(3); r(0) = rx; r(1) = ry; r(2) = rz; return rotate_rodrigues_33(r); } ///creates a homogen 3x3 shear matrix with given shears shx in x direction, and shy in y direction template const mat shearxy_33(const T &shx, const T ­) { mat m(3, 3); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = shx; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = shy; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; return m; } ///creates a homogen 3x3 shear matrix with given shears shx in x direction, and shy in y direction template const mat shearxz_33(const T &shx, const T &shz) { mat m(3, 3); m(0, 0) = 1; m(0, 1) = shx; m(0, 2) = 0; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(2, 0) = 0; m(2, 1) = shz; m(2, 2) = 1; return m; } ///creates a homogen 3x3 shear matrix with given shears shy in y direction, and shz in z direction template const mat shearyz_33(const T ­, const T &shz) { mat m(3, 3); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(1, 0) = shy; m(1, 1) = 1; m(1, 2) = 0; m(2, 0) = shz; m(2, 1) = 0; m(2, 2) = 1; return m; } ///creates a homogen 3x3 shear matrix template const mat shear_33(const T &syx, const T &szx, const T &sxy, const T &szy, const T &sxz, const T &syz) { mat m(3, 3); m(0, 0) = 1; m(0, 1) = syx; m(0, 2) = szx; m(1, 0) = sxy; m(1, 1) = 1; m(1, 2) = szy; m(2, 0) = sxz; m(2, 1) = syz; m(2, 2) = 1; return m; } ///creates a 4x4 translation matrix template const mat translate_44(const T &x, const T &y, const T &z) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = x; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(1, 3) = y; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = z; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a 4x4 translation matrix template const mat translate_44(const vec &v) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = v(0); m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(1, 3) = v(1); m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = v(2); m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a 4x4 scale matrix template const mat scale_44(const T &sx, const T &sy, const T &sz) { mat m(4, 4); m(0, 0) = sx; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = sy; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = sz; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } template const mat scale_44(const cgv::math::vec s) { assert(s.size() == 3); return scale_44(s(0), s(1), s(2)); } ///creates a 4x4 uniform scale matrix template const mat scale_44(const T &s) { mat m(4, 4); m(0, 0) = s; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = s; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = s; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a 4x4 rotation matrix around the x axis, the angle is in degree template const mat rotatex_44(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(4, 4); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = (T)cos((double)angler); m(1, 2) = -(T)sin((double)angler); m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = (T)sin((double)angler); m(2, 2) = (T)cos((double)angler); m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a 4x4 rotation matrix around the y axis, the angle is in degree template const mat rotatey_44(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(4, 4); m(0, 0) = (T)cos((double)angler); m(0, 1) = 0; m(0, 2) = (T)sin((double)angler); m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = -(T)sin((double)angler); m(2, 1) = 0; m(2, 2) = (T)cos((double)angler); m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a 4x4 rotation matrix around the z axis, the angle is in degree template const mat rotatez_44(const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(4, 4); m(0, 0) = (T)cos((double)angler); m(0, 1) = -(T)sin((double)angler); m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = (T)sin((double)angler); m(1, 1) = (T)cos((double)angler); m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } template const mat rotate_44(const T &dirx, const T &diry, const T &dirz, const T &angle) { T angler = angle * (T)3.14159 / (T)180.0; mat m(4, 4); T rcos = cos(angler); T rsin = sin(angler); m(0, 0) = rcos + dirx * dirx * ((T)1 - rcos); m(0, 1) = -dirz * rsin + diry * dirx * ((T)1 - rcos); m(0, 2) = diry * rsin + dirz * dirx * ((T)1 - rcos); m(1, 0) = dirz * rsin + dirx * diry * ((T)1 - rcos); m(1, 1) = rcos + diry * diry * ((T)1 - rcos); m(1, 2) = -dirx * rsin + dirz * diry * ((T)1 - rcos); m(2, 0) = -diry * rsin + dirx * dirz * ((T)1 - rcos); m(2, 1) = dirx * rsin + diry * dirz * ((T)1 - rcos); m(2, 2) = rcos + dirz * dirz * ((T)1 - rcos); m(3, 0) = (T)0; m(3, 1) = (T)0; m(3, 2) = (T)0; m(0, 3) = (T)0; m(1, 3) = (T)0; m(2, 3) = (T)0; m(3, 3) = (T)1; return m; } template const mat rotate_33(const cgv::math::vec &dir, const T &angle) { assert(dir.size() == 3); cgv::math::vec vdir = dir; vdir.normalize(); return rotate_33(vdir(0), vdir(1), vdir(2), angle); } template const mat rotate_44(const cgv::math::vec &dir, const T &angle) { assert(dir.size() == 3); cgv::math::vec vdir = dir; vdir.normalize(); return rotate_44(vdir(0), vdir(1), vdir(2), angle); } ///creates a 4x4 euler rotation matrix from yaw, pitch and roll given in degree template const mat rotate_euler_44(const T &yaw, const T &pitch, const T &roll) { T yawd = yaw * 3.14159 / 180.0; T pitchd = pitch * 3.14159 / 180.0; T rolld = roll * 3.14159 / 180.0; T cosy = (T)cos(yawd); T siny = (T)sin(yawd); T cosp = (T)cos(pitchd); T sinp = (T)sin(pitchd); T cosr = (T)cos(rolld); T sinr = (T)sin(rolld); mat m(4, 4); m(0, 0) = cosr * cosy - sinr * sinp * siny; m(0, 1) = -sinr * cosp; m(0, 2) = cosr * siny + sinr * sinp * cosy; m(0, 3) = 0; m(1, 0) = sinr * cosy + cosr * sinp * siny; m(1, 1) = cosr * cosp; m(1, 2) = sinr * siny - cosr * sinp * cosy; m(1, 3) = 0; m(2, 0) = -cosp * siny; m(2, 1) = sinp; m(2, 2) = cosp * cosy; m(2, 3) = 0; m(3, 0) = m(3, 1) = m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a homogen 4x4 shear matrix with given shears shx in x direction, and shy in y direction template const mat shearxy_44(const T &shx, const T ­) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = shx; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = shy; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a homogen 4x4 shear matrix with given shears shx in x direction, and shy in y direction template const mat shearxz_44(const T &shx, const T &shz) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = shx; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = 1; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = shz; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a homogen 4x4 shear matrix with given shears shy in y direction, and shz in z direction template const mat shearyz_44(const T ­, const T &shz) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = shy; m(1, 1) = 1; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = shz; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a homogen 4x4 shear matrix template const mat shear_44(const T &syx, const T &szx, const T &sxy, const T &szy, const T &sxz, const T &syz) { mat m(4, 4); m(0, 0) = 1; m(0, 1) = syx; m(0, 2) = szx; m(0, 3) = 0; m(1, 0) = sxy; m(1, 1) = 1; m(1, 2) = szy; m(1, 3) = 0; m(2, 0) = sxz; m(2, 1) = syz; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a perspective transformation matrix in the same way as gluPerspective does template const mat perspective_44(const T &fovy, const T &aspect, const T &znear, const T &zfar) { T fovyr = (T)(fovy * 3.14159 / 180.0); T f = (T)(cos(fovyr / 2.0f) / sin(fovyr / 2.0f)); mat m(4, 4); m(0, 0) = f / aspect; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = f; m(1, 2) = 0; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = (zfar + znear) / (znear - zfar); m(2, 3) = (2 * zfar * znear) / (znear - zfar); m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = -1; m(3, 3) = 0; return m; } ///creates a viewport transformation matrix template mat viewport_44(const T &xoff, const T yoff, const T &width, const T &height) { mat m(4, 4); T a = width / (T)2.0; T b = height / (T)2.0; m(0, 0) = a; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = xoff + (T)0.5; m(1, 0) = 0; m(1, 1) = b; m(1, 2) = 0; m(1, 3) = yoff + (T)0.5; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = (T)0.5; m(2, 3) = (T)0.5; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates a look at transformation matrix in the same way as gluLookAt does template const mat look_at_44(const T &eyex, const T &eyey, const T &eyez, const T ¢erx, const T ¢ery, const T ¢erz, const T &upx, const T &upy, const T &upz) { vec center(centerx, centery, centerz); vec eye(eyex, eyey, eyez); vec up(upx, upy, upz); vec f = normalize(center - eye); up = normalize(up); vec s = normalize(cross(f, up)); vec u = normalize(cross(s, f)); mat m(4, 4); m(0, 0) = s(0); m(0, 1) = s(1); m(0, 2) = s(2); m(0, 3) = 0; m(1, 0) = u(0); m(1, 1) = u(1); m(1, 2) = u(2); m(1, 3) = 0; m(2, 0) = -f(0); m(2, 1) = -f(1); m(2, 2) = -f(2); m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; m = m * translate_44(-eyex, -eyey, -eyez); return m; } template const mat look_at_44(vec eye, vec center, vec up) { vec f = normalize(center - eye); up = normalize(up); vec s = normalize(cross(f, up)); vec u = normalize(cross(s, f)); mat m(4, 4); m(0, 0) = s(0); m(0, 1) = s(1); m(0, 2) = s(2); m(0, 3) = 0; m(1, 0) = u(0); m(1, 1) = u(1); m(1, 2) = u(2); m(1, 3) = 0; m(2, 0) = -f(0); m(2, 1) = -f(1); m(2, 2) = -f(2); m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; m = m * translate_44(-eye); return m; } ///creates a frustrum projection matrix in the same way as glFrustum does template const mat frustrum_44(const T &left, const T &right, const T &bottom, const T &top, const T &znear, const T &zfar) { T e = 2 * znear / (right - left); T f = 2 * znear / (top - bottom); T A = (right + left) / (right - left); T B = (top + bottom) / (top - bottom); T C = -(zfar + znear) / (zfar - znear); T D = -(2 * zfar * znear) / (zfar - znear); mat m(4, 4); m(0, 0) = e; m(0, 1) = 0; m(0, 2) = A; m(0, 3) = 0; m(1, 0) = 0; m(1, 1) = f; m(1, 2) = B; m(1, 3) = 0; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = C; m(2, 3) = D; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = -1; m(3, 3) = 0; return m; } ///creates an orthographic projection matrix in the same way as glOrtho does template const mat ortho_44(const T &left, const T &right, const T &bottom, const T &top, const T &znear, const T &zfar) { T a = 2 / (right - left); T b = 2 / (top - bottom); T c = -2 / (zfar - znear); T tx = (right + left) / (right - left); T ty = (top + bottom) / (top - bottom); T tz = (zfar + znear) / (zfar - znear); mat m(4, 4); m(0, 0) = a; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = -tx; m(1, 0) = 0; m(1, 1) = b; m(1, 2) = 0; m(1, 3) = -ty; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = c; m(2, 3) = -tz; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m; } ///creates an orthographic projection matrix in the same way as glOrtho2d does template const mat ortho2d_44(const T &left, const T &right, const T &bottom, const T &top) { return ortho_44(left, right, bottom, top, (T)-1.0, (T)1.0); } ///creates a picking matrix like gluPickMatrix with pixel (0,0) in the lower left corner if flipy=false template const mat pick_44(const T &x, const T &y, const T &width, const T &height, int viewport[4], const mat &modelviewproj, bool flipy = true) { mat m(4, 4); T sx, sy; T tx, ty; sx = viewport[2] / width; sy = viewport[3] / height; tx = (T)(viewport[2] + 2.0 * (viewport[0] - x)) / width; if (flipy) ty = (T)(viewport[3] + 2.0 * (viewport[1] - (viewport[3] - y))) / height; else ty = (T)(viewport[3] + 2.0 * (viewport[1] - y)) / height; m(0, 0) = sx; m(0, 1) = 0; m(0, 2) = 0; m(0, 3) = tx; m(1, 0) = 0; m(1, 1) = sy; m(1, 2) = 0; m(1, 3) = ty; m(2, 0) = 0; m(2, 1) = 0; m(2, 2) = 1; m(2, 3) = 0; m(3, 0) = 0; m(3, 1) = 0; m(3, 2) = 0; m(3, 3) = 1; return m * modelviewproj; } //extract rotation angles from combined rotation matrix template void decompose_R_2_RxRyRz(const mat &R33, T &angle_x, T &angle_y, T &angle_z) { angle_y = asin(R33(0, 2)); /* Calculate Y-axis angle */ T C = cos(angle_y); T trx, atry; angle_y *= (T)(180 / 3.14159); if (std::abs(C) > (T)0.005) /* Gimbal lock? */ { trx = R33(2, 2) / C; /* No, so get X-axis angle */ atry = -R33(1, 2) / C; angle_x = atan2(atry, trx) * (T)(180 / 3.14159); trx = R33(0, 0) / C; /* Get Z-axis angle */ atry = -R33(0, 1) / C; angle_z = atan2(atry, trx) * (T)(180 / 3.14159); } else /* Gimbal lock has occurred */ { angle_x = 0; /* Set X-axis angle to zero */ trx = R33(1, 1); /* And calculate Z-axis angle */ atry = R33(1, 0); angle_z = atan2(atry, trx) * (T)(180 / 3.14159); } /* return only positive angles in [0,360] */ if (angle_x < 0) angle_x += (T)360; if (angle_y < 0) angle_y += (T)360; if (angle_z < 0) angle_z += (T)360; //std::cout << angle_x << " "<< angle_y << " " < const mat extract_frustrum_planes(const mat &modelviewprojection) { mat frustrum_planes(4, 6); frustrum_planes.set_col(0, modelviewprojection.row(3) - modelviewprojection.row(0)); //right frustrum_planes.set_col(1, modelviewprojection.row(3) + modelviewprojection.row(0)); //left frustrum_planes.set_col(2, modelviewprojection.row(3) - modelviewprojection.row(1)); //top frustrum_planes.set_col(3, modelviewprojection.row(3) + modelviewprojection.row(1)); //bottom frustrum_planes.set_col(4, modelviewprojection.row(3) - modelviewprojection.row(2)); //far frustrum_planes.set_col(5, modelviewprojection.row(3) + modelviewprojection.row(2)); //near // Normalize all planes for (unsigned i = 0; i < 6; i++) frustrum_planes.set_col(i, frustrum_planes.col(i) / length(frustrum_planes.col(i).sub_vec(0, 3))); return frustrum_planes; } } // namespace math } // namespace cgv