Loading...
Logo
Processing Forum
I know it's a common error about depth and only 32 pushMatrx - popMatrix pairs allowed and the answer is this skript:
Matrix stack - processing wiki
BUT i get the following errors.
Basically it is a  very very very big piece of code to show it, so i am gonna describe the basic problem.
I have my code running with no problem using pushMatrix - popMatrix. I try to extend it by adding  ope more pair of push/pop translating and rotating 25rects() all together.
Exception "cannot use more than 32 pushMatrix() appears.
I copy the code given by the upper link, as it is.
What happens is that it looks like it cancels a piece of many many many sets of [pushMatrix() - translate() - rotate() - shape() -popMatrix()] and by canceling i mean the the push/pop orders are as they where never written and all the translation rotations are in a row...
I also tested the upper piece of code to the oldest - working - version of my code. What happens there is that it seams not even reading the "shape()" code as described above...
What is happening?
How does really the "cheat" of the link work?

Replies(18)

Without seeing your code it is hard to know what you are doing wrong.

The "cheat" of the link is simple: Instead of using the built-in versions of pushMatrix() and popMatrix() that can only store 32 saved transformations, it replaces them with similar calls to functions that can store up to 512 saved transformations in a global, local array instead.
Are you trying to place each rect() based on the last one? If that is the case then you may want to set up your own matrix stacks. If not then make sure you are popping the matrices before pushing the next one.
Such "cheat" is rarely needed, 32 push should be enough for most cases...
If you have such error, there is something wrong in your code, and pushing (sic) the limit is only delaying the issue...
As said, double check that you execute (unconditionally) a pop for each push you do. Avoid nesting them too much, if you can. Keep the number of lines between push and pop low, if possible.
Well, it's more than 2.000 lines + 5 libraries so there is no way to upload it right here, and it is the answer to why have so many "push/pop"-s.
I would think the same problem (unclosed pushMatrix() ) but the truth is that with one less "push/pop", the program works fine with its own limit, one more simple transformation and the 32 limit notification appears. Then trying the well - known / above cheat but nothing works...
If you still want me to upload it, i ll find a way.
Every rect is placed on its own and the most of them include a double transformation (translate and rotate) but they may vary from single rect() to a method_for_a_shape() (sometimes with more than 20 lines)
puchMatrix();
translate(x,y,z);
rotate(x,y,z);
rect(); -OR- shape_method();
popMatrix();

Write now i'm trying to group some "push/pop"-s in order to reduce them...
But this will increase the number of lines among push and pop. Also by saying low number of lines you mean including the lines of shape_methods..?

This seems OK. I was afraid to see hundred of lines between the two methods.
There is no need to "group" push / pop if they are matching: the limit is reached if you push to many times without popping as often.
My guess is that he was grouping them to make sure he really was popping the correct number of times. I'd say that if that is the case, it is probably a good idea for debugging.

Personally what I do when I have run into the problem of incorrect popping is put the pop immediately after the push. Then I move the pop down the necessary number lines until it is doing what I want (the graphics and transformations are correctly sandwiched) just to be certain it is correct.
The strange thing is that I have as many push's as pop's, following asimes method...
What i used to do is to translate / rotate the shapes one by one, even though there where exact the same transformations. And also needed to "pick" the objects (picking* library).
Copy code
  1. void method() {
  2.       picker.start(1);
  3.             pushMatrix();
  4.                   translate(x1,y1,z1);
  5.                   rotate(pi);
  6.                         shape_1();
  7.             popMatrix();
  8.       picker.start(2);
  9.             pushMatrix();
  10.                   translate(x1,y1,z1);
  11.                   rotate(pi);
  12.                         shape_2();
  13.             popMatrix();
  14. //..............
  15.       picker.start(x);
  16.             pushMatrix();
  17.                   translate(x1,y1,z1);
  18.                   rotate(pi);
  19.                         shape_x();
  20.             popMatrix();
  21.       picker.stop();
  22. }
