[Closed] Nitrous SDK: display outside of bounding box?
I have an object that displays differently in each viewport, meaning it requires a different bounding box for each viewport in order to be displayed.
There is a documented function called “HasViewDependentBoundingBox” that is supposed to prevent max from caching bounding boxes on objects so that “GetWorldBoundBox” can be used to set a view-dependent bounding box…but as with a lot of obscure SDK functions…it’s broken and has no effect (not in Nitrous in max 2016, at least).
Is there another way to force a Nitrous viewport to display an object, regardless of where its bounding box is? With the old GraphicsWindows you could just register a display callback, but I haven’t come across any Nitrous display callbacks that allow view-dependent control.
I’ve scoured the various view/update/node contexts that get passed down in the PrepareDisplay and UpdatePerViewItems functions, but haven’t found a way to force an object to always draw in there.
So I’m not sure how many other people will run into this issue…but I figured I’d post my solution for posterity’s sake, since I finally found a hacky workaround.
Basically, I ended up constructing my object bounding box in such a way that it always encompasses a point in all the active viewports, at all times. Because that forces the object bounding box to be visible within all viewport rects, it’s drawn in all views at all times.
The reason this is a better solution than just setting the object bounding box to something huge, is this solution doesn’t screw up pan/zoom speeds. Setting the bounding box to something huge (ie, box.MakeCube(Point3(0,0,0), 1000000) will force a draw in all viewports, yes, but because the pan/zoom virtual camera target is constructed by examining scene extents…as soon as you pan/zoom in a perspective viewport, your camera will move at an insane speed to compensate for the massive bounding box. My solution always keeps the bounding box at the smallest possible size while ensuring it’s visible in all views.
The tradeoff is that you get a messed up bounding box, but whatever. That won’t affect anything other than the display of your object in bounding box mode.
Here’s the code for the GetWorldBoundBox override:
void camTex::GetWorldBoundBox(TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
{
box.Init();
int numV = GetCOREInterface7()->getNumViewports();
Point3 q[10];
for (int i = 0; i < numV; i++)
{
Matrix3 affine;
GetCOREInterface7()->getViewExp(i).GetAffineTM(affine);
affine.Invert();
Point3 p(0,0,-10);
p = p * affine;
q[i] = p;
}
box.IncludePoints(q, numV);
}
To ensure max always uses an up-to-date bounding box (normally it only clears a BBox cache when the object transform changes, not when a view is panned/zoomed/changed), I put
selfnode->InvalidateTM();
in my Nitrous “UpdatePerViewItems” override.
Why was all this necessary in the first place? Because my plugin constructs per-view meshes that don’t all exist in the same place across all views. So without this hack the viewports get confused when trying to decide where the geometry is, and will cull the geo in some views (even if it’s in a location where it should be visible).
Hopefully Autodesk will improve the Nitrous SDK in future releases, re-implementing the “HasViewDependentBoundingBox” override functionality.