kerjos-AnimatedLoop

I think my concept comes across, although this piece isn’t very pretty. I used Penner’s Ease Out Back to mimic just a bit the shudder of the projector as it passes on to the next slide.

I was thinking at first in terms of projection, but then of course, to make two wheels work together, there had to be a second transformation after “projection into slide.” Photography negatives seemed very appropriate for this: Light exposure is responsible for creating both the negative image on the film and the positive image back on paper. Thus, you get a suggested cycle of images.

This idea doesn’t really lend itself to simple geometry, in retrospect. I think it would be better conceived with more photo-collage elements, and maybe even without the 3D, which gave me considerable trouble.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Thank you Golan for this template!
//===================================================
// Global variables. 
String  myNickname = "nickname"; 
int     nFramesInLoop = 240;
int     nElapsedFrames;
boolean bRecording;
 
float x,y,z;
float xRotation = 0;
float yRotation = 0;
float zRotation = 0;
PImage img;
PImage img2;
PImage img3;
PImage img4;
 
//===================================================
void setup() {
  size (500, 500, P3D); 
  x = width/2;
  y = height/2;
  z = 0;
  img = loadImage("muybridgeHorse.jpg");
  img2 = loadImage("muybridgeHorse2.jpg");
  img3 = loadImage("muybridgeHorse3.jpg");
  img4 = loadImage("muybridgeHorse4.jpg");
  bRecording = false;
  nElapsedFrames = 0;
}
//===================================================
void keyPressed() {
  if ((key == 'f') || (key == 'F')) {
    bRecording = true;
    nElapsedFrames = 0;
  }
  if (key == CODED) {
      if (keyCode == LEFT) {
         yRotation += 0.2; 
      }
      if (keyCode == RIGHT) {
         yRotation -= 0.2; 
      }
      if (keyCode == UP) {
         xRotation += 0.2; 
      }
      if (keyCode == DOWN) {
         xRotation -= 0.2; 
      }
   }
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
  // here, I set the background and some other graphical properties
  background (50);
  smooth(); 
  stroke (0, 0, 0); 
  strokeWeight (2);
 
  //----------------------
  // Here, I assign some handy variables. 
  float px = 20;
  float py = 30;
 
 
  //----------------------
  // If we're recording, I include some visual feedback. 
  fill (255, 0, 0);
  textAlign (CENTER); 
  //String percentDisplayString = nf(percent, 1, 3);
  //text (percentDisplayString, px, py-15);
 
  //My Art:
   //float whichSlide = map(percent, 0,1, 0,8);
  float halfPercent = percent;
  if (halfPercent > 0.5) {
    halfPercent = 0.5;
  }
 
   translate(x,y,z);
   rotateY(yRotation);
   rotateX(xRotation);
 
   //Best Orientation:
   rotateX(-PI/4);
   translate(0,-100,0);
 
   //rectMode(CENTER);
   stroke(255,0,0);
   strokeWeight(1);
   //rect(0,0,25,25);
 
   pushMatrix();
 
   translate(0,100,-100);
   rotateX(PI/2);
 
   float r1 = 125;
   float r2 = 200;
   float cx = 0;
   float cy = 0;
 
   float[][] innerSlidePositions;
   innerSlidePositions = new float[8][3];
   stroke(255,0,0);
   noFill();
   //ellipse(cx,cy,r1*2,r1*2);
   float preTheta = map(halfPercent, 0,0.5, 0,1);
   //float preTheta2 = function_PennerEaseOutElastic(preTheta);
   float preTheta2 = function_PennerEaseOutBack(preTheta);
   float theta = map(preTheta2, 0,1, 0,PI/4);
   for (int i=0; i<8; i++) {
     float x1 = (r1 * cos(theta));
     float y1 = (r1 * sin(theta));
     float[] slidePosition = {x1,y1,theta};
     innerSlidePositions[i] = slidePosition;
     theta-=PI/4;
   }
   drawInnerSlides(innerSlidePositions,percent);
 
   float[][] outerSlidePositions;
   outerSlidePositions = new float[8][3];
   stroke(255,0,0);
   noFill();
   //ellipse(cx,cy,r2*2,r2*2);
   preTheta = map(halfPercent, 0,0.5, 0,1);
   //preTheta2 = function_PennerEaseOutElastic(preTheta);
   preTheta2 = function_PennerEaseOutBack(preTheta);
   theta = map(preTheta2, 0,1, 0,-PI/4);
   for (int i=0; i<8; i++) {
     float x = (r2 * cos(theta));
     float y = (r2 * sin(theta));
     float[] slidePosition = {x,y,theta};
     outerSlidePositions[i] = slidePosition;
     theta-=PI/4;
   }
   drawOuterSlides(outerSlidePositions,percent);
 
   //Projectors
   drawProjectors(percent);
 
   popMatrix();
}
 
