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 |
26 | Graphic3d_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 |
37 | // purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices. |
b7cd4ba7 |
38 | // ======================================================================= |
d325cb7f |
39 | void Graphic3d_CullingTool::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) |
b7cd4ba7 |
40 | { |
97f937cc |
41 | if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState())) |
825aa485 |
42 | return; |
825aa485 |
43 | |
b7cd4ba7 |
44 | myIsProjectionParallel = theCamera->IsOrthographic(); |
f29de682 |
45 | const gp_Dir aCamDir = theCamera->Direction(); |
825aa485 |
46 | |
3fe9ce0e |
47 | myCamera = theCamera; |
7c3ef2f7 |
48 | myProjectionMat = theCamera->ProjectionMatrix(); |
49 | myWorldViewMat = theCamera->OrientationMatrix(); |
825aa485 |
50 | myWorldViewProjState = theCamera->WorldViewProjState(); |
4ecf34cc |
51 | myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z()); |
f29de682 |
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() |
b7cd4ba7 |
56 | |
30a1b24e |
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 }; |
b7cd4ba7 |
66 | |
30a1b24e |
67 | // Planes go in order: |
68 | // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR |
69 | for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx) |
b7cd4ba7 |
70 | { |
30a1b24e |
71 | for (Standard_Integer i = 0; i < 2; ++i) |
b7cd4ba7 |
72 | { |
d325cb7f |
73 | Graphic3d_Vec3d aPlanePnts[3]; |
30a1b24e |
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 = |
d325cb7f |
85 | Graphic3d_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0], |
86 | aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f); |
30a1b24e |
87 | } |
b7cd4ba7 |
88 | } |
89 | } |
90 | |
91d96372 |
91 | // ======================================================================= |
92 | // function : SetViewportSize |
93 | // purpose : |
94 | // ======================================================================= |
d325cb7f |
95 | void Graphic3d_CullingTool::SetViewportSize (Standard_Integer theViewportWidth, |
96 | Standard_Integer theViewportHeight, |
97 | Standard_Real theResolutionRatio) |
91d96372 |
98 | { |
d918208a |
99 | myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1; |
100 | myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1; |
101 | myPixelSize = Max (theResolutionRatio / myViewportHeight, |
102 | theResolutionRatio / myViewportWidth); |
91d96372 |
103 | } |
104 | |
b7cd4ba7 |
105 | // ======================================================================= |
106 | // function : SignedPlanePointDistance |
107 | // purpose : |
108 | // ======================================================================= |
d325cb7f |
109 | Standard_Real Graphic3d_CullingTool::SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal, |
110 | const Graphic3d_Vec4d& thePnt) |
b7cd4ba7 |
111 | { |
7c3ef2f7 |
112 | const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x() |
113 | + theNormal.y() * theNormal.y() |
114 | + theNormal.z() * theNormal.z()); |
3c648527 |
115 | |
7c3ef2f7 |
116 | if (aNormLength < gp::Resolution()) |
117 | return 0.0; |
3c648527 |
118 | |
7c3ef2f7 |
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; |
b7cd4ba7 |
124 | return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z()); |
125 | } |
126 | |
4ecf34cc |
127 | // ======================================================================= |
128 | // function : SetCullingDistance |
129 | // purpose : |
130 | // ======================================================================= |
d325cb7f |
131 | void Graphic3d_CullingTool::SetCullingDistance (CullingContext& theCtx, |
132 | Standard_Real theDistance) const |
4ecf34cc |
133 | { |
2b8832bb |
134 | theCtx.DistCull = -1.0; |
4ecf34cc |
135 | if (!myIsProjectionParallel) |
136 | { |
2b8832bb |
137 | theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) |
138 | ? theDistance |
139 | : -1.0; |
4ecf34cc |
140 | } |
141 | } |
142 | |
143 | // ======================================================================= |
144 | // function : SetCullingSize |
145 | // purpose : |
146 | // ======================================================================= |
d325cb7f |
147 | void Graphic3d_CullingTool::SetCullingSize (CullingContext& theCtx, |
148 | Standard_Real theSize) const |
4ecf34cc |
149 | { |
2b8832bb |
150 | theCtx.SizeCull2 = -1.0; |
4ecf34cc |
151 | if (theSize > 0.0 && !Precision::IsInfinite (theSize)) |
152 | { |
f29de682 |
153 | theCtx.SizeCull2 = myPixelSize * theSize; |
154 | theCtx.SizeCull2 *= myCamScale; |
2b8832bb |
155 | theCtx.SizeCull2 *= theCtx.SizeCull2; |
4ecf34cc |
156 | } |
157 | } |
158 | |
b7cd4ba7 |
159 | // ======================================================================= |
160 | // function : CacheClipPtsProjections |
4ecf34cc |
161 | // purpose : |
b7cd4ba7 |
162 | // ======================================================================= |
d325cb7f |
163 | void Graphic3d_CullingTool::CacheClipPtsProjections() |
b7cd4ba7 |
164 | { |
30a1b24e |
165 | // project frustum onto its own normals |
14a35e5d |
166 | const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; |
30a1b24e |
167 | for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) |
b7cd4ba7 |
168 | { |
7c3ef2f7 |
169 | Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max(); |
170 | Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max(); |
30a1b24e |
171 | for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) |
b7cd4ba7 |
172 | { |
30a1b24e |
173 | Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal); |
14a35e5d |
174 | aMaxProj = Max (aProjection, aMaxProj); |
175 | aMinProj = Min (aProjection, aMinProj); |
b7cd4ba7 |
176 | } |
14a35e5d |
177 | myMaxClipProjectionPts[aPlaneIter] = aMaxProj; |
178 | myMinClipProjectionPts[aPlaneIter] = aMinProj; |
b7cd4ba7 |
179 | } |
180 | |
30a1b24e |
181 | // project frustum onto main axes |
d325cb7f |
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) }; |
b7cd4ba7 |
185 | for (Standard_Integer aDim = 0; aDim < 3; ++aDim) |
186 | { |
7c3ef2f7 |
187 | Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max(); |
188 | Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max(); |
30a1b24e |
189 | for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) |
b7cd4ba7 |
190 | { |
30a1b24e |
191 | Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]); |
14a35e5d |
192 | aMaxProj = Max (aProjection, aMaxProj); |
193 | aMinProj = Min (aProjection, aMinProj); |
b7cd4ba7 |
194 | } |
14a35e5d |
195 | myMaxOrthoProjectionPts[aDim] = aMaxProj; |
196 | myMinOrthoProjectionPts[aDim] = aMinProj; |
b7cd4ba7 |
197 | } |
198 | } |