Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

Lektion 7 – cosmic clock

25. Oktober 2011

The idea was to create a clock that represents the time that has passed since the big bang. Since that was pretty much impossible to find out (the estimates are that roughly 13.75 billion years passed since), I decided to go for a simple clock around a globe: Three lines around the globe represent hours, minutes and seconds.

After creating that, I decided to reintroduce the cosmic context by using texture on the original globe, and addding a second one around it with the texture of a galaxy. In the end I added an animation that zooms in from white nothingness, through the big bang and into the emergence of time.

The moon-textured globe with the clock rotates around its own axis until it is stopped by user interaction.

Download source + files (.zip)
/* ----------------------------------------------------------------------------
 *  codingSpace17					
 * ----------------------------------------------------------------------------
 *  Typo / Time
 * ----------------------------------------------------------------------------
 *  prog: max.rheiner@zhdk.ch
 * ----------------------------------------------------------------------------
 */
 
import peasy.test.*;
import peasy.org.apache.commons.math.*;
import peasy.*;
import peasy.org.apache.commons.math.geometry.*;
import processing.opengl.*;

int strokeWeights = 45;
PeasyCam camera;
float[] cameraOptions = new float[5];
int objectSize = 500;
color objectColor;
float objectColorIncrement = 0;
PImage objectMap;

int universeSize = 3000;
PImage universeMap;

int detail = 50;

texturedSphere universe;
texturedSphere myObject;


void setup()
{
  cameraOptions[0] = 1;
  cameraOptions[1] = 10000;
  cameraOptions[2] = 10000;
  cameraOptions[3] = 1;
  cameraOptions[4] = -1;
  
  size(800, 800, OPENGL);
  
  camera = new PeasyCam(this, width/2, height/2, 0, cameraOptions[2]);
  
  camera.setMinimumDistance(800);
  camera.setMaximumDistance(cameraOptions[2]);
  
  PFont font;  
  font = loadFont("HiraginoSansGB-W3-48.vlw");
  textFont(font, 48);
  smooth();
  
  universeMap = loadImage("universe-2.jpg");
  
  universe = new texturedSphere(universeSize, detail, detail);
  
  objectMap = loadImage("moon.jpg");
  
  myObject = new texturedSphere(objectSize, detail, detail);
  
  noStroke();
  
  //3DArc hours = new 3DArc(0, TWO_PI, 150, 3, 10, #000000);
  
  frameRate(30);
  
  loop();
  
  fill(255);
  
}



void draw()
{
  
  if(cameraOptions[0] == 1) {
    
    camera.setDistance(cameraOptions[1]);
    
    cameraOptions[1] -= cameraOptions[2] / 100;
    
    if(cameraOptions[1] <= 2000) cameraOptions[0] = 0;
    
  }
  
  if(cameraOptions[3] == 1 && cameraOptions[0] == 0) {
    
    camera.rotateY(radians(cameraOptions[4]));
        
  }
  
  background(255);
    
  //lights();  
  pushMatrix();

    translate(width / 2, height / 2, 0);
    
    pushMatrix();
      rotateX(90);  
      rotateZ(90);
      universe.drawSphere(universeMap);
    popMatrix();
    
   pushStyle();
    
      pushMatrix();
      
        setBillboard();
      
        /*translate(objectSize + strokeWeights, 0, 0);
      
        rotateX(-90);
        
        rotateY(90);*/
            
        fill(255);
                  
        text(hour(), objectSize + strokeWeights, -100, 0);
        text(minute(), objectSize + strokeWeights, 20, 0);
        text(second(), objectSize + strokeWeights, 140, 0);
      
      popMatrix();
    
    popStyle();
    
    directionalLight(255, 255, 255, -1, 1, -1);
    
    pushMatrix();
      //sphereDetail(200);
      fill(objectColor);
      rotateX(radians(90));
      myObject.drawSphere(objectMap);
      noFill();
      //cylinder(150, 300, 100);
    popMatrix();
    
    pushStyle();
      stroke(0);
      strokeWeight(1);
      noFill();
      
      rotateX(radians(90));
      
      float hours = map(hour(), 0, 24, 0, 360);
      
      float minutes = minute() * 6;
      
      float seconds = (second() + (millis() * 1.0 / 1000) % 1) * 6;
                        
      for(float i = 0; i < strokeWeights; i+=0.5) {
                
          pushMatrix();
  
            stroke((28 + i * 2) % 255, 141, 212);
          
            translate(0, 0, +100+i);
                    
            arc(0, 0, objectSize * 2 + strokeWeights - i, objectSize * 2 + strokeWeights - i, radians(0), radians(hours));
          
          popMatrix();
          
          pushMatrix();
          
            stroke(135, 224, (27 + i * 2) % 255);
          
            translate(0, 0, (-strokeWeights / 2) + i);
                      
            arc(0, 0, objectSize * 2 + strokeWeights, objectSize * 2 + strokeWeights, radians(0), radians(minutes));
                
          popMatrix();
  
          pushMatrix();
          
            stroke(224, (70 + i * 2) % 255, 27);
  
            translate(0, 0, -100-i);
            
            arc(0, 0, objectSize * 2 + strokeWeights - i, objectSize * 2 + strokeWeights - i, radians(0), radians(seconds));
          
          popMatrix();
                    
      }
      
      //ellipse(0, 0, 200, 200);
      
      //curve(0, 0, -800, -200, 0, -200, 200, 0, 200, 0, 0, -800);
          
    popStyle();
  popMatrix();
  
  if(minute() == 0 && second() == 0) {
   
    objectColor = color((28 + objectColorIncrement) % 130, 141, 212);
    
    objectColorIncrement += 20;
    
  } else if (second() ==  0) {
  
    objectColor = color(135, 224, (27 + objectColorIncrement) % 130);
  
    objectColorIncrement += 20;
  
  } else {
  
    objectColor = color(255);
    
    objectColorIncrement = 0;
    
  }
    
}



