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.
16 #include <Graphic3d_CullingTool.hxx>
18 #include <Precision.hxx>
22 // =======================================================================
23 // function : Graphic3d_CullingTool
25 // =======================================================================
26 Graphic3d_CullingTool::Graphic3d_CullingTool()
27 : myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB),
28 myIsProjectionParallel (Standard_True),
35 // =======================================================================
36 // function : SetViewVolume
37 // purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices.
38 // =======================================================================
39 void Graphic3d_CullingTool::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera)
41 if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState()))
44 myIsProjectionParallel = theCamera->IsOrthographic();
45 const gp_Dir aCamDir = theCamera->Direction();
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()
55 : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance()
57 // Compute frustum points
58 theCamera->FrustumPoints (myClipVerts);
60 // Compute frustum planes
61 // Vertices go in order:
63 const Standard_Integer aLookup1[] = { 0, 1, 0 };
64 const Standard_Integer aLookup2[] = { 0, 0, 1 };
65 Standard_Integer aShifts[] = { 0, 0, 0 };
67 // Planes go in order:
68 // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
69 for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
71 for (Standard_Integer i = 0; i < 2; ++i)
73 Graphic3d_Vec3d aPlanePnts[3];
74 for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter)
76 aShifts[aFaceIdx] = i;
77 aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter];
78 aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter];
80 aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]];
83 myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0];
84 myClipPlanes[aFaceIdx * 2 + i].Normal =
85 Graphic3d_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0],
86 aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f);
91 // =======================================================================
92 // function : SetViewportSize
94 // =======================================================================
95 void Graphic3d_CullingTool::SetViewportSize (Standard_Integer theViewportWidth,
96 Standard_Integer theViewportHeight,
97 Standard_Real theResolutionRatio)
99 myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1;
100 myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1;
101 myPixelSize = Max (theResolutionRatio / myViewportHeight,
102 theResolutionRatio / myViewportWidth);
105 // =======================================================================
106 // function : SignedPlanePointDistance
108 // =======================================================================
109 Standard_Real Graphic3d_CullingTool::SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal,
110 const Graphic3d_Vec4d& thePnt)
112 const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x()
113 + theNormal.y() * theNormal.y()
114 + theNormal.z() * theNormal.z());
116 if (aNormLength < gp::Resolution())
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());
127 // =======================================================================
128 // function : SetCullingDistance
130 // =======================================================================
131 void Graphic3d_CullingTool::SetCullingDistance (CullingContext& theCtx,
132 Standard_Real theDistance) const
134 theCtx.DistCull = -1.0;
135 if (!myIsProjectionParallel)
137 theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance)
143 // =======================================================================
144 // function : SetCullingSize
146 // =======================================================================
147 void Graphic3d_CullingTool::SetCullingSize (CullingContext& theCtx,
148 Standard_Real theSize) const
150 theCtx.SizeCull2 = -1.0;
151 if (theSize > 0.0 && !Precision::IsInfinite (theSize))
153 theCtx.SizeCull2 = myPixelSize * theSize;
154 theCtx.SizeCull2 *= myCamScale;
155 theCtx.SizeCull2 *= theCtx.SizeCull2;
159 // =======================================================================
160 // function : CacheClipPtsProjections
162 // =======================================================================
163 void Graphic3d_CullingTool::CacheClipPtsProjections()
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)
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)
173 Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal);
174 aMaxProj = Max (aProjection, aMaxProj);
175 aMinProj = Min (aProjection, aMinProj);
177 myMaxClipProjectionPts[aPlaneIter] = aMaxProj;
178 myMinClipProjectionPts[aPlaneIter] = aMinProj;
181 // project frustum onto main axes
182 Graphic3d_Vec3d anAxes[] = { Graphic3d_Vec3d (1.0, 0.0, 0.0),
183 Graphic3d_Vec3d (0.0, 1.0, 0.0),
184 Graphic3d_Vec3d (0.0, 0.0, 1.0) };
185 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
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)
191 Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]);
192 aMaxProj = Max (aProjection, aMaxProj);
193 aMinProj = Min (aProjection, aMinProj);
195 myMaxOrthoProjectionPts[aDim] = aMaxProj;
196 myMinOrthoProjectionPts[aDim] = aMinProj;