Created
March 24, 2020 21:17
-
-
Save possan/dbc96257c80072e14a6f0c951fd7d897 to your computer and use it in GitHub Desktop.
Dome projection animation tester
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
// Install and run processing 3 from processing.org | |
// Open Sketch menu > Click Import library > Add library... | |
// Install SelectFile plugin (v0.0.2) | |
// Install Video plugin (v1.0.1) | |
// Paste this code and hit Run | |
import select.files.*; | |
import processing.video.*; | |
static int IMAGE_DURATION = 3000; | |
class TexHolder { | |
int texWidth = 0; | |
int texHeight = 0; | |
float width = 1.0; | |
float height = 1.0; | |
PImage image = null; | |
String path = ""; | |
Movie movie = null; | |
long imageDeadline = 0; | |
String statusString = ""; | |
TexHolder(int texWidth, int texHeight) { | |
this.texWidth = texWidth; | |
this.texHeight = texHeight; | |
} | |
void load(String path, PApplet applet) { | |
this.path = path; | |
this.movie = null; | |
this.image = null; | |
if (path.toLowerCase().indexOf(".mov") != -1) { | |
try { | |
Movie m = new Movie(applet, path); | |
m.play(); | |
this.movie = m; | |
} | |
catch(Exception e) { | |
println("Exception", e); | |
} | |
} else { | |
try { | |
PImage t = null; | |
t = loadImage(path); | |
this.image = t; | |
} | |
catch(Exception e) { | |
println("Exception", e); | |
} | |
this.imageDeadline = millis() + IMAGE_DURATION; | |
} | |
} | |
void update() { | |
this.width = 1.0; | |
this.height = 1.0; | |
if (this.movie != null) { | |
if (this.movie.available()) { | |
this.movie.read(); | |
} | |
this.width = this.movie.width; | |
this.height = this.movie.height; | |
this.statusString = "Time " + round(this.movie.time() * 1000.0) + "/" + round(this.movie.duration() * 1000.0) + "ms"; | |
} else if (this.image != null) { | |
this.width = this.image.width; | |
this.height = this.image.height; | |
if (millis() < this.imageDeadline) { | |
this.statusString = "Still image"; | |
} else { | |
this.statusString = "Still image (invisible)"; | |
} | |
} else { | |
this.statusString = "Not loaded"; | |
} | |
} | |
void trigger() { | |
if (this.movie != null) { | |
this.movie.jump(0); | |
this.movie.play(); | |
} else if (this.image != null) { | |
this.imageDeadline = millis() + IMAGE_DURATION; | |
} | |
} | |
void bind() { | |
fill(0, 0, 0); | |
textureWrap(REPEAT); | |
if (this.image != null) { | |
if (millis() < this.imageDeadline) { | |
fill(255, 255, 255); | |
texture(this.image); | |
} | |
} | |
if (this.movie != null) { | |
fill(255, 255, 255); | |
texture(this.movie); | |
} | |
} | |
void drawPreview(int bx, int by, int mult) { | |
int pw = 100 * mult; | |
int ph = round(pw / (float)(texWidth / texHeight)); | |
blendMode(BLEND); | |
fill(0, 0, 0); | |
rect(bx, by, pw, ph); | |
blendMode(ADD); | |
if (this.movie != null) { | |
image(this.movie, bx, by, pw, ph); | |
} else if (this.image != null) { | |
image(this.image, bx, by, pw, ph); | |
} | |
} | |
} | |
int selectTarget = 0; | |
TexHolder cylinderTex = new TexHolder(2048, 512); | |
TexHolder topTex = new TexHolder(512, 512); | |
float scrollX = 0.0; | |
float scrollY = 0.0; | |
float velocityX = 0.0; | |
float velocityY = 0.0; | |
void fileSelected(File selection) { | |
if (selection == null) { | |
println("Window was closed or the user hit cancel."); | |
} else { | |
println("User selected " + selection.getAbsolutePath()); | |
if (selectTarget == 1) { | |
cylinderTex.load(selection.getAbsolutePath(), this); | |
} | |
if (selectTarget == 2) { | |
topTex.load(selection.getAbsolutePath(), this); | |
} | |
} | |
} | |
void setup() { | |
size(1200, 800, P3D); | |
frameRate(60); | |
surface.setTitle("Dome Preview"); | |
surface.setResizable(true); | |
cylinderTex.load("./cylinderdemo.mov", this); | |
topTex.load("./topdemo2.mov", this); | |
} | |
void _drawDomeVertex(float u, float v, float radii, int mapping, float umax, float vmax) { | |
float lata = u * PI / 50.0f; | |
float lat_x = -cos(lata); | |
float lat_y = sin(lata); | |
float vf = v / 25.0f; | |
float lon = vf * radii; | |
float rmult = sin(acos(v / 25.000001)); | |
float x = lat_x * radii * rmult; | |
float y = lat_y * radii * rmult; | |
float z = lon; | |
float tu, tv; | |
if (mapping == 1) { | |
tu = 1.0 * u * umax / 100.0f; | |
tv = 1.0 * vmax * (1.0 - vf); | |
vertex(x, y, z, tu, tv); | |
} else { | |
tu = 1.0 * umax * ((lat_x * rmult * 0.5f) + 0.5f); | |
tv = 1.0 * vmax * ((lat_y * rmult * 0.5f) + 0.5f); | |
vertex(x, y, z, tu, tv); | |
} | |
} | |
void _drawDomeShape(int mapping, float radius, float umax, float vmax) { | |
float G = 1.0; | |
for (int j=0; j<25; j++) { | |
for (int i=0; i<100; i++) { | |
_drawDomeVertex(i, j, radius, mapping, umax, vmax); | |
_drawDomeVertex(i+G, j, radius, mapping, umax, vmax); | |
_drawDomeVertex(i+G, j+G, radius, mapping, umax, vmax); | |
_drawDomeVertex(i, j+G, radius, mapping, umax, vmax); | |
} | |
} | |
} | |
void drawUI() { | |
blendMode(BLEND); | |
pushMatrix(); | |
cylinderTex.drawPreview(200, 20, 3); | |
fill(255, 255, 0); | |
text("Cylinder clip (" + cylinderTex.width + "x" + cylinderTex.height + ")", 20, 40); | |
fill(200, 200, 200); | |
text(cylinderTex.statusString, 20, 60); | |
text("[1] - Trigger", 20, 80); | |
text("[Q] - Load mov/png", 20, 100); | |
topTex.drawPreview(200, 120, 1); | |
blendMode(ADD); | |
fill(255, 255, 0); | |
text("Topdown clip (" + topTex.width + "x" + topTex.height + ")", 20, 140); | |
fill(200, 200, 200); | |
text(topTex.statusString, 20, 160); | |
text("[2] - Trigger", 20, 180); | |
text("[W] - Load mov/png", 20, 200); | |
//text("scroll = " + round(scrollX) + "," + round(scrollY), 20, 300); | |
popMatrix(); | |
} | |
void drawTest() { | |
blendMode(SUBTRACT); | |
pushMatrix(); | |
beginShape(); | |
cylinderTex.bind(); | |
fill(100, 100, random(255), 0.5); | |
vertex(300 + random(100), 300, 0, 0); | |
vertex(600, 250, 1024, 0); | |
vertex(650, 600, 1024, 512); | |
vertex(300, 500, 0, 512); | |
endShape(); | |
beginShape(); | |
topTex.bind(); | |
fill(random(255), 100, 100, 0.5); | |
vertex(300, 300, 0, 0); | |
vertex(600 + random(100), 250, 1024, 0); | |
vertex(650, 600, 1024, 512); | |
vertex(300, 500, 0, 512); | |
endShape(); | |
popMatrix(); | |
} | |
void drawDome() { | |
blendMode(BLEND); | |
pushMatrix(); | |
beginCamera(); | |
perspective(45, 1200.0/800.0, 0.1, 1000.0); | |
camera( | |
0.0, 200.0, 150.0, | |
0.0, 0.0, 25.0, | |
0.0, 1.0, 0.0); | |
pushMatrix(); | |
rotate(scrollY / 1000.0, 1, 0,0); | |
rotate(scrollX / 1000.0, 0, 0, 1); | |
// Render Grid, write Z | |
blendMode(ADD); | |
noLights(); | |
noFill(); | |
beginShape(LINES); | |
stroke(128, 128, 128); | |
strokeWeight(1); | |
for (int g=-20; g<=20; g++) { | |
float x = (float)g * 20.0; | |
vertex(-400, x, 0); | |
vertex(400, x, 0); | |
vertex(x, -400, 0); | |
vertex(x, 400, 0); | |
} | |
endShape(); | |
noStroke(); | |
// Render base color shape, write Z | |
blendMode(BLEND); | |
spotLight(255, 255, 255, 300, -150, 140, -1, 0, -0.5, PI/2, 2); | |
beginShape(QUADS); | |
fill(80, 80, 80); | |
_drawDomeShape(0, 100.0, 1.0, 1.0); | |
endShape(); | |
//fill(100, 255, random(255)); | |
//box(100); | |
noLights(); | |
// Render layer 1, additive, do not write Z | |
hint(DISABLE_DEPTH_MASK); | |
blendMode(ADD); | |
beginShape(QUADS); | |
cylinderTex.bind(); | |
_drawDomeShape(1, 101, cylinderTex.width, cylinderTex.height); | |
endShape(); | |
blendMode(ADD); | |
beginShape(QUADS); | |
topTex.bind(); | |
_drawDomeShape(2, 102, topTex.width, topTex.height); | |
endShape(); | |
hint(ENABLE_DEPTH_MASK); | |
popMatrix(); | |
endCamera(); | |
popMatrix(); | |
} | |
void draw() { | |
cylinderTex.update(); | |
topTex.update(); | |
scrollX += velocityX; | |
scrollY += velocityY; | |
velocityX *= 0.95; | |
velocityY *= 0.95; | |
background(64); | |
noStroke(); | |
textSize(14); | |
drawUI(); | |
//drawTest(); | |
drawDome(); | |
} | |
void mouseDragged() { | |
velocityX += mouseX - pmouseX; | |
velocityY += mouseY - pmouseY; | |
} | |
void keyPressed() { | |
if (key == '1') { | |
cylinderTex.trigger(); | |
} | |
if (key == '2') { | |
topTex.trigger(); | |
} | |
if (key == 'q') { | |
selectTarget = 1; | |
selectInput("Select a .mov or .png", "fileSelected"); | |
} | |
if (key == 'w') { | |
selectTarget = 2; | |
selectInput("Select a .mov or .png", "fileSelected"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment