Making your Custom Entity worldDraw or viewportDraw fast

by Fenton Webb

Issue

My Custom Entity is rather complex, whenever my users call the Rotate or Move command or basically do something which requires continual updating of the graphics it becomes very jerky and slow. How can I improve this?

Solution

All of the Graphics Primitive functions housed in the AcGiGeometry class return an Adesk::Boolean. It is this return value that must be checked for a value of True so that AutoCAD can efficiently allow degradation of the graphics redraw in order to maintain UI performance.

If the return value comes back as True it is because the Graphic system calculated that the Minimum Frames Per Second (FPS) setting in the Graphics Configuration is being reached and that there is a Mouse interaction already in the input queue waiting to be utilized. A condition of True requires that your worldDraw/viewportDraw returns as quickly as possible back to AutoCAD.

Here is an example:

Adesk::Boolean MyEntity::worldDraw(AcGiWorldDraw *wd)
{
    assertReadEnabled();
    
    // do some enormous amount of work
    for (int i=0; i<1000000; ++i)
    {
        // check if AutoCAD is telling you that the user has input pending
        if (wd->geometry().circle(.., .., ..))
            return (false); // abort the work, because a new draw is required
    }
}

Comments

7 responses to “Making your Custom Entity worldDraw or viewportDraw fast”

  1. hi,
    Is this even true for AcGiGeometry::draw calls?
    Thank you

  2. Hi Loic
    yes, it’s true!!
    You can also check inputPending() for AutoCAD side user interaction checking.

  3. god, I’ve never noticed that before, I’ve yet developed many (sometimes complex) subWorldDraw overrides, shame on me, thanks to you!

  4. Hi Loic
    no problem. One last thing, if you use DrawJigs, then the same rule applies. If you use AcEdJig, then you should check inputPending() for long iterations in your code – otherwise it’s handled by AutoCAD automatically.

  5. Loic Jourdan Avatar
    Loic Jourdan

    good tip indeed, I’ll double check but I’m pretty sure it applies once in my code
    thanks

  6. Hi Fenton,
    One last question, can we test AcGiCommonDraw::regenAbort return as well?

    i.e. would these pseudo-code equivalent? (sorry for indent)

    for each (ent in ents){
    if (mode->geometry().draw(ent)) //your tip
    break;

    }

    for each (ent in ents){
    mode->geometry().draw(ent);
    if (mode->regenAbort())
    break;

    }

    this question because, somewhere in my code, I have a custom acgiworlddraw/acgigeometry with draw(AcGiDrawable*) overrided and I wonder if this method has to return the result of AcGiCommonDraw::regenAbort in order to behave correctly.
    Thank you

  7. Hey Loic!
    you are absolutely right, regenAbort() informs you when you should not waste anymore time creating your geometry.
    Thanks for the reminder, it seems you got a lot out of this one which is nice to hear

Leave a Reply to Loic JourdanCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading