Merge branch 'dev' of github.com:peter-slattery/Lumenarium into dev

This commit is contained in:
Peter Slattery 2021-04-08 06:49:37 -07:00
commit 572c69b05c
6 changed files with 202 additions and 23 deletions

View File

@ -1,24 +1,24 @@
lumenarium_animation_file; lumenarium_animation_file;
animation_name: "voice_command"; animation_name: "voice_anim";
layers_count: 1; layers_count: 1;
blocks_count: 1; blocks_count: 1;
playable_range:{ playable_range:{
min: 0; min: 0;
max: 360; max: 3600;
}; };
layers:{ layers:{
layer:{ layer:{
name: "Colors"; name: "[New Layer]";
blend: "Add"; blend: "Add";
}; };
}; };
blocks:{ blocks:{
block:{ block:{
frame_range:{ frame_range:{
min: 0; min: 1;
max: 360; max: 3599;
}; };
layer_index: 0; layer_index: 0;
animation_name: "Pattern_Leafy"; animation_name: "Pattern_VoicePattern";
}; };
}; };

View File

@ -202,6 +202,14 @@ typedef struct system_time
s32 Second; s32 Second;
} system_time; } system_time;
internal r64
SecondsElapsed(system_time Start, system_time End)
{
u64 N = End.NanosSinceEpoch - Start.NanosSinceEpoch;
r64 S = (r64)N * NanosToSeconds;
return S;
}
struct context struct context
{ {
gs_thread_context ThreadContext; gs_thread_context ThreadContext;

View File

@ -10,6 +10,10 @@
internal pixel internal pixel
V4ToRGBPixel(v4 C) V4ToRGBPixel(v4 C)
{ {
C.x = Clamp01(C.x);
C.y = Clamp01(C.y);
C.z = Clamp01(C.z);
pixel Result = {}; pixel Result = {};
Result.R = (u8)(C.x * 255); Result.R = (u8)(C.x * 255);
Result.G = (u8)(C.y * 255); Result.G = (u8)(C.y * 255);
@ -488,5 +492,142 @@ Pattern_BulbMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r3
} }
} }
internal v4
GenPatchyColor(v3 P, r32 Time, v4 C0, v4 C1, v4 C2)
{
r32 LedRange = 300.0f;
r32 ScaleFactor = 1.0f / LedRange;
v3 Pp = P + v3{150, 100, 0};
r32 ScaleA = 1;
r32 NoiseA = Noise3D(((Pp / 38) + v3{0, 0, Time}) * ScaleA);
NoiseA = PowR32(NoiseA, 3);
NoiseA = Smoothstep(NoiseA);
r32 ScaleBP = 2;
r32 ScaleB = 15;
r32 NoiseBP = Noise3D(((Pp / 13) + v3{ 0, Time * -0.33f, 0}) * ScaleBP);
NoiseBP = PowR32(NoiseBP, 3);
r32 NoiseB = Noise3D(((Pp / 75) + v3{Time * 0.5f, 0, 0}) * ScaleB);
NoiseB = PowR32(NoiseB, 3);
NoiseB = Smoothstep(NoiseB) * NoiseBP;
r32 ScaleC = 1.5;
r32 NoiseCP = Noise3D(((Pp / 132) + v3{Time * -0.33f, 0, 0}) * 0.5f);
r32 NoiseC = Noise3D(((Pp / 164) + v3{Time * 0.25f, 0, 0}) * ScaleC);
NoiseC = PowR32(NoiseC, 3);
NoiseC = Smoothstep(NoiseC) * NoiseCP;
v4 C = (C0 * NoiseA) + (C1 * NoiseB) + (C2 * NoiseC);
C /= (NoiseA + NoiseB + NoiseC);
return C;
}
internal r32
GenVerticalStrips(v3 P, r32 Time)
{
v2 Right = v2{1, 0};
v2 Pa = V2Normalize(v2{P.x, P.z});
r32 Angle = .5f + (.5f * V2Dot(Pa, Right));
r32 HOffset = 70.0f;
r32 O = 50.0f;
r32 C = 10.0f;
r32 X = Angle;
r32 Y = P.y;
r32 I = FloorR32(Y / C) * C;
I += (X * HOffset) + (Time * 25);
r32 V = FractR32(I / O);
V = 2.0f * (0.5f - Abs(V - 0.5f));
Assert(V >= 0 && V <= 1);
return V;
}
internal v4
GenVerticalLeaves(v3 P, r32 Time, v4 C0, v4 C1, v4 C2)
{
r32 A = GenVerticalStrips(P, Time * .25f);
r32 B = GenVerticalStrips(P * .3f, Time);
r32 C = GenVerticalStrips(P * .25f, Time * 2);
v4 R = (C0 * A) + (C1 * B) + (C2 * C);
R /= A + B + C;
return R;
}
internal r32
GenLiquidBands(v3 P, r32 Offset, r32 Time)
{
r32 Width = 30;
r32 VAcc = 0;
for (u32 i = 1; i < 3; i++)
{
v3 P0 = v3{P.x + (23.124f * i), 0, P.z - (-12.34f * i)};
r32 Y = (P.y - Offset);
r32 S = Fbm3D(P0 * .005f, Time) * 250;
S += ModR32((Time * 100) - (150 * i), 400);
r32 V = (Width - Abs(Y - S)) / Width;
V = Clamp01(V);
VAcc += V;
}
return VAcc;
}
internal r32
GenDotBands(v3 P, r32 Time)
{
r32 RowHeight = 25;
r32 DotRadius = 20;
r32 Y = P.y + 150;
s32 Row = (s32)FloorR32(Y / RowHeight);
r32 RowH = Abs(FractR32(Y / RowHeight));
r32 DotDistY = Max(0, .5f - RowH) * 2;
r32 Angle = (V2Dot(V2Normalize(v2{P.x, P.z}), v2{1,0}) * .5f) + .5f;
r32 DotDistX = Abs(ModR32(Angle, .2f));
r32 DotDist = SqrtR32(PowR32(DotDistX, 2) + PowR32(RowH, 2));
r32 B = (DotRadius - DotDist) / DotRadius;
B = Clamp01(DotDist);
return DotDistY;
}
internal void
Pattern_VoicePattern(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
Time = Time * BLState->PatternSpeed;
phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly);
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1});
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v3 P = Leds->Positions[LedIndex].xyz;
v4 C = {};
C += GenPatchyColor(P, Time, C0, C2, {});
//C = GenVerticalLeaves((P - Assembly.Center) + v3{0, 150, 0}, Time, C0, C1, C2);
r32 Bands = GenLiquidBands(P, -250, Time);
//C = V4Lerp(Bands, C * .5f, C1);
//C = WhiteV4 * GenDotBands(P - Assembly.Center, Time);
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
}
#define BLUMEN_PATTERNS_H #define BLUMEN_PATTERNS_H
#endif // BLUMEN_PATTERNS_H #endif // BLUMEN_PATTERNS_H