Where shape_x() is a method with many lines and "if"-statements that integrates graphical controllers (sliders, radio buttons etc..)
So i 've used this method in order to make sure there where no conflicts between them. After using many many of these methods I believe that I have  simple reached the limit. Why the expansion does not working is hard to tell but, is very bad to just turn the upper method in this form?:
Copy code
  1. void method() {
  2.       pushMatrix();
  3.             translate(x1,y1,z1);
  4.             rotate(pi);
  5.            picker.start(1);
  6.                   shape_1();
  7.             picker.start(2);
  8.                   shape_2();
  9. //..............
  10.             picker.start(x);
  11.                   shape_x();
  12.             picker.stop();
  13.       popMatrix();
  14. }


Just tried it. Bad idea. sometimes works, other not and throwing the "too many calls to push matrix" exception.
What do i need for my code is simple sets of :
Copy code
  1. pushMatrix();
  2. rotate();
  3. translate();
  4. shape();
  5. popMatrix();
And this, i can make it up to 32 times...?!
Haw many lines of code or real shapes (ex rect()) can a "shape()" method accommodate?
A set of :
Copy code
  1. makeShape();
  2. vertex();
  3. vertex();
  4. ........
  5. endShape();
is thought to be one shape?
Just think that one shape() method looks like this:
Copy code
  1. void xDisplay()
  2.   {
  3.     pushStyle();
  4.     int area = (int) ypsos/num;
  5.     fill(rbxBg);
  6.     rect(xpos, ypos, platos, ypsos);
  7.     stroke(rbxBox);
  8.     for (int i=0; i< num; ++i)
  9.     {
  10.       rect(xpos, ypos+area*i, platos, area);
  11.     }
  12.     fill(rbxOn);
  13.     rect(xpos, (int) ypos+area*value, platos, area);
  14.     noStroke();
  15.     if (args != null) {
  16.       if (millis()-startT<3000)
  17.       {  
  18.         fill(fontColor);
  19.         textSize(pxF+3);
  20.         textAlign(CENTER, BOTTOM);
  21.         text(args[(int)value], xpos+platos/2, ypos);
  22.       }
  23.     }
  24.     popStyle();
  25.   }

Some of these methods have some lines more, other some lines less

I tried to reproduce your error but couldn't seem to do it. I made a sketch that makes an arbitrary number of push / pop calls. In the code below, it calls 200 of them back to back.

I also implemented a second solution that has the same effect visually, just undo the transformations manually. If the push / pop problem really cannot be solved in your program, then maybe manual undoing is worth a try:
Copy code
  1. int num = 200;
  2. PVector[] locs = new PVector[num];
  3. float[] rots = new float[num];

  4. void setup() {
  5.   size(600, 600);
  6.   noFill();

  7.   // Randomly placed things with random rotations
  8.   for (int i = 0; i < num; i++) {
  9.     locs[i] = new PVector(random(width), random(height));
  10.     rots[i] = random(TWO_PI);
  11.   }
  12. }

  13. void draw() {
  14.   background(255);

  15.   // Display
  16.   for (int i = 0; i < num; i++) {
  17.     // Implementation 1
  18.     pushMatrix();
  19.     translate(locs[i].x+5, locs[i].y+3);
  20.     rotate(rots[i]);
  21.     rect(0, 0, 10, 6);
  22.     popMatrix();

  23.     /*
  24.     // Implementation 2
  25.      translate(locs[i].x+5, locs[i].y+3);
  26.      rotate(rots[i]);
  27.      rect(0, 0, 10, 6);
  28.      rotate(-rots[i]); // Undo rotation
  29.      translate(-locs[i].x-5, -locs[i].y-3); // Undo translation
  30.      */
  31.   }

  32.   // Random movements and rotations
  33.   for (int i = 0; i < num; i++) {
  34.     locs[i].x += random(-1, 1);
  35.     locs[i].y += random(-1, 1);
  36.     rots[i] += random(-TWO_PI/32, TWO_PI/32);
  37.   }
  38. }
