| 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 | |
| 16 | #include <limits> |
| 17 | |
| 18 | #include <OpenGl_BVHTreeSelector.hxx> |
| 19 | #include <OpenGl_BVHClipPrimitiveSet.hxx> |
| 20 | #include <Graphic3d_GraphicDriver.hxx> |
| 21 | |
| 22 | // ======================================================================= |
| 23 | // function : OpenGl_BVHTreeSelector |
| 24 | // purpose : |
| 25 | // ======================================================================= |
| 26 | OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() |
| 27 | : myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB), |
| 28 | myIsProjectionParallel (Standard_True), |
| 29 | myCamScale (1.0), |
| 30 | myPixelSize (1.0) |
| 31 | { |
| 32 | // |
| 33 | } |
| 34 | |
| 35 | // ======================================================================= |
| 36 | // function : SetViewVolume |
| 37 | // purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices. |
| 38 | // ======================================================================= |
| 39 | void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) |
| 40 | { |
| 41 | if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState())) |
| 42 | return; |
| 43 | |
| 44 | myIsProjectionParallel = theCamera->IsOrthographic(); |
| 45 | const gp_Dir aCamDir = theCamera->Direction(); |
| 46 | |
| 47 | myCamera = theCamera; |
| 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() |
| 54 | ? theCamera->Scale() |
| 55 | : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance() |
| 56 | |
| 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 }; |
| 66 | |
| 67 | // Planes go in order: |
| 68 | // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR |
| 69 | for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx) |
| 70 | { |
| 71 | for (Standard_Integer i = 0; i < 2; ++i) |
| 72 | { |
| 73 | OpenGl_Vec3d aPlanePnts[3]; |
| 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 = |
| 85 | OpenGl_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0], |
| 86 | aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f); |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // ======================================================================= |
| 92 | // function : SetViewportSize |
| 93 | // purpose : |
| 94 | // ======================================================================= |
| 95 | void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth, |
| 96 | Standard_Integer theViewportHeight, |
| 97 | Standard_Real theResolutionRatio) |
| 98 | { |
| 99 | myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1; |
| 100 | myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1; |
| 101 | myPixelSize = Max (theResolutionRatio / myViewportHeight, |
| 102 | theResolutionRatio / myViewportWidth); |
| 103 | } |
| 104 | |
| 105 | // ======================================================================= |
| 106 | // function : SignedPlanePointDistance |
| 107 | // purpose : |
| 108 | // ======================================================================= |
| 109 | Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4d& theNormal, |
| 110 | const OpenGl_Vec4d& thePnt) |
| 111 | { |
| 112 | const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x() |
| 113 | + theNormal.y() * theNormal.y() |
| 114 | + theNormal.z() * theNormal.z()); |
| 115 | |
| 116 | if (aNormLength < gp::Resolution()) |
| 117 | return 0.0; |
| 118 | |
| 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()); |
| 125 | } |
| 126 | |
| 127 | // ======================================================================= |
| 128 | // function : SetCullingDistance |
| 129 | // purpose : |
| 130 | // ======================================================================= |
| 131 | void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx, |
| 132 | Standard_Real theDistance) const |
| 133 | { |
| 134 | theCtx.DistCull = -1.0; |
| 135 | if (!myIsProjectionParallel) |
| 136 | { |
| 137 | theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) |
| 138 | ? theDistance |
| 139 | : -1.0; |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | // ======================================================================= |
| 144 | // function : SetCullingSize |
| 145 | // purpose : |
| 146 | // ======================================================================= |
| 147 | void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx, |
| 148 | Standard_Real theSize) const |
| 149 | { |
| 150 | theCtx.SizeCull2 = -1.0; |
| 151 | if (theSize > 0.0 && !Precision::IsInfinite (theSize)) |
| 152 | { |
| 153 | theCtx.SizeCull2 = myPixelSize * theSize; |
| 154 | theCtx.SizeCull2 *= myCamScale; |
| 155 | theCtx.SizeCull2 *= theCtx.SizeCull2; |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | // ======================================================================= |
| 160 | // function : CacheClipPtsProjections |
| 161 | // purpose : |
| 162 | // ======================================================================= |
| 163 | void OpenGl_BVHTreeSelector::CacheClipPtsProjections() |
| 164 | { |
| 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) |
| 168 | { |
| 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) |
| 172 | { |
| 173 | Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal); |
| 174 | aMaxProj = Max (aProjection, aMaxProj); |
| 175 | aMinProj = Min (aProjection, aMinProj); |
| 176 | } |
| 177 | myMaxClipProjectionPts[aPlaneIter] = aMaxProj; |
| 178 | myMinClipProjectionPts[aPlaneIter] = aMinProj; |
| 179 | } |
| 180 | |
| 181 | // project frustum onto main axes |
| 182 | OpenGl_Vec3d anAxes[] = { OpenGl_Vec3d (1.0, 0.0, 0.0), |
| 183 | OpenGl_Vec3d (0.0, 1.0, 0.0), |
| 184 | OpenGl_Vec3d (0.0, 0.0, 1.0) }; |
| 185 | for (Standard_Integer aDim = 0; aDim < 3; ++aDim) |
| 186 | { |
| 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) |
| 190 | { |
| 191 | Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]); |
| 192 | aMaxProj = Max (aProjection, aMaxProj); |
| 193 | aMinProj = Min (aProjection, aMinProj); |
| 194 | } |
| 195 | myMaxOrthoProjectionPts[aDim] = aMaxProj; |
| 196 | myMinOrthoProjectionPts[aDim] = aMinProj; |
| 197 | } |
| 198 | } |