View File

@ -207,6 +207,8 @@ BlumenLumen_LoadPatterns(app_state* State)
Patterns_PushPattern(Patterns, Pattern_Rotary, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_Rotary, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_AllOnMask, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_AllOnMask, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_BulbMask, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_BulbMask, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_VoicePattern, PATTERN_MULTITHREADED);
} }
internal void internal void
@ -373,7 +375,7 @@ BlumenLumen_CustomInit(app_state* State, context Context)
BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context); BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context);
AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, ConstString("data/blumen_animations/anim_demo.foldanim")); AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, ConstString("data/blumen_animations/anim_demo.foldanim"));
BlumenLumen_SetPatternMode(BlumenPattern_Standard, 5, &State->AnimationSystem, BLState); BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, 5, &State->AnimationSystem, BLState);
#endif #endif
State->AnimationSystem.TimelineShouldAdvance = true; State->AnimationSystem.TimelineShouldAdvance = true;
@ -403,26 +405,17 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
u32 NameLen = CStringLength(Mic.AnimationFileName); u32 NameLen = CStringLength(Mic.AnimationFileName);
phrase_hue NewHue = PhraseHueMap_Get(BLState->PhraseHueMap, NameHash); phrase_hue NewHue = PhraseHueMap_Get(BLState->PhraseHueMap, NameHash);
if (NewHue.PhraseHash != 0) if (BLState->NextHotHue.Phrase.Length < NewHue.Phrase.Length)
{ {
if (BLState->PatternMode == BlumenPattern_Standard) BLState->NextHotHue = NewHue;
if (SecondsElapsed(BLState->TimePhraseReceptionBegan,
Context->SystemTime_Current) > PhrasePriorityMessageGroupingTime)
{ {
BLState->AssemblyColors[0] = NewHue; BLState->TimePhraseReceptionBegan = Context->SystemTime_Current;
BLState->AssemblyColors[1] = NewHue; BLState->InPhraseReceptionMode = true;
BLState->AssemblyColors[2] = NewHue;
} }
else BLState->TimeLastPhraseReceived = Context->SystemTime_Current;
{
u32 AssemblyIdx = BLState->LastAssemblyColorSet;
BLState->AssemblyColors[AssemblyIdx] = NewHue;
BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3;
}
BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, 5, &State->AnimationSystem, BLState);
BLState->TimeLastSetToVoiceMode = Context->SystemTime_Current;
BLState->LastHuePhrase = NewHue;
} }
BLState->ShouldUpdateLog = true;
}break; }break;
case PacketType_MotorState: case PacketType_MotorState:
@ -473,6 +466,35 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
} }
} }
if (BLState->InPhraseReceptionMode)
{
r32 SecondsSincePhraseBegan = SecondsElapsed(BLState->TimePhraseReceptionBegan, Context->SystemTime_Current);
if (SecondsSincePhraseBegan > PhrasePriorityMessageGroupingTime)
{
// if we are in standard color mode, shift all flowers to the new color
// otherwise, only shift the next flower in the sequence to the new color
phrase_hue NewHue = BLState->NextHotHue;
if (BLState->PatternMode == BlumenPattern_Standard)
{
BLState->AssemblyColors[0] = NewHue;
BLState->AssemblyColors[1] = NewHue;
BLState->AssemblyColors[2] = NewHue;
}
else
{
u32 AssemblyIdx = BLState->LastAssemblyColorSet;
BLState->AssemblyColors[AssemblyIdx] = NewHue;
BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3;
}
BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, 5, &State->AnimationSystem, BLState);
BLState->TimeLastSetToVoiceMode = Context->SystemTime_Current;
BLState->LastHuePhrase = NewHue;
BLState->ShouldUpdateLog = true;
BLState->InPhraseReceptionMode = false;
}
}
// Update next frames Hues // Update next frames Hues
r32 AnimTime = AnimationSystem_GetCurrentTime(State->AnimationSystem); r32 AnimTime = AnimationSystem_GetCurrentTime(State->AnimationSystem);
AnimTime = (r32)Context->TotalTime; AnimTime = (r32)Context->TotalTime;

View File

@ -175,6 +175,12 @@ struct blumen_lumen_state
animation_handle_array ModeAnimations[BlumenPattern_Count]; animation_handle_array ModeAnimations[BlumenPattern_Count];
phrase_hue_map PhraseHueMap; phrase_hue_map PhraseHueMap;
bool InPhraseReceptionMode;
phrase_hue NextHotHue;
system_time TimePhraseReceptionBegan;
system_time TimeLastPhraseReceived;
system_time TimeLastSetToVoiceMode; system_time TimeLastSetToVoiceMode;
phrase_hue LastHuePhrase; phrase_hue LastHuePhrase;

View File

@ -99,6 +99,8 @@ r32 FullBrightnessPercent = 1.0f;
// 2 is 2x as fast. // 2 is 2x as fast.
r32 GlobalAnimSpeed = 1.0f; r32 GlobalAnimSpeed = 1.0f;
r64 PhrasePriorityMessageGroupingTime = 1.0f;
// How often should Lumenarium send its status to the python server? // How often should Lumenarium send its status to the python server?
// //
#define STATUS_PACKET_FREQ_SECONDS 10 // in seconds #define STATUS_PACKET_FREQ_SECONDS 10 // in seconds