void cylinder(float w, float h, int sides)
{
  float angle;
  float[] x = new float[sides+1];
  float[] z = new float[sides+1];
 
  //get the x and z position on a circle for all the sides
  for(int i=0; i < x.length; i++){
    angle = TWO_PI / (sides) * i;
    x[i] = sin(angle) * w;
    z[i] = cos(angle) * w;
  }
 
  //draw the top of the cylinder
  beginShape(TRIANGLE_FAN);
 
  vertex(0,   -h/2,    0);
 
  for(int i=0; i < x.length; i++){
    vertex(x[i], -h/2, z[i]);
  }
 
  endShape();
 
  //draw the center of the cylinder
  beginShape(QUAD_STRIP); 
 
  for(int i=0; i < x.length; i++){
    vertex(x[i], -h/2, z[i]);
    vertex(x[i], h/2, z[i]);
  }
 
  endShape();
 
  //draw the bottom of the cylinder
  beginShape(TRIANGLE_FAN); 
 
  vertex(0,   h/2,    0);
 
  for(int i=0; i < x.length; i++){
    vertex(x[i], h/2, z[i]);
  }
 
  endShape();
}




void mousePressed() {
 
 cameraOptions[3] = 0;
  
}


//*** Set Billboard ***//

void setBillboard()
{
 PMatrix3D mp;

 mp = (PMatrix3D)getMatrix();
 mp.m00 = 1;
 mp.m01 = 0;
 mp.m02 = 0;

 mp.m10 = 0;
 mp.m11 = 1;
 mp.m12 = 0;

 mp.m20 = 0;
 mp.m21 = 0;
 mp.m22 = 1;

 setMatrix(mp);
}


class texturedSphere {

  float R = 3000;
  int xDetail = 50;
  int yDetail = 50;
  float[] xGrid = new float[xDetail+1];
  float[] yGrid = new float[yDetail+1];
  float[][][] allPoints = new float[xDetail+1][yDetail+1][3];
  
  //*** Textured Sphere ***//
  
  ////////////////////////////////////////////////////////////////////////
  texturedSphere(float R, int xDetail, int yDetail){
  
    this.R = R;
    this.xDetail = xDetail;
    this.yDetail = yDetail;
    
    // Create a 2D grid of standardized mercator coordinates
    for(int i = 0; i <= xDetail; i++){
      xGrid[i]= i / (float) xDetail;
    } 
    for(int i = 0; i <= yDetail; i++){
      yGrid[i]= i / (float) yDetail;
    }
  
    textureMode(NORMALIZED);
  
    // Transform the 2D grid into a grid of points on the sphere, using the inverse mercator projection
    for(int i = 0; i <= xDetail; i++){
      for(int j = 0; j <= yDetail; j++){
        allPoints[i][j] = mercatorPoint(R, xGrid[i], yGrid[j]);
      }
    }
  }
  
  ////////////////////////////////////////////////////////////////////////
  float[] mercatorPoint(float R, float x, float y){
  
    float[] thisPoint = new float[3];
    float phi = x*2*PI;
    float theta = PI - y*PI;
  
    thisPoint[0] = R*sin(theta)*cos(phi);
    thisPoint[1] = R*sin(theta)*sin(phi);
    thisPoint[2] = R*cos(theta);
  
    return thisPoint;
  }
  
  ////////////////////////////////////////////////////////////////////////
  void drawSphere(PImage Map){
  
    for(int j = 0; j < yDetail; j++){
      beginShape(TRIANGLE_STRIP);
      texture(Map);
      for(int i = 0; i <= xDetail; i++){
        vertex(allPoints[i][j+1][0],   allPoints[i][j+1][1],   allPoints[i][j+1][2],   xGrid[i],   yGrid[j+1]);
        vertex(allPoints[i][j][0],     allPoints[i][j][1],     allPoints[i][j][2],     xGrid[i],   yGrid[j]);
      }
      endShape(CLOSE);
    }
  }

}