Last active
November 14, 2015 19:57
-
-
Save eamonnbell/b6d327915c464b1eef64 to your computer and use it in GitHub Desktop.
VR experiments with Processing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.jsfml.audio.*; | |
import org.jsfml.window.event.*; | |
import org.jsfml.window.*; | |
import org.jsfml.system.*; | |
import org.jsfml.internal.*; | |
import org.jsfml.graphics.*; | |
import java.util.*; | |
import java.text.*; | |
import java.nio.file.*; | |
import peasy.*; | |
BlobComplex blob_complex; | |
PeasyCam cam; | |
VRListener vr_listener; | |
class Blob { | |
PVector location; | |
PVector velocity; | |
PVector target_location; | |
Date date; | |
int size; | |
String filename; | |
Music sound; | |
Blob(PVector location_, int size_, Date date_, String filename_) { | |
// Blobs represent sound sources and have location, size and velocity | |
location = location_; | |
target_location = location_; | |
size = size_; | |
date = date_; | |
velocity = new PVector(0, 0, 0); | |
filename = filename_; | |
// Create a new JSFML music object for each Blob | |
sound = new Music(); | |
Path p = Paths.get(sketchPath(filename)); | |
try { | |
sound.openFromFile(p); | |
} | |
catch (Exception e) { | |
println("Unable to open music file."); | |
println(e); | |
} | |
// Make sure the Music object takes absolution positions | |
sound.setRelativeToListener(false); | |
// MinDistance is the maximum distance at which a sound is heard at its maximum volume | |
sound.setMinDistance(250); | |
} | |
void play() { | |
// Wraps the play function of the sound | |
sound.play(); | |
} | |
void update() { | |
// Increment location by velocity on every update | |
location.add(velocity); | |
// If Blob is in motion to a new target and gets close enough, set | |
// velocity to zero and snap to target_location | |
if (PVector.sub(target_location, location).mag() < 2) { | |
location = target_location; | |
velocity = new PVector(0, 0, 0); | |
} | |
PVector l = location.get(); | |
l.add(new PVector(width/2, height/2, 0)); | |
sound.setPosition(l.x, l.y, l.z); | |
} | |
void move_to(PVector target) { | |
target_location = target; | |
velocity = PVector.sub(target_location, location); | |
velocity.normalize(); | |
velocity.mult(3); | |
} | |
void display() { | |
pushMatrix(); | |
PVector l = location.get(); | |
l.add(new PVector(width/2, height/2, 0)); | |
translate(l.x, l.y, l.z); | |
sphere(size); | |
popMatrix(); | |
} | |
} | |
class BlobComplex { | |
Table table = loadTable("data.csv", "header"); | |
int blobcount = table.getRowCount(); | |
Blob[] blobs = new Blob[blobcount]; | |
BlobComplex() { | |
Table table = loadTable("data.csv", "header"); | |
for (int i = 0; i < table.getRowCount (); i++) { | |
TableRow row = table.getRow(i); | |
PVector rand_loc = PVector.random3D(); | |
rand_loc.mult(100); | |
Date blobDate = null; | |
SimpleDateFormat isoSDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); | |
try { | |
blobDate = isoSDF.parse(row.getString("time")); | |
} | |
catch (Exception e) { | |
println("Unable to parse date stamp."); | |
} | |
blobs[i] = new Blob(rand_loc, row.getInt("size"), blobDate, row.getString("filename")); | |
} | |
} | |
void update() { | |
// Update every Blob in the BlobComplex | |
for (int i = 0; i < blobs.length; i++) { | |
blobs[i].update(); | |
} | |
} | |
void display() { | |
// Update every Blob in the BlobComplex | |
for (int i = 0; i < blobs.length; i++) { | |
blobs[i].display(); | |
} | |
} | |
} | |
class VRListener { | |
PVector location; | |
PVector direction; | |
VRListener(PVector location_, PVector direction_) { | |
// VRListener is just a thin wrap around the Listener object | |
// which allows us to render a representation of it. | |
location = location_; | |
direction = direction_; | |
// Listener represents the location and direction of the listener in 3D space | |
// It doesn't require instantiation and has only static methods. | |
Listener.setPosition(location.x, location.y, location.z); | |
Listener.setDirection(direction.x, direction.y, direction.z); | |
} | |
void display() { | |
pushMatrix(); | |
// Draw a red sphere representing the location of the listener | |
PVector l = location.get(); | |
l.add(new PVector(width/2, height/2, 0)); | |
translate(l.x, l.y, l.z); | |
fill(200, 15, 15); | |
sphere(20); | |
fill(255); | |
// Draw a green line representing the orientation of the listener | |
strokeWeight(3); | |
stroke(0, 255, 0); | |
PVector d = direction.get(); | |
d.mult(35); | |
line(0, 0, 0, d.x, d.y, d.z); | |
noStroke(); | |
popMatrix(); | |
} | |
void update() { | |
// Set the position and location of the listener to that of the VRListener | |
Listener.setPosition(location.x, location.y, location.z); | |
Listener.setDirection(direction.x, direction.y, direction.z); | |
} | |
} | |
void setup() { | |
size(640, 640, P3D); | |
// Create and setup | |
cam = new PeasyCam(this, width/2, height/2, 0, 100); | |
cam.setMinimumDistance(50); | |
cam.setMaximumDistance(500); | |
// Create blob complex | |
blob_complex = new BlobComplex(); | |
// Create VR listener with (position, direction) | |
vr_listener = new VRListener(new PVector(0, 0, 0), new PVector(1, 0, 1)); | |
} | |
void draw() { | |
background(0); | |
noStroke(); | |
lights(); | |
vr_listener.display(); | |
vr_listener.update(); | |
blob_complex.update(); | |
blob_complex.display(); | |
} | |
void keyPressed() { | |
// Move a random blob to a random location on the sphere of size 250 | |
// and trigger associated sound. | |
PVector rand_loc = PVector.random3D(); | |
rand_loc.mult(int(random(250))); | |
int index = int(random(blob_complex.blobcount)); | |
blob_complex.blobs[index].move_to(rand_loc); | |
blob_complex.blobs[index].play(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment