donut icon indicating copy to clipboard operation
donut copied to clipboard

Do not redraw continuous

Open Dandandan opened this issue 15 years ago • 11 comments
trafficstars

Please redraw only on animation using noLoop() and own draw calls.

(smaller issue btw, please place frameRate(30) in your setup function instead of draw).

Hope you appreciate my comment.

Dandandan avatar Dec 07 '09 13:12 Dandandan

Hi! That sounds like a good idea. Could you give a short example where to put the noLoop() calls etc.?

Also I think recalculating all the state-values in update isn't always necessary. It should depend on whether the animation is playing or not. I'm just wondering how I would then detect mouseOver events (when different slices/segments are activated).

frameRate(30) must go to setup(), obviously ;) Thanks!

I'm doing some modifications on donut while preparing the launch of ASKKEN™ 1.0. Saving some cpu cycles on Donut drawing would help a lot there. ;)

michael avatar Dec 07 '09 14:12 michael

noLoop() should go in setup(), then processingjs doesn't call your draw function anymore. You should redraw only when there are new properties to draw. so i think you have to call your draw (or redraw) function manually with an setInterval on each 1000/frameRate ms and do a clearInterval when the animation is stopped. Just like this (on your tweet example):

import("Tween.lib");

class MovingObject { float x; float y; float tx; float ty; Tween t; Tween t2;

public MovingObject(float x, float y, float tx, float ty) { this.x = x; this.y = y; this.tx = tx; this.ty = ty; t = new Tween(this, "x", Tween.strongEaseInOut, x, tx, 2); t2 = new Tween(this, "y", Tween.bounceEaseInOut, y, ty, 2); }

public void update() { t.tick(); t2.tick(); }

public int isPlaying() { return t.isPlaying(); }

public void draw() { noStroke(); fill(120); ellipse(x, y, 30, 30); }

public void restart() { t.start(); t2.start(); } }

MovingObject mo;

void setup() { size(400, 150); mo = new MovingObject(50, 30, 360, 130); noLoop(); frameRate(30); }

void animate() { if (!l) { l = setInterval( function() { if (mo.isPlaying()) { redraw(); } else { clearInterval(l); l = 0; } }, 1000/frameRate ); } }

void draw() { background(244); mo.update(); mo.draw(); }

void mousePressed() { mo.restart(); animate(); }

oh and these lines in your draw function: " stroke(0); fill(0);

pushMatrix(); popMatrix();" seem to do nothing.

I really like the design of ASKKEN! It is really a nice way to browse for information. Looking forward to ASKKEN™ 1.0 ;)

Dandandan avatar Dec 07 '09 15:12 Dandandan

http://pastebin.org/61886

Dandandan avatar Dec 07 '09 18:12 Dandandan

Thank you! Great ideas!

I'll try to apply this approach to the current ASKKEN implementation and merge it back to DONUT when it's ready. However regarding ASKKEN, things seem to be a bit more difficult. The main reason why I'm redrawing all the time is, that nodes and edges in ASKKEN are organized by a particle system. That means nodes are likely to move around all the time (at least slowly to find their right place) which requires a redraw every iteration. Do you have an idea how I could come around that? I mean at least I can save performance when I skip update() (except for the x/y position update resulting from the particle system) if no animation is playing. However.. I'm not sure if I can save some draw iterations here. Any ideas?

Thank you so far :)

michael avatar Dec 07 '09 20:12 michael

Ehm, yeah that's more difficult. Maybe some options:

  1. You could check (if you don't use floats for your rendering) wether or not the positions did change and only draw things if they did. So you don't do a noLoop but don't draw (and background fill) all the time.
  2. Stop the particle system temporarily if there is nearly no change anymore.
  3. Use animations for most things (like adding a donut) and only use physics when you drag around the donuts and then do (2).
  4. Use animations and come up with an other design.

"I mean at least I can save performance when I skip update() (except for the x/y position update resulting from the particle system) if no animation is playing. However.. I'm not sure if I can save some draw iterations here"

For the update thing I think you could use the same technique as described above, but then calling the update function. I don't know if it improves performance much because on update() it doesn't draw things, does it?

Good luck :)

Dandandan avatar Dec 07 '09 20:12 Dandandan

By the way, to me seems option 3 the most plausible option + you could accelerate the process of stabilizing the donuts.

Dandandan avatar Dec 07 '09 21:12 Dandandan

Aii. Good thinking. I'll take that into consideration. Now I need some "particlesystemStableEnough?" detection, to turn it off when not needed. ;)

What is your background Dan? Are you coming from the (native) Processing community? Really great to get some input, since I'm quite new to the computer graphics business. I started off with Processing.js, so there's no Processing past in my case. ;)

Do you have some sketches/examples online? In case you have, pls share them. :)

michael avatar Dec 07 '09 21:12 michael

Regarding update().... DONUT's update calculations are quite heavy. So that might be the cause for some frame drops -> needs to be tested. Mhh... maybe a profiling tool could reveal that. Don't know any. :/

michael avatar Dec 07 '09 21:12 michael

I am just a first year (so a couple of months) computer science student. I did some time ago experiments with processingjs just as an ebook (http://speechcorpus.googlepages.com/ebook.html) and a very simple window manager. Coming days I have probably no time to investigate further, maybe Thursday or weekend.

Firebug (great tool!, can profile under console tab and then click profile and after a while again) reveals this:

(donutsegment.draw()) 2435 16.8% 1937.867ms 7951.808ms 3.266ms 1.02ms 42.639ms 1 (line 225)

(donutslice.draw()) 16558 15.83% 1826.078ms 4102.711ms 0.248ms 0.139ms 24.474ms 1 (line 92)

arc 5222 12.16% 1403.095ms 1403.095ms 0.269ms 0.062ms 9.856ms processing.js (line 1628)

array.size() 496350 8.26% 952.607ms 952.607ms 0.002ms 0.001ms 0.074ms processing.js (line 507)

Donut.totalSlices() 29220 6.96% 802.435ms 1417.268ms 0.049ms 0.045ms 0.13ms 1 (line 379)

stroke 22268 6.78% 781.988ms 1389.776ms 0.062ms 0.028ms 10.156ms

line 16558 5.2% 600.285ms 600.285ms 0.036ms 0.023ms 8.199ms processing.js (line 1649)

color 30996 4.82% 556.414ms 720.088ms 0.023ms 0ms 8.211ms processing.js (line 534) fill 7235 2.06% 237.992ms 345.499ms 0.048ms 0.029ms 3.498ms

According to Firebug the update function is this: Donut.update() 487 0.53% 61.524ms 2460.399ms 5.052ms 4.707ms 6.802ms

(I've added the correct names, don't know why but Firebug was reporting array.clear instead of array.size).

You could iterate faster (if you didn't know) over an array by the way by storing the length(s) of (an) array(s) before the for loop(s). That can help a little bit.

Dandandan avatar Dec 07 '09 23:12 Dandandan

Oh and one big deal: I think yo can remove those lines of Donutsegment.draw " fill(DONUT_BACKGROUND);

noStroke();

strokeWeight(this.breadth+2*OUTER_BORDER);

stroke(DONUT_BACKGROUND);

noFill();

arc(donut.x, donut.y, (donut.radius)*2, (donut.radius)*2, this.angleStart, this.angleStop);"

does nothing :)

Dandandan avatar Dec 08 '09 06:12 Dandandan

found some time: http://pastebin.org/62191 totalslizes is just a data member of donut, saves some cycles :).

Dandandan avatar Dec 08 '09 15:12 Dandandan