From 4ecf34cce7d5ea995a2ce1d35ffa91790fc42aa1 Mon Sep 17 00:00:00 2001 From: kgv Date: Sun, 5 Nov 2017 18:07:25 +0300 Subject: [PATCH] 0029295: Visualization, TKOpenGl - provide distance culling option Graphic3d_ZLayerSettings::CullingDistance() and ::CullingSize() - added new properties configuring culling of small and distant objects, disabled by default. OpenGl_BVHTreeSelector now handles size culling and distance culling in addition to frustom culling. --- src/Graphic3d/Graphic3d_ZLayerSettings.hxx | 30 ++++++++- src/OpenGl/OpenGl_BVHTreeSelector.cxx | 70 ++++++++++++++++++-- src/OpenGl/OpenGl_BVHTreeSelector.hxx | 25 +++++-- src/OpenGl/OpenGl_Layer.cxx | 28 ++++---- src/OpenGl/OpenGl_Layer.hxx | 2 +- src/OpenGl/OpenGl_View_Redraw.cxx | 5 +- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 30 +++++++++ tests/v3d/glsl/culldist | 34 ++++++++++ tests/v3d/glsl/cullsize | 51 ++++++++++++++ 9 files changed, 245 insertions(+), 30 deletions(-) create mode 100644 tests/v3d/glsl/culldist create mode 100644 tests/v3d/glsl/cullsize diff --git a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx index e7bf523b8d..8ca091dec4 100644 --- a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx +++ b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx @@ -33,7 +33,9 @@ struct Graphic3d_ZLayerSettings //! Default settings. Graphic3d_ZLayerSettings() - : myIsImmediate (Standard_False), + : myCullingDistance (Precision::Infinite()), + myCullingSize (Precision::Infinite()), + myIsImmediate (Standard_False), myUseEnvironmentTexture (Standard_True), myToEnableDepthTest (Standard_True), myToEnableDepthWrite(Standard_True), @@ -62,6 +64,30 @@ struct Graphic3d_ZLayerSettings } } + //! Return TRUE, if culling of distant objects (distance culling) should be performed; FALSE by default. + //! @sa CullingDistance() + Standard_Boolean HasCullingDistance() const { return !Precision::IsInfinite (myCullingDistance) && myCullingDistance > 0.0; } + + //! Return the distance to discard drawing of distant objects (distance from camera Eye point); by default it is Infinite (distance culling is disabled). + //! Since camera eye definition has no strong meaning within orthographic projection, option is considered only within perspective projection. + //! Note also that this option has effect only when frustum culling is enabled. + Standard_Real CullingDistance() const { return myCullingDistance; } + + //! Set the distance to discard drawing objects. + void SetCullingDistance (Standard_Real theDistance) { myCullingDistance = theDistance; } + + //! Return TRUE, if culling of small objects (size culling) should be performed; FALSE by default. + //! @sa CullingSize() + Standard_Boolean HasCullingSize() const { return !Precision::IsInfinite (myCullingSize) && myCullingSize > 0.0; } + + //! Return the size to discard drawing of small objects; by default it is Infinite (size culling is disabled). + //! Current implementation checks the length of projected diagonal of bounding box in pixels for discarding. + //! Note that this option has effect only when frustum culling is enabled. + Standard_Real CullingSize() const { return myCullingSize; } + + //! Set the distance to discard drawing objects. + void SetCullingSize (Standard_Real theSize) { myCullingSize = theSize; } + //! Return true if this layer should be drawn after all normal (non-immediate) layers. Standard_Boolean IsImmediate() const { return myIsImmediate; } @@ -162,6 +188,8 @@ protected: TCollection_AsciiString myName; //!< user-provided name Handle(Geom_Transformation) myOriginTrsf; //!< transformation to the origin gp_XYZ myOrigin; //!< the origin of all objects within the layer + Standard_Real myCullingDistance; //!< distance to discard objects + Standard_Real myCullingSize; //!< size to discard objects Graphic3d_PolygonOffset myPolygonOffset; //!< glPolygonOffset() arguments Standard_Boolean myIsImmediate; //!< immediate layer will be drawn after all normal layers Standard_Boolean myUseEnvironmentTexture; //!< flag to allow/prevent environment texture mapping usage for specific layer diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx index 21cfccbbd6..644b429fce 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.cxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.cxx @@ -24,7 +24,11 @@ // purpose : // ======================================================================= OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() -: myIsProjectionParallel (Standard_True) +: myIsProjectionParallel (Standard_True), + myCamScaleInv (1.0), + myDistCull (-1.0), + myPixelSize (1.0), + mySizeCull2 (-1.0) { // } @@ -44,6 +48,8 @@ void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theC myProjectionMat = theCamera->ProjectionMatrix(); myWorldViewMat = theCamera->OrientationMatrix(); myWorldViewProjState = theCamera->WorldViewProjState(); + myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z()); + myCamScaleInv = 1.0 / myCamera->Scale(); Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0; Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0; @@ -124,11 +130,14 @@ void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theC // function : SetViewportSize // purpose : // ======================================================================= -void OpenGl_BVHTreeSelector::SetViewportSize (const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight) +void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth, + Standard_Integer theViewportHeight, + Standard_Real theResolutionRatio) { myViewportHeight = theViewportHeight; - myViewportWidth = theViewportWidth; + myViewportWidth = theViewportWidth; + myPixelSize = Max (theResolutionRatio / theViewportHeight, + theResolutionRatio / theViewportWidth); } // ======================================================================= @@ -153,10 +162,38 @@ Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z()); } +// ======================================================================= +// function : SetCullingDistance +// purpose : +// ======================================================================= +void OpenGl_BVHTreeSelector::SetCullingDistance (Standard_Real theDistance) +{ + myDistCull = -1.0; + if (!myIsProjectionParallel) + { + myDistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) + ? theDistance + : -1.0; + } +} + +// ======================================================================= +// function : SetCullingSize +// purpose : +// ======================================================================= +void OpenGl_BVHTreeSelector::SetCullingSize (Standard_Real theSize) +{ + mySizeCull2 = -1.0; + if (theSize > 0.0 && !Precision::IsInfinite (theSize)) + { + mySizeCull2 = (myPixelSize * theSize) / myCamScaleInv; + mySizeCull2 *= mySizeCull2; + } +} + // ======================================================================= // function : CacheClipPtsProjections -// purpose : Caches view volume's vertices projections along its normals and AABBs dimensions -// Must be called at the beginning of each BVH tree traverse loop +// purpose : // ======================================================================= void OpenGl_BVHTreeSelector::CacheClipPtsProjections() { @@ -254,5 +291,26 @@ Standard_Boolean OpenGl_BVHTreeSelector::Intersect (const OpenGl_Vec3d& theMinPt } } + // distance culling - discard node if distance to it's bounding box from camera eye is less than specified culling distance + if (myDistCull > 0.0) + { + // check distance to the bounding sphere as fast approximation + const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5; + const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5; + if ((aSphereCenter - myCamEye).Modulus() - aSphereRadius > myDistCull) + { + return Standard_False; + } + } + + // size culling - discard node if diagonal of it's bounding box is less than specified culling size + if (mySizeCull2 > 0.0) + { + if ((theMaxPt - theMinPt).SquareModulus() < mySizeCull2) + { + return Standard_False; + } + } + return Standard_True; } diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx index cddae0bcf6..e0815f5931 100644 --- a/src/OpenGl/OpenGl_BVHTreeSelector.hxx +++ b/src/OpenGl/OpenGl_BVHTreeSelector.hxx @@ -33,7 +33,19 @@ public: //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices. Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); - Standard_EXPORT void SetViewportSize (const Standard_Integer theViewportWidth, const Standard_Integer theViewportHeight); + Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth, + Standard_Integer theViewportHeight, + Standard_Real theResolutionRatio); + + //! Setup distance culling. + Standard_EXPORT void SetCullingDistance (Standard_Real theDistance); + + //! Setup size culling. + Standard_EXPORT void SetCullingSize (Standard_Real theSize); + + //! Caches view volume's vertices projections along its normals and AABBs dimensions. + //! Must be called at the beginning of each BVH tree traverse loop. + Standard_EXPORT void CacheClipPtsProjections(); //! Detects if AABB overlaps view volume using separating axis theorem (SAT). //! @param theMinPt [in] maximum point of AABB. @@ -42,10 +54,6 @@ public: Standard_EXPORT Standard_Boolean Intersect (const OpenGl_Vec3d& theMinPt, const OpenGl_Vec3d& theMaxPt) const; - //! Caches view volume's vertices projections along its normals and AABBs dimensions. - //! Must be called at the beginning of each BVH tree traverse loop. - Standard_EXPORT void CacheClipPtsProjections(); - //! Return the camera definition. const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } @@ -139,6 +147,13 @@ protected: Standard_Integer myViewportHeight; Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices. + + Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling + Standard_Real myCamScaleInv; //!< inverted camera scale for size culling + Standard_Real myDistCull; //!< culling distance + Standard_Real myPixelSize; //!< pixel size for size culling + Standard_Real mySizeCull2; //!< squared culling size + }; #endif // _OpenGl_BVHTreeSelector_HeaderFile diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx index d3d86014e1..f5bca3f86b 100644 --- a/src/OpenGl/OpenGl_Layer.cxx +++ b/src/OpenGl/OpenGl_Layer.cxx @@ -489,9 +489,15 @@ void OpenGl_Layer::updateBVH() const void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const { updateBVH(); - - OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector(); - traverse (aSelector); + if (myBVHPrimitives .Size() != 0 + || myBVHPrimitivesTrsfPers.Size() != 0) + { + OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector(); + aSelector.SetCullingDistance (myLayerSettings.CullingDistance()); + aSelector.SetCullingSize (myLayerSettings.CullingSize()); + aSelector.CacheClipPtsProjections(); + traverse (aSelector); + } const Standard_Integer aViewId = theWorkspace->View()->Identification(); for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) @@ -516,15 +522,8 @@ void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) // function : traverse // purpose : // ======================================================================= -void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const +void OpenGl_Layer::traverse (const OpenGl_BVHTreeSelector& theSelector) const { - // handle a case when all objects are infinite - if (myBVHPrimitives .Size() == 0 - && myBVHPrimitivesTrsfPers.Size() == 0) - return; - - theSelector.CacheClipPtsProjections(); - opencascade::handle > aBVHTree; for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) { @@ -595,9 +594,9 @@ void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const else { Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); - const OpenGl_Structure* aStruct = - isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) - : myBVHPrimitives.GetStructureById (aIdx); + const OpenGl_Structure* aStruct = isTrsfPers + ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) + : myBVHPrimitives.GetStructureById (aIdx); aStruct->MarkAsNotCulled(); if (aHead < 0) { @@ -696,7 +695,6 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace, const Standard_Boolean hasLocalCS = !myLayerSettings.OriginTransformation().IsNull(); const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera(); - Handle(Graphic3d_Camera) aCameraBack; if (hasLocalCS) { // Apply local camera transformation. diff --git a/src/OpenGl/OpenGl_Layer.hxx b/src/OpenGl/OpenGl_Layer.hxx index f04a3a8766..a74ea4302a 100644 --- a/src/OpenGl/OpenGl_Layer.hxx +++ b/src/OpenGl/OpenGl_Layer.hxx @@ -135,7 +135,7 @@ protected: void updateBVH() const; //! Traverses through BVH tree to determine which structures are in view volume. - void traverse (OpenGl_BVHTreeSelector& theSelector) const; + void traverse (const OpenGl_BVHTreeSelector& theSelector) const; //! Iterates through the hierarchical list of existing structures and renders them all. void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const; diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index 93f5640730..b579c524a4 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -877,9 +877,10 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, } #endif - // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm). + // update states of OpenGl_BVHTreeSelector (frustum culling algorithm); + // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale myBVHSelector.SetViewVolume (myCamera); - myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height()); + myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 37900c1e24..fcc5c5cce1 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -4655,6 +4655,8 @@ inline void printZLayerInfo (Draw_Interpretor& theDI, theDI << " Immediate: TRUE\n"; } theDI << " Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n"; + theDI << " Culling distance: " << theLayer.CullingDistance() << "\n"; + theDI << " Culling size: " << theLayer.CullingSize() << "\n"; theDI << " Depth test: " << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n"; theDI << " Depth write: " << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n"; theDI << " Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n"; @@ -4885,6 +4887,33 @@ static int VZLayer (Draw_Interpretor& theDI, aSettings.SetOrigin (anOrigin); aViewer->SetZLayerSettings (aLayerId, aSettings); } + else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN + && anArgIter + 1 < theArgNb + && (anArg == "-cullingdistance" + || anArg == "-cullingdist" + || anArg == "-culldistance" + || anArg == "-culldist" + || anArg == "-distcull" + || anArg == "-distculling" + || anArg == "-distanceculling")) + { + Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId); + const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]); + aSettings.SetCullingDistance (aDist); + aViewer->SetZLayerSettings (aLayerId, aSettings); + } + else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN + && anArgIter + 1 < theArgNb + && (anArg == "-cullingsize" + || anArg == "-cullsize" + || anArg == "-sizecull" + || anArg == "-sizeculling")) + { + Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId); + const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]); + aSettings.SetCullingSize (aSize); + aViewer->SetZLayerSettings (aLayerId, aSettings); + } else if (anArg == "-settings" || anArg == "settings") { @@ -11548,6 +11577,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) theCommands.Add("vzlayer", "vzlayer [layerId]" "\n\t\t: [-add|-delete|-get|-settings]" + "\n\t\t: [-origin X Y Z] [-cullDist Distance] [-cullSize Size]" "\n\t\t: [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]" "\n\t\t: [-enable|-disable {positiveOffset|negativeOffset|textureenv}]" "\n\t\t: ZLayer list management:" diff --git a/tests/v3d/glsl/culldist b/tests/v3d/glsl/culldist new file mode 100644 index 0000000000..255fdf2372 --- /dev/null +++ b/tests/v3d/glsl/culldist @@ -0,0 +1,34 @@ +puts "========" +puts "0029295: Visualization, TKOpenGl - provide distance culling option" +puts "Check distance culling" +puts "========" + +set THE_NB_BOXES 5 +set THE_COLORS { RED GREEN BLUE1 YELLOW PURPLE1 } +set THE_PICK_PNTS1 { { 20 80 } { 60 110 } { 120 140 } { 200 180 } { 300 240 } } +set THE_PICK_PNTS2 { { 110 140 } { 130 150 } { 160 170 } { 200 190 } { 240 210 } } + +pload MODELING VISUALIZATION +vclear +vinit View1 +vaxo +vcamera -persp +for { set x 0 } { $x < $THE_NB_BOXES } { incr x } { box b$x $x 0 0 0.5 0.2 0.4; vpoint p$x $x 0 0; vdisplay -mutable p$x; vdisplay -dispMode 1 b$x } +for { set x 0 } { $x < $THE_NB_BOXES } { incr x } { vsetcolor b$x [lindex $THE_COLORS $x] } +vline l 0 0 0 5 0 0 +vdisplay -mutable l +vfit +vzlayer default -culldist 7 +for { set x 0 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1 $x] rgb name] == "BLACK" } { puts "Error: object is culled" } } +vdump $::imagedir/${::casename}_7.png + +vzlayer default -culldist 5 +for { set x 2 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1 $x] rgb name] == "BLACK" } { puts "Error: object is culled" } } +for { set x 0 } { $x < 2 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1 $x] rgb name] != "BLACK" } { puts "Error: object is NOT culled" } } +vdump $::imagedir/${::casename}_5.png + +vzoom 0.5 +vzlayer default -culldist 10 +for { set x 1 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2 $x] rgb name] == "BLACK" } { puts "Error: object is culled" } } +for { set x 0 } { $x < 1 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2 $x] rgb name] != "BLACK" } { puts "Error: object is NOT culled" } } +vdump $::imagedir/${::casename}_10.png diff --git a/tests/v3d/glsl/cullsize b/tests/v3d/glsl/cullsize new file mode 100644 index 0000000000..892bceae6d --- /dev/null +++ b/tests/v3d/glsl/cullsize @@ -0,0 +1,51 @@ +puts "========" +puts "0029295: Visualization, TKOpenGl - provide distance culling option" +puts "Check size culling" +puts "========" + +set THE_NB_BOXES 5 +set THE_COLORS { RED GREEN BLUE1 YELLOW PURPLE1 } +set THE_PICK_PNTS1O { { 10 165 } { 100 200 } { 170 250 } { 250 250 } { 350 300 } } +set THE_PICK_PNTS1P { { 40 170 } { 100 200 } { 170 250 } { 250 250 } { 380 350 } } +set THE_PICK_PNTS2O { { 148 192 } { 175 200 } { 190 200 } { 200 220 } { 250 230 } } +set THE_PICK_PNTS2P { { 152 192 } { 175 200 } { 190 200 } { 220 220 } { 250 230 } } + +pload MODELING VISUALIZATION +vclear +vinit View1 +vaxo +for { set x 1 } { $x <= $THE_NB_BOXES } { incr x } { box b$x [expr $x * 1.0] 0 0 [expr $x * 0.2] [expr $x *0.1] [expr $x *0.3]; vdisplay -dispMode 1 b$x } +for { set x 1 } { $x <= $THE_NB_BOXES } { incr x } { vsetcolor b$x [lindex $THE_COLORS [expr $x - 1]] } +vline l 1 0 0 6 0 0 +vdisplay -mutable l +vcamera -ortho +vfit + +vzlayer default -cullsize 25 +vcamera -ortho +for { set x 0 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1O $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +vdump $::imagedir/${::casename}_25o.png +vcamera -persp +for { set x 0 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1P $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +vdump $::imagedir/${::casename}_25p.png + +vzlayer default -cullsize 50 +vcamera -ortho +for { set x 1 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1O $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +for { set x 0 } { $x < 1 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1O $x] rgb name] != "BLACK" } { puts "Error: object $x is NOT culled" } } +vdump $::imagedir/${::casename}_50o.png +vcamera -persp +for { set x 1 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1P $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +for { set x 0 } { $x < 1 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS1P $x] rgb name] != "BLACK" } { puts "Error: object $x is NOT culled" } } +vdump $::imagedir/${::casename}_50p.png + +vzoom 0.25 +vzlayer default -cullsize 30 +vcamera -ortho +for { set x 2 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2O $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +for { set x 0 } { $x < 2 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2O $x] rgb name] != "BLACK" } { puts "Error: object $x is NOT culled" } } +vdump $::imagedir/${::casename}_30o.png +vcamera -persp +for { set x 2 } { $x < $THE_NB_BOXES } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2P $x] rgb name] == "BLACK" } { puts "Error: object $x is culled" } } +for { set x 0 } { $x < 2 } { incr x } { if { [vreadpixel {*}[lindex $THE_PICK_PNTS2P $x] rgb name] != "BLACK" } { puts "Error: object $x is NOT culled" } } +vdump $::imagedir/${::casename}_30p.png -- 2.20.1