on frames with overlapping blocks, the blocks are blended together
This commit is contained in:
parent
a6c8d0c955
commit
5e6ac25490
|
@ -88,8 +88,12 @@ struct animation_array
|
||||||
struct animation_layer_frame
|
struct animation_layer_frame
|
||||||
{
|
{
|
||||||
animation_block Hot;
|
animation_block Hot;
|
||||||
|
bool HasHot;
|
||||||
|
|
||||||
animation_block NextHot;
|
animation_block NextHot;
|
||||||
bool HasNextHot;
|
bool HasNextHot;
|
||||||
|
|
||||||
|
r32 HotOpacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(pjs): This is an evaluated frame - across all layers in an
|
// NOTE(pjs): This is an evaluated frame - across all layers in an
|
||||||
|
@ -97,9 +101,7 @@ struct animation_layer_frame
|
||||||
struct animation_frame
|
struct animation_frame
|
||||||
{
|
{
|
||||||
animation_layer_frame* Layers;
|
animation_layer_frame* Layers;
|
||||||
b8* LayersFilled;
|
|
||||||
u32 LayersCount;
|
u32 LayersCount;
|
||||||
u32 LayersCountMax;
|
|
||||||
|
|
||||||
// NOTE(pjs): These are all parallel arrays of equal length
|
// NOTE(pjs): These are all parallel arrays of equal length
|
||||||
animation_block* Blocks;
|
animation_block* Blocks;
|
||||||
|
@ -438,6 +440,10 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_aren
|
||||||
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
||||||
|
|
||||||
animation_frame Result = {0};
|
animation_frame Result = {0};
|
||||||
|
Result.LayersCount = ActiveAnim->Layers.Count;
|
||||||
|
Result.Layers = PushArray(Arena, animation_layer_frame, Result.LayersCount);
|
||||||
|
ZeroArray(Result.Layers, animation_frame, Result.LayersCount);
|
||||||
|
|
||||||
Result.BlocksCountMax = ActiveAnim->Layers.Count;
|
Result.BlocksCountMax = ActiveAnim->Layers.Count;
|
||||||
Result.Blocks = PushArray(Arena, animation_block, Result.BlocksCountMax);
|
Result.Blocks = PushArray(Arena, animation_block, Result.BlocksCountMax);
|
||||||
Result.BlocksFilled = PushArray(Arena, b8, Result.BlocksCountMax);
|
Result.BlocksFilled = PushArray(Arena, b8, Result.BlocksCountMax);
|
||||||
|
@ -449,6 +455,39 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, gs_memory_aren
|
||||||
|
|
||||||
if (FrameIsInRange(Block.Range, System->CurrentFrame))
|
if (FrameIsInRange(Block.Range, System->CurrentFrame))
|
||||||
{
|
{
|
||||||
|
animation_layer_frame* Layer = Result.Layers + Block.Layer;
|
||||||
|
if (Layer->HasHot)
|
||||||
|
{
|
||||||
|
// NOTE(pjs): With current implementation, we don't allow
|
||||||
|
// animations to hvae more than 2 concurrent blocks in the
|
||||||
|
// timeline
|
||||||
|
Assert(!Layer->HasNextHot);
|
||||||
|
|
||||||
|
// NOTE(pjs): Make sure that Hot comes before NextHot
|
||||||
|
if (Layer->Hot.Range.Min < Block.Range.Min)
|
||||||
|
{
|
||||||
|
Layer->NextHot = Block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Layer->NextHot = Layer->Hot;
|
||||||
|
Layer->Hot = Block;
|
||||||
|
}
|
||||||
|
Layer->HasNextHot = true;
|
||||||
|
|
||||||
|
frame_range BlendRange = {};
|
||||||
|
BlendRange.Min = Layer->NextHot.Range.Min;
|
||||||
|
BlendRange.Max = Layer->Hot.Range.Max;
|
||||||
|
Layer->HotOpacity = 1.0f - FrameToPercentRange(System->CurrentFrame, BlendRange);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Layer->Hot = Block;
|
||||||
|
Layer->HotOpacity = 1.0f;
|
||||||
|
Layer->HasHot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(pjs): Get rid of these fields, they're redundant now
|
||||||
Result.BlocksFilled[Block.Layer] = true;
|
Result.BlocksFilled[Block.Layer] = true;
|
||||||
Result.Blocks[Block.Layer] = Block;
|
Result.Blocks[Block.Layer] = Block;
|
||||||
Result.BlocksCount++;
|
Result.BlocksCount++;
|
||||||
|
|
|
@ -11,6 +11,18 @@ LedBlend_Overwrite(pixel PixelA, pixel PixelB)
|
||||||
return PixelB;
|
return PixelB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal pixel
|
||||||
|
LedBlend_Overwrite(pixel PixelA, pixel PixelB, r32 Opacity)
|
||||||
|
{
|
||||||
|
pixel Result = {};
|
||||||
|
|
||||||
|
r32 BOpacity = 1.0f - Opacity;
|
||||||
|
Result.R = (u8)((PixelA.R * Opacity) + (PixelB.R * BOpacity));
|
||||||
|
Result.G = (u8)((PixelA.G * Opacity) + (PixelB.G * BOpacity));
|
||||||
|
Result.B = (u8)((PixelA.B * Opacity) + (PixelB.B * BOpacity));
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
internal pixel
|
internal pixel
|
||||||
LedBlend_Add(pixel PixelA, pixel PixelB)
|
LedBlend_Add(pixel PixelA, pixel PixelB)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +80,18 @@ LedBlend_GetProc(blend_mode BlendMode)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, assembly Assembly, animation_pattern* Patterns, gs_memory_arena* Transient)
|
||||||
|
{
|
||||||
|
u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
|
||||||
|
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
|
||||||
|
|
||||||
|
// :AnimProcHandle
|
||||||
|
u32 AnimationProcIndex = Block.AnimationProcHandle - 1;
|
||||||
|
animation_proc* AnimationProc = Patterns[AnimationProcIndex].Proc;
|
||||||
|
AnimationProc(Buffer, Assembly, SecondsIntoBlock, Transient);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies,
|
AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies,
|
||||||
led_system* LedSystem,
|
led_system* LedSystem,
|
||||||
|
@ -80,7 +104,15 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
|
||||||
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
||||||
animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(System, Transient);
|
animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(System, Transient);
|
||||||
|
|
||||||
led_buffer* LayerLedBuffers = PushArray(Transient, led_buffer, CurrFrame.BlocksCountMax);
|
// NOTE(pjs): This mirrors animation_layer_frame to account
|
||||||
|
// for overlapping
|
||||||
|
struct layer_led_buffer
|
||||||
|
{
|
||||||
|
led_buffer HotBuffer;
|
||||||
|
led_buffer NextHotBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_led_buffer* LayerBuffers = PushArray(Transient, layer_led_buffer, CurrFrame.LayersCount);
|
||||||
|
|
||||||
for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++)
|
for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++)
|
||||||
{
|
{
|
||||||
|
@ -88,32 +120,61 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
|
||||||
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex);
|
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex);
|
||||||
|
|
||||||
// Create the LayerLEDBuffers
|
// Create the LayerLEDBuffers
|
||||||
for (u32 Layer = 0; Layer < CurrFrame.BlocksCountMax; Layer++)
|
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||||
{
|
{
|
||||||
led_buffer TempBuffer = {};
|
layer_led_buffer TempBuffer = {};
|
||||||
TempBuffer.LedCount = AssemblyLedBuffer->LedCount;
|
if (CurrFrame.Layers[Layer].HasHot)
|
||||||
TempBuffer.Positions = AssemblyLedBuffer->Positions;
|
{
|
||||||
TempBuffer.Colors = PushArray(Transient, pixel, TempBuffer.LedCount);
|
TempBuffer.HotBuffer.LedCount = AssemblyLedBuffer->LedCount;
|
||||||
LedBuffer_ClearToBlack(&TempBuffer);
|
TempBuffer.HotBuffer.Positions = AssemblyLedBuffer->Positions;
|
||||||
|
TempBuffer.HotBuffer.Colors = PushArray(Transient, pixel, TempBuffer.HotBuffer.LedCount);
|
||||||
|
LedBuffer_ClearToBlack(&TempBuffer.HotBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
LayerLedBuffers[Layer] = TempBuffer;
|
if (CurrFrame.Layers[Layer].HasNextHot)
|
||||||
|
{
|
||||||
|
TempBuffer.NextHotBuffer.LedCount = AssemblyLedBuffer->LedCount;
|
||||||
|
TempBuffer.NextHotBuffer.Positions = AssemblyLedBuffer->Positions;
|
||||||
|
TempBuffer.NextHotBuffer.Colors = PushArray(Transient, pixel, TempBuffer.HotBuffer.LedCount);
|
||||||
|
LedBuffer_ClearToBlack(&TempBuffer.NextHotBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerBuffers[Layer] = TempBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Each layer's block to the appropriate temp buffer
|
// Render Each layer's block to the appropriate temp buffer
|
||||||
for (u32 Layer = 0; Layer < CurrFrame.BlocksCountMax; Layer++)
|
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||||
{
|
{
|
||||||
led_buffer TempBuffer = LayerLedBuffers[Layer];
|
animation_layer_frame LayerFrame = CurrFrame.Layers[Layer];
|
||||||
|
if (LayerFrame.HasHot)
|
||||||
|
{
|
||||||
|
led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer;
|
||||||
|
animation_block Block = LayerFrame.Hot;
|
||||||
|
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient);
|
||||||
|
}
|
||||||
|
|
||||||
if (!CurrFrame.BlocksFilled[Layer]) { continue; }
|
if (LayerFrame.HasNextHot)
|
||||||
animation_block Block = CurrFrame.Blocks[Layer];
|
{
|
||||||
|
led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer;
|
||||||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
animation_block Block = LayerFrame.NextHot;
|
||||||
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
|
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient);
|
||||||
|
}
|
||||||
// :AnimProcHandle
|
}
|
||||||
u32 AnimationProcIndex = Block.AnimationProcHandle - 1;
|
|
||||||
animation_proc* AnimationProc = Patterns[AnimationProcIndex].Proc;
|
// Blend together any layers that have a hot and next hot buffer
|
||||||
AnimationProc(&TempBuffer, *Assembly, SecondsIntoBlock, Transient);
|
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||||
|
{
|
||||||
|
animation_layer_frame LayerFrame = CurrFrame.Layers[Layer];
|
||||||
|
layer_led_buffer LayerBuffer = LayerBuffers[Layer];
|
||||||
|
if (LayerFrame.HasNextHot)
|
||||||
|
{
|
||||||
|
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
||||||
|
{
|
||||||
|
pixel A = LayerBuffer.HotBuffer.Colors[LED];
|
||||||
|
pixel B = LayerBuffer.NextHotBuffer.Colors[LED];
|
||||||
|
LayerBuffer.HotBuffer.Colors[LED] = LedBlend_Overwrite(A, B, LayerFrame.HotOpacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consolidate Temp Buffers
|
// Consolidate Temp Buffers
|
||||||
|
@ -127,7 +188,7 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
|
||||||
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
||||||
{
|
{
|
||||||
pixel A = AssemblyLedBuffer->Colors[LED];
|
pixel A = AssemblyLedBuffer->Colors[LED];
|
||||||
pixel B = LayerLedBuffers[Layer].Colors[LED];
|
pixel B = LayerBuffers[Layer].HotBuffer.Colors[LED];
|
||||||
AssemblyLedBuffer->Colors[LED] = Blend(A, B);
|
AssemblyLedBuffer->Colors[LED] = Blend(A, B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,17 @@ TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||||
|
{
|
||||||
|
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||||
|
{
|
||||||
|
Leds->Colors[LedIndex].R = 0;
|
||||||
|
Leds->Colors[LedIndex].B = 255;
|
||||||
|
Leds->Colors[LedIndex].G = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// END TEMPORARY PATTERNS
|
// END TEMPORARY PATTERNS
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -210,11 +221,12 @@ EndCurrentOperationMode(app_state* State)
|
||||||
DeactivateCurrentOperationMode(&State->Modes);
|
DeactivateCurrentOperationMode(&State->Modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GlobalAnimationPatternsCount = 3;
|
s32 GlobalAnimationPatternsCount = 4;
|
||||||
animation_pattern GlobalAnimationPatterns[] = {
|
animation_pattern GlobalAnimationPatterns[] = {
|
||||||
{ "Test Pattern One", 16, TestPatternOne },
|
{ "Test Pattern One", 16, TestPatternOne },
|
||||||
{ "Test Pattern Two", 16, TestPatternTwo },
|
{ "Test Pattern Two", 16, TestPatternTwo },
|
||||||
{ "Test Pattern Three", 18, TestPatternThree },
|
{ "Test Pattern Three", 18, TestPatternThree },
|
||||||
|
{ "Pattern_AllGreen", 16, Pattern_AllGreen },
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "editor/panels/foldhaus_panel_types.h"
|
#include "editor/panels/foldhaus_panel_types.h"
|
||||||
|
|
Loading…
Reference in New Issue