From 829cea09ba1529c43b4cf7fa6bfb2ad8cd309727 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 16 Mar 2026 19:16:28 -0500 Subject: [PATCH] collada: draw ship20 (untextured) --- Makefile | 8 +- data/scenes/ship20.cpp | 427 ++++++++++++++++++++++++++++++ data/scenes/ship20/ship20.cpp | 429 +++++++++++++++++++++++++++++++ data/scenes/ship20/ship20.idx | Bin 0 -> 38976 bytes data/scenes/ship20/ship20.vjw | 0 data/scenes/ship20/ship20.vtx | Bin 0 -> 133272 bytes include/collada/effect.h | 8 + include/collada/instance_types.h | 28 ++ include/collada/scene.h | 32 +++ include/collada/types.h | 407 +++++++++++++++++++++++++++++ include/collada_scene/ship20.h | 7 + include/data/scenes/ship20.h | 3 + include/new.h | 9 + shader/collada/generic.frag | 8 + shader/collada/static.vert | 12 + src/collada/animate.cpp | 205 +++++++++++++++ src/collada/effect.cpp | 16 ++ src/collada/node_state.cpp | 67 +++++ src/collada/scene.cpp | 280 ++++++++++++++++++++ src/test.cpp | 16 +- 20 files changed, 1959 insertions(+), 3 deletions(-) create mode 100644 data/scenes/ship20.cpp create mode 100644 data/scenes/ship20/ship20.cpp create mode 100644 data/scenes/ship20/ship20.idx create mode 100644 data/scenes/ship20/ship20.vjw create mode 100644 data/scenes/ship20/ship20.vtx create mode 100644 include/collada/effect.h create mode 100644 include/collada/instance_types.h create mode 100644 include/collada/scene.h create mode 100644 include/collada/types.h create mode 100644 include/collada_scene/ship20.h create mode 100644 include/data/scenes/ship20.h create mode 100644 include/new.h create mode 100644 shader/collada/generic.frag create mode 100644 shader/collada/static.vert create mode 100644 src/collada/animate.cpp create mode 100644 src/collada/effect.cpp create mode 100644 src/collada/node_state.cpp create mode 100644 src/collada/scene.cpp diff --git a/Makefile b/Makefile index cb52a23..6cc7f0e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC=$(PREFIX)gcc CXX=$(PREFIX)g++ -OPT = -O2 -march=x86-64-v3 +OPT = -O0 -march=x86-64-v3 CSTD = -std=gnu23 CXXSTD = -std=gnu++23 @@ -35,7 +35,11 @@ OBJS = \ src/collision_scene.o \ src/line_art.o \ src/boids.o \ - src/boids_scene.o + src/boids_scene.o \ + src/collada/scene.o \ + src/collada/effect.o \ + src/collada/node_state.o \ + data/scenes/ship20/ship20.o all: test.so diff --git a/data/scenes/ship20.cpp b/data/scenes/ship20.cpp new file mode 100644 index 0000000..9297e2f --- /dev/null +++ b/data/scenes/ship20.cpp @@ -0,0 +1,427 @@ +#include "collada/types.h" + +namespace ship20 { + + using namespace collada::types; + +light const light_environmentambientlight = { + .type = light_type::AMBIENT, + .color = { 0.0f, 0.0f, 0.0f }, +}; + +light const light_omni002_light = { + .type = light_type::POINT, + .color = { 1.0f, 1.0f, 1.0f }, +}; + +light const light_omni003_light = { + .type = light_type::POINT, + .color = { 1.0f, 1.0f, 1.0f }, +}; + +// shipple2_png +image const image_shipple2_png = { + .resource_name = "_0_SHIPPLE2_PNG", +}; + +image const * const images[] = { + &image_shipple2_png, +}; + +effect const effect_diffusetexture = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.588f, 0.588f, 0.588f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.5f, 0.5f, 0.5f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +effect const effect_cyanengine = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.9647059f, 1.0f, 1.0f}, + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +effect const effect_emissivetexture = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.588f, 0.588f, 0.588f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +material const material_diffusetexture_material = { + .effect = &effect_diffusetexture, +}; + +material const material_cyanengine_material = { + .effect = &effect_cyanengine, +}; + +material const material_emissivetexture_material = { + .effect = &effect_emissivetexture, +}; + +input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = { + { + .semantic = "POSITION", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, + { + .semantic = "NORMAL", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, + { + .semantic = "TEXCOORD", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, +}; + +triangles const triangles_geom_ship[] = { + { + .count = 2949, // triangles + .index_offset = 0, // indices + .inputs_index = 0, // index into inputs_list + }, + { + .count = 60, // triangles + .index_offset = 8847, // indices + .inputs_index = 0, // index into inputs_list + }, + { + .count = 239, // triangles + .index_offset = 9027, // indices + .inputs_index = 0, // index into inputs_list + }, +}; + +geometry const geometry_geom_ship = { + .mesh = { + .triangles = triangles_geom_ship, + .triangles_count = 3, + + .vertex_buffer_offset = 0, + .vertex_buffer_size = 133272, + + .index_buffer_offset = 0, + .index_buffer_size = 38976, + } +}; + +geometry const * const geometries[] = { + &geometry_geom_ship, +}; + +transform const transforms_node_environmentambientlight[] = { +}; + +instance_geometry const instance_geometries_node_environmentambientlight[] = { +}; + +instance_controller const instance_controllers_node_environmentambientlight[] = { +}; + +instance_light const instance_lights_node_environmentambientlight[] = { + { + .light = &light_environmentambientlight, + } +}; + +channel const * const node_channels_node_environmentambientlight[] = {}; + +node const node_node_environmentambientlight = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_environmentambientlight, + .transforms_count = 0, + + .instance_geometries = instance_geometries_node_environmentambientlight, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_environmentambientlight, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_environmentambientlight, + .instance_lights_count = 1, + + .channels = node_channels_node_environmentambientlight, + .channels_count = 0, +}; + +transform const transforms_node_ship[] = { + { + .type = transform_type::ROTATE, + .rotate = {0.0f, 0.0f, 1.0f, -180.0f}, + }, +}; + +instance_material const instance_geometry_instance_materials_node_ship_0[] = { + { + .element_index = 1, // an index into mesh.triangles + .material = &material_cyanengine_material, + + .emission = { .input_set = -1 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = -1 }, + .specular = { .input_set = -1 }, + }, + { + .element_index = 0, // an index into mesh.triangles + .material = &material_diffusetexture_material, + + .emission = { .input_set = -1 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = 0 }, + .specular = { .input_set = -1 }, + }, + { + .element_index = 2, // an index into mesh.triangles + .material = &material_emissivetexture_material, + + .emission = { .input_set = 0 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = 0 }, + .specular = { .input_set = -1 }, + }, +}; + +instance_geometry const instance_geometries_node_ship[] = { + { + .geometry = &geometry_geom_ship, + + .instance_materials = instance_geometry_instance_materials_node_ship_0, + .instance_materials_count = 3, + }, +}; + +instance_controller const instance_controllers_node_ship[] = { +}; + +instance_light const instance_lights_node_ship[] = { +}; + +channel const * const node_channels_node_ship[] = { +}; + +node const node_node_ship = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_ship, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_ship, + .instance_geometries_count = 1, + + .instance_controllers = instance_controllers_node_ship, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_ship, + .instance_lights_count = 0, + + .channels = node_channels_node_ship, + .channels_count = 0, +}; + +transform const transforms_node_omni002[] = { + { + .type = transform_type::TRANSLATE, + .translate = {-286.5521f, 395.7583f, 161.5579f}, + }, +}; + +instance_geometry const instance_geometries_node_omni002[] = { +}; + +instance_controller const instance_controllers_node_omni002[] = { +}; + +instance_light const instance_lights_node_omni002[] = { + { + .light = &light_omni002_light, + } +}; + +channel const * const node_channels_node_omni002[] = { +}; + +node const node_node_omni002 = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_omni002, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_omni002, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_omni002, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_omni002, + .instance_lights_count = 1, + + .channels = node_channels_node_omni002, + .channels_count = 0, +}; + +transform const transforms_node_omni003[] = { + { + .type = transform_type::TRANSLATE, + .translate = {333.2103f, -314.4593f, 161.5578f}, + }, +}; + +instance_geometry const instance_geometries_node_omni003[] = { +}; + +instance_controller const instance_controllers_node_omni003[] = { +}; + +instance_light const instance_lights_node_omni003[] = { + { + .light = &light_omni003_light, + } +}; + +channel const * const node_channels_node_omni003[] = { +}; + +node const node_node_omni003 = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_omni003, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_omni003, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_omni003, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_omni003, + .instance_lights_count = 1, + + .channels = node_channels_node_omni003, + .channels_count = 0, +}; + +node const * const nodes[] = { + &node_node_environmentambientlight, // 0 + &node_node_ship, // 1 + &node_node_omni002, // 2 + &node_node_omni003, // 3 +}; + +inputs const inputs_list[] = { + { + .elements = input_elements_position_0_3_normal_0_3_texcoord_0_3, + .elements_count = 3, + }, +}; + +types::descriptor const descriptor = { + .nodes = nodes, + .nodes_count = (sizeof (nodes)) / (sizeof (nodes[0])), + + .inputs_list = inputs_list, + .inputs_list_count = (sizeof (inputs_list)) / (sizeof (inputs_list[0])), + + .images = images, + .images_count = (sizeof (images)) / (sizeof (images[0])), + + .position_normal_texture_buffer = "RES_SCENES_SHIP20_VTX", + .joint_weight_buffer = "RES_SCENES_SHIP20_VJW", + .index_buffer = "RES_SCENES_SHIP20_IDX", +}; + +} diff --git a/data/scenes/ship20/ship20.cpp b/data/scenes/ship20/ship20.cpp new file mode 100644 index 0000000..203f876 --- /dev/null +++ b/data/scenes/ship20/ship20.cpp @@ -0,0 +1,429 @@ +#include "collada/types.h" + +#include "data/scenes/ship20.h" + +namespace ship20 { + + using namespace collada::types; + +light const light_environmentambientlight = { + .type = light_type::AMBIENT, + .color = { 0.0f, 0.0f, 0.0f }, +}; + +light const light_omni002_light = { + .type = light_type::POINT, + .color = { 1.0f, 1.0f, 1.0f }, +}; + +light const light_omni003_light = { + .type = light_type::POINT, + .color = { 1.0f, 1.0f, 1.0f }, +}; + +// shipple2_png +image const image_shipple2_png = { + .resource_name = "_0_SHIPPLE2_PNG", +}; + +image const * const images[] = { + &image_shipple2_png, +}; + +effect const effect_diffusetexture = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.588f, 0.588f, 0.588f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.5f, 0.5f, 0.5f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +effect const effect_cyanengine = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.9647059f, 1.0f, 1.0f}, + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +effect const effect_emissivetexture = { + .type = effect_type::BLINN, + .blinn = { + .emission = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .ambient = { + .type = color_or_texture_type::COLOR, + .color = {0.588f, 0.588f, 0.588f, 1.0f}, + }, + .diffuse = { + .type = color_or_texture_type::TEXTURE, + .texture = { .image_index = 0 }, // shipple2_png + }, + .specular = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .shininess = 10.0f, + .reflective = { + .type = color_or_texture_type::COLOR, + .color = {0.0f, 0.0f, 0.0f, 1.0f}, + }, + .reflectivity = 0.0f, + .transparent = { + .type = color_or_texture_type::COLOR, + .color = {1.0f, 1.0f, 1.0f, 1.0f}, + }, + .transparency = 1.0f, + .index_of_refraction = 0.0f, + } +}; + +material const material_diffusetexture_material = { + .effect = &effect_diffusetexture, +}; + +material const material_cyanengine_material = { + .effect = &effect_cyanengine, +}; + +material const material_emissivetexture_material = { + .effect = &effect_emissivetexture, +}; + +input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = { + { + .semantic = "POSITION", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, + { + .semantic = "NORMAL", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, + { + .semantic = "TEXCOORD", + .semantic_index = 0, + .format = input_format::FLOAT3, + }, +}; + +triangles const triangles_geom_ship[] = { + { + .count = 2949, // triangles + .index_offset = 0, // indices + .inputs_index = 0, // index into inputs_list + }, + { + .count = 60, // triangles + .index_offset = 8847, // indices + .inputs_index = 0, // index into inputs_list + }, + { + .count = 239, // triangles + .index_offset = 9027, // indices + .inputs_index = 0, // index into inputs_list + }, +}; + +geometry const geometry_geom_ship = { + .mesh = { + .triangles = triangles_geom_ship, + .triangles_count = 3, + + .vertex_buffer_offset = 0, + .vertex_buffer_size = 133272, + + .index_buffer_offset = 0, + .index_buffer_size = 38976, + } +}; + +geometry const * const geometries[] = { + &geometry_geom_ship, +}; + +transform const transforms_node_environmentambientlight[] = { +}; + +instance_geometry const instance_geometries_node_environmentambientlight[] = { +}; + +instance_controller const instance_controllers_node_environmentambientlight[] = { +}; + +instance_light const instance_lights_node_environmentambientlight[] = { + { + .light = &light_environmentambientlight, + } +}; + +channel const * const node_channels_node_environmentambientlight[] = {}; + +node const node_node_environmentambientlight = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_environmentambientlight, + .transforms_count = 0, + + .instance_geometries = instance_geometries_node_environmentambientlight, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_environmentambientlight, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_environmentambientlight, + .instance_lights_count = 1, + + .channels = node_channels_node_environmentambientlight, + .channels_count = 0, +}; + +transform const transforms_node_ship[] = { + { + .type = transform_type::ROTATE, + .rotate = {0.0f, 0.0f, 1.0f, -180.0f}, + }, +}; + +instance_material const instance_geometry_instance_materials_node_ship_0[] = { + { + .element_index = 1, // an index into mesh.triangles + .material = &material_cyanengine_material, + + .emission = { .input_set = -1 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = -1 }, + .specular = { .input_set = -1 }, + }, + { + .element_index = 0, // an index into mesh.triangles + .material = &material_diffusetexture_material, + + .emission = { .input_set = -1 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = 0 }, + .specular = { .input_set = -1 }, + }, + { + .element_index = 2, // an index into mesh.triangles + .material = &material_emissivetexture_material, + + .emission = { .input_set = 0 }, + .ambient = { .input_set = -1 }, + .diffuse = { .input_set = 0 }, + .specular = { .input_set = -1 }, + }, +}; + +instance_geometry const instance_geometries_node_ship[] = { + { + .geometry = &geometry_geom_ship, + + .instance_materials = instance_geometry_instance_materials_node_ship_0, + .instance_materials_count = 3, + }, +}; + +instance_controller const instance_controllers_node_ship[] = { +}; + +instance_light const instance_lights_node_ship[] = { +}; + +channel const * const node_channels_node_ship[] = { +}; + +node const node_node_ship = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_ship, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_ship, + .instance_geometries_count = 1, + + .instance_controllers = instance_controllers_node_ship, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_ship, + .instance_lights_count = 0, + + .channels = node_channels_node_ship, + .channels_count = 0, +}; + +transform const transforms_node_omni002[] = { + { + .type = transform_type::TRANSLATE, + .translate = {-286.5521f, 395.7583f, 161.5579f}, + }, +}; + +instance_geometry const instance_geometries_node_omni002[] = { +}; + +instance_controller const instance_controllers_node_omni002[] = { +}; + +instance_light const instance_lights_node_omni002[] = { + { + .light = &light_omni002_light, + } +}; + +channel const * const node_channels_node_omni002[] = { +}; + +node const node_node_omni002 = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_omni002, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_omni002, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_omni002, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_omni002, + .instance_lights_count = 1, + + .channels = node_channels_node_omni002, + .channels_count = 0, +}; + +transform const transforms_node_omni003[] = { + { + .type = transform_type::TRANSLATE, + .translate = {333.2103f, -314.4593f, 161.5578f}, + }, +}; + +instance_geometry const instance_geometries_node_omni003[] = { +}; + +instance_controller const instance_controllers_node_omni003[] = { +}; + +instance_light const instance_lights_node_omni003[] = { + { + .light = &light_omni003_light, + } +}; + +channel const * const node_channels_node_omni003[] = { +}; + +node const node_node_omni003 = { + .parent_index = -1, + + .type = node_type::NODE, + + .transforms = transforms_node_omni003, + .transforms_count = 1, + + .instance_geometries = instance_geometries_node_omni003, + .instance_geometries_count = 0, + + .instance_controllers = instance_controllers_node_omni003, + .instance_controllers_count = 0, + + .instance_lights = instance_lights_node_omni003, + .instance_lights_count = 1, + + .channels = node_channels_node_omni003, + .channels_count = 0, +}; + +node const * const nodes[] = { + &node_node_environmentambientlight, // 0 + &node_node_ship, // 1 + &node_node_omni002, // 2 + &node_node_omni003, // 3 +}; + +inputs const inputs_list[] = { + { + .elements = input_elements_position_0_3_normal_0_3_texcoord_0_3, + .elements_count = 3, + }, +}; + +collada::types::descriptor const descriptor = { + .nodes = nodes, + .nodes_count = (sizeof (nodes)) / (sizeof (nodes[0])), + + .inputs_list = inputs_list, + .inputs_list_count = (sizeof (inputs_list)) / (sizeof (inputs_list[0])), + + .images = images, + .images_count = (sizeof (images)) / (sizeof (images[0])), + + .position_normal_texture_buffer = "data/scenes/ship20/ship20.vtx", + .joint_weight_buffer = "data/scenes/ship20/ship20.vjw", + .index_buffer = "data/scenes/ship20/ship20.idx", +}; + +} diff --git a/data/scenes/ship20/ship20.idx b/data/scenes/ship20/ship20.idx new file mode 100644 index 0000000000000000000000000000000000000000..6077f25b9ab2563c8f8f5600e98321303031edbb GIT binary patch literal 38976 zcmYkF1+-S>)V8i1MCD;Kx_p;1yoQ0yG88o?(Xi^ zf6n_qdyI3(nB!URTx;+B?tMN!INw3;R$FbgRVgSP%8>rAENl(s!ZvZ`$qG;rtWA5? zrt_7cGE@mwp+?x2)YXJq;9BhKYC|0;&f__C+rjp*L#P|KW74(k1Uk>{`RaxG zao%$SXc)YA-OkVmc7evw1e%6sar)-4Yj8&AbMP6o2rc7wBX@^Zp*2}Ja}Tg@?wQ(b zliF;X+H42z(>=C_4$u+y3Y|*0&eUCkedpYld+Zvz#koKC(LMAa3+FX^2K&zSg5I!q z*e9+J>9vaM_NCVKgZ{8@7!Ws*+z<8-gUG@iKz(4a@7!SU+FnnFfNm%ZgW)g&4uXSA ztgW4~Z#@!5!RXZHA*szVS?kA!adG3x32jJq)x1l3CG6GBj>|$U~L|s+B^Zgu6sE#cwOB|a59_{ zP9=4x!Rc^DI5TbmxeykGvq;_9a1JaEOXBQ1yEL3j>XyNIaDKQT?n3e+xHw!w>Mn)L zV0l;(cX`(KWF_cU!4+_2xQf(yoaZdg?|F5rVGXPeSI1pLUJL8OdQx{CTn{&d4RIUE zP2e%&tj>Mi2sZ`ysJj_%fm^|S+y=J?_gU;$cSrDf*t-+%g1f^#ajx%$`+{EQwRHAm zGw8(HeR%!*VN3A3#h!Ez1ovXk>put&1+P==N%wH@dd0qUj|8u4?@@RRit}%YbFF_o zJVEMA-IL*|I8*m@c!t#ZdVUt33%<5>&%+DwVtA>9v-fg%g>>#!cnw|;Z^XSBZ(rVm z!g(IgD<0?Zo>y-z&g$L#X004^o?6TW@+UkNXhb5B7BKl|wui$I=CVU(B z9r-={5Pl?eKf%xNOZYYJH}ZG*Bm7C~{(`^ZpYU(of24n?^1VRTg02*y9<0_C9p;D+!>Z(9hs1~Zn)gZS8*J58+6KX;2P$zCXa(mbz)FpL0!cO41#B=Dx zx?ZRsXX+Y+hNNz1Xau{2#&J!^rqB$m&E~1iU7-cEgxyk`yQel=L2K9pJYGDfZck_f zZ9}^__u+op2WNGzJAmgBy{;qd1)Wlxol~1#peuBP?$9G^YkRJ(J&$W^pOMe1XXsVJ z`E08N`_A=-y5+_jm-%3GS`fx9-T`-im$e<_7m`&pjRmM+f(%b6?hl zKPJvS9t-op+MJ)-bpOY}@!&DyIdmt$Qoh!U!ijOF?j%x92Hh!eDx4Nhk8^znxIPmW zfUg7bbx}BTVOT^u=li4YlV?%O*>UHPer>#OSqwVUb#X6C;=I45;9BhK&V^-gUTX9F z)TYnC8Pj_d@AraWPj?|)1Q&-(O1Mj@FAMgaTMjGW@~|?_KOgw#gjKBN3ea6iUInYe z8dA3wu7+#EwQ=jn^{JiF>#l?A;fAmw&hu@AO~G^PZiJiQ=5R~gt>kTRd$@ztnL3XV zkJtI0aSYr^Ed%22BJYMn>B$7p-2?Z+ePMIlNc!VpVi-m0?x#PAoEo;U);$0Zg4YwT zt$PSOzt@q6K{pVbeZ0QV&BMQ8mcycOJAv2Wem!Mzpx*1Z$lo4t48J#Zh^rhBtC--i#teYrnt^TX8U zN8lbm2KOZHMQ8m9d>Y(av2WdH!Mzpx)_oq_Z?SLP7vW3N-dFH7d=tKnbD!?(yYM}! zbB{lOdlL7e`w@PEpWzo61cSq`ajqADYjY9&77F(}>$Bmk@CT{;6V8Ff;jcJTw

