From 58888c694c14bb9aec1bc4f0d6a8e01d0f9c1a51 Mon Sep 17 00:00:00 2001 From: Justin Rosenstein Date: Sun, 1 Dec 2013 18:48:21 -0800 Subject: [PATCH] Optimized gimbal -- now at 60fps --- JR.pde | 129 +++++++++++++++++++++++++++++++++++++++++++------ SugarCubes.pde | 6 +-- 2 files changed, 117 insertions(+), 18 deletions(-) diff --git a/JR.pde b/JR.pde index ba9498b..025d74f 100644 --- a/JR.pde +++ b/JR.pde @@ -2,12 +2,14 @@ color BLACK = #000000; class Gimbal extends SCPattern { + private final PerfTimer perf = new PerfTimer(); + private final boolean DEBUG_MANUAL_ABG = false; private final int MAXIMUM_BEATS_PER_REVOLUTION = 100; private boolean first_run = true; private final LXProjection projection; - private final BasicParameter beatsPerRevolutionParam = new BasicParameter("SLOW", 20./MAXIMUM_BEATS_PER_REVOLUTION); + private final BasicParameter beatsPerRevolutionParam = new BasicParameter("SLOW", 25./MAXIMUM_BEATS_PER_REVOLUTION); private final BasicParameter hueDeltaParam = new BasicParameter("HUED", 60./360); private final BasicParameter fadeFromCoreParam = new BasicParameter("FADE", 1); private final BasicParameter girthParam = new BasicParameter("GRTH", .18); @@ -82,34 +84,46 @@ class Gimbal extends SCPattern { for (LXVector c : projection) { //if (first_run) println(c.x + "," + c.y + "," + c.z); - rotate3d(c, a, 0, 0); - rotate3d(c, PI/4, PI/4, PI/4); + rotate3dA(c, a); + rotate3dPiOver4(c); color color1 = ring1.colorFor(c); - rotate3d(c, 0, b, 0); + rotate3dB(c, b); color color2 = ring2.colorFor(c); - rotate3d(c, 0, 0, g); + rotate3dG(c, g); color color3 = ring3.colorFor(c); colors[c.index] = specialBlend(color1, color2, color3); } - first_run = false; + first_run = false; } class Ring { float hue; float radius, girth; + float _multiplier; public Ring(float hue, float radius, float girth) { this.hue = hue; this.radius = radius; this.girth = girth; + this._multiplier = 100. / girth * fadeFromCoreParam.getValuef(); } public color colorFor(LXVector c) { + float xy_distance_to_circle = sqrt(c.x * c.x + c.y * c.y) - radius; + float z_distance_to_circle = c.z * ringExtendParam.getValuef(); + + float distance_to_circle + = sqrt(xy_distance_to_circle * xy_distance_to_circle + + z_distance_to_circle * z_distance_to_circle); + + return lx.hsb(this.hue, 100, 100. - distance_to_circle * _multiplier); + + /* PRE-OPTIMIZED IMPLEMENTATION float theta = atan2(c.y, c.x); float nearest_circle_x = cos(theta) * radius; float nearest_circle_y = sin(theta) * radius; @@ -122,13 +136,60 @@ class Gimbal extends SCPattern { float xy_distance = sqrt(c.x*c.x + c.y*c.y); return lx.hsb(this.hue, 100, (1 - distance_to_circle / girth * fadeFromCoreParam.getValuef()) * 100); + */ } - + } } +class PerfTimer { + + private final Map m = new TreeMap(); + private String current_phase = null; + private int current_phase_start_time = 0; + private int total_time = 0; + + public void start(String phase_name) { + if (current_phase != null) { + stop(); + } + current_phase = phase_name; + current_phase_start_time = millis(); + } + + public void stop() { + int current_time = millis(); + + assert(current_phase != null); + assert(current_phase_start_time != 0); + int time_ellapsed = current_time - current_phase_start_time; + m.put(current_phase, + (m.containsKey(current_phase) ? m.get(current_phase) : 0) + + time_ellapsed); + + current_phase = null; + current_phase_start_time = 0; + total_time += time_ellapsed; + } + + public void report() { + if (random(0, 60 * 4) < 1) { + println("~~~~~~~~~~~~~~~~~~"); + for (String phase_name : m.keySet()) { + print(phase_name); + for (int i = phase_name.length(); i < 30; ++i) { + print(" "); + } + println("" + (float) m.get(phase_name) / total_time); + } + } + } + +} + + @@ -215,7 +276,45 @@ class Zebra extends SCPattern { } +float HALF_OF_ONE_OVER_SQRT2_MINUS_1 = (1./sqrt(2) - 1) / 2; +float HALF_OF_ONE_OVER_SQRT2_PLUS_1 = (1./sqrt(2) + 1) / 2; +float SQRT2 = sqrt(2); + +/** Equivalent to rotate3d(c, a, 0, 0); */ +void rotate3dA(LXVector c, float a) { + float ox = c.x, oy = c.y; + float cosa = cos(a); + float sina = sin(a); + c.x = ox * cosa - oy * sina; + c.y = ox * sina + oy * cosa; +} +/** Equivalent to rotate3d(c, 0, b, 0); */ +void rotate3dB(LXVector c, float b) { + float ox = c.x, oz = c.z; + float cosb = cos(b); + float sinb = sin(b); + c.x = ox * cosb + oz * sinb; + c.z = oz * cosb - ox * sinb; +} +/** Equivalent to rotate3d(c, 0, 0, g); */ +void rotate3dG(LXVector c, float g) { + float oy = c.y, oz = c.z; + float cosg = cos(g); + float sing = sin(g); + c.y = oy * cosg - oz * sing; + c.z = oz * cosg + oy * sing; +} +/** Equivalent to rotate3d(c, PI/4, PI/4, PI/4); */ +void rotate3dPiOver4(LXVector c) { + float ox = c.x, oy = c.y, oz = c.z; + c.x = ox / 2 + oy * HALF_OF_ONE_OVER_SQRT2_MINUS_1 + oz * HALF_OF_ONE_OVER_SQRT2_PLUS_1; + c.y = ox / 2 + oy * HALF_OF_ONE_OVER_SQRT2_PLUS_1 + oz * HALF_OF_ONE_OVER_SQRT2_MINUS_1; + c.z = - ox / SQRT2 + oy / 2 + oz / 2; +} + void rotate3d(LXVector c, float a /* roll */, float b /* pitch */, float g /* yaw */) { + float ox = c.x, oy = c.y, oz = c.z; + float cosa = cos(a); float cosb = cos(b); float cosg = cos(g); @@ -232,11 +331,10 @@ void rotate3d(LXVector c, float a /* roll */, float b /* pitch */, float g /* ya float c1 = -sinb; float c2 = cosb*sing; float c3 = cosb*cosg; - - float[] cArray = { c.x, c.y, c.z }; - c.x = dotProduct(new float[] {a1, a2, a3}, cArray); - c.y = dotProduct(new float[] {b1, b2, b3}, cArray); - c.z = dotProduct(new float[] {c1, c2, c3}, cArray); + + c.x = ox * a1 + oy * a2 + oz * a3; + c.y = ox * b1 + oy * b2 + oz * b3; + c.z = ox * c1 + oy * c2 + oz * c3; } float dotProduct(float[] a, float[] b) { @@ -267,9 +365,10 @@ color specialBlend(color c1, color c2, color c3) { float b1 = brightness(c1); float b2 = brightness(c2); float b3 = brightness(c3); - float relative_b1 = b1 / (b1 + b2 + b3); - float relative_b2 = b2 / (b1 + b2 + b3); - float relative_b3 = b3 / (b1 + b2 + b3); + float b_denominator = b1 + b2 + b3; + float relative_b1 = b1 / b_denominator; + float relative_b2 = b2 / b_denominator; + float relative_b3 = b3 / b_denominator; return lx.hsb( (h1 * relative_b1 + h2 * relative_b1 + h3 * relative_b3) % 360, diff --git a/SugarCubes.pde b/SugarCubes.pde index 71f846e..ff85065 100644 --- a/SugarCubes.pde +++ b/SugarCubes.pde @@ -60,6 +60,9 @@ LXPattern[] patterns(GLucose glucose) { new Pong (glucose), new Worms(glucose), + // JR + new Gimbal(glucose), + // Alex G // Tim @@ -107,9 +110,6 @@ LXPattern[] patterns(GLucose glucose) { // Shaheen //new HelixPattern(glucose).setEligible(false), - //JR - new Gimbal(glucose), - // Sam new JazzRainbow(glucose), -- 2.34.1