Digital Reality

Published by Tim on Sunday April 10, 2022

Last modified on January 25th, 2024 at 14:07

A few months ago I did a livestream marathon on Youtube over a period of 5 days. The theme I chose was “Digital Reality” and I wanted to see to what extent I could build a 3D world with first-person control in a limited amount of time using Processing. I had a lot of fun, also because many of you were there live and gave me feedback via the chat. Thanks again for that.

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

sketch.pde

float MAGNITUDE = 12000;
PImage tex, floor;

PGraphics scene;

PImage texture;

PShader shade;

ArrayList<Videowall> walls;

float speed = 50;

float tileW;
float tileH;

float cameraZ = -5000;
PShape globe;

color BG = 0;
color FG = #F1F1F1;

float mx, my;

float TILES_X = 100;
float TILES_Y = 100;

void setup() {
  size(1920, 1080, P3D);
  tex = loadImage("16.jpg");
  floor = loadImage("25.jpg");
  tex.filter(GRAY);
  floor.filter(GRAY);

  globe = createShape(SPHERE, 10000);
  globe.textureMode(NORMAL);
  globe.setTexture(tex);
  globe.setStroke(false);

  scene = createGraphics(width, height, P3D);
  texture = createGraphics(width, height, P3D);

  walls = new ArrayList<Videowall>();

  for (int i = 0; i < 20; i++) {
    walls.add(new Videowall(i));
  }

  imageMode(CENTER);

  tileW = MAGNITUDE/TILES_X;
  tileH = MAGNITUDE/TILES_Y;

  shade = loadShader("halftone.glsl");
}

void draw() {
  shade.set("pixelsPerRow", 8000);

  mx = map(mouseX, 0, width, -90, 90);
  my = map(mouseY, 0, height, 200, -10000);

  float eyeX = width/2.0;
  float eyeY = height/2.0 + my;
  float eyeZ =(height/2.0) / tan(PI*30.0 / 180.0);
  float centerX = width/2.0;
  float centerY = height/2.0;
  float centerZ = 0;
  float upX = 0;
  float upY = 1;
  float upZ = 0;

  scene.beginDraw();
  scene.background(BG);
  scene.camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);

  // scene.directionalLight(255, 255, 255, 0, 0.5, -1);
  scene.perspective(PI/3.0, (float)width/height, 1, 100000);
  drawScene();
  interactionKeyboard();

  scene.endDraw();

  image(scene, width/2, height/2);
  filter(shade);

  texture = g.get();

  rec(30,1000);
}

ui.pde

void interactionKeyboard() {
  if (keyPressed) {
    if (key == 'w') {
      cameraZ += speed;
    } else if (key == 's') {
      cameraZ -= speed;
    } else if(key == 'p'){
     saveFrame("out/" + nf(int(random(1000000)),7) + ".png"); 
    }
  }
}

scene.pde

void drawScene() {

  // create the dome / sky
  scene.fill(#0000FF);
  scene.noStroke();
  scene.push();
  scene.translate(scene.width/2, scene.height/2);
  scene.rotateY(radians(frameCount * 1));
  // globe.setTexture(texture);
  scene.shape(globe);
  scene.pop();

  // Create the floor
  
  scene.fill(FG);
  scene.noStroke();
  scene.push();
  scene.translate(scene.width/2, scene.height/2 + 1200, cameraZ);
  scene.rotateY(radians(90 + mx));
  scene.rotateX(radians(90));
  scene.push();
  scene.fill(BG);
  scene.translate(0, 20);
  scene.textureMode(NORMAL); 
  scene.beginShape();
  scene.texture(floor);
  scene.vertex(-MAGNITUDE, -MAGNITUDE, 0, 0);
  scene.vertex(MAGNITUDE, -MAGNITUDE, 1, 0);
  scene.vertex(MAGNITUDE, MAGNITUDE, 1, 1);
  scene.vertex(-MAGNITUDE, MAGNITUDE, 0, 1);
  scene.endShape();
  scene.pop();
  
  scene.push();
  scene.translate(0,0,2100);
  // scene.rotateZ(radians(-frameCount));
  // Distribute the videowalls
  for (int i = 0; i < walls.size(); i++) {

    Videowall W = walls.get(i);

    scene.push();
    scene.translate(W.Z, W.X, W.Y);
    scene.rotateX(radians(W.ROTX));
    scene.rotateY(radians(W.ROTY));
    scene.rotateZ(radians(W.ROTZ));
    W.display();
    scene.image(texture, 0, 0,W.wallSize,W.wallSize);
    scene.pop();
  }
  
  scene.pop();


  scene.pop();
}

videowall.pde

class Videowall {

  PGraphics pg;

  float X;
  float Y;
  float Z;
  float ROTX, ROTY, ROTZ;
  
  int wallSize;

  color VIDEOWALL_FG = #000000;
  color VIDEOWALL_BG = #F1F1F1;

  int modulo;
  int s;

  Videowall(int _s) {

    modulo = int(random(5, 60));
    
    
    wallSize = int(random(200,3000));

    pg = createGraphics(wallSize, wallSize, P3D);

    noStroke();
    
    float mag = 500;
    
    X = random(-mag, mag);
    Y = random(-mag, mag);
    Z = random(-mag, mag);
    
   // X = 0;
   // Y = 0;
    // Z = 0;
    
    ROTX = random(-180, 180);
    ROTY = random(0,0);
    ROTZ = random(-180, 180);

  }

  void display() {

    float eyeX = pg.width/2.0 + mx * 3;
    float eyeY = pg.height/2.0;
    float eyeZ =(pg.height/2.0) / tan(PI*30.0 / 180.0);
    float centerX = pg.width/2.0;
    float centerY = pg.height/2.0;
    float centerZ = 0;
    float upX = 0;
    float upY = 1;
    float upZ = 0;

    pg.beginDraw();
    pg.background(VIDEOWALL_FG);
    pg.camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
    pg.fill(VIDEOWALL_BG);
    pg.directionalLight(255, 255, 255, -1, 0, 0);
    pg.noStroke();
    pg.translate(pg.width/2, pg.height/2);
    pg.sphere(160);
    pg.endDraw();
  }
}

Related

Lena Weber about her collaboration with A. G. Cook

Lena: This 10-minute visualiser for A. G. Cooks album teaser featuring my python archive generator, is one of my favourite […]

Computer Cursive by Tay Papon Punyahotra

One of the first exercises I assign to my students in my seminars is called “Random Compositions”. Basically, it’s quite […]

A custom Mockup Tool, built with Processing (updated)

For my students at Elisava, I have created a new version of my mockup-tool. You need two different files for […]

Preview: When Computers create Collages

2023-12-01 Today I want to share with you a first prototype that will be the basis for a new course […]

Preview: Random Compositions

One of the most exciting and maybe even unsettling discoveries in the learning process of Creative Coding in Graphic Design […]

trustTheProcess(4) – Data Stream

2023-08-03 In this episode I have been looking at String Methods in p5.js, or rather in Javascript. Originally I wanted […]

trustTheProcess(3) – ASCII Blobs

2023-07-20 Today I share the edit of the third episode of my trustTheProcess() livestreams with you. In it I rebuilt […]

trustTheProcess(2) – Time in Space

In this livestream from June 22, 2023, I used Processing to develop an interactive, three-dimensional timeline of exemplary historical data […]