0030058: Visualization, Select3D_SensitivePrimitiveArray - the selection is not fast...
[occt.git] / src / OpenGl / OpenGl_BVHTreeSelector.cxx
CommitLineData
b7cd4ba7 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
14a35e5d 16#include <limits>
17
b7cd4ba7 18#include <OpenGl_BVHTreeSelector.hxx>
19#include <OpenGl_BVHClipPrimitiveSet.hxx>
c04c30b3 20#include <Graphic3d_GraphicDriver.hxx>
b7cd4ba7 21
b7cd4ba7 22// =======================================================================
23// function : OpenGl_BVHTreeSelector
24// purpose :
25// =======================================================================
26OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
4ecf34cc 27: myIsProjectionParallel (Standard_True),
f29de682 28 myCamScale (1.0),
2b8832bb 29 myPixelSize (1.0)
b7cd4ba7 30{
31 //
32}
33
34// =======================================================================
825aa485 35// function : SetViewVolume
36// purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices.
b7cd4ba7 37// =======================================================================
38void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera)
39{
97f937cc 40 if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState()))
825aa485 41 return;
825aa485 42
b7cd4ba7 43 myIsProjectionParallel = theCamera->IsOrthographic();
f29de682 44 const gp_Dir aCamDir = theCamera->Direction();
825aa485 45
3fe9ce0e 46 myCamera = theCamera;
7c3ef2f7 47 myProjectionMat = theCamera->ProjectionMatrix();
48 myWorldViewMat = theCamera->OrientationMatrix();
825aa485 49 myWorldViewProjState = theCamera->WorldViewProjState();
4ecf34cc 50 myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z());
f29de682 51 myCamDir.SetValues (aCamDir.X(), aCamDir.Y(), aCamDir.Z());
52 myCamScale = theCamera->IsOrthographic()
53 ? theCamera->Scale()
54 : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance()
b7cd4ba7 55
7c3ef2f7 56 Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0;
57 Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0;
58 Standard_Real aNear = 0.0, aFar = 0.0;
b7cd4ba7 59 if (!myIsProjectionParallel)
60 {
61 // handle perspective projection
7c3ef2f7 62 aNear = myProjectionMat.GetValue (2, 3) / (- 1.0 + myProjectionMat.GetValue (2, 2));
63 aFar = myProjectionMat.GetValue (2, 3) / ( 1.0 + myProjectionMat.GetValue (2, 2));
b7cd4ba7 64 // Near plane
7c3ef2f7 65 nLeft = aNear * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
66 nRight = aNear * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
67 nTop = aNear * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
68 nBottom = aNear * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
b7cd4ba7 69 // Far plane
7c3ef2f7 70 fLeft = aFar * (myProjectionMat.GetValue (0, 2) - 1.0) / myProjectionMat.GetValue (0, 0);
71 fRight = aFar * (myProjectionMat.GetValue (0, 2) + 1.0) / myProjectionMat.GetValue (0, 0);
72 fTop = aFar * (myProjectionMat.GetValue (1, 2) + 1.0) / myProjectionMat.GetValue (1, 1);
73 fBottom = aFar * (myProjectionMat.GetValue (1, 2) - 1.0) / myProjectionMat.GetValue (1, 1);
b7cd4ba7 74 }
75 else
76 {
77 // handle orthographic projection
7c3ef2f7 78 aNear = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) + 1.0);
79 aFar = (1.0 / myProjectionMat.GetValue (2, 2)) * (myProjectionMat.GetValue (2, 3) - 1.0);
b7cd4ba7 80 // Near plane
7c3ef2f7 81 nLeft = ( 1.0 + myProjectionMat.GetValue (0, 3)) / (-myProjectionMat.GetValue (0, 0));
b7cd4ba7 82 fLeft = nLeft;
7c3ef2f7 83 nRight = ( 1.0 - myProjectionMat.GetValue (0, 3)) / myProjectionMat.GetValue (0, 0);
b7cd4ba7 84 fRight = nRight;
7c3ef2f7 85 nTop = ( 1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
b7cd4ba7 86 fTop = nTop;
7c3ef2f7 87 nBottom = (-1.0 - myProjectionMat.GetValue (1, 3)) / myProjectionMat.GetValue (1, 1);
b7cd4ba7 88 fBottom = nBottom;
89 }
90
7c3ef2f7 91 OpenGl_Vec4d aLeftTopNear (nLeft, nTop, -aNear, 1.0), aRightBottomFar (fRight, fBottom, -aFar, 1.0);
92 OpenGl_Vec4d aLeftBottomNear (nLeft, nBottom, -aNear, 1.0), aRightTopFar (fRight, fTop, -aFar, 1.0);
93 OpenGl_Vec4d aRightBottomNear (nRight, nBottom, -aNear, 1.0), aLeftTopFar (fLeft, fTop, -aFar, 1.0);
94 OpenGl_Vec4d aRightTopNear (nRight, nTop, -aNear, 1.0), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0);
b7cd4ba7 95
7c3ef2f7 96 const OpenGl_Mat4d aViewProj = myWorldViewMat * myProjectionMat;
97 OpenGl_Mat4d anInvWorldView;
98 myWorldViewMat.Inverted (anInvWorldView);
b7cd4ba7 99
825aa485 100 myClipVerts[ClipVert_LeftTopNear] = anInvWorldView * aLeftTopNear;
101 myClipVerts[ClipVert_RightBottomFar] = anInvWorldView * aRightBottomFar;
102 myClipVerts[ClipVert_LeftBottomNear] = anInvWorldView * aLeftBottomNear;
103 myClipVerts[ClipVert_RightTopFar] = anInvWorldView * aRightTopFar;
104 myClipVerts[ClipVert_RightBottomNear] = anInvWorldView * aRightBottomNear;
105 myClipVerts[ClipVert_LeftTopFar] = anInvWorldView * aLeftTopFar;
106 myClipVerts[ClipVert_RightTopNear] = anInvWorldView * aRightTopNear;
107 myClipVerts[ClipVert_LeftBottomFar] = anInvWorldView * aLeftBottomFar;
b7cd4ba7 108
109 // UNNORMALIZED!
110 myClipPlanes[Plane_Left] = aViewProj.GetRow (3) + aViewProj.GetRow (0);
111 myClipPlanes[Plane_Right] = aViewProj.GetRow (3) - aViewProj.GetRow (0);
112 myClipPlanes[Plane_Top] = aViewProj.GetRow (3) - aViewProj.GetRow (1);
113 myClipPlanes[Plane_Bottom] = aViewProj.GetRow (3) + aViewProj.GetRow (1);
114 myClipPlanes[Plane_Near] = aViewProj.GetRow (3) + aViewProj.GetRow (2);
115 myClipPlanes[Plane_Far] = aViewProj.GetRow (3) - aViewProj.GetRow (2);
116
117 gp_Pnt aPtCenter = theCamera->Center();
7c3ef2f7 118 OpenGl_Vec4d aCenter (aPtCenter.X(), aPtCenter.Y(), aPtCenter.Z(), 1.0);
b7cd4ba7 119
120 for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB; ++aPlaneIter)
121 {
7c3ef2f7 122 OpenGl_Vec4d anEq = myClipPlanes[aPlaneIter];
b7cd4ba7 123 if (SignedPlanePointDistance (anEq, aCenter) > 0)
124 {
7c3ef2f7 125 anEq *= -1.0;
b7cd4ba7 126 myClipPlanes[aPlaneIter] = anEq;
127 }
128 }
129}
130
91d96372 131// =======================================================================
132// function : SetViewportSize
133// purpose :
134// =======================================================================
4ecf34cc 135void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth,
136 Standard_Integer theViewportHeight,
137 Standard_Real theResolutionRatio)
91d96372 138{
139 myViewportHeight = theViewportHeight;
4ecf34cc 140 myViewportWidth = theViewportWidth;
141 myPixelSize = Max (theResolutionRatio / theViewportHeight,
142 theResolutionRatio / theViewportWidth);
91d96372 143}
144
b7cd4ba7 145// =======================================================================
146// function : SignedPlanePointDistance
147// purpose :
148// =======================================================================
7c3ef2f7 149Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4d& theNormal,
150 const OpenGl_Vec4d& thePnt)
b7cd4ba7 151{
7c3ef2f7 152 const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x()
153 + theNormal.y() * theNormal.y()
154 + theNormal.z() * theNormal.z());
3c648527 155
7c3ef2f7 156 if (aNormLength < gp::Resolution())
157 return 0.0;
3c648527 158
7c3ef2f7 159 const Standard_Real anInvNormLength = 1.0 / aNormLength;
160 const Standard_Real aD = theNormal.w() * anInvNormLength;
161 const Standard_Real anA = theNormal.x() * anInvNormLength;
162 const Standard_Real aB = theNormal.y() * anInvNormLength;
163 const Standard_Real aC = theNormal.z() * anInvNormLength;
b7cd4ba7 164 return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z());
165}
166
4ecf34cc 167// =======================================================================
168// function : SetCullingDistance
169// purpose :
170// =======================================================================
2b8832bb 171void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx,
172 Standard_Real theDistance) const
4ecf34cc 173{
2b8832bb 174 theCtx.DistCull = -1.0;
4ecf34cc 175 if (!myIsProjectionParallel)
176 {
2b8832bb 177 theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance)
178 ? theDistance
179 : -1.0;
4ecf34cc 180 }
181}
182
183// =======================================================================
184// function : SetCullingSize
185// purpose :
186// =======================================================================
2b8832bb 187void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx,
188 Standard_Real theSize) const
4ecf34cc 189{
2b8832bb 190 theCtx.SizeCull2 = -1.0;
4ecf34cc 191 if (theSize > 0.0 && !Precision::IsInfinite (theSize))
192 {
f29de682 193 theCtx.SizeCull2 = myPixelSize * theSize;
194 theCtx.SizeCull2 *= myCamScale;
2b8832bb 195 theCtx.SizeCull2 *= theCtx.SizeCull2;
4ecf34cc 196 }
197}
198
b7cd4ba7 199// =======================================================================
200// function : CacheClipPtsProjections
4ecf34cc 201// purpose :
b7cd4ba7 202// =======================================================================
203void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
204{
14a35e5d 205 const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
206 for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
b7cd4ba7 207 {
7c3ef2f7 208 const OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
209 Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
210 Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
b7cd4ba7 211 for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
212 {
7c3ef2f7 213 Standard_Real aProjection = aPlane.x() * myClipVerts[aCornerIter].x()
214 + aPlane.y() * myClipVerts[aCornerIter].y()
215 + aPlane.z() * myClipVerts[aCornerIter].z();
14a35e5d 216 aMaxProj = Max (aProjection, aMaxProj);
217 aMinProj = Min (aProjection, aMinProj);
b7cd4ba7 218 }
14a35e5d 219 myMaxClipProjectionPts[aPlaneIter] = aMaxProj;
220 myMinClipProjectionPts[aPlaneIter] = aMinProj;
b7cd4ba7 221 }
222
b7cd4ba7 223 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
224 {
7c3ef2f7 225 Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
226 Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
b7cd4ba7 227 for (Standard_Integer aCornerIter = 0; aCornerIter < ClipVerticesNB; ++aCornerIter)
228 {
7c3ef2f7 229 Standard_Real aProjection = aDim == 0
230 ? myClipVerts[aCornerIter].x()
231 : (aDim == 1
232 ? myClipVerts[aCornerIter].y()
233 : myClipVerts[aCornerIter].z());
14a35e5d 234 aMaxProj = Max (aProjection, aMaxProj);
235 aMinProj = Min (aProjection, aMinProj);
b7cd4ba7 236 }
14a35e5d 237 myMaxOrthoProjectionPts[aDim] = aMaxProj;
238 myMinOrthoProjectionPts[aDim] = aMinProj;
b7cd4ba7 239 }
240}