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 timesNote 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