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