# G4P and perspective()

**URL:** <https://discourse.processing.org/t/g4p-and-perspective/44027>\
**Category:** Libraries\
**Created:** [March 5, 2024, 9:36am UTC](https://discourse.processing.org/t/g4p-and-perspective/44027 "2024-03-05T09:36:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![matwolf](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/matwolf/32/19408_2.png) [@matwolf](https://discourse.processing.org/u/matwolf)\
**Post date:** [March 5, 2024, 9:36am UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/1 "2024-03-05T09:36:31Z")

</div>

Hi!

Recently I stumbled over G4P and I love it! Ta so much, Peter, for this fine library! Especially the gui-builder is a knock-out (and in my case it knocked out ControlP5, which, to the best of my knowledge, lacks a graphical builder). I was able to build the most recent project with G4P very satisfactorily! However, a couple of effects occured. (I’ll post single topics.)

**perspective()**

When yu change the perspective of your scene, the G4P-elements seem to bee unaware of that. This means that the gui-elements appear elsewhere on the screen, but the event procedures are fired at the “original” pixel positions.

Code to show behaviour:

**Main tab** :

```auto
import g4p_controls.*;

public void setup(){
  size(480, 320, P3D);
  createGUI();

  // Wide angle "lens" (with 90° field of view):
  // The button appears smaller and closer to the centre of the stage, but the 
  // "reaction zone" remains at its place. This renders it basically unusable. 
  perspective( PI/2, (float)width/(float)height, 3, 1000);
  // Comment line 14 to check against default perspective with fov 60°.
  
}

public void draw(){
  background(230);
  translate( width/2, height/2 );
  rotateX( PI/4 );
  rotateY( PI/6 );
  box( 100, 100, 100 );  
}

```

Tab **gui** (from builder):

```auto
public void button1_click1(GButton source, GEvent event) { //_CODE_:button1:590660:
  println("button1 - GButton >> GEvent." + event + " @ " + millis());
  println( "Button pressed." );
} //_CODE_:button1:590660:

public void createGUI(){
  G4P.messagesEnabled(false);
  G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
  G4P.setMouseOverEnabled(false);
  surface.setTitle("Sketch Window");
  button1 = new GButton(this, 22, 22, 80, 30);
  button1.setText("Face text");
  button1.addEventHandler(this, "button1_click1");
}

GButton button1;

```

If this is a bug or I’m missing something, I can’t tell.

The machine is running Manjaro Linux 23.1.3 with Linux Kernel 6.1.77-2-MANJARO. Processing is build no 1293, G4P 4.3.9.

Cheers, Mat

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [March 5, 2024, 12:07pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/2 "2024-03-05T12:07:40Z")

</div>

> [@matwolf](#):
>
> ```auto
> public void draw(){
> push();
> background(230);
> translate( width/2, height/2 );
> rotateX( PI/4 );
> rotateY( PI/6 );
> box( 100, 100, 100 );  
> pop();
> }
> 
> ```

G4P draws all the controls after the `draw` method executes so retains the effect of any canvas transformations. To avoid this surround the code in draw with a `push/pop` pair as shown above, this should solve the problem.

---

<div class="post-metadata">

**Author:** ![matwolf](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/matwolf/32/19408_2.png) [@matwolf](https://discourse.processing.org/u/matwolf)\
**Post date:** [March 5, 2024, 12:32pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/3 "2024-03-05T12:32:32Z")

</div>

Thanks for the quick response! But sorry, same behavior.  
(I already did some experiments with push- and popMatrix().)

Add: Btw: Adding resetMatrix() also doesn’t solve the issue: The box is gone from the stage (obviosly being created ›somewhere else‹), but the button again is dislocated.

---

<div class="post-metadata">

**Author:** ![matwolf](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/matwolf/32/19408_2.png) [@matwolf](https://discourse.processing.org/u/matwolf)\
**Post date:** [March 5, 2024, 12:52pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/4 "2024-03-05T12:52:33Z")

</div>

I also tried to reverse the push-pop-sequence:

```auto
void setup() {
  size(480, 320, P3D);
  createGUI();
  push();
}

void draw() {
  pop();
  // code…
  push();
}

```

but also to no effect.

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [March 5, 2024, 2:10pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/5 "2024-03-05T14:10:47Z")

</div>

`push` and `pop` save and restore the transformation matrix but does not seem to work with the `perspective` command. In my opinion this seems weird behaviour by Processing ☹

There is a simple solution shown below.

- I moved your perspective command from `setup` to `draw` which is necessary for this solution to work See point (1) below.
- I have included the `push` and `pop` statements to isolate any transformation used in rendering the frame.
- Finally at the end of draw added the `perspective();` statement to reset the perspective to its default state.

Couple of other points

1. It is also preferable / recommended to put all rendering transformation statements inside `draw` or a method called from `draw`.
2. The `push`/`pop` statements must be paired in that order like curly braces `{ }` makes sense but `} {` doesn’t

```auto
public void setup() {
  size(480, 320, P3D);
  createGUI();
}

public void draw() {
  push();
  background(230);
  perspective( PI/2, (float)width/(float)height, 3, 1000);
  translate( width/2, height/2 );
  rotateX( PI/4 );
  rotateY( PI/6 );
  box( 100, 100, 100 );
  pop();
  perspective();
}

```

---

<div class="post-metadata">

**Author:** ![matwolf](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/matwolf/32/19408_2.png) [@matwolf](https://discourse.processing.org/u/matwolf)\
**Post date:** [March 5, 2024, 2:21pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/6 "2024-03-05T14:21:26Z")

</div>

Fantastic, this is it! Now that you showed me, it’s hard for to see how I have not seen that simple and elegant solution!

Thanks a lot – being able to use perspective adds a whole lot of flexibility in designing my presentations!

(Btw: the initial push was in setup()… 😉 But anyways, this is so much better!)

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [March 5, 2024, 2:32pm UTC](https://discourse.processing.org/t/g4p-and-perspective/44027/7 "2024-03-05T14:32:25Z")

</div>

> [@matwolf](#):
>
> (Btw: the initial push was in setup()… 😉 But anyways, this is o much better!)

For every `push` statement there must be a matching `pop` statement and vica-versa otherwise the program will crash ! ! ! Splitting them into different methods is a recipe for disaster never ever do it.

Having said that you can nest `push` / `pop` statements e.g.

```auto
void draw(){
  background(200);
  // some code
  push(); // ---A
  // some more code
  push(); // ---B
  rnederSomethingElse();
  // some more code
  pop(); // ---B
  pop(); // ---A
}

void rnederSomethingElse(){
  // some more code
  push(); // ---C
  // even more code
  pop(); // ---C
}
```
