1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-31 11:15:31 +03:00
occt/src/Graphic3d/Graphic3d_CullingTool.cxx
Pasukhin Dmitry 1f386af59f
Coding - Update method guards for consistency #333
Apply new regex replacement with method's guards in .cxx
Update GH workflow with style checking
2025-02-03 11:16:00 +00:00

196 lines
7.6 KiB
C++

// Created on: 2013-12-25
// Created by: Varvara POSKONINA
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Graphic3d_CullingTool.hxx>
#include <Precision.hxx>
#include <limits>
//=================================================================================================
Graphic3d_CullingTool::Graphic3d_CullingTool()
: myClipVerts(0, Graphic3d_Camera::FrustumVerticesNB),
myIsProjectionParallel(Standard_True),
myCamScale(1.0),
myPixelSize(1.0)
{
//
}
//=================================================================================================
void Graphic3d_CullingTool::SetViewVolume(const Handle(Graphic3d_Camera)& theCamera,
const Graphic3d_Mat4d& theModelWorld)
{
const bool hasModelTrsf = !theModelWorld.IsIdentity();
if (!myWorldViewProjState.IsChanged(theCamera->WorldViewProjState()) && !hasModelTrsf)
{
return;
}
myIsProjectionParallel = theCamera->IsOrthographic();
const gp_Dir aCamDir = theCamera->Direction();
myCamera = theCamera;
myProjectionMat = theCamera->ProjectionMatrix();
myWorldViewMat = theCamera->OrientationMatrix();
myWorldViewProjState = theCamera->WorldViewProjState();
myCamEye.SetValues(theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z());
myCamDir.SetValues(aCamDir.X(), aCamDir.Y(), aCamDir.Z());
if (hasModelTrsf)
{
Graphic3d_Mat4d aModelInv;
theModelWorld.Inverted(aModelInv);
myCamEye = (aModelInv * Graphic3d_Vec4d(myCamEye, 1.0)).xyz();
myCamDir = (aModelInv * Graphic3d_Vec4d(myCamDir, 0.0)).xyz();
}
myCamScale = theCamera->IsOrthographic()
? theCamera->Scale()
: 2.0
* Tan(theCamera->FOVy() * M_PI
/ 360.0); // same as theCamera->Scale()/theCamera->Distance()
// Compute frustum points
theCamera->FrustumPoints(myClipVerts, theModelWorld);
// Compute frustum planes
// Vertices go in order:
// 0, 2, 1
const Standard_Integer aLookup1[] = {0, 1, 0};
const Standard_Integer aLookup2[] = {0, 0, 1};
Standard_Integer aShifts[] = {0, 0, 0};
// Planes go in order:
// LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
{
for (Standard_Integer i = 0; i < 2; ++i)
{
Graphic3d_Vec3d aPlanePnts[3];
for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter)
{
aShifts[aFaceIdx] = i;
aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter];
aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter];
aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]];
}
myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0];
myClipPlanes[aFaceIdx * 2 + i].Normal =
Graphic3d_Vec3d::Cross(aPlanePnts[1] - aPlanePnts[0], aPlanePnts[2] - aPlanePnts[0])
.Normalized()
* (i == 0 ? -1.f : 1.f);
}
}
}
//=================================================================================================
void Graphic3d_CullingTool::SetViewportSize(Standard_Integer theViewportWidth,
Standard_Integer theViewportHeight,
Standard_Real theResolutionRatio)
{
myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1;
myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1;
myPixelSize = Max(theResolutionRatio / myViewportHeight, theResolutionRatio / myViewportWidth);
}
//=================================================================================================
Standard_Real Graphic3d_CullingTool::SignedPlanePointDistance(const Graphic3d_Vec4d& theNormal,
const Graphic3d_Vec4d& thePnt)
{
const Standard_Real aNormLength = std::sqrt(
theNormal.x() * theNormal.x() + theNormal.y() * theNormal.y() + theNormal.z() * theNormal.z());
if (aNormLength < gp::Resolution())
return 0.0;
const Standard_Real anInvNormLength = 1.0 / aNormLength;
const Standard_Real aD = theNormal.w() * anInvNormLength;
const Standard_Real anA = theNormal.x() * anInvNormLength;
const Standard_Real aB = theNormal.y() * anInvNormLength;
const Standard_Real aC = theNormal.z() * anInvNormLength;
return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z());
}
//=================================================================================================
void Graphic3d_CullingTool::SetCullingDistance(CullingContext& theCtx,
Standard_Real theDistance) const
{
theCtx.DistCull = -1.0;
if (!myIsProjectionParallel)
{
theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite(theDistance) ? theDistance : -1.0;
}
}
//=================================================================================================
void Graphic3d_CullingTool::SetCullingSize(CullingContext& theCtx, Standard_Real theSize) const
{
theCtx.SizeCull2 = -1.0;
if (theSize > 0.0 && !Precision::IsInfinite(theSize))
{
theCtx.SizeCull2 = myPixelSize * theSize;
theCtx.SizeCull2 *= myCamScale;
theCtx.SizeCull2 *= theCtx.SizeCull2;
}
}
//=================================================================================================
void Graphic3d_CullingTool::CacheClipPtsProjections()
{
// project frustum onto its own normals
const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
{
Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB;
++aCornerIter)
{
Standard_Real aProjection = myClipVerts[aCornerIter].Dot(myClipPlanes[aPlaneIter].Normal);
aMaxProj = Max(aProjection, aMaxProj);
aMinProj = Min(aProjection, aMinProj);
}
myMaxClipProjectionPts[aPlaneIter] = aMaxProj;
myMinClipProjectionPts[aPlaneIter] = aMinProj;
}
// project frustum onto main axes
Graphic3d_Vec3d anAxes[] = {Graphic3d_Vec3d(1.0, 0.0, 0.0),
Graphic3d_Vec3d(0.0, 1.0, 0.0),
Graphic3d_Vec3d(0.0, 0.0, 1.0)};
for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
{
Standard_Real aMaxProj = -std::numeric_limits<Standard_Real>::max();
Standard_Real aMinProj = std::numeric_limits<Standard_Real>::max();
for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB;
++aCornerIter)
{
Standard_Real aProjection = myClipVerts[aCornerIter].Dot(anAxes[aDim]);
aMaxProj = Max(aProjection, aMaxProj);
aMinProj = Min(aProjection, aMinProj);
}
myMaxOrthoProjectionPts[aDim] = aMaxProj;
myMinOrthoProjectionPts[aDim] = aMinProj;
}
}