/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined( INCLUDED_VIEW_H ) #define INCLUDED_VIEW_H #include "cullable.h" #include "math/frustum.h" #if defined( _DEBUG ) #define DEBUG_CULLING #endif #if defined( DEBUG_CULLING ) extern int g_count_dots; extern int g_count_planes; extern int g_count_oriented_planes; extern int g_count_bboxs; extern int g_count_oriented_bboxs; #endif inline void debug_count_dot(){ #if defined( DEBUG_CULLING ) ++g_count_dots; #endif } inline void debug_count_plane(){ #if defined( DEBUG_CULLING ) ++g_count_planes; #endif } inline void debug_count_oriented_plane(){ #if defined( DEBUG_CULLING ) ++g_count_oriented_planes; #endif } inline void debug_count_bbox(){ #if defined( DEBUG_CULLING ) ++g_count_bboxs; #endif } inline void debug_count_oriented_bbox(){ #if defined( DEBUG_CULLING ) ++g_count_oriented_bboxs; #endif } /// \brief View-volume culling and transformations. class View : public VolumeTest { /// modelview matrix Matrix4 m_modelview; /// projection matrix Matrix4 m_projection; /// device-to-screen transform Matrix4 m_viewport; Matrix4 m_scissor; /// combined modelview and projection matrix Matrix4 m_viewproj; /// camera position in world space Vector4 m_viewer; /// view frustum in world space Frustum m_frustum; bool m_fill; void construct(){ m_viewproj = matrix4_multiplied_by_matrix4( matrix4_multiplied_by_matrix4( m_scissor, m_projection ), m_modelview ); m_frustum = frustum_from_viewproj( m_viewproj ); m_viewer = viewer_from_viewproj( m_viewproj ); } public: View( bool fill = false ) : m_modelview( g_matrix4_identity ), m_projection( g_matrix4_identity ), m_scissor( g_matrix4_identity ), m_fill( fill ){ } void Construct( const Matrix4& projection, const Matrix4& modelview, std::size_t width, std::size_t height ){ // modelview m_modelview = modelview; // projection m_projection = projection; // viewport m_viewport = g_matrix4_identity; m_viewport[0] = float(width / 2); m_viewport[5] = float(height / 2); if ( fabs( m_projection[11] ) > 0.0000001 ) { m_viewport[10] = m_projection[0] * m_viewport[0]; } else{ m_viewport[10] = 1 / m_projection[10]; } construct(); } void EnableScissor( float min_x, float max_x, float min_y, float max_y ){ m_scissor = g_matrix4_identity; m_scissor[0] = static_cast( ( max_x - min_x ) * 0.5 ); m_scissor[5] = static_cast( ( max_y - min_y ) * 0.5 ); m_scissor[12] = static_cast( ( min_x + max_x ) * 0.5 ); m_scissor[13] = static_cast( ( min_y + max_y ) * 0.5 ); matrix4_full_invert( m_scissor ); construct(); } void DisableScissor(){ m_scissor = g_matrix4_identity; construct(); } bool TestPoint( const Vector3& point ) const { return viewproj_test_point( m_viewproj, point ); } bool TestLine( const Segment& segment ) const { return frustum_test_line( m_frustum, segment ); } bool TestPlane( const Plane3& plane ) const { debug_count_plane(); return viewer_test_plane( m_viewer, plane ); } bool TestPlane( const Plane3& plane, const Matrix4& localToWorld ) const { debug_count_oriented_plane(); return viewer_test_transformed_plane( m_viewer, plane, localToWorld ); } VolumeIntersectionValue TestAABB( const AABB& aabb ) const { debug_count_bbox(); return frustum_test_aabb( m_frustum, aabb ); } VolumeIntersectionValue TestAABB( const AABB& aabb, const Matrix4& localToWorld ) const { debug_count_oriented_bbox(); return frustum_intersects_transformed_aabb( m_frustum, aabb, localToWorld ); } const Matrix4& GetViewMatrix() const { return m_viewproj; } const Matrix4& GetViewport() const { return m_viewport; }; const Matrix4& GetModelview() const { return m_modelview; } const Matrix4& GetProjection() const { return m_projection; } bool fill() const { return m_fill; } const Vector3& getViewer() const { return vector4_to_vector3( m_viewer ); } }; #endif