G4P and perspective()

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:

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):

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

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.

1 Like

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.

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

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

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

but also to no effect.

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 :frowning_face:

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
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();
}
3 Likes

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()… :wink: But anyways, this is so 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.

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
}
2 Likes