a3bcd1edd397588885b04f34f31629c4fd86784d
[occt.git] / src / OpenGl / OpenGl_BVHTreeSelector.cxx
1 // Created on: 2013-12-25
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 1999-2014 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 #include <limits>
17
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_BVHClipPrimitiveSet.hxx>
20 #include <Graphic3d_GraphicDriver.hxx>
21
22 // =======================================================================
23 // function : OpenGl_BVHTreeSelector
24 // purpose  :
25 // =======================================================================
26 OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
27 : myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB),
28   myIsProjectionParallel (Standard_True),
29   myCamScale (1.0),
30   myPixelSize (1.0)
31 {
32   //
33 }
34
35 // =======================================================================
36 // function : SetViewVolume
37 // purpose  : Retrieves view volume's planes equations and its vertices from projection and world-view matrices.
38 // =======================================================================
39 void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera)
40 {
41   if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState()))
42     return;
43
44   myIsProjectionParallel = theCamera->IsOrthographic();
45   const gp_Dir aCamDir = theCamera->Direction();
46
47   myCamera             = theCamera;
48   myProjectionMat      = theCamera->ProjectionMatrix();
49   myWorldViewMat       = theCamera->OrientationMatrix();
50   myWorldViewProjState = theCamera->WorldViewProjState();
51   myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z());
52   myCamDir.SetValues (aCamDir.X(), aCamDir.Y(), aCamDir.Z());
53   myCamScale = theCamera->IsOrthographic()
54              ? theCamera->Scale()
55              : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance()
56
57   // Compute frustum points
58   theCamera->FrustumPoints (myClipVerts);
59
60   // Compute frustum planes
61   // Vertices go in order:
62   // 0, 2, 1
63   const Standard_Integer aLookup1[] = { 0, 1, 0 };
64   const Standard_Integer aLookup2[] = { 0, 0, 1 };
65   Standard_Integer aShifts[]        = { 0, 0, 0 };
66
67   // Planes go in order:
68   // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
69   for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
70   {
71     for (Standard_Integer i = 0; i < 2; ++i)
72     {
73       OpenGl_Vec3d aPlanePnts[3];
74       for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter)
75       {
76         aShifts[aFaceIdx] = i;
77         aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter];
78         aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter];
79         
80         aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]];
81       }
82       
83       myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0];
84       myClipPlanes[aFaceIdx * 2 + i].Normal =
85           OpenGl_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0],
86                                aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f);
87       }
88   }
89 }
90
91 // =======================================================================
92 // function : SetViewportSize
93 // purpose  :
94 // =======================================================================
95 void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth,
96                                               Standard_Integer theViewportHeight,
97                                               Standard_Real theResolutionRatio)
98 {
99   myViewportHeight = theViewportHeight;
100   myViewportWidth  = theViewportWidth;
101   myPixelSize = Max (theResolutionRatio / theViewportHeight,
102                      theResolutionRatio / theViewportWidth);
103 }
104
105 // =======================================================================
106 // function : SignedPlanePointDistance
107 // purpose  :
108 // =======================================================================
109 Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4d& theNormal,
110                                                                 const OpenGl_Vec4d& thePnt)
111 {
112   const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x()
113                                              + theNormal.y() * theNormal.y()
114                                              + theNormal.z() * theNormal.z());
115
116   if (aNormLength < gp::Resolution())
117     return 0.0;
118
119   const Standard_Real anInvNormLength = 1.0 / aNormLength;
120   const Standard_Real aD  = theNormal.w() * anInvNormLength;
121   const Standard_Real anA = theNormal.x() * anInvNormLength;
122   const Standard_Real aB  = theNormal.y() * anInvNormLength;
123   const Standard_Real aC  = theNormal.z() * anInvNormLength;
124   return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z());
125 }
126
127 // =======================================================================
128 // function : SetCullingDistance
129 // purpose  :
130 // =======================================================================
131 void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx,
132                                                  Standard_Real theDistance) const
133 {
134   theCtx.DistCull = -1.0;
135   if (!myIsProjectionParallel)
136   {
137     theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance)
138                     ? theDistance
139                     : -1.0;
140   }
141 }
142
143 // =======================================================================
144 // function : SetCullingSize
145 // purpose  :
146 // =======================================================================
147 void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx,
148                                              Standard_Real theSize) const
149 {
150   theCtx.SizeCull2 = -1.0;
151   if (theSize > 0.0 && !Precision::IsInfinite (theSize))
152   {
153     theCtx.SizeCull2 = myPixelSize * theSize;
154     theCtx.SizeCull2 *= myCamScale;
155     theCtx.SizeCull2 *= theCtx.SizeCull2;
156   }
157 }
158
159 // =======================================================================
160 // function : CacheClipPtsProjections
161 // purpose  :
162 // =======================================================================
163 void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
164 {
165   // project frustum onto its own normals
166   const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
167   for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
168   {
169     Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
170     Standard_Real aMinProj =  std::numeric_limits<Standard_Real>::max();
171     for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter)
172     {
173       Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal);
174       aMaxProj = Max (aProjection, aMaxProj);
175       aMinProj = Min (aProjection, aMinProj);
176     }
177     myMaxClipProjectionPts[aPlaneIter] = aMaxProj;
178     myMinClipProjectionPts[aPlaneIter] = aMinProj;
179   }
180
181   // project frustum onto main axes
182   OpenGl_Vec3d anAxes[] = { OpenGl_Vec3d (1.0, 0.0, 0.0),
183                             OpenGl_Vec3d (0.0, 1.0, 0.0),
184                             OpenGl_Vec3d (0.0, 0.0, 1.0) };
185   for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
186   {
187     Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
188     Standard_Real aMinProj =  std::numeric_limits<Standard_Real>::max();
189     for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter)
190     {
191       Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]);
192       aMaxProj = Max (aProjection, aMaxProj);
193       aMinProj = Min (aProjection, aMinProj);
194     }
195     myMaxOrthoProjectionPts[aDim] = aMaxProj;
196     myMinOrthoProjectionPts[aDim] = aMinProj;
197   }
198 }