0023428: Extend OpenGl_Context to use Geometry Shaders extension
[occt.git] / src / OpenGl / OpenGl_telem_view.cxx
CommitLineData
b311480e 1// Copyright (c) 1999-2012 OPEN CASCADE SAS
2//
3// The content of this file is subject to the Open CASCADE Technology Public
4// License Version 6.5 (the "License"). You may not use the content of this file
5// except in compliance with the License. Please obtain a copy of the License
6// at http://www.opencascade.org and read it completely before using this file.
7//
8// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10//
11// The Original Code and all software distributed under the License is
12// distributed on an "AS IS" basis, without warranty of any kind, and the
13// Initial Developer hereby disclaims all such warranties, including without
14// limitation, any warranties of merchantability, fitness for a particular
15// purpose or non-infringement. Please see the License for the specific terms
16// and conditions governing the rights and limitations under the License.
17
2166f0fa
SK
18/***********************************************************************
19
20FONCTION :
21----------
22File OpenGl_telem_view :
23
24************************************************************************/
25
5f8b738e 26#include <OpenGl_GlCore11.hxx>
2166f0fa
SK
27#include <OpenGl_telem_view.hxx>
28#include <OpenGl_telem_util.hxx>
29#include <OpenGl_Display.hxx>
30
31static void
32EvalViewMappingMatrix( tel_view_mapping mapping /* View Mapping */,
33 Tint *error_ind /* Out: Error Indicator */,
34 Tmatrix3 mat /* Out: Mapping Matrix * */,
35 Tint flag,
36 Tfloat cx,
37 Tfloat cy,
38 Tint clip_flag,
39 Tlimit3 *clip_limit
40 )
41{
42 Tfloat gx, gy, xsf, ysf, zsf;
43 Tfloat fpd, bpd;
44
45 /* OCC18942 */
46 Tfloat n, f, r, l, t, b, Zprp, dx, dy, VPD;
47
48 /* FSXXX */
49 /* GLint gdtmp; */
50 Tlimit3 vp = { ( float )-1.0, ( float )1.0, ( float )-1.0, ( float )1.0, ( float )1.0, ( float )-1.0 };
51 Tmatrix3 pmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
52 { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
53 { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
54 { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
55 Tmatrix3 mmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
56 { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
57 { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
58 { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
59
60 fpd = mapping->fpd;
61 bpd = mapping->bpd;
62
63 /* invalid window */
64 if( mapping->window.xmin >= mapping->window.xmax ||
65 mapping->window.ymin >= mapping->window.ymax )
66 {
67 *error_ind = 1;
68 return;
69 }
70
71 /* invalid viewport */
72 if( mapping->viewport.xmin >= mapping->viewport.xmax ||
73 mapping->viewport.ymin >= mapping->viewport.ymax ||
74 mapping->viewport.zmin >= mapping->viewport.zmax )
75 {
76 *error_ind = 2;
77 return;
78 }
79
80 /* invalid back/front plane distances */
81 if( mapping->bpd >= mapping->fpd )
82 {
83 *error_ind = 3;
84 return;
85 }
86
87 /* prp between front and back planes */
0003c4b2 88 if (openglDisplay.IsNull() || !openglDisplay->Walkthrough())
2166f0fa
SK
89 {
90 if( mapping->prp[2] < mapping->fpd &&
91 mapping->prp[2] > mapping->bpd )
92 {
93 *error_ind = 4;
94 return;
95 }
96 }
97
98 if( mapping->prp[2] == mapping->vpd )
99 {
100 *error_ind = 5; /* prp on view plane */
101 return;
102 }
103
104 if( mapping->viewport.xmin < 0 ||
105 mapping->viewport.xmax > 1 ||
106 mapping->viewport.ymin < 0 ||
107 mapping->viewport.ymax > 1 ||
108 mapping->viewport.zmin < 0 ||
109 mapping->viewport.zmax > 1 )
110 {
111 *error_ind = 6; /* viewport limits outside NPC space */
112 return;
113 }
114
115 *error_ind = 0;
116
117 /* OCC18942: Moved here while debugging perspective projection matrix */
118 /* centers */
119 if( flag == 0 )
120 {
121 cx = mapping->window.xmin + mapping->window.xmax, cx /= ( float )2.0;
122 cy = mapping->window.ymin + mapping->window.ymax, cy /= ( float )2.0;
123 }
124
125 gx = (cx - mapping->prp[0]) / (mapping->vpd - mapping->prp[2]);
126 gy = (cy - mapping->prp[1]) / (mapping->vpd - mapping->prp[2]);
127
128#ifdef PRINT
129 printf("EvalViewMappingMatrix \n");
130 printf("prp %f %f %f \n", mapping->prp[0], mapping->prp[1], mapping->prp[2]);
131 printf("vpd fpd bpd %f %f %f \n", mapping->vpd, mapping->fpd, mapping->bpd);
132 printf("window limit %f %f %f %f\n", mapping->window.xmin, mapping->window.xmax,
133 mapping->window.ymin, mapping->window.ymax);
134 printf("viewport limit %f %f %f %f\n", mapping->viewport.xmin, mapping->viewport.xmax,
135 mapping->viewport.ymin, mapping->viewport.ymax);
136#endif
137
138 /* projection matrix */
139 if( mapping->proj == TelParallel )
140 {
141
142 pmat[2][0] = -gx; pmat[3][0] = mapping->vpd*gx;
143 pmat[2][1] = -gy; pmat[3][1] = mapping->vpd*gy;
144 }
145 else if (!openglDisplay.IsNull() && !openglDisplay->SymPerspective())/* TelPerspective */
146 {
147 pmat[0][0] = pmat[1][1] = mapping->prp[2] - mapping->vpd;
148 pmat[2][0] = -gx;
149 pmat[2][1] = -gy;
150 pmat[2][3] = ( float )-1.0;
151 pmat[3][0] = mapping->vpd * gx;
152 pmat[3][1] = mapping->vpd * gy;
153 pmat[3][3] = mapping->prp[2];
154
155 /* modify the next two cells to change clipping policy */
156 if (!openglDisplay.IsNull() && !openglDisplay->Walkthrough())
157 {
158 pmat[2][2] = mapping->prp[2] - ( fpd + bpd );
159 pmat[3][2] = fpd * bpd;
160 }
161 }
162 /* OCC18942: New approach to calculation of mapping (projection) matrix */
163 else
164 {
165 dx = mapping->window.xmax - mapping->window.xmin;
166 dy = mapping->window.ymax - mapping->window.ymin;
167 Zprp = mapping->prp[2];
168 VPD = Zprp - mapping->vpd;
169
170 /*
171 Calculate canonical perspective projection parameters as if we were about
172 to use glFrustum() to create symmetric perspective frustum.
173
174 After the view orientation matrix is applied, the coordinate system origin is located
175 at the VRP and oriented properly. However, the viewplane has width = dx and height = dy
176 and its center (cx, cy, VPD) is not always located at the view Z axis.
177 The canonical perspective projection matrix assumes the eye is located at (0, 0, 0).
178 Thus the old approach resulted in a non-symmetric perspective,
179 as X and Y coordinates of the projection reference point (PRP) were not updated
180 when cx and cy changed. Moreover, such "static" perspective had some other disadvantages,
181 such as non-realistic panning, i.e. instead of moving the eye (or camera) over the model
182 a sort of "frame" moved over the static perspective projection picture,
183 exposing a part of this static picture to the user.
184
185 In order to make the perspective symmetric, we need to translate
186 the coordinate system to PRP before projection.
187 Thus we translate X, Y and Z co-ordinates by -cx, -cy and -Zprp respectively.
188
189 NOTE: mat[i][j] means j-th element of i-th column, as OpenGL accepts the matrices
190 in column-major order, while in C two-dimensional arrays are stored in memory
191 in row-major order!
192
193 VPD is used below instead of near clipping plane dispance (n) in order to simplify
194 calculation of l and r values. If we did not use VPD in the matrix calculation, we would have to
195 project 0.5 * dx, -0.5 * dx, 0.5 * dy and - 0.5 * dy onto the near clipping plane
196 to calculate these values.
197
198 Pending issues:
199 1. It is still necessary to find a way to calculate the perspective projection matrix
200 for TPM_WALKTHROUGH projection model. This projection model is not supported yet
201 by the new code.
202 */
203 r = .5f * dx;
204 l = -r;
205 t = .5f * dy;
206 b = -t;
207 n = Zprp - fpd; f = Zprp - bpd;
208
209 mat[0][0] = 2.f * VPD / (r - l);
210 mat[1][1] = 2.f * VPD / (t - b);
211 mat[2][0] = (r + l) / (r - l);
212 mat[2][1] = (t + b) / (t - b);
213 mat[2][2] = - (f + n) / (f - n);
214 mat[2][3] = -1.f;
215 /*
216 The last column takes into account translation along X, Y and Z axis
217 before projecting. This can be considered as a result of right-multiplying the canonical
218 perspective projection matrix P by a translation matrix T
219 (it differs form the canonical matrix by the last column only):
220 | 1 0 0 -cx |
221 | 0 1 0 -cy |
222 mat = P * T, where T = | 0 0 1 -Zprp |
223 | 0 0 0 1 |
224 */
225 mat[3][0] = -mat[2][0] * Zprp - mat[0][0] * cx;
226 mat[3][1] = -mat[2][1] * Zprp - mat[1][1] * cy;
227 mat[3][2] = -2.f * f * n / (f - n) - mat[2][2] * Zprp;
228 mat[3][3] = Zprp;
229
230#ifdef PRINT
231 printf("r l t b n f: %f %f %f %f %f %f \n", r,l,t,b,n,f);
232 printf( "mapping_matrix (new code):\n" );
233 pr_matrix(mat);
234#endif
235
236 /* return here, as further calculations are related to the old approach */
237 return;
238 }
239
240 /* scale factors */
241 xsf = (vp.xmax - vp.xmin) / (mapping->window.xmax - mapping->window.xmin);
242 ysf = (vp.ymax - vp.ymin) / (mapping->window.ymax - mapping->window.ymin);
243 zsf = (vp.zmax - vp.zmin) / (fpd - bpd);
244
245 /* map matrix */
246 mmat[0][0] = xsf, mmat[1][1] = ysf, mmat[2][2] = zsf;
247 mmat[3][0] = vp.xmin - xsf*mapping->window.xmin;
248 mmat[3][1] = vp.ymin - ysf*mapping->window.ymin;
249 mmat[3][2] = vp.zmin - zsf*bpd;
250
251 /* multiply to obtain mapping matrix */
252 TelMultiplymat3( mat, pmat, mmat );
253
254#ifdef PRINT
255 printf( "mapping_matrix :\n" );
256 pr_matrix(mat);
257#endif
258}
259
260void
261TelEvalViewOrientationMatrix( Tfloat *vrp /* View Reference Point */,
262 Tfloat *vpn /* View Plane Normal */,
263 Tfloat *vup /* View Up Vector */,
264 Tfloat *asf /* Axial Scale Factors */,
265 Tint *error_ind/* Out: Error indicator */,
266 Tmatrix3 rmat /* Out: Orientation Matrix */
267 )
268{
269 Tfloat u[3], v[3], n[3], f;
270
271 /* view plane normal of zero length */
272 if( vecmag(vpn) == 0.0 )
273 {
274 *error_ind = 1;
275 return;
276 }
277
278 /* view up vector of zero length */
279 if( vecmag(vup) == 0.0 )
280 {
281 *error_ind = 2;
282 return;
283 }
284
285 /* view up vector parallel to view plane normal */
286 vecang(vup, vpn, f);
287 if( f == 0.0 )
288 {
289 *error_ind = 3;
290 return;
291 }
292
293 *error_ind = 0;
294
295 veccpy(n, vpn);
296 veccpy(v, vup);
297 vecnrm(n);
298
299 veccrs(u,v,n); /* up vector cross plane normal gives U axis */
300 vecnrm(u);
301
302 veccrs(v,n,u); /* plane normal cross U axis gives modified up vector */
303 vecnrm(v); /* redundant ? */
304
305 /* rotate to align along u, v, n */
306 rmat[0][0] = ( float )u[0] * asf[0],
307 rmat[0][1] = ( float )v[0] * asf[0],
308 rmat[0][2] = ( float )n[0] * asf[0],
309 rmat[0][3] = ( float )0.0;
310
311 rmat[1][0] = ( float )u[1] * asf[1],
312 rmat[1][1] = ( float )v[1] * asf[1],
313 rmat[1][2] = ( float )n[1] * asf[1],
314 rmat[1][3] = ( float )0.0;
315
316 rmat[2][0] = ( float )u[2] * asf[2],
317 rmat[2][1] = ( float )v[2] * asf[2],
318 rmat[2][2] = ( float )n[2] * asf[2],
319 rmat[2][3] = ( float )0.0;
320
321 /* translate to centre at vrp */
322
323 rmat[3][0] = - ( float ) (u[0]*vrp[0] + u[1]*vrp[1] + u[2]*vrp[2]);
324 rmat[3][1] = - ( float ) (v[0]*vrp[0] + v[1]*vrp[1] + v[2]*vrp[2]);
325 rmat[3][2] = - ( float ) (n[0]*vrp[0] + n[1]*vrp[1] + n[2]*vrp[2]);
326 rmat[3][3] = ( float )1.0;
327
328#ifdef PRINT
329 printf("TelEvalViewOrientationMatrix \n");
330 printf("view_ref_pt %f %f %f \n", vrp[0], vrp[1], vrp[2]);
331 printf("view_up_vec %f %f %f \n", vup[0], vup[1], vup[2]);
332 printf("view_plane_normal %f %f %f \n", vpn[0], vpn[1], vpn[2]);
333 pr_matrix(rmat);
334#endif
335
336 return;
337}
338
339void
340TelEvalViewMappingMatrix( tel_view_mapping mapping /* View Mapping */,
341 Tint *error_ind /* Out: Error Indicator */,
342 Tmatrix3 mat /* Out: Mapping Matrix */
343 )
344{
345 EvalViewMappingMatrix( mapping, error_ind, mat, 0, ( float )0.0, ( float )0.0, 0, 0 );
346}
347