c z>Rc}c*UR8sDBc_YiMxcn82%0ak%haAy7I2qyp%CkC*}#SxY6*RVMvDtN5O)3Ts_e@cSdbpOI>D_MNpS&gp#b@qC_F zs>jtJw*~iYZF(QxpKI%l9J>Z;QcJD4+F9F^)u5{bS5vPI+r^nWe;v#AtaYYqfBnb~ zadpWZVW&`!)VbEz4-MiPk~>2qur_x|Z8nA`&=i`5=5f1{EubY>o4chpcL!%Zu2pCq z=dTTajqJf%_5_{jx=mU=*a`mWo>nXa9a_Mqzk$Mdy2E_96Bi|ho$@z!Q%(%S5j z)DH_?;rv6KT_8p_JsjqVBCJ>{xAp*fKA-LuPHe& z&f3@2V6Zlaq&A%!3d3M{7!l{M%Y)$H;IC2LNbs0ZVRW4D-@gC(K4@(oLeJXt_nk51 zSQr<^le!6TXq-J~bT{*SZv}f&xQW!0z;gU)B!R&*TU7|8d7KKyta5v-Loz#Pm;Q);Awa!JRA2M`8>Q3ULLb*}ZVh3;{$lW)MA;Vn|< zzTN-Z;4|=9tPJnOy-U6a?}N4ZLHLmTD7E=9IAg!4%}?S@pRY5f&-_#P3_cHE#C=JA z1z(46NS&$sHhdRn>b?&@kh&k?Cn(PEwRC=ezYtF1erLgG_!%$1K;cH=e`RgowEr9Q zV%;J?S|H6N;RT=(# z6-tx3GGtlUI+P=I+dz4!5Gux1A}d1`s0!7fdZ-cSb+@Ii8Qg=;YuAF>!9D1_ejV5@ zxEI~_umjW$JI3uq)&s9C?n74}8bHI;=FX|jMqwASalFpD2{eV`nb+p|6|NcHuYuTi zt~u-qEket<-IA_lchLF$N-MH;@Ou~C9$DLyJwew7+Csb3X8Y7;2l$0AX-9Ie;AiZ* zPOLjam(Z2eb%XBU{fqam>j6EX7kIu?ILFDsbL)D;2KIYH*gI|?vJdnP{YahnZC!Yu z!T(&Iqt8_OLqFWUU>+OkM()hRaCZa##VEhm~=w z$SdH=a22Ur4QpU+xH|3{(z@{1QtQ?wUCa77&vPC4vsdw)y5gAYspW<^z4eCRwR9e1 zU3kx_+X!CU>&Yh2nXYdPH^tpddOeR3XLYy0tx)WzaJS)ZhdaWZr0y=b8}3PM_U6}( z-t3;*^v_H8;_rjv`S|>FK99|*UF&tuy7%I~JWlrt&(L{i#Am9zpW1sY?sp5d?nQde z_`Ix5f3Eug`5-(5-m~}qaPavTUlZLU!DnypQSf+=_2Ps#Dz=VR1kNS(*&A19xH zC&N>u&eS~}o{2Mc&xYqnovC|1ybx#VUJNghI#c&@cqPu%y&7I4b*Aq1@J5`edo#R6 z>P+3+;hi{B_ilKP)S0^X!v}F6k{`jx;S*B#DSQT>hcDtx-Iw7jQfKPE4&TImOMVC6 zhaX6tsrxbf6ldyw4!@APU*R|SJ^T^(C;1or9sVJ8rtaVHU))w@`Li384rNH4sVf_{ zjw?rQ1LZ>nQdbcwLFG^-t}0m#s)rh+Zd<4cwL z`p^IxhMnU~U8ArIsWWwrLzB3sWHV?Ub|rPDu0?1WXXHp#d&adP+d{k0 zp46GT4xwY5soN`bB6X&&bLbLh>biz*q|VfJ4?W^cUC+>q)S0^8VedFow@>Ip>P%hV z&@ax^`C1WQH#)x;_4CbkykANGIMa3eurF)f02l}j@KPUi`@#P3E$0${Mxh%72f%@0 zaNLljYZ(fQYUnkZc$Yr?mf zxjr9Un-{<&=B1>&5bx)$V$V5i{Y7CquPL4Di{X-Z^U~C&bGpl5Iar%3Qk%}%zZ_Nu zX9~B9`ifxRIo*|TRj{vH4QpU+xH`_%T@$V)b*64zSRZHVt_#c@Nwh?jv=Z!MgDG$88}WfCs}vq|Vem93F`? zb&rO}NS&#BJUkI+>YfZwkvdcNba*Dt)IA%XBXy?k`S3!Vse3WJMCwf4%i)zcQ}=3k zjnusk)`fo~t~I{~n!+y0CS>DKxHp-73*H86^PSY@yYL>o4OKjd z#+ka$!sn!}1$$}*Ur=u*za+m3_psKv{u&;p7QOBp_!b7Twl*J0ZGIQ$%=e)`-Z|Gl zfS)ahzHp=XeM9#n{h#3H@C&K?6@G)?!yj>`?$7WSsWWwdhkxQs-M`^KQfKP6+WP+~ zMe0hEWuR=>n$(qpZJ>Op5NGNthDxN))Kv~u;!IuDP>s}?y6T}uoT=M3)FgGapf=PA z+r@29?f`Yej-+lUs0Z~!gSdv|&d@0ALh2er6KI;+Y!;mL7-w|W&0$w)5n7VFfnH}V zp2zcAo4bQEuC1N*Jgq|OxIM@{!JnyHn|1hoL7Z`3@7lTzcpu)6wRsK4SeqViZF=6e z&<@&%4soWgW7vz-nYvD)bDXK`61tMQZqOZigr0G|$lkDb*oV~hfxgf$^p7)j`-TCe z&eRPI`^D`~4uS*1fuwFQ41u9xSln=O1eD`Bia%S?9Rvs4csXI2zi!*ie!*Qg}d-K`*HLyOO z+O@U!?)n5c5l#vx$CT>dp@5#F@Iq zVF{^Q3f6@`H*Ohu9-JR8Aa$nh!f;WXsk=B_Lh4N2rQx!;<>U&uJgg*jtKbT_GF%mB z>Q;v}q|Vf>4OhpRx@*FilfyM)IameBNW~ZVrBCq%(E5 zgyQogQ+I3dGbvpuUR$@}ZV#nd>$>rK;T^a;Ll@RMQ+HSB6ld!04jozROx-=9eVnPg zH?(1`yN~r|xIb(mb$+Jx0O_+3pNsB6>WARr@Cd0hb&rO};!NG+;R#Y_>YfZw#XU_v z1J8!%NZs@B0=yVriZgXDhgV3Qse3iN7H8^S4{wkKT23!js^etd1dAioTKSnEvPS7GlsQ}=b~#ad_T zz6m|z%J7=|7WZ8!%Ub8>r{Cj#2rseLnL6)HyeHj{)IY(`;TKY8>V6Hs#r;nH0e^3G2D^t=ai*?y*n`yV32mTlXcuSd+J_FL z&eU}bd&PAkJ42VymDHKKZlQZzM}F__LESTSV6EF9df|G9iE(?g-Us@GzND@n^oM=J zfVg}4H87BRzi=OGoj=>zA7@VrXW!W^q}&KPfA&+^Jmb$#gc+=L3*kWA z;IJsJI_DUITgF=a3`w_|dMJKaSi@R3ob?DeC>%`c#_@Xh&pjhko1;>jqu~%317pLu zxDz;bJoSWdB5U1D?q?btikFF?n?z2ADWG>|IuvVbXIxu5>w0RKM(V1uU;ke62jQ@| z!^!C|Bg`aqvtTwH5$41lNzR3%!qKGen51htHcoFnFU*fOb;pI{N!BAgUXjyr`s z6;2DMlZ88j`pjV8xdpHg7KO9o&L+=+syqj&0)< zr#ly#uoioTTZV7STI@NeI}gqeP4T)5;6k`4TwKDrU-xa_tdrVwzA5SXnvou-vnRFV z+;3y39K0``YrV&c^E%UYu}{ydbM5}!ujqBYFZy2CBs7kzNp1_(Lp4%YopW76UK(n! z)|tARNToJB}yNX;5Yl3~}^g8Rca5Y>Lu8mtqu7~Tw^`!2GtnJB$ zxQ(R87U$VSt-BF!f}6uFakrAUfjx0f=lO1jJA&8KdC%Vao#C#yyUBatUbqi7!~J1P zoZk9@@L;^p;30T8_H{1^TUTW!OiHK|LHrJ+nHOX{|Ua;aVGb=yGstaTozlL}BVIHRis zm7z+g8mF%Y)q^v-8n7+Y47JGGpx0S@UC&=9xG&vyus!S$>c;Iz?gaHheNxu|8p6(@ zQQR(MV`vhZk~(LbLG$2ox?Q0Kv<$n&?M}9W)?p7)wh^|xpik%<*N?RCob(5sdvss>h5>N{$^Bq| za3AhxP&lB3^BEi%>^nCYhQQD;EY7ulco;$Iyw*YBTI}n@>)Z31p8w!5vV`;cqk?_s zyr$yCzFz-x%- z(j5zWYncZ+YiGQ+wK+evc^o)v&svTLo%`|{o>xwQVy~uaIT76ZNpLcp5>Ab?uP>gV zvxPHH3m)g3*K+Tt2d`0FUsud~ti3bfOjr;W#w{Yxg0sUpq;4@Rfu-TxxMk#daDKRe z)LjS{!NuW{xJ$`y&^25}>XyR_xIChdY8Zg}ambu3+D}yWt+VH{2JunY!C8-yCqVZkJOxjOXX4z4{bz&w(Ye-pygUcG=ivo- z5nh6q;g!_ptEtV`pqMLa^L6k%_N;wIZ@`w?c#_ZGYj?}T^b-Xq@!&naF@ z_W@LcO5wve{YUU|a7O33y~Zcu)40#b&*6*kC8_%gzJ_m7o8P83zk~1L2lz3y`BQ51 zXZQtvh2O&OCEOp>e+K)`>HdPhgMHmU@Gtxq{0IDWrO47ycxQBFpe$@1%Eh_oZK%r! z_pftb?x6x+DnjAhLnYQ?&pDlYtjt>M>D-rlsX|Is(7DHIPp^|+wcu+)8pN3mVdvnSZW%L; z$X&vDtaXi9Hv#Wa{F)T5DRpr#_MG#cboQhf=$eCj_r9#nT~nJaQkyNoS?6{OJ_p_I z&pE=o}mq?YYXk5edrK3m3!+*y;qpVTGxqnXXp~TlDclt9eRYGalPX0OK;Ha z4f{Z!&^OL=d%k|5KdIXn2Ef3uU)=uWAUGf#NEXgxoD=)b`99%$#$alxPOTe4?e{yy z_dY{e>xRK_7!eMN^ZP8nm-721@p~uT!SqLh-!F;ZC+S9k*DKzyM#mjOjsdSDo?qvC z+gQ>$@i?9L;xiZ*#*;el+k2c44lUvAJ16#?v-TVl!=yNmb7pdwLKeQ4ql10tbnfApU|)AE%mephZMr{eb3V8i_jO!2o;(5cI&1gkp4^9=2s&%`a8fwA zgmVw41pChE+~cXie&J4|K0VlX?hH5+7KDXy?rRa872LDVeYq$1A!mc`99RrXU@4pn z#e1p0uj*Xu8wBfRp<uwClhC+?yNJ4Ju< z61X(9CUvInvan~|a&iS+9#)dNRd7XW*H^~1B|D^cMz8a;mI{2fUOxD_i_Z6ltLU!| ze!ikx!+I^u;`zx;&|MAJz)`GaF6f*!U5m%)d>^_NyoPvgo%iIvy$5S^9jwpVx<6b8 z*N4t=H;`Sxwb<8ffQ`^C^eo{vQTyvy>^rBs5&ShH_H;MF&2US&HO}>IaC^|}?tnYt zuGHq;sm*)fUbqi7hx_BUkPpCvU~N8>+I$#1?h$x2cn;lh@EANE7L{;MP(K;$J2xAi zO6}U?3->g&$A~@Wo`Gkf247354Z7!`3$LTjU~T#tp|$yZTvxoG8;ah!7wEkRFM+lB za%%IHtY0Nx3x#`~^&9YJc#G7%4e!9a;k~%`$q(Q|_y|4*UsKW#bk_P$Qk$QqHhukl z2A{(h;mf#{q`xk|3SX1DZ{S<_E_@$1otyzbfVFvAYV#QQ5q^T7!!L2alGcU)jaoO5 zuZihe_G7L4o!a~M{^bwQ{Ruvw;#vJg{dc_1x)#URgnv?-|E4zo1Kki98uYsV{X^&+ zTYOGis>1&}*Q@E5W-WSM8L}*F9m01Slv!v1lCNU!bn*vdO02D&w_nue{CM*?I37-b6T?YyCzGeZ zso^xTaHmtB5$rpsI};WJ`?`hTIg9fzit~H=?YYNBWO?!|{Mo_JG<4=UI6s%Mw(oi| zEP*$1@&@Rv_3KGl2Rh%6eIH&*&)?tty>0_u{CrV&E(RRSHWsn18d>xa7~=o^_tg)b)?Q~yNC7R zx;U@t^{)>%kh%@95jKSz<8C6ow%3!JL3az>3b(=Sa0lF3VqMhcUEsX4)_223o@epQ z?};;Y#h*RyWv#mpHpBg4OWXtGgJ4gb(=Flau^1krmWSgWAs@|JXHWMSJPuE!HlIvw zJ_SqJ*AjS|TAqn}mV6GL4=<3q7r}e?xyVbPdl_DVSHW|5uDYC8b^zUL@H+J29%LWT zy#a5+TjA|EpMm#XcxQC}Iqn_O=O{i`-MiH9!TaF@vTz?#e-!LHr~4Q_3HEiL!e{V# z_#)1IxtA})S7hPb=hwl$b2`6v-vs-G^K1QWuhQ!xX;VQA-6zn-Sj(h%| znIFPL*18|FwkJPU{knK z)TM)c=X7PDY_MNAkNe;M0Zw|(Z4KpMn^3-lt3X{b*mq7>2`UHsg{wkcHQ0AfR}HEM z`-St`UQg^hR|B?%nxR%)ZL$t*7q%yLJ3w97G3*pqkE{<3LPJuwGc2 zuj`*I_Oox?0CFJg7xpK0gWv!-FwEdJ?4ONXn|>eajBD$`q|dT=K0~N=J{!HY3RG|QbGq4ZM6h4DIn+l6`_Ad+!coC~;f|(0CfIlGSeOU% z!*OxPlPAE5;UuzfCsUsi>^rAB6;2EGb*IA_aAsIg!Y!m;6zn^vI}6SZ_6v6o_2OXP zxh1d^&JD{-xbvvb5B8nA04{`!!o?-rCDfM&`_5ek%V9;hJZ>eq3a$uOlDey4HLMA1 zlLG?mp_x!M=04`(aD4uX_L^rCPb>Ztn z?CbnK^exiQEoC+o?rprEZ;CzV-htbxZwv3ny+0HUEo;Gdj>2F^GKba6@K9?DSl?C>xb(PUxu$p-PiC9d>g)t`=0y( zehfd6x}V_}_%-|%r~e)P2+kDlPwKydedlz4!#}~k?qB#1iocj%iod9>D@~SxvSDjd zR}Qv;@}WXpMY0l94pm5<_u)NNrIu=O-j92(&RS|f;oS4Kti_&lI`>?Ywb(11_f(6u z*mJHn>3-d})B&CM=e=$hwvXE(>$;@u2s&}bd4G<*7hl_*sHI-qNZi3tpS3gqowdFp zDc1f>S9XpwU2ny?r4ei0|JJ_ts70@{-U{D1-fWWEY?`&cS!%O+YIE0M-6FJ%Gj+R# z-ASFPYZY3@?LqDdZ9-eJaP6qu2m8+HIzY!@zi@j|cMA5M({+X}!G7VoQg;jXo$C%g zpl9e6*PGlM_6dE+!u6%@7wkLNANGX-VPM>T4w4Z zV83u9s1FMEozoo*BZK|IjiMeM>^rAB1jYpWg&RvfF4%WYHy$Pg`-MA{dSbBeoNf|K z4)%3ZU}~H_XLOJA+PxPZ4A%aAIN2OGjk&|%aIiL~r#5H6Oqd0;!x1Ii9O@&3edly@ z;izE0a7R-g6YM+Z-?clIe3%^0uh(HPkG0GPowa^UI4=F;$rE5K-rDr^rAB8_o%8hhNwDvn zZYi7_?CX}nd2oKXAnro)BDgqQLKf~)>dS(C=XA?qMX+DE%c)le`_AcB!4<)N;jW~< zD%f{!HLQWP;p(_+$ZKI;SWoJ%gX`gjupw?Exe0CzH<7xV;TE_RboOs6v9@-`zV+>J z2iytzyWno{9ImbJ$=cdE*VZ2Ex~T7^zAt!A`~LiVGkJf!GaGQl+S(b{)>}yDb=GE& z)TZ~WH@)8n;6ZpOJY2#(Lj7p4@0{*2cs$rI+!NGK2K&xE1y92>;n}$7$mijO@FJ;u z30{U*!mB0RYt*j?`_Ad!fH#AE-COWByc6Dydyjk{J_sL@x{tu0pz5Bv-N1^=TzT`96OlnG_Y z!fj1mF4%WYw+)mJ_I2K$Ukkq`)@Frx(|fN-R)Wf*3R$?S)YXE0=XBMfMzCMFZK-Pp z`_AcVLG56_aCNA+3-+DUZ4WyH`-Q7Zy<@QN+)hw0&Ym;6`p^IxhMh~eM%23m`_Aba zLz7^?a80S31^do5hh3pXXc@N~xjVE9t;xdeLA__N@0_j;v<>zP*N(bj- zPH~;dF3>e}BXx86bN?LZPAxr3xY_ugti_&lx|z_6wb(1%bbN2tV$Zqd{64%A_GT^n zfbKbZesA4}we*F;`Mr2Q)?&{&o!`6nXD#*$=lA;ivKD*J>HKV90BfOPB#q>3-)z~!*rMtX2#7Ty>IVdW`k}r&uk(bK`nDi zxC!_pS&KdA=8{Lj(cu_U_Xa&b^Ej4T=9O@-;ODazd(P=zg5y|=y~6n!%<-(no^zM; znp*)Uu$B`+cNo2?a1v`d84BmUc|T&$xl_nf;k0l%S-3N(&kXjRTL24TQ8+8^Z1Nmf z9F~xUTS|RyuJgguK=Y4oTV&A#TVI`~z zSHxXOUInYe8dB$fN9=zeyp~$7F5zCrU&C7LId?6&4%Ub3$iiJueM7MCoNfbb4E77R ziTcK1-#MN8_ddkF?k2byZV9)>-A3LHcZ54h-Cb}u+!O9C;qIf}9PB%HKWu>q!hFi74!#F#vov0uabEA*+SwoA z$Kbr~8t(Haaz1n7-%-{b&i%}UpXtdjpqmAA;8)i28|Z!~|A0TkU!?AD_y_Ds;q?E) zf5Dl;`Hx?e3ih2V&AJSf4O^4CaT#^phr-&j|h= zwfO%Hqbr-7LM=5|>sD~gdhqXjh<^`6*MMs_gq=epQnw2<276MtCe%%#S!hn`Ox>=b zMO;gAH`pCof$O3+TgRJwq&D}2Hd$M@&AO<~cJXHW(1Gk2ud~)!?**NpGq@*f(>+<6 zU7%~$MQwJAH@icRtgSt-YiqCN+PWw7g5F{8xP8bz&^PoWb^T#q7!U@=?MLnpgTeu% z&hvZD;yj*HcOZBk&nJUHHw1>JcCFV9gW*u@(>?1(z(L?K;;imq7zv}o=r~h%NEk!v z#=){PjXX@SzZ^gNO8{P?e-MjD} zydOS@`;hzyJ`SIdx=-OVa4q%=XMP^OAe}RHU&2@LHGBi#CSA*Sapw2%LvXHeKT`h` z>^t`}`~ts*-{QR1@9;e+JK8TwnKB@Z809b$ z%He!1`(Yt!>vn_kcRs1FT-_oVZ_+=tf^?@{M{TKg=- z=cDsFp0}8HpM~>YJx1(1r}LQ<=do8fpP_pY`_AcnM($PY70zeaFxYc$XJ`bwgvKRY z6Y8eHzH`l>IqVu*kS$Z2yMZ(It#^l3&^qi9w*{sIKHYQAU{9~>1-*m)!kO-IZ`cR=guW$Q zKkEL$zH_>LVL-62bFCj3_KVw}90Ui114-Rr7y?7Xu(;t_+mjKXGY^7;LrFI>ZWK8h z4uLT+HnnSg;mmPiJn5XNn-C6-n@CQA$zckq^ID#FYM55SdA`Gfedmg698N9v3+J__ z2Yc?t=j1b+5oX5uoP1`p!fdi|K9eJYedlyOvpK31Ph|%fgKLRxQzWT;^QC3VPs^a?10< zAW|kHjZ{)=<%8(By64w6fB@IUjGRAA!>HR0-XbR9#{<4$cA+ho@w{*qH9kIwQ$vHv zbNlM543}RLz9G`!K~fo_5o$ne&t1>+=v>B0Tq0sT@pV6}GW*T=TvUWVYKJk50dW_- zO02=t;)95;d+JrjznLwI6yfffDh%`G%w05{zXezBdPjzWf#5Yhg1^~06}kne!2Os4 z!-U@GK}lau;=cxH61MMfzGs&z278*;Mtk4B}u+2!?ahfgmOs&=-x#{+)`qpQ5FGWn# zq@^HXGt2Z#7)fL4-C$~Et%H)ufs@M;SjHJd1OIO~89C>8YIMNQ*TAHz*5Q-nf|_{4 zr;MB!H(xMy3(K6^<4;fNy-MxX;A2U;oplStKG|Iq=^C(hHY6|lF>!aB)MAM9?37(93Zbo2>e7?2!EgWH=ijS=?PTzU+#WZFR9`hzLZL3s}RRk(s- zt_8->My-xWtjq1{Rzl5Qmgl=S9%|b;!+At1!yH(!j5e)Wg*n{&>M-WgapI*giO08% zhW9Vdge&%~Wf)(>6nglzHAwGxufw~6gUGOga^6~zy+dO#xIAVR!_>^RqK7$HU=BlS z9n8_gQg9Y@gV5fgEdur98Za6DvX}b>XD|zi-_Oz{f24eMDd-kV{r2T$8|BLx4 z8oQqV3(%<^!07Vcx`LkAQch)0l6J_bA5WIM1mY@x&T$?(PVjf@X@sTuT0j|{YN zu$;r*54z;7CC_;pvnD~mX%P0-Z(x|E^Ow^Fey zm{3O7AEsjeWa?GQQu1NLVo>;C2cOIA+mnRe^UvW462oEY;VYFEzt?iS!eTg@)M0cj zS>cAV%r4^NqcQj#E)}Yw&QX4sF`63_taw+F|j5z|$?xo_60v{zhi)$O9_b;P{}qDoIJgoVc=(T`pVTy_-he!W$Ie%uLX;(#f5;drHY*BXnA%u>a6f`&`iYp% zotGG!-=*!hYVs(q5$mctoU8k}SNmRSxH12tGgK(0bqW$S@ z?}WGbY4GQnry%M%tIJ+(9n$*Mfa`Cq1f#0V>|-ai3r$_qpqxrOXsxPabS<|_M+@T4 z;-lWHz*c^9mCbMem>%f>6HcCDn7-oB4DSSv*H1Fc<-2o`c~C#cfTb%OZeNnH5c{xQ z6o+$WO2G^nR##t4(a#7Nvao}R!*hH-JwxQfTla1M+FLY2O<{tQ6QfJ{>Tvpv`oEd1 z0fum_Q!K-rHPxnHwrl-MPVlc$Fp1~OFn9JD(H}pm{)^Gf)rV*G+!@BMxd*}itgab% zH&tr5Iai5e%=5-*_|TVK?}s;kNBjq@E~B~Q1QuI&S^ND+hrEl!q3nZ|j2x+DEht50 zxTEd*3l80}!Ieh8{jB%p1BmuFU>Mi@@5on9#Kc^1Ahtd@@h1)?o8Eyt)7iCboLqvg z>>BPkbNVHRFrB;!f8?~S>kpl2Ha7awrLtZc4q4s8=-LxD6G@C5<9NvUiNo;=pZ?hs z!crCBc0~S*aekN%UkiQ-F09yXKW;+`kTDKo_A&09CMKuDSFZzv`*%z8<8GyZS$A0G zfSCu%R+A+a6hFbb89lmXTEAVcR zvCqv*0b_paS`eT}=iD{;*L<10)Pl_sk&MlPiQmy}s|gIFQ+7-+w;!<8`j8IaxoSYC zOYC{t*L+!BeFu76SU-oQw4nMsT8_~vIObrODJc4R?o|Dkbm;Z@1K8}x&R6K>7UcTa zmSMWa^8~NY+t?iao(_kpKLSl-EdHlGhekXFGA8W))0Zw`r!<^)`z|AA-SQF?5j339 zwKp)!cFYmYTJia%zP>-yKf})Z)rlo&YrrIiQ9agR?zMV`xtJMxQx!VyX7`r9Y#yMe z3|rr{F}gycW+KDyqaBBi!m&=Zc)QmE<+{%zIr~Jh5lgeN@yXf+)z!H&x>}Ua+csYc zW$a1y8wwS2+5OPe!UdJox;i?!4Z!3((&3DzGlJZCd+Y}Kr+{A*7cuekhq>tyL+QRt zhaOLA1(=pYEtd)NDWGD?=Fn-aNimbdatw z{^~IV!McFh(wPVsl!w6K?(-SuMoTWWa)}MSci}iZhv)|`HY48K`cxSBVgZ~l#WGI& zj#1+m*w6=}Oz|Z?`-HL+zw*8gN{2xY7r@$1Pe#tG^M@(Tcu)GvEfYN5!5N%h^;+08 zBN_VdTMX?~SbGjUK16*r_oS~8CisZC$H1A7^2BA+NEn;D7#3@=%;kD{bm7c#JU(m% z=G0%F?9}rHT>T<}MAP{#vm@FkB5um_=XWZ5%MaJPOI^yIhmONO${ zsPTI#67W)w}+V*!uODM(k!{fQvtPwmlMd-Mz*i zeUD(|T>Lf^DFv>=F}-5UN3Vp){r-x-B_sxBws-T_PGaNd^L#xt|N9vH%!Qp86;wei z+lC2tr$$2)`WxSJFdOqfJT;K=nlbp4-UHZ>4abNhaoPgc1JTeZtebD4!7>AK< z)%d|lhp^(;M+nOm8bEJ$B;0uIJ^zXktIPaAJ=N>69{;$#2lKz2NnF~#ldoK#2wi_Z z1K0NQnR&-&o}=FX(#8F5NZ|voh7&!!5%zNiCc~MVn!#>;z%XSmr%}1zbn#+OIefKd zyO3(vw$B%xx%2XyfqJqn!^F8bQ2579_yx0m_&5IvL~PIi{^jq>q3og;AkCU(vNMiT z_u7X#PBK=)_WOSzWG>zS?SWIEUu%CzKeT7$thXA4hG=!-d#_1hKV+52-TNbes_hJD zxa}ht@daa;K{a2f#b(#>A)B+Xafe$7jYU~N!O92Tm3Rp%?y@#hkw>V#mfd)oL@`#I zI-ES`mIE~OAoPjq2Cc=cE^ZF_{f8!bYE>fm@(YI#>%M@o{*H{UW1nlOpo_YW2VTtq z&&*yEFD|LVeREAk`LjH{<-}tcoxy`p*sJ4sp7joFasEca)@2o#@_q^AtKI`oS2-}u zCqF*AO9=7M2R>Mi{xhO=%0)2Z#SGXr@gcC9<-{;ed`Bd0vlbt`pcHfcC`}CP@C1pH zOW_FL%OLwI%M72TgO25_!recf!Vdq4BzF3}<`1?`f_~2~0+(9WKc^)oq41(z)T6m& zn0Lo15bT~U+&(uFT7I4fmCRQ%IZ5?pOQdki24#19Vu`%7LbZl%go{HQq}I)aD^ngZ zOhK6rGVr%WzkomHkiJ9c^kD;`|0W*hCeMN4$62Pq#t0G9&N!6NUOR{ASsMp;%6{fY#Ik3~ zkdp(^@~hD(^wKAXht@*EqIM0@e@!3^Rp{d9FS^I9Q`Ml?lhYsphHckbTSxhcfjQM9-ISLgi>QEdBnPf3@{K!z5=7LOXdA zQNsZn%z1Y(ksUFOFyX~RLzgc8s@beP+`EjGl`3g`ZxGDj4}}jmJq7PxPh#eM+Nc0T zd&tvEXA~2gqBaw2XIPMadzm)e?qLElWTjEam8-%Ss9Rg*yn93c3)eq{Z&Y9c%+6*Q78BcnSB4Sv#(){gnraM*u8 z@v6;_wDPJZggPm}sflG?@w`zpw5L;w!W*R5gpwxmQT1I~w~0ymso>eKaK;{IW?K zMfk*evi;3t>Ew)H9jN~>hG7zPTae@!f9mAvrxee=%km=(dW_rlv?dm>P1YO^|Ye1yw11mxDL#dGZ2dBB4C>xW6#R=C#c@P26uShOij;rCx!PF?KU1! zfjjdgp+zIhd==H}&U@D2@{t9U{A{;V_ihG?@5^MvT1mKcuo)wVz`i5LCw0^Zg>6)= z@!;A?9d9PouV3=SXZ)6XI=9RriMn|k{baxuPbEssCH3}Xt}8NC1%PB z3W$}y{dxY)@npcGF;Hcd05l-)+5}9$Wk(3gyK0m|$P@8Bj9?QYZ{@DyO{p5mw z>{&fYt}aw|pWQprxWx952KyO?64hjKDp!f_l#$douL{CcGLd&KC7Mh%QiEn1?hKP` zkU~!q)zChMMN^h$1Igzn%6RH}9;CUV5!@#2!Z3g8S`!nKskn>YP`>6D@%6NR9hI~m zY<$Dkd;c)v+E>RpZ@5qRi?Ej{vEwomM7rFY*PtO24mtEB1VBsFNwjFMv6~jS0RUgN z{``m8Gsv0RkQ4x21)T(6S+0)D{Hbe+?Mc6M5VSmqA;ojTt!w>Z#P+0!m^=T4;nvxT zG6~>Z9Kp!p*4h3rVqId!<-ah0YJ*}%YzOi5`;Tw0sM zoAcF{jQykyojk1>=F{XPG-~P*T(d@jI{kXQAgs`XcldKUsoW(655`9@Yni)0uYav2 zxOV3aPxDDSsX6rncyu|9VQ!4^K~B%A@lUl1)ack|K|{nBUgDK>GPOt&#uUdf%sn2T zwiVTO#CsHX-fOhpgEb%697(rvIDK1G+xbssyYYL_?9A>h0oQtvo~S0nWyJo;v3L(` z)!DsH{C-h8w+3Hqmq=B`-2e~eZk~Fnx0sY(Ckg9+?}y^L--vz^j$#IDI04o#*eh(d zjv^H;--DFja>VtzT@n(GA@bb~rUPaJg-Ja^t-PhA$He!5Y-G>D8-ly&rB@9uVbI+$ zGGq?m_fE4>@?S<4iT0nPmszHwXE(aPnw4X}!;81*=L=!)yfpIV`*)yo&jQ9jQ#H;b zbnPU5c5+X{u%l^$!}V?Un?!Rl-dhqn#Z6@x?m5`w-Ntj@(J0)vGmZ38?f_c`CNfO> zUL(3qRM+DAN4&nUk{6)*loZ1}GSQ}Qit1zk$tVwb0=nJ|WSBNlJ<3p2*Ag=_6}0`v z8uL@Pex{SZw4VTvlk9mRu33$~uf_OKY0zfg?(B5i=_N%QG0G{Ig0Q2 z4&XSydHDpw-f%g2Y2*{|IFj{`xUS`~XgI@k>5k;Cie$lAPFG_FIU z8j+ZJd1)|D*Ehg=PH#FnMKrE$zsL2{vIJ#{YBFNxPt1#Bb-q?3@L0)?ODG!qd{J#j z%*3qiu$kJi=Cqh8xceAv`#p9KOBZxNRBsV8?=>xLD-JcE7SE}a{{;~4xRe=Jz>t|} za`$M*jW0G)KJy>g-fLS?+bfczEb`Bx-~Orn?2de`=hG^YGaByNdXY~ooe9^x@5G0i z6maNx1e1?-j15C^r@U#)oCpVoJ^p&pr9l?wKqVVS4V7by2RrnsY*30mmj zNL(CxlV9{AnM_Mmg0^TC>*xH(l%?rxYDw!rGOV)-m%VQ81bE` zLUbqc=gXlixu3-OpG882#opu@av1cRzJg&YEKSfU4}JVtlr592csOHxKgjitDs*??1a~@ z$$<9!RB|oSf;)9KFpR0&K1x;ZDZXpjS!$eRC84@=9@zh2F&UZlMO1gnV;I~NctB$Dd_x@PRV)g`qPl+IR7 z$0v7JQ0i*$iHtlN%zo@bE^~Sc?v7u>*rR-KBvMZMgy+Y`P&4xeksqmS;JIxo**>BR zczIQPO}c-`ocJm9qW` z+MiAtPtstoGfaomcC=DMOQ=d`@KYbiUBMrHzmtDAAnmw*D`XnRc9jFv+sNB+cqNJ8&MVe(p+5zOj|M zJk*b@at#+IHgpr)MX@TsAb}az65~j;Hq8Wg?p35}A10H>>c;Wu*!hH7wh|0H9>p-+ zbGf+6mt0Rcg47q!2=2Meozr6ELv~F60ahDfClge@g6WX0?QrjLu7nS%vG51DqG4ax zSN&&Kn-BTv#dpv#p~#+F|GB}54UcC&r1$mjApdf`eZpON*f@!;5pfx3_XotA!68t_ zzWXocuUb?01489(Fw71a#N+BJxtB#%^wW3Ty=Wy!_j*7WtA@ZZy)X7!+KO@&;url7`>Bh7hm)Q^?Im`}y4?vVdkZ zTL<{VNMwF*=$AH^kes!Q+&j6Up37X`a~*{bc#G1fcQmMf&LqYqCXvNu9)jJCnV>qJ zl~cLv8k(5b&gk0fA44QxNFvX!tmJ2)OfVykWsW>~jkH&0pr{M09VYIIAumUH5R>Y% z!1>!*p!#?3iizm1*O11(i60j21+xS7h|(5+aCl2LXbfTRDPl%^_Y~)u5f8)3grn-j z(D7A-mkUJ=}3!+V{RraYs6dJ1t_E zKjY%&>duWf0lX8+JKB%Asfc1lXFE(?oBN_F0)URkKO&C%H&AGLHr4!&d?RT2{^< zMy$*6=WufV&}lH|$UPpH;ojq>`1-(=M|ufyPQkqw{9(l7>Wksd1()I8LH;n}Iqi$# z_D5xi>UA$iyOZWe?$~hqqy8}BKC7L4RnkdEbZ#pgs^v1=dv5CtRkB0Xog6mO>92e4 zA4Ys%cC%9@*Nt>1KOTv-<=%zGYe$w^fo3@E!cyA9$>*Vx#MiqgfrU9Aj;bhQ_Cql< z-t!t&r*;(^^1_+KMr;t)`3{F3D_!6#KbEnbdlNOgU!#UJ)?qhJ>yrh|^};uI9N#83T&Vd? zSbbg}ZqIRnYR2rlc_4hw$jLu0jTy|cCHESK6Q|uUajPbw*|Tm@Qc}k;8_y#^@zW^2o@ESNH+2EL*v-~S zURs5r^DBC(_Noim)TFa~zA#JZGC2*_=r4p>!@?Ok>0`oB-~$(QOozt$6+7_#WpTla z%5>=2lqvV%>Iz8FczK%DJ%_ z_c4W7epoEIroson1+if97dLo4V>82WdjfluW61%w2Y_Kx18+mO8_XEBg<-foilvo7 zWRA^MfScG7v0vswQX`*XF4){aRjvE*UReW7OD&$1pRfijx;+52-U6&!Q>{? zs91wvvKxqvJRL&@U)%wvHuNK;JLkiS8LS*}zfIDjlX$J*D){B*Lw;-c0KRq%BhqIt zfaN#Ye4g8rb2?%Xc~esKes+B#pUWJwx{Ry`)!=4^1F;W>uL~9?r9kWKv7qA9cK)0A zQB3@FOl?4qhKcH{AC<9db)ofJ_9sEflNn${brJtk)M$p`_S<|tWkuklmczRyd-&wE z?fmOoS%z!R1*zQx-y;qNejdj2%iGTHFw2QGdJ8sgV1K& zy(1d4cZww6o-hV$LJk1<(G4DHVSTu${u&y-Z!_+{p%kl_6G{H+9Skn-E(2Px-QfBP z)`ugV8<6wt6L^=`Vyt6kh23lgRcL^@!+{1%fXBu8j6I*$oJDriPT+EL7Gs5QO?`ru zDzqQ%4qHOP!KvSjiQ8Fp#cm58zxFIv+dYea?ngBsheyFjUg2Q8qkuW%izbsQ176Bg2|2;0R%OpCOVu^1!e;;#|6vfwv96$|^ zfEWFD03~|n|Fma}+ioyYXBNZsHLk?##h_L6#x6cv-&mhRH6yk09narmH3v%hXCj@! z=&{RSJ+TR-y>?}oEpKy?nW;AZ=Hq+J#qzN5!4eO!V0AK_x2Fhb#7t$Fd!KVqRnbOV zKkN)vHs%H|LS_$m(jE)zzmr26~ zau_V@+eM7<>y4x^VgVjicANty8xyfZiXa1-VY%j4MdtFQTTl!=D>gIK2X zP9BOhyha_7dXGiuZ>p~_G$v*Tr9fw^EHK&)XKdc4uo{irjvPMk`h{)RI%TtITti)_ zsGp>`y9f+?&D!&2=s9F6LpTg6{e{UMT2rThW!FcF7}ex0;G7OSr@f2Lp(7rR)Zr2D zupMuVc*z~T!WyYGxMOWR;H`81pSluaR)Baj)}Fp}y)=jfN1wCywBzCElfnsyN7LG{ zh_~xNl5wfM!j}XXLCt{AilUfvuwZHg+TVMJ>Xx~R^)ogAsk_e!zfTwK3$N!x_t%jO zGs%Aj`Y^!+f3I7LCCX0)+SPaMTL&(Ozm@^GWiIiEHF>QM!mqpklCqevUG8iq*zITs;R}rOMj*|9_#d=mskvG2?eQFO2()~wu1n9rR}Trl;7EBJ2E zwU}jI&Gkj6W=Yc@-yfqswrwCZ?!=NiN2-HoHMY=uHd{C5zI$@tVLvXggX z$7Rz9owsph)KCj>Uevqs<~n<)wn$!#42^f=-g_FTebH&~ev%e%?CVGTj`=ds{7y6@ zhg(;_+mZ}Fs212a5AX%ty88I~L^NaFIJ_}lmeTe}fXcOs`~=&4Fn6;Oe7cpby$cS7 zqY)b0C@&vbs$rw3uXkSwKh7|pKgCHKS`K7&>1l^D_c(mOQHorW4y95<_=dyP`QkUk z&EsPJWe?Vy0B(22zy_5-f@=?VTopVka5#K9>^98$Yh0?rvuJ5g4PLd5q}1D+_%Azr zVC&@1gv(M%sIKkI=;GF~R~|9t=Lynb6i5|t>)67;+o*Cu4W4*{q|THp@^pSKhEMi2 z5q_eYdBR8b?U-9v-*LiDSX7@5%}>F4Ze87JM>iuU^JodBw)|dgmuSy8VzkFjENAt; z35-45w}7abtLj8=p3rqVZO45J;4)6NzGT<%G4{HxUkNV5)n$^zBkxQ#v|s07LUMJ< z%YA0%BGhFsC7TV&w#ZW9;SvMpZT&<9YY+FH%e{At=j-+Fci6t}-3|{8U`VJnGp_37 z7tGyZLCRq&p)8DiIYNR^cSnSnxvb2-Q~$}I|FbTkKV~A-+sf9lvAuUtP4F8;dmg6- zOUxjSRxcyNHoOyLkDdtOTy`$Bhh1Z87h)#usweT_Q!+Wz#!Q&(IT1dVW&3jbs&9yy z^HUrdo4LIQ;})dD7~25eS^xD+tp4de;Px=2iTWv*sf^@}8gk2?+rz+RlCSvk4j7Ju!z1~B^(S!O`bWf%1wSOdgO`R2{(9@@zP}$v?qIE>JFJ}` zM{?iaxlDAMGMO_>&wf|9$6pNht$)*=#biN)q#h!V8-9LT(Skg@d=4IF#x7LaneKKvE}41^1LaS({y1d$^1M3_3khv4!{Z zRr+6y@A>nLoSh;$SGG^6FVJq{U46qcPlvPbU&HeP8OCJwH)>^Ij9_T&JhdwRCyp<2rVaJ|&o>SEjsyU(;b_o-M;j+pc<~1ZwM0$+4r5kY6apmca8rMX5Nn;ZbjErPawWj zxx?u>dL*`VA~8$}!0XMfaH8EIhUx1rES7VqlC6QrO@D%3jW~fUmgqVBu#O-Dq{kE5 z=4D_^lPesQcbJi5WcUQNG@n2UAv)CK=oIpea0F415GI_JnFZEgWqTOa8Mo7h+=+5(^|?f{{@5qsn!q?BO4SVROW-k#gjoxkDqD?6 z$9L4AJyS{R?D4|MB|7AF+zcMt%>uW+JzkXa#yj_)u;jS<4I^7oV z*rs^TEW7U_hPzI=_AGIBw0`w;9@Dq;mpzjMk+~?3`ZS=2I*?vn|3WXqu1EA1Dd}Je ztrz|~o=1F4hqtK%JcW?S_1t*o#$ox#W$@h0y}Wsgotg9EPaH;P`ZGD3#))H;$4ya< z>Fhe*_cK0(SeLK{PDtOsaf!$ixhMrSY3NhSs+E- zWprmnki*dtlEl#YPlO}6_>WHl$`W zS$wOJuQAdQ7WBlybrae8n5xSn^!2F@edpXDydn21aeCc-e#=N7xGFFbF0a;SEoJh> z)yTUhi#BukhOLOxC*Np25LEc#u-8Kh7M8M%eCA>lB9l$4?-+^ia_Jz{mGp$pI|Jam zWm3?=hP9d7S6THagvdDUMotcwgShCMtLZxUUB!e}kwG+|bEy$^&H!JfiXFz@F7-sC;zSF>`r-;*N1(@ysm*H-29RC;Z&n#XhT*O z{r%He?B*_KGP!wRT@a;B4(3ZiISbb2?~!T9X}K@0JIn@Ka>R$U*>+KIebx^`CG`W) zde7S2SAT*|>3g7M`g`6hjnHmf55HA#5;HRPCG^YNdCvsN@aVv~FySblxtr_H&_nyj z4Z;e9>##d%)kH&~qwutYsIEnP<)VagC)MowQn?LNsKu;=<9hUu&S znKqaUYg*M9hWjnv$g@(!nD`0s(snDj_trcZf0ylVG0v@`2G0}Xm%BQ#)P?7XVQ^@JN6ZO@HuZhot&cwC<$#_`Kf@eN!GUL)HTaK))H{fUH@56TbUE(bassclgN5S

