-
Notifications
You must be signed in to change notification settings - Fork 10
Writing Your First MPE Program
Our first MPE program will be the simple 3D PeasyCam example working across multiple displays. You can find this example in the source repository of this library. You will need the PeasyCam and the MPE Cluster libraries installed for this to work.
import processing.opengl.*;
import peasy.*;
PeasyCam cam;
// MPE includes
import mpe.Process;
import mpe.Configuration;
// MPE Process thread
Process process;
// MPE Configuration object
Configuration tileConfig;
Peasy and opengl are self explanatory. Peasy will create an easy to use camera for interaction, and opengl is needed for fast 3D hardware acceleration.
The MPE includes are for the process and configuration objects, process and tileConfig. The tileConfig object will read in the configuration file we created in the previous step. The process object will create a thread that will run in the background receiving communication from the master process on how to synchronize with the rest of the display.
void setup() {
// create a new configuration object and specify the path to the configuration file
tileConfig = new Configuration("data/configuration.xml", this);
// set the size of the sketch based on the configuration file
size(tileConfig.getLWidth(), tileConfig.getLHeight(), OPENGL);
// create a new process
process = new Process(tileConfig);
// disable camera placement by MPE, because it interferes with PeasyCam
process.disableCameraReset();
// initialize the peasy cam
cam = new PeasyCam(this, 3000);
cam.setMinimumDistance(0);
cam.setMaximumDistance(5000);
// start the MPE process
process.start();
}
In the setup method, we point our tileConfig object at the configuration file we created. Then we call the Processing size() function, with the size of the local display of the process, and the 3D acceleration method. Because there will be 4 processes running on our display in the end, each process with have its own tileConfig.getLWidth() and tileConfig.getLHeight(), which will be 400. The functions grab the local width and height of the display. The corresponding getMWidth() will grab the pixel size of the entire display in width, including all displays in the configuration.
We run process.disableCameraReset(); specifically for peasycam, so peasycam doesn't interfere with MPE's functionality. This step is not necessary if not using a camera library.
Finally, we call process.start(), which will start the MPE communication thread in the background.
// when the master process receives a mouse event, broadcast the update camera state to the other processes
void mouseDragged()
{
process.broadcast(cam.getState());
}
Because mouse events only occur on the head process, we want to capture them and send them to the other processes. This is done by the process.broadcast() call. The arguments of this call can be any object, or event a vector of objects. Here, we send the camera state over to all the processes.
This will be received in the Processing draw() method, next.
Lastly, we draw a couple of boxes:
void draw() {
// synchronize this process' camera with the headnode
if(process.messageReceived())
{
// set the animation time to 0, otherwise we get weird behavior
cam.setState((CameraState) process.getMessage(), 0);
}
// draw a couple boxes
scale(5);
rotateX(-.5);
rotateY(-.5);
background(0);
fill(255,0,0);
box(200);
pushMatrix();
translate(0,0,200);
fill(0,0,255);
box(50);
popMatrix();
}
The only special thing here is that we need to check and see if we have received any messages from the master process. When the master process broadcasts the camera state, the followers processes will receive a new camera state here. They simply set their camera state to the received state, with an animation time of 0.
import processing.opengl.*;
import peasy.*;
PeasyCam cam;
// MPE includes
import mpe.Process;
import mpe.Configuration;
// MPE Process thread
Process process;
// MPE Configuration object
Configuration tileConfig;
void setup() {
// create a new configuration object and specify the path to the configuration file
tileConfig = new Configuration("data/configuration.xml", this);
// set the size of the sketch based on the configuration file
size(tileConfig.getLWidth(), tileConfig.getLHeight(), OPENGL);
// create a new process
process = new Process(tileConfig);
// disable camera placement by MPE, because it interferes with PeasyCam
process.disableCameraReset();
// initialize the peasy cam
cam = new PeasyCam(this, 3000);
cam.setMinimumDistance(0);
cam.setMaximumDistance(5000);
// start the MPE process
process.start();
}
void draw() {
// synchronize this process' camera with the headnode
if(process.messageReceived())
{
// set the animation time to 0, otherwise we get weird behavior
cam.setState((CameraState) process.getMessage(), 0);
}
// draw a couple boxes
scale(5);
rotateX(-.5);
rotateY(-.5);
background(0);
fill(255,0,0);
box(200);
pushMatrix();
translate(0,0,200);
fill(0,0,255);
box(50);
popMatrix();
}
// when the master process receives a mouse event, broadcast the update camera state to the other processes
void mouseDragged()
{
process.broadcast(cam.getState());
}
Next: How to run your program