DynamicDraw conduit, how to set clipping bounds?

Hi @stevebaer,

i have a very simple Rhino.Display.CustomDisplay conduit which shows an axis widget, it consists of 3 colored lines. This conduit is not “dynamic”.

While this CustomDisplay runs, i am prompting the user with a simple GetPoint operation for a new location of the axis widget. The point getter draws an axis widget (with arrows) using a DynamicDraw at the mouse position while prompting for a new point which is the new origin of the axis widget. In V6 i get this:

In case you cannot view the video: ConduitClippingProblem.zip (1.2 MB)

It looks like, the DynamicDraw is using the clipping bounds of the CustomDisplay conduit. This is not related to the ground plane setting. Is there a way to tell the DynamicDraw of my point getter that it should not clip at all ?

_
c.

It shouldn’t be clipping. What function are you calling to draw the axis with arrows?

Hi @stevebaer,

i am using below code in my GetPointDynamicDrawFunc to draw the widget axes:

# draw world axis lines while picking plane origin
args.Display.DrawArrow(line_x, x_axis_color, 0, 0.2)
args.Display.DrawArrow(line_y, y_axis_color, 0, 0.2)
args.Display.DrawArrow(line_z, z_axis_color, 0, 0.2)

Btw. if i change to drawing also the axes previously shown in the Rhino.Display.CustomDisplay in the dynamic conduit of the point getter, the clipping is correct.

_
c.

Thanks, I’ve logged this at https://mcneel.myjetbrains.com/youtrack/issue/RH-51369
and will try to take a look at it this week.

This will be fixed in SR15. Thanks

1 Like

Hi @stevebaer, using (6.16.19190.7001, 09.07.2019) i get below clipping problems when i try to draw a shaded brep sphere using e.DrawBrep (or the sphere’s brep wireframes using e.DrawBrepWires). The clipping problems are the same using e.DrawSphere:

How can i control the clipping when i draw in OnDynamicDraw of a point getter ?
How to get rid of the display artefact at the sphere seam ? (I tried two sided etc.)
_
c.

You’ll probably have to also enable a custom conduit at the same time and increase the scene bounding box to include your geometry.

Hi @stevebaer, you mean a Rhino.Display.CustomDisplay conduit ? I do not see a method to set the scene bounding box there, it offers only Get on the CustomDisplay.ClippingBox property.

Shouldn’t the dynamic display of the point getter automatically include the bounding box of the geometry it draws ?

Another related question: Since OnDynamicDraw does not offer depth drawing i tried to replace it with OnPostDrawObjects and set FullFrameRedrawDuringGet property to True. But this gave me the following (translated from german) error in the output:

The Objectpointer was not bound to an instance of an object

But it continued to run, with the same clipping problems. To my surprise, the clipping still happened even when i have drawn a large box around all my objects. This can’t be right.

_
c.

OnDynamicDraw was never really designed for shaded object drawing.

CalculateBoundingBox is the function I was referring to for increasing the scene bounds during a draw
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Display_DisplayConduit_CalculateBoundingBox.htm

Hi @stevebaer, i know, therefore i tried to just replace it with OnPostDrawObjects. I’ve found the reason for above error message, it was not related to the conduit, my sphere was just Unset for one frame in the beginning.

If i setup a new Rhino.Display.DisplayConduit just to include the bounding box in my dynamic display conduit, the clipping problem can be handled of course. But i think this is a bit unproductive as i then need to disable the conduit which is the reason i use the dynamic one. It disables itself on the fly.

Any idea what causes the display artifacts on the shaded (transparent) sphere seam ?

_
c.

I agree it is a bit unproductive. I’ll look into what it would take to add this functionality to the GetPoint class

2 Likes

@clement i needed also to expand bbox and made workaround for this, heres the snippet:

double inflate = Math.Pow(10, 10);
EventHandler<Rhino.Display.CalculateBoundingBoxEventArgs> displayBBoxHandler = (s, e) => { e.IncludeBoundingBox(new BoundingBox(new Point3d(-inflate, -inflate, -inflate), new Point3d(inflate, inflate, inflate))); };
Rhino.Display.DisplayPipeline.CalculateBoundingBox += displayBBoxHandler;

using (Rhino.Input.Custom.GetPoint getPointAction = new Rhino.Input.Custom.GetPoint())
{
    getPointAction.SetCommandPrompt("Please include e.CurrentPoint in DynamicDraw BBox it should be sufficent.");

    getPointAction.DynamicDraw += (sender, e) =>
        {
            DoStuff();
        };

    if (getPointAction.Get() != Rhino.Input.GetResult.Point)
    {
        Rhino.Display.DisplayPipeline.CalculateBoundingBox -= displayBBoxHandler;
        Rhino.RhinoApp.WriteLine("Failed to pick point.");
        return;
    }
}

Rhino.Display.DisplayPipeline.CalculateBoundingBox -= displayBBoxHandler; 

Be sure to remove the handler in any other case it can cause memory leaks.

@stevebaer Check command prompt tip :wink: BTW I know it’s another topic but can we do something to pass textures from memory instead of reading them from paths ? I need it for eg. here -> https://developer.rhino3d.com/api/RhinoCommon/html/Overload_Rhino_Display_DisplayMaterial_SetBitmapTexture.htm

Please refer to

Hi @nathanletwory :wink: Thanks for the input.

I saw it already but here is the same thing as with BBox. Instead of lets say SetTexture(Color data) or SetTexture(Bitmap bitmap) we have to implement Evaluator which as we already know works oddly (at least from my pov or just due to my not understanding - especially with high res textures) what actually double the need of calculations since first map is created/read then evaluated by custom memory evaluator and again reevaluated internally.

So first we have evaluation boxing and than we have next boxing due to conversion to basic material and next display material - you have to admit it’s quite long chain to reach the target.

@D-W, thanks for that, how would it look like in python ?

Thanks for your example code. I currently solved the problem altogether with the hint @stevebaer gave and found it is very effective as all you need is a global variable from the point getter say:

current_point = e.CurrentPoint

which you set eg. in the OnMouseMove event. Then i can access the point “dynamically” from a full DisplayConduit which i have to setup before and close after picking the point. The good thing is that this method offers full access to shaded display, culling and all regular display events. Imho this makes OnDynamicDraw look nearly useless.

Only drawback i found is that i need to disable the conduit manually after the point picker is done. There must be a way to automate this which i have not discovered yet.

_
c.

@clement as you know i don’t speak PY so can’t help here much.

The above code makes the same it is just compressed in a lambda expression which allows you to keep method encapsulated instead of writing a whole new custom display class, when you actually don’t need it at all.

The same way you can attach eventhandler to PostDraw and use it as a one liner without on/off custom conduit.

Yes and no since you are always one step behind as OnDynamicDraw is called after BBox calcs so your update takes always previous position instead of new position, but ofc it is always better than nothing or spending time on reinventing the wheel :wink:

1 Like