|
Author |
Topic: Extruder based on Casey Reas' Landscape (Read 2061 times) |
|
Dara
|
Extruder based on Casey Reas' Landscape
« on: Jan 13th, 2003, 11:00pm » |
|
http://www.darakilicoglu.com/wod/extruder/index.html Landscape from Casey Reas inspired me to do this simple stuff. However i am not happy with the speed. I dont want to be greedy i am just wondering if this can run faster? Any suggestions? // Extruder 2 // by Dara Kilicoglu // Based on Landscape by Casey Reas // Extruder reads a bitmap image and redraws it in 3d space using box() method. // Also original image's pixel RGB values are used to extrude boxes. int paperWidth = 400; int paperHeight = 400; int bmpWidth = 40; int bmpHeight = 60; boolean onetime = true; int angle = 0; int af = 5; float d = 10; int [][] aPixels = new int[40][60]; float rr,gg,bb,tt; void setup() { size(400,400); background(0, 0, 0); noStroke(); } void readImage() { BImage b; b = loadImage("mary6040.gif"); image(b, 0, 0); for (int i=0; i<bmpWidth; i++) { for (int j=0; j<bmpHeight; j++) { aPixels[i][j] = getPixel(i, j); } } } void loop() { if(onetime) { readImage(); onetime = false; } translate(paperWidth/2,paperHeight/2,50); rotateY(angle*(TWO_PI/360)); if (angle>180 || angle<0) { af *=-1; } angle += af; for (int i=0; i<bmpWidth; i++) { for (int j=0; j<bmpHeight; j++) { fill(aPixels[i][j]); rr = red(aPixels[i][j]); gg = green(aPixels[i][j]); bb = blue(aPixels[i][j]); tt = rr+gg+bb; push(); translate(((-bmpWidth*5)/2)+(i*5),((-bmpHeight*5)/2)+(j*5),0); box(3,3,(int(tt/d))); pop(); } } }
|
« Last Edit: May 3rd, 2003, 4:50pm by Dara » |
|
|
|
|
Martin
|
Re: Extruder based on Casey Reas' Landscape
« Reply #1 on: Jan 18th, 2003, 12:34pm » |
|
wondering... is there a way to insert screenGrab() somewhere inside the loop? tried doing that but all i get in the tiff's are just black backgrounds, no objects. thnks!
|
|
|
|
benelek
|
Re: Extruder based on Casey Reas' Landscape
« Reply #2 on: Jan 18th, 2003, 2:23pm » |
|
right at the end of the program, before the loop() ends: on Jan 13th, 2003, 11:00pm, Dara wrote: ... box(3,3,(int(tt/d))); pop(); } } // stick screenGrab(); here. } |
| make sure u have the image in the right folder, and that the variables at the top of the program are set according to the image's dimentions. -jacob
|
« Last Edit: Jan 18th, 2003, 2:24pm by benelek » |
|
|
|
|
Martin
|
Re: Extruder based on Casey Reas' Landscape
« Reply #3 on: Jan 18th, 2003, 3:02pm » |
|
bah. i hate this computer of mine. haha. ... i did exactly that a while ago and it ddnt work... and now it works. complete weirdness!
|
|
|
|
fry
|
Re: Extruder based on Casey Reas' Landscape
« Reply #4 on: Jan 31st, 2003, 3:52pm » |
|
regarding dara's initial question, there are two answers regarding the speed issues, i'll post them separate since i think the bboard is gonna choke on this long answer. first one is more to do with philosophy.. p5, like any environment is going to have speed problems. for some (lots of?) things, it will be worse than flash or director or c or opengl, and for others will be better (though less so as compared to c/opengl). dara had asked for some further clarification, i'm providing a full answer here, though it's not so much directed at dara as i think it's an important as a broader issue that comes up often. speed in applications is always an issue, consider it part of the medium you're working with. i would include your programming environment as part of that medium. so considering that, it is often more useful to think about ways to make your program/concept *better*, either through re-considering how your app works to take better advantage of the medium, or to do things in a more clever way. as anyone knows, the best work is often done through the simplest solution possible. as an example, consider peter cho's work (http://pcho.net and specifically http://www.typeractive.com/letterscapes/). none of this is extremely computation-heavy, however he manages to get extremely clever use of the medium (in those cases, java). he does this consistently, even on his other, non-java, work. peter claims this is just because he's too lazy to do it a more complicated way, but he's very modest and i prefer to belive it's more to do with him being very talented. this also gets into another issue.. when creating software, it is possible to develop exceptionally complicated things that are very attractive in their intricacy and number. taking your example here to an extreme, i could make a version that used millions of boxes (instead of hundreds) and the result would likely be interesting, but only for the fact that it's so many things, not for how it had been interpreted by you, the artist/designer/developer. often, when running into speed problems, it's necessary to re-evaluate the 'why' and what you're trying to communicate with the piece, before bearing down to optimize.. a less talented designer loudly blames his tools, the more talented figure out a better way to do things without the artificial complexity and wind up with a better piece in the end. (that's in no way a criticism of dara, i'm speaking very broadly here..) this is just like any other medium, but it gets confused with software, because it's easy to make complex things, and it seems like they should 'work' if only your machine were faster.. well, the speed of an average machine is one aspect of the medium, and that has to be taken into account. the 'what if' of a better/faster environment doesn't matter. it would be like saying "well, this would be an amazing oil painting if the colors could change through different times of the day to adjust to lighting conditions." the medium can't do it, so you have to work within the constraints of it. (continued in next message)
|
|
|
|
fry
|
Re: Extruder based on Casey Reas' Landscape
« Reply #5 on: Jan 31st, 2003, 3:55pm » |
|
as the second part of my answer, and at the risk of undermining my point, there are a handful of things that can be done to speed up the app that dara posted, and often learning these sort of speedups helps deepen one's understanding of programming in general, and to better understand how the medium 'works'. in this case, probably your most expensive routine is this piece of loop: Code:push(); translate(((-bmpWidth*5)/2)+(i*5),((-bmpHeight*5)/2)+(j*5),0); box(3,3,(int(tt/d))); pop(); |
| each time you do a push(), an array of 16 floats is copied. that's expensive speed wise. each time you translate(), a 4x4 matrix is multiplied by another, which is even more expensive. a pop() does the same 16 float array copy. while something like this wouldn't be a big deal in opengl, i think it might take a bit of a performance hit in java/p5. one possible speedup would be to write a version of the box() function that takes x and y coordinates, so that the push()/translate()/pop() are no longer necessary. certainly this isn't optimal coding-wise, but if you must have the speed, it would be something to try. this is what the box() function looks like: Code: public void box(float w, float h, float d) { float x1 = -w/2f; float x2 = w/2f; float y1 = -h/2f; float y2 = h/2f; float z1 = -d/2f; float z2 = d/2f; beginShape(QUAD_STRIP); vertex(x1, y1, z2); // A vertex(x1, y1, z1); // B vertex(x2, y1, z1); // C vertex(x2, y1, z2); // D vertex(x2, y2, z2); // E vertex(x2, y2, z1); // H vertex(x1, y2, z1); // G vertex(x1, y2, z2); // F vertex(x1, y1, z2); // A again vertex(x1, y1, z1); // B again endShape(); beginShape(QUADS); // now the sides CBGH and ADEF vertex(x2, y1, z1); // C vertex(x1, y1, z1); // B vertex(x1, y2, z1); // G vertex(x2, y2, z1); // H vertex(x1, y1, z2); // A vertex(x2, y1, z2); // D vertex(x2, y2, z2); // E vertex(x1, y2, z2); // F endShape(); } |
| by adding extra parameters for x and y, and adding those inside the vertex() calls, you might get better results. your code i had quoted would then become something like: Code:box(3,3,(int(tt/d)), (((-bmpWidth*5)/2)+(i*5),((-bmpHeight*5)/2)+(j*5)) |
| i think this solution would speed things up a good bit, though it's not going to make it *insanely* fast.. it's no silver bullet. also, from looking elsewhere on the bboard, you might know that red(), green() etc are not optimal (see http://proce55ing.net/discourse/yabb/board_Syntax_action_displa_y_num_1037826044.html), but there for convenience. a more optimized version of: Code:rr = red(aPixels[i][j]); gg = green(aPixels[i][j]); bb = blue(aPixels[i][j]); tt = rr+gg+bb; |
| would be Code:tt = ((aPixels[i][j] >> 16) & 0xff) + ((aPixels[i][j] >> 8) & 0xff) + (aPixels[i][j] & 0xff); |
| crap.. went to edit and now the msg is too long.. continued in the next part..
|
« Last Edit: Jan 31st, 2003, 4:05pm by fry » |
|
|
|
|
fry
|
Re: Extruder based on Casey Reas' Landscape
« Reply #6 on: Jan 31st, 2003, 4:05pm » |
|
less important, but there's also a lot of math that you're doing with multiplies that could be faster with just adding. i.e. you could set a variable called bmpWidth5, rather than using bmpWidth*5 inside your loop, to avoid multiplying those together 2400 times (60 x 40) on each frame. similarly, the i*5 and j*5 could be replaced by something called ii and jj that just add 5 each time through the loop: Code:int ii = 0; int jj = 0; for (int i = 0; i < bmpWidth; i++) { for (int j = 0; j < bmpHeight; j++) { // do your loop stuff here jj += 5; } jj = 0; // reset jj ii += 5; } |
| also, now that i'm really looking at your app, i don't think you really need aPixels[] at all.. unless you're doing anything fancier with the 2D array, you can just use the image data directly. and using index to cycle through the 1D array can be quicker.. i tried explaining this elsewhere on the board (can't find the post) but i think it's kinda abstract unless you see it in an example. so to people who read that post, here's the example. so you can remove readImage(), and after all these changes, your new loop() looks like: Code:BImage b; int bmpWidth5 = bmpWidth * 5; int bmpHeight5 = bmpHeight * 5; void loop() { if (onetime) { // annoying p5 bug to be fixed b = loadImage("mary6040.gif"); onetime = false; } translate(paperWidth/2,paperHeight/2,50); rotateY(radians(angle)); // another tweak if (angle>180 || angle<0) { af = -af; //af *=-1; // quick fix here } angle += af; int index = 0; int ii = 0; int jj = 0; // note height is on the outside ! for (int j = 0; j < bmpHeight; j++) { for (int i = 0; i < bmpWidth; i++) { // do your loop stuff here int pixel = b.pixels[index]; // get directly from image fill(pixel); tt = ((pixel >> 16) & 0xff) + ((pixel >> 8) & 0xff) + (pixel & 0xff); // the int() around tt/d is prolly not needed box(3, 3, int(tt/d), -bmpWidth5/2 + ii, -bmpHeight5/2 + jj); index++; // important! ii += 5; } ii = 0; // reset ii jj += 5; } } |
| phew. so some of the optimizations actually make your code a lot cleaner, and easier to understand. in no way am i intending to pick on your example (wouldn't expect newer programmers to know how to pull the thing apart), though it brings up lots of useful tidbits about how to make things speedy. some things will help more than others, but the idea behind this solution being faster holds.. even if only an incremental improvement for a 60x40 image, it would be an enormous improvement for a 640x480 image. this got a lot longer than i had intended. at any rate, hope y'all find this useful..
|
|
|
|
fry
|
Re: Extruder based on Casey Reas' Landscape
« Reply #7 on: Jan 31st, 2003, 4:51pm » |
|
ok, last one, i swear.. instead of int bmpWidth5 = bmpWidth * 5; int bmpHeight5 = bmpHeight * 5; and this inside the loop: box(3, 3, int(tt/d), -bmpWidth5/2 + ii, -bmpHeight5/2 + jj); just use: int left = -(bmpWidth*5) / 2; int top = -(bmpHeight*5) / 2; and inside the loop: box(3, 3, int(tt/d), left + ii, top + jj); also didn't mention.. 'int pixel' gets set once, because you're using that pixel several times, so it's faster to get and set it once that doing b.pixels[index] every time. one could also say "int pixel = b.pixels[index++]" in this example, and remove the separate index++ line, but that limits you if you eventually want to use index elsewhere inside that loop..
|
« Last Edit: Jan 31st, 2003, 4:55pm by fry » |
|
|
|
|
gsm
|
Re: Extruder based on Casey Reas' Landscape
« Reply #8 on: May 1st, 2003, 10:32pm » |
|
And another one that's turned into a bit of a habbit for me: division is slower than multiplication... Try the following and then switch the statement that assigns int x. Notice the speed difference in the output window... Code: void setup() { } void loop() { for ( int i=0; i<10000000; i++) { //int x = int(i*0.2); int x = i/5; } println(millis()); } |
| this is a huge loop of course, but a few smaller loops with multiple divisions in them can accumulate quite quickly... and then again, even small things can help
|
|
|
|
Dara
|
Re: Extruder based on Casey Reas' Landscape
« Reply #9 on: May 3rd, 2003, 5:30pm » |
|
hi, thank you very much for your posts. after fry's long answer i realized that this project is not suitable for java environment at all. i did all the optimizations, little tweaks and stuff but i couldn't notice the difference at all. i dont worry about its optimization anymore because i was looking for a way to run this maybe 2-3 times faster. but i am happy now because this was my first processing example and i learned so many things from that. as i think of this piece more and as i learn computer graphics fundamentals in time i get to new optimization ideas for extruder. hopefully i will practice those in my future projects. thank you very much for your help and ideas
|
|
|
|
|