825aa485 |
1 | // Created on: 2015-06-18 |
2 | // Created by: Anton POLETAEV |
3 | // Copyright (c) 2015 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #ifndef _Graphic3d_TransformPers_HeaderFile |
17 | #define _Graphic3d_TransformPers_HeaderFile |
18 | |
778cd667 |
19 | #include <Aspect_TypeOfTriedronPosition.hxx> |
825aa485 |
20 | #include <Bnd_Box.hxx> |
21 | #include <BVH_Box.hxx> |
3fe9ce0e |
22 | #include <Graphic3d_Camera.hxx> |
825aa485 |
23 | #include <Graphic3d_TransformUtils.hxx> |
24 | #include <Graphic3d_TransModeFlags.hxx> |
778cd667 |
25 | #include <Graphic3d_Vec.hxx> |
825aa485 |
26 | #include <NCollection_Mat4.hxx> |
778cd667 |
27 | |
28 | DEFINE_STANDARD_HANDLE(Graphic3d_TransformPers, Standard_Transient) |
825aa485 |
29 | |
30 | //! Class for keeping and computing transformation persistence. |
778cd667 |
31 | //! Note that instance of this class can not define |
32 | //! no transformation persistence Graphic3d_TMF_None - NULL handle should be used for this purpose. |
33 | class Graphic3d_TransformPers : public Standard_Transient |
825aa485 |
34 | { |
778cd667 |
35 | DEFINE_STANDARD_RTTIEXT(Graphic3d_TransformPers, Standard_Transient) |
825aa485 |
36 | public: |
37 | |
778cd667 |
38 | //! Return true if specified mode is zoom/rotate transformation persistence. |
39 | static Standard_Boolean IsZoomOrRotate (Graphic3d_TransModeFlags theMode) |
40 | { |
41 | return (theMode & (Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers)) != 0; |
42 | } |
43 | |
44 | //! Return true if specified mode is 2d/trihedron transformation persistence. |
45 | static Standard_Boolean IsTrihedronOr2d (Graphic3d_TransModeFlags theMode) |
46 | { |
47 | return (theMode & (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_2d)) != 0; |
48 | } |
825aa485 |
49 | |
778cd667 |
50 | //! Create Graphic3d_TransformPers instance from deprecated parameters set |
51 | //! decoding 2D corner + offset parameters from 3D point. |
52 | Standard_EXPORT static Handle(Graphic3d_TransformPers) FromDeprecatedParams (Graphic3d_TransModeFlags theFlag, |
53 | const gp_Pnt& thePoint); |
54 | |
55 | public: |
56 | |
57 | //! Set transformation persistence. |
58 | Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode) |
59 | : myMode (theMode) |
60 | { |
61 | if (IsZoomOrRotate (theMode)) |
62 | { |
63 | SetPersistence (theMode, gp_Pnt(0.0, 0.0, 0.0)); |
64 | } |
65 | else if (IsTrihedronOr2d (theMode)) |
66 | { |
67 | SetPersistence (theMode, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (0, 0)); |
68 | } |
69 | else |
70 | { |
71 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode."); |
72 | } |
73 | } |
74 | |
75 | //! Set Zoom/Rotate transformation persistence with an anchor 3D point. |
76 | //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers. |
77 | Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode, |
78 | const gp_Pnt& thePnt) |
79 | : myMode (Graphic3d_TMF_None) |
80 | { |
81 | SetPersistence (theMode, thePnt); |
82 | } |
83 | |
84 | //! Set 2d/trihedron transformation persistence with a corner and 2D offset. |
85 | //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d. |
86 | //! The offset is a positive displacement from the view corner in pixels. |
87 | Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode, |
88 | const Aspect_TypeOfTriedronPosition theCorner, |
89 | const Graphic3d_Vec2i& theOffset = Graphic3d_Vec2i (0, 0)) |
90 | : myMode (Graphic3d_TMF_None) |
91 | { |
92 | SetPersistence (theMode, theCorner, theOffset); |
93 | } |
94 | |
95 | //! Return true for Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers modes. |
96 | Standard_Boolean IsZoomOrRotate() const { return IsZoomOrRotate (myMode); } |
97 | |
98 | //! Return true for Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d modes. |
99 | Standard_Boolean IsTrihedronOr2d() const { return IsTrihedronOr2d (myMode); } |
825aa485 |
100 | |
101 | //! Transformation persistence mode flags. |
778cd667 |
102 | Graphic3d_TransModeFlags Mode() const { return myMode; } |
825aa485 |
103 | |
778cd667 |
104 | //! Transformation persistence mode flags. |
105 | Graphic3d_TransModeFlags Flags() const { return myMode; } |
106 | |
107 | //! Set Zoom/Rotate transformation persistence with an anchor 3D point. |
108 | //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers. |
109 | void SetPersistence (const Graphic3d_TransModeFlags theMode, |
110 | const gp_Pnt& thePnt) |
111 | { |
112 | if (!IsZoomOrRotate (theMode)) |
113 | { |
114 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode."); |
115 | } |
116 | |
117 | myMode = theMode; |
118 | myParams.Params3d.PntX = thePnt.X(); |
119 | myParams.Params3d.PntY = thePnt.Y(); |
120 | myParams.Params3d.PntZ = thePnt.Z(); |
121 | } |
122 | |
123 | //! Set 2d/trihedron transformation persistence with a corner and 2D offset. |
124 | //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d. |
125 | void SetPersistence (const Graphic3d_TransModeFlags theMode, |
126 | const Aspect_TypeOfTriedronPosition theCorner, |
127 | const Graphic3d_Vec2i& theOffset) |
128 | { |
129 | if (!IsTrihedronOr2d (theMode)) |
130 | { |
131 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode."); |
132 | } |
133 | |
134 | myMode = theMode; |
135 | myParams.Params2d.Corner = theCorner; |
136 | myParams.Params2d.OffsetX = theOffset.x(); |
137 | myParams.Params2d.OffsetY = theOffset.y(); |
138 | } |
139 | |
140 | public: |
141 | |
142 | //! Return the anchor point for zoom/rotate transformation persistence. |
143 | gp_Pnt AnchorPoint() const |
144 | { |
145 | if (!IsZoomOrRotate()) |
146 | { |
147 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::AnchorPoint(), wrong persistence mode."); |
148 | } |
149 | |
150 | return gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ); |
151 | } |
152 | |
153 | //! Set the anchor point for zoom/rotate transformation persistence. |
154 | void SetAnchorPoint (const gp_Pnt& thePnt) |
155 | { |
156 | if (!IsZoomOrRotate()) |
157 | { |
158 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetAnchorPoint(), wrong persistence mode."); |
159 | } |
160 | |
161 | myParams.Params3d.PntX = thePnt.X(); |
162 | myParams.Params3d.PntY = thePnt.Y(); |
163 | myParams.Params3d.PntZ = thePnt.Z(); |
164 | } |
165 | |
166 | //! Return the corner for 2d/trihedron transformation persistence. |
167 | Aspect_TypeOfTriedronPosition Corner2d() const |
168 | { |
169 | if (!IsTrihedronOr2d()) |
170 | { |
171 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::Corner2d(), wrong persistence mode."); |
172 | } |
173 | |
174 | return myParams.Params2d.Corner; |
175 | } |
176 | |
177 | //! Set the corner for 2d/trihedron transformation persistence. |
178 | void SetCorner2d (const Aspect_TypeOfTriedronPosition thePos) |
179 | { |
180 | if (!IsTrihedronOr2d()) |
181 | { |
182 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetCorner2d(), wrong persistence mode."); |
183 | } |
184 | |
185 | myParams.Params2d.Corner = thePos; |
186 | } |
187 | |
188 | //! Return the offset from the corner for 2d/trihedron transformation persistence. |
189 | Graphic3d_Vec2i Offset2d() const |
190 | { |
191 | if (!IsTrihedronOr2d()) |
192 | { |
193 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::Offset2d(), wrong persistence mode."); |
194 | } |
195 | |
196 | return Graphic3d_Vec2i (myParams.Params2d.OffsetX, myParams.Params2d.OffsetY); |
197 | } |
198 | |
199 | //! Set the offset from the corner for 2d/trihedron transformation persistence. |
200 | void SetOffset2d (const Graphic3d_Vec2i& theOffset) |
201 | { |
202 | if (!IsTrihedronOr2d()) |
203 | { |
204 | Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetOffset2d(), wrong persistence mode."); |
205 | } |
206 | |
207 | myParams.Params2d.OffsetX = theOffset.x(); |
208 | myParams.Params2d.OffsetY = theOffset.y(); |
209 | } |
825aa485 |
210 | |
211 | public: |
212 | |
213 | //! Apply transformation to bounding box of presentation. |
3fe9ce0e |
214 | //! @param theCamera [in] camera definition |
825aa485 |
215 | //! @param theProjection [in] the projection transformation matrix. |
216 | //! @param theWorldView [in] the world view transformation matrix. |
217 | //! @param theViewportWidth [in] the width of viewport (for 2d persistence). |
218 | //! @param theViewportHeight [in] the height of viewport (for 2d persistence). |
219 | //! @param theBoundingBox [in/out] the bounding box to transform. |
220 | template<class T> |
3fe9ce0e |
221 | void Apply (const Handle(Graphic3d_Camera)& theCamera, |
222 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
223 | const NCollection_Mat4<T>& theWorldView, |
224 | const Standard_Integer theViewportWidth, |
225 | const Standard_Integer theViewportHeight, |
226 | Bnd_Box& theBoundingBox) const; |
227 | |
228 | //! Apply transformation to bounding box of presentation |
3fe9ce0e |
229 | //! @param theCamera [in] camera definition |
825aa485 |
230 | //! @param theProjection [in] the projection transformation matrix. |
231 | //! @param theWorldView [in] the world view transformation matrix. |
232 | //! @param theViewportWidth [in] the width of viewport (for 2d persistence). |
233 | //! @param theViewportHeight [in] the height of viewport (for 2d persistence). |
234 | //! @param theBoundingBox [in/out] the bounding box to transform. |
235 | template<class T> |
3fe9ce0e |
236 | void Apply (const Handle(Graphic3d_Camera)& theCamera, |
237 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
238 | const NCollection_Mat4<T>& theWorldView, |
239 | const Standard_Integer theViewportWidth, |
240 | const Standard_Integer theViewportHeight, |
7c3ef2f7 |
241 | BVH_Box<T, 3>& theBoundingBox) const; |
825aa485 |
242 | |
243 | //! Compute transformation. |
244 | //! Computed matrix can be applied to model world transformation |
245 | //! of an object to implement effect of transformation persistence. |
3fe9ce0e |
246 | //! @param theCamera [in] camera definition |
825aa485 |
247 | //! @param theProjection [in] the projection transformation matrix. |
248 | //! @param theWorldView [in] the world view transformation matrix. |
249 | //! @param theViewportWidth [in] the width of viewport (for 2d persistence). |
250 | //! @param theViewportHeight [in] the height of viewport (for 2d persistence). |
251 | //! @return transformation matrix to be applied to model world transformation of an object. |
252 | template<class T> |
3fe9ce0e |
253 | NCollection_Mat4<T> Compute (const Handle(Graphic3d_Camera)& theCamera, |
254 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
255 | const NCollection_Mat4<T>& theWorldView, |
256 | const Standard_Integer theViewportWidth, |
257 | const Standard_Integer theViewportHeight) const; |
258 | |
71d8ccc7 |
259 | //! Apply transformation persistence on specified matrices. |
260 | //! @param theCamera camera definition |
261 | //! @param theProjection projection matrix to modify |
262 | //! @param theWorldView world-view matrix to modify |
263 | //! @param theViewportWidth viewport width |
264 | //! @param theViewportHeight viewport height |
825aa485 |
265 | template<class T> |
3fe9ce0e |
266 | void Apply (const Handle(Graphic3d_Camera)& theCamera, |
778cd667 |
267 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
268 | NCollection_Mat4<T>& theWorldView, |
269 | const Standard_Integer theViewportWidth, |
270 | const Standard_Integer theViewportHeight) const; |
71d8ccc7 |
271 | |
778cd667 |
272 | private: |
273 | |
274 | //! 3D anchor point for zoom/rotate transformation persistence. |
275 | struct PersParams3d |
71d8ccc7 |
276 | { |
778cd667 |
277 | Standard_Real PntX; |
278 | Standard_Real PntY; |
279 | Standard_Real PntZ; |
280 | }; |
281 | |
282 | //! 2d/trihedron transformation persistence parameters. |
283 | struct PersParams2d |
284 | { |
285 | Standard_Integer OffsetX; |
286 | Standard_Integer OffsetY; |
287 | Aspect_TypeOfTriedronPosition Corner; |
288 | }; |
289 | |
290 | private: |
291 | |
292 | Graphic3d_TransModeFlags myMode; //!< Transformation persistence mode flags |
293 | union |
294 | { |
295 | PersParams3d Params3d; |
296 | PersParams2d Params2d; |
297 | } myParams; |
71d8ccc7 |
298 | |
825aa485 |
299 | }; |
300 | |
301 | // ======================================================================= |
302 | // function : Apply |
303 | // purpose : Apply transformation to world view and projection matrices. |
304 | // ======================================================================= |
305 | template<class T> |
3fe9ce0e |
306 | void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, |
778cd667 |
307 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
308 | NCollection_Mat4<T>& theWorldView, |
309 | const Standard_Integer theViewportWidth, |
310 | const Standard_Integer theViewportHeight) const |
311 | { |
150ed3d5 |
312 | (void )theViewportWidth; |
778cd667 |
313 | (void )theProjection; |
314 | if (myMode == Graphic3d_TMF_None |
71d8ccc7 |
315 | || theViewportHeight == 0) |
825aa485 |
316 | { |
317 | return; |
318 | } |
319 | |
778cd667 |
320 | // use total size when tiling is active |
3bffef55 |
321 | const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight; |
778cd667 |
322 | |
323 | // a small enough jitter compensation offset |
324 | // to avoid image dragging within single pixel in corner cases |
325 | const Standard_Real aJitterComp = 0.001; |
326 | if (myMode == Graphic3d_TMF_TriedronPers) |
3fe9ce0e |
327 | { |
328 | // reset Z focus for trihedron persistence |
329 | const Standard_Real aFocus = theCamera->IsOrthographic() |
330 | ? theCamera->Distance() |
331 | : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative |
332 | ? Standard_Real(theCamera->ZFocus() * theCamera->Distance()) |
333 | : Standard_Real(theCamera->ZFocus())); |
334 | |
335 | // scale factor to pixels |
336 | const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); |
3bffef55 |
337 | const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); |
3fe9ce0e |
338 | const gp_Dir aForward (theCamera->Center().XYZ() - theCamera->Eye().XYZ()); |
339 | gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance()); |
778cd667 |
340 | if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0) |
3fe9ce0e |
341 | { |
778cd667 |
342 | const Standard_Real anOffsetX = (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale; |
343 | const gp_Dir aSide = aForward.Crossed (theCamera->Up()); |
344 | const gp_XYZ aDeltaX = aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffsetX); |
345 | if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0) |
3fe9ce0e |
346 | { |
778cd667 |
347 | aCenter += aDeltaX; |
3fe9ce0e |
348 | } |
349 | else |
350 | { |
778cd667 |
351 | aCenter -= aDeltaX; |
3fe9ce0e |
352 | } |
353 | } |
778cd667 |
354 | if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0) |
3fe9ce0e |
355 | { |
778cd667 |
356 | const Standard_Real anOffsetY = (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale; |
357 | const gp_XYZ aDeltaY = theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffsetY); |
358 | if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0) |
3fe9ce0e |
359 | { |
778cd667 |
360 | aCenter += aDeltaY; |
3fe9ce0e |
361 | } |
362 | else |
363 | { |
778cd667 |
364 | aCenter -= aDeltaY; |
3fe9ce0e |
365 | } |
366 | } |
367 | |
778cd667 |
368 | NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix(); |
369 | Graphic3d_TransformUtils::Translate (aWorldView, aCenter.X(), aCenter.Y(), aCenter.Z()); |
370 | Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale); |
371 | theWorldView.ConvertFrom (aWorldView); |
3fe9ce0e |
372 | return; |
373 | } |
778cd667 |
374 | else if (myMode == Graphic3d_TMF_2d) |
825aa485 |
375 | { |
150ed3d5 |
376 | const Standard_Real aFocus = theCamera->IsOrthographic() |
377 | ? theCamera->Distance() |
378 | : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative |
379 | ? Standard_Real(theCamera->ZFocus() * theCamera->Distance()) |
380 | : Standard_Real(theCamera->ZFocus())); |
381 | |
382 | // scale factor to pixels |
383 | const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); |
3bffef55 |
384 | const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); |
150ed3d5 |
385 | gp_XYZ aCenter (0.0, 0.0, -aFocus); |
778cd667 |
386 | if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0) |
825aa485 |
387 | { |
778cd667 |
388 | aCenter.SetX (-aViewDim.X() * 0.5 + (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale); |
389 | if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0) |
150ed3d5 |
390 | { |
391 | aCenter.SetX (-aCenter.X()); |
392 | } |
825aa485 |
393 | } |
778cd667 |
394 | if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0) |
825aa485 |
395 | { |
778cd667 |
396 | aCenter.SetY (-aViewDim.Y() * 0.5 + (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale); |
397 | if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0) |
150ed3d5 |
398 | { |
399 | aCenter.SetY (-aCenter.Y()); |
400 | } |
825aa485 |
401 | } |
402 | |
825aa485 |
403 | theWorldView.InitIdentity(); |
150ed3d5 |
404 | Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z())); |
405 | Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale)); |
406 | return; |
825aa485 |
407 | } |
778cd667 |
408 | else |
825aa485 |
409 | { |
410 | // Compute reference point for transformation in untransformed projection space. |
7c3ef2f7 |
411 | NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix(); |
412 | Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ); |
778cd667 |
413 | if ((myMode & Graphic3d_TMF_RotatePers) != 0) |
825aa485 |
414 | { |
778cd667 |
415 | // lock rotation by nullifying rotation component |
7c3ef2f7 |
416 | aWorldView.SetValue (0, 0, 1.0); |
417 | aWorldView.SetValue (1, 0, 0.0); |
418 | aWorldView.SetValue (2, 0, 0.0); |
778cd667 |
419 | |
7c3ef2f7 |
420 | aWorldView.SetValue (0, 1, 0.0); |
421 | aWorldView.SetValue (1, 1, 1.0); |
422 | aWorldView.SetValue (2, 1, 0.0); |
778cd667 |
423 | |
7c3ef2f7 |
424 | aWorldView.SetValue (0, 2, 0.0); |
425 | aWorldView.SetValue (1, 2, 0.0); |
426 | aWorldView.SetValue (2, 2, 1.0); |
825aa485 |
427 | } |
428 | |
778cd667 |
429 | if ((myMode & Graphic3d_TMF_ZoomPers) != 0) |
825aa485 |
430 | { |
778cd667 |
431 | // lock zooming |
432 | gp_Vec aVecToEye (theCamera->Direction()); |
433 | gp_Vec aVecToObj (theCamera->Eye(), gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ)); |
434 | const Standard_Real aFocus = aVecToObj.Dot (aVecToEye); |
435 | const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); |
436 | const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); |
7c3ef2f7 |
437 | Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale); |
825aa485 |
438 | } |
7c3ef2f7 |
439 | theWorldView.ConvertFrom (aWorldView); |
778cd667 |
440 | return; |
825aa485 |
441 | } |
442 | } |
443 | |
444 | // ======================================================================= |
445 | // function : Apply |
446 | // purpose : Apply transformation to bounding box of presentation. |
447 | // ======================================================================= |
448 | template<class T> |
3fe9ce0e |
449 | void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, |
450 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
451 | const NCollection_Mat4<T>& theWorldView, |
452 | const Standard_Integer theViewportWidth, |
453 | const Standard_Integer theViewportHeight, |
454 | Bnd_Box& theBoundingBox) const |
455 | { |
3fe9ce0e |
456 | if (theBoundingBox.IsVoid()) |
457 | { |
458 | return; |
459 | } |
460 | |
825aa485 |
461 | T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; |
462 | |
463 | theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); |
464 | |
7c3ef2f7 |
465 | typename BVH_Box<T, 3>::BVH_VecNt aMin (aXmin, aYmin, aZmin); |
466 | typename BVH_Box<T, 3>::BVH_VecNt aMax (aXmax, aYmax, aZmax); |
467 | BVH_Box<T, 3> aBBox (aMin, aMax); |
825aa485 |
468 | |
3fe9ce0e |
469 | Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox); |
825aa485 |
470 | |
471 | theBoundingBox = Bnd_Box(); |
472 | theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(), |
473 | aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z()); |
474 | } |
475 | |
476 | // ======================================================================= |
477 | // function : Apply |
478 | // purpose : Apply transformation to bounding box of presentation. |
479 | // ======================================================================= |
480 | template<class T> |
3fe9ce0e |
481 | void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, |
482 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
483 | const NCollection_Mat4<T>& theWorldView, |
484 | const Standard_Integer theViewportWidth, |
485 | const Standard_Integer theViewportHeight, |
7c3ef2f7 |
486 | BVH_Box<T, 3>& theBoundingBox) const |
825aa485 |
487 | { |
3fe9ce0e |
488 | NCollection_Mat4<T> aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight); |
489 | if (aTPers.IsIdentity() |
490 | || !theBoundingBox.IsValid()) |
825aa485 |
491 | { |
492 | return; |
493 | } |
494 | |
7c3ef2f7 |
495 | const typename BVH_Box<T, 3>::BVH_VecNt& aMin = theBoundingBox.CornerMin(); |
496 | const typename BVH_Box<T, 3>::BVH_VecNt& aMax = theBoundingBox.CornerMax(); |
825aa485 |
497 | |
498 | typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8]; |
499 | anArrayOfCorners[0] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast<T> (1.0)); |
500 | anArrayOfCorners[1] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast<T> (1.0)); |
501 | anArrayOfCorners[2] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast<T> (1.0)); |
502 | anArrayOfCorners[3] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast<T> (1.0)); |
503 | anArrayOfCorners[4] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast<T> (1.0)); |
504 | anArrayOfCorners[5] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast<T> (1.0)); |
505 | anArrayOfCorners[6] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast<T> (1.0)); |
506 | anArrayOfCorners[7] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast<T> (1.0)); |
507 | |
508 | theBoundingBox.Clear(); |
509 | for (Standard_Integer anIt = 0; anIt < 8; ++anIt) |
510 | { |
511 | typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt]; |
512 | aCorner = aTPers * aCorner; |
513 | aCorner /= aCorner.w(); |
7c3ef2f7 |
514 | theBoundingBox.Add (aCorner.xyz()); |
825aa485 |
515 | } |
516 | } |
517 | |
518 | // ======================================================================= |
519 | // function : Compute |
520 | // purpose : Compute transformation. |
521 | // ======================================================================= |
522 | template<class T> |
3fe9ce0e |
523 | NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera, |
524 | const NCollection_Mat4<T>& theProjection, |
825aa485 |
525 | const NCollection_Mat4<T>& theWorldView, |
526 | const Standard_Integer theViewportWidth, |
527 | const Standard_Integer theViewportHeight) const |
528 | { |
778cd667 |
529 | if (myMode == Graphic3d_TMF_None) |
825aa485 |
530 | { |
531 | return NCollection_Mat4<T>(); |
532 | } |
533 | |
778cd667 |
534 | NCollection_Mat4<T> aWorldView (theWorldView); |
825aa485 |
535 | NCollection_Mat4<T> anUnviewMat; |
71d8ccc7 |
536 | if (!theWorldView.Inverted (anUnviewMat)) |
825aa485 |
537 | { |
538 | return NCollection_Mat4<T>(); |
539 | } |
540 | |
71d8ccc7 |
541 | // compute only world-view matrix difference to avoid floating point instability |
542 | // caused by projection matrix modifications outside of this algorithm (e.g. by Z-fit) |
778cd667 |
543 | Apply (theCamera, theProjection, aWorldView, theViewportWidth, theViewportHeight); |
71d8ccc7 |
544 | return anUnviewMat * aWorldView; |
825aa485 |
545 | } |
546 | |
547 | #endif // _Graphic3d_TransformPers_HeaderFile |