+nCR#R4?fbll;s2c~c5dBDUc0)4Xz_yk!-rWXXioV$s+dSRW z56##tL(8qsz>51vkU~-!L|&>Q(CxDz_YxaFg2EgGuV&G^w(Z6aO^hcGJZ-Bxy0MVx z^pk>_a%>!KuggUlD}Cvdr3bO^{t09dC=$dJ<`Z8tK7f(WSzX-yFsCb#d@{3_cd~aS z!QBtN)~`gMP>%LK`W{o@xs$<`>Y%^966tdGJeXw2>f-K)vhk^;#*X#%^3sC{?taMK zR~1A|QPKcme!Bv}-BXy~PXz(Dmy`9Y<>8*G>>g!RlZ@`&D4^r=$6}XA zKKXRo7(w$5W70}aL6nQK>-}wf4$^pBK%ep2iS3#fM~;2;zJ6zSF_EvV0A-Zev9H;< z8of8$O1G(fz|=&2?~SWXY*$TCBbHbyz%^y8pSeuVFKseS9oxSwLBbl zkM&RQnL#L5V=Jw?V<4W}<_7a~TLe!Z42D$(3Q)C@%@Zt-J))jd8MM5%Bc@{f983*d zDO8-bh%^Wi^+T4LFh0ceeo@EwZJ|?-Eyf0JR)8CidJ6{|%q0yI<>C4o_FSGY)exyB z?5B5a{_1euq6zf8brM#eTTI5RR)tAp*}1p{=Aj`LrF4Z~i9_XfE5bN(sxV>Ca`JYk zim1<=or@;JrDz#hO4q6BVLrF*$fRR?g&UhqNWQr$40mVeqM#xh<-aVY^;T@g5^`cl zCE0A@t>p)Z^hv64qZ2z9$;We0XM7?3qqQ4*Y(Jj-@bjEdLdpiZpHqZ&{aD7UY!Olk zDWtb%4Z(fSza}J~s1Osb`@u3&5$a~MevY5N8f|#8ogO}+9ZQ`LNwV~gaLcQ)P;P}H zG^%9hbnN6o$bQfP`qsz(xPB7&pu&>RCgBAFIO1h%bl&@ zFs0W5;SNhUyhRaqAa=govyD-;AS41qNQ_DW?(t}YW#TzY~(JY>T8j(xHXncXjO+-0@%4&R~LaiM^(`2Gn}x%DN{(- zJUQaAtTq{AssU9#vvV;_n1(dp9HU2E-iZzT=ub+w4kb+BGopR426Ss@{k(DTN;F@o zj4pShu%^SYu=feH;ukuIOq7C+>euf$0P;3CJQdQwvuYb$Y^tK{jeU&5Jf+s+(9Iibj z)@Eeas58X4Mjgntr{GiuDlspk+X}B@6+tHCx-Vx5SKEO)_y zpqDP?Xw%luutYZP9&#%xq>iDB4NjeKFjAq(6+fHdyvLh1As3A`DMU3IBhXzUqewW~roG`W@kd zD>sGQ`XTo&JVhdv?6?;qEE}alaPPu4qXN<1mHp{!ZatK}^O1Uu&$f2MME7NP(Kkae zLG0a=`(AKAA_=y~-L&V=$s)M#1zb7iHED46XivLm8I3}&9PXQfhUk7e<>X@Ch7q?2 z?wi8wNs1`3M3%l?H5j+tb`dO*tmg+Aguz=g&V%qyHpa$Srcgr*`qKuF2jk7lQ+SvX z!Q1*G9VRxO10jdUGyD9Dg_)F<&J7gqIT)Yg{!yrPtb{)yG!?eBo(4a2Stfq*AT+@1 z0+Mfih3(N80F52aflay&uw%+ekaCpO)$itbl=0b`9s})hr`alSz@rPi@KdTLB zpJ4YNJv$W?YiC1Ww%5luoIM7bQsnq=mqtU$(l$V?WaXfdBT-JM938oA9Ijt885ZtL z;ZNT)623Tk9`rxOt}k((G^xKlfzDiZUOwmjgwZ#fxwO$$mY7W`w6 zxCglHml?y1AGUx$ZZF#dEW=@r@2|$?v}GCQc;X_UvNo9v-X{sU%qJ6R$M$RIn4awo zojzdjgJkmhj!wX39DiKIyMh$)x;Ysq3|r*D=;~D1uKeX6oBJu z2-~g!-JWkC{AUd~7QxPi>`o&@jChS!3H9*8Z(-!EZVXS7=#Bx)f+f0 zN@2hAefr)W>CYZXKa$tRjng&~X2w_f-$mbG>O@Dtg=g)Vx!}fFeOMvUo<59!S0Vnd z7~|Gk##!zlzMN?lT$7IPv)G$->5#^;cui&*@gmAjnAZ^v7vEEabKTgOH(E9U4ZpFU-h5XF-{J6qIJ?%0Xd3Sg zx1Cgl-3R`i14tT6k$Wv!p#}`>-;i|c0iZns%VwO4Or>Ueq?dl zJo3wUC88G7gtG(&%v`h-x}sZmE9s|US1}CAk``O%k;*Gth3;R5!ijBcE}^kM32mNM zLEl+iiVgMdAr?JaK(2kS1puxA*U$fVE)k_CMal#%AbVz&3%R)jHz(QqR+5wrn@wg{ zFDJM;372^~!(S-VY(V0jqMu>lD3ozx~0c-*<*+T1W^Gw=K16!I`J8gOmq<|I1b%0Y^cE-BUD{I8sZJ1#A|E#UHa z4bt(J1IZm1m-)6d1tw|k6@H`C0GAQkf2Q`7?5FeQpTbg(rb5lUOkwAYkNgG2sxaz1 z>mRN?S!0$%t6FJd{%SRXnfWOogG> zi|mtChJ%?mLndMTtt>fuAFO6`YCR=cEb1pa(7YmyXdBP#G zY=4yatT_~7LrYE@g^T}vS5J-o&!6c~_-p|@f8P6_^UL4EoL=EF3csN@_JrMu&A><} z0oFNt{l&Pvo=x{=vT`I(=Mj6SCc?7gA^$K~W*qfXJBNN2-i;Ypyd}a*1IW3&NTEuq zG)%qB<_X^N3n;#24qf%S7>k*Ckr=dSF=@Z(laS1nhGE7N{;_8=KbOAWQNWzb5g(S5 zhFh!%Nm&_an)82W?kn3|T5Ah4TiDw_D5!uPoavb>oFMhM);)ho^bb_6lhrI37uq|SEFH5WU%ay zGx<`!fptluw+_D4VCYrE_FeRU_nA`2FGTJs^4QrDZ9-VoE1dgj8O&%N3^SGnF>>0E z8X=+da)yyMG9%seAU!4BI0xNZ+k$FG+{Q-kGa%n-odQSV4dFC#pI$G!9~K?~NM_iT*3Yv} z5WcJ&#C;L{?uw6vC|94z#Nl@Rap=vWyXb=1S8TCvF7c)Q1&DT=4_{%nP$`Z5t&cd5 ziRjkrD`?xa``FC!t^5gJ4ua7z8U|Zg!jkKDj2!N`QhcWH)imSa%DiI09T(R>=8^kA zLR$zd7Jc`{^-s8?DpDR*hgKQnU^(-O!KLaT=sk50kZY?1u^U+*j*iHr9-MDLZtHep zpC`KTSJ1I=K}HE!6KF^J#P0_upI83F^kvVQca@;w z_neCD>DFmL#^Z~yN3QQqf1VZ#&8O`L4IDY#dW+`u6cW?jBAESp1i`JhaNq0(Rj2R< zwS21g6@P!qd4uNmBOT{o6;csh0#uMja{H0E-#591$q+B3alwdNsU-LNChm7qJDc)& z*ENpTuMvGW%Kc7?+aF~YsY^_#epFxCkV10%qqyHd-9E2HY&vqY{)%)e$^8au#fL1a zC7=TJJl4Y=wk{)@gn0zdFcO||J`Q#)XXmtb@F!~Rfh{PqN*yb+UP}x~4kbLWD7dNZ zFz{4l>verGv$WJ;>&!*WdJj`lM^?GfDDamFW_vP+$a|PVY-)&vOO|NBYigkk)7Njs z9BR>oO-;cJbLNu}!yB=z z2myg9st|VA5*XCn&DVEenefM>5j|)Sl@ziHYw$cxXdb*R+&n7+{+jWPkBnI6DzBFM zk@wA^-@cz%LQ(>|LgZ1%li$oR=rOi45rcS;8TFz&Ii@q(Jra7r3{ z@C$*C1?+o)I1Urlim>wI3e1^usZ>swb3Yv(-E;PzJ5l$-`&0?v14RaI#at)Pf@w#4 zz=D}YU?^1x+KnKy-Um&-MZFGkN5KPDU{;}S@JCiJsP-uWS#mqTo`>vRCg0=-B{O&& zdfJ$WO`Nm@dT8c?As-8Xoai?u_cyS6i>iB!HF0XJnPksf+n_B=1*Y5_M z3T!{*)};z)dU!4M)9(PLVwD81l`Rz-&d&fI_sYOp1-4(bf3`BJ*Ah|#&IqviI!Vy> zM1fGrYXx||sSMni`@b2DRr$c?GP}3*r7LM>KKRXqW3HHDfN9c=Ds!*Dn^k+ z^8pA1CV8OWHg;e>1OLtH3$G-@TxH z=#rot&aex!HhB!z2!crM{)2=rQ)sYf5F0<-7@K{t187$Ukn*QW1bxL= z{-e_XGY=;pRml_F7!${#DqW1l;S%`G#yZe7YYExENP|##{eN*tKF_9%U*{m}@LibQ zJqP$CPaWnT+5xl%1{Zrnq7U$aTvHTPj&5YUxxo z;X*kbHipDr37!y!YKQoh8y7*nu>0W5Q?^dBGh+zKRysz%jqk!ne}74AIXs~)Er=2p~Hgw5YiceS6# z{HuNv-PM{x_cm{6+Svhe?wnzmtA{iZ;a5nn{nm@g)O;o!q#Xs1ru#vqBv}}&KrxJb z=v36-u#m2MbO{?`(o5iQj$mhs4|Fo<4@Qpkp8B;1?%r6>Ju)WD;VIq z5E|ylK(ms&45L{Uhw^py)3c9l!Q>A~k*^P{30HS5fDK#QLGH^YhN;YtK?R?V(A9+- zv4iV7iLXOQ{!|Blcw~GlNLhNBVYoHn_dP!FvHbzNfR*0?w<4#Ptmm~{{{&w6s=|ovEW@pJ2e$@5r%^gQJ>w3*t#xz9esE(j zOv0^sGnTZ0RfiPeqEJ>2_Z{T$+)%hQV2%ByZ?^&W9fVuExZyB^luNe|-2O6@c!ua9rp1_Tb_5M@HB7;*r!=)q1OWRf92FNnp8py3ZlgMuD z5icQMm*mz!xN$i1s1x~Cx0G*RAi94Z83JF;VC8V@8-rt<$XCI;`Hk;&Np5|E`@WMa zE6qD_Hl3VRZYbow?_`U9r)!ib4!0Jo;1?w%cr_Q&$@6-8!a1UGef-^b0Zgq>)uuxF zpx0>p+Oy%r6KomT{$nt)>!u=X4QJ~%TpwCbC=>j8l19pP)(W{k{8&5^HH&nmpBH^Q zklj%~VYle_fz~e+9ueu9R>9`0Tt6EWU#o8{Nhf3V7YMn2?u+5BoxXH6*vZ0@D~O5b zqx#cOqFEtrar8PCnH|P+5Y-?{q-P5aRQkitphkw_u0h|6DLjFQxixH-kh=z_?2AL` z_98iZO0bnmjl9h$opd`qNElxv1H*6JVdQXQwPY&6YZv*s%}ZX$U8j99+<5Lw7jZ-p zh7__fze8pvS`<-8$6fEh7WXsfYgML`6VFu(Dv=`8vt!?Gxa;EGPbL0Df#`QNls*W! z>w+5_L7^Ss#KI|j{p0|W8yh-tf#}Qab@a7?L-4nF2iSalD!(E_bRRaCg^t_UH^d`L zCZg2?*3%cu#^U2*>cPC)Y5dNo5oGZ+Ss3oc#t%2fnnMI&*6hjrS0^J#Zj5o6&3WGB zgW)`$3}50ehN~-ezc*>Chw&N)O8lkktER5#_dwRs7Hed1%3Zj5nt_50RMEOGJ>&Ku$0jZ9C5~k*6i$%vfzt!j;INhK@4<3o6_5K#T+r|rQdQoN z8>@2D6VR;6b@cm)BiPfQlBDY@KVg8zLb&s-D)jvLkkQ4BpEW&_q?3=IaKx~MkQ=L9 zW^AT69Cwv37&Aixa$}6EE9`(bJgjXg@E9log(GEQU^*Lz&knCdw$IklZo5BYt=qg| zq@;~N-#`MMu#tr?^w>D$#_H)f(RpzY6C4kcfZSN+GR+f}Mc?H*^5y@`M z9NmlY3&K1|uCCjr-BdITqhH94!b$1Zydz6C3Z3wDn0)9nD3@mM4q10@QX?fp>1^3i zxX!QVe4F<`SgV-^tG09lT+)=ud!z0qQ(pSMv|jLVJUK!Rnr2kmUHG02eph+!-f47lNF-hVA(w#P zRSvLIW+H^yzMwiOz@G;;1CynHG-OHoOx)aB(y};8afp$GqGA zhs>r!hTKSGBpJRt0fh~Ur*)Yu>2syFc+g|P4rC(aDY(c*nY^n`5s-nttRJP|dz1=U z6;?n%U+_Aw3s1pjW8X^8s8XrT^-jS%w?CDxo?K19*nmv=%O>=^b{aiK|Evfy z&{yq?MwDt3NOwGZSOk5+*jPNR3AND+q#F*N6v5blao8OA4T&yIqc>|(uz9rntKK5TGWgVy%Ayz#$olE6gqjSK5_lU6%xkbg!NL{IL~zXgm*@gZ!1&i zwq>1&%~sdQ<%ik+hqPb^GO1EK+U)rdx@hRBRt)rIe$9^F9yNrH$|`H+i_twSdvBgD zw@unE-koJb&+gx!&T-8~JvX+&$rFW`hw&3>TtWE7rqE_K1|*Ch_>IuVGELF(;VCpS ztta6(LeSTvC5VWGt%go7$rp9}!1m$>XVe^XH7Z&DDqfF2bFfP2CNln& ziU&OV^UoRD=p)LqAkSp^^1YoUW7TBD?DHC;`wvsF;mtqj$093!?Y&5hmsNL;lUMq8 zmBgg)Aoe?nr22NLIPLaNWF`^LvAd{*$?iUkl$$;_kPJJpiI|vbN1j(n#rFQ+QN`Q; zoDJ>^oGPDFsVDJX+}W~-{eGcg6)v9i^}|2oiF~go!*iy}-*h&RxHB1qQhX|1^KxKu z*0&GHXoN7HC%JmEZ$VS#OSIZZtf&BDIQx94Rc%)MxThTsZ#k#se*2WkQ{}dzZ~VFX zdDhp7?aswzJ?wCGs1Wn;w-1{&0?)bJ8@s&h>;!-NnQO{2qtVIoT^YZ`RPG3Dv#vLO zUS#j+KTw3t4263E{mNIiT{ljCX0(#z-m}>_%(4pU7RNcA@9%^^dkE_)yoPz%bFo3M zd&s=aPA7N`E7pd}R^5%1dzQD6T5Oy6XhJlDFtTaCPF+j-bOSg7COn9dJQ zI5$stA|B=@ri(YH727}VkJZtXf0)1ZwfQ8S}B{E+fmDz7)D`oiIR_go8 zVEUEW3e+dh0cZINHM8)08<$S&sofvv(3;NM5&Yf;)&`c9H5HG@IpV0#*08|ZK(0QQ z>yLEItf^$$-TLANhfJp;_PrFxDC%=z4e!m0`eKt#Dx!`**`lQMUTEju;siP(?1|$DnRlyNU^pJ@t!zzX+q&Z8jh+-74_7bDjd=n(Av>IrK+m=Q zT1*yr^NgZi7}gZ;%AP=XjoVy2sJA+X*TlThaw#azJoGF~%*o@ltEc%+^>hVupM{!BkRN{49YIG$$vAFexZh!-~t zHQ>>?1Z0liyT}~BJczG{?RGx}Kbo?fquWm^LDscopB+N?bjrcuF-JdnFDJg_-hCm$8mvl7kP{{Xm=yx>?jzkcPYFbE)F-` zn?^f+jF6t2@Qr7}*N5_U{uUeDbymbGwBxNGAWDhWay1~zdB7UH+v5_fwTAyX)unuSVIaT;F z*|wA!Wj>xs`S}rF>fz@oDa>@>bh5H%G@u--Y5Z?Df3lpJ^i+e1O#6rruuS3kOb52^ z52y8fhK5On_dAmJml=t7UuN;AFZdj=b4~sXDR~Pu*B^baGS5Qdn7;X6d0&THe3`8I zfZBAm=6%6$Qy&65CgE-H?Dc(kCd+FH(`R@d6Z`fPhRhIoJG}F;C(oQCvl#t%+02j` z0+ZF^OK;c@6#8`{&ukjDgt7NAVh)`w7K_iAQDf>3N^|BX;q;;a{Js7z|870Pa0$~U zcOp~0Un-tF*^j!XvzbiWv=Ez~55UJnbv!fAYcX^F;Zo*){!(%KLz?sgt0mO7)uV9i zz5u*dw+-)W_nmBpcsHK$P)!rxWWQgy{D~qvhjd5ZDtDqBM)+>Ie)%#cT~&{1XgVjp zHD@N>RO3gjq^=>Ivl|h$LSW!rYza%HkC!HrJK9x>iob0@V`m5qoYS2wGxcI3Y5L)j zsQ$uE)cc6QWUk3###Sz2?l-H7o24nValv3RyZbr9$Lj!6tq~Y_4WC!DXLZf>(rCN5 z;`W*c5%p4F;G9ln_w5H)sgdhyHxj#_??u&I##by6p< zTW%tDpW281j1-u*7Uj&Ej{}&vW#`2CteqRD)yT|}jYRI5Ey!kuz`z(w>z|5eTd9#D znHvf1x0}(9O9Eq~oyu%iY9~LayHp%`VIPtDRg=_imx`VH>0$G9q0bVmmnod^k#IaX znB4y(8DHM4gO4jOMrK(h?l1`-4+xwXQ>Qvj%p_=u(N|Sz#|#2(lWr`vzGD0D#F(U2KF(#hjS?N{o(YZvIM02K@%(K3iVdd z&g^Qo=42s5J%196M|bUlwZ;fN7G@32Vyfem*EApkm2(57rSn7YYSwcFUUY&@LTkCFC?h;0KT(F(o*^WVPtK_Ku>%W~Kbpk3*;(v&d}@z7leS=sof- zg4!{#FJDyr7c}f<2JyouuvK3^*x&EGUm|`ypo}mv=#OB3KlrRZYilCDd+0KeUTBP< z1`Yf^s`H^FTz&qJXwjYC2!0<0zeoDwlZ+qUY81^Fql4zNb&+>}f8*C@_$`+D0QSDM zWGAWA_k;+3iv_<~IvjP^`*Q)oX45AY0+i|x^SX&C$ zmXA(*$yu*b=)Iv564v6uHEQ|IE>v#&B>Kx!Iq98y5xKn<<_pHgq}S7_vE>WsRm;0l zFgBo_na(Nn`p{0KW}j*T+JW<)R3AehIg?E8W8dNb&OeRlEWsDNf35A5NdKDWM$VZn zM%P9hM24OM1Mh>2IxVC#+_T6xn}Sg6pj{}yPGI2u)YZg@)~Vh?X=ONJpHG|6OlyIG z_qdJUlqkmyFUaMAN%%XSgk5{y=I6`vN(?h-(L2U6^@VsvUJ%_BpoG@yzM?J?6!Ogy z&dlNZZ2T>P&bhab2>E!L3iKoYsd?lWLR7@){J1AJJ(ohKd^ac5Vv5L|m#6<>;2NG+ znMwy+21#EVeiP+do<>dQg!eL41!AV*aUr9W@J#%JoJXB_5{4aSZ$ih)Pouy?!ne&Z z#y*lo)P&-RxZnIzG^zX~s>>1H-9TRpd!|vvpF;5O=i3qV1;<=5Y!vC~k%YH(GDUFA zFjjq>_3+aBV{!2@eN+^75)DWbe8KS?XYY+|j@jcUBM!G35By!_tM8&Uea7H7D=S<5 zuF>W_nQh@TLl1o+{%yhboc9@rLnfD_^L_GB)m`BoP#RmKae5}rbR2R?TyD4y86OS8 zYA!`+b?(Gq`qw}a2GEvlE8&hBQ+n-TlOIiH=8 z#nl8_?zEEJG-d$)(QzBk%#X@p=Gf~q%XjS)U%4+qI(ri6w$Im*uXTSTkM05kW2`1l zjNY>SfBN=ZM|ND_h@5{2zK$=E>djdn7#fC?$HLFZ|0e}?3ZUaMzKe0y0eJ4^XaXj z>?$#v)5WF3eB5|DTA?Al9k@p;6!*1e`^nH3f`{{rVvpvH5_vlgF-K)D7HRT!y2{OM zIA8k`g}ol!qnSly@J!O(Mr)2y?9qll5XLjs@`|kY_Xj*9e^t&i5y8TE;Qq_?R$Cix z%%umn^NeEuJ?sFOK2nYcks-hnw?lZgxDQm@hb|km1Js zznB1a-_6-M(6Xn7jKUXWxbY|$Zr(YDn|H|kVj0D}!`OffH=h5+n0!j)V|n9ZVgC*p zg|A+Kfxfu-;TSG{pdF4;#1D)yXonlm|6&e}59G%)iG82>-;BZ+WS}oD4mpO4!~bR! zaR_4-GMumf#c*c@+K&J(!tC>SoDIfjd81;g3l=2Q{SFycPuI zkb%A+1AQGnw}uINQ!iVqxzQOi_m{T8>>Ze258*upGVq=Pne;iKqD6C7kgC&CF=U`G z$UtAV7t5GmA2b+8a-%b3w7U<$>s^KMz;Lzx2T2-Q<2rDAo_l4FWluoCeJKWeJxwCZW|LHVaHVKtfky8R63ovj-@l$ zcRSbE{<>Vgt?FpWaEx|nXJ*GVD_W)Trs#6I9na(ir}E5-zUIuL3xAk-aca!To&D&# znkdqGhlHMU-yT02D~u-~@{WvS{BM~tLElrTu$%+rDeX9VHp~2IFFXSz-!f&c^hNT^ zr|M;mOS;q7vR9GF$AjLs(GB0&DA+05B9n2<)j6G+#vS9SbBoWC!9ELlX2~F7PP+$s zGvq)!W~bII+5W>lX!~sugl->qx<;=rMvDZ!q&A6Tcwe#8*2={9XVRYc9LXc&UQ#<) zUyJhN_}`UcXN3X~x zZj7N5%C{5e->jyxwFcqm>H?E?-I$rM)n6Xq^iJkJvIjlm^loy?cQ@K;**N?%dJ%8u zNP3}+W8RpmF>0n0Db25^NSav4GpmjXzw7ZrP5!q#5AVu+sTxBrAyUZwmZ|)2uPDeB z=0Z(fW-%f_u6kOZS^vv{dN{v5xqM3^9aAt4U%M$VHQxwEyKahn*swLSHnxN5n!;*o z?Mr?7>~2r2m7d7k`I~0Y*;C`N+hpMy{!Itd{P9RU=DyI!74{yH_}7#5i{0owlZ{<_+n!S>O@5B-CwM?o> z5AiahM}E<1<;y;tlxcojB=?VRFGe>XQK#3Bqg_s2qs&s<;HvY&d)TOf=CU|8cOsgc zn7U7Ch52&7KTvkp z^qH*o!vLlmt0A9%H4+7HjHBtb#`rWX*x_=OoA+L(-5Kux4?Jbk5>}U!oA+ND|EZPc za_8+F14hN5&q>i)4YKN?5I+hA>fMZABB3ws4JI#K>W87;4b-VARUJdW^zKEC`l8Qj z$p1&D2Ie4b3^B|>SdS02O<_Gg>=$=$S~4ARx`|kHdMg3@#lak$l19*O zjXBb-+5<7nL1-r-aGhwUZU>R(=TsWnQRr426D!j>rKxm6hy`Kua9+_Gr~RmhNew?= zqU1&LUcQT%TzysNM3yO>YeD3k`B0?FGD~|4%#;mja$8n|Z?UVg^XHHhx^P@IG0$G9 zSiCA1U01H&uUzH9?2FDowV0EHYJ|ciVQ|a&9;$RUlY-m7N&vK z)BMWnY2K}L5a$|&(C_=*K;zd|71j3iLLmlUc{{SrVe)KpfrQf{nQs?FFE1`bA5#`n zzm2`n?-s`X+$8x&R&SKE)4ai(4$9HRTMxW0n&@tWCQSRq+iAz@a&j7coSkk~UbOBd zO{}q`4;4Df2Gz7Mr34`#!)gL@cA{etEzz;SUmm_Kq6u9zx_<}$`F;(n8#v5biPvEn z@)6N<#ty*0x2h7ikuF--!rb3GK>mr?@~{!ZDA$_ zb(CkaI&_?!DY2S#<&^O_!2dYtrwhj>oGf1r^EX z-68y17^!VDbC1=kU-ycP&YdCDpLFBxD6yJ%*3TSV zhI^`si3XOrF&8`5wJ8!6o*{f&nCrH?m<_C+9cM>wbDX;JW*(k&<9d;J$9AIst6sdF zFjn&}X}YV+2-ePf%j1;ZyLouwANQibUE7K17Uqkc2UEoA*>QI0m0PLKucL9&%_~KB zk1i)%^@TGc%V8eOuEMeWc#2u3AIls%G^(ia_;Mome=zFxY|qpi7o=Geb~{1_`s%=b zzc}g3W$Ezz6OPc=oXByEd2=5ZgWeMHhuT!^ckGJP|9h^(lF}-o&n=}aA~UB8sj=G&$23vI5HD@a zX(nFVZsam<^cCmY!L&n23g6XTR&7+nr}PJ8!jmisN?W&b|rgz`jqBha3nYZls z1b#tNMSfe3I&yXt4D`h@K7mt3pIik-;mh&%4+gUupxk)2vGv$jk}8}AEsl09*d&bS zXHXZ+>3gcjE4fVFKHYgE%Y1%w$4R~?((ydYaJ~jk?}Fube=v%5tdV`!ayV{zQOTT> z4wr*`_}`V$&=zyO!Q-0FO8%&IqrS0Bwnlo zKV+G@#y3RqVY)7M35zm7OYv&!dJFSGxH|)rfg4FLVS<)wJGXDQL@re#~YO_bMzFU|Hc|a-JCmsxyv%>%NmjE ze=$&R>&K}zsE`!aALwhR^2eeF?73D?j~$NlSSF%{Iab$Gp84$tKc0OZ{=?K9UV~KE zv+vv3Kd3ncb;M$htU=x_%(>muF{fRnU^=to znYwiiD)=AF;}{?8HCl)MJ?C{R2Ksu^!rYzv+7bG?IU`CwfYq?(#`E)80Pbz3->^(U3p33;Np8eyPxs6F<@|kK5Z-gAf%5F7@AQ5V`|dct zp0@)vu%Kr2!t{g4cj3PosFMX5=*tx8(Jy*<(`!4Nbb!9#vyBDIJZG7*(31}E*#mVD(z|_czGX3s8bB} zj@PlzS_?xhh(X339HHK^VmzGI7{}aUnbkcq9mcbo$R)0VCNgAN>5%~j`kFOSk6x|e zO$YAIE`q+GR`@%AJ$jM4H?0}4q6lh*E9Q&S?}oZ&F|3|=VLL%j95PVj8#2(BLrf69 zeW`)c)!x*~7t~Vk|1to#FKI_tsmBySEpOJw?5QO&|8PP?X_&oPh#`p zAWANRy6uYm;_TG3%#;?Ui<&VuStV$@Lq?HEB!S6m?`Z7j{)y^7#dI z8KC|k)MbFo3wF)i;@4O-MtZssGSC;t>}_G7uW#%Z9iu$ok&DdQc*(tethgyAqF5Xk&?bxm1Hrm>v%?&la z%Thj5ZdTKA(#745P~%&%Z{oB&XN7;JRP3hX^Nw1MdS3U@pqIj$0QJP@vU@a}Y2)#b z^6idLPh7E&-nwF6`QKWi z>sU>8+gfdYje^?lBafQUe#cz#!DAa8p|-nXpUc^SdZU+E{rBH3`tOg}J+%Y7@8;H@ zP0@(<(zU?BPnSCu7=A#@K0f2WD^TpaIXl!>M4JyCfU`gJAw@>lV3%ZxP_7&Z1>VmEs(!Hoy? z2%!h}xq-fWdON;&u8Pw;2>O+Za|zDQqJu&7d#6$qRl@3wy->xvDlH6q29kL?o2`e4 zkXfvar?c(S#r>C=ByJ7d_x4fcX_*VLhXu5_Zyle%Eo3l8=%`=EN6 zinMY?2kd8K*vAZxIe*b3YEtDWbn@l&R%3>>kNJUsGNfDJvNYf2mfi+E6?mo zx=iK6W#-<`_L7^mY^~?J`FP%?ov8fKS!9**pBf*X2bY;I9Xm)Gtfv+~@SKmQ_S=ub zr=9($#%Ej2Q05_;B2N&llv#zWLnr#U(nk_?>F2SYxMo2LpUZVUL`=VnbL6+IHk2fJ z_|fx93MfCe2WgtI4_?_QoV`OkQFBc3^}Z5%LgEMl+8MO98xwzRl6>a1ld_tLmyy}W z>GX-Z3}j{CiI><4TJvLcjF^gs3Gy4!-%E!3i1F?QQ+ni_rR1F+<8aVB;k^SKPfc(D zetG>9bz|PtR^x$8_s6z);O^N}(=Ky*pfnMw{0`^$anRS5F^O2cpBYs?zm$|tNkF^z z3e0JZF3h>0iE{eLF=S;HiEY$_sgeULs1Jq-$o7E1z;^)}HfC7VegHKYiD=6aiO6wk z1n&!;&u=L0gk(v!fTw1ANal?wlabkdeTj_a(OBZ-xqjJe^N4EJwRUdet>w^OJB6D z)|5sR~251d*gzb8s~ z$JTn7zyBvzxxF{+&o-h{7@@s3m4^M~C)S0REx1|28E>oM3w#D2#g#(X; zcN0E-5BT?1#h>2GzOT}d7Br{Qrt^OkbMLmuOTst6@ZHvRCnIvr3HDugfHKK3ig#Np zz%vwWyWDvFS&R4HQD2)3e<1;OKDZ@T>Miij!9 zhd&Qx2k#t1gME$2wWafTUk_FP&5UpFgJ-(+BQ;j*v|^wy6J0O-xzvK3>aX9**V{dM z%zd^;YrNwg*;6|&yk(>XS!cq&Pw6Pe9=aLAJ_Y1^VqYJe`Lr*oG*bt|e1~g7&eBwz zv$H*!b9O8N8R%=}0rng6&EKV!C4&g)OT(ZuGoY}Se8@m~iQULltkdqTw9ac4X>TgV z{Vx1_ZGrg?*OtH8$<|Fk33J2vT#nS&W>g3DmapmC*4cD@B7W3#Lppf76UE$Eh_plh z%^WVffQEiqEYchkMo(K)fg%_oPovhKk*#{&TW-_;lk+;`qv*42gDBQ1ijJ z^|^n`UHyOCx!&;(O0N{w4Qux)CGtBa@{c1t#qtA5D8IvT(X9^g^t~x} zko)mrye}@7Rm1zpz3)!uYeLJ^Uy3%rPNf?U-1#TpVJ<)G5s6mrcp%+zCmzFGUY}c4 za;LJFypu@>=3Sd9sIT))>AB|%vC?2MK5<|*ABQk6b{qC3s_ar|>xvhAE-Uf^zV9~p zw2OE-B%U5chEwo;H;mPd?_LmnRz}mL`C1CbD!dPVu$X}wH!h@+a+nm}2jRQy{SAH5 z`k@QyKBcAeZl9u#6bGS_5y7}}+aJ`WPUzeG@C6lC;;*I_%shBWj>4Nlmxb(qoG^W6XA5Xv6hD<=Prnqxv zxj24TA@$PFj4bw#z;h9e%61D(52c>Wf-nPF`rM1+ft&NGvVjB0f#V|a_n!HPx+^f9 zNB3aD+I5rtskY+^2ac0&w?nagw|wM(L118yGCRMERLGC3Tul`*Y1 zY&Nwi31irwO?2+P%&Ol?Mt*j(xYvS%lzUYab(ILgW&LtcuBmXHVQ;$Fv&*TMZ|6~K zu18?lo34EDVi~EupYiVyBUUp@r!uv-Qoemcao(FO)ak3x6AbniTQY11*KR&I3Pd^+= zO&|W8us9$vMDKc8UQmG~^x1l`WJVNC9ax4I$B&>U61BuGgNyulV9XD+oKO4QT#P3E z8bRg1sw0fL2#i{mDr5X)spO#RA+c3y9IbC@jPA`EMdjZ7KwKMeiMIpuLg{fFZSm6x zt&bW-eUJY{j5HINpA)+>TFd%MM*cb=4jY$1$2`s^7NmGk146zM!@3H+&S37Ox+c(t z(^e9hNgmWXy(Z#hCxL-FP#Jd;=*BsPqTi7o6x4x&`L+380$mhzLi8!zgSuVONEjWs z$&VTKY^*(%Ko=Jn6LyO{DA=hPM|eAhDe`u_MjjGeQ}I(3j=*E%+O)BiENpY z1NLHF^LV<%rW>^dB9&oxNck(Eu_P{e<1hlaif-e{zA0z5}5U>uVlB~ zRx(aeubs!YiKc7P(S~Cia~v-7X2! z$Hc!$$Ut9lEle59Kwq%0wR^}HYIBD`x~^~!3Hw^ZwZ(q#RCJ8R*QXdk30`IL2m_ zz`&lUmCj~(=qwv-kdlGs)I1_8T?GdA*?!0}!&(^FXIpR9JDKH`bxfAk1?PU{Vtg~M z6JDdc1=Sv^A%bQ-=C3pCn_9nW6n^x*J#PNE8;$p>Bc22aOqa9TOyc!<%-kzqoXaQ8 z!VB;s$>7dtKt!-L9|i0lP&)IP6?co!)!uy5+V z>@aK<;NT>>BS)}rD))U<-e)b@O6xu1e3o&`cXg6i$Wd_P4+5D9c>y)%`Y#H@;S<%Q zRJ|NQjk&me1DHa0UGcGH2gN^A!*CC&q4eu}IT|&mnF!b}tQ(C1{g{B}zLE=b{L&?`9Z zJJid{G;T?hR``fjn*y-L8Io!@w-EJrs3q$A%K3TMDQJ=f556VovNl7U)Ncyjef$)q z_N55rKCdH!O$5fcWT#9?_p4;?u*KpK6@-lny3jtAdr@zvr-aQG;T|W8I3n9){Z*2p zv_t&z8OH6u=+obZ??=n3pAn}v3d}{54lmBx1v# z@#uL=e@IuAYfM||OC+xes_uaTT^&D+gg~UPgj^;zH23w3-^gXTAml3zfp)R6C&`+ym0hTeKK!nCfj$# zXzyCd^qhU-%Hai~u6<}E4-4n*EL9PhLpE0#JDmc_U~_G8>_sQ1Xnj5G?BtCXm$1Km zcK~na;KCbBdB+0D6-RBc!F|=jICDKba-cWwI5)a?(JaiSk z!6+sGk8pD3nZNn+oE(7Pdk8v@!RZ-H-uXP|^3hMk>-xIe&lc}2c4X&$cy0hbQMs14 zljNJp_#Cd;L-zGnt9Srq&7~ph(mF9 z1V0ytta2DLssmHIp-S8-x(Cv%7)O7y*1?ib3sE0sp-=Ms(Pd2PO+zNg@QFCZ-3aAY zdeNW8X=3HTndtj=SKbcHuiXQUPrelagG~mdjAc8@xy!ykV%aYrI(^SOhprjgc*D{# zboi{0gD_83zWUIewofVc%+YR@r!{t^OhK<6k}a=3h>v*r(nAL?A_|SPaD8qVdQmIn zAk0(y(Z2Mq%rwHezgDX}9prhDx#qY|60_o>cxSm6?N~4t-EmjL&-}yCkTybo!92Ye z>`6O2Mx%=dRa)igmt_|j$5E#ws^f#j%tm**Lt`FVwXZFHI42C9yDa1&%+u4e+-Zry zDb(|I+g5p6?^eP*>s}yn{-h_{%N~-NPankn^2THJhQWmS@{ahadw@JJR-pc-OVDc-Kl1wREC39)5Z%Dw-kW7hHc1zw^Lx=Yyyr9dz)Upee{C zR$$=TQolirw~jnSJ-e@iJyND24OJnR;Tn}}F2>WH4pPl$b@7ZDQ_-s70^`(aC1d!f zL}I$(G}3?4m%4J2z}H@zVr_aXQnD281s&R~Wb&K}B)#0V#8U>R6@Lkxg;$wZBduy* z!L z=%Fcf42Z@a&vziL%Bg5X*}r3T^7NA84w=z7^6_>AWA$%ihB1E#_)0VIc0$M6;j;Gu z82TF1xPsXjvRYDq)DlcGu zxi}vzmd$O4+Zs%2m0!Li)0nnfRpp<*x0U=nI+Wfp3ZXP@D{N9)hOS=k%U@^N%@C$$ z@jK>(=4bJvvEAv2JyX%yrNi-IL?Nb+P-_os|1~{((TlInL?`VqhPD4tUwG50q4ckZ zc1Uf36^8o4hob`-b=CXKYV8{F4L1jBX~$tGLLP^Mt{0+_rGl^OS1ydw?F&r9r4Qnc zVQZ=C9~Y3*qCjjMS%CC2h4;CzMqX?6Lo(n|F1nx+gJJDItl3XBbfr34o1^}_;xMe) zFUuIf*dD#ZtPazV41TwpoVrO3r`P*oOQH~&bP}F>HNIIf$3*X#wY_>vax>pko0$!$ z>-h25YY>H2we%2x`g#XyDyVz$>yXl$$*uJDpiUogLK|(LuZ;VgpNOGOAFS)w-WN^W zTJi}U`51^{UH{Ww)=XSX8RPx@t9VAWrD&bLGLCva33p`0I|Gx2XJhThw#@K_s`4Hs zrV<&IP7NV96SeXM_)|d{TIMYG66?8v zD(P~TNIw*fb4x1FlRv^-97zjhyuTUC@7MK`sBL^qnfh%Ze%Q{&eShCZKMaI9H6D}6 zEJOX|OP{Dp_H8hr5&3}l!mw*q=3Vq!SBOK%{24hMC%VibHy8A2#jJA5V2-5qlOObL zBdN7^#V4CRtlet`ho9JO*3gLV5{V`qLKc|1Lu(9QyGw z5A&kl%L=z?pGCfUZQCj@HeQ*@47pOnoL&4<{PQ5j4&FuNG9&gI&lMDMOc#C^%$?h= zF1T0E3eq^dPpjNnaegwhyUPRSNb&=5tl1bGb?XAve`gJvs9l7vC<)*E!@T&WIu75Q zdWAA+_Y}drn0#Bz>{?sO>~8l|T-P`ZJK-*L)RA(eU0Hy39T4UM=1zB!HGXum3q3RR zDuTHKnIxB2)VCSF^v$zJS~1YqlwNzc^_-aafsTjd{hQ1Pw!sv?= z$5MIhJ9g-6bXRlcr`mlc=674k=EV!>@@#W*O=vc{&#o;o1B6_L`947wMHkc^q`u;7 zBAD-x8K1k5UXYn1635M;AOn4=7(f5Vx1J{-&hv{_wyIIoUk)J8Jwk(dfW}cl;mA@X_LvjVj(F2H&B7>?7 z>e!7kq!j<}d{3;3qjz1e7Zp!Rp1Pb{D*Op6NHPEZA$@u787b#p@AoKV~3DvGT z5SIpQpdbT%eYj9Y?Trq^NuP5l=nJkb&)e*z`qxj#o6GYlxVFGGYT%JgRHwS>n6W9M z;5z0c%a_HKPm=e3Xe?PrJYdhw4oRn7l?n*RJcrvHt7 z_g6beZhOW;BI)3W=HF05eWoqMMYAU0bw4KZOlA9{vJQJJ<=tI+NNj$rBHSBB5Nq^O zafa$6G{{|ePyPGVGFiIS5V?P_kt8s=iE!&r5F;KYv)_O}LVB*kd*SH&wz6)YhsvXs zyGiP*RL}{pi=v>z$=G&RC98?>9}T`2n}^CBQiVRrm#+7By3FpEr^HtN^In)cvl_Xl zgFIJDV0LIWio#x`;;R+^(KUxD7T8naP0%EM27c4kk>*(Yt$h9N4_ z@h_8cp?*CouNHngv@^)*7kc@43av9VlZ19oUSBACy3C`rDdW_DW83hY+HKf!&n^;7#ORN(HNafXJ6bQ zJ*TgaAOn3t2Ks84c2*WQ#aI=0*L3GqPjH%;dR&=8`tf$#j@kgGhEt4;c--kA5f%za7SpGGJi*K&I`uSe##z zf(G=`p&$c&K?eF7Kk}f=Xq%<{vBdxhWKOn!gqF@0#shN@GB5`rquu{JS~oKS>wcL> zLI(Qcm<=q`iDjU#xc*tPO#_F>4ZY1JvXnh2c*cBu-)$oK3^>Y-_{P5cb#i2+1+XV$)jv-z@zIoi;9Rttz5w6QXf*X&w6hNtjcZ?|TYwp-UMTsMU{sFwFM@&kxDI zSxuDRqy|Zh{Z60@pVXRwXC_M7ONPAZn3d4ehi3U*+gI$vB&ouB(rl-DZ`!#w@leW$~zhv=qula#zSOFW@r?aUd5BTB0pln-hy4R4>3OGlaUxil<4;Bcnd@JIqhvOSJ?HrVCc$jdGj>rACxU#+MguM*h zH|aXhLS=b}iBX&5@e%fX+Wc4_-WSwznZ>X`B4PRGY3zt$ab9*-IVd)UPh}l-IM-t#oGLUS`&n*VHks zc66ImM;w0M3isIO#9trC!2J$nps!`MGibI^FX>_V96?Q6sEzyfQ7Bzfl17YOZ~;MW zT)3Bk`=+#Ddz`5zeD~GSVJPz%*D_*bT}kBP2zLK90ws>yj`S)dcxw{k#|-y7KFtxd zf3PF+=(7W*Oq1XaA283HKz7W_&#LmIah)Yj&!gyTOAZkZo_kP+r5_%0K*Td}zcaEr zie9?-2yxtG59-1SUG35nd{uvNVocfZSD&f(km#+7qV=wBAeN8Yk9y7v$CED#*AVVO z<}Qt*Z0-!0U*+~uPUXy89*9kj>jW!b!7W>N8rSKVJ`#sARh_F-85=y~;(P=d=*w;V0DAvtYrOYWEP}q^nxMC?KaKC$;}I#d5L^@B+OpQZ zKON}lfa_W3)fN~GJ9S+xR5MkcK;65d}l7! zcQSQ6lXr%g|4iul(5p`~Gt^Dh!B~ujw$M!*0aoj z7)|;j+o$5=k2mLFpNejJhVsg#JzO|uZFeL3)vHl>@>1h`JJTAXG*gR@pT9BD23hFB zIN=;y!DO8Dka2dZSv&sb66^mLCakI&m5$Tr-$g3M%-JE?nym9|P1cdHIIDi2pP;Jp zUOZ!lni)r{p)MSAYW`eQOy=DncBms(_~4P+F)xLzNM zx<9VB#{cs5-*!x$RuTtegmqr=+qpQjpS9M`HpBZo*GCe@VfwjUjO!*_m#ev?bDzUo z?VQ&O%+(9k#LT>78>`N8L5B9*+vLJd|Q}-GHmJk2C){W9cBXnB#Z{cEoL}5GoM=Jyd=EYtgL-~;s zE#6M@fIjvW`o6p!-+l(@{DOby#b&_#Eq4a9+A$k%tmJ!E!n}aKAk(pD7INq{o6kW7 zlXT2O_BRIRAY`B~$gFVfbN;=puRS~O80H}K1)0y(XS9Lcr*h9?itEgcXMS?$^Y_2| z@OF;fX+XzT3wa82c>&q({L+&G19RC)*32jeo49axx}LdKJd)|>aE{%pY_qCG$;Lu1 z!+iH$?j{X%Tk6n-)oq9Q{-(zxCZ>~x%bU^>vPmLm>8In19THf^An6g>7&?Lp=q71Vzk$WbGWv-Fi-0>TS>Vd&MPd@1eJi0lXbW?r`gdUg_F%g-5*k z-wxM}X_Nez?W|-IH=YwOGS8W>5}1rW6^Ir^@OI#u02#QpKxPoD>F#lRCEr8yoqaxU zgPRNJ>;I48^7LmIf8T~y z)AB;)uZ5mh>SposYtCE6XEs*Z5`=~ z7s5X1ky8#@95t8EFK7ocH#KsQ^UT)F+rB2U3Sb8^3SV4}Dzx*zd~tT%FL=>Td)6YS zgTK)5b^2KUTmb)li|KNs-IejADpjn3vv@{v4LN3ptsAY{ zQ5{#*?d0ooU#lMEnW6-t2N%Z}s5{faQ_b*!bu0K%uWwQN8Km z*IcmY^$yhNv^NNwD)HCwZ;aM~Y}93g@C=|}xcRzJZ9-e!665A$UD5vwbLEW^>cQ$A zaq+AeGiT@UA5436G{bKG2l&2WlMOoXjN-R*%!`HXC<8j5n0P;l=6aMV;%8HMfPA0- z7KvuWQs-Am{#56e=ZLCq3u!Im3FxuXZ~k{Z*&QMus3n$Yv3A1b-O=S)?L|L3Cex>1 z%t!CF8+iuC;qtW8B8zq!juGsA2gYHyJ8|--LrLdkHV%JjyCQ46*=e|KA}uakiKc84 z;;>bWu}qlrW+yk6fw2mi!)(v1KR-+Pe1|axeL-e_yBsuOP%wXe6wD_!#{R}Ad~tCI z8R!c#YSTxe8NaqTwdt0KVXQ)5ZCPf23v)f$2uCVS=Hu`xd!0LLizSoT80-43KZ;tE z?i7-pgkP8H;SIjAAr_}tO&8fku1>F5>#R7Gldt8Wl zMQm{K+}}FSrYR$hXSlj`MP6JsCFEYAulVtNSK47?`Bh*JG%4W+M$iA1I}1Wr*%+BT&K(8A-BbRSUq|aw>4D!$`R4?f zJJ1(os&`}~%W1-Mf`Z}V`ELx&(_??}1sNUtIFU`X4pGYXaDjOWefg~2O;iOmJ8otB zvqVcx&FPZBH2lIcYKVW@tfkjpUNiII0m;(Q6QEg_la`UEQS zJ<@xEJVBZ!>vdZs9x^Q0?qX84;~VxG*3IvRH&!3z=Zjo3UVh;D8nO3XC-G-x9|wn| zcaE=ECdRf4UO8kJ&y1cuO>TWPSM2%JNqk+8ENb)RqhkfjxHxpheYdUQ8Q4E6&ZMDe za>y4)?w!k#07G24Y&XxqK8hNPRu@i=%yQ&Cb^!~WFPyBXP!<|kw@B{ zaz4WLaJ#kTo=xPt7kq3;leMw$U^RZsu=iR_`&%{>YF;?LW9Q<-A}zdHS%+tOgs8|P z-Yt@KW@F6iSZ`b7&O(eehqLDwI|XeN*fZ@~NjFz|q_cUE^NHnR ztTEew)!6Ni8~YmIYfgDQ6L#5?tt%ZOR_;>he4b^hW*LwrEaS@d(F=QWm}g*K6tGM$ z*3Lzifq4P*>ln*)VVN5&1M>^UvvHL%Uh1)eT0}Utif1p2G4i%+_DQsr3Y?!mw7`Xj z#!_KxZSj&kZT#}cYJNQauWjXV;gyneKl7buI4I+-`gf@c7iWA{Sp%<#5c-P1yqML( z++i7*7m%4Vy<_nt6u^u`Y9x%OaPZ?IT0@sE`RI-HHmKqX z$1;A*Fn9D*%Zti8>e6Z~({7InR&prinXZ>KuuEk9#K_s zNY#Jk;1|}8MGFIS5awxB&lQe&S36-1FHZ~^=qskj3ddtD4D|IrzL$KF!H*IZHosJj z1v_f29q}-ItoicG|Hs&OM@7+l@6!|nL}?;oML-b&1(CL!Fj=hFKrE#p|zVUs(e9mwG@OU`Sx%Vcy$s{*7_u=}7 zoXd3>Q-bBFV+=W$$$9#)>p%98^OT%lR|pI_zvOFj*{h?{dHHR)x1~L1GK@X0yCHx7 zrFpS|>mNBr@kUJk|G-{H89yqD!zkW}$^YJls+87swc+G2lNsh9uFY}uN$FoX1K{jY zsj;&&hiTS7%DfRp!L=R#!I1A^XSA6CGKa;%+gU!~-|t}+Z(Zejo7W^k+s_t&eCsOz zd+hg>(y&$AsQs~eb}K!Tpk_O3pu6#(_ptQVWXaec8PXozvZ%f5!-4v{Sm>-80J6sA zfOVxV+@4l0hvbZ|#Ot?zk;$^X!JoNy9mSX~9&WCe2MYdhE0es*t1TA` zY(L{YrVO}}yvZd0va>6X(YPV}i+@?JOI{m%G*0X6oK#pWULmWHpM~YM_m#E(sn;#9 zng8{%wREoS&H*-iis(?|RIWBSiE;M0D6#dlmQI|NRNTdPIj|f!m$g;x@s}L3HaPy? zve{W0j{mL=F30Ha*5m4j%P~bhF9!cFjOx!8Tps}Mk^WU<+|#6&>`RH3^h2k(ft{VN zi&b9Y8WNED%bt<_)kKB*ce#FkI3O0}is!+jEoxA_X3(GUQegDYzh!p!4}!bvO~mqd zQZIz;AAj!MMNQN&eh)Qb+b8C`ZUFocFp!pG=DYoaA$`^7M=I=_qA!-ui{sV9bCX%Y@|nN|Fb>Hm5Uq z9vUDXj`L(l9&ovDDEP$X|M#*yTJ;^rnn*rz`QL30d&`Q?@Oe9W!Jl2^bqBr2y!taw z$y}Pavz3+oex|a&Qr@|exitTlGah3`m%nr+<;XGa`@LluB|SL4^|2T;GpW%v)#D#s z;-B_2P6XAJ1lX44(_HziIr_ zt{HfrmAIss%CH!@mabJjIK02e|^|2c8@@r?#e+q7=ON!fAh_+470H=OzV=Dd3 z-~&f{Xwpp^u2JFF1oBNE*m#0D#~uS4&-p+P|6jnj+L4o^t#2-IIAkaa9u!3VnzNB9 zT5ui&`TN1ItJ}cL4?HF+KUOk`>MW|7;6UAus$+iD9s&koli>-FOK0V^%#@VMzt@7pIXHfV;}#^QvR`|V(EWf! zj+qm;9fZD%Wvy4d0BXd#p}@F`QU|_iNrjGdw7|x!QkYx9@N=h|nM95m+x>u~&-FVM zXMfFuR&|j~f5!{L=p#HPbBdWH*Q0}ITEPej>j1#~_71DsmXSE%}ay^^b~ON)pGi;b`kwk&~`QqNInJ}bPixzk$?Ip zWLK)hYH&AEU&C}s*ZNs-{)g?rIwFj@>QN_bxFhB4@tTk>nP*}lDzyJlT{9{kY8_k$ zDw);vIo%t=^v`EGjMgSI$-D?%Q9{Rv>W&+d;G&%tAmicqstWfD!qQ$f9ESAg7mjn_ z&WxpC`qxWB3)>sQo#XlU!sNVYYCi)yI+ufGGCxotsS_TEzro2N`+36B5a@aEJ{a3C zmL~g|^yhc)hQdeNyTS$EI)RmUuM4}5xW&mK$09XX3!XYT4%#IS{m)n^eB+{>vheG^ zIH0n49=!S31%873H;x>O%NV1)pU2c~0I=P|!AQuOb;`i# zH?!f6YG-&vvxLJOeiTDb8{0|B++R`_-8ESeYn|KQ&csq zJw;-ql*^w!B<+!7y8qU750|Cpy$!^I@DSdA$UV04&d!4^ zI`C)M%1AG;dnS(|&kiFtoN+kT$e+y@@AU*bukb!ko>R1R^9B{&=Fj-MExo|QJ-fNK zljof!mR1gJOIqyZF|;gKFVHI`m&1_fxbYX9?Kci~1~d?H-S};wsH25XY;GBhK~IuO)ihH%^!Ad14H(o<1pme;f1ZqarXsJxVXg8`fZ@w z@LL?lLUn{J;6{5m?ns5(FyrWB-)8Y~t%h5hfK&NZ4r7-vTsFtbfqLDs!mX);>e2aY zKXAGh=57LEq5S&OTFgp)S~z_CWjZH^>c8se@Ln@?pOoNAy@bw09EpE}| ziHoGa>vh9F^}1VD0c-b}+&3534;RU~QGVAChl={)PcE+lL1XwBwF2{-KLslIQ%HeLwl>=a@I}PhTF#Ka+sTw zPoq%XaQ%a8?~4?*_s3n_ z01RE#1^zqYVKj#a zB4W8NidZfRoeD*MK^zA2?}!xqJ7(t&gJ*PtKSB#%W9*8Xh*3U zyo3AM=>GMiBac4e*38AJOTp@Tz7KJIb&+}7OA5552oq^Mo$?<{P)k>s5){v2aNT&(h6kemV6I&>g(tjuIk*P9 z$Y1&Lf9z>k@)*Qg@b>IV>M08N{^T!=eC;(4dNu=OZT2wUv9vGJ;DD3MD-L4FUPoJ#jF!=sdB)Udk(iy^6VN;1DKtl^E4~w3yWbS*B6Q2O+F?%>&8AbM@6CDasg7Oi!oDEN%984lO%!sy`KyTe% z4g){gi7s3`hhE@#-G$-HkF~6y!F`)-4lMz(ss$WoZgF=})}C|d3C0*cb3Jl?TB)2P z7Dj2rf(Pn6rj3Dt=*^aMoIP(-b{)CoozLA{MJ5D+uU0%phA}VN7omJC=d0$RLAH7P zH+Q&B5ZD#Ne{*sDd8FWB2}m1gr|6%H4odLLL2b^Swa0IwlE7a`vVWS}r3FhljJ$sy zjZlW!Qof&CTQiG))`OpSMVy@0)?T&tcfn*6*Z-;ORN#BiyS^WXv9u~cOK^ScC7=A= z=1i?DQP@0Or3DaFTk_eVH{?GODa;-@%Vb-vc1!9KQwW8 z0X`Roa2Wgs94X#_cP_K7iXGTU+l)zpEqPDD!F~Q5rZs!=aP8i(Y5biFz9$kXIJp!n zi`+Mi!foIjcRuG0^KFR~d|M>OILiW_H230kVJ8gf}e=laCe|$OqDOa1vf_Va}aY1AO#mvb8M(xzu*0A{<#T62lnN3 zwT9`PqznhA^S+8X1(1T9X=eBA5``QUPc?XZIq!#|^oAoOdjFlw;$#q^1=^JwsQ`zS)g6Lh_RE2T1Nx<_4kHNfVA_cD*IbPP! zOyJc>J|78lmLUaaS@)ttf{AT_vq@7bd^^Snx}W2}%dL&6!^OAYs|P<8t;yNj;}KA^ z=KC4*njrJl+dej8}suOL^bGoMlMCk9JGvbj8(k;T)#fyc6_P<>w&g5km^j zvNs0tl`q6Pm2#dC6Hz;uyo~oBoac!Y9BP;!jaBfYk$Ij9%x|6uR>2cNVy@lFqB3SV z$#zWZk20Ay%-O3_!KVYsAA>=Xm{SHOE-(eK* zcUYW1<%ZvN%6$sI&7p|5IgH|MPHff;_&R~#C*XHC6!GqcQM|he+&Ke|P2n;4O$|l7 zsSzsP)P&rd3a=IL7+l8;De9P^wwmybxi1(HG7hQ*=KZN-hHI2jiW+5sg`=Qj?Ex@v z{!dV~XZxQTWw`zrrKmrqcKbZ2NQncxF9t!$u7iK-kKr1dl%mFF59jZo>CklG=`{(y za6kB`#wMKPg4c&wl5&gW3)Opk_h@e7CgfPt8wU3l1r2!TFgNfUIxNh3mp%pkMQbKega+ z9ZsaE!@2pzeqgiE2$+qZ4aaue@}~|buCa*}H8wk~It2E|brX--9Sy~EH~y)yiR;%P zMg2NSNHLhdkrHo9j)up(t^HHK&Te-V^}~B5dcWx_6?i@koZYlVs8cl;j`{f*T;9RI z3yAY@qtN>`=!|U}^d)d0hz)5cJpXM0RG-*3?2pp>f1uuJ^n2Nt|><;YRXmMJf&0PGJ%mfgnm)Ypgy0+;QDox zqJCZfeYb$o^mL%*;0JFiJp;uzd0i_VdZA7xZ_tj*D%5xN_Hf&-NTBCD8d`3A4|;s2 zxOqYDGrxT|hR2r71)qN*c(3v^=o84-k2>_Jf(kinD%$;g0(flu0z5sZhxvzW@ZMMx z*1GfWIB;D)q^Qd`BWE=bcq{?K-pztSz1!f?5;soQ#{eO^$;*sPqusKrjEXX?#^s!2oOry+cP!uq1_NKx0(Ep@Zdy=fI=@iHD({Tc!z z4)ZyR<>v<>ty(AP;^xWJT)|19LG?z)!z~V`H@d@&Bp%cGhzGi3Z%bA8DW#qV7c&Lkg+3WQn zWmW{Eu{08XcHHr&HYToni4=7&?>W-IzG4~Ec3Ci7RGa&!?j^2ii4-+0U97@Ex8)O< zugh_*oLd|I)U?EPQ<0)>>WFQjU~%L~###^$rR#J5)J?^8N-0H6)FQ)$;OplIM)zPe zba}GlPfb+voZ{f12d!>*go}io;k`AFz}pu?xN#rZD+tNFHD&Wg=QC@f)`I1u?b(0< zeOPvCGT8fk7Kg!nzDWOJ8(FuQU)B2pcY)^(0jz^hIYW0(!tq!hb4fKAZR)Qo>lggJ zy7}{NAj}G2t2UN15h2N-hUGDOMRQQoAPrgP`Gt(@w9P>8#2_}bjT!4VFa<2R%VRM2 zG`b31Wl4Dv)vC+Fp|xgI)d!P0W{5>Hc>Ig68&BGU`Gw)>Bf*0D+4_IkL$+&tb_5(! z?=9T*S;CO*8le-7rc7{>={}5f%j^{hl{4`4+5dr2`j`x;x4f=rQ8Q3{=iO+`>}H99 znMjzV|IsD!NGiK^zABu5E1L744PG};+2$f-`R1V{;UX*0ySLTlJN`bqoKb;elHEAW z9MfA!*(^|U^!Ou*z$;g9YuHXf>a$cfTDvQ}k_$OZt$PTX|FTk&IiW?;CBj4a&~d2i zbfrlD53CTSqSUmuBKm8324*Oi)PR*8m@W~mDKfVfATUY=h)OcOtB~MV- z4t(3UPVDZqIW)}$=e)5GZ>d1-7-!DrAdmnlq9SKt6%alVa%&2^18ZAD(7Cryo&4?@f${{qft3BcohKt zd~8{P=`?V!8|Kqw2T9*Bx4JEJAu$SF@)#QC?qqk;zZh4g0vA%3BCaL3C-vMO=GNU9 zRz9|5TuTv)lVkGI7{((%lEaX(I0Z(oOO6@we_#~4&E|~OA#BC>yq2S{}!@j zY*5jze`Cm)o+38*Zwwh5RM`A)4B0MH*Rez;7!v8rwVl+Zz{uOx8b)EyzcHje3XI$y zQVxkx#47)7^ZymABr*7m#*$--c}qnNnA`mw(3iA%U<>C}WC|vhz<0D#<<1YpXX6AYe_Te`=Iv-Tvp7=;^O}J*} zhuj~RqmLC@lHRdb1=W$C1#>T?vdMYMFeX2a!;ow5$`>Yr%Qs#Mj31`5#>1Py{qrdt z#u8!c>AIuFWQgFkO7?K+f^G+gj9B(1z$oq%nos{1@ z$ob#pd~IcM*O+@6*N;6jpTUy+mDj{K(KDYTNU3jgbH297-Nq%N+P)~s=9<(F?9!h*)fVG zIWC7Aokr5jN72clU#q(uOcCs>YH(eH`+0z`GIWm{&h=06*KO#|QeKzqW*_nNpHJx@ zlTz4c@7{tp+oy6E@;ms|w?XW+xrW}kC583Tc@5Ten9E@>-=F9@=8-4+N8ZmQ-yi1k z6E$GY`hR0cErBl*gCF292`tHjNyeJI z!ZYYv^)zOhRsu`%S7OdYQQXbG|7jP=nTYurkqq{Ae8{&ol4s}i#iss2juU>QvLpv6=8MGd)txzvR#9!0)ut=Q@^JrT)?T%U>TK{(2er){Nu;#r%~h4fEQ|F$$lT`!mU3iFrBE(B|Hv)lb(*{HENkxZSX@ z;s?h3i~BodktDG9Fpqf@eTMRyV1q#_<%=SxS zUtcqUHypD#OsXG6i5`xTJRhJd{WZ%)c=@s#Xv|4wmrG6HmhOBER@!znH5S_(e8@(6 zPoN`Q7nm)Ka!ciGHkGa9)>2gs__As+VXc& z=L|}y?i-9n4{t7%7#h3-i?U^4`~wemzWXC^bHFlAm(HG^NGIhZ%88AUjLq%{-%Btz z%EsYrV~-EO$A`Z+C)asFE`;4*90Id5b^luDueGnFX5BFr6-G5x@9p0LUbQuVHOhV2 z18W;Vn?k-_O5MyTMc&s0KX=frX(TwHH?YKr69vYXx$thSEiflfZqD?M&l2u#7U{{Z8g2~0Vn2R<#usDZ5%gBATy;7L; z)a4k-nw#^W@Subq+h!UgGVb%oS5J1Bgvy_ckqo`IL2|xx04y65LB~}$Gn=pC!wFf_@yHCs}h^OLDGx27EimoblVsFsEj9g*|1wu49$`k@nYgX|Bt=>YIg0@N0il zkh$QepvJ}$t`PHcXO`7$v^>QcjrgH0skn#p-75PFWwBEjgT?J(@Zl&<7y0eZFY|{h z84*Z+`j~0$+nq1~n%$a@iR&Ot+_^MEpD-@3&hbTWUIkz=Y;_`CIem>Fe! zusKt7D-g&rHDNqPv8R>qjh%l)h_~a~38R$5#M>gWK>TkEDd*hIcP^TnQ&~6n=`<;a zv9gA)@>2Vm*&#rJv z=aDdT|82qPh$TR{{BMkWe~3Ae;TQjrP*?4Nn8YY_$uZSthHxU*m37_3h15l!zlQny zu^Ib+F!KEZc`i`&kG$<9hCE*=F!HvyhEeGHH-^+j<~1$C@w#Wdy;!^bH=M}4Ci0v+ z&P5Nd=;_72-yiEto^ur#`FXj1v>tq|=f!sE>HgPwS)ogwueC*}2i?2leT3HD3R0JR z4ysEQN=LhIrIH#W;FEA=rsd{QFegs{Z{+g1j_mB~+}wHU5k^fCxx?f0Jec@VIHnaM zfMLV<+)L+)*U?q4%aTqtmDIK47I6L5D*ELOH|Xv=3hvp#W8}IN+$f!%j(}8;Rdl6) zSNL?=C^+aTuWQ%VPY4dZEMZ1RP?_ZrPBZ>Om!GzPJ^V(&t<(E{KQr2*>s3f+8By!=`>f}o0$lEri8=(KI$AM)odmT zzUv`9)LlktPY;wG!=&DO^4RK_&kSa4l~i|g+C;XWoM}22`6bGolbiUO@V%w zrorB3Jf{DWA!xj3twcrTFy%CPKcoGzm(YAr3^d;{75b?2@#ogox=vLL=YHiJwk9)H-f6gWI*`D-@ zhWk#x61Ew+2ZV3;h3e|TTt9zE{e%jFO583-&Z5k34}%}Y6~c^>-Qmz(zHr4YeoV>S zxfMn+P#ers`mq|x)%lGjrebO zYjSFwg)qyF-y@MZfnRlEVLRvDz$~F!pcOR^9`3w>)79~K9m>467WvsgDraUaTvqG{ z;M7_2kMo$;?D0ZEIPyRaCx^^YEG!LynNAl0vUX-p{+a+|OmjI5nJ05Rayq=O zjPJ&-3>KEOn*uXJ^8R2FrXNKW;)~$dI6wHMx(T$r?!u55%t3<`95g+T$H36Do5Aqv zHcU~G4@`TtiIa22=^84l--&*x_oYk>;-TiiWng+;J7Cj-xfRZA{=11b1!F#m-> z!GBTwag*?6d@s&_U)!4g!6j{Hcq8 z#E>~TEyo-H>a_sgwB9acM{W{c*}&Jh!<-$6;OuZ!aCY=4&l8@D;xS`aT}K_IYmwLM zXv)=nHhfiL1(t>F1}(G3!OQ@@U6|_!DY$-$C(MSwe&~bq+ls)V;Bj#0GQNK>X9rSn zcDx>2TsdA#5B8gh|Pq3)|#9EXUc9J^wQ-hv5axb{JEe76s)&cZt%kvIk z-V>zYJ*jB+#C6ll0oyeSuHT^ZhxY_?h#&>0NiJOGItPCbTzh-LElYI%aGJE(Uq|Qt zOi+iD40W$u1dHdC3+)&5h7;U`a9k4KF3hQf6kJGOIt_s^G*dV~%@mFV!awb5&7O&y z4+BGsPTY94)~@>vhr#4KJjUldi}oZ9LaR>Sp~fgLW2QG{0!i0Mm@yz1*v{eCmV(q3 z9Oih`9jXYe1(Ko_z`k-OoG@`K*ptos59V$_1a||i;BHuER1WF}cH`{9+zm*M z#0u^PRjM4o?>q+cl^_LQ$yx#CM8S1OI&}4cy-Rb!tv0-GU@j7*;3DxDv`=_5F{* zdCUid6nsFNU-lCxzWzZUQAvSul@Y*qBX2Y2`aue=AN9S$n3F?CoEn(O#^+8X9iyA+UV#MkXq-vE0_eULRYQNb6})oG%QZ$zm@BUN1|OnZb+KdE>dl*`ZCGePSM{+ z;W__e3LL$k$BYe*K>OR6pi!7}YK;C;W{K-&VcgR>Fv`;nI;QiOA%UY&(?DzV&a{x4 zt2vzMR({j9zQY3eYd*mF*8KM!bG0A^4^-WuZdFo^bjB$$0S>tr2Ohce{fxPpkb(!w z=zuD{`JO2=JueAPa`gv4dzo{6*b81nl5Pj23ETTnUo%wTwdLW=*BRb8A89P?3;0+{ zY~pof-|m1kI#ipws`CTbO&rghvY8B9zKw-uK74$mwS82<)~Ps`kH@sOA9KGp6>iJO z(xw(fL`EPD(cfM%{ zoZ+4bKHrbLt0nJ_-%oXcE2|SZo9z>4AWN%l$aj0SWM^~=dnds}(C5W{;p-`C(C!Am zXEW~>&Yi7LyMq#TRw}EK94743)lewE*IV14KjVw{MxY)>8znw|>XPc!DQx1-0%5FW zj&PWJH#n#RFK0m2Tr_$`e^e8%F6rhyht;Xj7REZ~fQf6{!$%wVeG3`Gzj-T>ZPHus zdbOQDAY=F>hWaswse2Oxt964J5<|wQGxpoi+2T|f1(L;Nj9QOAiROJhg34B~62rzz z^t0D~uzu(##$%o`H0(CwKmAiIaA5XDEP$UZ)BoxpGWNc?#6_4_l?v^S!74KLP6yYa z(y2$#+!9tIJ)kY_{uA>!?!3eV;Q0KU_xwFI8Rw50yM(KiGG>&_g^csNZ*Jz~q#Z1f z7%aH$`~j~S`}=Kok;_@Sb0B9kDaXCSAAaa+=4x8s!jN*v^C@{=mXGO+dcMw^rp703 z+`~O~NYocY*f6`0-dE6ionX-{kCcei_eVOY2$XLEVt zQ||0AHEEw@PSH&GtcMa~=p|+3nDaW$97eGZ|93pW!fY@!-@xBrv=*00oIDtw9>(W3 zck6PQi(SYjAC{zCoDA-MOk~G8+0t^%19d(pklJwr9SMCYm1FdkMuUUp^VylJ-ijCZ z9t`0`e!R&1gcKZepRe0f(5q9eE191_<`wjtn##sF2MJCFuH@#9BCmkVVMx5-FWzn0 zA9kHB{40ln)TOy0hb}P=f-RF@15y`xkKZG{5A$8=8+c|p^{;#Y@*aPm)Qedz@`4ou zHQ3hf@z-ph0rLvC(bp1c81f#UloQ>c12emryKar}{!7l*fV-$Gj_u64_f#Uy8VudP zQ}jnedsaTCdsF~7rlCfckow9-slmfKiMGKM@LhR6TjKdye1G_0D9PlZyH8@bfv2 z0m<9-8{>caG$&^ZmUCg#K-cx%E(tEah;K*YK{{JjQzI7fD8NjG%MuB)Gsylfxu<@EB5#d~YGoF_-@OA z;kk{t1Af0;n(Zu*V^p1aIlh|HIeTL54@qv^J1ow)mkM8Rui`L6`v2D+xek1{^GBD$ zo}k(hXzk5392@*tomc%$Y{#U+(M#G02WVQtxw(8@qt;>t@^9{az~7Y|+*gk->y=1_ zDhJ#uCYVEN-e9J4dt3r9Zwy?$g1>jr81)c6?@=PPpJnd$-7yjdsSaSe*%g6x8^^!{ zW_+B#wezxE*R&!&kGeHEm(tV0>I;0HLqE%h=+@N|sa9Bb$%E)5_>%6yte-QJ_Do9$ zD=+?UOvE=ExVS%`liYjRJtSUID(zo#K(h4ITv&DJBfTs*j)~H?5!!gg{0D5RaclHXhg?rcXYn^dfEmH1VE8DJMEDklXtil^l|IUr%JS zPp%MrJK@L3F@4YTy2yEP;Qf5|)Yu(@Ni#-p-yOxg=<#&~az1cKs@vgfwcVOoY?ybE z;Iio%CTP74oVS|yXVT~E>2S6k^~2?WYb`_ieCKZ+(MhEM*_qR3sNl;!#&hRu@hjgL zXh}DLyscK;Jla>-5rynXmn{$(Bb9J{);DJWeN_c>qk*~R^mfq27gPR@>F_DI`wzU)nLh}*#)%AoUjH-r)6D?R{CFiKu#NJK4xhTIg|5JqZ1-1DgbP^j)13a@W&07HN9=aivmmm=RI=`vflFVw;~3;5FHuDCb=!5`i#Ft?D`rI|JZ zg{du;8E)>0wtBn{-m-+kF#I032(&A9#< zGb9LY@2nqG;EYM_5IW)%I#n| z=&XfkXXhxGbY!D&%U&LHcTyZ$-$zfW{f0p%~2#?hBZ@^p2jrU9RhF`CANpYdQ8-j_z;-bNPQ_ya##06Q7JZn~jPVAVWIw1C386&Mb z39`=dKISlN2?`qEBrp<}fXbnn2GdJVuIw=nJx&N+eOLIPxqoW1Y z+Vg$5Z1qy~&US;W!JvsU!1?nvORb%k3^ZV74bpK z`mn687St={_YyrEZP3Y{>tx4n_d}2A{%l^S$KvZ31aP#YChT&X@54cd?o&@Bi)5PJ zM3k=86J~gD2CeNmo$VWfb0!O|x&EQde^G~bu9GDnnnCHT)nZp1^riLtPGl`{9pIHm z`0slyn1njn7s`qQ3fxLJIRLBK!|6HO7qE42ba5^^KNbUrTOz$VyJTC}wzyrlzr=if zhM znfb!C)SS#1*j{}xUAtg6lR88Xu6F0gBJpr0dJ~^3`(EEnJ#rlYn|_|6e=0jcuT$Ev zvJH=kpRyFKdbml}bzmcvJOx6w@CLo^c^{~;P#g9u<;TmXXgbmj%av_N?}YqMzW~Y) zb(w)z0$>rV4NVvG<7GXxBXaGyTUPtNEmCqE&rWa;rKz_a;QMQOQ0E~(7G8_3P`UCh zS!{G~Bq(xZvwN%4(|XxKEiXMdOO0>)_!3*Bw1wtjGB+REPJ0P_@1@V+|iOjrvA# zTqEDl`p#KsMbAQ6V$=<)*d`gi@2^eo2-RoaJ<)~VKl1&&T0a9#XZ91S@v8KF^HMN2!WcRk^5cFa*$mCtcu4j%trMF0(vEE! zAz z>3Lf8&WPNyC%;>F4VwmSTilsxU7NtUmjHfhOy|C*tzpPKA_Ybs8!UQ}1dYv27|Y`-^#2cr zj31J5zXV%ck0$j7J@vwMnvDCAXW?N=$?)~J$oq7eM9T{z9m&bjTxQ^KG zYV^t3r3*d_d*L@jF(Lfflf>8^NnywLp6v2?Q4LLE$UB8QkqK;L+;vysgmi|yQy}B~ zM)>SG?C1=^svflr8Rs8AL>tX5P?yz}>7$G#XPJn=Dxq(`nXq>BX%O*-_rv%Z9Z@@< zGg8g^=M?JHj$LMa3Zz-P!Pmo%f~12y=IOLF%Axx;X~blGG{Nh=(Bx2oaA0^cY^XmD zerEC9f@Xt~sLt!#%KARgM^_gliK+ICVBOPHIJf2$2;0YF+FT!i7JYJ*nL$_NFkY7( zbpMRt*j_IfnBD-omGEl|=I=(C;Tp2p^ZTQQilOWmy<}n4=AM7?clU77MX@eUvh%JM zXu-)t%-tjn;oEu9P`R)HNHTbv<$IvBX&cd~AKJ)rzIn+Qw{-&d=2ZCP8IqWf)~ce$%crQ!(2fd1V? z_R8irf7K)ueLssnglMD635!ZBZ)t$u<;k#7=kp(%F>gC!dc2S>q0Q0lb3@qsy}E)V>f5kV*ILU~c>0p>_H0`L7@K>CK-2bqT)_`_ecf~$tbN<@@ zy!$m6oz2gch1K*yN79PG( zRw{6Zy*d+l-RH0Gd%yVuQP*p`WNUABN1NT6z{%wf%%uUoaN|)u*u0z9MSd?H)U<~c zg=NgR5x5=>@xAcvZiQBP9FonRq=y3S4B&?oo0u;m1Zz%rf_pXjZ;EBK8#)(PCexj} ziYnaF2Ii+sVm}XP&s0#x&{NFc!;;_k9j}z3`pog{;_?MdYv1=Ma}}r-GL`-6d4MLr z??$^4(Ats3vKuoBsm{J%!Swr6+2!v{06<1?g-Prl9dm}dxU6H&4=`dywQekFGr8aB z{^bCZ)qh3xAJy{#ab8esQ)dc~0?AiKG1NcS&uQXi_z7 z7SQ)z#yEe7fG+FHgm+f(^-gi^VroHVu{3wpW49l+{y^(Q4zuhl=Dp1?6Z#Kt;Px$; zYn9r**G}d#qYv^MYQxmdoC^*X#KVS2AJ}Na*Yd)=u9Rv00NI3R{gB@!XXfnMEU-5& z7GByr8OAIL9Fv1dWY=`&c@=^tq}OBK$v`iCd| zNJ56}jiDhYN01-ICJruV9IaLV=$bHEL`BVCENicnG$(V7#EhPTad9@wNwo8+~ zd{9JvDwxXnMQ)+%h9<&VubJ@ZAr(%}L~ng`p}bt$WtbYZ`2AQ~#Xq<*p(qs!RrH}x z9-rsn_Q4+YJ69xC3F|?%YYt?b+o=n+mnXt;0}Y|m2mZdG@nAnht1ggwC23Ns{cOS8 z_3ljU^aQv>w==vljL!pU`}Py1m6OY1P8M_nblwko;>Y=L(N%r8Xda)R*_u7{>Jm_y z%I|+#lXG0V2)u9R=Y?8XI%PmtNbjz0PxYD913c&##GITz7iyd;1!>8@eJpnZy1o3C zw4z5H)pKWG_}1hY*dK5C7pE=ekVR^P&q;S3xJ$K}Tq%f{e*naNj{Y}?EUJBRLAr6| z9ct`=dV1jJJ)k#?{)poPC;p}5C3@Fu1ld`#tSwmFwZslPibt^3{v)$bTczb%Y~@ul0rB)_BJWEziI zi1(1C(^;wZfHPF7$vUQ6Q4s7assuT`%E6%mz7HcrdPt{NrF2Q(Oe%a*K69l!1P&j* z9cVO^g4osn>@ySa-uRojK05hjhwam!F3$41*haiJCg<0noVKz_+Ir{-t24mVS|E_u zS=xO5)E^8v7Ar5HIz|)=FU0Qx|K=2E?p`gm8jwfb zAM^J3r;)MHZsaadP4Eu1)`!d9mV)Zv<4(pvjISg?%5DiN?)T15Z_vxMyuLOTH%}bBzuQFA61* zAH>r2DQs)GMlQ2W!NBtSRi)KQESYOWzB#HpZ30&Bzg~4gHJK&f9O3%&)UBXm>DLG5 z)V=!o;1Zq92rOsA6C)0T%?o({snGvOE#JLPI=jq}Dso&7IwgiP-k1YoO~XDgS(}fK zwTAIDF@W`Br*msdYjs!l-ZF-lE`@TKne7dcLsqmj_?I>1d^8he-%DcFRL_R9W*NcD z2H_kg;z4gD>)26}5VnL8Pd*Ne_tepAJtN`MHEV^^e%Cn6*}a|7(xt|d+51*g>5*bU zY3njB)GU~xvr%Z_#$!%=G(xGpx=5Z_=TKrV7O1@f44W4Yrw`pIOs06uML`AiJ^PDW zo1H(YISK2*hrn)h$?kY)y_EsK7W47>P6LKgF$K|7+%YxO)c=97=8OStIV=U<{Ursj zr}FW6xj)Y}$fFJ%*5bZR=L$9G%sZ*@;P#V$&N9u@?ob6nZ|Usd4b+&So@~m&uVCuf zJkVK!&j|f^{$*!VWmNUjT3RXGL4ELvU?*uV1lbeUgWQ#PUC^Sq?`e+pcS=pazw}W} zHZ^$2EY{mN3v_zF9%$5U1G}pEx;-6-)>1D*yriM+7E%u3A}CA$YQ;2;7*6I9(g&X`xXO6_TF;yD43V1om># zJlb-~BH(?y2rSp)F|EllT9N~t&hu+a&T2JO^VnJY$*G!Fi7xtVIT^P*TYud5rk_v^nj~Q?T=l#payfvG> zHiz8*SW~i8cx-hr zYzyv!!W4erq8UCMwYAKZRo*{Gb+Y~e5S$?1lH><7657H(QGD*o#l6Oe3CNW#|MG)U zJMsy*sfxt+M+Lyqr_^Dd$9T>jc>8C-R%;T@ePo%TrwscS|7v?>D66eZuJ_FF=5i??&ky8 z&Gst=x2}8yPyO{^6@>dO{9k+}{&`wI-QHiUH*Jchhe*f%kpofovs_1u>_ zK;9{kZQrvxluba6g3+@Yz>>Y%aC$f|hm1K~a~lmcQticcpF6W;%z=y*)NUUFo2mPP zxExcKj1`c+u`+NN%Z;=1CsSF^1C}&- zS3{?Th%EnqurOCFx&+mz@VmYa& ze^Kg-U%L+6hHLh$oJQ}*az+;O=kC_zkn@6^U;by4#9|y5tnK1Slk@AK#Yi;QHdkhU z@Cr41@l3HB#uTWIr)LGUh1nZixOvfvDy@1MSUn5>CO=ZXJ>qwWsRD-Ll%>Snx(pO2JfBUmNJy?wEPqc3mlRm#$Edx!D z%$3Dmc}>k|V@I2mrm}-im5WQI+R)sEzjJBL9%jEb49n%`1v#c6;jfvJX~TpTi9swm zrlfCN4HGk-yf(FX8XdsT?GO)q0(Qv$no+@^MwYU zE&{93N-XI=Eykv}M#l=7{W3LVwZ#`oCO|>Eo*095>22bDjI=o!ztM9xrv%jV}r z)TN}_0wM~0X|%*2lDfG|&Km{Nk}_XN`dIj74>V%;3Ym7&9cswDAK=iUY4kuP zKe(#I01leW=P-~qxB1cxX1ROQlX?Zfio5vD?+!jkksQ-yUvYgHzW};NmuZmnF^y4k zkZ0)%*}KU7)T5uuaLkebI>=}myyvP9OOp*bKP2V!N%Lj9$^-VaG#R|o5`n=(bhN$K8fYr3BM>ae|kP{Q>yy;)LM)XhZ7$HHG`9@-Tp zMrttGOSX%j>`#WnyqmzDQvQ6Ae&agTQ#o9=SiKkO{_6=XdI#tV;}lr7t{EU@8*U#} zXVXkY!18|{R9rE@@J4=fgh=+yJ@m#S3gs$hE)hOkDM2O zzMTqnUn|4+?Rd=0{MXc*S2JXls=p|;Jx|2_E~wKE(o|Tt@DunBc#KTBhT3!}O!lVa zC-s=#Mh}i+#laS-P(QL6lmXtJ@^^=+>ILz#ys;msz9BD}U2E|>@|0k>W6d{kstcd@ z)uY={>bY~8?Di#`7nd0$&KGYN8)J^;v-!$!(0g7EnGac2SIQh55XC-zw^~T%LvDBa zN;$Mmmvt3%MI*P*XCkcUv2CSU;s;79(E2XF?5CKuLpnwq-#T+nUj-Z5{8Q4`YfdLg2F=19PW5DoE zVDGQE_wV!aflueDQ`=qDGu_iw=ln>v$H`6z{`MYD8dQki64mddn`FdYXO?lXXAgC_ zNVMhNVM1d>JCG|_702ewHRxN~3<0^|TzGlJu{*avRIHs;O~AQ;f;s^M$tq&fQL7yR4`Hcu1tCz^c7}U^^>p;X=(zPsH z#RPPuhP;fy#pQ1~9o2GraDF{H@Z!JmgFnRJlEP2~+Tc{wX=76y zJ3-6~IPW1A<@C4+EAcKlPDEWf!_18H-_Fz_Im5r^Ttx6_#SX%n z$?x@`ex*ZH2bl$@W%zIXO7)rf!QKvirxj+)cnx%TW)9EZul)E#AN<;$xbr6#!?Sl7 zKf^ygp{LaA5{f}_7{(#*k6NS9V@X^4eD3>1?P^@`Z;isqlcuN~W#5Ez^;`~fY`aTA ziMi81dYTW`7?I!nrl^+cHKiQ5B9}qjJEUHN1fIJQXZ3lTW}tQ5vZd3qqZ`c{a_t+Xk1sbw7NyX6<5HD|Z<`!{FY%t+*d&)n@? z&y^iJ+=+-leHnb_7U?V^jk``&t?A!_x_ls>jXdE-oXcq@>wui_=6B*=2HJV__6@yi zL>zmmmrlXo>`Y(umR{i+$7U-&=R-TN#;2G&GhO}GR@SBW1flLmT~h;VbMDQGV%Hzv zBsOmPTQpH}@n#1s)8n&*d?^ zo$=^c(ZQrBJg5Jc0y@Wo;qAa0UNu+$tx-6j+1rAnb#4Mi%>{kFy(9_;&wU^nQsmL7 z&KLT#D|I|>AGx`pR~Kyz{ek0bv2Hw`V7jAVsF5~?&B>eO#YwikH;y5#H4wnOzmQ zI#=H=DvfZKrGNZPjI)Yk$rGk{V#~b(2Kw`%94TVoZ7sO|BOXutV~o#!5PQ?X-?gWg zMDb^}k;3YGJg)3$glD`Fd!|8uPWs1T@5}v(Eo7%Eloy{b>8!&3F9l7%bJA6D(KNrpQKB5%sbetL9&i-}5 z!f%IMCbiM{u+&LWuy}xgQFA%GiWBVcF_v+ADwcc*R-7IG4e@q@HUtWGAeUr}FK(v_ zSNLVt2^clk-(myCDx5DEV{pC-ew`Ei;p1@K2sg#O8>V^LT#WJlyoeIV5c=$4?4yVa z({pxcz^HwOT$XL)*ny=hXdH7@m{WCZK(5gtaqQG?%jteCPYd&<=AzzRq$m$d<&uw| z@mce6`BYxA^LOr!nJH6+HtLlK<74|^1vT-Zjxr?S1K!VJ@^X`%xjH-iV__9?$jKHk zUAHZxhTD!+#{K+&F916qX1_&sLvjVoSvrL>ewC{1GyNmJ%VAO)xGc_nLqntm0w%?M zDb;Pz31!4f5u^5J;r8bESKlH51Mh$nCmxab4$Q{@VZPr3W!u%W`7aTQ-HZGH?cVqEa|np;8*OR(uus_B{u%IbXz za?+%6=(fRTI$_fyY+mGokI3E%n0f9?sNB2Dloi>_$QB25@dAgX%(k_|@zt9yINh+R zz?FG3l_Fk^RgTa~Ag_Ih#uq;_blZTA=v(DZl%^E#62mdvIX50pIUh}1zrQD|Ikyva zIV57>Tx{VmM~kEB9nC9c1>Z8z=;|j{oY{z& zl_Dm2T?#e2a;dVSUW=?(#9@n^-gI)uvxKMnex&tU#K8G_Tpf?y>T47sPLTyIbh8li zRK%FKDx>!Fj#C!Q-albjF*FMCRi? z=*l(`)6A}vTKA!cGIIG@GMmF(J=Ka%F5F10IlTo9m@Z;qtR{4iXJ`xTEBTbcCj+Twu!5Sxgb|0QXLlLDbFxTWSUkR zS8P zM(jqOi>>G9)ry<*YLF~PfC{$IYi+#CV<=<)H9qFnO zYtY%O`E19*CP?~57uV>Bn3;W3sOrcjsvcuMbd&ANb?7OglVn`j!81@p<}-TQ~T%3;-MY!4 zMi{u(6-PzmN&9vwrlla}Zu|+9+ebY2`}QV<8kT=TiE~<$&)df1{?l91M<(qg9Jif7 zh7Uz9SUc%&y%5hI>_;0qL?Bo@`L~!iYf570(?-I4L9Ld>!)CLW0?03cnrR>C)~I&n7J0NjI@PCWCjnU@d35b{Aw48qMB_yg|cSPB<46pHD-h zOBb-KSF~r~T);JI#kF>5O^X=z^FtNwvF1D)_FSBIxNdxq?jdGAi(~f$QZ%fygL4{F z6OIp^j-~f<-{*g4pF(VkXa{o5aEZek0^88K-Kq)51)pE(ZKCn7dBf=0vq*GhNER}6 z6Yap~;NmumaFS~Z{bG|Jis-cq`8bIf_&gol)eIX{Z(;P3q}cQ0CN!hJh=I?hjo+Fe zNyZa;g>MWV>Fk0Bce)|WDO^`Az6Im7+k1(C52qO4ar8emhHjU_sa}g;DedE*kSkC4 z;jcbTP`cqW<~+e5uN3h-oVP>B@|6ZZZj;t$<8a(}TcTBXKAraT)IWCMI)8$@+u?8T zr+9AqO}57V6#9Br{GL*kLsGT(^OQ}Z9+5xjdFa@Kx!8HuCUm6q6!JYF-bsdB<^6^e zZX;swwl>!2Z(NHyC7^ah?Fe$gIQ&58qwxh3u+{uxG_mwJdYdMG1A>^N7fjiv zM+V{tLk>2=z?k=RF=CfhjK&2=j8XpFPww$SIIbdj={l`N>OgNY*cki{00Qa=hE6+%(`x)@QYQIjm8H)-_M4V%#@NS zwv)|DdbPwJe|xn<$UztzuOmt3CD-4^veSCH^#<;n{tpo|KQxV+JBNyi9l_=KJb}jvR-yigd6??G5 zcan$*%shJ>#V&AJL7ynH!$)6=cAQhrQ}yoMlvAfHcS*BBOflEfVSLGQy8m>p*HE!& z2kx!-=QQ6}p8wD93)FinxNqu}ThD8ovyrJ!PxBb{zNzg~rLezv8sEMs$>4WC-p;yw zjcgvXDRHJxVOq9Ewg#dIsZX|9rfPo>&?Z2osTa~ zi!KwhvU#q#p2Gx;USNR01@~4q!ASxp=2l&Q-XHbe$^%6UcAUcx7d=_5D`48IYzOd| zz0u;H5$=fwUvI{1)w0D|+XXx7J<*^$qCcbUFBNt9en+sQdR8i6g8fB*;GSq1^HLa} zpRMlnY@MOo3W1dNeGnSeU#LpMRd`F!d%@>d1=S$7iisRxj3I7L|54Wf0=W~CC&sV>O zJ-*rwj6*d>eGZ_GLmtEX!^f%`!`tEKLXCkwt1-MC=riQ{qans>QIL36ptb|K)EJh- zKrXoU)~#}ujo-YA_&g<^g=;Td!+DH1hxx)`;2Iusd@XhT*w-TBTNVlJl(9{4%w};7 z-#X+H)&8Y{a>ou4qqY;)yeGC>DPka3rAIVgpieQ{{>x>M3$F7J1K0V3XV+1FFKUX? zbvL>|OvSRM*a(YzM(8udK%XI3;_N`h;@K-{t*P-Ca>3^X#K7l;4d4jv{#gIw8=4OY1MU9kt(>elwug7w>!`hjhgJEl5d&AMx{ zi-}Hb68GKagukfWuw3go$zv7idO4) zSH`rzj%v?MK@K1N*oyehxZQpcv(nO*T72%0a$aOB0`)y0!FMRiL%;>)S4Y2-PA z-L`QUzPeGglfR{imv+}(bt2bdpaq1>Rm6|chDRU z+!jn2c5`K48(CtsSkxzq8{kR>&2FaJ{yDcOd}##!>UKymYttGgGs+nsEfi}#nnsTj z{E3*FUPM*Qz;3rC^r10NnH`)zi?btz@wwV@BqiIjTlxF&rJ@NN!*NvUb|Ux1S|(Mm z7k;cQ+DRz0pvG_YR{2O@6}b*I$J0+`(p$a{W2MW-;HO~?z0MNzNFMXTx|PzvdIHk_ za*}3=MFM8^5%G7eY^6=w4e?QFoibK#_~nf5&Tm1l*b>c#b9eu)Tw5dfbAOSpFg`AW z+ABX-jUtv3ar8d>cwv0Xb41MRZv>_PcCxBpzjZ}T9ed-~dDTq%Q)Bi_rW@8vj27(t zO@HUi$uW4?BykM?raNhSe<&VR5hmDyy*?=K8lq;&Fn0GuGZyyxfZwT=k8Tky5(crJ zPrEegQ-K!UC#!lTsO;x9C%0r)5JqK#SmT&3tnHpAIOx21zs1b6FBQ9Up(^N!5|bhC ziCwK+*>~Gb+32)iXxu^ZeSTmNP3nGItnyyif<)Kup;H^iu=0~v7@PQ}xGGn?R{*(| zD|B%mcQbbAXM;vu(C4rtt#Im_5iB!n6$8JmhxW83Bf0zv{wh_z{g^aKW zEAoDtFg^yCO@+Kz@YPOP*vEy)xSmDZSH=msvv9CDU#=BB$y?Tsir&2Mq3jTSiO9Yj zg8Vl|vTV8qKE;Z5_*~^pM&YL(otfdE zjWN`qf%WfDlN8p!!yaz8r^e#oQ(uY2r?wKXha1en$q57=R+pyOs^1gC9E5hFeAg>> z8n%?_eu`(I9kss05mJLqD~`vJ0d~ZIyYuqbN%tZ1uCIkLEao)t^q(9lnsC8@ZN4}T z>$a&P(7dqxORLu)zvgcQ%;by&xg)2Gw`8z}%cp=ioHwSLm^ZLV0m)&?G(?OncCoxO zr;E47Sj#1v^+Np7VViBV-j`^! zWn!(swSQui-2QYb>2mLzi_02L4_G4trH#-ksQ(m=G#W5Po9D_?=>-(8Au`{|52qBA zpbv3NnBNxe=(oui!A>owarvca0d=d=nOtKQ!1boMipHi_<-h6VjshAm%{i@1UeAuV z)4{KhK}wIslDtz^vo+ z_4@U1BIuR$`GD~3(LM0*ty;tlWQf*xZz;S77ZZeh)PN>(-k-2=gee0%{Q2(7e3mdo zBO5S((>*ba|4js*(H87f?CBx@$Z5>+c8(tHibot8jIUgHp8qZ8H_^2Lqt-q7x5mnR zc@2@?Oi!?L-rijPg446(?X2XqQG7XVl&Zc@^GA|3#P9}8FHZL@sKQ40T@S-_@w+Kw z@!E-g`Koz0iE*8c1UnP`TFa9;Z8+Y}(rI{U!u|Z$lh1LtSVc?| zP8+WOBWL*_w^k%kdlO|}or5KBo94^%P7_`aItX^=q~E1RbNX@fVkk0X4~Ka)2Rr|| zoo{ybG@;#qnagRz#Y`J4AHvyrXMYqKy_$#T{Bh0q-L;(vd)8U7Q|7pf%HZ_lcsr^A zN71Dh^YFy0W%=Ze?L_wmjD5cm)ULeIfG4HxqlRi6S3}sv2O>WYKBHzD>XU846r11W}#(8OR716B$1N~|F zHlCgM`J!S__Av?c2XYP9T*6G2MY74-FBQSm7`$}HIoZKbZOm&6UfFIYA2afj%bSC` zOev@D@QgK~SF@wBezyy!>uJl7b*E{X?N;@K8Q%>)e3bnVcMXXN8>neKypyUKXBZRb|>EDqy%`XKQvyjLSTFTZo+>^DU= zZp&c_w8QIHYA^Px4s$7{ zT-s|%n53G+@LctN?Hc*Rb9wqsk$oI|SOWdw`)o&kJwyFz)q(lOo!O-7Bt5uWblNAe=P=5o?2Bb+W-P`r}l2J@q2uTG8(I1bG`^c5)cy;gf_hhkrfsot_f=0rGM*Wg&$gnJT~YGxqRepCwcO>s{+^FmLDYiZ|gK-hvfCabx5lL1O3^l z@juKwjw`r2`r^$zM8qNIgQe$|on_JeQP7N4n z=YF^+>ps$e{XP46BRfz(7wQzhIJq6=6n+%Au1yb>_uw>|d9I(2d|31I&Dm}CPbIz_ zrfUNR`tzWH>(-p-jr>t-Mg3bhc~N2(@>*0Qa80$1k(+Tk&Q>RWxqP4J$L_va%eZwm zmcCoeeHUIRVxS$UO9kz~cM_;?1>Z^FyM!Gw!jH{8*pk5G&hT9V`eV&uo^Y7-mdBl; zKk9dz!Y;Q9Cv)#M5kKz}wo5iUXMZ-wbG)5|?+$8zcnz%e+psmJi&x?SO| zd*Hn0BLsh-ruHjuBfMDKgVps}nGZF!q0ciX7~!=#9;|O>YCiNCazRaP$fb@$Ub75p zbMJX%iTe(V5d48!;oYD5uq_IkvsK#R`A{ny`s^I;$KJS5%NXi!YUHyzFLk`$(4if54(?d8vymP3y1{cn%{wha3w&>Yo)Gg; zxBba4bGr9cu5W(d%zUWZ4*h{#&>yIA05$la#sSoSzjYv!UeGU|{k>&(KGc7QcAju+ z*p_j1`J)u4@}M24xxlaUodZ(x^&C#+LCpoIYtLisr=;Y+?RzQ@>e@qpc&J(>}wp9$^Fk46M%7;3| z&>x(M1}L4TnB^2sngCMPkL)lA--5A~O!mhs?OdW?NiEStAB(PJnQu&PeGcxLp^B=GNBmU7u?!;jNILxOeg?UgD8Ttb;&>zUfzdze@@5avgRuagiepl!H+1~Fc zB3{nJMKM;AN2aA{$I^*HoI}S6H!{o>AlR&L!=(CdJGUd1;Z|;*opVj*do~!Wk zO|-UR4&GhvA?Z+i18toy){#Md>b%c4kzLsw9P((71nN_(_dC4qq+ie{r0FybXG!!V zM(!1;*He4JXQ-E5688xWbC`x>&Sy%XUbcGw#oJlP?X8}0dn-$&sU&4(C5oCU_BV#w z+;g}++JLEJai7xd5~$6s-Vgp;2XlS9C&=-QzTgkkH;>_TInNuoVSHn&1nQfs_ouua zsJVGz*K_pytk{82+!c>IG8kta*(iY;=<5A4Z-@DUaQD7FaO(SRw9M>1GWhsN zSm&W;{iZO4-3{%q|HBm$s9CSxzw>q`j(5i~zjV1?Mds)ar$IB?cAsEpB)7*e;r8#m zF1Z%Be}A&Z5Vuc_lQ0~HwGlDu^90_`;w-M$xwIIC7AB!?PqeV1<`Th9EABiYlRHn~ z?I802+`HRV^xe%v^5n4=PHZV+)aM(=_YEm}95m%b3E-U>$*U&l*gIZW^NA_mrfZI~O$+C0uvlsrpBu>K34*G*d;&Sq=u zq6ht2i{N=3?9(-_#~NffqzOAE)*b(?PuHWiF=$qsrfmBco*4G&>InL#PVqOwV?G+Q zf3(`-zx7pf)iuDLm)fwUG41f*`l`Lxx`;v?2BZB0XJOb|>~FmYN_E@eNl4sN!}@O6 zLjcxy!{460_#T>AIUF5-I<3)fhrQtJpXQ-ntCP^MVKW=~3~TLS?LVxwhg{#j%W;mu zZz6a{7Z#2)M&PCp{!xXs5?toEUxsb~J_ z$@A7+Mp>Pot-9`zQ5Z8~9G+L0!;Is4Y$jNE;#GCxS@*WreW|->vMNfps>mT=J#(zv zVD?b7A^SMO4ZmIxC*(WCgwD2R%Pc8&eDn|kVj$ORe;@W~*+=H;yeW;iMj4n<<+bBg zSHr#+4)P?~%vx)9=@0Iv1px0KefAp1!su@>~7rmZvk+JzOjXm}@2|1X! z;iZm=fn>Ziry?3@{tgoMaqv7`XMhbWYte(5gk-G!kZ2^C5-ea& z>9nKH`b|)=hmIfzn-F$@wm(z2eT46k-pP1w$Yh+-O?h`(ac+w@vy*!TL78mP95m?*}?3SpjyOk63^Zn`E!S5 z;yPN>(=CG7t8Hpg*Rf*#4*XpQZyjI^mfoUY_M7+DbN;Z(V7l+|VX{>#;#qjke@SC4 zd2*V!YL?#%%@(=+BYL)*Zrc{!H;SYdEUIH*@e$0}}777BSA3FOxIoy-9-~9Qx?rP}Hek!)3r+6DT@)>faE#vwt>})}& zof%C)uD|6MToZIm+EP98I;;BhR24c6jb{y-zf`<+Uri6RCb88yaZP|euiDSu58wP< zQCZlFfIf#9>r-02x~SG!HgmDw5Y68EdR5VTyOdF0U4--l=L&1W-?&l@qfpcw5fi%M zG`aeD7uA67A6?d49A-WhWym6=p={Wja@4w|SPu)i4wjr_`hH#_(;YRJow}|Z1uMl| zUOYF1)auz)<>+BXR*-4T@)gTu#fk{Fto2QlSSjXUf7i(_s+(O^ABMP*s{JuccFUu( z>n#_uw_P6sjY zdoGN_OjAp`$|;WRU;aeMFLlhr*x2~$3Egc~7)#rxGcY#bx7vNRmdu8}i`Z_()(res z3!hEz?WQwz8yB%iW3B=|o8X#h6gC#mf4GIwjC{+$X90Ysz-J|Vrd)V%ge;Xlr?LaN zzD74rqC*9KsBnlsuH5zqwR>txaQWoUH7Ok}4D!EeTEU=%%2 zz&ySBm2^+ep%QjpB6q&|h=z{QLA86Q;4}B%ql3%EUS5+Q=u(AEms17Jt4M>?Ok^^= zm0vhl@xTt*$orgV$Gk}=YQbESqQp7p$)20DQAy7pbk8v%_P4O@kTDs<{~UL%VXXE#>uPfHK@@EqQL*8g!vg z5HoZF*UNO=4&>fix!#)y`on<&LeD^6bg9?W7UDvrn!Gg6Q8=tI&95A$l!QR2t}5#tfnn)C|)MVa2&Ms|tr zhX)Z3rFCyqUd)7;1Atu+u6TjOr&~>80a(4 zrP06zeTKR0)ieyhNK9ayEh*-C-%Jq$drjZvxcW74!Cup_ zFX&D*ho!=XqcRHynfKa6wD!9vaJ4(5Peqr_Q_i{c*`;*iOm+cYjHF!((BfO0iM2CC z4D3NFSu~gJRoa9|U7$iQ`fMOxg^2Mp$g2Ytbii3zwYL}fZsuHek-a_P#PwMmaW{hq znlEDb`#&c>=@qT&znjcXoy!i(9xPRrt5D+WwFI&ea|iY*-OFJde4M4Sn<@nRlt%9D zLFKs`l1G+jkw4?-vYiyBiZAa}X#1kIgwJ+y-GJI>-51YggC?|6Ff}R!waGM%J*4tYkbC5{`2YgC<&73EWJNu9f}jSPGp$bMdwL|@Z8hjPu+iT=hS2I`0n z=@!Ti*<4D?uc^?FksAmtxwvLt{BA<&PEVyss~u!pyFhk~9rq5v{q`weGKiIfMNB7S z11jL<32KGY7IJhU*B8O94WnOeFh@Yxv~?ZR*0g6I6IW0-2@l&*o`%XFSg< zQS)hA3C+18#vtb_>EHW0)h<1WjIo-`W*$AswEE1|vi#Xe_;*za^X}iWhAh#!PBmHS zNosxdVRcT^O!GN;s30qosIe3=MZt&2-Tl8%aZPrRPak2n#b;yo+n{}D(yznB$&KQ( z$)a#4*~IV*HK*SaGC&itW;yLx&&oZhXx~v{z!ni>lweA>Y^o_AKk)$B-rR_t{&grj zYsX@gJT;%#S-}YYobTF_9PqBCoLs${9B-<_`t%*cex+uh*P05V+dUD(=b-f-9r>|M zr^sUcS|*{VAA5O~KM~61pi`g!VZN`?k>9$siM%|kjydn`%gUZ^m+_d34kCuHRqQk2 zT2X$RGBWhOZ+>#{8+!4mI2`aS0l9|t5Z*TiYhIz6DXtaO7?+XJP1;HOYt_(mxc;=B z$qC5ut9aiJ*3`6qP7*mCdNY0AM`P2U3(@0--iCjxdGx;)jI7^?y+{65JDFJ)jOtx_ z3I6=e=e93&(7+ip1PtuavDLFv-sKNl3I=iYo?4G|PB^fb^#Yy;+RzrEY<)@abo|8dw3 zq(aL%($)wM?dgFR^=yp-GJOO)2L@cGoD6cP-nRN=#Cd5!n6VLdk$T`ay>-!`1`M>5 z-G!1C5Zu^=Zzo(HZzMF2i}#UE6-HB*qjRX1uXV|Qci&~zpJjOQ@}Btjjd6I>21_BH zqb2dw#IW;Jm-mL)B6&12Y2FuGZ|IAOZWHhUr)~n~VbEe~^qe%xcFrDhr*^iYIduwE zy$->H=X>Gf6MG7n2=7En8PbV*9al!~T-HAS^mSVlA0C6hwIK1J0!lc?{+peTW+Z+$ zLeveko}Ne@&^M*t?Yc^4lmzE(seMGGgvH_JoE^DzuwchOF^M{nd%~r3pwFi4vOBdVbPDJx!y9o0&e`E<2f6Y|sXZnDQ zb2VeuRJyYt$LQkm(y8co7qQ0hfI}K(!?aYs$*3aRgqbtCn6KX8fxYX-(H%Y-U>NhiW)xG0yh@7>TD&8NJ@LTZ zyUXd1I}GquFFj;6Nz4oAv*B4Ue4}~+O>Wl3*Ua_MkA)%^%t6gBp195S$pxd+^c&^i zSCeAOzB%L4Ztowm=$9u>-2KYAeUd(YI7<&5JR{~Z%&&nXz3{H&1j41eUZeba?Nm(V zbT+59JbOTR6X?MjhLq}zi#`x;h~Z+bUsV7QGWGuJ5ODatf#_P zo+o#fx?@SsXmr!H72c4chx#-Xa}eg&shO^rGC7GlJ#W@1zdkQNPf3QKq_oERlgf>* zxMkf5w0dtdye(A^oxLdLY0a=g>QToW%H^XTc`bjAbp5_a-1N+16m&r!-Pk2!I=dE9 zuAV2UPu~9Ik{`FEiN*7A?abY17Kia_umid7I_#Ei$eoX$DRv{s1%3W-@VabLWDKXP z-5tR-0p`0yl_&ckAqah`Y=#TdEYRT{qCYSPgF?L6S3i296V_Vz(AiGtQGaoK?$sqz zr?;-5tOL%GZq;7wHox{Lv2`o_dzLwBY9nHb9wkxjHl3t8#QT$@MtQLv<^`g2)0*M4 zT|1$OVv!5333lhlvLCi?B^2>G_(*&wRP|Jx)0aw;+X;QH6EW-Grck}@&8gQP-;-7+#0FkY-Fw<)2F2YUcJg3b&U}7tF~eV6>NL0=uorw-@1FQ&F&=s0R(>2R<)S z_RK+7Jw;5*rmLtE(j2O@s~$PIcY^eD;7q*Qwi<;qv(WtwBG=zAyS|#D(4Asz{EZ97 zDvYs7(+Z_6lf!Vx{p|?G*ny;#)Pf}^skm@|(szWeOyU!UM?BtvX16s%LrO$0h)FQ< zC_qP=$-KuOD@kq$DJ^Swe3aM0;tzZUMY|1ej@LU?udhT zPeEsv4Z;TzgOuI=TeqI%@{8z{v<2lgnU7)Jdi66o)#S!GW$lIcb_aMEJrep4QTYWNsV;hbiO%IM`W**>7Bb!Ym(og&B_eae(YH6-itx28|vRn zl6p{%hi@v^&efsj#B5U}a(b@OgT`ZfA`f+KBfdYwx^>NC`pl;J8rV8_0)}<#Eu-7~ zqcK-CDUPfC{(~&>WDGUt9(L|eMTVCsJsy7{TW)ls_l(oV)h6R{Yr`|hH&%QPZ=?x0 zE($d%&LHZOA{%J}>fd*y1})N3nHO49MNA^kyB=a-JlD88 zuuWT}(9fPbHj3vP^dc%&zm-Ze@EbV_JFt1|Qo8u3BR2kBf{r;`2{FG~nnWE+uu^4t zHKpG4AIu)V6iClm+Z8+RzlFNb7yW_pd}FYj?cAxHwg~FhD4sW7nnCrs^jdjl$y4%Y z7G|A2^6BMf+}+HT43Z>@;{#*$o7Nci+LTL7*X9oqjMbI7lc>ygca(=>?~oBTqu9{v z=a}w0U!w{7`RGy;@%}u_i;lAX?7idd*cpMB5zLE8H%Mw%da*LI`9tz;T|ZWe+p(dC zN|AnL4%)R}oC|0tM*a+ao9@M4J9DU!9T;OT51l|(Z-%mkt}PnHnD*NKRHn%#<)g4? zr2nE))G>Pu>$~eNns)jOid!JY5AM6z9CnV!q%jvPSvU-j@2=szMq5yBW24$pWsP(Ux8pn2IX6H6gr*n1j&gXtTNa z{DjfWiCYI6`3$+nu33Z^B&W&9$mtB^f@{Jj=V>_m)l7x|&`%6p6I3(oDgDE*m0!4X zj>mP}^ZY|Ig>3VCX4p~&jjRyIXC&}hGc6iNeEBLHI7P}ppJARxS4HAoWi_&biE#|f z(V4ga6T!33;y^!5SD;b!ly0OmG z?cy#fyA&(Rci;kSyzzx>YrqO-;Qewm+V;P83ci~$3s1-3&n;y%v;)_T3+;87XIo?O z;W=^zTsKavfosC!raMvhnrV1*X*L7b1nBeo zb0ug`m@kg`l*T}xrA66fWa&gzm%A3!dg2b<(fEMka#9?w$bERXOuG}`t@C*=$9#<$~f zXriC6jv0UBz7M|XrE)xNM^P;$%>1jZP`9azaQ@8k`0IKRQ`zD$*>bnNs-xVT8t`K^ z?OHp8SZ5TEleF%kUasP|p! z^c_4-6*bC^x}I#xYN6q5VC4b&sX-00YbyG4ylfHqaHp4Q`bk?#&1J%I#SM9jN*nsv zr!GB6UdWoDI@ZsE(wptUMqk%sTh+Xw>j%`Lk6xnBKa2N~4>BjH=9%@RECb!yhpq;! z!|B&_w|=!~iHdtv&O~<+JW)>XF@Fg(&Lb{V~r7l@mxFg3>i6jpek@?FRF)kEM9deT^d(w zgsx^kKt0}za|-=|T+kmF8yYULc&>Y`tmvc>g0WF^=QMfbh>dEEuPxOSV9a_}pdT9I z_&__&#ze5$uj5dU&ISy$19JyrVD5|^nnjvzvsc}>>p?-x@fP>cvRNV*^ao;~Kafkm zdoHtnMld$~JdcK4Fi#V=?qQ}n%*R_-dDAdYBfF=Nn|k(9nR?h#MRB_s|LOB_#jpwV zkMsA?Tt6`mq0c;52FKNg{7m7yb5qEGBPXQ^0(m<hIs+=Yao%#NGk3znX!{G%&!L^Pj}~CXD%e2W7ggG#4t|- zrfeWX506#FRrRE#>}j)h*@8| z05^O627S*K#~J3S_ajaAlgT>9e&k3D^K}2?1LQY{394&MFUn%vG3MMyZRWB)cdy`A z4f^gaa>2aNKcS-KNAJ=OTzxjoiU4CDE4&!(0q@1mE^q8%8AdXt|sD|Z}5-?;Ng7>9p*4r&d%hkQnhc3{j8 z?HA453a>-XbH`&C^MBKjE$Ya{SVLaGcn%F4&TL-y5tW^oh+#bcO|N$P*Gd%r@P9F{ zj%PZi^2GkBn%HfqH-_=d$NV%e2UWs|E>yWy_mh&7>8MAi2wYS4znF*bB*gwTOs}Q- zvh=hFe5ZN=j+-vl7{dL|8nbw2$H3Oar}L4R>E(l0cIYU)Ck#=BQl81JRBHl1lU7R; zm=Cd<#IXaBxTT#BUNE$ifGK|%L)|m$rn;&8N%p+6jv3d#sVq|#fj9gJ!>b%cJ8-{a z=rWTjK5>v3zIh=&w0$tPJE#_6^BaYV0Y78#?~hV^lMpfefR1Y9&yLK>J^Hls)0jp&s&IeN#C;~cbgnjY z7RBOb=lXKz@1j;O)LNBIoKL&H&}A6o*hX5b&`xje3?Ss{1;%Curw0V=z`euFOV7~} zz25b-?C(rNVCy^K$%0v-Ltt75de#hH-y1vXN#h^yiz!M_JSC-b~Z>F^&9z zTyUQPx!~Rb?spRW2jb*bl;984hkbc35Em9E5Th5ILr@$jbgW$WfgWN17|j~c zAMd&@5$wRdjAwl?_V$;c5#4s6xT#!;@Ox2HvbA$x>JxsWBrOc7kR`#~-f9Sn9v@y-KZTW`nheCU-ShIZgP|A(Gkh})Lq@Z;Ayxb#8@UJxLjCm4;G zL4B+4q^c-3pnl)%L6{|v#Y3;R#;MbTadfu0mx2D24h$u>RJh^2uErSp1Gz%3+2X9z z1Mu|o^AY5NYeM?K?%3DO8Q095j^LUAbJ=KpcZ_ci#6#j{BACn2=V4=e;C-L^<2}zJ z5cK&<{9S7IQ)fB7oOZFPxQXg-&cVh~Ysu*or-}KG#GVG~8Ym@)ncVXzTEq1#c=~>H zKiIFJGgrIa*SW8Jqw5iusa(yGHdk}xacx~*{P=T3K#{nPsq2Y0aF`z9y7)ZT&*8(5 z7iVEVhYm)j^2%lAavqc3(F{L(HXKh{W|8e={hBCF))VGkjY&E_qKL;-a~N-1s(+YC z3OYANJjYgJ{%r?h)c){xXs*5~m#c3&G&j=0>eB;MRoYqj7OA%LZ?3sj)u?!kv4F8b z^_0Y+ubju6oc{@J9xx5p9Wu@{a<4?$6UBO~n_KQuN2;9V?=B80a;?0HbhvTeqiPdS&^f2 zzMs5`v^LEZFn_CS)1MZD{y2)?3)C3Cmj&z{0WoSWJ~nb1xLSn-4yd>qgSJXVJ8BH? zGxX>G!u;EgwR9Dc6)rvt)W4mNv4Jzw&pIY~=R_Tcd_2eY z=$5<9*h|2`yx8MuD&JeEC)nXJXB#kHRwgKSLF3%v?eyj}R${KM68ZqbyijxT@%%T8 znk(i=V@&H#Dag6=EFn+T7=C=99f*NkD+hNQc+=5qAUE$A<`>M<1$6U)%Z_^r7?`K( zG35PO9ou$b!FLgJtxg&W z5mT6c8@;Ua`Oms>>`AiI$5kQ*t{amkj-xU-X(Qer9;3Hf#3XeqN31OPKX!W6#bdqe ztAxIvuLg>m4Ez|X*91P_|AtX>@p=0H!|?w64FkEfGM1k0=`Q9nTw5U5(8Q%@j}I0x ztEZL|n`VgX&$TZB@^M;`RQI)~U5v_y;I|qq@_yHpZKdaqN}r28ot72(2>qIP%&>rA zc-JHyJPL0S`ZeWOi2a(hZ5GO}xNId)XY_ZWQr+=sqjhMb=O5;J-XbIoc_)max=xet zLv^c}1eZS%_c-^YX=q9493gkq7`~SCZx}V#OUtfB<-pE0oiyY!L$ssD@cuwM5ToFJ zJ8l(8xp|H$vNjotqr2pzXjct9u}TZ;;1uD0i`ov)<$BH?OLwOuY1S_^XuUBuKIns9LhY^HLb3L?KiNxe zFwjuWWAsA1;6Yd9*sZK3Gcw@?!q!cMF;rvtxj0wd6+2ufas83@NN;~CYL_9t1E?|o zwgWM0e|S3w|6n|#wGAHTy zoqnD0+cyRI$TPjSP`bg(T$;psBh9C0iOLR(SUrpJ=zf#m0!BSw!o2GbW@fu=mJV}_ zW?>w5xEU$G-j{ZXgoFlw%k z|HABRo`%Nv@)yQXjp6-)b|40FmHG~4R{q)|)#wn7VI0DEo_IQ2(F?bh@LF{+o-cFb zY^+aG6S){mdfA;<<`#Z|Cgn9iPL!1K^e1H{>-(|C<*J0$1l~k6SF*;cL>>d2!L2 zkh=#y6MX*OWJiwqmjuDi{;y5&9ka)RKk8WJWBy@jN>0ak(GJWVc}-7wa-N2q_lL)H z9#oOWL0%tWX5#AGE?x?wh-1!Se&Bezvv{St!71>V}-xJgr-k&UB z2Vx-CKBq{;oJEg@W$%H!d$@KN0D7?C6fX^OZe{~hkQ(N7cGji5cdH>66NVkVlvdoB< zH2wTRQqE!I&h4?~wsiuAUN=_0|M5D~)@jKhRGw!^FX>=H1rPoU1? zwa$}5QY2h2F5GU80j{eF6ELs`Airjbe+hVOGi`jQ*#-fVlQB?!tmLiGZ_xh7y8#`H zOdR=me&nx>+b-QHV4Ao0kXzOrrIc09wzy zsF`>>kC)rwru0H#jrtpxNw+?DgRi@QNpaMaPmU4o+#1^^+aaqB-(wxO``jI89A6<| zU>~zlch)(ycXK_>V?J!vz@vWG2>!tSW6d`<&1T;D2|mZxw8XWee+igdPMUI!DPph1 z^7KL3k+mXb!7EKnWW5tGfAeS8f)+U1=c#~!J<7scT+bQ*`iT%5?-%RgwHgM3&kv_+ z%0rw^x*X#Am|fp;J169oh*8AqW3S$=1Pts6cBQbxnQ^*ej3v7p;*79%0>(T*Qy%J{#CcZaWqZEf>ij;$bBomnQFUTt?=XK8}3NKXhDm={Ml zOgj#9mBYZifbpEeVLEY`a~uZ7^W2MW@()A$kQ(jsTyi-~)l3t*ki+Dfx5MKD#J(9Y z4lSxI*kvPDGK&dmqd0^yHq%*y-D-S`xhZ#P6wltz9p#ZhmDJgv*)G!?Fy$QPjD`+g z87y+S+l`VpTep|eZ<6Ek_^utBcVIL#H{FptQ{iGhElv3CkZbm|*3yZZhV1Fj9*wwQ zUKq!hN=jQBvN|6;aP!@oxQTPIU}xsRPV%)#^e3{$$QE)KqYN!vE-4W((C53p z|Kox_!&o(Yx<=C7(2zB$^}sMz+h5R;AF&g;e4ee5*fn4bPqxJLa`Bl0?S%IqfxFH! zbtbb-8`*)m<2`HyK6rAbM7G5g!`wj^b>ur*9i|R(<7_f*1irrcm4sPjiWlD0!msDN z5q=l+XA#HcoownX;kckbFn7L&kHE8*SV}icHN`M@9N+5519v)*gH7{XzHpfFOGV6` z`TF?#{pSD4ozEP`F40n&!P$YiWA#Nx9zUwSu+Ao5u(PuP)6dcnN6}jUu~XG)W&VlF zZLp5JTO&I#ziwNs%sQK-q~mllWN?eG|~pE1^b`dJts=uf!$ z%KRe@T+knwgV)Xe=MT(5n9EN92IexqZljB5lpUO%g}Tu%#%GvXc?eE7IQ7qWd>+$+ z%vatvvllST1co`v^|?6n?0*+0XapGh7XhVP|#BUtN7Z;vI%{93BCFi#;5Y?#An zzMqesHGENu+gh~#lz2wXbIt$x|B5^FxSZ1e|7$8+rIIBRl94?sin=@3)w%DOL4=S- zQc6kIC`!6z$uP2S8Od5%MoERb&pDm@7Gj8*EMuLq4B0{`S^8erIh|bP^qKkR_xSZ! zj~=hy*Ltq^d0yB1T<gA;m&G3<1cqjpXAaA5HF zO)>7A@C;&&WXIxs8A$Ct8K&O0(qK&~C2GiT71J;O$VM)ThW6I0DDqoH@*Bg*l!


