# Too many calls to pushMatrix()

**URL:** <https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411>\
**Category:** Coding Questions\
**Created:** [August 21, 2020, 9:00am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411 "2020-08-21T09:00:06Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![todai](https://avatars.discourse-cdn.com/v4/letter/t/e5b9ba/32.png) [@todai](https://discourse.processing.org/u/todai)\
**Post date:** [August 21, 2020, 9:00am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/1 "2020-08-21T09:00:07Z")

</div>

Hey,

Is there a way to increase the matrix stack depth for pushMatrix()?  
I am working with 3D objects that have to be displayed with a relative position from one and other. The 3D objects are all created with box() from a list of positions saved in a tree structure. I use a recursive function to display the tree.

```auto
void displayModelRelative(Node node) {
  pushMatrix();
  translate(node.data[0], node.data[1], node.data[2]);
  
  rotateX(radians(node.data[3]));
  rotateY(radians(node.data[4]));
  rotateZ(radians(node.data[5]));
 
  box(node.data[6], node.data[7], node.data[8]);

  for (Node child : node.children) {
    displayModelRelative(child);
  }
  popMatrix();
}

```

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [August 21, 2020, 9:05am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/2 "2020-08-21T09:05:02Z")

</div>

> [@todai](#):
>
> Is there a way to increase the matrix stack depth for pushMatrix()?

> [@pushMatrix() cannot use push more than 32 times](https://discourse.processing.org/t/pushmatrix-cannot-use-push-more-than-32-times/12860/5):
>
> /\*\* \* Change PGraphics Max Pushes (v1.0) \* GoToLoop (2019/Jul/21) \* \* https://Discourse.Processing.org/t/ \* pushmatrix-cannot-use-push-more-than-32-times/12860/5 \*/ import processing.awt.PGraphicsJava2D; import java.lang.reflect.Field; static final int PUSHES = 35, DIAM = 8, OFFSET\_Y = 15; void setup() { size(100, 550); noLoop(); fill(#FFFF00); stroke(#FF0000); setMaxPushes((PGraphicsJava2D) getGraphics(), PUSHES); } void draw() { clear(); for (int i = 0; i \< …

---

<div class="post-metadata">

**Author:** ![todai](https://avatars.discourse-cdn.com/v4/letter/t/e5b9ba/32.png) [@todai](https://discourse.processing.org/u/todai)\
**Post date:** [August 21, 2020, 9:12am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/3 "2020-08-21T09:12:07Z")

</div>

Thanks for the fast reply, I already came across this post and tried it.  
I’ve tested it again and I’m getting this error:

ClassCastException: processing.opengl.PGraphics3D cannot be cast to processing.awt.PGraphicsJava2D

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [August 21, 2020, 9:20am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/4 "2020-08-21T09:20:21Z")

</div>

In the above code use popMatrix before the for loop instead of after it

---

<div class="post-metadata">

**Author:** ![todai](https://avatars.discourse-cdn.com/v4/letter/t/e5b9ba/32.png) [@todai](https://discourse.processing.org/u/todai)\
**Post date:** [August 21, 2020, 9:28am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/5 "2020-08-21T09:28:20Z")

</div>

Unfortunately that is not possible. If I place the popMatrix before the loop the whole relative position is gone.

This is an example of the display model:  
 ![adsf](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/d0ddd237e1c0a30eaf32ed0215ca4a857671d5a8.png)

Each object has a relative position to the parent in the tree.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [August 21, 2020, 9:44am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/6 "2020-08-21T09:44:20Z")

</div>

> [@todai](#):
>
> ClassCastException: processing.opengl.PGraphics3D cannot be cast to processing.awt.PGraphicsJava2D

That reflection hack was intended for renderer JAVA2D only, sorry.

For the OPENGL renderers P2D & P3D a hacking workaround is substantially more complicated.

B/c their method **pushMatrix()** checks against constant MATRIX\_STACK\_DEPTH rather than the _length_ of 1 of the 4 2D arrays:

> <https://github.com/processing/processing/blob/processing-0270-3.5.4/core/src/processing/opengl/PGraphicsOpenGL.java#L3716-L3725>

So we have to go beyond than just [**expand()**](https://processing.org/reference/expand_.html) the length of the 4 2D arrays:

> <https://github.com/processing/processing/blob/processing-0270-3.5.4/core/src/processing/opengl/PGraphicsOpenGL.java#L302-L320>

Besides that we’d have to keep in check the counter _modelviewStackDepth_ is always less than MATRIX\_STACK\_DEPTH after a call to **pushMatrix()** and always more than `0` after a call to **popMatrix()**.

EDIT:

B/c _modelviewStackDepth_ acts not only as a push/pop counter but also as the current index for the 4 `float[][]` arrays, we cannot simply cheat on its current value!

Both methods **pushMatrix()** & **popMatrix()** would need to be re-written so they would check against the _length_ of 1 of the 4 `float[][]` arrays instead of constant MATRIX\_STACK\_DEPTH.

An even easier fix would be to make field MATRIX\_STACK\_DEPTH `public` & non-`final`, so we could customize its value on our own if we needed to:  
`static protected final int MATRIX_STACK_DEPTH = 32;` →   
`static public int MATRIX_STACK_DEPTH = 32;`

But for that, you’re gonna need to be very patient and lucky in order to convince the devs to make such piece-of-cake fix:

> **[Issues · processing/processing](https://github.com/processing/processing/issues)**
>
> Source code for the Processing Core and Development Environment (PDE) - Issues · processing/processing

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [August 21, 2020, 10:19am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/7 "2020-08-21T10:19:38Z")

</div>

And if you work without pushMatrix and popMatrix all together?

Then all values be real relative

OR use pushMatrix and popMatrix for each box individually and use global positions (not relative)

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [August 22, 2020, 6:29pm UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/8 "2020-08-22T18:29:24Z")

</div>

I’ve come up w/ a workaround for the **pushMatrix()**'s 32x limit! 🥳

The current transform is stored in 4 PMatrix3D fields on the PGraphicsOpenGL object:

> <https://github.com/processing/processing/blob/processing-0270-3.5.4/core/src/processing/opengl/PGraphicsOpenGL.java#L281-L284>

So I’ve defined my own wrapper class named MatrixFrameGL to store those 4 fields:

## MatrixFrameGL.pde:

```auto
/**
 * Push/Pop Limit Workaround (v1.0.1)
 * GoToLoop (2020/Aug/22)
 *
 * Discourse.Processing.org/t/too-many-calls-to-pushmatrix/23411/8
 * Gist.GitHub.com/GoToLoop/e35ac69e9bd4dbbcce557218c3b20588
 */

// Comment out the package statement below if it's inside a ".java" file:
//package processing.core;

import processing.opengl.PGraphicsOpenGL;

static // Comment the keyword static if it's inside a ".java" file!
  public class MatrixFrameGL implements Cloneable
{
  public PMatrix modelview, modelviewInv, camera, cameraInv;

  public MatrixFrameGL() {
  }

  public MatrixFrameGL(final PGraphics pg) {
    pushMatrix(pg);
  }

  public MatrixFrameGL pushMatrix(final PGraphics pg) {
    return pushMatrix((PGraphicsOpenGL) pg);
  }

  public MatrixFrameGL pushMatrix(final PGraphicsOpenGL pg) {
    modelview = pg.modelview.get();
    modelviewInv = pg.modelviewInv.get();
    camera = pg.camera.get();
    cameraInv = pg.cameraInv.get();
    return this;
  }

  public MatrixFrameGL popMatrix(final PGraphics pg) {
    return popMatrix((PGraphicsOpenGL) pg);
  }

  public MatrixFrameGL popMatrix(final PGraphicsOpenGL pg) {
    pg.modelview.set(modelview);
    pg.modelviewInv.set(modelviewInv);
    pg.camera.set(camera);
    pg.cameraInv.set(cameraInv);
    return this;
  }

  @Override public MatrixFrameGL clone() {
    try {
      final MatrixFrameGL frame = (MatrixFrameGL) super.clone();
      frame.modelview = modelview.get();
      frame.modelviewInv = modelviewInv.get();
      frame.camera = camera.get();
      frame.cameraInv = cameraInv.get();
      return frame;
    }
    catch (final CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }
}

```

We instantiate the class MatrixFrameGL by passing a P2D or P3D PGraphics object.

Alternatively we can simply instantiate it w/o passing anything and only later on invoke its method **pushMatrix()** passing the P2D or P3D PGraphics object.

For the sketch’s main canvas we can pass its field [_g_](http://processing.github.io/processing-javadocs/core/processing/core/PApplet.html#g) or pass [**getGraphics()**](http://processing.github.io/processing-javadocs/core/processing/core/PApplet.html#getGraphics--):

- `MatrixFrameGL frame = new MatrixFrameGL(g);`
- `MatrixFrameGL frame = new MatrixFrameGL(getGraphics());`
- `MatrixFrameGL frame = new MatrixFrameGL().pushMatrix(g);`
- `MatrixFrameGL frame = new MatrixFrameGL().pushMatrix(getGraphics());`

The opposite operation is by calling method **popMatrix()** which restores the transform back into the passed PGraphics object argument:

- `frame.popMatrix(g);`
- `frame.popMatrix(getGraphics());`

As a bonus, class MatrixFrameGL also provides a **clone()** method: 😉

- `MatrixFrameGL clonedFrame = frame.clone();`

To test-drive the class if it’s indeed working I’ve coded the sketch below: 🏎

## Push\_Pop\_Limit\_Workaround.pde:

```auto
/**
 * Push/Pop Limit Workaround (v1.0.1)
 * GoToLoop (2020/Aug/22)
 *
 * Discourse.Processing.org/t/too-many-calls-to-pushmatrix/23411/8
 * Gist.GitHub.com/GoToLoop/e35ac69e9bd4dbbcce557218c3b20588
 */

import java.util.Queue;
import java.util.ArrayDeque;

final Queue<MatrixFrameGL> frames = new ArrayDeque<MatrixFrameGL>();

static final int BOXES = 32, SIZE = 6, MOV = SIZE << 2;
static final float ROT = TAU / BOXES;

void setup() {
  size(1200, 200, P3D);
  noLoop();
  stroke(#FFFF00); // yellow
}

void draw() {
  clear();

  translate(0, height >> 2);
  fill(#FF0000); // red
  recursiveBoxes(BOXES, SIZE, MOV, ROT, g, null); // 32 boxes

  translate(0, height >> 1);
  fill(#0000FF); // blue
  recursiveBoxes(BOXES * 3 >> 1, SIZE, MOV, ROT, g, frames); // 48 boxes
}

static final void recursiveBoxes(
  final int qty, final int size, final int moveX, final float rot, 
  final PGraphics pg, 
  final Queue<MatrixFrameGL> frames // pass null to use regular push/pop
  )
{
  if (qty <= 0) return;

  if (frames != null) frames.add(new MatrixFrameGL(pg));
  else pg.pushMatrix();

  pg.translate(moveX, 0);
  pg.rotateX(rot);
  pg.box(size);

  recursiveBoxes(qty - 1, size, moveX, rot, pg, frames);

  if (frames != null) frames.remove().popMatrix(pg);
  else pg.popMatrix();
}

```

There’s also a Java “library” version of the class MatrixFrameGL on the link below: 🐙

> **[Push/Pop Limit Workaround (Java Mode)](https://Gist.GitHub.com/GoToLoop/e35ac69e9bd4dbbcce557218c3b20588)**
>
> Push/Pop Limit Workaround (Java Mode). GitHub Gist: instantly share code, notes, and snippets.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [August 23, 2020, 2:31am UTC](https://discourse.processing.org/t/too-many-calls-to-pushmatrix/23411/9 "2020-08-23T02:31:02Z")

</div>

Given this is a tricky workaround, having a Python Mode version for it can be helpful: 🐍

> **[Push/Pop Limit Workaround (Python Mode)](https://Gist.GitHub.com/GoToLoop/193d951ef13f212f09e2b2809efc4de0)**
>
> Push/Pop Limit Workaround (Python Mode). GitHub Gist: instantly share code, notes, and snippets.
