Skip to content

Commit

Permalink
Bring in latest updates from master
Browse files Browse the repository at this point in the history
  • Loading branch information
larryfenn committed Aug 22, 2022
2 parents 807061a + f94f93d commit adc7f0d
Show file tree
Hide file tree
Showing 13 changed files with 392 additions and 31 deletions.
100 changes: 100 additions & 0 deletions Spectrum/Color.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;

namespace Spectrum {
internal class Color {

public byte R;
public byte G;
public byte B;
public double H;
public double S;
public double V;

public Color(byte r, byte g, byte b) {
R = r;
G = g;
B = b;
double max = Math.Max(Math.Max(r / 255.0d, g / 255.0d), b / 255.0d);
double min = Math.Max(Math.Max(r / 255.0d, g / 255.0d), b / 255.0d);

double d = max - min;
double s = max == 0 ? 0 : d / max;
double v = max;
double h = 0;

if (max != min) {
if (r > g) {
if (r > b) {
h = (g - b) / d + (g < b ? 6 : 0);
} else {
h = (r - g) / d + 4;
}
} else {
if (g > b) {
h = (b - r) / d + 2;
} else {
h = (r - g) / d + 4;
}
}

h /= 6;
}
H = h;
S = s;
V = v;
}

public Color(double h, double s, double v) {
H = h;
S = s;
V = v;
double r = 0, g = 0, b = 0;

int i = (int)Math.Floor(h * 6);
double f = h * 6 - i;
double p = v * (1 - s);
double q = v * (1 - f * s);
double t = v * (1 - (1 - f) * s);

switch (i % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}

R = (byte)(255 * r);
G = (byte)(255 * g);
B = (byte)(255 * b);
}

public override string ToString() {
return $"0x{R:x2}{G:x2}{B:x2}";
}

public int ToInt() {
return 256*256*(int)R + 256*(int)G + (int)B;
}

private static byte ToByte(double x) {
return (byte)Math.Min(Math.Max(Math.Round(x), 0), 255);
}

public static Color BlendRGB(double alpha, Color a, Color b) {
return new Color(
ToByte((b.R - a.R) * alpha + a.R),
ToByte((b.G - a.G) * alpha + a.G),
ToByte((b.B - a.B) * alpha + a.B)
);
}
public static Color BlendHSV(double alpha, Color a, Color b) {
return new Color(
((b.H - a.H) * alpha + a.H),
((b.S - a.S) * alpha + a.S),
((b.V - a.V) * alpha + a.V)
);
}
}
}
4 changes: 2 additions & 2 deletions Spectrum/Converter/ColorConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ System.Globalization.CultureInfo culture
return null;
}
int rgb = (int)value;
Color color = new Color();
System.Windows.Media.Color color = new System.Windows.Media.Color();
color.R = (byte)(rgb >> 16);
color.G = (byte)(rgb >> 8);
color.B = (byte)rgb;
Expand All @@ -43,7 +43,7 @@ System.Globalization.CultureInfo culture
if (value == null) {
return null;
}
Color color = (Color)value;
System.Windows.Media.Color color = (System.Windows.Media.Color)value;
return (int)color.R << 16
| (int)color.G << 8
| (int)color.B;
Expand Down
17 changes: 17 additions & 0 deletions Spectrum/Operator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,28 @@ class Operator {
audio,
dome
));
this.visualizers.Add(new LEDDomeSplatVisualizer(
this.config,
audio,
dome
));
this.visualizers.Add(new LEDDomeQuaternionTestVisualizer(
this.config,
orientation,
dome
));
this.visualizers.Add(new LEDDomeQuaternionPaintbrushVisualizer(
this.config,
audio,
orientation,
dome
));
this.visualizers.Add(new LEDDomeQuaternionFocusVisualizer(
this.config,
audio,
orientation,
dome
));
this.visualizers.Add(new LEDDomeRaceVisualizer(
this.config,
audio,
Expand Down
4 changes: 4 additions & 0 deletions Spectrum/Spectrum.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,19 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Color.cs" />
<Compile Include="Converter\ColorConverter.cs" />
<Compile Include="Converter\TrueIfValueConverter.cs" />
<Compile Include="Converter\SpecificValuesConverter.cs" />
<Compile Include="Converter\FPSToBrushConverter.cs" />
<Compile Include="Converter\StringJoinConverter.cs" />
<Compile Include="OrientationInput.cs" />
<Compile Include="Visualizers\LEDDomeFullColorFlashDiagnosticVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeQuaternionFocusVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeQuaternionPaintbrushVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeQuaternionTestVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeRaceVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeSplatVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeRadialVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeSnakesVisualizer.cs" />
<Compile Include="Visualizers\LEDDomeTVStaticVisualizer.cs" />
Expand Down
68 changes: 68 additions & 0 deletions Spectrum/Visualizers/LEDDomeQuaternionFocusVisualizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Spectrum.Audio;
using Spectrum.Base;
using Spectrum.LEDs;
using System;
using System.Numerics;

namespace Spectrum.Visualizers {
class LEDDomeQuaternionFocusVisualizer : Visualizer {


private Configuration config;
private AudioInput audio;
private OrientationInput orientation;
private LEDDomeOutput dome;
private Vector3 spot = new Vector3(0, 1, 0);

public LEDDomeQuaternionFocusVisualizer(
Configuration config,
AudioInput audio,
OrientationInput orientation,
LEDDomeOutput dome
) {
this.config = config;
this.audio = audio;
this.orientation = orientation;
this.dome = dome;
this.dome.RegisterVisualizer(this);
}

public int Priority {
get {
return this.config.domeActiveVis == 6 ? 2 : 0;
}
}

public bool Enabled { get; set; }

public Input[] GetInputs() {
return new Input[] { this.orientation };
}

void Render() {
for (int i = 0; i < LEDDomeOutput.GetNumStruts(); i++) {
var leds = LEDDomeOutput.GetNumLEDs(i);
for (int j = 0; j < leds; j++) {
var p = StrutLayoutFactory.GetProjectedLEDPoint(i, j); // centered on (.5, .5), [0, 1] x [0, 1]
var x = 2 * p.Item1 - 1; // now centered on (0, 0) and with range [0, 1]
var y = 1 - 2 * p.Item2; // this is because in the original mapping x, y come "out of" the top left corner
float z = (float)Math.Sqrt(1 - x * x - y * y);
Vector3 pixelPoint = new Vector3((float)x, (float)y, z);
// Calibration assigns (0, 1, 0) to be 'forward'
// So we want the post-transformed pixel closest to (0, 1, 0)?
int color = 0;
if (Vector3.Distance(Vector3.Transform(pixelPoint, orientation.rotation), spot) < .25) {
color = 0xFFFFFF;
}

this.dome.SetPixel(i, j, color);
}
}
}
public void Visualize() {
this.Render();

this.dome.Flush();
}
}
}
69 changes: 69 additions & 0 deletions Spectrum/Visualizers/LEDDomeQuaternionPaintbrushVisualizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Spectrum.Audio;
using Spectrum.Base;
using Spectrum.LEDs;
using System;
using System.Numerics;

namespace Spectrum.Visualizers {
class LEDDomeQuaternionPaintbrushVisualizer : Visualizer {


private Configuration config;
private AudioInput audio;
private OrientationInput orientation;
private LEDDomeOutput dome;
private Vector3 spot = new Vector3(0, 1, 0);

public LEDDomeQuaternionPaintbrushVisualizer(
Configuration config,
AudioInput audio,
OrientationInput orientation,
LEDDomeOutput dome
) {
this.config = config;
this.audio = audio;
this.orientation = orientation;
this.dome = dome;
this.dome.RegisterVisualizer(this);
}

public int Priority {
get {
return this.config.domeActiveVis == 5 ? 2 : 0;
}
}

public bool Enabled { get; set; }

public Input[] GetInputs() {
return new Input[] { this.orientation };
}

void Render() {
for (int i = 0; i < LEDDomeOutput.GetNumStruts(); i++) {
var leds = LEDDomeOutput.GetNumLEDs(i);
for (int j = 0; j < leds; j++) {
var p = StrutLayoutFactory.GetProjectedLEDPoint(i, j); // centered on (.5, .5), [0, 1] x [0, 1]
var x = 2 * p.Item1 - 1; // now centered on (0, 0) and with range [0, 1]
var y = 1 - 2 * p.Item2; // this is because in the original mapping x, y come "out of" the top left corner
float z = (float)Math.Sqrt(1 - x * x - y * y);
Vector3 pixelPoint = new Vector3((float)x, (float)y, z);
// Calibration assigns (0, 1, 0) to be 'forward'
// So we want the post-transformed pixel closest to (0, 1, 0)?
Color color = new Color(0, 0, 0);
if(Vector3.Distance(Vector3.Transform(pixelPoint, orientation.rotation), spot) < .25) {
color = new Color((256 * (orientation.rotation.W + 1)) / 256d, 1, 1);
}
// todo : rework to use jan karls buffer
this.dome.SetPixel(i, j, color.ToInt());
}
}
}

public void Visualize() {
this.Render();

this.dome.Flush();
}
}
}
30 changes: 6 additions & 24 deletions Spectrum/Visualizers/LEDDomeQuaternionTestVisualizer.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using Spectrum.Audio;
using Spectrum.Base;
using Spectrum.Base;
using Spectrum.LEDs;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;

namespace Spectrum.Visualizers {
Expand All @@ -13,7 +9,6 @@ class LEDDomeQuaternionTestVisualizer : Visualizer{
private Configuration config;
private OrientationInput orientation;
private LEDDomeOutput dome;
private Vector4 spot = new Vector4(0, 1, 0, 0);

public LEDDomeQuaternionTestVisualizer(
Configuration config,
Expand All @@ -39,8 +34,6 @@ LEDDomeOutput dome
}

void Render() {
Vector4 newSpot = Vector4.Transform(spot, orientation.rotation);
Tuple<double, double> projectedSpot = Convert3D(newSpot);
for (int i = 0; i < LEDDomeOutput.GetNumStruts(); i++) {
var leds = LEDDomeOutput.GetNumLEDs(i);
for (int j = 0; j < leds; j++) {
Expand All @@ -52,30 +45,19 @@ LEDDomeOutput dome
Vector3 pixelPointQuat = Vector3.Transform(pixelPoint, orientation.rotation);
// Color maxes
int maxIndex = MaxBy(pixelPointQuat);
int color = 0;
Color color = new Color(0, 0, 0);
if(maxIndex == 0) {
color = 0xFF0000;
color = new Color(255, 0, 0);
} else if(maxIndex == 1) {
color = 0x00FF00;
color = new Color(0, 255, 0);
} else if(maxIndex == 2) {
color = 0x0000FF;
color = new Color(0, 0, 255);
}

this.dome.SetPixel(i, j, color);
this.dome.SetPixel(i, j, color.ToInt());
}
}
}

private static Tuple<double, double> Convert3D(Vector4 vector) {
// Lambert azimuthal equal-area projection
double x = Math.Sqrt(2 / (1 + vector.X)) * vector.Y * -1;
double y = Math.Sqrt(2 / (1 + vector.X)) * vector.Z;
// Dome coordinate space is [0, 1] x [0, 1] centered at (.5, .5)
x = (x + 1) / 2;
y = (y + 1) / 2;
return new Tuple<double, double>(x, y);
}

public void Visualize() {
this.Render();

Expand Down

0 comments on commit adc7f0d

Please sign in to comment.