Commit | Line | Data |
---|---|---|
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 | ||
20 | FONCTION : | |
21 | ---------- | |
22 | File 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 | ||
31 | static void | |
32 | EvalViewMappingMatrix( 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 | ||
260 | void | |
261 | TelEvalViewOrientationMatrix( 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 | ||
339 | void | |
340 | TelEvalViewMappingMatrix( 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 |