Using quads for projection mapping

edited February 2016 in Library Questions

Hi! I'm trying to integrate this Quad library/ sample sketch with my own GIF generator but it keeps breaking (Null Pointer Exception)

I'm wondering if that's because the image needs to be loaded in Setup and can't be reloaded/ refreshed in Draw?

Gif Code below

PImage loopingGif=null;
//ThinkGearSocket neuroSocket;
int attention=10;
int meditation=10;

PFont font;
int rand;
int interval = 400; //timer's interval
int lastRecordedTime = -12220;


void setup() {
}


void draw() {


  if (millis()-lastRecordedTime>interval) {
    println("here");
    if (attention<=30) {
      rand = int(random(1, 5)); 
      String fn= ((rand) + ".gif"); 
      //loopingGif = new Gif(this, fn);
      //loopingGif.loop();
      lastRecordedTime= millis();
    } else {
      rand = int(random(5, 9)); 
      String fn= ((rand) + ".gif");
      println (fn); 
      //loopingGif = new Gif(this, fn);
      //loopingGif.loop();
      lastRecordedTime= millis();
    }
  } else {
    // image(loopingGif, 0, 0);
    println("show");
    // lastRecordedTime= millis();
  }
}

Answers

  • edited February 2016

    @Chrisir any ideas? X_X

  • you join two sketches

    show your attempt

    where is the npe?

  • edited February 2016

    Progress has been made- I merged it and it works but when I try to delete the extra Quads (0-3) I get NullPointerExceptions

      /*ProjectedQuads - a simple class for projection mapping demo
    
      ProjectedQuads / ProjectedQuadsTest.pde
      v1.0 / 2010.01.30
    
      Keyboard:
      - 'd' toggle debug mode
      - 'S' save settings
      - 'L' load settings
      - '>' select next quad in debug mode
      - '<' select prev quad in debug mode
      - '1', '2', '3', '4' select one of selected quad's corners 
      - Arrow keys (left, right, up, down) move selected corner's position (you can also use mouse for that)  
    */
    
    
    String configFile = "data/quadsconfig.txt";
    
    ProjectedQuads projectedQuads;
    PImage    quadImage;
    PImage newImage;
    PImage newImage2;
    PImage newImage3;
    PImage newImage4;
    PGraphics quadGraphics;
    import gifAnimation.*;
    PImage[] animation;
    int rand;
    int interval = 3000; //timer's interval
    int lastRecordedTime = -12200;
    
    Gif loopingGif0;
    Gif loopingGif1;
    Gif loopingGif2;
    Gif loopingGif3;
    Gif loopingGif4;
    
    void setup() {
       size(displayWidth, displayHeight, P3D);
    
      projectedQuads = new ProjectedQuads();  
      projectedQuads.load(configFile);  
      //we want to display 3 quads so if there was no config file
      //or less than 3 were defined we increase number to 3
      if (projectedQuads.getNumQuads() < 5) {
        projectedQuads.setNumQuads(5);  
      }  
       newImage= loadImage("9.gif");
       newImage2= loadImage("10.gif");
       newImage3= loadImage("11.gif");
       newImage4= loadImage("12.gif");
    
      loadGifs(); 
    
    }
    
    void loadGifs() {
      rand = int(random(1,9)); //HERE YOU CHOOSE BETWEEN 10 DIFFERENT IMAGES
      String fn= ((rand) + ".gif"); //CALL YOUR FUNCTION 'takerandomimage'
      loopingGif4 = new Gif(this, fn);
      loopingGif4.loop();  
    
      projectedQuads.getQuad(0).setTexture(newImage);
      projectedQuads.getQuad(1).setTexture(newImage2);
      projectedQuads.getQuad(2).setTexture(newImage3);  
      projectedQuads.getQuad(3).setTexture(newImage4); 
      projectedQuads.getQuad(4).setTexture(loopingGif4);    
    
    
    }
    
    void draw() {
      background(0);
    
    
       if(millis()-lastRecordedTime>interval){
         loadGifs();
         lastRecordedTime= millis();
       }
    
    
      //draw projected quads on the screen
      projectedQuads.draw();
    }
    
    void keyPressed() {
      //let projectedQuads handle keys by itself
      projectedQuads.keyPressed();
    
      if (key == 'r') {
       loadGifs(); 
      }
    
    }
    
    void mousePressed() {
      //let projectedQuads handle mousePressed by itself
      projectedQuads.mousePressed();
    }
    
    void mouseDragged() {
      //let projectedQuads handle mouseDragged by itself
      projectedQuads.mouseDragged();
    }
    

    There are two other Tabs in the sketch

    "PROJECTED QUADS"

    class ProjectedQuads {
      private ArrayList quads;
      private boolean debugMode = true;
      private int selectedQuad = 0;
      private int selectedPoint = 0;  
      private float numSubdivisions = 5;
      PFont debugFont;
    
      public ProjectedQuads() {
        quads = new ArrayList();
        debugFont = createFont("Arial", 64);
      }
    
      public boolean getDebugMode() {
        return debugMode;
      }
    
      public void setDebugMode(boolean debugMode) {
        this.debugMode = debugMode;
      }
    
      public void setNumQuads(int num) {
        while(quads.size() > num) {
          quads.remove(quads.size()-1);
        }
        while(quads.size() < num) {
          quads.add(new Quad());
        }
        selectedQuad = quads.size()-1;
      }
    
      public int getNumQuads() {
        return quads.size();
      }
    
      public Quad getQuad(int i) {
        return (Quad)quads.get(i);
      }
    
      public void load(String configFile) {
        String[] data = loadStrings(configFile);
        if (data == null) {
          return;
        }
        setNumQuads(data.length);
        for(int i=0; i<data.length; i++) {
          PVector[] points = ((Quad)quads.get(i)).getPoints();
          String[] lineArr = data[i].split(" ");
          for(int j=0; j<4; j++) {
            points[j].x = parseFloat(lineArr[j*2]);
            points[j].y = parseFloat(lineArr[j*2+1]);
          }    
        }
        println("ProjectedQuads loaded from: " + configFile);
      }
    
      public void save(String configFile) {
        String data = "";
        for(int i=0; i<quads.size(); i++) {
          PVector[] points = ((Quad)quads.get(i)).getPoints();
          for(int j=0; j<4; j++) {
            data += points[j].x + " " + points[j].y;
            if (j < 3) data += " ";
          }
          if (i < quads.size()-1) data += "\n";
        }
        saveStrings(configFile, data.split("\n"));
        println("ProjectedQuads saved to: " + configFile);
      }
    
    
      //draw all the quads
      public void draw() {    
        if (debugMode) {
          textFont(debugFont);
        }
    
        for(int i=0; i<quads.size(); i++) {    
          if (debugMode) {
            if (i == selectedQuad) {
              stroke(255, 0, 0, 255);
            }
            else {
              stroke(255, 0, 0, 50);
            }
          }
          else {
            noStroke();
          }    
          beginShape(QUADS);   
          Quad q = (Quad)quads.get(i);
          texture(q.getTexture());
    
          for(int x=0; x<numSubdivisions; x++) {
            for(int y=0; y<numSubdivisions; y++) {
              calcVertex(q, x/numSubdivisions, y/numSubdivisions);
              calcVertex(q, (x+1)/numSubdivisions, y/numSubdivisions);
              calcVertex(q, (x+1)/numSubdivisions, (y+1)/numSubdivisions);
              calcVertex(q, x/numSubdivisions, (y+1)/numSubdivisions);
            }
          }
          endShape();
          if (debugMode) {
            PVector center = q.getCenterPoint();
    
            fill(0, 0, 0);  
            text(""+i, center.x-22, center.y+22);           
    
            if (i == selectedQuad) {
                fill(0, 255, 0);  
            }
            else {
                fill(255, 0, 0);
            }
    
            text(""+i, center.x-20, center.y+20);    
          }
        }
    
        if (debugMode) {
          drawAnchors();
        }
      }  
    
      //calculates vertex for sub quads
      public void calcVertex(Quad q, float sx, float sy) {
        PVector[] points = q.getPoints();
        float tx = points[0].x + (points[1].x - points[0].x)*sx;
        float ty = points[0].y + (points[1].y - points[0].y)*sx;        
        float bx = points[3].x + (points[2].x - points[3].x)*sx;
        float by = points[3].y + (points[2].y - points[3].y)*sx;   
        float gw = q.getTexture().width;
        float gh = q.getTexture().height;    
    
        if(q.isMirrored()) {
          vertex(tx + (bx - tx) * sy, ty + (by - ty) * sy, gw-sx*gw, sy*gh);
        }
        else {
          vertex(tx + (bx - tx) * sy, ty + (by - ty) * sy, sx*gw, sy*gh);
        }  
      }
    
      public void drawAnchors() {
        stroke(255, 0, 0);
        rectMode(CENTER);   
        if (selectedQuad > -1) {    
          Quad q = (Quad)quads.get(selectedQuad);
    
          for(int i=0; i<4; i++) {  
            if (i == selectedPoint) {
              fill(0, 255, 0);
            }
            else {
              fill(255, 0, 0);
            }
            rect(q.getPoints()[i].x, q.getPoints()[i].y, 10, 10);
          }
        }
      }
    
    
      public void keyPressed() {
        if (selectedQuad > -1 && selectedPoint > -1) {
          PVector[] points = ((Quad)quads.get(selectedQuad)).getPoints();
          switch(keyCode) {
          case LEFT: 
            points[selectedPoint].x -= 1; 
            break;
          case RIGHT: 
            points[selectedPoint].x += 1; 
            break;
          case UP: 
            points[selectedPoint].y -= 1; 
            break;
          case DOWN: 
            points[selectedPoint].y += 1; 
            break;      
          }
        }
    
        if (key == '1') {
          selectedPoint = 0;
        }
        if (key == '2') {
          selectedPoint = 1;
        }
        if (key == '3') {
          selectedPoint = 2;
        }
        if (key == '4') {
          selectedPoint = 3;
        }
        if (key == '<') {
          selectedQuad = (selectedQuad - 1 + quads.size()) % quads.size();
        }
        if (key == '>') {
          selectedQuad = (selectedQuad + 1) % quads.size();
        }
    
        //Shift + 's' to avoid accidental saving
        if (key == 'S') {
          projectedQuads.save(configFile);
        }
    
        //Shift + 'l' to avoid accidental loading
        if (key == 'L') {
          projectedQuads.load(configFile);
        }
    
        //Toggle debug/design/setup mode
        if (key == 'd') {
          projectedQuads.setDebugMode(!projectedQuads.getDebugMode());
        }
      }
    
      public void mousePressed() {
        selectedPoint = -1;
        if (selectedQuad > -1) {
          PVector[] points = ((Quad)quads.get(selectedQuad)).getPoints();
          for(int i=0; i<4; i++) {
            if ((Math.abs(mouseX - points[i].x) < 10) && (Math.abs(mouseY - points[i].y) < 10)) {
              selectedPoint = i;
              break;
            }
          }
        }
      }
    
      public void mouseDragged() {
        if (selectedQuad > -1 && selectedPoint > -1) {
          PVector[] points = ((Quad)quads.get(selectedQuad)).getPoints();
          points[selectedPoint].x = mouseX;
          points[selectedPoint].y = mouseY;   
          //snapping
          for(int i=0; i<quads.size(); i++) {
            if (i == selectedQuad) continue;
            PVector[] otherPoints = ((Quad)quads.get(i)).getPoints();
            for(int j=0; j<4; j++) {
              if ((abs(otherPoints[j].x - points[selectedPoint].x) < 5) 
                && (abs(otherPoints[j].y - points[selectedPoint].y) < 5)) {
                points[selectedPoint].x = otherPoints[j].x;
                points[selectedPoint].y = otherPoints[j].y;
                break;
              }
            }
          }
        }
      }
    
    }
    

    And "QUADS"

    /*
      ProjectedQuads / Quads.pde 
      v1.0 / 2010.01.30
    */
    
    class Quad {
      private PVector[] points;
      private PImage texture;
      private boolean mirrored = false;
    
      public Quad() {
        points = new PVector[4];
        points[0] = new PVector(width/4, height/4);
        points[1] = new PVector(width/4*2, height/4);
        points[2] = new PVector(width/4*2, height/4*2);
        points[3] = new PVector(width/4, height/4*2);
      }
    
      public PVector[] getPoints() {
        return points;
      }
    
      public PImage getTexture() {
        return texture;
      }
    
      public void setTexture(PImage texture) {
        this.texture = texture;
      }
    
    
      public boolean isMirrored() {
        return mirrored;
      }
    
      public void setMirrored(boolean mirrored) {
        this.mirrored = mirrored;
      } 
    
      public PVector getCenterPoint() {
        return new PVector(
          (points[0].x + points[1].x + points[2].x + points[3].x)/4, 
          (points[0].y + points[1].y + points[2].y + points[3].y)/4
        );
      } 
    }
    

    As well as a quads-config.txt which contains this

    200.0 150.0 431.0 88.0 671.0 121.0 417.0 224.0. 
    200.0 150.0 417.0 224.0 426.0 552.0 212.0 427.0. 
    417.0 224.0 671.0 121.0 659.0 417.0 426.0 552.0. 
    
  • I think you're far more advanced than I am

    what is projection mapping btw.

    in which line does the error occur (tab and line number?)

    what do the numbers in the txt-file mean? Do 4 numbers together define one quad? Like those: 200.0 150.0 431.0 88.0

    remark : to display them better , you might want to go back and edit your post, select them and hit ctrl-o (as you would with code, you know?)

    200.0 150.0 431.0 88.0 671.0 121.0 417.0 224.0 200.0 150.0 417.0 224.0 426.0 552.0 212.0 427.0 417.0 224.0 671.0 121.0 659.0 417.0 426.0 552.0

    Best, Chrisir ;-)

  • [Fixed data]

  • this codes needs a bunch of animated gif files called 0.gif to 12.gif

    As well as a quads-config.txt

    String configFile = "data/quadsconfig.txt";
    

    no hyphen in the name!

  • i get an immediate npe in processing 2, jogamp having problem with texture.

Sign In or Register to comment.