How to write titles and legends in 2D fashion when working in P3D?

I have completed my sketch in working in P3D mode apart from titles and legends. How do I write these texts normally like 2D when working from this mode. I’ve introduced a camera in the sketch to enable panning and zooming functionality. This causes the titles to transform according to the camera. I’ve tried transforming the title to correct position but it still looks somewhat off

Also how can I make it free from mouse zoom and panning. ie it holds its position even though other parts of the sketch moves.

Here is my code:


PImage worldMap;

PShape box;

Table table;

int rowCount;

float x1, y1, z1, x2, y2, z2;

//Interaction Zoom and Pan Variables:

float zoom = 600;

float panLeft = 0;

float panTop = 0;


void setup() {

  size(1400, 800, P3D);

  table = new Table("From_USA_Coordinates.tsv");

  rowCount = table.getRowCount();

  worldMap = loadImage("world.topo.bathy.200406.3x5400x2700.jpg"); 

  worldMap.resize(500, 300);

  textureMode(NORMAL);

  fill(255);

  //stroke(color(44,48,32));

  box = createShape(BOX, -650, 300, 0);

  box.beginShape(BOX);

  box.endShape();
  
  box.setTexture(worldMap);
  

}

void draw() {  
  
  background(255);
  
  fill(0);
  
  titlesAndLegends();
    
  display();  

}


void mouseDragged() {
  if((mouseX- pmouseX) > 0){
    panLeft -= 5;
  } else {
    panLeft += 5;
  }
  
  if((mouseY-pmouseY) > 0) {
    //panTop -=5;
  }
}



void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  if(e == 1) {
    zoom += 30;
  }else {
    zoom -= 30;
  } 
}

