Implemented the structure for different layers to have blend modes.
We now copy the led buffer for each assembly once per layer that has an active animation in it. The animations edit these temporary buffers, which are then blended together after all layers have created buffers, for each assembly.
This commit is contained in:
parent
f1936a016c
commit
d5309819e6
|
@ -5,7 +5,7 @@
|
|||
//
|
||||
#ifndef FOLDHAUS_ANIMATION
|
||||
|
||||
#define ANIMATION_PROC(name) void name(assembly* Assembly, r32 Time)
|
||||
#define ANIMATION_PROC(name) void name(assembly_led_buffer* Assembly, r32 Time)
|
||||
typedef ANIMATION_PROC(animation_proc);
|
||||
|
||||
struct frame_range
|
||||
|
@ -21,9 +21,18 @@ struct animation_block
|
|||
u32 Layer;
|
||||
};
|
||||
|
||||
enum blend_mode
|
||||
{
|
||||
BlendMode_Overwrite,
|
||||
BlendMode_Add,
|
||||
BlendMode_Multiply,
|
||||
BlendMode_Count,
|
||||
};
|
||||
|
||||
struct anim_layer
|
||||
{
|
||||
string Name;
|
||||
blend_mode BlendMode;
|
||||
};
|
||||
|
||||
#define ANIMATION_SYSTEM_LAYERS_MAX 128
|
||||
|
@ -124,7 +133,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim
|
|||
|
||||
// Layers
|
||||
internal u32
|
||||
AddLayer (string Name, animation_system* AnimationSystem)
|
||||
AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite)
|
||||
{
|
||||
// TODO(Peter): If this assert fires its time to make the layer buffer system
|
||||
// resizable.
|
||||
|
@ -136,6 +145,7 @@ AddLayer (string Name, animation_system* AnimationSystem)
|
|||
*NewLayer = {0};
|
||||
NewLayer->Name = MakeString(PushArray(&AnimationSystem->Storage, char, Name.Length), Name.Length);
|
||||
CopyStringTo(Name, &NewLayer->Name);
|
||||
NewLayer->BlendMode = BlendMode;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
State->Transient = {};
|
||||
State->Transient.FindAddressRule = FindAddress_InLastBufferOnly;
|
||||
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
|
||||
|
@ -192,9 +193,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
|
||||
State->AnimationSystem.LayersMax = 32;
|
||||
State->AnimationSystem.Layers = PushArray(&State->Permanent, anim_layer, State->AnimationSystem.LayersMax);
|
||||
AddLayer(MakeStringLiteral("Base Layer"), &State->AnimationSystem);
|
||||
AddLayer(MakeStringLiteral("Color Layer"), &State->AnimationSystem);
|
||||
AddLayer(MakeStringLiteral("Sparkles"), &State->AnimationSystem);
|
||||
AddLayer(MakeStringLiteral("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite);
|
||||
AddLayer(MakeStringLiteral("Color Layer"), &State->AnimationSystem, BlendMode_Multiply);
|
||||
AddLayer(MakeStringLiteral("Sparkles"), &State->AnimationSystem, BlendMode_Add);
|
||||
} // End Animation Playground
|
||||
|
||||
|
||||
|
@ -296,8 +297,8 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena)
|
|||
LEDIdx < LEDUniverseRange.RangeOnePastLast;
|
||||
LEDIdx++)
|
||||
{
|
||||
led LED = Assembly.LEDs[LEDIdx];
|
||||
pixel Color = Assembly.Colors[LED.Index];
|
||||
led LED = Assembly.LEDBuffer.LEDs[LEDIdx];
|
||||
pixel Color = Assembly.LEDBuffer.Colors[LED.Index];
|
||||
|
||||
|
||||
DestChannel[0] = Color.R;
|
||||
|
@ -356,6 +357,103 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
CurrentBlocks[Block.Layer] = Block;
|
||||
}
|
||||
|
||||
#if 1
|
||||
assembly_led_buffer* LayerLEDBuffers = PushArray(&State->Transient, assembly_led_buffer, CurrentBlocksMax);
|
||||
|
||||
for (u32 AssemblyIndex = 0; AssemblyIndex < State->ActiveAssemblyIndecies.Used; AssemblyIndex++)
|
||||
{
|
||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(AssemblyIndex);
|
||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
||||
|
||||
arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient);
|
||||
|
||||
for (u32 Layer = 0; Layer < CurrentBlocksMax; Layer++)
|
||||
{
|
||||
if (!CurrentBlocksFilled[Layer]) { continue; }
|
||||
animation_block Block = CurrentBlocks[Layer];
|
||||
|
||||
// Prep Temp Buffer
|
||||
LayerLEDBuffers[Layer] = Assembly->LEDBuffer;
|
||||
LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, Assembly->LEDBuffer.LEDCount);
|
||||
|
||||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
||||
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||
// TODO(Peter): Temporary
|
||||
switch(Block.AnimationProcHandle)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
TestPatternOne(&LayerLEDBuffers[Layer], SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
TestPatternTwo(&LayerLEDBuffers[Layer], SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
TestPatternThree(&LayerLEDBuffers[Layer], SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
// NOTE(Peter): Zero is invalid
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Temp Buffers
|
||||
// We do this in reverse order so that they go from top to bottom
|
||||
for (u32 Layer = 0; Layer < CurrentBlocksMax; Layer++)
|
||||
{
|
||||
if (!CurrentBlocksFilled[Layer]) { continue; }
|
||||
|
||||
switch (State->AnimationSystem.Layers[Layer].BlendMode)
|
||||
{
|
||||
case BlendMode_Overwrite:
|
||||
{
|
||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
||||
{
|
||||
Assembly->LEDBuffer.Colors[LED] = LayerLEDBuffers[Layer].Colors[LED];
|
||||
}
|
||||
}break;
|
||||
|
||||
case BlendMode_Add:
|
||||
{
|
||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
||||
{
|
||||
u32 R = (u32)Assembly->LEDBuffer.Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R;
|
||||
u32 G = (u32)Assembly->LEDBuffer.Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G;
|
||||
u32 B = (u32)Assembly->LEDBuffer.Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B;
|
||||
|
||||
Assembly->LEDBuffer.Colors[LED].R = (u8)GSMin(R, (u32)255);
|
||||
Assembly->LEDBuffer.Colors[LED].G = (u8)GSMin(G, (u32)255);
|
||||
Assembly->LEDBuffer.Colors[LED].B = (u8)GSMin(B, (u32)255);
|
||||
}
|
||||
}break;
|
||||
|
||||
case BlendMode_Multiply:
|
||||
{
|
||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
||||
{
|
||||
r32 DR = (r32)Assembly->LEDBuffer.Colors[LED].R / 255.f;
|
||||
r32 DG = (r32)Assembly->LEDBuffer.Colors[LED].G / 255.f;
|
||||
r32 DB = (r32)Assembly->LEDBuffer.Colors[LED].B / 255.f;
|
||||
|
||||
r32 SR = (r32)LayerLEDBuffers[Layer].Colors[LED].R / 255.f;
|
||||
r32 SG = (r32)LayerLEDBuffers[Layer].Colors[LED].G / 255.f;
|
||||
r32 SB = (r32)LayerLEDBuffers[Layer].Colors[LED].B / 255.f;
|
||||
|
||||
Assembly->LEDBuffer.Colors[LED].R = (u8)((DR * SR) * 255.f);
|
||||
Assembly->LEDBuffer.Colors[LED].G = (u8)((DG * SG) * 255.f);
|
||||
Assembly->LEDBuffer.Colors[LED].B = (u8)((DB * SB) * 255.f);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
ClearArenaToSnapshot(&State->Transient, ResetAssemblyMemorySnapshot);
|
||||
}
|
||||
#else
|
||||
for (s32 Layer = CurrentBlocksMax - 1; Layer >= 0; Layer--)
|
||||
{
|
||||
if (!CurrentBlocksFilled[Layer]) { continue; }
|
||||
|
@ -365,6 +463,11 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j);
|
||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
||||
|
||||
// TEmporary
|
||||
assembly_led_buffer TempBuffer = Assembly->LEDBuffer;
|
||||
TempBuffer.Colors = PushArray(&State->Transient, pixel, TempBuffer.LEDCount);
|
||||
GSZeroArray(TempBuffer.Colors, pixel, TempBuffer.LEDCount);
|
||||
|
||||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
||||
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||
// TODO(Peter): Temporary
|
||||
|
@ -372,25 +475,32 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
{
|
||||
case 1:
|
||||
{
|
||||
TestPatternOne(Assembly, SecondsIntoBlock);
|
||||
TestPatternOne(&TempBuffer, SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
TestPatternTwo(Assembly, SecondsIntoBlock);
|
||||
TestPatternTwo(&TempBuffer, SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
TestPatternThree(Assembly, SecondsIntoBlock);
|
||||
TestPatternThree(&TempBuffer, SecondsIntoBlock);
|
||||
}break;
|
||||
|
||||
// NOTE(Peter): Zero is invalid
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
// Temporary
|
||||
for (u32 i = 0; i < TempBuffer.LEDCount; i++)
|
||||
{
|
||||
Assembly->LEDBuffer.Colors[i] = TempBuffer.Colors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
s32 HeaderSize = State->NetworkProtocolHeaderSize;
|
||||
dmx_buffer_list* DMXBuffers = 0;
|
||||
|
|
|
@ -96,19 +96,28 @@ internal void OpenColorPicker(app_state* State, v4* Address);
|
|||
|
||||
// BEGIN TEMPORARY PATTERNS
|
||||
internal void
|
||||
TestPatternOne(assembly* Assembly, r32 Time)
|
||||
TestPatternOne(assembly_led_buffer* Assembly, r32 Time)
|
||||
{
|
||||
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
|
||||
{
|
||||
led LED = Assembly->LEDs[LEDIdx];
|
||||
if (LED.Position.x < 0)
|
||||
{
|
||||
Assembly->Colors[LED.Index].R = 255;
|
||||
Assembly->Colors[LED.Index].B = 255;
|
||||
Assembly->Colors[LED.Index].G = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assembly->Colors[LED.Index].R = 0;
|
||||
Assembly->Colors[LED.Index].B = 0;
|
||||
Assembly->Colors[LED.Index].G = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
TestPatternTwo(assembly* Assembly, r32 Time)
|
||||
TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
|
||||
{
|
||||
r32 PeriodicTime = (Time / PI) * 2;
|
||||
|
||||
|
@ -162,7 +171,7 @@ TestPatternTwo(assembly* Assembly, r32 Time)
|
|||
}
|
||||
|
||||
internal void
|
||||
TestPatternThree(assembly* Assembly, r32 Time)
|
||||
TestPatternThree(assembly_led_buffer* Assembly, r32 Time)
|
||||
{
|
||||
v4 GreenCenter = v4{0, 0, 150, 1};
|
||||
r32 GreenRadius = GSAbs(GSSin(Time)) * 200;
|
||||
|
|
|
@ -21,9 +21,9 @@ ConstructAssemblyFromDefinition (assembly_definition Definition,
|
|||
// NOTE(Peter): Setting this to zero so we can check at the end of the loop that creates leds
|
||||
// and make sure we created to correct number. By the time this function returns it should be
|
||||
// the case that: (Assembly.LEDCount == Definition.TotalLEDCount)
|
||||
Assembly.LEDCount = 0;
|
||||
Assembly.Colors = PushArray(&Assembly.Arena, pixel, Definition.TotalLEDCount);
|
||||
Assembly.LEDs = PushArray(&Assembly.Arena, led, Definition.TotalLEDCount);
|
||||
Assembly.LEDBuffer.LEDCount = 0;
|
||||
Assembly.LEDBuffer.Colors = PushArray(&Assembly.Arena, pixel, Definition.TotalLEDCount);
|
||||
Assembly.LEDBuffer.LEDs = PushArray(&Assembly.Arena, led, Definition.TotalLEDCount);
|
||||
Assembly.LEDUniverseMapCount = Definition.LEDStripCount;
|
||||
Assembly.LEDUniverseMap = PushArray(&Assembly.Arena, leds_in_universe_range, Definition.LEDStripCount);
|
||||
|
||||
|
@ -34,8 +34,8 @@ ConstructAssemblyFromDefinition (assembly_definition Definition,
|
|||
|
||||
leds_in_universe_range* LEDUniverseRange = Assembly.LEDUniverseMap + StripIdx;
|
||||
LEDUniverseRange->Universe = StripDef.StartUniverse;
|
||||
LEDUniverseRange->RangeStart = Assembly.LEDCount;
|
||||
LEDUniverseRange->RangeOnePastLast = Assembly.LEDCount + StripDef.LEDsPerStrip;
|
||||
LEDUniverseRange->RangeStart = Assembly.LEDBuffer.LEDCount;
|
||||
LEDUniverseRange->RangeOnePastLast = Assembly.LEDBuffer.LEDCount + StripDef.LEDsPerStrip;
|
||||
|
||||
// NOTE(Peter): this should be a switch on the type, but we only have one for
|
||||
// now. The assert is to remind you to create more cases when necessary
|
||||
|
@ -45,19 +45,19 @@ ConstructAssemblyFromDefinition (assembly_definition Definition,
|
|||
v4 WS_StripEnd = RootPosition + V4(StripDef.InterpolatePositionEnd * Scale, 1);
|
||||
s32 LEDsInStripCount = StripDef.LEDsPerStrip;
|
||||
|
||||
Assert(Assembly.LEDCount + LEDsInStripCount <= Definition.TotalLEDCount);
|
||||
Assert(Assembly.LEDBuffer.LEDCount + LEDsInStripCount <= Definition.TotalLEDCount);
|
||||
|
||||
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount;
|
||||
for (s32 Step = 0; Step < LEDsInStripCount; Step++)
|
||||
{
|
||||
s32 LEDIndex = Assembly.LEDCount++;
|
||||
Assembly.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
|
||||
Assembly.LEDs[LEDIndex].Index = LEDIndex;
|
||||
s32 LEDIndex = Assembly.LEDBuffer.LEDCount++;
|
||||
Assembly.LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
|
||||
Assembly.LEDBuffer.LEDs[LEDIndex].Index = LEDIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(Peter): Did we create the correct number of LEDs?
|
||||
Assert(Assembly.LEDCount == Definition.TotalLEDCount);
|
||||
Assert(Assembly.LEDBuffer.LEDCount == Definition.TotalLEDCount);
|
||||
return Assembly;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ LoadAssembly (app_state* State, context Context, char* Path)
|
|||
gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly);
|
||||
|
||||
State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
|
||||
State->TotalLEDsCount += NewAssembly.LEDCount;
|
||||
State->TotalLEDsCount += NewAssembly.LEDBuffer.LEDCount;
|
||||
|
||||
Context.PlatformFree(AssemblyFile.Base, AssemblyFile.Size);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ internal void
|
|||
UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context)
|
||||
{
|
||||
assembly* Assembly = State->AssemblyList.GetElementAtIndex(AssemblyIndex);
|
||||
State->TotalLEDsCount -= Assembly->LEDCount;
|
||||
State->TotalLEDsCount -= Assembly->LEDBuffer.LEDCount;
|
||||
FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree);
|
||||
|
||||
State->AssemblyList.FreeElementAtIndex(AssemblyIndex);
|
||||
|
|
|
@ -33,6 +33,13 @@ struct leds_in_universe_range
|
|||
s32 Universe;
|
||||
};
|
||||
|
||||
struct assembly_led_buffer
|
||||
{
|
||||
u32 LEDCount;
|
||||
pixel* Colors;
|
||||
led* LEDs;
|
||||
};
|
||||
|
||||
struct assembly
|
||||
{
|
||||
memory_arena Arena;
|
||||
|
@ -40,9 +47,13 @@ struct assembly
|
|||
string Name;
|
||||
string FilePath;
|
||||
|
||||
assembly_led_buffer LEDBuffer;
|
||||
|
||||
#if 0
|
||||
u32 LEDCount;
|
||||
pixel* Colors;
|
||||
led* LEDs;
|
||||
#endif
|
||||
|
||||
u32 LEDUniverseMapCount;
|
||||
leds_in_universe_range* LEDUniverseMap;
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
enum node_type
|
||||
{
|
||||
NodeType_RevolvingDiscs,
|
||||
NodeType_SolidColorProc,
|
||||
NodeType_RevolvingDiscs,
|
||||
NodeType_VerticalColorFadeProc,
|
||||
NodeType_Count,
|
||||
};
|
||||
|
||||
static node_specification_ NodeSpecifications[] = {
|
||||
{ NodeType_RevolvingDiscs, {"RevolvingDiscs", 14}, gsm_StructType_revolving_discs_data },
|
||||
{ NodeType_SolidColorProc, {"SolidColorProc", 14}, gsm_StructType_solid_color_data },
|
||||
{ NodeType_RevolvingDiscs, {"RevolvingDiscs", 14}, gsm_StructType_revolving_discs_data },
|
||||
{ NodeType_VerticalColorFadeProc, {"VerticalColorFadeProc", 21}, gsm_StructType_vertical_color_fade_data },
|
||||
};
|
||||
|
||||
void CallNodeProc(node_type Type, u8* NodeData)
|
||||
{
|
||||
switch(Type) {
|
||||
case NodeType_RevolvingDiscs:
|
||||
{
|
||||
RevolvingDiscs((revolving_discs_data*)NodeData);
|
||||
} break;
|
||||
case NodeType_SolidColorProc:
|
||||
{
|
||||
SolidColorProc((solid_color_data*)NodeData);
|
||||
} break;
|
||||
case NodeType_RevolvingDiscs:
|
||||
{
|
||||
RevolvingDiscs((revolving_discs_data*)NodeData);
|
||||
} break;
|
||||
case NodeType_VerticalColorFadeProc:
|
||||
{
|
||||
VerticalColorFadeProc((vertical_color_fade_data*)NodeData);
|
||||
|
|
|
@ -160,15 +160,15 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
|
|||
{
|
||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
||||
assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
||||
u32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob);
|
||||
u32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDBuffer.LEDCount, MaxLEDsPerJob);
|
||||
|
||||
for (u32 Job = 0; Job < JobsNeeded; Job++)
|
||||
{
|
||||
draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data);
|
||||
JobData->LEDs = Assembly.LEDs;
|
||||
JobData->Colors = Assembly.Colors;
|
||||
JobData->LEDs = Assembly.LEDBuffer.LEDs;
|
||||
JobData->Colors = Assembly.LEDBuffer.Colors;
|
||||
JobData->StartIndex = Job * MaxLEDsPerJob;
|
||||
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDCount);
|
||||
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDBuffer.LEDCount);
|
||||
JobData->Batch = &RenderLEDsBatch;
|
||||
JobData->FaceCameraMatrix;
|
||||
JobData->ModelViewMatrix = ModelViewMatrix;
|
||||
|
|
Loading…
Reference in New Issue