zV{{p3#rT$%K^3m(jygDI#Irijg_Oe@>qqy<&Hsq@f5;rxWbWxJ z>n+*GApx2nP<#uSdzy@0nOl_S+7sPjR~`3KLB_6-XX3qH=DGGjn&x9)DabQ%TnCSX zV|2@pS_^SIUPv=7_NhWWtZtpjc6lSs@a!jw`t2H4>aF{<#73~Acj9Mu&ks?sR`Z4cbx#qvUc5AN@o~$Riy+k2d6)!fIR;$@b3Zrpj8KBxB=~D;QEG@#?#S1 zwO4iPYEDztnZRQ)+GAJLLCzVCyMxjyn#vp7Vvn zCRKxp1)>Jm$*H=Hs<;T>pVg>Q_QxwAb3NK;LHh(z@n7bu^u6B2cE(w0mREqm>8bF} zD!n?Iyq+d1%HuGP?L^Mq4MJWIJaZ)fue4c{(*aNBr)OYl2H|p2F zfLG55hHN`I4_}#taRXek!780UU=xz5!}G2QWs&`?PBP+77mkFE(Sz&sGdWjZz8uWm z-`yTA{Llszhod_UhWshE9gRnHWpmXmJ-}ad)MKg+%mv>pTL7;=aE0%n=nFFM&!POh z3{_)JcjI@vn6nP!>7IE}^pY4vJ-6-GWkpD&~HrA;$uZpQlwsiePzB>s z=>*ptixo6aR@%}NbVjNt-&qvAv5w|`Pn!a6{yc^W@pFd3IhzDcLt|=m$PK<(yiw51 zI%7+_JTOrurvBl6pkyJ}G^8IGy}k>xp}-k7H9sV18X8jJ&atM5KAZPjzx z2M43L4=zeLtEJd>vMj9WSfeQnqF`HI>_a>j+g+Ng^1nBsNjqBFwRS9UA05AEs&Z)e z!kyGqw1u@}O1}GryL8Ga&w3y*Vt4 zY&n~A{He&5wDUtzqLLE?28x6BAM}b zMeF0e`B$#@kzY1{wF@+DCVsc>IR6J#WG^TBx!FngSEl;TF&oPTO}^(gu8d|O z6>!Z2j?6jf{(ZaI13rX{`z=YRzB_&Y5b8s|KbQ8k8tAd`p=&8B%P%_xte+}A%VZ9S zi*59&aYZ8(R(I5p-s1-|bHuyp8rrvM;x`pOcpog3^^e~Y-l^js+UeshluZ_|W72N6 zg(HR!hj(tD0H0TgacJGoE#aHIEYe>6XsG?;2?Gzi!RO!S zg4kb04W7^QQGGtxS|}?cKj)2kZvof*GZH>U_34xF#Scn%3Eo`zDK8XhmLd&#mmn%j zDV2r3ivxG3cZ2i&L7lQtot09ZXJ0h}3ypfhZnkc9>fGnt5?X5euFFTM!sTsYr!K>x zkAE>q3p|^&u_w;jzCGsBJ~9A^mhjoj%0v`nNj&*S3$p5w7cXr-I&?_+37GVU%V% z%6<0BbCmb@=1XBrv7L#2{yJy3N_x()%zUf&eO*k@{K1+Zk6jfsch=+bo;$S=u{ zL4BBv`cN13Me}Jur0%aB6|_b1cEvQEyYL>4`#CROPq0&-9>ify*yu|7sN;FcGx254miqbjE1Q;iv^1vq3k+E8&TtU@GzxC9^{XAzoJ*VBFBOLC^uGT{TVMN!X*Ji7@m0jZ7g2%G zDq9>=G+wkcUXPrAV~j@`F&-P^U|`Z%*r#T^eEqWAl^HX2D>rvov(P7RQ&5n)n| zjnyy)eg7tnJBqu|N^uuq+e+9`_oqVp{a0{|LhV?gb84*=cM;nAS2hvF5#ceE)8Mo0 zf%d<$w^0m?#o8b1*g@y!TIt+8NB;_Y{v5j3@Kwi?q#YCwpp#-M&d)XB^wGV<12c_; zvvaY`MvYMXhE|H-h#ynVYNF0=8g$mLmCpL_#+S2dhd{Wox=|gCR2Gg0$d5GP z@=zR+SjLyOqjNo7Z*;EL0-Y&XnuT+#&z}Qxd}0KDDb)v^N$FbGoJoy&HjQgC=RDx^ zbL(i(nUwA>IROup)8biSj*XJlC8kxp}+W{T(gq#a3v%Zf&K z4K-JNt(i1ooHiN7Lg4s>+ljxhIJXXN7a8XuX>fc(LmG6Jq{C-zc-+GWxp1BbMSn!r zN7CT>G^BAaInJ~g{*8*|^!RkWGhlgYFjS?7vXQ%2fbpHgxZD6wJ>FhpsCs8?#D_Zk z1}Z~>;ayW-L6hFNgHV5mI6Z!!R}+<{vtfaCWFg=pr@+^Z0|ZUuqV|HO^ZhxD=Kup$ z#v5H-k%wQWq`yoHxr(NEe5qL!xJn+Ni1_@+*5GB zYOUZe$hKctHWK)HwujqasNi|8=OC!Hc+Vu+hbf&#ftii0;Gm}-Fv++Ku#LVh3$YB8 zSO)jA)Q5;=c!Fi1#4=bT^M*++t4%Afav-`J}RsUhpk?+$_ z^^H-2Mj9`2OrKU90gJ9Y0}E!<)sXe+`XLkaM{zHGRCUWDiP>Z76SPls4wGpq_zvOjzs^|^98l>hiND-w?t;0Cu8s$(nw|1?`N_sGNz)~aV(sS z{6!}JmA|Nslj(=P=ie;vFNBy1>@VEXY1m!fU)083%)3BC3mJbw#+YqKv9f(-{Dq{! z{-Plb8G8^o$OZby`-|H6jR2$>C!;}Y9Yy#HR?c6bb)J&edGBUgR&Jd~>ljV=3s%lw zpmmHU{0=MUckrwvd;u%x3(&ej6F!BN^C=DOeUbixY&%-#S-EwdtTXZ#ten3f_qE79 zG}7;o8glQ8^cQ4VXr1Te)_Jm@k-y;N{6#~1Xrxae`w;m8t^r>lyN5>l0&?#Q`3qLg zUyx;?b)J=5=gDzL{(_bB7vvrq@;j`Y-&t?>kvFjDt-XKYXF4P21KTtymEC@31nlYQ z2?C78JLSvg^;00fYOaPS=#5?8UU+?0Zn%Zi0_NVB8 zi0f?fi<9iLHDjRnPeZ^2YcUSfV(2Np^{68L1pNjBbs*H}eZ^8aH zIg9<SCe@&&z8!we)}`qKKEyBZ$(4H&D}u$&tLYM4BofZKFfYBoXhM%XXoFtM!u!&H3dh(YeBZZ%b2 zw!X+-9kvMU-x&y3utcKSoLx$jx};r%h}#>Kg;m3f)r(WZS4v+di?frmOytgX+31Ix884-$1FQ{K_-248ej zUQ=@&x}Vb|8HK`~w?7K+Crv#gwWG2UbuVWeq|cU}bJLWd*t+~bH7C}E!nlvG1kKb- z!?Z(E6LrS1H|cjHFDTwzRda*VS}8~SBMnz( z$|x&>pjVCN=$i-YADE%)Kp68(EbCynvvy^(HM*ih z-INM$x@N#mHJ5+XhgokB2%o?CAk^pFX znK?OgGQ8g5z0j^-2A|WmeQc)PxigKv)?NWZ`Y+^~mqjy;yhC9~J5l3Yct-o_rIFT^ z+3Nl=9e}d381AL#N@kr^C^R`Bw(G$04cf_%p7R?`wz`)Y3#hmHBu$E!7OGSFG}-|d;gM^oUujunEP?!_PYsh2zHy10DH zvl%8#R*st6S7FFlxrf4;|A_t5`BQem!BI9k(`!4?lA&U{C!x5E6=j;A6NBJkN19I{E&pnM7iQa**p``R!exoR%_ z*c*+hCJ0VM-!kK86#q2U*yx&BZ5Ga#jUJ)AcP;N}`mvK?yFp@|vE~rytQ+EUpdjtc zJ9}-qnwvS;o57lraaC@*P~6bU}raazJ5qB7c_cr#rmLJ5(QE&i8;+LGo6RV zaqScRn73|0&`M8yc2G_VUdlI5M5zPJw;~q6X!^&`P;B0#{ftW7eVkxh8JRg4>}mUtgSuDA$Ho%Io2Jtp`)K zR?Qg|c4yLBO@&FT#CD;)9$G0ENx!*(>7AzLMsMIW9Y2S{X79!M<9nXd{$)=WtUYs6 z@F_Sx8u!P^98c=#j3lAXyVQw-=EN*fBXQTop2MksCQcDFms3T}dJknCJ44%_payLh zHPpfa!OqdnE;JMKL^x+V5a!>1Nw<8;;jLI!exo&lChGQWZd-L&e_WPx^jjx)6FpGW zB}6DIT+3@&ROh6n`?#1_J^JH12R1p^zc{y=QoPzOXaaNB2pUV9h=QK?m4cn$A6Gi9 zUe*|-x`hgwh$_*}8UvpK+-9j=0YQdfO8Z{~jcdQPf}M)>&kC?Y>YuPKWG6( zBW8`^Pgko2h+3 z<7{)m&Pg=xX~<6QjoaJ-K91voHop`WQRc@qwRX^*gj(s|!h0yM;*lL03dhBd+**$F z1*4a@6zt%6i0$BcxCDKp*sPRQSmYSF4ZSxQNOeZ{4Qi$P2CrACxs;!VyLDS|?}VS% z1`xZsonQygd29#I`2Z9j^ozwF#aQEgiqB1wYwh4?2W#-Na}a%ZF|*sAytywkHRBz= zXz-lJ8V#EB##hwv^FqbR`GZ<9b2ck$?d&_nX>Xs}s9X_RNWVg{Wu}uR<>jv~*7Qi< z04mMI`k*^ewbGraMsL-y>Z7G*vu?3w{SaSZy-sX<7B*=3yJO-to(}tJHRz63t#n6g;cGP)iK9lQDG@(%-%|xF8f*o=lBkeqDvJH?LX}m}~SR*|xR_!`sf2pQWkQkp3b9<$c{@ z{!RZON6m!iRI)>kdml6>aD8snJcE)3|4oXO#lMfb9?2?}E`UAlqif&Q@!!cDPZdj0 zF4~8&f`5;<6@9nxzcq25`1ft-UA@|*wV?THl=!}Z*qkQV9LTXb;$H!X2@jAs+*E5qH0-<1TvLpgp& zOidF^4dj>_u{lk!Ign#>#Q3zt`27M=gzZkph3fVq1^J?=*QP80kNO^)BmT!)CwsfO76 zzi{_|;rD-Ib26vo2fbF598;6|A`zPdIW{NrMIy$h@9wFJ%oVsrGaC20N^nv$-UF8^`EDNzYlw)%;UjSliD96;e z4{=#FY!2nvoUAiqd??5Gh|QIln`+n`Ho)e!IRy}#Lpe4l@A*gE4du8S&sAJj4ZlM< ze#dhaYiigWHo)eBriRTqIW|Y!tt7acljCmueBrWc_??sEcQRiIVsmtNge;p2V^PEA zoE)2zxls^zqa4p)b2ol=2!7|}_??{3h`TvC?k49U;&)Dt-^qSPOzn#2YkfAyYZUGu z+|P)qYc=(lT38dXhO|SnIl2Cjc1Xr2*E+=AoE&$PYbN4%ff?)bJGqV_Hs=~(^V&5E zu{qZOo7b)_h|Ptv>a%(M^#}JMUZ+Uz{(2n~H6*{2>mlN9D97DoS%}|-wXi@=CA=auk{y*&4sf5f3o@i0hhG7*8l(j literal 0 HcmV?d00001 diff --git a/include/collada/effect.h b/include/collada/effect.h new file mode 100644 index 0000000..6f7b746 --- /dev/null +++ b/include/collada/effect.h @@ -0,0 +1,8 @@ +#pragma once + +namespace collada::effect { + extern unsigned int program_static; + extern unsigned int program_skinned; + + void load_effects(); +} diff --git a/include/collada/instance_types.h b/include/collada/instance_types.h new file mode 100644 index 0000000..a286154 --- /dev/null +++ b/include/collada/instance_types.h @@ -0,0 +1,28 @@ +#pragma once + +#include "directxmath/directxmath.h" + +#include "collada/types.h" + +namespace collada::instance_types { + + struct __attribute__((aligned(16))) lookat { + XMVECTOR eye; + XMVECTOR at; + XMVECTOR up; + }; + + struct __attribute__((aligned(16))) transform { + union { + instance_types::lookat lookat; + XMMATRIX matrix; + XMVECTOR vector; + }; + types::transform_type type; + }; + + struct node_instance { + transform * transforms = NULL; + XMMATRIX world; + }; +} diff --git a/include/collada/scene.h b/include/collada/scene.h new file mode 100644 index 0000000..9032a5d --- /dev/null +++ b/include/collada/scene.h @@ -0,0 +1,32 @@ +#pragma once + +#include "collada/types.h" + +namespace collada::scene { + struct static_skinned { + unsigned int static_mesh; + unsigned int skinned_mesh; + }; + + struct state { + types::descriptor const * descriptor; + + unsigned int vertex_buffer_pnt; + unsigned int vertex_buffer_jw; + unsigned int index_buffer; + + static_skinned * vertex_arrays; + int * vertex_buffer_strides; + + void load_layouts(); + void load_scene(types::descriptor const * const descriptor); + + void draw_geometry(types::geometry const & geometry, + types::instance_material const * const instance_materials, + int const instance_materials_count); + void draw_instance_geometries(types::instance_geometry const * const instance_geometries, + int const instance_geometries_count); + void draw_node(types::node const & node); + void draw(); + }; +} diff --git a/include/collada/types.h b/include/collada/types.h new file mode 100644 index 0000000..b7dff97 --- /dev/null +++ b/include/collada/types.h @@ -0,0 +1,407 @@ +#pragma once + +namespace collada::types { + + struct float2 { + float const x; + float const y; + }; + + struct float3 { + float const x; + float const y; + float const z; + }; + + struct float4 { + float const x; + float const y; + float const z; + float const w; + }; + + struct float7 { + float const a; + float const b; + float const c; + float const d; + float const e; + float const f; + float const g; + }; + + struct matrix { + float const _11, _12, _13, _14; + float const _21, _22, _23, _24; + float const _31, _32, _33, _34; + float const _41, _42, _43, _44; + }; + + ////////////////////////////////////////////////////////////////////// + // geometry + ////////////////////////////////////////////////////////////////////// + + enum class input_format { + FLOAT1, + FLOAT2, + FLOAT3, + FLOAT4, + INT1, + INT2, + INT3, + INT4, + }; + + struct input_element { + char const * const semantic; + int const semantic_index; + enum input_format const format; + }; + + // inputs uniqueness is by evaluted pointer + struct inputs { + input_element const * const elements; + int const elements_count; + }; + + struct triangles { + int const count; + int const index_offset; + int const inputs_index; + }; + + struct mesh { + // `triangles` must become a union if non-triangles are implemented. + // instance_geometry is an index into this array. + types::triangles const * triangles; + int const triangles_count; + + int const vertex_buffer_offset; + int const vertex_buffer_size; + + int const index_buffer_offset; + int const index_buffer_size; + }; + + struct geometry { + types::mesh mesh; + }; + + ////////////////////////////////////////////////////////////////////// + // light + ////////////////////////////////////////////////////////////////////// + + enum class light_type { + AMBIENT, + DIRECTIONAL, + POINT, + SPOT, + }; + + struct light { + light_type type; + float3 color; + }; + + ////////////////////////////////////////////////////////////////////// + // image + ////////////////////////////////////////////////////////////////////// + + struct image { + const char * resource_name; + }; + + ////////////////////////////////////////////////////////////////////// + // effect + ////////////////////////////////////////////////////////////////////// + + enum class color_or_texture_type { + COLOR, + TEXTURE, + }; + + struct texture { + int const image_index; // index in to images + }; + + struct color_or_texture { + color_or_texture_type type; + union { + float4 color; + types::texture texture; + }; + }; + + struct blinn { + color_or_texture const emission; + color_or_texture const ambient; + color_or_texture const diffuse; + color_or_texture const specular; + float const shininess; + color_or_texture const reflective; + float const reflectivity; + color_or_texture const transparent; + float const transparency; + float const index_of_refraction; + }; + + struct lambert { + color_or_texture const emission; + color_or_texture const ambient; + color_or_texture const diffuse; + color_or_texture const reflective; + float const reflectivity; + color_or_texture const transparent; + float const transparency; + float const index_of_refraction; + }; + + struct phong { + color_or_texture const emission; + color_or_texture const ambient; + color_or_texture const diffuse; + color_or_texture const specular; + float const shininess; + color_or_texture const reflective; + float const reflectivity; + color_or_texture const transparent; + float const transparency; + float const index_of_refraction; + }; + + struct constant { + float4 const color; + color_or_texture const reflective; + float const reflectivity; + color_or_texture const transparent; + float const transparency; + float const index_of_refraction; + }; + + enum class effect_type { + BLINN, + LAMBERT, + PHONG, + CONSTANT, + }; + + struct effect { + effect_type const type; + union { + types::blinn const blinn; + types::lambert const lambert; + types::phong const phong; + types::constant const constant; + }; + }; + + ////////////////////////////////////////////////////////////////////// + // node + ////////////////////////////////////////////////////////////////////// + + struct lookat { + float3 const eye; + float3 const at; + float3 const up; + }; + + enum class transform_type { + LOOKAT, + MATRIX, + ROTATE, + SCALE, + SKEW, + TRANSLATE, + }; + + struct transform { + transform_type const type; + union { + types::lookat const lookat; + types::matrix const matrix; + float4 const rotate; + float3 const scale; + float7 const skew; + float3 const translate; + }; + }; + + enum class node_type { + JOINT, + NODE, + }; + + struct material { + types::effect const * const effect; + }; + + struct bind_vertex_input { + int input_set; // TEXCOORD semantic input slot + }; + + struct instance_material { + int const element_index; // an index into mesh.triangles + types::material const * const material; + + // heavily simplified from collada data model + bind_vertex_input const emission; + bind_vertex_input const ambient; + bind_vertex_input const diffuse; + bind_vertex_input const specular; + }; + + struct instance_geometry { + types::geometry const * const geometry; + + instance_material const * const instance_materials; + int const instance_materials_count; + }; + + struct skin { + types::geometry const * const geometry; // source + + matrix const * const inverse_bind_matrices; // one per joint + + int const vertex_buffer_offset; + int const vertex_buffer_size; + }; + + struct controller { + types::skin skin; + }; + + struct instance_controller { + types::controller const * const controller; + + //node const * const skeleton; // a reference to the root of the joint heirarchy + + int const * const joint_node_indices; // one per joint + int const joint_count; + + instance_material const * const instance_materials; + int const instance_materials_count; + }; + + struct instance_light { + types::light const * const light; + }; + + ////////////////////////////////////////////////////////////////////// + // animation + ////////////////////////////////////////////////////////////////////// + + enum class interpolation { + LINEAR, + BEZIER, + }; + + struct source { + union { + float const * const float_array; + enum interpolation const * const interpolation_array; + }; + int const count; + int const stride; + }; + + struct sampler { + source const input; + source const output; + source const in_tangent; + source const out_tangent; + source const interpolation; + }; + + enum class target_attribute { + A, // alpha color component + ANGLE, // euler angle + B, // blue color component + G, // green color component + P, // third texture component + Q, // fourth texture component + R, // red color component + S, // first texture coordinate + T, // second texture coordinate + TIME, // time in seconds + U, // first generic parameter + V, // second generic parameter + W, // fourth cartesian coordinate + X, // first cartesian coordinate + Y, // second cartesian coordinate + Z, // third cartesian coordinate + ALL, + }; + + struct channel { + sampler const * const source_sampler; + int const target_node_index; // an index into the nodes array + int const target_transform_index; + types::target_attribute const target_attribute; + }; + + /* + struct animation { + animation const * const animations; // nested animations + int const animations_count; + + channels const * const channels; + int const channels_count; + }; + */ + + struct camera { + float xfov; + float yfov; + float znear; + float zfar; + float aspect_ratio; + }; + + ////////////////////////////////////////////////////////////////////// + // scene + ////////////////////////////////////////////////////////////////////// + + struct node { + int const parent_index; + + node_type const type; + + transform const * const transforms; + int const transforms_count; + + instance_geometry const * const instance_geometries; + int const instance_geometries_count; + + instance_controller const * const instance_controllers; + int const instance_controllers_count; + + instance_light const * const instance_lights; + int const instance_lights_count; + + channel const * const * const channels; + int const channels_count; + + //node const * const * const nodes; + //int const nodes_count; + }; + + struct descriptor { + // these are only the top-level nodes; nodes may have children + node const * const * const nodes; + int const nodes_count; + + inputs const * const inputs_list; + int const inputs_list_count; + + image const * const * const images; + int const images_count; + + //animation const * const animations; + //int const animations_count; + + // hmm, this part is not really platform-agnostic: + char const * const position_normal_texture_buffer; + char const * const joint_weight_buffer; + char const * const index_buffer; + }; +} diff --git a/include/collada_scene/ship20.h b/include/collada_scene/ship20.h new file mode 100644 index 0000000..62870dc --- /dev/null +++ b/include/collada_scene/ship20.h @@ -0,0 +1,7 @@ +#pragma once + +#include "collada/types.h" + +namespace collada_scene::ship20 { + extern collada::types::descriptor const descriptor; +} diff --git a/include/data/scenes/ship20.h b/include/data/scenes/ship20.h new file mode 100644 index 0000000..bf1e416 --- /dev/null +++ b/include/data/scenes/ship20.h @@ -0,0 +1,3 @@ +namespace ship20 { + extern collada::types::descriptor const descriptor; +} diff --git a/include/new.h b/include/new.h new file mode 100644 index 0000000..b1a73dd --- /dev/null +++ b/include/new.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +template +T * New(int elements) +{ + return (T *)aligned_alloc(16, (sizeof (T)) * elements); +} diff --git a/shader/collada/generic.frag b/shader/collada/generic.frag new file mode 100644 index 0000000..8040155 --- /dev/null +++ b/shader/collada/generic.frag @@ -0,0 +1,8 @@ +#version 430 core + +out vec4 Color; + +void main() +{ + Color = vec4(1, 0, 0, 1); +} diff --git a/shader/collada/static.vert b/shader/collada/static.vert new file mode 100644 index 0000000..952d348 --- /dev/null +++ b/shader/collada/static.vert @@ -0,0 +1,12 @@ +#version 430 core + +layout (location = 0) in vec3 Position; +layout (location = 1) in vec3 Normal; +layout (location = 2) in vec3 Texture; + +layout (location = 0) uniform mat4 Transform; + +void main() +{ + gl_Position = Transform * vec4(Position, 1); +} diff --git a/src/collada/animate.cpp b/src/collada/animate.cpp new file mode 100644 index 0000000..37ec7d8 --- /dev/null +++ b/src/collada/animate.cpp @@ -0,0 +1,205 @@ + static inline float fract(float f) + { + return f - floorf(f); + } + + static inline float loop(float f, float n) + { + return fract(f / n) * n; + } + + static inline int find_frame_ix(source const& source, float t) + { + for (int i = 0; i < source.count - 1; i++) { + if (source.float_array[i] <= t && source.float_array[i+1] > t) { + return i; + } + } + return -1; + } + + static inline float linear_interpolate_iv(source const& source, int frame_ix, float t) + { + float prev = source.float_array[(frame_ix+0) * source.stride]; + float next = source.float_array[(frame_ix+1) * source.stride]; + return (t - prev) / (next - prev); + } + + static inline float linear_interpolate_value(source const& source, int frame_ix, int parameter_ix, float iv) + { + float prev = source.float_array[(frame_ix+0) * source.stride + parameter_ix]; + float next = source.float_array[(frame_ix+1) * source.stride + parameter_ix]; + return prev + iv * (next - prev); + } + + static inline float pow3(float f) + { + return f * f * f; + } + + static inline float pow2(float f) + { + return f * f; + } + + static inline XMVECTOR bezier(XMVECTOR p0, XMVECTOR c0, XMVECTOR c1, XMVECTOR p1, float s) + { + return + p0 * pow3(1 - s) + + 3 * c0 * s * pow2(1 - s) + + 3 * c1 * pow2(s) * (1 - s) + + p1 * pow3(s); + } + + static inline float bezier_binary_search(XMVECTOR p0, XMVECTOR c0, XMVECTOR c1, XMVECTOR p1, float want) + { + float low = 0.0f; + float high = 1.0f; + + int iterations = 0; + while (iterations < 20) { + iterations += 1; + + float s = (high + low) * 0.5f; + XMVECTOR bs = bezier(p0, c0, c1, p1, s); + float t = XMVectorGetX(bs); + + const float epsilon = 0.001f; + if (fabsf(t - want) < epsilon) { + return XMVectorGetY(bs); + } + + if (t > want) { + high = s; + } else { + low = s; + } + } + + print("%f %f\n", XMVectorGetX(p0), XMVectorGetY(p0)); + print("%f %f\n", XMVectorGetX(c0), XMVectorGetY(c0)); + print("%f %f\n", XMVectorGetX(c1), XMVectorGetY(c1)); + print("%f %f\n", XMVectorGetX(p1), XMVectorGetY(p1)); + assert(false); + } + + static inline XMFLOAT2 const * tangent_index(source const& source, int frame_ix, int parameter_ix) + { + int ix = frame_ix * source.stride + parameter_ix * 2; + return (XMFLOAT2 const *)&source.float_array[ix]; + } + + static float bezier_sampler(sampler const * const sampler, int frame_ix, int parameter_ix, float t) + { + /* + P0 is (INPUT[i] , OUTPUT[i]) + C0 (or T0) is (OUT_TANGENT[i][0] , OUT_TANGENT[i][1]) + C1 (or T1) is (IN_TANGENT[i+1][0], IN_TANGENT[i+1][1]) + P1 is (INPUT[i+1], OUTPUT[i+1]) + */ + + float frame0_input = sampler->input.float_array[frame_ix+0]; + float frame1_input = sampler->input.float_array[frame_ix+1]; + + float frame0_output = sampler->output.float_array[(frame_ix+0) * sampler->output.stride + parameter_ix]; + float frame1_output = sampler->output.float_array[(frame_ix+1) * sampler->output.stride + parameter_ix]; + + XMVECTOR p0 = XMVectorSet(frame0_input, frame0_output, 0, 0); + XMVECTOR c0 = XMLoadFloat2(tangent_index(sampler->out_tangent, frame_ix + 0, parameter_ix)); + XMVECTOR c1 = XMLoadFloat2(tangent_index(sampler->in_tangent, frame_ix + 1, parameter_ix)); + XMVECTOR p1 = XMVectorSet(frame1_input, frame1_output, 0, 0); + + return bezier_binary_search(p0, c0, c1, p1, t); + } + + static void apply_transform_target(transform& transform, + enum target_attribute channel_target_attribute, + float value) + { + switch (transform.type) { + case transform_type::TRANSLATE: __attribute__((fallthrough)); + case transform_type::SCALE: + switch (channel_target_attribute) { + case target_attribute::X: transform.vector = XMVectorSetX(transform.vector, value); return; + case target_attribute::Y: transform.vector = XMVectorSetY(transform.vector, value); return; + case target_attribute::Z: transform.vector = XMVectorSetZ(transform.vector, value); return; + default: assert(false); + } + case transform_type::ROTATE: + switch (channel_target_attribute) { + case target_attribute::X: transform.vector = XMVectorSetX(transform.vector, value); return; + case target_attribute::Y: transform.vector = XMVectorSetY(transform.vector, value); return; + case target_attribute::Z: transform.vector = XMVectorSetZ(transform.vector, value); return; + case target_attribute::ANGLE: transform.vector = XMVectorSetW(transform.vector, value); return; + default: assert(false); + } + default: + assert(false); + break; + } + } + + static enum target_attribute const rotate_target_attributes[] = { + target_attribute::X, + target_attribute::Y, + target_attribute::Z, + target_attribute::ANGLE, + }; + + static enum target_attribute const translate_scale_target_attributes[] = { + target_attribute::X, + target_attribute::Y, + target_attribute::Z, + }; + + static void animate_channel_segment(channel const& channel, + transform& transform, + int frame_ix, float t) + { + enum target_attribute const * target_attributes = &channel.target_attribute; + int target_attributes_count = 1; + if (channel.target_attribute == target_attribute::ALL) { + switch (transform.type) { + case transform_type::TRANSLATE: __attribute__((fallthrough)); + case transform_type::SCALE: + target_attributes = translate_scale_target_attributes; + target_attributes_count = 3; + break; + case transform_type::ROTATE: + target_attributes = rotate_target_attributes; + target_attributes_count = 4; + break; + default: + assert(false); + break; + } + } + + for (int parameter_ix = 0; parameter_ix < target_attributes_count; parameter_ix++) { + + enum collada::interpolation interpolation = channel.source_sampler->interpolation.interpolation_array[frame_ix]; + + float value; + if (interpolation == interpolation::BEZIER) { + value = bezier_sampler(channel.source_sampler, frame_ix, parameter_ix, t); + } else { + float iv = linear_interpolate_iv(channel.source_sampler->input, frame_ix, t); + value = linear_interpolate_value(channel.source_sampler->output, frame_ix, parameter_ix, iv); + } + + apply_transform_target(transform, target_attributes[parameter_ix], value); + } + } + + static void animate_node(node const& node, node_instance& node_instance, float t) + { + for (int i = 0; i < node.channels_count; i++) { + channel const& channel = *node.channels[i]; + transform& transform = node_instance.transforms[channel.target_transform_index]; + + int frame_ix = find_frame_ix(channel.source_sampler->input, t); + assert(frame_ix >= 0); // animation is missing a key frame + + animate_channel_segment(channel, transform, frame_ix, t); + } + } diff --git a/src/collada/effect.cpp b/src/collada/effect.cpp new file mode 100644 index 0000000..46d2572 --- /dev/null +++ b/src/collada/effect.cpp @@ -0,0 +1,16 @@ +#include "opengl.h" + +#include "collada/effect.h" + +namespace collada::effect { + + unsigned int program_static; + unsigned int program_skinned; + + void load_effects() + { + program_static = compile_from_files("shader/collada/static.vert", + nullptr, + "shader/collada/generic.frag"); + } +} diff --git a/src/collada/node_state.cpp b/src/collada/node_state.cpp new file mode 100644 index 0000000..b55fb1e --- /dev/null +++ b/src/collada/node_state.cpp @@ -0,0 +1,67 @@ +#include "directxmath/directxmath.h" + +#include "collada/types.h" +#include "collada/instance_types.h" + +namespace collada::node_state { + inline static void load_transform(instance_types::transform * instance_transform, + types::transform const & transform) + { + switch (transform.type) { + case types::transform_type::LOOKAT: + instance_transform->lookat.eye = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.eye); + instance_transform->lookat.at = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.at); + instance_transform->lookat.up = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.up); + break; + case types::transform_type::MATRIX: + instance_transform->matrix = XMLoadFloat4x4((XMFLOAT4X4 *)&transform.matrix); + break; + case types::transform_type::ROTATE: + instance_transform->vector = XMLoadFloat4((XMFLOAT4 *)&transform.rotate); + break; + case types::transform_type::SCALE: + instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.scale); + break; + case types::transform_type::TRANSLATE: + instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.translate); + break; + default: + assert(false); + } + } + + void initialize_node_transforms(types::node const * const node, + instance_types::node_instance * const node_instance) + { + for (int i = 0; i < node->transforms_count; i++) { + load_transform(&node_instance->transforms[i], + node->transforms[i]); + } + } + + inline static bool vector_equal(XMVECTOR V1, XMVECTOR V2) + { + uint32_t CR; + XMVectorEqualR(&CR, V1, V2); + return XMComparisonAllTrue(CR); + } + + inline static XMMATRIX transform_matrix(instance_types::transform const& transform) + { + switch (transform.type) { + case types::transform_type::TRANSLATE: + return XMMatrixTranslationFromVector(transform.vector); + case types::transform_type::ROTATE: + assert(!vector_equal(XMVectorSetW(transform.vector, 0), XMVectorZero())); + return XMMatrixRotationNormal(transform.vector, + XMConvertToRadians(XMVectorGetW(transform.vector))); + case types::transform_type::SCALE: + return XMMatrixScalingFromVector(transform.vector); + case types::transform_type::MATRIX: + return transform.matrix; + default: + assert(false); + break; + } + } +} diff --git a/src/collada/scene.cpp b/src/collada/scene.cpp new file mode 100644 index 0000000..1c824aa --- /dev/null +++ b/src/collada/scene.cpp @@ -0,0 +1,280 @@ +#include +#include +#include + +#include "glad/gl.h" +#include "directxmath/directxmath.h" + +#include "new.h" +#include "file.h" +#include "view.h" + +#include "collada/types.h" +#include "collada/instance_types.h" +#include "collada/scene.h" +#include "collada/effect.h" + +namespace collada::scene { + + struct layout { + struct { + unsigned int position; + unsigned int normal; + unsigned int texture; + unsigned int blend_indices; + unsigned int blend_weight; + } attribute; + struct { + unsigned int transform; + } uniform; + }; + + const layout layout = { + .attribute = { + .position = 0, + .normal = 1, + .texture = 2, + .blend_indices = 3, + .blend_weight = 4, + }, + .uniform = { + .transform = 0, + }, + }; + + unsigned int attribute_location(char const * const semantic, + int semantic_index) + { + if (strcmp(semantic, "POSITION") == 0 && semantic_index == 0) { + return layout.attribute.position; + } + if (strcmp(semantic, "NORMAL") == 0 && semantic_index == 0) { + return layout.attribute.normal; + } + if (strcmp(semantic, "TEXCOORD") == 0 && semantic_index == 0) { + return layout.attribute.texture; + } + if (strcmp(semantic, "BLENDINDICES") == 0 && semantic_index == 0) { + return layout.attribute.blend_indices; + } + if (strcmp(semantic, "BLENDWEIGHT") == 0 && semantic_index == 0) { + return layout.attribute.blend_weight; + } + printf("unknown semantic %s index %d\n",semantic, semantic_index); + assert(false); + } + + unsigned int input_format_gl_size(types::input_format format) + { + switch (format) { + case types::input_format::FLOAT1: return 1; + case types::input_format::FLOAT2: return 2; + case types::input_format::FLOAT3: return 3; + case types::input_format::FLOAT4: return 4; + case types::input_format::INT1: return 1; + case types::input_format::INT2: return 2; + case types::input_format::INT3: return 3; + case types::input_format::INT4: return 4; + default: assert(false); + } + } + + unsigned int input_format_gl_type(types::input_format format) + { + switch (format) { + case types::input_format::FLOAT1: return GL_FLOAT; + case types::input_format::FLOAT2: return GL_FLOAT; + case types::input_format::FLOAT3: return GL_FLOAT; + case types::input_format::FLOAT4: return GL_FLOAT; + case types::input_format::INT1: return GL_INT; + case types::input_format::INT2: return GL_INT; + case types::input_format::INT3: return GL_INT; + case types::input_format::INT4: return GL_INT; + default: assert(false); + } + } + + // return stride + static inline int load_layout(types::inputs const & inputs, + int binding, + int start_offset, + unsigned int vertex_array) + { + glBindVertexArray(vertex_array); + int offset = start_offset; + for (int i = 0; i < inputs.elements_count; i++) { + unsigned int location = attribute_location(inputs.elements[i].semantic, inputs.elements[i].semantic_index); + glEnableVertexAttribArray(location); + unsigned int gl_size = input_format_gl_size(inputs.elements[i].format); + unsigned int gl_type = input_format_gl_type(inputs.elements[i].format); + glVertexAttribFormat(location, gl_size, gl_type, GL_FALSE, offset); + glVertexAttribBinding(location, binding); + offset += gl_size * 4; + } + int stride = offset - start_offset; + glBindVertexArray(0); + return stride; + } + + types::input_element const input_elements_blendindices_0_4_blendweight_0_4[] = { + { + .semantic = "BLENDINDICES", + .semantic_index = 0, + .format = types::input_format::INT4, + }, + { + .semantic = "BLENDWEIGHT", + .semantic_index = 0, + .format = types::input_format::FLOAT4, + }, + }; + + types::inputs const skin_inputs = { + .elements = input_elements_blendindices_0_4_blendweight_0_4, + .elements_count = 2, + }; + + void state::load_layouts() + { + vertex_arrays = New(descriptor->inputs_list_count); + vertex_buffer_strides = New(descriptor->inputs_list_count); + + glGenVertexArrays(2 * descriptor->inputs_list_count, (unsigned int *)vertex_arrays); + + for (int i = 0; i < descriptor->inputs_list_count; i++) { + // static + int stride = load_layout(descriptor->inputs_list[i], + 0, // binding + 0, // start_offset + vertex_arrays[i].static_mesh); + vertex_buffer_strides[i] = stride; + + // skinned + load_layout(descriptor->inputs_list[i], + 0, // binding + 0, // start_offset + vertex_arrays[i].skinned_mesh); + load_layout(skin_inputs, + 1, // binding + 0, // start_offset + vertex_arrays[i].skinned_mesh); + } + } + + unsigned int load_vertex_buffer(const char * filename) + { + int size; + void * data = read_file(filename, &size); + assert(data != NULL); + unsigned int vertex_buffer; + glGenBuffers(1, &vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + + free(data); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return vertex_buffer; + } + + unsigned int load_index_buffer(const char * filename) + { + int size; + void * data = read_file(filename, &size); + assert(data != NULL); + printf("%s %d\n", filename, size); + + unsigned int index_buffer; + glGenBuffers(1, &index_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + + free(data); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + return index_buffer; + } + + void state::load_scene(types::descriptor const * const descriptor) + { + this->descriptor = descriptor; + + load_layouts(); + + vertex_buffer_pnt = load_vertex_buffer(descriptor->position_normal_texture_buffer); + vertex_buffer_jw = load_vertex_buffer(descriptor->joint_weight_buffer); + index_buffer = load_index_buffer(descriptor->index_buffer); + } + + void state::draw_geometry(types::geometry const & geometry, + types::instance_material const * const instance_materials, + int const instance_materials_count) + { + glUseProgram(collada::effect::program_static); + + types::mesh const& mesh = geometry.mesh; + + for (int j = 0; j < instance_materials_count; j++) { + types::instance_material const& instance_material = instance_materials[j]; + types::triangles const& triangles = mesh.triangles[instance_material.element_index]; + + //set_instance_material(instance_material); + + unsigned int vertex_buffer_offset = mesh.vertex_buffer_offset; + unsigned int vertex_buffer_stride = vertex_buffer_strides[triangles.inputs_index]; + unsigned int vertex_array = vertex_arrays[triangles.inputs_index].static_mesh; + + glBindVertexArray(vertex_array); + glBindVertexBuffer(0, vertex_buffer_pnt, vertex_buffer_offset, vertex_buffer_stride); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); + + unsigned int index_count = triangles.count * 3; + unsigned int indices = triangles.index_offset * (sizeof (unsigned int)) + mesh.index_buffer_offset; + + unsigned int instance_count = 1; + unsigned int base_vertex = 0; + unsigned int base_instance = 1; + glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES, + index_count, + GL_UNSIGNED_INT, + (void *)((ptrdiff_t)indices), + instance_count, + base_vertex, + base_instance); + } + } + + void state::draw_instance_geometries(types::instance_geometry const * const instance_geometries, + int const instance_geometries_count) + { + for (int i = 0; i < instance_geometries_count; i++) { + types::instance_geometry const &instance_geometry = instance_geometries[i]; + draw_geometry(*instance_geometry.geometry, + instance_geometry.instance_materials, + instance_geometry.instance_materials_count); + } + } + + void state::draw_node(types::node const & node) + { + draw_instance_geometries(node.instance_geometries, node.instance_geometries_count); + } + + void state::draw() + { + glUseProgram(collada::effect::program_static); + glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform); + + for (int i = 0; i < descriptor->nodes_count; i++) { + types::node const & node = *descriptor->nodes[i]; + + // joints are not drawn + if (node.type != types::node_type::NODE) + continue; + + draw_node(node); + } + } +} diff --git a/src/test.cpp b/src/test.cpp index 79142a4..575df30 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -21,6 +21,10 @@ #include "collision_scene.h" #include "collision.h" #include "boids_scene.h" +#include "collada/effect.h" +#include "collada/scene.h" +#include "collada/types.h" +#include "data/scenes/ship20.h" struct line_location { struct { @@ -50,6 +54,8 @@ static quad_location quad_location; // globals ////////////////////////////////////////////////////////////////////// +static collada::scene::state scene_state; + unsigned int empty_vertex_array_object = -1; unsigned int quad_index_buffer = -1; @@ -290,6 +296,13 @@ void load(const char * source_path) line_art::load(); collision_scene::load(); boids_scene::load(); + + ////////////////////////////////////////////////////////////////////// + // collada + ////////////////////////////////////////////////////////////////////// + + collada::effect::load_effects(); + scene_state.load_scene(&ship20::descriptor); } void update_keyboard(int up, int down, int left, int right, @@ -569,7 +582,8 @@ void draw() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //collision_scene::draw(); - boids_scene::draw(); + //boids_scene::draw(); + scene_state.draw(); } last_frame_time = current_time;