1 // Created on: 2013-12-25
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 1999-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.
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_BVHClipPrimitiveSet.hxx>
20 #include <Graphic3d_GraphicDriver.hxx>
22 // =======================================================================
23 // function : OpenGl_BVHTreeSelector
25 // =======================================================================
26 OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
27 : myIsProjectionParallel (Standard_True),
34 // =======================================================================
35 // function : SetViewVolume
36 // purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices.
37 // =======================================================================
38 void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera)
40 if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState()))
43 myIsProjectionParallel = theCamera->IsOrthographic();
46 myProjectionMat = theCamera->ProjectionMatrix();
47 myWorldViewMat = theCamera->OrientationMatrix();
48 myWorldViewProjState = theCamera->WorldViewProjState();
49 myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z());
50 myCamScaleInv = 1.0 / myCamera->Scale();
52 Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0;
53 Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0;
54 Standard_Real aNear = 0.0, aFar = 0.0;
55 if (!myIsProjectionParallel)
57 // handle perspective projection
58 aNear = myProjectionMat.GetValue (2, 3) / (- 1.0 + myProjectionMat.GetValue (2, 2));
59 aFar = myProjectionMat.GetValue (2, 3) / ( 1.0 + myProjectionMat.GetValue (2, 2));
61 nLeft = aNear * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
62 nRight = aNear * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
63 nTop = aNear * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
64 nBottom = aNear * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
66 fLeft = aFar * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
67 fRight = aFar * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
68 fTop = aFar * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
69 fBottom = aFar * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
73 // handle orthographic projection
74 aNear = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) + 1.0);
75 aFar = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) - 1.0);
77 nLeft = ( 1.0 + myProjectionMat.GetValue (0, 3)) / (-myProjectionMat.GetValue (0, 0));
79 nRight = ( 1.0 - myProjectionMat.GetValue (0, 3)) / myProjectionMat.GetValue (0, 0);
81 nTop = ( 1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
83 nBottom = (-1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
87 OpenGl_Vec4d aLeftTopNear (nLeft, nTop, -aNear, 1.0), aRightBottomFar (fRight, fBottom, -aFar, 1.0);
88 OpenGl_Vec4d aLeftBottomNear (nLeft, nBottom, -aNear, 1.0), aRightTopFar (fRight, fTop, -aFar, 1.0);
89 OpenGl_Vec4d aRightBottomNear (nRight, nBottom, -aNear, 1.0), aLeftTopFar (fLeft, fTop, -aFar, 1.0);
90 OpenGl_Vec4d aRightTopNear (nRight, nTop, -aNear, 1.0), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0);
92 const OpenGl_Mat4d aViewProj = myWorldViewMat * myProjectionMat;
93 OpenGl_Mat4d anInvWorldView;
94 myWorldViewMat.Inverted (anInvWorldView);
96 myClipVerts[ClipVert_LeftTopNear] = anInvWorldView * aLeftTopNear;
97 myClipVerts[ClipVert_RightBottomFar] = anInvWorldView * aRightBottomFar;
98 myClipVerts[ClipVert_LeftBottomNear] = anInvWorldView * aLeftBottomNear;
99 myClipVerts[ClipVert_RightTopFar] = anInvWorldView * aRightTopFar;
100 myClipVerts[ClipVert_RightBottomNear] = anInvWorldView * aRightBottomNear;
101 myClipVerts[ClipVert_LeftTopFar] = anInvWorldView * aLeftTopFar;
102 myClipVerts[ClipVert_RightTopNear] = anInvWorldView * aRightTopNear;
103 myClipVerts[ClipVert_LeftBottomFar] = anInvWorldView * aLeftBottomFar;
106 myClipPlanes[Plane_Left] = aViewProj.GetRow (3) + aViewProj.GetRow (0);
107 myClipPlanes[Plane_Right] = aViewProj.GetRow (3) - aViewProj.GetRow (0);
108 myClipPlanes[Plane_Top] = aViewProj.GetRow (3) - aViewProj.GetRow (1);
109 myClipPlanes[Plane_Bottom] = aViewProj.GetRow (3) + aViewProj.GetRow (1);
110 myClipPlanes[Plane_Near] = aViewProj.GetRow (3) + aViewProj.GetRow (2);
111 myClipPlanes[Plane_Far] = aViewProj.GetRow (3) - aViewProj.GetRow (2);
113 gp_Pnt aPtCenter = theCamera->Center();
114 OpenGl_Vec4d aCenter (aPtCenter.X(), aPtCenter.Y(), aPtCenter.Z(), 1.0);
116 for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter)
118 OpenGl_Vec4d anEq = myClipPlanes[aPlaneIter];
119 if (SignedPlanePointDistance (anEq, aCenter) > 0)
122 myClipPlanes[aPlaneIter] = anEq;
127 // =======================================================================
128 // function : SetViewportSize
130 // =======================================================================
131 void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth,
132 Standard_Integer theViewportHeight,
133 Standard_Real theResolutionRatio)
135 myViewportHeight = theViewportHeight;
136 myViewportWidth = theViewportWidth;
137 myPixelSize = Max (theResolutionRatio / theViewportHeight,
138 theResolutionRatio / theViewportWidth);
141 // =======================================================================
142 // function : SignedPlanePointDistance
144 // =======================================================================
145 Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4d& theNormal,
146 const OpenGl_Vec4d& thePnt)
148 const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x()
149 + theNormal.y() * theNormal.y()
150 + theNormal.z() * theNormal.z());
152 if (aNormLength < gp::Resolution())
155 const Standard_Real anInvNormLength = 1.0 / aNormLength;
156 const Standard_Real aD = theNormal.w() * anInvNormLength;
157 const Standard_Real anA = theNormal.x() * anInvNormLength;
158 const Standard_Real aB = theNormal.y() * anInvNormLength;
159 const Standard_Real aC = theNormal.z() * anInvNormLength;
160 return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z());
163 // =======================================================================
164 // function : SetCullingDistance
166 // =======================================================================
167 void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx,
168 Standard_Real theDistance) const
170 theCtx.DistCull = -1.0;
171 if (!myIsProjectionParallel)
173 theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance)
179 // =======================================================================
180 // function : SetCullingSize
182 // =======================================================================
183 void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx,
184 Standard_Real theSize) const
186 theCtx.SizeCull2 = -1.0;
187 if (theSize > 0.0 && !Precision::IsInfinite (theSize))
189 theCtx.SizeCull2 = (myPixelSize * theSize) / myCamScaleInv;
190 theCtx.SizeCull2 *= theCtx.SizeCull2;
194 // =======================================================================
195 // function : CacheClipPtsProjections
197 // =======================================================================
198 void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
200 const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
201 for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
203 const OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
204 Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
205 Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
206 for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
208 Standard_Real aProjection = aPlane.x() * myClipVerts[aCornerIter].x()
209 + aPlane.y() * myClipVerts[aCornerIter].y()
210 + aPlane.z() * myClipVerts[aCornerIter].z();
211 aMaxProj = Max (aProjection, aMaxProj);
212 aMinProj = Min (aProjection, aMinProj);
214 myMaxClipProjectionPts[aPlaneIter] = aMaxProj;
215 myMinClipProjectionPts[aPlaneIter] = aMinProj;
218 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
220 Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
221 Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
222 for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
224 Standard_Real aProjection = aDim == 0
225 ? myClipVerts[aCornerIter].x()
227 ? myClipVerts[aCornerIter].y()
228 : myClipVerts[aCornerIter].z());
229 aMaxProj = Max (aProjection, aMaxProj);
230 aMinProj = Min (aProjection, aMinProj);
232 myMaxOrthoProjectionPts[aDim] = aMaxProj;
233 myMinOrthoProjectionPts[aDim] = aMinProj;