Thanx Asimes!
It ' s a good idea. Back to simple basics, and if you give it a thought, it is just 1 more line of code that either ways it is being executed..
I 'll try it and post results...
Bad news.
The case is that i use some functions, like the example I wrote previously ( xDisplay() ),
in the draw() {....} method,
Copy code
  1. draw() {
  2. if (case1) obj1.xDisplay();
  3. if (case2) obj2.xDisplay();
  4. .....................................
  5. if (caseN) objN.xDisplay();
  6. }
and every xDisplay includes apart from the push/pop~Matrix();, some picker.start(i);/ stop(); (i>0) from picking* library, methods.
The problem is that when in xDisplay() method there is the push/pop pair, picking* works perfect.
But when I replaced the pair with backwards transformations ...
Copy code
  1. translate(x, y);
  2. rotate(f);
  3. picker.start(0);
  4. xDisplay();
  5. picker.stop();
  6. rotate(-f);
  7. translate(-x, -y);
then the "picker" works only for the last rendered in draw(), xDisplay function.....

I am confused...
Copy code


Also a new notice:
If i extend push/pop depth with the upper given code ( Matrix stack - processing wiki), picking* library simply does not work...?
any ideas...?
I would say that an in depth look at your code would be needed at this point, I have a feeling something somewhere else in the program is making the matrix stack unhappy or something. Does the for loop example I posted work for you for large num?
I think you are right. right now I have found a temporal solution: I have used push/pop pair wherever there is picking object and transformation(x) / transformation(-x)  pairs wherever there is just graphics without picking.
But this is not going to work because I want an expandable code, so in sort future there will be a problem.
At the following link you can find a 7zip. file where I include 2 versions of my code that both work, but there is a difference:
The oldest code is in the folder named "expand_copy". The newest code with the temporal fix, as i have described upper, is called "expand_trials"
The sort difference between them is that the second has also one more tab/class (1 instance object) with code called "fidSmplBsd_bass", that also needs / uses an instance of ADSR class found in "graphic_cntrl_classes" tab.
push/pop pairs are found in every tab named somehow like  " fid***_sth" and in the "graphic_cntrl_classes" tab at "Waver" method (at the bottom of the tab) threre are some more at "graphic_cntrl_classes" tab /  stedySlider" & "stedyIO" classes but i don't use them anywhere in the code anymore).

http://www.4shared.com/archive/oroYhXZB/expand_copy.html



You better check the newest version

The download seemingly doesn't work if you don't have an account. Can you just post the code.

Also, does the for loop example I posted work for you for large num?
try this one:
http://rapidshare.com/files/3771147006/expand%20copy.7z

The for loop half works. The problem is with the picking* library that does not work correctly, as it does work only for the last shape() drawn in sketch and not for every shape() drawn in the frame
I'm not familiar with that library
Ok. Object Picking is a technique in graphics that is used in order to find the closest object (2D o 3D) in a plain of a window (specific view), at a specific coordinate. That means that in 3D it returns the object with the less depth, of all the objects that can be intersected of a line, that derives from the camera point and passes through the specified screen coordinates (usually the mouse). So is the object that at the specified coordinate hides all the others. In a 2D plain is the shape that is being drawn at the top of the others (if all visible, the one that can be seen).
In processing there is a library for this called picking*. Basically it has 3 methods: "void start(i)" i::integer>=0. This way if you have an object or shape you register it with a unique integer number (i). "void stop()" Stops the registration of objects.
"int get(x,y)" does object picking and returns the integer id of the top viewed object (if we assume that all objects are visible, you understand what i mean..) that exists at the x,y coordinates.
Seen n example and you will understand ( picking*).(// Works with processing 1.5, & Not with later editions)

Anyway. Still I don't know how exactly this library works with depth...