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