void drawLight() {
  // Define colors ... based on https://processing.org/examples/lineargradient.html
    color c1 = color(255);
    color c2 = color(255,255,255,0);
    //noFill();
    //quad(-10,0,10,0,50,-200,-50,-200);
    for (int z = -15; z < 15; z++) { pushMatrix(); translate(0,0,z); for (int i = 0; i >= -150; i--) {
         float inter = map(i, 0,-150, 0,1);
         float interX = map(i, 0,-150, 0,50);
         color c = lerpColor(c1,c2,inter);
         stroke(c);
         line(-10-interX, i, 10+interX, i);
      }
      popMatrix();
    }
}
 
void drawProjectors(float percent) {
    fill(100);
    box(30);
    if ((percent > 0.8) && (percent < 0.9)) { drawLight(); } pushMatrix(); translate(0,250,0); fill(100); box(30); if ((percent > 0.8) && (percent < 0.9)) {
      drawLight();
    }
    popMatrix();
 
}
 
void drawInnerSlides(float[][] slidePositions, float percent) {
  for (int i=0; i<slidePositions.length; i++) {
      float x = slidePositions[i][0];
      float y = slidePositions[i][1];
      float theta = slidePositions[i][2];
      drawInnerSlideFromThisPoint(x,y,theta,i,percent);
  }
} 
 
void drawOuterSlides(float[][] slidePositions, float percent) {
  for (int i=0; i<slidePositions.length; i++) { float x = slidePositions[i][0]; float y = slidePositions[i][1]; float theta = slidePositions[i][2]; drawOuterSlideFromThisPoint(x,y,theta,i,percent); } } void drawInnerSlideFromThisPoint(float x, float y, float theta, int i, float percent) { pushMatrix(); translate(x,y,0); rotateX(-PI/2); rotateY(theta + PI/2); rectMode(CENTER); noStroke(); if((i==7) && ((percent > 0.8) && (percent < 0.9))) { fill(255); } if((i==3) && ((percent > 0.8) && (percent < 0.9))) { noFill(); } else { fill(210); } //box(40); rect(0,0,60,60); if ((i > 3) && (i < 7)) { translate(-35,-30,1); image(img4, 10, 10); translate(0,0,-2); image(img4,10,10); } if ((i == 7) && (percent > 0.8)) {
    translate(-35,-30,-1);
    image(img4, 10, 10);
  }
  if ((i == 3) && (percent < 0.9)) { translate(-35,-30,1); image(img4, 10, 10); } popMatrix(); } void drawOuterSlideFromThisPoint(float x, float y, float theta, int i, float percent) { pushMatrix(); translate(x,y,0); rotateX(-PI/2); rotateY(theta + PI/2); rectMode(CENTER); noStroke(); if((i==1) && ((percent > 0.8) && (percent < 0.9))) { fill(255); } if((i==5) && ((percent > 0.8) && (percent < 0.9))) {
    noFill();
  } else {
    fill(210);
  }
  //box(40);
  rect(0,0,60,60);
 
  if ((i < 5) && (i > 1)) {
    translate(-35,-30,1);
    image(img, 10, 10);
    translate(0,0,-2);
    image(img, 10, 10);
  }
  if ((i == 1) && (percent > 0.8)) {
    translate(-35,-30,1);
    image(img, 10, 10);
  }
  if ((i == 5) && (percent < 0.9)) {
    translate(-35,-30,-1);
    image(img, 10, 10);
  }
 
  popMatrix();
}
 
//------------------------------------------------------------------
float function_PennerEaseOutBack (float x) {
  //functionName = "Penner's Ease-Out Back";
 
  float s = 1.70158;
  x = x-1.0;
  float y = (x*x*((s+1.0)*x + s) + 1.0);
  return y;
}
//Golan Levin's Pattern Master
 
//------------------------------------------------------------------
float function_PennerEaseOutElastic(float t) {
  //functionName = "Penner's EaseOut Elastic";
 
  if (t==0) return 0.0; 
  if (t==1) return 1.0;
  float p = 0.3f;
  float s = p/4;
 
  return (pow(2, -10*t) * sin( (t-s)*(2*PI)/p ) + 1);
}
//Golan Levin's Pattern Master
 
//===================================================
// Taken from https://github.com/golanlevin/Pattern_Master
float function_DoubleExponentialSigmoid (float x, float a) {
  // functionName = "Double-Exponential Sigmoid";
 
  float min_param_a = 0.0 + EPSILON;
  float max_param_a = 1.0 - EPSILON;
  a = constrain(a, min_param_a, max_param_a); 
  a = 1-a;
 
  float y = 0;
  if (x<=0.5) {
    y = (pow(2.0*x, 1.0/a))/2.0;
  } else {
    y = 1.0 - (pow(2.0*(1.0-x), 1.0/a))/2.0;
  }
  return y;
}