Display conduit Questions

Hi
I have two questions regarding display conduits

  1. How to draw shaded brep that is already added in the RhinoDoc with DrawShadedBrep ?
    The ON_Brep* that is returned from CRhinoBrepObject::Brep is const, and DrawShadedBrep takes nonconst brep
    object, so is it save here to const_cast ???

    class MyConduit :public CRhinoDisplayConduit
    {
    private:
    CRhinoBrepObject* mBrepObj;
    public:
    MyConduit(CRhinoBrepObject* obj):
    CRhinoDisplayConduit(CSupportChannels::SC_CALCBOUNDINGBOX |
    CSupportChannels::SC_POSTDRAWOBJECTS | CSupportChannels::SC_DRAWOBJECT)
    {
     mBrepObj = obj;
    }
    bool ExecConduit( CRhinoDisplayPipeline& dp, UINT nChannel,bool& bTerminate)
    {
    if (nChannel == CSupportChannels::SC_DRAWOBJECT)
    {
    if( m_pChannelAttrs->m_pObject == mBrepObj)
    m_pChannelAttrs->m_bDrawObject = false;
    }
    if (nChannel == CSupportChannels::SC_POSTDRAWOBJECTS)
    {
    const ON_Brep* brep = mBrepObj->Brep();

                  // doesnot compile cause DrawShadedBrep takes nonconst Brep&
                  dp.DrawShadedBrep(*brep,mymaterial); 
            }
       }
    

    };
    ON_Brep* myBrep = GetBrepHere
    CRhinoBrepObject* brep_obj = new CRhinoBrepObject();
    brep_obj ->SetBrep( myBrep);
    context.m_doc.AddObject(brep_obj);  
    MyConduit* conduit = new MyConduit(brep_obj);
    conduit->Enable();
    RhinoApp().ActiveDoc().Regen();

Why when drawing objects (that are added in rhino document ) with display conduit, when I select the rendered object it is not selection highlighted ?

Specifically, I was trying with CRhinoMeshObject , I want to draw the CRhinoMeshObject by myself. So i added the CRhinoMeshObject to the document, and set m_pChannelAttrs->m_bDrawObject = false in CSupportChannels::SC_DRAWOBJECT so Rhino can know that it will be custom drawed, and I drawed the mesh in SC_POSTDRAWOBJECTS. But when I try to select the rendered mesh, the mesh is selected, but it is not highlighted by the selection, so I guess I need to highlight the object through the conduit too, when it is selected, but do not know how to do that.
I guess the same behavior is seen for CRhinoBrepObject, but was not able to try because of problem 1).
.

Thank you

Hi Elizabeta,

You don’t need a custom conduit to display Rhino objects in shaded display mode. If you were just using Rhino, you could use the SetObjectDisplayMode command. Using the SDK, you can do this:

Does this help?

Hi Dale
Thank you for answering. Actually I didn’t tell you my original purpose with the conduit, and I am not using the conduit just to draw my objects shaded. I am using the conduit because I need to draw objects in specific order, like DrawOrder plugin in Rhino4.So basically I am doing this:

  1. Add my objects to Rhino Document, indentify them with user data
  2. Deny Rhino from drawing my specific objects by setting m_pChannelAttrs->m_bDrawObject = false inside the SC_DRAWOBJECT channel
  3. In the SC_POSTDRAWOBJECTS channel, turn depth testing off, draw my specific objects shaded in the order I want, then turn depth testing on.

And this works great, my objects are drawn in the order I want. But still remains my two problems:

  1. How to draw CRhinoBrepObject with the conduit because DrawShadedBrep takes non const Brep
    so I can’t do this:

    DrawShadedBrep(*myBrepObj->Brep(),mymaterial); // doesn’t compile

    If I copy the brep, originally stored in CRhinoBrepObject, and draw the copied brep, it compiles, but I doubt the efficiency of this :

    ON_Brep copy = *myBrepObj->Brep();
    DrawShadedBrep(copy,mymaterial);

  2. Objects that were drawn with conduit ( in the SC_POSTDRAWOBJECTS channel ) are not highlighted when selected. I guess since I am drawing the objects by myself and deny Rhino to draw them, I need to highlight them in the moment they are selected. How to do that.

It should be fine to cast away the const on the brep object… The only reason it’s not const is because it will actually create the render meshes for the brep if none exist. I didn’t add a const version of the function, since it could add confusion to whomever uses it if/when there are no render meshes attached to the brep. In other words, calling a const version of DrawShadedBrep() could result in nothing happening because there are no render meshes… And yes, making a copy of the brep is very inefficient, for the reasons I just explained above about render mesh creation.

Since selected objects do not require any sort of ordering (i.e. they’re always on top of everything else)… You should just let Rhino draw them if/when they’re highlighted… So in your conduit you should also check if the object is highlighted and NOT set DrawObject to false if it is… Something like:

if ( MY_OBJECT && !m_pDisplayAttrs->m_IsHighlighted )
m_pChannelAttrs->m_bDrawObject = false;

…something like that. Then Rhino will go ahead and draw the object using the current state.

-Jeff

Thank you Jeff for your help, it works.
However one more question, DrawShadedBrep doesnot draw the edges of the brep. How to show also its edges
thank you again

That’s because “render meshes” and “wires” are completely different entities, and are controlled separately by different display attributes. Are you wanting to force the edges to display? Or do you want your objects to display and follow the settings set by the current display mode? I highly recommend you do the latter, so that your objects conform to any other features that depend on display mode settings.

That being said, all you need to do is call the DrawObject() method on the pipeline. For example:

dp.DrawObject( m_pChannelAttrs->m_nObjectIndex );

