Lumenarium/src_v2/user_space/incenter_user_space.c

231 lines
6.3 KiB
C

#define INCENTER_METER 1.0f
#define INCENTER_FOOT 0.3048f
#define INCENTER_METERS(count) (count) * INCENTER_METER
#define INCENTER_FEET(count) (count) * INCENTER_FOOT
#define INCENTER_PER_METER(count) INCENTER_METER / (r32)(count)
internal v4
incenter_latlng_to_cartesian(r32 lat, r32 lng, r32 radius)
{
r32 theta = (lat / 180.0f) * r32_pi;
r32 phi = (lng / 180.0f) * r32_pi;
// spherical to cartesian conversion
v4 result = {
radius * sinf(phi) * cosf(theta),
radius * sinf(phi) * sinf(theta),
radius * cosf(phi),
1
};
return result;
}
#include "../user_space/incenter_patterns.c"
#include "../user_space/incenter_secondary_patterns.c"
#include "incenter_scenes.h"
////////////////////////////////////////////////
// INCENTER SCENES
internal void
incenter_scenes_init(Incenter_State* ins, u32 cap, Allocator* a)
{
incenter_scene_descs_init();
ins->scenes = incenter_scene_descs;
ins->scenes_cap = Incenter_Scene_Count;
ins->scene_at = Incenter_Scene_WelcomeHome;
}
internal void
incenter_scene_go_to(Incenter_State* ins, u32 index)
{
ins->transition_time = 0;
ins->scene_next = index % ins->scenes_cap;
ins->scene_mode = Incenter_SceneMode_TransitioningOut;
}
internal void
incenter_scene_go_to_next(Incenter_State* ins)
{
incenter_scene_go_to(ins, ins->scene_at + 1);
}
internal void
incenter_scene_go_to_prev(Incenter_State* ins)
{
incenter_scene_go_to(ins, ins->scene_at - 1);
}
internal void
incenter_scene_set_mode(Incenter_State* ins, Incenter_Scene_Mode mode)
{
ins->scene_mode = mode;
}
internal void
incenter_scene_render(App_State* state, Incenter_State* ins)
{
assert(ins->scene_mode != Incenter_SceneMode_Count);
Incenter_Pattern* pattern = 0;
if (ins->scene_mode > Incenter_SceneMode_Count)
{
// Update the transition if necessary
if (ins->transition_time >= INCENTER_TRANSITION_DURATION) {
if (ins->scene_mode == Incenter_SceneMode_TransitioningOut) {
ins->transition_time = 0;
ins->scene_mode = Incenter_SceneMode_TransitioningIn;
ins->scene_at = ins->scene_next;
ins->scene_time = 0;
} else {
ins->scene_mode = Incenter_SceneMode_Passive;
}
}
}
// DRaw the transition
switch (ins->scene_mode)
{
case Incenter_SceneMode_TransitioningOut: pattern = pattern_sun_transition_shrink; break;
case Incenter_SceneMode_TransitioningIn: pattern = pattern_sun_transition_grow; break;
default: {
Incenter_Scene scene = ins->scenes[ins->scene_at];
pattern = scene.patterns[ins->scene_mode];
} break;
}
Assembly_Array assemblies = state->assemblies;
if (pattern)
{
pattern(assemblies.pixel_buffers[0], assemblies.strip_arrays[0], ins);
}
else
{
pattern_color(assemblies.pixel_buffers[0], assemblies.strip_arrays[0], 0, 0, 0);
}
}
////////////////////////////////////////////////
// INCENTER LIFECYCLE
internal App_Init_Desc
incenter_get_init_desc()
{
App_Init_Desc result = {};
result.assembly_cap = 4;
return result;
}
internal void
incenter_init(App_State* state)
{
// create user space data
Incenter_State* ins = allocator_alloc_struct(permanent, Incenter_State);
state->user_space_data = (u8*)ins;
incenter_scenes_init(ins, 8, permanent);
// create the sculpture
u32 lights_per_primary_city = 123;
u32 primary_city_lights = (city_count + 1) * lights_per_primary_city;
u32 secondary_city_count = (city_secondary_count - city_secondary_first) + 1;
u32 secondary_city_lights = secondary_city_count;
u32 lights_cap = primary_city_lights + secondary_city_lights;
Assembly_Handle ah = assembly_add(&state->assemblies, lit_str("incenter"), lights_cap, city_count + 2);
scratch_get(scratch);
Allocator* s = scratch.a;
v3 start_p = (v3){0, 0, 0};
Assembly_Strip* vertical_strip = assembly_add_strip(&state->assemblies, ah, 123);
assembly_strip_create_leds(
&state->assemblies,
ah,
vertical_strip,
start_p,
(v3){0, INCENTER_FEET(-4.5f), 0},
123
);
// ADDING PRIMARY CITIES
r32 radius = INCENTER_FEET(10);
for (u32 i = 0; i < city_count; i++)
{
Incenter_City_Desc city = city_descs[i];
v3 end_p = incenter_latlng_to_cartesian(city.lat, city.lon, radius).xyz;
Assembly_Strip* strip = assembly_add_strip(&state->assemblies, ah, 123);
strip->output_kind = OutputData_NetworkSACN;
strip->sacn_universe = city.sacn_universe;
assembly_strip_create_leds(&state->assemblies, ah, strip, start_p, end_p, 123);
}
// ADDING SECONDARY CITIES
// TODO: This probably isn't how these lights will be hooked up
Assembly_Strip* secondary_strip = assembly_add_strip(&state->assemblies, ah, secondary_city_lights);
secondary_strip->output_kind = OutputData_NetworkSACN;
secondary_strip->sacn_universe = incenter_secondary_city_universe;
for (u32 i = city_secondary_first; i < city_secondary_count; i++)
{
Incenter_City_Desc city = city_descs[i];
v4 light_p = incenter_latlng_to_cartesian(city.lat, city.lon, radius);
assembly_add_led(&state->assemblies, ah, secondary_strip, light_p);
}
// PATTERN INIT
pattern_random_fill_prep();
r32 rad = 0.05f;
sculpture_updated(state, 5, rad);
scratch_release(scratch);
}
internal void
incenter_frame_prepare(App_State* state)
{
}
#if defined(PLATFORM_SUPPORTS_EDITOR)
internal void
incenter_sculpture_visualizer_ui(App_State* state, Editor* ed)
{
UI_Layout layout = *ed->ui.layout;
layout.mode = UILayout_Columns,
layout.bounds_min = (v2){0, 0},
layout.bounds_max.x = 250;
ui_layout_push(&ed->ui, &layout);
Incenter_State* ins = (Incenter_State*)state->user_space_data;
ui_text_f(&ed->ui, WHITE_V4, "Scene Time: %fs", ins->scene_time);
ui_text_f(&ed->ui, WHITE_V4, "Scene: %s", ins->scenes[ins->scene_at].name);
ui_layout_pop(&ed->ui);
}
#endif
internal void
incenter_frame(App_State* state)
{
Incenter_State* ins = (Incenter_State*)state->user_space_data;
Assembly_Array assemblies = state->assemblies;
{ // INPUT HANDLING
Input_State* is = state->input_state;
if (input_key_went_down(is, KeyCode_LeftArrow)) incenter_scene_go_to_prev(ins);
if (input_key_went_down(is, KeyCode_RightArrow)) incenter_scene_go_to_next(ins);
}
ins->scene_time += state->target_seconds_per_frame;
ins->transition_time += state->target_seconds_per_frame;
incenter_scene_render(state, ins);
}
internal void
incenter_cleanup(App_State* state)
{
}