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