…the DrawObject() only concerns itself about drawing things that are NOT related to render meshes. In fact, you really should try to conform to Rhino’s display attributes as close as possible…but that can get pretty complicated. For example, since you’re manually drawing the render meshes, what happens if you’re in a Rendered mode? Are you also handling the case for materials and textures that are possibly assigned to your objects? Probably not.

Since all you’re interested in is ordering your objects, then perhaps the best approach for you would be to simply just call DrawSurface() and DrawObject(), and let Rhino worry about all the complexities.

Something like this…

if ( MY_OBJECT )
{
if ( dp.DrawingSurfaces() )
dp.DrawSurface( m_pChannelAttrs->m_nObjectIndex );
if ( dp.DrawingWires() )
dp.DrawObject( m_pChannelAttrs->m_nObjectIndex );
m_pChannelAttrs->m_bDrawObject = false;
}

That should also handle any highlighting conditions as well. But here’s the problem… m_pChannelAttrs->m_nObjectIndex is only valid while inside the SC_DRAWOBJECT channel…since you’re drawing all of your objects inside SC_POSTDRAWOBJECTS, that’s not going to work…and neither will the calls to dp.DrawingSurface() and/or dp.DrawingWires()… But…since it sounds like you’re already storing user data on your objects, you could track those states inside your user data…and then retrieve it later in SC_POSTDRAWOBJECTS while you’re drawing your objects.

Something like so:

switch ( nChannel)
{
case SC_DRAWOBJECT:
{
if ( MY_OBJECT )
{
CRhinoObject* pObj = m_pChannelAttrs->m_pObject;
MyUserData* pMUD = pObj->GetUserData(…);

  pMUD->m_bDrawSurface = dp.DrawingSurfce();
  pMUD->m_bDrawWires = dp.DrawingWires();
  pMUD->m_nObjectIndex = m_pChannelAttrs->m_nObjectIndex;

  m_pChannelAttrs->m_bDrawObject = false;     
}
break;

}

case SC_POSTDRAWOBJECTS:
{
for (int i = 0; i < NUMBER_OF_MY_OBJECTS; i++)
{
CRhinoObject* pObj = MY_OBJECTS[i];
MyUserData* pMUD = pObj->GetUserData(…);

  if ( pMUD->m_bDrawSurface )
    dp.DrawSurface( pMUD->m_nObjectIndex );
  if ( pMUD->m_bDrawWires )
    dp.DrawObject( pMUD->m_nObjectIndex );
}
break;

}
}

Please keep in mind that I just typed all that from scratch, so there are most likely syntax errors as well as semantic errors…but you should get the idea. Also keep in mind that “m_nObjectIndex” is only valid for the duration of the current pipeline drawing pass, so do not hold onto any longer than you have to, and do not expect it to be valid the next time through the pipeline.

-Jeff

Actually I just thought of something that might not work given the way I coded the example above…

Do not just set m_bDrawingSurfce = dp.DrawingSurface()… Why? Because the pipeline can make multiple calls to your conduit based on which pass is currently being executed…

Instead you should do this…

if ( dp.DrawingSurface() )
pMUD->m_bDrawSurface = true;
if ( dp.DrawingWires() )
pMUD->m_bDrawWires = true;

…then in your SC_POSTDRAWOBJECTS channel, set them back to false after you’ve drawn them.

if ( pMUD->m_bDrawSurface )
dp.DrawSurface( pMUD->m_nObjectIndex );
if ( pMUD->m_bDrawWires )
dp.DrawObject( pMUD->m_nObjectIndex );
pMUD->m_bDrawSurface = pMUD->DrawWires = false;

-Jeff

I tried your code, and it works, but it only draws the brep as shaded when the display mode of the viewport is shaded. I need to show the objects always as shaded regardless of the display mode of the viewport, and show the edges on them. Also I don’t want to show the isocurves of the brep, only the edges . thank you for your help

Ok I solved the problem.To force my objects to always show as shaded regardless of display mode, I followed the following link http://wiki.mcneel.com/developer/sdksamples/shadeobjects to add material for shading in its attributes. And to hide the isocurves , I did attributes.m_wire_density = -1;
And then added the object in Rhino document.

The conduit code is same as you post above, and everything works. If you can check it again so I can be sure I understand you. Thank you very much for your help

case SC_DRAWOBJECT:
{
if ( MY_OBJECT )
{
CRhinoObject* pObj = m_pChannelAttrs->m_pObject;
MyUserData* pMUD = pObj->GetUserData(…);

 if(dp.DrawingSurfce();)
 {
     pMUD->m_bDrawSurface = true;
     dp.DrawSurface( m_pChannelAttrs->m_nObjectIndex );
 }

 if( dp.DrawingWires())
 {
       pMUD->m_bDrawWires = true;
       dp.DrawObject( m_pChannelAttrs->m_nObjectIndex );           
 }    
 pMUD->m_nObjectIndex = m_pChannelAttrs->m_nObjectIndex;

 m_pChannelAttrs->m_bDrawObject = false;    

}
}
break;

case SC_POSTDRAWOBJECTS:
{
dp.PushDepthTesting(false) ;

for (int i = 0; i < NUMBER_OF_MY_OBJECTS; i++)
{
  CRhinoObject*  pObj = MY_OBJECTS[i];
  MyUserData*    pMUD = pObj->GetUserData(...);

  if ( pMUD->m_bDrawSurface )
     dp.DrawSurface( pMUD->m_nObjectIndex );
  if ( pMUD->m_bDrawWires )
    dp.DrawObject( pMUD->m_nObjectIndex );

   pMUD->m_bDrawSurface = pMUD->DrawWires = false;

}
dp.PopDepthTesting();
}
break;