Grips bounding box

I have a plugin in which I am working with custom grips for Nurbs surfaces. In addition to the standard set of grips,I have a few added grips which perform special functions when moved.

The problem I’m having is that the new grips do not get rendered when they are outside whatever bounding box is used when drawing the grips.

How is this bounding box determined and is there a way to overcome this problem? Since CRhinoObjectGrips is not a CRhinoObject, it doesn’t have the bounding box plumbing, and I can;t seem to change the behavior by altering the inner workings of my custom CRhinoGripObject-derived class.

How are you creating your grips? Have you seen this example?

https://github.com/mcneel/Rhino5Samples_CPP/tree/master/SampleCustomGrips

Yes, my process is very similar to that, with the exception that I am creating custom grips on a standard Rhino object instead of a custom object. The issue seems to have something to do with clipping planes in a particular view. If I draw a 3-D box that surrounds everything they display and work just fine, but that is a less-than-ideal workaround.

Also changing the level of zoom changes the amount of the grip that gets displayed and where it gets clipped. Zooming way out in a perspective view seems to have the effect of making the entire set of grips show up.

How are you doing this? Are you just drawing grips using a conduit?

I have derived classes from CRhinoObjectGrips, CRhinoGripObject, and CRhinoGripsEnabler. I have written a CRhinoGripsEnabler::TurnOnGrips and called RegisterGripsEnabler. When I want to turn them on (with my own special PointsOn command) I call the TurnOnGrips function for my Enabler.The CRhinoObjectGrips-derived class calls the base constructor with the GRIP_TYPE set to custom_grip.

The added grips are put into CRhinoObjectGrips::m_grip_list, so the grips themselves are managed by Rhino (including selection and rendering). I am drawing the control polygon myself using calls to CRhinoDrawGripsSettings::DrawControlPolygonLine inside my CRhinoObjectGrips::Draw override.

Here you can see the result. In the top view, all the grips are properly rendered, but in the perspective view they are clipped:

If I put a rectangle in the drawing to enlarge the drawing extents the whole thing gets drawn:

Or if I zoom out in the perspective view I get less and less clipping until it finally shows the whole thing (it’s a bit difficult to see here, I admit. With each zoom out I get more and more of the grip polygons until they all show):

My conclusion thus far has been that the grips are being clipped because they are beyond the drawing extents, but I do not know a way to communicate to Rhino the fact that the extents are beyond the extents of the convex hull of the control volume for the ON_NurbsSurface.

For reference, Steve Baer is at least passingly familiar with what I’m trying to do here…not to throw him under the bus or anything :wink:

Don’t worry about throwing @stevebaer under any bus - we do it here all the time…

I’m not quite sure I understand where the problem is. But, try this simple “work around” and see if the problem goes away.

Define a new conduit class that listens for the CSupportChannels::SC_CALCBOUNDINGBOX channel. When the conduit’s ExecConduit member is called for this channel, union the grip locations with the scene’s bounding box. I’m thinking of something like this:

class CCustomGripHelperConduit : public CRhinoDisplayConduit
{
public:
  CCustomGripHelperConduit(CCustomGrips* grips);
  bool ExecConduit(CRhinoDisplayPipeline& dp, UINT nChannel, bool& bTerminate); 

public:
  CCustomGrips* m_grips;
};

CCustomGripHelperConduit::CCustomGripHelperConduit(CCustomGrips* grips)
: CRhinoDisplayConduit(CSupportChannels::SC_CALCBOUNDINGBOX)
, m_grips(grips)
{
}

bool CCustomGripHelperConduit::ExecConduit(CRhinoDisplayPipeline& dp, UINT nChannel, bool& bTerminate )
{
  if (nChannel == CSupportChannels::SC_CALCBOUNDINGBOX)
  {
    if (0 != m_grips)
    {
      ON_3dPointArray locations;
      for (int i = 0; i < m_grips->m_grip_list.Count(); i++)
        locations.Append(m_grips->m_grip_list[i].GripLocation());
      m_pChannelAttrs->m_BoundingBox.Union(locations.BoundingBox());
    }
  }
  return true;
}

Then, when you enable your grips, create an instance of the conduit and enable it. When you destroy your grips, disable your conduit.

In doing this, the scene’s bounding box will grow and your grips should not longer be clipped. Make sense?

Thanks, Dale, that has done the trick.

Thanks for the update. I still want to check to see if this really is the real solution. In general, the object should provide the bounding box. But since you are not creating a custom object, this might be what is required.

I’ll keep digging…

I’m sure that’s the problem - the grips themselves don’t seem to be queried to find the bounding box. I tried a number of things to see where I could get a hook into the process but could never get a hit on one of my breakpoints.

The only other thing I could think of would be if there were a way to affect the display conduit being used for the grips, accessible via the CRhinoDrawGripsSettings parameter to the draw function, but it appeared that everything useful in there was inaccessible/protected.

I do have one more question - is there a good way to take over the drawing of the grips themselves, to change fill color and or shape (circles vs. squares for certain, unselectable grips). How is the default grip box size determined?

I suppose the most helpful thing for me would be an example of how to draw a grip in the normal way, choosing the default sizes and colors. I could then modify that according to my needs.

Thanks for any help you can give on that.

EDIT: I should clarify that I don’t want to change the appearance of any grips that operate in the normal manner. In my application I have a few grips marked as managed, and they are unselectable (via an override of the CRhinoGripObject::Pick function).

For custom grips, override your CRhinoObjectGrips derived classes Draw() handler. This function is passes the default grip drawing settings, CRhinoDrawGripsSettings. Making a copy of this, modifying it, and then calling the base class’s Draw() member is one way of customizing grip drawing.

Yeah, I’m doing something like this:

void MyBrepGrips::Draw (CRhinoDrawGripsSettings& dgs)
{
    this->DrawControlPolygonHelper (dgs);
	for (int i=0; i<m_grip_list.Count(); i++)
	{
		MyBrepGrip* pGrip = MyBrepGrip::Cast(m_grip_list[i]);
		if (pGrip)
		{
			if (IsManagedPole(*pGrip))
			{
				COLORREF grip_color = (pGrip->IsSelected()) ? RGB(255,255,0) : RGB(255,255,255);
				dgs.m_dp.DrawPoint(pGrip->m_base_point, 2, ERhinoPointStyle::RPS_CONTROL_POINT, grip_color);
			}
			else 
			{
				COLORREF grip_color = (pGrip->IsSelected()) ? RGB(255,255,0) : RGB(0,0,0);
				dgs.m_dp.DrawPoint(pGrip->m_base_point, 2, ERhinoPointStyle::RPS_CONTROL_POINT, grip_color);
			}
		}
	}
    //CRhinoObjectGrips::Draw (dgs);
}

I just wasn’t sure if I was missing anything important in there. I notice that I can’t seem to find a convenient way to change the fill color of the grip using the standard DrawPoint, also.