public void display() {  
 
  camera(panLeft, zoom , zoom, panLeft, 0, panTop, 0, 1, 0);   // eye(0, 600, 600) center(0, 0, 0) up(0, 1, 0)
  
  pushMatrix();

    translate(-350, 0, 0);

    shape(box);
    
    //box.scale(zoom);

  popMatrix();

  

  pushMatrix();

    translate(350, 0, 0);

    shape(box);
    

  popMatrix();
  

  pushMatrix();

    // To use the center of the left box as center coordinates

    translate(-350, 0, 0);
    
    textSize(15);

  for(int row = 1; row < rowCount; row++) {

    float USALatitude = table.getFloat(row, 3);

    float USALongitude = table.getFloat(row, 4);

    String countryName = table.getString(row,1);

    

    //Mapped Within X-axis of the left side map box

    float mappedLatitude = map(USALatitude,-90, 90, 150, -150); // Latitude is in Y axis

    float mappedLongitude = map(USALongitude, -180, 180, -325, 325); // Longitude in X Axis

    x1 = mappedLongitude;

    y1 = mappedLatitude;

    z1 = 0;

    

    float tripCountryLatitude = table.getFloat(row, 5);

    float tripCountryLongitude = table.getFloat(row, 6);     

    float tripLatitude = map(tripCountryLatitude, -90, 90, 150, -150); // In Y, same mapping

    float tripLongitude = map(tripCountryLongitude, -180, 180, 375, 1025); 

    // In X, having the position of the right box depending on the coordinates center

    x2 = tripLongitude;

    y2 = tripLatitude;

    z2 = 0;
    

    float zOff = map(0, 0, height, 300, 0); // Move mouse up and down
    

    float a = (x2-x1)/3;

    float b = (y2-y1)/3;

    stroke(#F05252);

    noFill();

    bezier(x1, y1, z1,                 // First point

         x1 + a, y1 + b, z1 + zOff,  // First intermediate point

         x2 - a, y2 - b, z2 + zOff,  // Second intermediate point

         x2, y2, z2); 
     
    //rotate(PI); 
    stroke(255);
    fill(255);
    text(countryName, x2-10, y2+10, z2+20);

  }

  popMatrix();

}

void titlesAndLegends() {
  pushMatrix();
    translate(-1000, -900, 0);
    //rotateY(-PI/4);
    textSize(50);
    fill(0);
    text("From USA to Other Parts of the World - 2019", width/2, 50);
  popMatrix();
}

Code for table:

class Table {
  int rowCount;
  String[][] data;
  
  
  Table(String filename) {
    String[] rows = loadStrings(filename);
    data = new String[rows.length][];
    
    for (int i = 0; i < rows.length; i++) {
      if (trim(rows[i]).length() == 0) {
        continue; // skip empty rows
      }
      if (rows[i].startsWith("#")) {
        continue;  // skip comment lines
      }
      
      // split the row on the tabs
      String[] pieces = split(rows[i], TAB);
      // copy to the table array
      data[rowCount] = pieces;
      rowCount++;
      
      // this could be done in one fell swoop via:
      //data[rowCount++] = split(rows[i], TAB);
    }
    // resize the 'data' array as necessary
    data = (String[][]) subset(data, 0, rowCount);
  }
  
  
  int getRowCount() {
    return rowCount;
  }
  
  
  // find a row by its name, returns -1 if no row found
  int getRowIndex(String name) {
    for (int i = 0; i < rowCount; i++) {
      if (data[i][0].equals(name)) {
        return i;
      }
    }
    println("No row named '" + name + "' was found");
    return -1;
  }
  
  
  String getRowName(int row) {
    return getString(row, 0);
  }


  String getString(int rowIndex, int column) {
    return data[rowIndex][column];
  }

  
  String getString(String rowName, int column) {
    return getString(getRowIndex(rowName), column);
  }

  
  int getInt(String rowName, int column) {
    return parseInt(getString(rowName, column));
  }

  
  int getInt(int rowIndex, int column) {
    return parseInt(getString(rowIndex, column));
  }

  
  float getFloat(String rowName, int column) {
    return parseFloat(getString(rowName, column));
  }

  
  float getFloat(int rowIndex, int column) {
    return parseFloat(getString(rowIndex, column));
  }
  
  
  void setRowName(int row, String what) {
    data[row][0] = what;
  }


  void setString(int rowIndex, int column, String what) {
    data[rowIndex][column] = what;
  }

  
  void setString(String rowName, int column, String what) {
    int rowIndex = getRowIndex(rowName);
    data[rowIndex][column] = what;
  }

  
  void setInt(int rowIndex, int column, int what) {
    data[rowIndex][column] = str(what);
  }

  
  void setInt(String rowName, int column, int what) {
    int rowIndex = getRowIndex(rowName);
    data[rowIndex][column] = str(what);
  }

  
  void setFloat(int rowIndex, int column, float what) {
    data[rowIndex][column] = str(what);
  }


  void setFloat(String rowName, int column, float what) {
    int rowIndex = getRowIndex(rowName);
    data[rowIndex][column] = str(what);
  }  
}

The links to my image files and datatable
https://drive.google.com/file/d/1sZw5Gc3xf_RTM_Ti6FeJ-_PVj49b0mlT/view

https://drive.google.com/file/d/111Tmhy6YDBQBmI2AaJuTPrrtdGZZpJSy/view

1 Like

It depends what you do in your sketch:

  • To isolate graphic from text normally you would write pushMatrix(); before the graphic section and popMatrix(); after this section. Then comes the text, unaffected by the translation / rotation in the graphic section. Use noLights(); before the text.

  • When you use a camera() command just say camera(); noLights(); prior to the text (!) section.

void draw() {
  // 3D code
 
  hint(DISABLE_DEPTH_TEST);
  camera();
  noLights();
  // 2D code (text)
  hint(ENABLE_DEPTH_TEST);
}

see https://amnonp5.wordpress.com/2012/01/28/25-life-saving-tips-for-processing/ (number 9)

  • peasyCam has a HUD (Heads Up Display), surround the text section with cam.beginHUD(); and cam.endHUD();

Chrisir

2 Likes

Thanks Chrisir. I used builtin camera() function like you suggested and it worked.
A question about PeasyCam. In my case, it worked with the primitive shape like box, but not with the rest of the sketch, do you have an idea in general why? Because of this I had to write the code to pan and zoom myself.

No, I don’t know

Apologies

We would have to see your code