]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/view.h
Merge branch 'transfilterfix' into 'master'
[xonotic/netradiant.git] / radiant / view.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_VIEW_H )
23 #define INCLUDED_VIEW_H
24
25 #include "globaldefs.h"
26 #include "cullable.h"
27 #include "math/frustum.h"
28
29
30 #if GDEF_DEBUG
31 #define DEBUG_CULLING
32 #endif
33
34
35 #if defined( DEBUG_CULLING )
36
37 extern int g_count_dots;
38 extern int g_count_planes;
39 extern int g_count_oriented_planes;
40 extern int g_count_bboxs;
41 extern int g_count_oriented_bboxs;
42
43 #endif
44
45 inline void debug_count_dot()
46 {
47 #if defined( DEBUG_CULLING )
48     ++g_count_dots;
49 #endif
50 }
51
52 inline void debug_count_plane()
53 {
54 #if defined( DEBUG_CULLING )
55     ++g_count_planes;
56 #endif
57 }
58
59 inline void debug_count_oriented_plane()
60 {
61 #if defined( DEBUG_CULLING )
62     ++g_count_oriented_planes;
63 #endif
64 }
65
66 inline void debug_count_bbox()
67 {
68 #if defined( DEBUG_CULLING )
69     ++g_count_bboxs;
70 #endif
71 }
72
73 inline void debug_count_oriented_bbox()
74 {
75 #if defined( DEBUG_CULLING )
76     ++g_count_oriented_bboxs;
77 #endif
78 }
79
80
81 /// \brief View-volume culling and transformations.
82 class View : public VolumeTest {
83 /// modelview matrix
84     Matrix4 m_modelview;
85 /// projection matrix
86     Matrix4 m_projection;
87 /// device-to-screen transform
88     Matrix4 m_viewport;
89
90     Matrix4 m_scissor;
91
92 /// combined modelview and projection matrix
93     Matrix4 m_viewproj;
94 /// camera position in world space
95     Vector4 m_viewer;
96 /// view frustum in world space
97     Frustum m_frustum;
98
99     bool m_fill;
100
101     void construct()
102     {
103         m_viewproj = matrix4_multiplied_by_matrix4(matrix4_multiplied_by_matrix4(m_scissor, m_projection), m_modelview);
104
105         m_frustum = frustum_from_viewproj(m_viewproj);
106         m_viewer = viewer_from_viewproj(m_viewproj);
107     }
108
109 public:
110     View(bool fill = false) :
111             m_modelview(g_matrix4_identity),
112             m_projection(g_matrix4_identity),
113             m_scissor(g_matrix4_identity),
114             m_fill(fill)
115     {
116     }
117
118     void Construct(const Matrix4 &projection, const Matrix4 &modelview, std::size_t width, std::size_t height)
119     {
120         // modelview
121         m_modelview = modelview;
122
123         // projection
124         m_projection = projection;
125
126         // viewport
127         m_viewport = g_matrix4_identity;
128         m_viewport[0] = float(width / 2);
129         m_viewport[5] = float(height / 2);
130         if (fabs(m_projection[11]) > 0.0000001) {
131             m_viewport[10] = m_projection[0] * m_viewport[0];
132         } else {
133             m_viewport[10] = 1 / m_projection[10];
134         }
135
136         construct();
137     }
138
139     void EnableScissor(float min_x, float max_x, float min_y, float max_y)
140     {
141         m_scissor = g_matrix4_identity;
142         m_scissor[0] = static_cast<float>((max_x - min_x) * 0.5 );
143         m_scissor[5] = static_cast<float>((max_y - min_y) * 0.5 );
144         m_scissor[12] = static_cast<float>((min_x + max_x) * 0.5 );
145         m_scissor[13] = static_cast<float>((min_y + max_y) * 0.5 );
146         matrix4_full_invert(m_scissor);
147
148         construct();
149     }
150
151     void DisableScissor()
152     {
153         m_scissor = g_matrix4_identity;
154
155         construct();
156     }
157
158     bool TestPoint(const Vector3 &point) const
159     {
160         return viewproj_test_point(m_viewproj, point);
161     }
162
163     bool TestLine(const Segment &segment) const
164     {
165         return frustum_test_line(m_frustum, segment);
166     }
167
168     bool TestPlane(const Plane3 &plane) const
169     {
170         debug_count_plane();
171         return viewer_test_plane(m_viewer, plane);
172     }
173
174     bool TestPlane(const Plane3 &plane, const Matrix4 &localToWorld) const
175     {
176         debug_count_oriented_plane();
177         return viewer_test_transformed_plane(m_viewer, plane, localToWorld);
178     }
179
180     VolumeIntersectionValue TestAABB(const AABB &aabb) const
181     {
182         debug_count_bbox();
183         return frustum_test_aabb(m_frustum, aabb);
184     }
185
186     VolumeIntersectionValue TestAABB(const AABB &aabb, const Matrix4 &localToWorld) const
187     {
188         debug_count_oriented_bbox();
189         return frustum_intersects_transformed_aabb(m_frustum, aabb, localToWorld);
190     }
191
192     const Matrix4 &GetViewMatrix() const
193     {
194         return m_viewproj;
195     }
196
197     const Matrix4 &GetViewport() const
198     {
199         return m_viewport;
200     };
201
202     const Matrix4 &GetModelview() const
203     {
204         return m_modelview;
205     }
206
207     const Matrix4 &GetProjection() const
208     {
209         return m_projection;
210     }
211
212     bool fill() const
213     {
214         return m_fill;
215     }
216
217     const Vector3 &getViewer() const
218     {
219         return vector4_to_vector3(m_viewer);
220     }
221 };
222
223 #endif