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