/*
* Copyright Inria and Bordeaux University.
* Author Jeremy Laviole. jeremy.laviole@inria.fr
* PapAR project is the open-source version of the
* PapARt project. License is LGPLv3, distributed with the sources.
* This project can also distributed with standard commercial
* licence for closed-sources projects.
*/
package fr.inria.papart.procam.display;
import fr.inria.papart.procam.Papart;
import fr.inria.papart.procam.Screen;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PMatrix3D;
import processing.core.PVector;
import processing.opengl.PGraphicsOpenGL;
/**
*
* @author jiii
*/
public class BaseDisplay {
Semaphore sem = new Semaphore(1);
public PGraphicsOpenGL graphics;
public ArrayList<Screen> screens = new ArrayList<Screen>();
protected PApplet parent;
// public PGraphicsOpenGL graphicsUndist;
protected static int DEFAULT_SIZE = 200;
protected boolean registered = false;
protected int frameWidth = DEFAULT_SIZE, frameHeight = DEFAULT_SIZE;
protected int drawingSizeX = DEFAULT_SIZE, drawingSizeY = DEFAULT_SIZE;
protected float quality = 1;
public BaseDisplay() {
setParent(Papart.getPapart().getApplet());
}
public BaseDisplay(PApplet applet) {
setParent(applet);
}
public BaseDisplay(PApplet applet, int quality) {
setParent(applet);
this.quality = quality;
}
public void init() {
initGraphics();
automaticMode();
}
/**
* Called in init(). Do not call manually except if you know what yeu do.
*/
protected void initGraphics() {
this.graphics = (PGraphicsOpenGL) parent.createGraphics((int) (frameWidth * quality),
(int) (frameHeight * quality), PApplet.OPENGL);
}
public void automaticMode() {
registered = true;
// Before drawing.
parent.registerMethod("pre", this);
// At the end of drawing.
parent.registerMethod("draw", this);
}
public void manualMode() {
registered = false;
parent.unregisterMethod("draw", this);
parent.unregisterMethod("pre", this);
}
public void registerAgain() {
if (!registered) {
return;
}
manualMode();
automaticMode();
}
/**
* Called in automatic mode.
*/
public void pre() {
this.clear();
}
public void clear() {
try {
sem.acquire();
this.graphics.beginDraw();
this.graphics.clear();
this.graphics.endDraw();
} catch (InterruptedException ex) {
Logger.getLogger(BaseDisplay.class.getName()).log(Level.SEVERE, null, ex);
}
sem.release();
}
public PGraphicsOpenGL beginDraw() {
try {
sem.acquire();
this.graphics.beginDraw();
return this.graphics;
} catch (InterruptedException ex) {
Logger.getLogger(BaseDisplay.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public PGraphicsOpenGL beginDrawOnScreen(Screen screen) {
// Get the markerboard viewed by the camera
PMatrix3D screenPos = screen.getLocation();
this.beginDraw();
this.graphics.applyMatrix(screenPos);
return this.graphics;
}
public void endDraw() {
this.graphics.endDraw();
sem.release();
}
/**
* Called in Automatic mode to display the image.
*/
public void draw() {
parent.g.background(100, 0, 0);
drawScreensOver();
parent.noStroke();
parent.g.image(this.render(), 0, 0, this.drawingSizeX, this.drawingSizeY);
// pxCopy = getPixelsCopy();
}
public int[] pxCopy;
public PImage render() {
return this.graphics;
}
public void drawScreens() {
this.beginDraw();
this.graphics.clear();
renderScreens();
this.endDraw();
}
public void drawScreensOver() {
this.beginDraw();
renderScreens();
this.endDraw();
}
public void renderScreens() {
for (Screen screen : screens) {
if (!screen.isDrawing()) {
continue;
}
this.graphics.pushMatrix();
this.graphics.applyMatrix(screen.getLocation());
this.graphics.image(screen.getTexture(), 0, 0, screen.getSize().x, screen.getSize().y);
this.graphics.popMatrix();
}
}
public PGraphicsOpenGL getGraphics() {
return this.graphics;
}
public int[] getPixelsCopy() {
int[] out;
try {
sem.acquire();
this.graphics.loadPixels();
out = new int[graphics.pixels.length];
System.arraycopy(graphics.pixels, 0, out, 0, graphics.pixels.length);
sem.release();
return out;
} catch (InterruptedException ex) {
Logger.getLogger(BaseDisplay.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
/**
* Use with care !
*
* @param parent
*/
protected void setParent(PApplet parent) {
this.parent = parent;
}
public float getQuality() {
return quality;
}
public void setQuality(float quality) {
this.quality = quality;
}
public void setFrameSize(int width, int height) {
this.frameWidth = width;
this.frameHeight = height;
}
public int getWidth() {
return frameWidth;
}
public int getHeight() {
return frameHeight;
}
public void setDrawingSize(int w, int h) {
this.drawingSizeX = w;
this.drawingSizeY = h;
}
public void addScreen(Screen s) {
screens.add(s);
}
public PVector projectPointer(Screen screen, float x, float y) {
PMatrix3D screenMat = screen.getLocation();
screenMat.invert();
PVector transformed = new PVector();
screenMat.mult(new PVector(x * drawingSizeX, y * drawingSizeY), transformed);
return transformed;
}
}