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()
31 myIsViewportSet (Standard_False) {}
33 //=======================================================================
34 // function : SetOrientation
35 // purpose : Stores current orientation matrix
36 //=======================================================================
37 void SelectMgr_FrustumBuilder::SetOrientation (const Graphic3d_Mat4d& theOrientation)
39 myOrientation = theOrientation;
42 //=======================================================================
43 // function : SetProjection
44 // purpose : Stores current projection matrix
45 //=======================================================================
46 void SelectMgr_FrustumBuilder::SetProjection (const Graphic3d_Mat4d& theProjection)
48 myProjection = theProjection;
51 //=======================================================================
52 // function : SetWindowSize
53 // purpose : Stores current window width and height
54 //=======================================================================
55 void SelectMgr_FrustumBuilder::SetWindowSize (const Standard_Integer theWidth,
56 const Standard_Integer theHeight)
62 //=======================================================================
63 // function : SetViewport
64 // purpose : Stores current viewport coordinates
65 //=======================================================================
66 void SelectMgr_FrustumBuilder::SetViewport (const Standard_Real theX,
67 const Standard_Real theY,
68 const Standard_Real theWidth,
69 const Standard_Real theHeight)
71 myViewport = NCollection_Vec4<Standard_Real> (theX, theY, theWidth, theHeight);
72 myIsViewportSet = Standard_True;
75 //=======================================================================
76 // function : InvalidateViewport
78 //=======================================================================
79 void SelectMgr_FrustumBuilder::InvalidateViewport()
81 myIsViewportSet = Standard_False;
84 //=======================================================================
85 // function : SignedPlanePntDist
86 // purpose : Calculates signed distance between plane with equation
87 // theEq and point thePnt
88 //=======================================================================
89 Standard_Real SelectMgr_FrustumBuilder::SignedPlanePntDist (const SelectMgr_Vec3& theEq,
90 const SelectMgr_Vec3& thePnt) const
92 const Standard_Real aNormLength = LENGTH (theEq);
93 const Standard_Real anInvNormLength = aNormLength < Precision::Confusion() ? 0.0 : 1.0 / aNormLength;
94 const Standard_Real anA = theEq.x() * anInvNormLength;
95 const Standard_Real aB = theEq.y() * anInvNormLength;
96 const Standard_Real aC = theEq.z() * anInvNormLength;
97 return anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z();
100 //=======================================================================
101 // function : safePointCast
103 //=======================================================================
104 static NCollection_Vec4<Standard_Real> safePointCast (const gp_Pnt& thePnt)
106 Standard_Real aLim = 1e15f;
108 // have to deal with values greater then max float
109 gp_Pnt aSafePoint = thePnt;
110 const Standard_Real aBigFloat = aLim * 0.1f;
111 if (Abs (aSafePoint.X()) > aLim)
112 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
113 if (Abs (aSafePoint.Y()) > aLim)
114 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
115 if (Abs (aSafePoint.Z()) > aLim)
116 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
119 NCollection_Vec4<Standard_Real> aPnt (aSafePoint.X(), aSafePoint.Y(), aSafePoint.Z(), 1.0);
124 //=======================================================================
125 // function : unProject
126 // purpose : Unprojects point from NDC coords to 3d world space
127 //=======================================================================
128 SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const
130 Graphic3d_Mat4d aInvView;
131 Graphic3d_Mat4d aInvProj;
133 // this case should never happen
134 if (!myOrientation.Inverted (aInvView) || !myProjection.Inverted (aInvProj))
136 return SelectMgr_Vec3 (0.0, 0.0, 0.0);
139 // use compatible type of point
140 NCollection_Vec4<Standard_Real> aPnt = safePointCast (thePnt);
142 aPnt = aInvProj * aPnt; // convert to view coordinate space
143 aPnt = aInvView * aPnt; // convert to world coordinate space
145 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
147 return SelectMgr_Vec3 (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
150 // =======================================================================
151 // function : ProjectPntOnViewPlane
152 // purpose : Projects 2d screen point onto view frustum plane:
153 // theZ = 0 - near plane,
154 // theZ = 1 - far plane
155 // =======================================================================
156 SelectMgr_Vec3 SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX,
157 const Standard_Real& theY,
158 const Standard_Real& theZ) const
160 Standard_Real aX, anY, aZ;
163 if (!myIsViewportSet)
165 aX = 2.0 * theX / myWidth - 1.0;
166 anY = (myHeight - 1 - theY) / myHeight * 2.0 - 1.0;
167 aZ = 2.0 * theZ - 1.0;
171 aX = 2.0 * (theX - myWidth * myViewport.x()) /
172 (myWidth * (myViewport.z() - myViewport.x())) - 1.0;
173 anY = 2.0 * (theY - myHeight * myViewport.y()) /
174 (myHeight * (myViewport.w() - myViewport.y())) - 1.0;
178 return unProject (gp_Pnt (aX, anY, aZ));