3D Environments
First Person Perspective
Processing
The sensor we used in session 3 to control a virtual object can also be used to control a virtual camera. By placing sensor/ESP32/battery on a headset, head movements can be tracked an linked to the virtual camera. Here is an example in Processing. A 3D environment is populated with simple spheres as placeholders for potential virtual performance partners that may sound. They are defined in the class 'Sonatars'.
The first person camera is also defined by its own class ('FPCamera'). Orientation in the 3D environment is derived from the head movements of the user. Key strokes allow for moving forwards or backwards in space. Of course, the interactions for movement could be made interactive in a more advanced way by adding more interfaces to the setup.
// Install UDP library by Stephane Cousot
import peasy.*;
//import peasy.org.apache.commons.math.geometry.Vector3D;
//import peasy.org.apache.commons.math.geometry.Rotation;
import oscP5.*;
import netP5.*;
import hypermedia.net.*;
//PeasyCam cam;
FirstPersonCamera camera;
OscP5 oscP5;
NetAddress myRemoteLocation;
PVector cameraPos;
int population = 50;
Sonatar[] sonicActors = new Sonatar[population];
UDP udp; // Create a UDP object
int port = 8888; // Set the port number to listen for incoming messages from the ESP32
float rotX = 0;
float rotY = 0;
float rotZ = 0;
void setup() {
//size(1200, 800, P3D);
fullScreen(P3D);
camera = new FirstPersonCamera(this, 0, 0, 0);
//camera = new FirstPersonCamera(this, 0, -100, 300);
camera.setRotation(15, 0, 0);
// Initialize OSC addresses for SuperCollider
oscP5 = new OscP5(this,12000); // Port number 12000
myRemoteLocation = new NetAddress("127.0.0.1",57120); // localhost
// Initialize the UDP connection and start listening for ESP32
udp = new UDP(this, port);
udp.listen(true);
for(int i = 0; i < sonicActors.length; i++ ){
sonicActors[i] = new Sonatar(random(-PI,PI), random(-PI,PI), random(300,1000));
//sonicActors[i] = new Sonatar(PI, random(-PI,PI), random(300,1000));
OscMessage initialMessage = new OscMessage("/new");
oscP5.send(initialMessage, myRemoteLocation);
}
}
void draw() {
background(0);
ambientLight(100, 100, 126);
directionalLight(100, 130, 160, -1, 0, 0);
camera.setRotation(rotZ, rotX, rotY); // Rotate the camera angle according to the sensor data
camera.update();
for(int i = 0; i < sonicActors.length; i++ ){
sonicActors[i].paint();
//float [] myPosFloat = cam.getPosition();
//PVector myPos = new PVector(myPosFloat[0], myPosFloat[1], myPosFloat[2]);
//float dist = sonicActors[i].getDistance(myPos);
OscMessage volMessage = new OscMessage("/loudness");
volMessage.add(i);
//volMessage.add(dist);
oscP5.send(volMessage, myRemoteLocation);
//println(dist);
}
}
// Receive function for UDP. Triggered when UDP data is arriving no matter which port
void receive(byte[] data, String ip, int port) {
String message = new String(data); // Convert the byte array to a string
String senderIP = ip; // We can use the sender IP to see who was sending the data
int senderPort = port; // We can use the sender's port number to filter by sender
// Split the received String to get the XYZ-parameters
String[] values = split(message, ",");
String[] valX = split(values[0], ":");
String[] valY = split(values[1], ":");
String[] valZ = split(values[2], ":");
// Get the values and convert them from degrees to radians
rotX = radians(float(valX[1]));
rotY = radians(float(valY[1]));
rotZ = radians(float(valZ[1]));
println("Rotation x: "+rotX+" y: "+rotY+" z: "+rotZ);
}
void keyPressed() {
float moveAmount = 10;
if (key == 'i') camera.moveForward(moveAmount);
if (key == 'k') camera.moveForward(-moveAmount);
}
TouchDesigner
Last updated