
Wed, 11/16/2022 - 16:44
I have a custom implementation of a AIS_InteractiveObject
where GL_ARRAY_BUFFER
are managed directly because they're originating from an external library and copying them into Graphic3d_ArrayOfPrimitives
would double the used resources (they're send through a callback and are directly uploaded to the GPU).
I was hoping that by overriding PrsMgr_PresentableObject::BoundingBox
and setting thePrs->SetInfiniteState(false)
and thePrs->SetMutable(true)
for the presentation the bounding box would be taken into account by V3d_View::ZFitAll
but that didn't work:
The "handdrawn" ais object is a simple yellow box which completely wraps a native occt sphere shape:
It seems like the actual near and far values for the orthographic projection are summed up by Graphic3d_CView::MinMaxValues
using
Graphic3d_Layer::BoundingBox
Graphic3d_Structure::addTransformed
Graphic3d_Structure::minMaxCoord
and ultimately
Graphic3d_Group::AddPrimitiveArray
which iterates over all attribute arrays of which i have none.
For testing purposes it added the bounds calculated by the external lib as a single line in a Graphic3d_Group
with a Graphic3d_ArrayOfPolylines
like
auto const aabb = ...
Handle(Graphic3d_Group) group = thePrs->NewGroup();
Handle(Graphic3d_ArrayOfPolylines) lines = new Graphic3d_ArrayOfPolylines(2, 0, 0, Standard_False, Standard_False);
lines->AddVertex(aabb->first);
lines->AddVertex(aabb->second);
group->AddPrimitiveArray(lines);
and got the desired result.
I also tried to adapt Z near and far directly in the overridden OpenGl_Element::Render
function like
auto projection = aCtx->ProjectionState.Current();
auto theNear = aCtx->Camera()->ZNear();
auto theFar = aCtx->Camera()->ZFar();
auto const diff = theFar - theNear;
theNear -= 3 * diff;
theFar += 3 * diff;
projection.SetValue(2, 2, (-2.0) / (theFar - theNear));
projection.SetValue(2, 3, (theFar + theNear) / (theFar - theNear));
aCtx->ProjectionState.Push();
aCtx->ProjectionState.SetCurrent(projection);
aCtx->ApplyProjectionMatrix();
// render
// [...]
// reset states
aCtx->ProjectionState.Pop();
aCtx->ApplyModelViewMatrix();
to see if increasing the range to include the z bounds of my object would help but that didn't work; now the handdrawn object is always behind the occ shape:
I hope adapting z near and far in the render method is the right approach and i'm just doing something wrong.
Is it possible to render manually like this and take ad hoc bounding boxes into account or is the only possibility to fill at least a minimum in a Graphic3d_Group so that Graphic3d_Group::AddPrimitiveArray
can do the rest and calculate a proper bounding box which then leads to matching Z near and far values?
Wed, 11/16/2022 - 17:36
Take a look at "VUserDrawObj::Compute()" sample - I think Graphic3d_Group::SetMinMaxValues() method is what you are looking for. There is no need adding a "fake" primitive array into the group.
Wed, 11/16/2022 - 17:51
Nice! This works for
::Compute
!Is there a way to do this per render call?
Buffers are added to the "same group" and some are constantly transformed like