ViewportSelect()



  • On 07/04/2014 at 10:19, xxxxxxxx wrote:

    Hi,

    I`m using utils.ViewportSelect() within a Python plugin to select all polygons visible to the viewport camera..

    However - it seems to add around .25 sec overhead each time i loop over the pixels on screen.  I suspect this might be just because Python for loops are quite slow but looking for any ideas on this.  My code is as follows:

    vps = c4d.utils.ViewportSelect()
    			
    bd = doc.GetRenderBaseDraw()
    frame = bd.GetFrame()
    width = frame["cr"] - frame["cl"] + 1
    height = frame["cb"] - frame["ct"] +1
    			
    vps.Init(width, height, bd, [obj], c4d.Mpolygons, False, c4d.VIEWPORTSELECTFLAGS_0)
    			
    for i in xrange(width) :
    	for j in xrange(height) :
    		res = vps.GetPixelInfoPolygon(i, j)
    		if res:
    			baseSelection.Select(res["i"])
    

    Any ideas or suggestions on how this might run faster would be appreciated!



  • On 11/04/2014 at 07:18, xxxxxxxx wrote:

    Hi Eclectrik,

    I'll make a C++ version to benchmark the two, but I don't think Python is the issue here. Python
    might not be fast, but is really not that slow either! I can iterate over 10 million empty passes in
    less than a second on my machine.

    Best,
    -Niklas



  • On 17/04/2014 at 13:52, xxxxxxxx wrote:

    How do you come to the .25 sec per loop? I've compared the C++ and Python version and I
    have almost expected the Python version to be slower than it actually is.

    While the C++ version executed within about 45-60 milliseconds, tested on a landscape object with
    default parameters, the Python version executed in about 355 to 420 milliseconds, which is less
    than 9 times

    Note that I have set "onlyvisible" to True since you only want to select visible elements.

    Python Version

    >
    > import c4d
    > import time
    >
    > def main() :
    > start = time.time()
    > sel = op.GetPolygonS()
    > vps = c4d.utils.ViewportSelect()
    > bd = doc.GetRenderBaseDraw()
    > frame = bd.GetFrame()
    > width = frame["cr"] - frame["cl"] + 1
    > height = frame["cb"] - frame["ct"] +1
    >
    > vps.Init(width, height, bd, [op], c4d.Mpolygons, True, c4d.VIEWPORTSELECTFLAGS_0)
    >
    > for i in xrange(width) :
    > for j in xrange(height) :
    > res = vps.GetPixelInfoPolygon(i, j)
    > if res:
    > sel.Select(res["i"])
    >
    > c4d.EventAdd()
    > print (time.time() - start) * 1000, "ms"
    >
    > main()

    C++ Version

    >
    > if (!doc) return false; // better safe than sorry
    >
    > BaseObject* op = doc->GetActiveObject();
    > if (nullptr == op || !op->IsInstanceOf(Opolygon)) {
    > GePrint("Select a Polygon object.");
    > return true;
    > }
    > Float64 start = GeGetMilliSeconds();
    > doc->StartUndo();
    > doc->AddUndo(UNDOTYPE_CHANGE_SELECTION, op);
    > BaseSelect* sel = ToPoly(op)->GetPolygonS();
    > doc->EndUndo();
    >
    > AutoAlloc<ViewportSelect> vps;
    > BaseDraw* bd = doc->GetRenderBaseDraw();
    > Int32 cl, ct, cr, cb;
    > bd->GetFrame(&cl, &ct, &cr, &cb);
    >
    > Int32 width = cr - cl + 1;
    > Int32 height = cb - ct + 1;
    >
    > if (!vps->Init(width, height, bd, op, Mpolygons, true, VIEWPORTSELECTFLAGS_0)) {
    > GePrint("Could not initialize ViewportSelect");
    > return true;
    > }
    >
    > for (Int32 i=0; i < width; ++i) {
    > for (Int32 j=0; j < height; ++j) {
    > ViewportPixel* p = vps->GetPixelInfoPolygon(i, j);
    > while (p) {
    > sel->Select(p->i);
    > p = p->next;
    > }
    > }
    > }
    >
    > EventAdd();
    > GePrint(String::FloatToString(GeGetMilliSeconds() - start) + " ms");
    > return true;

    Best,
    -Niklas


Log in to reply