DrawPolygonObject at specific z-offset



  • I am doing some experimentation with a SceneHookData-derived plugin, and would like in the SceneHookData::Draw to perform during SCENEHOOKDRAW::DRAW_PASS the following steps:

    • fill the viewport with a color
    • draw a wireframe of a sphere on top

    To achieve this I create a GeClipMap the size of the viewport, fill it with a color, get its bitmap and perform a BaseDraw::DrawTexture.
    I am using BaseDraw::SetMatrix_Screen(lineZoffset). By default the lineZoffset is set to 0.

    Then I use BaseDraw::DrawPolygonObject to draw a mesh object.

    Unfortunately, I do not see the wireframe of the object, and wonder if this is due some z-offset?
    I have tried to perform a ```BaseDraw::LineZOffset(lineZoffset + 1) right before the DrawPolygonObject in order to make sure the z-order of the wireframe is always higher than that of the DrawTexture, although documentation doesn't mention the DrawPolygonObject to be affected by the LineZOffset.

    I am wondering how to get the wireframe shown on top of the DrawTexture.



  • Hi @C4DS,

    thank you for reaching out to us. This is probably not possible in the way you are trying to implement it, assuming that I do understand your approach correctly. Note the special note in the description of BaseDarw::SetMatrix_Screen

    This method only affects the new 3D drawing methods below it, i.e. DrawLine(), LineStrip(), DrawHandle(), DrawPoly(), DrawTexture(), DrawCircle(), DrawBox(), DrawPolygon() and DrawSphere().

    What is also a bit unclear to me is on which plane you do draw your texture, I assume on the camera plane, i.e., at z=0.0? I am not sure if you are aware of it, but screen space does not mean 2D, you can still offset things along the depth/z-axis.

    Long story short, I did recreate your setup in Python and do not really see a way out. I also looked at the code of DrawPolygonObject and it looks like that is should respect the z-depth of a drawing operation when you pass DRAWOBJECT::Z_OFFSET as flag, but it does not work for me. I will reach out to the devs to ask them if this combination of screen space (the texture) and world space (the polygon object) drawing operation while supporting a drawing order is supported. I will report back when I have an answer. But I would not hold my breath that this is possible.

    Cheers,
    Ferdinand

    My test script as a Python scripting tag, in case I somehow misunderstood you.

    import c4d
    
    LINEZOFFSET = 0
    
    
    def GetViewBitmapData(viewFrame, color=c4d.Vector(.25, .5, 1), alpha=.5,
                          zdepth=0.):
        """Returns the data for a texture drawing operation of filling the 
        viewport with an uniformly colored bitmap.
        """
        # Create the canvas for a 1x1 bitmap.
        color *= 255
        alpha *= 255
        canvas = c4d.bitmaps.GeClipMap()
        canvas.Init(w=1, h=1)
        canvas.BeginDraw()
        canvas.SetColor(int(color.x), 
                        int(color.y), 
                        int(color.z), 
                        int(alpha))
        canvas.SetPixel(0, 0)
        canvas.EndDraw()
    
        # The polygon data.
        padr4 = [c4d.Vector(viewFrame["cl"], viewFrame["ct"], zdepth),
                 c4d.Vector(viewFrame["cl"], viewFrame["cb"], zdepth),
                 c4d.Vector(viewFrame["cr"], viewFrame["cb"], zdepth),
                 c4d.Vector(viewFrame["cr"], viewFrame["ct"], zdepth)]
        cadr = [c4d.Vector(1)] * 4
        vnadr = [c4d.Vector(0, 0, 1)] * 4
        uvadr = [c4d.Vector(0, 0, 0),
                 c4d.Vector(0, 1, 0),
                 c4d.Vector(1, 1, 0),
                 c4d.Vector(1, 0, 0)]
    
        # Return the DrawTexture signature.
        return {"bmp": canvas.GetBitmap().GetClone(),
                "padr4": padr4,
                "cadr": cadr,
                "vnadr": vnadr,
                "uvadr": uvadr,
                "pntcnt": 4,
                "alphamode": c4d.DRAW_ALPHA_FROM_IMAGE,
                "flags": c4d.DRAW_TEXTUREFLAGS_USE_PROFILE_COLOR}
    
    
    def draw(bd):
        """
        """
        # The hosting object and the frame of the viewport.
        node = op.GetObject()
        viewFrame = bd.GetSafeFrame()
    
        # Draw the bitmap.
        bd.SetMatrix_Screen(LINEZOFFSET)
        #bd.DrawTexture(**GetViewBitmapData(viewFrame))
    
        # Draw the polygon object.
        bh = c4d.plugins.BaseDrawHelp(bd, doc)
        # bd.SetMatrix_Screen(LINEZOFFSET + 1)
        bd.LineZOffset(5)
        bd.DrawPolygonObject(bh, node, c4d.DRAWOBJECT_Z_OFFSET)
    
    
    def main():
        pass 
    


  • Hi @C4DS,

    so I heard back from the developers and tried out a couple of things. The devs told me what you and I already did suspect, i.e., that the z-depth of a drawing operation is not being shared between drawing spaces. They suggested that you should try camera space, but after trying that myself, I cannot see a scenario where this would help you other than making the texture placement slightly more convenient.

    In the camera space scenario you would have to place the texture physically behind the object, since DrawPolygonObject will always be drawn in matrix space. In matrix space you could reverse the order, but you have to remember that zdepth is actually that, a depth value, and not an integer drawing order, so setting that value can be tricky. In both cases you would have to do manually the math to place the texture precisely within the view- or safeframe.

    I hope this somewhat helps, although it is again no solution for you.

    Cheers,
    Ferdinand



  • @ferdinand
    Thanks for the details.

    Unfortunately, the z-order of the texture is not in my hands.
    I am actually using a DrawTexture in order to emulate a 3rd party GPU render preview.
    As such, I have no control how that preview is drawn. What I am trying to achieve is draw some mesh objects in front of said preview, and for this I was experimenting with the DrawPolygonObject on top of a DrawTexture.

    From the replies so far I understand there is no adequate solution.

    I have also experimented with DrawLine and Line Strip drawing.
    While these provide some useful results, they're more labor intensive then a simple DrawPolygonObject. And are rather slow, especially DrawLine.

    If no further comments are to be given, I will consider the case closed, since no appropriate solution is at hand.



  • Hi @C4DS,

    I am not sure that I can follow on what you are exactly doing. But my assumption is that you have x objects in a scene, want to block out all these objects with some kind of background texture and then draw one of these objects on top of that background texture, right? This is unfortunately not possible in my understanding.

    What you could do, is fill the viewport with a background texture by putting it behind an object by manually doing the trigonometry/transforms necessary for a given cemara. Not fun to do, because you have all these ifs and whens of camera parameters, but doable. This however would only give you a custom background and block out everything behind it, but not what is between the camera, the object and the background. Which is probably not what you are after if I understand you correctly.

    Cheers,
    Ferdinand