1 // Created on: 2014-11-24
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <SelectMgr_FrustumBuilder.hxx>
18 #define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
19 #define LENGTH(A) (std::sqrt (A.x() * A.x() + A.y() * A.y() + A.z() * A.z()))
22 //=======================================================================
23 // function : SelectMgr_FrustumBuilder
24 // purpose : Creates new frustum builder with empty matrices
25 //=======================================================================
26 SelectMgr_FrustumBuilder::SelectMgr_FrustumBuilder()
29 myWorldViewProjState(),
32 myIsViewportSet (Standard_False)
37 //=======================================================================
38 // function : SetWorldViewMatrix
39 // purpose : Stores current world view transformation matrix
40 //=======================================================================
41 void SelectMgr_FrustumBuilder::SetWorldViewMatrix (const Graphic3d_Mat4d& theWorldView)
43 myWorldView = theWorldView;
46 //=======================================================================
47 // function : WorldViewMatrix
48 // purpose : Returns current world view transformation matrix
49 //=======================================================================
50 const Graphic3d_Mat4d& SelectMgr_FrustumBuilder::WorldViewMatrix() const
55 //=======================================================================
56 // function : SetProjectionMatrix
57 // purpose : Stores current projection matrix
58 //=======================================================================
59 void SelectMgr_FrustumBuilder::SetProjectionMatrix (const Graphic3d_Mat4d& theProjection)
61 myProjection = theProjection;
64 //=======================================================================
65 // function : ProjectionMatrix
66 // purpose : Returns current projection matrix
67 //=======================================================================
68 const Graphic3d_Mat4d& SelectMgr_FrustumBuilder::ProjectionMatrix() const
73 //=======================================================================
74 // function : SetWorldViewProjState
75 // purpose : Stores current world view projection matrix state
76 //=======================================================================
77 void SelectMgr_FrustumBuilder::SetWorldViewProjState (const Graphic3d_WorldViewProjState& theState)
79 myWorldViewProjState = theState;
82 //=======================================================================
83 // function : WorldViewProjState
84 // purpose : Returns current world view projection matrix state
85 //=======================================================================
86 const Graphic3d_WorldViewProjState& SelectMgr_FrustumBuilder::WorldViewProjState() const
88 return myWorldViewProjState;
91 //=======================================================================
92 // function : SetWindowSize
93 // purpose : Stores current window width and height
94 //=======================================================================
95 void SelectMgr_FrustumBuilder::SetWindowSize (const Standard_Integer theWidth,
96 const Standard_Integer theHeight)
102 //=======================================================================
103 // function : SetViewport
104 // purpose : Stores current viewport coordinates
105 //=======================================================================
106 void SelectMgr_FrustumBuilder::SetViewport (const Standard_Real theX,
107 const Standard_Real theY,
108 const Standard_Real theWidth,
109 const Standard_Real theHeight)
111 myViewport = NCollection_Vec4<Standard_Real> (theX, theY, theWidth, theHeight);
112 myIsViewportSet = Standard_True;
115 //=======================================================================
116 // function : InvalidateViewport
118 //=======================================================================
119 void SelectMgr_FrustumBuilder::InvalidateViewport()
121 myIsViewportSet = Standard_False;
124 //=======================================================================
125 // function : SignedPlanePntDist
126 // purpose : Calculates signed distance between plane with equation
127 // theEq and point thePnt
128 //=======================================================================
129 Standard_Real SelectMgr_FrustumBuilder::SignedPlanePntDist (const SelectMgr_Vec3& theEq,
130 const SelectMgr_Vec3& thePnt) const
132 const Standard_Real aNormLength = LENGTH (theEq);
133 const Standard_Real anInvNormLength = aNormLength < Precision::Confusion() ? 0.0 : 1.0 / aNormLength;
134 const Standard_Real anA = theEq.x() * anInvNormLength;
135 const Standard_Real aB = theEq.y() * anInvNormLength;
136 const Standard_Real aC = theEq.z() * anInvNormLength;
137 return anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z();
140 //=======================================================================
141 // function : safePointCast
143 //=======================================================================
144 static NCollection_Vec4<Standard_Real> safePointCast (const gp_Pnt& thePnt)
146 Standard_Real aLim = 1e15f;
148 // have to deal with values greater then max float
149 gp_Pnt aSafePoint = thePnt;
150 const Standard_Real aBigFloat = aLim * 0.1f;
151 if (Abs (aSafePoint.X()) > aLim)
152 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
153 if (Abs (aSafePoint.Y()) > aLim)
154 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
155 if (Abs (aSafePoint.Z()) > aLim)
156 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
159 NCollection_Vec4<Standard_Real> aPnt (aSafePoint.X(), aSafePoint.Y(), aSafePoint.Z(), 1.0);
164 //=======================================================================
165 // function : unProject
166 // purpose : Unprojects point from NDC coords to 3d world space
167 //=======================================================================
168 SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
170 Graphic3d_Mat4d aInvView;
171 Graphic3d_Mat4d aInvProj;
173 // this case should never happen
174 if (!myWorldView.Inverted (aInvView) || !myProjection.Inverted (aInvProj))
176 return SelectMgr_Vec3 (0.0, 0.0, 0.0);
179 // use compatible type of point
180 NCollection_Vec4<Standard_Real> aPnt = safePointCast (thePnt);
182 aPnt = aInvProj * aPnt; // convert to view coordinate space
183 aPnt = aInvView * aPnt; // convert to world coordinate space
185 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
187 return SelectMgr_Vec3 (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
190 // =======================================================================
191 // function : ProjectPntOnViewPlane
192 // purpose : Projects 2d screen point onto view frustum plane:
193 // theZ = 0 - near plane,
194 // theZ = 1 - far plane
195 // =======================================================================
196 SelectMgr_Vec3 SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX,
197 const Standard_Real& theY,
198 const Standard_Real& theZ) const
200 Standard_Real aX, anY, aZ;
203 if (!myIsViewportSet)
205 aX = 2.0 * theX / myWidth - 1.0;
206 anY = (myHeight - 1 - theY) / myHeight * 2.0 - 1.0;
207 aZ = 2.0 * theZ - 1.0;
211 aX = 2.0 * (theX - myWidth * myViewport.x()) /
212 (myWidth * (myViewport.z() - myViewport.x())) - 1.0;
213 anY = 2.0 * (theY - myHeight * myViewport.y()) /
214 (myHeight * (myViewport.w() - myViewport.y())) - 1.0;
218 return unProject (gp_Pnt (aX, anY, aZ));