| 36 | } |
| 37 | |
| 38 | void TriFrustum::ExtractFrustum( const Matrix* proj ) |
| 39 | { /** |
| 40 | proj - The projection matrix to extract a frustum from. |
| 41 | */ |
| 42 | #ifdef TRINITYDEV |
| 43 | if( m_frustumTestCounter != 0 ) |
| 44 | m_frustumCullingRatio = (float)m_frustumRejectionCounter / (float)m_frustumTestCounter; |
| 45 | m_frustumRejectionCounter = 0; |
| 46 | m_frustumTestCounter = 0; |
| 47 | #endif |
| 48 | // Frustum Extraction |
| 49 | // This is actually very simple when you understand all the components of the projection matrix. |
| 50 | // dRatio = far/(far - near ) |
| 51 | // Columns |
| 52 | // X->( (1/tan(fov/2))/aspectratio, 0, 0 ). You need to scale all the input values by the 1/tan, because when the 'fov' changes you want to see more. |
| 53 | // We also want to make sure that the values are not stretched when the screen is not a perfect square. That is why |
| 54 | // we like to scale the x values by the 1/aspectRatio. |
| 55 | // Y->( 0 1/tan(fov/2), 0 ) The Y values need scaling to, but they do not have to be changed by the aspect ratio because the aspect ratio is a scale relating the |
| 56 | // size of 'Y' to x values. x/Y. |
| 57 | // |
| 58 | // Z->( 0, 0, dRatio, -near*dRatio ) The depth values get mapped to the z-buffer between the ranges of 0.0 - 1.0. To ensure that no values get divided by zero |
| 59 | // we use the near plane and store the actual z value in the w member of the output vector. No value get projected to 2D space before |
| 60 | // the z-buffer test, so the projection matrix does not project anything. It basically just scales the values so they can be projected |
| 61 | // in a simple homogeneous fashion, x/w, y/w, z/w by a frustum with a 90 degree fov. |
| 62 | // To map the depth values correctly to the z-buffer and make sure we don't divide by zero we subtract the near plane from the z-value, so |
| 63 | // if the z-value was behind the near plane the sign of the value would switch. Then we need to scale it back to where it was to get the |
| 64 | // correct z-buffer value. We want all our values to be mapped correctly between 0.0 - 1.0 where 0.0 is our near plane and 1.0 is our far plane. |
| 65 | // So we can't just subtract the nearplane then divide that by the distance between the near and far plane, because than the depth values that |
| 66 | // would lie on or behind the farplane(by distance equal to the nearplane) would get drawn. So the value we need to scale the value back into place |
| 67 | // after we have subtracted the nearplane is the ratio between the distance to the farplane and the distance between the near and far plane. |
| 68 | // *)dRatio = farplane/ (farplane - nearplane ) |
| 69 | // *)zbuffer = z - nearplane*dRatio |
| 70 | // We can split this formula up in the projection matrix to correctly store the z-buffer information in the z member of the output vector. |
| 71 | // z-nearplane*dRatio = z*dRation - nearplane*dRatio. As you can see in the third column of the projection matrix, and given that the input vector |
| 72 | // is homogeneous with a w=1.0. |
| 73 | // |
| 74 | // W->( 0, 0, 1.0, 0 ) All this does is copy the depth value to the w member of the output vector. |
| 75 | // |
| 76 | // So to extract the frustums we only need to add and subtract column vectors to get the normals. |
| 77 | |
| 78 | // front |
| 79 | // The normal of the near plane is the same as the w-component in the projection matrix |
| 80 | m_planes[PLANE_FRONT].a = ( proj->_13 ); |
| 81 | m_planes[PLANE_FRONT].b = ( proj->_23 ); |
| 82 | m_planes[PLANE_FRONT].c = ( proj->_33 ); |
| 83 | m_planes[PLANE_FRONT].d = ( proj->_43 ); // This will produce the correct number when it is divided by the length of the normal |
| 84 | //left |
| 85 | m_planes[PLANE_LEFT].a = ( proj->_14 + proj->_11 ); |
| 86 | m_planes[PLANE_LEFT].b = ( proj->_24 + proj->_21 ); |
| 87 | m_planes[PLANE_LEFT].c = ( proj->_34 + proj->_31 ); |
| 88 | m_planes[PLANE_LEFT].d = ( proj->_44 + proj->_41 ); |
| 89 | //top |
| 90 | m_planes[PLANE_TOP].a = ( proj->_14 - proj->_12 ); |
| 91 | m_planes[PLANE_TOP].b = ( proj->_24 - proj->_22 ); |
| 92 | m_planes[PLANE_TOP].c = ( proj->_34 - proj->_32 ); |
| 93 | m_planes[PLANE_TOP].d = ( proj->_44 - proj->_42 ); |
| 94 | //right |
| 95 | m_planes[PLANE_RIGHT].a = ( proj->_14 - proj->_11 ); |
no outgoing calls
no test coverage detected