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 |
9ad4ff93 |
37 | // purpose : |
b7cd4ba7 |
38 | // ======================================================================= |
9ad4ff93 |
39 | void 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 |
107 | void 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 |
121 | Standard_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 |
143 | void 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 |
159 | void 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 |
175 | void 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 | } |