From: Michel Pollet Date: Fri, 1 Jun 2012 22:17:00 +0000 (+0100) Subject: reprap: c3 update etc X-Git-Tag: v1.0~107 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=d03d508ebf29745d1a92dd3581793e8bacb12ccf;p=sx%2Fsimavr.git reprap: c3 update etc probably last update befire I spin it out Signed-off-by: Michel Pollet --- diff --git a/examples/board_reprap/Makefile b/examples/board_reprap/Makefile index d3c2cb4..50b4e3b 100644 --- a/examples/board_reprap/Makefile +++ b/examples/board_reprap/Makefile @@ -21,15 +21,17 @@ firm_src = ${wildcard atmega*.c} firmware = ${firm_src:.c=.hex} simavr = ../../ +LIBC3 = ../shared/libc3 + IPATH = . IPATH += src IPATH += ../parts IPATH += ../shared +IPATH += $(LIBC3)/src IPATH += ${simavr}/include IPATH += ${simavr}/simavr/sim VPATH = src -VPATH += src/c3 VPATH += ../parts VPATH += ../shared @@ -42,9 +44,7 @@ include ../Makefile.opengl LDFLAGS += ${shell pkg-config --libs pangocairo} LDFLAGS += -lpthread -lutil -ldl LDFLAGS += -lm - -C3SRC = ${wildcard src/c3/*.c} -C3OBJ = ${patsubst src/c3%,${OBJ}%,${C3SRC:.c=.o}} +LDFLAGS += -rpath $(LIBC3)/${OBJ}/.libs -L$(LIBC3)/${OBJ}/.libs -lc3 CPPFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} @@ -55,18 +55,19 @@ include ${simavr}/Makefile.common board = ${OBJ}/${target}.elf -${board} : ${C3OBJ} ${board} : ${OBJ}/mongoose.o ${board} : ${OBJ}/button.o ${board} : ${OBJ}/uart_pty.o ${board} : ${OBJ}/thermistor.o ${board} : ${OBJ}/heatpot.o ${board} : ${OBJ}/stepper.o -${board} : ${OBJ}/c_utils.o ${board} : ${OBJ}/${target}.o ${board} : ${OBJ}/${target}_gl.o -${target}: ${board} +build-libc3: + $(MAKE) -C $(LIBC3) CC="$(CC)" CFLAGS="$(CFLAGS)" + +${target}: build-libc3 ${board} @echo $@ done clean: clean-${OBJ} diff --git a/examples/board_reprap/gfx/BlurryCircle.png b/examples/board_reprap/gfx/BlurryCircle.png index 9490ccf..a8a316b 100644 Binary files a/examples/board_reprap/gfx/BlurryCircle.png and b/examples/board_reprap/gfx/BlurryCircle.png differ diff --git a/examples/board_reprap/gfx/BlurryCircle16.png b/examples/board_reprap/gfx/BlurryCircle16.png new file mode 100644 index 0000000..d619bc1 Binary files /dev/null and b/examples/board_reprap/gfx/BlurryCircle16.png differ diff --git a/examples/board_reprap/gfx/BlurryCircle4.png b/examples/board_reprap/gfx/BlurryCircle4.png new file mode 100644 index 0000000..82b48d8 Binary files /dev/null and b/examples/board_reprap/gfx/BlurryCircle4.png differ diff --git a/examples/board_reprap/gfx/BlurryCircle8.png b/examples/board_reprap/gfx/BlurryCircle8.png new file mode 100644 index 0000000..64ff0a7 Binary files /dev/null and b/examples/board_reprap/gfx/BlurryCircle8.png differ diff --git a/examples/board_reprap/gfx/Fxaa3_11.h b/examples/board_reprap/gfx/Fxaa3_11.h new file mode 100644 index 0000000..a2abfec --- /dev/null +++ b/examples/board_reprap/gfx/Fxaa3_11.h @@ -0,0 +1,2047 @@ +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif diff --git a/examples/board_reprap/gfx/hb.png b/examples/board_reprap/gfx/hb.png new file mode 100644 index 0000000..3ca05c7 Binary files /dev/null and b/examples/board_reprap/gfx/hb.png differ diff --git a/examples/board_reprap/gfx/postproc.fs b/examples/board_reprap/gfx/postproc.fs new file mode 100644 index 0000000..49de3fd --- /dev/null +++ b/examples/board_reprap/gfx/postproc.fs @@ -0,0 +1,87 @@ +#version 120 + +// References: +// http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/ +// http://jmonkeyengine.googlecode.com/svn-history/r9095/trunk/engine/src/core-data/Common/MatDefs/Post/ + +#extension GL_EXT_gpu_shader4 : enable + +uniform sampler2D m_Texture; +uniform vec2 g_Resolution = vec2(800,600); + +//uniform float m_VxOffset; +uniform float m_SpanMax = 8.0; +uniform float m_ReduceMul = (1.0/8.0); + +varying vec2 texCoord; +varying vec4 posPos; + +#define FxaaTex(t, p) texture2D(t, p) + + #define OffsetVec(a, b) ivec2(a, b) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + +vec3 FxaaPixelShader( + vec4 posPos, // Output of FxaaVertexShader interpolated across screen. + sampler2D tex, // Input texture. + vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}. +{ + + #define FXAA_REDUCE_MIN (1.0/128.0) + //#define FXAA_REDUCE_MUL (1.0/8.0) + //#define FXAA_SPAN_MAX 8.0 + + vec3 rgbNW = FxaaTex(tex, posPos.zw).xyz; + vec3 rgbNE = FxaaTexOff(tex, posPos.zw, OffsetVec(1,0), rcpFrame.xy).xyz; + vec3 rgbSW = FxaaTexOff(tex, posPos.zw, OffsetVec(0,1), rcpFrame.xy).xyz; + vec3 rgbSE = FxaaTexOff(tex, posPos.zw, OffsetVec(1,1), rcpFrame.xy).xyz; + + vec3 rgbM = FxaaTex(tex, posPos.xy).xyz; + + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max( + (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), + FXAA_REDUCE_MIN); + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2( m_SpanMax, m_SpanMax), + max(vec2(-m_SpanMax, -m_SpanMax), + dir * rcpDirMin)) * rcpFrame.xy; + + vec3 rgbA = (1.0/2.0) * ( + FxaaTex(tex, posPos.xy + dir * vec2(1.0/3.0 - 0.5)).xyz + + FxaaTex(tex, posPos.xy + dir * vec2(2.0/3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + FxaaTex(tex, posPos.xy + dir * vec2(0.0/3.0 - 0.5)).xyz + + FxaaTex(tex, posPos.xy + dir * vec2(3.0/3.0 - 0.5)).xyz); + + float lumaB = dot(rgbB, luma); + + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + { + return rgbA; + } + else + { + return rgbB; + } +} + +void main() +{ + vec2 rcpFrame = vec2(1.0) / g_Resolution; + gl_FragColor = vec4(FxaaPixelShader(posPos, m_Texture, rcpFrame), 1.0); +// gl_FragColor.g *= 2; +} diff --git a/examples/board_reprap/gfx/postproc.vs b/examples/board_reprap/gfx/postproc.vs new file mode 100644 index 0000000..1031ee1 --- /dev/null +++ b/examples/board_reprap/gfx/postproc.vs @@ -0,0 +1,16 @@ +#version 120 +//uniform mat4 g_WorldViewProjectionMatrix; +uniform vec2 g_Resolution = vec2(800,600); +uniform float m_SubPixelShift = 1.0 / 4.0; + +varying vec2 texCoord; +varying vec4 posPos; + +void main() { + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; + texCoord = gl_MultiTexCoord0.xy; + vec2 rcpFrame = vec2(1.0) / g_Resolution; + posPos.xy = texCoord; + posPos.zw = texCoord - (rcpFrame * vec2(0.5 + m_SubPixelShift)); +} diff --git a/examples/board_reprap/marlin/Marlin.hex b/examples/board_reprap/marlin/Marlin.hex index 9ec87c2..4eb3b1c 100644 --- a/examples/board_reprap/marlin/Marlin.hex +++ b/examples/board_reprap/marlin/Marlin.hex @@ -1,2877 +1,2759 @@ -:10000000EFC700000C9418080C9418080C941808FA -:100010000C9418080C9418080C9418080C941808E0 -:100020000C9418080C9418080C9418080C941808D0 -:10003000FFC700000C94DD3AFBC70000F9C70000C1 -:10004000F7C700000C94FA4C0C949D20F1C70000F7 -:100050000C945A22EDC70000EBC70000E9C700006E -:10006000E7C70000E5C70000E3C70000E1C70000E4 +:10000000FCC700000C941A080C941A080C941A08E7 +:100010000C941A080C941A080C941A080C941A08D8 +:100020000C941A080C941A080C941A080C941A08C8 +:100030000C941A080C947F39FDC70000FBC7000020 +:10004000F9C700000C949A490C943321F3C70000BF +:100050000C94E122EFC70000EDC70000EBC70000E1 +:10006000E9C70000E7C70000E5C70000E3C70000DC :10007000084AD73B3BCE016E84BCBFFDC12F3D6C0F :1000800074319ABD56833DDA3D00C77F11BED9E475 :10009000BB4C3E916BAAAABE000000803F05A84C55 :1000A000CDB2D44EB93836A9020C50B99186880821 -:1000B0003CA6AAAA2ABE000000803F4572726F7259 -:1000C0003A005072696E7465722073746F70706557 -:1000D000642064657520746F206572726F72732E70 -:1000E0002046697820746865206572726F7220619D -:1000F0006E6420757365204D39393920746F207214 -:10010000657374617274212E202854656D70657258 -:1001100061747572652069732072657365742E2031 -:10012000536574206974206265666F72652072651C -:100130007374617274696E6729005072696E7465B8 -:10014000722068616C7465642E206B696C6C282960 -:100150002063616C6C6564202121006F6B00526527 -:1001600073656E643A006563686F3A002200556EED -:100170006B6E6F776E20636F6D6D616E643A2200F7 -:100180007A5F6D696E3A00795F6D696E3A00785FEB -:100190006D696E3A005A3A00593A0020436F756E05 -:1001A0007420583A00453A005A3A00593A00583AF1 -:1001B000004649524D574152455F4E414D453A4DDB -:1001C00061726C696E2056313B20537072696E7497 -:1001D00065722F6772626C206D617368757020663E -:1001E0006F722067656E36204649524D5741524521 -:1001F0005F55524C3A687474703A2F2F7777772E88 -:100200006D656E64656C2D70617274732E636F6DB5 -:100210002050524F544F434F4C5F56455253494F15 -:100220004E3A312E30204D414348494E455F545996 -:1002300050453A4D656E64656C204558545255449E -:1002400045525F434F554E543A310A0020423A001E -:1002500020453A00543A0020573A0020453A0054CD -:100260003A0020403A0020423A006F6B20543A0096 -:100270005072696E7465722073746F70706564205B -:1002800064657520746F206572726F72732E2046DC -:10029000697820746865206572726F7220616E647F -:1002A00020757365204D39393920746F207265735C -:1002B00074617274212E202854656D7065726174AA -:1002C0007572652069732072657365742E2053659D -:1002D00074206974206265666F726520726573743C -:1002E000617274696E6729006F6B004E6F204C69F4 -:1002F0006E65204E756D6265722077697468206343 -:100300006865636B73756D2C204C617374204C6948 -:100310006E653A004E6F20436865636B73756D20A0 -:1003200077697468206C696E65206E756D626572A0 -:100330002C204C617374204C696E653A00636865CB -:10034000636B73756D206D69736D617463682C20C8 -:100350004C617374204C696E653A004C696E65207F -:100360004E756D626572206973206E6F74204C61EA -:100370007374204C696E65204E756D6265722B3109 -:100380002C204C617374204C696E653A002020501B -:100390006C616E6E657242756666657242797465EF -:1003A000733A20002046726565204D656D6F727945 -:1003B0003A20006572696B00207C20417574686F7B -:1003C000723A2000323031322D30322D3235002059 -:1003D0004C61737420557064617465643A20003117 -:1003E0002E302E3020524332004D61726C696E3ACD -:1003F000200020536F6674776172652052657365C3 -:100400007400205761746368646F67205265736578 -:1004100074002042726F776E206F7574205265737E -:100420006574002045787465726E616C2052657346 -:10043000657400506F7765725570007374617274E3 -:10044000002200656E717565696E67202200656324 -:10045000686F3A0020746F6F206C6F6E672065784C -:1004600074727573696F6E2070726576656E7465EF -:10047000640020636F6C6420657874727573696FB3 -:100480006E2070726576656E7465640024F427D3FF -:10049000FD204D0FB0119A05160CE9022D09C80177 -:1004A000650733013206DE005405A700AD04830062 -:1004B0002A046900C10356006B03480023033D0072 -:1004C000E6023500B1022D00840228005C02230000 -:1004D0003902200019021C00FD011900E401170077 -:1004E000CD011500B8011300A50111009401100001 -:1004F00084010F0075010E0067010D005A010C0008 -:100500004E010B0043010A0039010A002F010900C6 -:10051000260109001D010800150107000E01080051 -:1005200006010700FF000600F9000600F3000600C0 -:10053000ED000600E7000500E2000500DD00050013 -:10054000D8000500D3000400CF000500CA00040055 -:10055000C6000400C2000400BE000300BB0004008B -:10056000B7000300B4000300B1000400AD000300B5 -:10057000AA000300A7000200A5000300A2000300D8 -:100580009F0002009D0003009A00020098000300F3 -:100590009500020093000200910002008F0002000B -:1005A0008D0002008B00020089000200870002001B -:1005B000850002008300020081000100800002002B -:1005C0007E0002007C0001007B0002007900010037 -:1005D000780002007600010075000100740002003E -:1005E0007200010071000100700002006E00010045 -:1005F0006D0001006C0001006B0002006900010049 -:10060000680001006700010066000100650001004C -:10061000640001006300010062000100610001004C -:10062000600001005F0001005E0001005D0001004C -:100630005C0001005B0000005B0001005A0001004B -:100640005900010058000100570000005700010048 -:100650005600010055000100540000005400010044 -:100660005300010052000100510000005100010040 -:10067000500001004F0000004F0001004E0000003C -:100680004E0001004D0001004C0000004C00010034 -:100690004B0000004B0001004A000100490000002F -:1006A0004900010048000000480001004700000028 -:1006B0004700010046000000460001004500000020 -:1006C0004500010044000000440001004300000018 -:1006D0004300010042000000420001004100000010 -:1006E0004100000041000100400000004000010006 -:1006F0003F0000003F0001003E0000003E000000FF -:100700003E0001003D0000003D0001003C000000F3 -:100710003C0000003C0001003B0000003B000000EA -:100720003B0001003A0000003A0000003A000100DE -:1007300039000000390000003900010038000000D5 -:1007400038000000380001003700000037000000CA -:1007500037000100360000003600000036000100BE -:1007600035000000350000003500000035000100B4 -:1007700034000000340000003400010033000000A9 -:10078000330000003300000033000100320000009D -:100790003200000032000000320001003100000091 -:1007A0003100000031000000310001003000000085 -:1007B0003000000030000000300001002F00000079 -:1007C0002F0000002F0000002F0001002E0000006D -:1007D0002E0000002E0000002E0000002E00010060 -:1007E0002D0000002D0000002D0000002D00010054 -:1007F0002C0000002C0000002C0000002C00000049 -:100800002C0001002B0000002B0000002B0000003A -:100810002B0000002B0001002A0000002A0000002D -:100820002A0000002A0000002A0000002A0001001F -:100830002900000029000000290000002900000014 -:100840002900000029000100280000002800000005 -:1008500028000000280000002800010027000000F8 -:1008600027000000270000002700000027000000EC -:1008700027000000270001002600000026000000DD -:1008800026000000260000002600000024F4B12805 -:1008900073CB111D62AECC159698F410A287900D03 -:1008A000127A190BF96E4009B965D307E65DB506F2 -:1008B0003157D005615116054B4C7D04CE47FD03E1 -:1008C000D14392033F403603093DE902203AA40296 -:1008D0007C376A0212353602DC320802D430E1017C -:1008E000F32EBD01362D9E01982B8101172A670139 -:1008F000B028500160273B0125262801FD24160160 -:10090000E7230701E022F800E821EB00FD20DE00EC -:100910001F20D3004C1FC800841EBF00C51DB5009A -:10092000101DAD00631CA500BE1B9E00201B970080 -:10093000891A9100F8198A006E198500E9187F005C -:100940006A187B00EF1776007917710008176D00A1 -:100950009B166A0031166500CC1562006A155F00AF -:100960000B155B00B01458005814560002145200C6 -:10097000B013500060134E0012134B00C712490011 -:100980007E12460038124500F3114300B0114000BA -:1009900070113F0031113D00F4103C00B8103A00D6 -:1009A0007E103800461037000F103500DA0F340083 -:1009B000A60F3300730F3100420F3000120F3000CA -:1009C000E20E2D00B50E2D00880E2C005C0E2B00C3 -:1009D000310E2A00070E2800DF0D2800B70D270072 -:1009E000900D26006A0D2600440D2400200D2400E1 -:1009F000FC0C2300D90C2200B70C2200950C21001E -:100A0000740C2000540C1F00350C1F00160C1F0026 -:100A1000F70B1E00D90B1D00BC0B1C00A00B1C000B -:100A2000840B1C00680B1B004D0B1B00320B1A00C3 -:100A3000180B1900FF0A1900E60A1900CD0A180060 -:100A4000B50A18009D0A1800850A17006E0A1600DC -:100A5000580A1600420A16002C0A1600160A15003B -:100A6000010A1500EC091400D8091400C409140087 -:100A7000B00914009C0913008909130076091300BA -:100A800063091200510912003F0912002D091100DB -:100A90001C0912000A091100F9081000E9081100E8 -:100AA000D8081000C8081000B8081000A8081000E6 -:100AB00098080F0089080F007A080F006B080F00D4 -:100AC0005C080F004D080E003F080E0031080E00B4 -:100AD00023080E0015080E0007080D00FA070D0088 -:100AE000ED070D00E0070D00D3070D00C6070D0050 -:100AF000B9070C00AD070C00A1070D0094070B000F -:100B000089070C007D070C0071070C0065070B00BE -:100B10005A070B004F070B0044070B0039070B0067 -:100B20002E070B0023070B0018070A000E070B0007 -:100B300003070A00F9060A00EF060A00E5060A00A4 -:100B4000DB060A00D1060900C8060A00BE06090035 -:100B5000B5060A00AB060900A206090099060900BD -:100B600090060900870609007E060900750609003F -:100B70006C060800640609005B06080053060900BD -:100B80004A060800420608003A0608003206080035 -:100B90002A060800220608001A06080012060700A6 -:100BA0000B06080003060800FB050700F405080013 -:100BB000EC050700E5050700DE050700D70507007F -:100BC000D0050700C9050700C2050700BB050700DF -:100BD000B4050700AD050700A6050600A00507003F -:100BE00099050700920506008C050600860507009A -:100BF0007F05060079050600730507006C050600F1 -:100C000066050600600506005A0506005405060044 -:100C10004E05060048050600420505003D05060094 -:100C200037050600310505002C05060026050500E0 -:100C3000210506001B050500160506001005050028 -:100C40000B0505000605060000050500FB04050070 -:100C5000F6040500F1040500EC040500E7040500B6 -:100C6000E2040500DD040500D8040500D3040500F6 -:100C7000CE040500C9040500C4040500BF04040037 -:100C8000BB040500B6040500B10405006563686F88 -:100C90003A00205A3A0020593A0020583A00656E2E -:100CA0006473746F7073206869743A2000457272BF -:100CB0006F723A0054656D7065726174757265206B -:100CC0006865617465642062656420737769746324 -:100CD000686564206F66662E204D415854454D501E -:100CE00020747269676765726564202121003A206B -:100CF000457874727564657220737769746368658A -:100D000064206F66662E204D494E54454D50207428 -:100D100072696767657265642021003A20457874BE -:100D20007275646572207377697463686564206F97 -:100D300066662E204D415854454D502074726967A7 -:100D400067657265642021001000C90220013C0122 -:100D500030020A014003EF005004DD006005D000BE -:100D60007006C5008007BC009008B500A009AE0061 -:100D7000B00AA900C00BA300D00C9F00E00D9A00A0 -:100D8000F00E96000010930010118F0020128C00BE -:100D900030138800401485005015820060168000D2 -:100DA00070177D0080187A0090197800A01A7500DD -:100DB000B01B7300C01C7000D01D6E00E01E6C00E4 -:100DC000F01F6A00002167001022650020236300E5 -:100DD0003024610040255F0050265C0060275A00E7 -:100DE0007028580080295600902A5400A02B5100EA -:100DF000B02C4F00C02D4D00D02E4B00E02F4800EE -:100E0000F0304600003243001033400020343D00F3 -:100E100030353A0040363700503734006038300003 -:100E200070392C00803A2800903B2200A03C1C0026 -:100E3000B03D1400C03E0800D03F0000202D2049E6 -:100E40006E76616C69642065787472756465722071 -:100E50006E756D626572202100202D20496E7661CD -:100E60006C6964206578747275646572206E756D46 -:100E7000626572210020403A006F6B20543A0050A6 -:100E80004944204175746F74756E65206661696CA4 -:100E9000656420212C2054656D70657261747572D3 -:100EA0006520746F206869676800204B643A2000F1 -:100EB000204B693A2000204B703A2000204E6F20D2 -:100EC0006F76657273686F6F742000204B643A20F0 -:100ED00000204B693A2000204B703A200020536FCD -:100EE0006D65206F76657273686F6F742000204B9C -:100EF000643A2000204B693A2000204B703A2000D1 -:100F000020436C617369632050494420002054756C -:100F10003A2000204B753A2000206D61783A20007D -:100F2000206D696E3A200020643A200020626961D9 -:100F3000733A2000002124272A002225282B002094 -:100F4000232629020202020202020204040404040B -:100F50000404040303030303030303010101010168 -:100F60000101010102040810204080010204081060 -:100F7000204080010204081020408080402010089A -:100F80000402010000000102000000000000000453 -:100F90000307060000000000000000000000000041 -:100FA000000000494E46494E4954594E414ECDCC61 -:100FB000CC3D0AD7233C17B7D13877CC2B32959547 -:100FC000E6241FB14F0A000020410000C842004043 -:100FD0001C4620BCBE4CCA1B0E5AAEC59D7477245D -:100FE00011241FBECFEFD0E1DEBFCDBF12E0A0E0E5 -:100FF000B1E0E2E2F2EB02C005900D92A638B10733 -:10100000D9F71AE0A6E8B2E001C01D92A73FB107E8 -:10101000E1F71FE0C0EEDFE004C02297FE010E946E -:101020005D53CE3DD107C9F70E9498200C940F590B -:101030000C940000AF92BF92CF92DF92EF92FF929A -:101040000F931F93DF93CF93CDB7DEB7E0970FB623 -:10105000F894DEBF0FBECDBFDE011196EFE6F2E0E1 -:1010600080E101900D928150E1F7DE015196EFE5AC -:10107000F2E080E101900D928150E1F7DE0191965E -:10108000EFE4F2E080E101900D928150E1F7BE01C2 -:101090006F5F7F4F40E255E021E1A22EB12CAC0EF4 -:1010A000BD1E00E115E091E2E92EF12CEC0EFD1ED3 -:1010B00080E3C82E85E0D82E20E030E0FB0181914E -:1010C0009191A191B191BF01FA0181939193A19363 -:1010D000B193AF01F50181919191A191B1915F011E -:1010E000F80181939193A193B1938F01F7018191BD -:1010F0009191A191B1917F01F60181939193A19377 -:10110000B1936F012F5F3F4F24303105B9F680E076 -:1011100090E0AAEFB3E48093440590934505A09333 -:101120004605B093470580E090E8ABE3B5E48093D3 -:10113000480590934905A0934A05B0934B0580E07C -:1011400090E0DC018093400590934105A093420517 -:10115000B093430520E23EE440E050E020930C05CC -:1011600030930D0540930E0550930F05809358055D -:1011700090935905A0935A05B0935B0580E090E0E9 -:10118000A0EAB1E480934C0590934D05A0934E05E1 -:10119000B0934F058DEC9CECACECBEE38093500516 -:1011A00090935105A0935205B093530580E090E0D1 -:1011B000A0EAB0E48093540590935505A09356059A -:1011C000B0935705E6E6F1E007C09091C00095FFA7 -:1011D000FCCF8093C600319684918823B1F7E0E07C -:1011E000F1E006C09091C00095FFFCCF8093C6004F -:1011F00081918823B9F78091C00085FFFCCF8AE0F8 -:101200008093C600E0960FB6F894DEBF0FBECDBF48 -:10121000CF91DF911F910F91FF90EF90DF90CF90D2 -:10122000BF90AF900895DF93CF9300D0CDB7DEB7D6 -:101230008091F10A9091F20A9E012F5F3F4F009733 -:1012400019F4275F3A4002C0281B390B3A832983DF -:1012500089819A810F900F90CF91DF910895AF927D -:10126000BF92CF92DF92EF92FF920F931F93CF9393 -:10127000DF938BE095E040E052EC61E070E00E948B -:101280008F22EBE3F4E007C09091C00095FFFCCF04 -:101290008093C600319684918823B1F78091C00075 -:1012A00085FFFCCF8AE08093C60086E691E0FC01D2 +:1000B0003CA6AAAA2ABE000000803F6563686F3A8A +:1000C00000737461727400506F7765725570002010 +:1000D00045787465726E616C20526573657400209A +:1000E00042726F776E206F7574205265736574006D +:1000F000205761746368646F67205265736574008C +:1001000020536F6674776172652052657365740061 +:100110004D61726C696E3A2000312E302E302052C3 +:10012000433200204C6173742055706461746564BF +:100130003A2000323031322D30352D303200207CE3 +:1001400020417574686F723A20006572696B0020F7 +:1001500046726565204D656D6F72793A20002020EA +:10016000506C616E6E657242756666657242797436 +:1001700065733A20004572726F723A004C696E6581 +:10018000204E756D626572206973206E6F74204C0D +:10019000617374204C696E65204E756D6265722BBB +:1001A000312C204C617374204C696E653A00636891 +:1001B00065636B73756D206D69736D617463682C15 +:1001C000204C617374204C696E653A004E6F204379 +:1001D0006865636B73756D2077697468206C696EF0 +:1001E00065206E756D6265722C204C617374204CB5 +:1001F000696E653A004E6F204C696E65204E756DD4 +:10020000626572207769746820636865636B7375D3 +:100210006D2C204C617374204C696E653A006F6BD5 +:10022000005072696E7465722073746F70706564CB +:100230002064657520746F206572726F72732E2052 +:1002400046697820746865206572726F7220616EED +:100250006420757365204D39393920746F207265BB +:100260007374617274212E202854656D70657261FB +:10027000747572652069732072657365742E2053DE +:100280006574206974206265666F7265207265739B +:1002900074617274696E6729006F6B20543A002094 +:1002A0002F0020423A00202F0020403A00543A000C +:1002B00020453A0020573A00543A0020453A0020A1 +:1002C000423A004649524D574152455F4E414D45D5 +:1002D0003A4D61726C696E2056313B2053707269E1 +:1002E0006E7465722F6772626C206D6173687570D1 +:1002F00020666F722067656E36204649524D574121 +:1003000052455F55524C3A687474703A2F2F777784 +:10031000772E6D656E64656C2D70617274732E63DB +:100320006F6D2050524F544F434F4C5F56455253C0 +:10033000494F4E3A312E30204D414348494E455F9A +:10034000545950453A4D656E64656C204558545279 +:10035000554445525F434F554E543A310A00583A7E +:1003600000593A005A3A00453A0020436F756E74BE +:1003700020583A00593A005A3A00785F6D696E3A4F +:1003800000795F6D696E3A007A5F6D696E3A00556B +:100390006E6B6E6F776E20636F6D6D616E643A2267 +:1003A000002200526573656E643A006F6B005072F4 +:1003B000696E7465722068616C7465642E206B6967 +:1003C0006C6C28292063616C6C65642021210050CD +:1003D00072696E7465722073746F707065642064E6 +:1003E000657520746F206572726F72732E20466976 +:1003F0007820746865206572726F7220616E642067 +:10040000757365204D39393920746F2072657374A6 +:10041000617274212E202854656D70657261747547 +:1004200072652069732072657365742E205365743C +:10043000206974206265666F7265207265737461ED +:100440007274696E6729000000000102000000005C +:100450000000000403070600000000000000000088 +:10046000000000000000000102040810204080018C +:1004700002040810204080010204081020408080FF +:1004800040201008040201020202020202020204D9 +:100490000404040404040403030303030303030127 +:1004A00001010101010101002225282B002124273F +:1004B0002A6563686F3A0020636F6C642065787406 +:1004C000727573696F6E2070726576656E7465649F +:1004D0000020746F6F206C6F6E6720657874727582 +:1004E00073696F6E2070726576656E746564006501 +:1004F00063686F3A00656E6473746F707320686927 +:10050000743A200020583A0020593A00205A3A0004 +:1005100024F427D3FD204D0FB0119A05160CE902E3 +:100520002D09C801650733013206DE005405A70016 +:10053000AD0483002A046900C10356006B03480020 +:1005400023033D00E6023500B1022D00840228009D +:100550005C0223003902200019021C00FD01190071 +:10056000E4011700CD011500B8011300A501110029 +:100570009401100084010F0075010E0067010D0049 +:100580005A010C004E010B0043010A0039010A0018 +:100590002F010900260109001D01080015010700AF +:1005A0000E01080006010700FF000600F900060022 +:1005B000F3000600ED000600E7000500E20005007C +:1005C000DD000500D8000500D3000400CF000500C1 +:1005D000CA000400C6000400C2000400BE000300FC +:1005E000BB000400B7000300B4000300B100040026 +:1005F000AD000300AA000300A7000200A50003004D +:10060000A20003009F0002009D0003009A00020068 +:100610009800030095000200930002009100020080 +:100620008F0002008D0002008B0002008900020092 +:1006300087000200850002008300020081000100A3 +:10064000800002007E0002007C0001007B000200AE +:1006500079000100780002007600010075000100B9 +:1006600074000200720001007100010070000200BD +:100670006E0001006D0001006C0001006B000200C3 +:1006800069000100680001006700010066000100C8 +:1006900065000100640001006300010062000100C8 +:1006A00061000100600001005F0001005E000100C8 +:1006B0005D0001005C0001005B0000005B000100C8 +:1006C0005A000100590001005800010057000000C5 +:1006D00057000100560001005500010054000000C1 +:1006E00054000100530001005200010051000000BD +:1006F00051000100500001004F0000004F000100B8 +:100700004E0000004E0001004D0001004C000000B2 +:100710004C0001004B0000004B0001004A000100AA +:1007200049000000490001004800000048000100A5 +:10073000470000004700010046000000460001009D +:100740004500000045000100440000004400010095 +:10075000430000004300010042000000420001008D +:100760004100000041000000410001004000000085 +:10077000400001003F0000003F0001003E0000007B +:100780003E0000003E0001003D0000003D00010071 +:100790003C0000003C0000003C0001003B00000069 +:1007A0003B0000003B0001003A0000003A0000005E +:1007B0003A00010039000000390000003900010052 +:1007C0003800000038000000380001003700000049 +:1007D000370000003700010036000000360000003E +:1007E0003600010035000000350000003500000033 +:1007F0003500010034000000340000003400010026 +:10080000330000003300000033000000330001001B +:10081000320000003200000032000000320001000F +:100820003100000031000000310000003100010003 +:1008300030000000300000003000000030000100F7 +:100840002F0000002F0000002F0000002F000100EB +:100850002E0000002E0000002E0000002E000000E0 +:100860002E0001002D0000002D0000002D000000D2 +:100870002D0001002C0000002C0000002C000000C6 +:100880002C0000002C0001002B0000002B000000B9 +:100890002B0000002B0000002B0001002A000000AC +:1008A0002A0000002A0000002A0000002A000000A0 +:1008B0002A00010029000000290000002900000092 +:1008C0002900000029000000290001002800000084 +:1008D0002800000028000000280000002800010077 +:1008E000270000002700000027000000270000006C +:1008F000270000002700000027000100260000005C +:10090000260000002600000026000000260000004F +:1009100024F4B12873CB111D62AECC159698F41057 +:10092000A287900D127A190BF96E4009B965D307A9 +:10093000E65DB5063157D005615116054B4C7D0477 +:10094000CE47FD03D14392033F403603093DE90200 +:10095000203AA4027C376A0212353602DC320802E1 +:10096000D430E101F32EBD01362D9E01982B81017B +:10097000172A6701B028500160273B01252628016E +:10098000FD241601E7230701E022F800E821EB002F +:10099000FD20DE001F20D3004C1FC800841EBF00B6 +:1009A000C51DB500101DAD00631CA500BE1B9E003B +:1009B000201B9700891A9100F8198A006E1985008A +:1009C000E9187F006A187B00EF177600791771002D +:1009D00008176D009B166A0031166500CC15620081 +:1009E0006A155F000B155B00B014580058145600D0 +:1009F00002145200B013500060134E0012134B004B +:100A0000C71249007E12460038124500F311430018 +:100A1000B011400070113F0031113D00F4103C0056 +:100A2000B8103A007E103800461037000F1035001D +:100A3000DA0F3400A60F3300730F3100420F30007D +:100A4000120F3000E20E2D00B50E2D00880E2C0086 +:100A50005C0E2B00310E2A00070E2800DF0D280047 +:100A6000B70D2700900D26006A0D2600440D2400C6 +:100A7000200D2400FC0C2300D90C2200B70C22000E +:100A8000950C2100740C2000540C1F00350C1F0025 +:100A9000160C1F00F70B1E00D90B1D00BC0B1C0011 +:100AA000A00B1C00840B1C00680B1B004D0B1B00D3 +:100AB000320B1A00180B1900FF0A1900E60A190078 +:100AC000CD0A1800B50A18009D0A1800850A1700FB +:100AD0006E0A1600580A1600420A16002C0A160062 +:100AE000160A1500010A1500EC091400D8091400B3 +:100AF000C4091400B00914009C09130089091300EB +:100B00007609130063091200510912003F0912000F +:100B10002D0911001C0912000A091100F908100022 +:100B2000E9081100D8081000C8081000B808100023 +:100B3000A808100098080F0089080F007A080F0015 +:100B40006B080F005C080F004D080E003F080E00F8 +:100B500031080E0023080E0015080E0007080D00CE +:100B6000FA070D00ED070D00E0070D00D3070D009B +:100B7000C6070D00B9070C00AD070C00A1070D005A +:100B800094070B0089070C007D070C0071070C000F +:100B900065070B005A070B004F070B0044070B00BB +:100BA00039070B002E070B0023070B0018070A005C +:100BB0000E070B0003070A00F9060A00EF060A00F9 +:100BC000E5060A00DB060A00D1060900C8060A008D +:100BD000BE060900B5060A00AB060900A206090018 +:100BE0009906090090060900870609007E0609009B +:100BF000750609006C060800640609005B0608001B +:100C0000530609004A060800420608003A06080092 +:100C1000320608002A060800220608001A06080004 +:100C2000120607000B06080003060800FB05070074 +:100C3000F4050800EC050700E5050700DE050700E0 +:100C4000D7050700D0050700C9050700C205070042 +:100C5000BB050700B4050700AD050700A6050600A3 +:100C6000A005070099050700920506008C050600FF +:100C7000860507007F050600790506007305070055 +:100C80006C05060066050600600506005A050600AC +:100C9000540506004E0506004805060042050500FD +:100CA0003D05060037050600310505002C05060048 +:100CB00026050500210506001B0505001605060092 +:100CC000100505000B0505000605060000050500DA +:100CD000FB040500F6040500F1040500EC04050022 +:100CE000E7040500E2040500DD040500D804050062 +:100CF000D3040500CE040500C9040500C4040500A2 +:100D0000BF040400BB040500B6040500B1040500DF +:100D100020626961733A200020643A2000206D69E6 +:100D20006E3A2000206D61783A2000204B753A2001 +:100D3000002054753A200020436C61736963205091 +:100D400049442000204B703A2000204B693A200093 +:100D5000204B643A2000504944204175746F7475EB +:100D60006E65206661696C6564212054656D7065EF +:100D700072617475726520746F2068696768006FAE +:100D80006B20543A0020403A005049442041757489 +:100D90006F74756E65206661696C65642120746985 +:100DA0006D656F757400504944204175746F74759A +:100DB0006E652066696E6973686564202120506CD9 +:100DC00061636520746865204B702C204B6920613D +:100DD0006E64204B6420636F6E7374616E74732055 +:100DE000696E2074686520636F6E666967757261ED +:100DF00074696F6E2E68004572726F723A00202D12 +:100E000020496E76616C69642065787472756465DA +:100E100072206E756D62657221001000C90220019A +:100E20003C0130020A014003EF005004DD00600580 +:100E3000D0007006C5008007BC009008B500A0096E +:100E4000AE00B00AA900C00BA300D00C9F00E00DBB +:100E50009A00F00E96000010930010118F002012DF +:100E60008C003013880040148500501582006016F5 +:100E7000800070177D0080187A0090197800A01A01 +:100E80007500B01B7300C01C7000D01D6E00E01E0A +:100E90006C00F01F6A00002167001022650020230B +:100EA00063003024610040255F0050265C0060270D +:100EB0005A007028580080295600902A5400A02B10 +:100EC0005100B02C4F00C02D4D00D02E4B00E02F14 +:100ED0004800F03046000032430010334000203418 +:100EE0003D0030353A004036370050373400603826 +:100EF000300070392C00803A2800903B2200A03C42 +:100F00001C00B03D1400C03E0800D03F0000202D62 +:100F100020496E76616C69642065787472756465C9 +:100F200072206E756D6265722021003A20457874DA +:100F30007275646572207377697463686564206F85 +:100F400066662E204D415854454D50207472696795 +:100F500067657265642021003A2045787472756473 +:100F60006572207377697463686564206F66662EA6 +:100F7000204D494E54454D50207472696767657223 +:100F8000656420210054656D7065726174757265C9 +:100F90002068656174656420626564207377697494 +:100FA00063686564206F66662E204D415854454D38 +:100FB0005020747269676765726564202121004959 +:100FC0004E46494E4954594E414E000020410000C2 +:100FD000C84200401C4620BCBE4CCA1B0E5AAEC5BF +:100FE0009D74CDCCCC3D0AD7233C17B7D13877CCF4 +:100FF0002B329595E6241FB14F0A11241FBECFEF67 +:10100000D0E1DEBFCDBF12E0A0E0B1E0E8EDFAEA4A +:1010100002C005900D92A038B107D9F71AE0A0E8F8 +:10102000B2E001C01D92A13FB107E1F70E942E215D +:101030000C946A550C940000AF92BF92CF92DF924D +:10104000EF92FF920F931F93CF93DF93CDB7DEB74D +:10105000E0970FB6F894DEBF0FBECDBF80E1E7E3A7 +:10106000F1E0DE01919601900D928A95E1F780E121 +:10107000E7E4F1E0DE01519601900D928A95E1F7E7 +:1010800080E1E7E5F1E0DE01119601900D928A958D +:10109000E1F76E0181E2C80ED11C85E2E82E8AE0FC +:1010A000F82E8E010F5E1F4F65E37AE0AE014F5FB1 +:1010B0005F4F95E1A92E9AE0B92E20E030E0F601CD +:1010C00081919191A191B1916F01F70181939193D8 +:1010D000A193B1937F01F80181919191A191B19177 +:1010E0008F01FB0181939193A193B193BF01FA0109 +:1010F00081919191A191B191AF01F501819391936A +:10110000A193B1935F012F5F3F4F24303105B9F6B2 +:1011100080E090E0AAEFB3E480930D0A90930E0A6A +:10112000A0930F0AB093100A80E090E8ABE3B5E417 +:101130008093090A90930A0AA0930B0AB0930C0AB1 +:101140001092110A1092120A1092130A1092140AA5 +:1011500080E29EE4A0E0B0E08093450A9093460AC6 +:10116000A093470AB093480A1092F9091092FA091D +:101170001092FB091092FC0980E090E0A0EAB1E433 +:101180008093050A9093060AA093070AB093080A71 +:101190008DEC9CECACECBEE38093010A9093020AC8 +:1011A000A093030AB093040A80E090E0A0EAB0E4C0 +:1011B0008093FD099093FE09A093FF09B093000A64 +:1011C000EBEBF0E007C09091C00095FFFCCF80935F +:1011D000C600319684918111F6CFE7E6F1E006C0B2 +:1011E0009091C00095FFFCCF8093C6008191811142 +:1011F000F7CF8091C00085FFFCCF8AE08093C600C6 +:10120000E0960FB6F894DEBF0FBECDBFDF91CF9151 +:101210001F910F91FF90EF90DF90CF90BF90AF9014 +:101220000895CF93DF9300D0CDB7DEB78091EB0A5E +:101230009091EC0A9E012F5F3F4F009719F4215FB8 +:101240003A4002C0281B390B3A83298389819A814D +:101250000F900F90DF91CF910895CF92DF92EF9290 +:10126000FF920F931F93CF93DF9300D000D0CDB7A1 +:10127000DEB740E052EC61E070E081E894E00E946B +:101280001623E1ECF0E007C09091C00095FFFCCF81 +:101290008093C600319684918111F6CF8091C00071 +:1012A00085FFFCCF8AE08093C6008BEB90E0FC01C9 :1012B00007C03091C00035FFFCCF2093C6003196A7 -:1012C00024912223B1F724B720FF14C0E3E3F4E014 +:1012C00024912111F6CF24B720FF14C0E7ECF0E001 :1012D00007C04091C00045FFFCCF3093C600319657 -:1012E00034913323B1F73091C00035FFFCCF3AE0A1 -:1012F0003093C60021FF14C0E3E2F4E007C0409140 -:10130000C00045FFFCCF3093C600319634913323A3 -:10131000B1F73091C00035FFFCCF3AE03093C60002 -:1013200022FF14C0E2E1F4E007C04091C00045FF95 -:10133000FCCF3093C600319634913323B1F730910E +:1012E00034913111F6CF3091C00035FFFCCF3AE098 +:1012F0003093C60021FF14C0EFECF0E007C040912E +:10130000C00045FFFCCF3093C600319634913111B7 +:10131000F6CF3091C00035FFFCCF3AE03093C600E5 +:1013200022FF14C0EFEDF0E007C04091C00045FF80 +:10133000FCCF3093C600319634913111F6CF309105 :10134000C00035FFFCCF3AE03093C60023FF14C045 -:10135000E2E0F4E007C04091C00045FFFCCF3093CD -:10136000C600319634913323B1F73091C00035FF78 -:10137000FCCF3AE03093C60025FF14C0E2EFF3E063 +:10135000E0EFF0E007C04091C00045FFFCCF3093C4 +:10136000C600319634913111F6CF3091C00035FF6F +:10137000FCCF3AE03093C60025FF14C0E0E0F1E076 :1013800007C03091C00035FFFCCF2093C6003196D6 -:1013900024912223B1F72091C00025FFFCCF2AE041 -:1013A0002093C60014BEE9EEF3E007C03091C00000 -:1013B00035FFFCCF2093C600319624912223B1F74C -:1013C000EFEDF3E007C03091C00035FFFCCF209374 -:1013D000C600319624912223B1F72091C00025FF49 -:1013E000FCCF2AE02093C600FC012491E6E6F1E060 +:1013900024912111F6CF2091C00025FFFCCF2AE037 +:1013A0002093C60014BEE0E1F1E007C03091C00018 +:1013B00035FFFCCF2093C600319624912111F6CF42 +:1013C000E9E1F1E007C03091C00035FFFCCF209388 +:1013D000C600319624912111F6CF2091C00025FF3F +:1013E000FCCF2AE02093C600FC012491EBEBF0E057 :1013F00008C03091C00035FFFCCF2093C600319665 -:1014000024912223B1F7EFECF3E007C03091C00044 -:1014100035FFFCCF2093C600319624912223B1F7EB -:10142000E4ECF3E007C03091C00035FFFCCF20931F -:10143000C600319624912223B1F7E8EBF3E007C010 +:1014000024912111F6CFE3E2F1E007C03091C00052 +:1014100035FFFCCF2093C600319624912111F6CFE1 +:10142000E3E3F1E007C03091C00035FFFCCF20932B +:10143000C600319624912111F6CFEEE3F1E007C00A :101440003091C00035FFFCCF2093C6003196249127 -:101450002223B1F7E3EBF3E007C03091C00035FF82 -:10146000FCCF2093C600319624912223B1F720911E +:101450002111F6CFEAE4F1E007C03091C00035FF7A +:10146000FCCF2093C600319624912111F6CF209114 :10147000C00025FFFCCF2AE02093C600FC01849128 -:10148000E6E6F1E008C09091C00095FFFCCF8093A4 -:10149000C600319684918823B1F7E4EAF3E007C0EF +:10148000EBEBF0E008C09091C00095FFFCCF80939B +:10149000C600319684918111F6CFEFE4F1E007C0E8 :1014A0009091C00095FFFCCF8093C6003196849147 -:1014B0008823B1F7B8DEBC018BE095E04AE050E04C -:1014C0000E949C23EDE8F3E007C09091C00095FFD7 -:1014D000FCCF8093C600319684918823B1F78BE0CE -:1014E00095E060ED74E04AE050E00E949C2380911A -:1014F000C00085FFFCCF8AE08093C6001092740480 -:1015000010927504109276041092770480E092DDB8 -:10151000C0E3D5E000E215E03CE5E32E35E0F32E34 -:101520006991799189919991F801A190B190C190B7 -:10153000D1908F010E94DD4FA60195010E941252A9 -:101540000E94B14FF70161937193819391937F0151 -:10155000F5E0C034DF0721F70E94BA4B0E94CF2C80 -:101560000E94D340DF91CF911F910F91FF90EF9098 -:10157000DF90CF90BF90AF90089580916C049091D0 -:101580006D04019660E070E00C94615380916C04EE -:1015900090916D04019660E070E04AE050E00C9498 -:1015A000CE54682FE091EA02F091EB0240E650E061 -:1015B000E49F9001E59F300DF49F300D1124C90187 -:1015C00084519D4F70E00E9418569C0190936D04C9 -:1015D00080936C0481E02115310509F480E00895C1 -:1015E0000E94E2206093B4027093B5028093B60229 -:1015F0009093B702EBE5F1E007C09091C00095FF32 -:10160000FCCF8093C600319684918823B1F78091F6 -:10161000C00085FFFCCF8AE08093C60008958BE070 -:1016200095E00E94D222EEE5F1E007C09091C00063 -:1016300095FFFCCF8093C600319684918823B1F743 -:101640004091AC025091AD026091AE027091AF0238 -:101650004F5F5F4F6F4F7F4F8BE095E02AE030E0A8 -:101660000E946C238091C00085FFFCCF8AE08093AC -:10167000C600B6CF4F925F926F927F928F929F92E9 -:10168000AF92BF92CF92DF92EF92FF920F931F9390 -:10169000CF93DF9370E6C72ED12C64E0662E712CB9 -:1016A00051E0A52EB12CE0E7F2E084904AE0942EC0 -:1016B000E8EEF2E05490442443941CC28D3071F063 -:1016C0008A3321F490916F04992341F020917004A2 -:1016D000309171042F3531050CF4EEC1E0917004A6 -:1016E000F0917104309719F410926F0422C2809126 -:1016F0007204909173048C9DE0018D9DD00D9C9D92 -:10170000D00D1124EC0FFD1FE451FD4F10822091EC -:101710006F04222309F0CBC110926F048C589B4FA9 -:10172000FC0110828E0104511D4FC8016EE470E06F -:101730000E941856009709F412C190936D0480938B -:101740006C049501201B310B280F391F2C0F3D1FF6 -:10175000C90184519D4F60E070E04AE050E00E9472 -:10176000CE54609378047093790480937A049093B4 -:101770007B04E090AC02F090AD020091AE021091BB -:10178000AF02A80197012F5F3F4F4F4F5F4F621786 -:1017900073078407950709F43AC0209172043091C9 -:1017A00073042C9DC0012D9D900D3C9D900D112426 -:1017B00084519D4F68E171E00E942356009739F5EE -:1017C000EBEBF0E007C09091C00095FFFCCF809359 -:1017D000C600319684918823B1F7EBE5F3E007C0AA -:1017E0009091C00095FFFCCF8093C6003196849104 -:1017F0008823B1F78BE095E0B801A7012AE030E03B -:101800000E946C238091C00085FFFCCF92C0809124 -:101810007204909173048C9DE0018D9DD00D9C9D70 -:10182000D00D1124CE0184519D4F6AE270E00E94D8 -:101830001856009709F457C020E000E002C00327C3 -:101840002F5FFE01E20FF11DE451FD4F30813A326E -:10185000B1F790936D0480936C049E0124513D4F29 -:10186000A501421B530B9A01280F391F2C0F3D1F56 -:10187000C90184519D4F60E070E00E9461530E9455 -:10188000AC4F10E00617170709F458C0EBEBF0E077 -:1018900007C09091C00095FFFCCF8093C6003196A1 -:1018A00084918823B1F7EDE3F3E007C09091C00085 -:1018B00095FFFCCF8093C600319684918823B1F7C1 -:1018C0004091AC025091AD026091AE027091AF02B6 -:1018D0008BE095E02AE030E00E946C238091C0000C -:1018E00085FFFCCF26C0EBEBF0E007C09091C00075 -:1018F00095FFFCCF8093C600319684918823B1F781 -:10190000E4E1F3E007C09091C00095FFFCCF809325 -:10191000C600319684918823B1F78BE095E0B80139 -:10192000A7012AE030E00E946C238091C00085FF6F -:10193000FCCF8AE08093C60072DE47C080917804B5 -:1019400090917904A0917A04B0917B048093AC02C9 -:101950009093AD02A093AE02B093AF023BC0C8011A -:101960006AE270E00E9418560097A1F1EBEBF0E0FC -:1019700007C09091C00095FFFCCF8093C6003196C0 -:1019800084918823B1F7EBEEF2E007C09091C0009C -:1019900095FFFCCF8093C600319684918823B1F7E0 -:1019A0004091AC025091AD026091AE027091AF02D5 -:1019B0008BE095E02AE030E00E946C238091C0002B -:1019C00085FFFCCF8AE08093C600109271041092CC -:1019D0007004AFC080917204909173048C9D80015B -:1019E0008D9D100D9C9D100D1124E801C451DD4FFB -:1019F000CE0167E470E00E941856009709F442C0D7 -:101A000090936D0480936C0495012C1B3D0B280F63 -:101A1000391F200F311FC90184519D4F60E070E0D4 -:101A20000E9461530E94AC4F6430710558F580915B -:101A3000AB02882399F4852DE8EEF2E008C090917E -:101A4000C00095FFFCCF8093C60031968491882317 -:101A5000B1F78091C00085FFFCCF12C0882DE0E770 -:101A6000F2E008C09091C00095FFFCCF8093C600C3 -:101A7000319684918823B1F78091C00085FFFCCF17 -:101A80009092C60080917204909173040196B30104 -:101A90000E94F752909373048093720480917C04A7 -:101AA00090917D04019690937D0480937C04109224 -:101AB0007104109270041EC08B3311F440926F04B5 -:101AC00090916F049923B1F4409172045091730482 -:101AD0004C9DF0014D9DF00D5C9DF00D1124E20F29 -:101AE000F31FE451FD4F80832F5F3F4F309371040C -:101AF00020937004809107059091080520910905B5 -:101B000030910A05821B930B8F779070009789F0B4 -:101B100080917C0490917D048430910554F48BE095 -:101B200095E00E94B62280936E048A3009F0C6CDFB -:101B3000D5CDDF91CF911F910F91FF90EF90DF9066 -:101B4000CF90BF90AF909F908F907F906F905F905D -:101B50004F9008958F929F92AF92BF92CF92DF9253 -:101B6000EF92FF920F931F93CF93DF93F1E1EF2E4C -:101B7000F2E0FF2ECDE8D2E008EC12E0E6E8CE2E4F -:101B8000E2E0DE2EF70181917F010BDD882321F158 -:101B9000F4DC4B015C01F6018081882319F460912B -:101BA000D80201C061E070E0882777FD8095982F0A -:101BB0000E94DF4F288139814A815B810E94125245 -:101BC0009B01AC01C501B4010E94644EF801608321 -:101BD00071838283938309C088819981AA81BB81A3 -:101BE000F80180839183A283B38324960C5F1F4FF7 -:101BF0000894C11CD11CF5E1EF16F2E0FF0609F0D4 -:101C0000C1CF86E4CEDC8823D1F0B7DC7B018C0128 -:101C10006093D9027093DA028093DB029093DC0226 -:101C200020E030E0A9010E944051181644F4E092EF -:101C3000F201F092F3010093F4011093F501DF91AA -:101C4000CF911F910F91FF90EF90DF90CF90BF90B9 -:101C5000AF909F908F9008957DDF89E4A2DC882368 -:101C600051F08BDC6093BC027093BD028093BE0286 -:101C70009093BF020BC080E090E0DC018093BC0237 -:101C80009093BD02A093BE02B093BF028AE489DCA8 -:101C9000882351F072DC6093C0027093C10280937C -:101CA000C2029093C302089580E090E0DC0180932B -:101CB000C0029093C102A093C202B093C3020895E0 -:101CC000CF92DF92EF92FF920F931F936091C80221 -:101CD0007091C9028091CA029091CB0220E030E05D -:101CE000A9010E943D4F87FF0BC080E090E0DC011E -:101CF0008093C8029093C902A093CA02B093CB020A -:101D00006091CC027091CD028091CE029091CF0271 -:101D100020E030E0A9010E943D4F87FF0BC080E02A -:101D200090E0DC018093CC029093CD02A093CE0290 -:101D3000B093CF026091D0027091D1028091D20213 -:101D40009091D30220E030E0A9010E943D4F87FF2F -:101D50000BC080E090E0DC018093D0029093D10230 -:101D6000A093D202B093D3026091C8027091C902CD -:101D70008091CA029091CB0220E030E04DE453E420 -:101D80000E944051181664F480E090E0ADE4B3E4A2 -:101D90008093C8029093C902A093CA02B093CB0269 -:101DA0006091CC027091CD028091CE029091CF02D1 -:101DB00020E030E04DE453E40E944051181664F4F2 -:101DC00080E090E0ADE4B3E48093CC029093CD0248 -:101DD000A093CE02B093CF026091D0027091D10255 -:101DE0008091D2029091D30220E030E040EF52E4A3 -:101DF0000E944051181664F480E090E0A0EFB2E435 -:101E00008093D0029093D102A093D202B093D302D8 -:101E10000E94E2206093B4027093B5028093B602F0 -:101E20009093B7026091EA017091EB01882777FDEA -:101E30008095982F0E94DF4F2091F2013091F3019D -:101E40004091F4015091F5010E94125220E030E0DF -:101E500040E752E40E94444F20E030E048EC52E476 -:101E60000E94444F7B018C0188EC92E06CEC72E0A4 -:101E700040ED52E024ED32E0A9EACA2EA2E0DA2ECB -:101E80000E945E2D8091C8029091C902A091CA0261 -:101E9000B091CB0280938D0290938E02A0938F021B -:101EA000B09390028091CC029091CD02A091CE028D -:101EB000B091CF028093910290939202A0939302EB -:101EC000B09394028091D0029091D102A091D2025D -:101ED000B091D3028093950290939602A0939702BB -:101EE000B09398028091D4029091D502A091D6022D -:101EF000B091D7028093990290939A02A0939B028B -:101F0000B0939C021F910F91FF90EF90DF90CF90C4 -:101F100008959F92AF92BF92CF92DF92EF92FF927D -:101F20000F931F93CF93DF93982E6091BC02709113 -:101F3000BD028091BE029091BF022091C0023091FB -:101F4000C1024091C2025091C3020E944D517B01D7 -:101F50008C016091EA017091EB0100D000D000D0BB -:101F6000CDB7DEB72196882777FD8095982F0E9400 -:101F7000DF4F2091F2013091F3014091F401509133 -:101F8000F5010E94125220E030E040E752E40E9446 -:101F9000444F20E030E048EC52E40E94444F5B01A3 -:101FA0006C01E882F9820A831B839C828091A902DA -:101FB0008D838DE892E068EC72E04CEB52E020E01B -:101FC00001E0B2E0EB2E0E9478248091C80290914B -:101FD000C902A091CA02B091CB0280938D02909366 -:101FE0008E02A0938F02B09390028091CC029091C8 -:101FF000CD02A091CE02B091CF0280939102909336 -:102000009202A0939302B09394028091D002909197 -:10201000D102A091D202B091D30280939502909305 -:102020009602A0939702B09398028091D402909167 -:10203000D502A091D602B091D702809399029093D5 -:102040009A02A0939B02B0939C028DB79EB706960E -:102050000FB6F8949EBF0FBE8DBF0E94E220609322 -:10206000B4027093B5028093B6029093B702DF91E9 -:10207000CF911F910F91FF90EF90DF90CF90BF9085 -:10208000AF909F900895F8940E94184C5A985A98CF -:102090005A985A98EBEBF0E007C09091C00095FF7A -:1020A000FCCF8093C600319684918823B1F7EAE390 -:1020B000F1E007C09091C00095FFFCCF8093C6006F -:1020C000319684918823B1F78091C00085FFFCCFC1 -:1020D0008AE08093C600FFCFEF92FF920F931F9389 -:1020E0000E94E2202091B8023091B9024091BA02D8 -:1020F0005091BB02E090B402F090B5020091B6029C -:102100001091B7026E197F09800B910B26173707C4 -:102110004807590730F4211531054105510509F0EB -:10212000B2DF8091EE019091EF01A091F001B091AA -:10213000F1010097A105B10529F10E94E22020914B -:10214000B4023091B5024091B6025091B702621BC1 -:10215000730B840B950B2091EE013091EF014091B0 -:10216000F0015091F101261737074807590750F43D -:1021700090914C0A80914D0A981721F45A985A98D8 -:102180005A985A980E94062D1EBA1F910F91FF90DF -:10219000EF9008952F923F924F925F926F927F92AD -:1021A0008F929F92AF92BF92CF92DF92EF92FF9267 -:1021B0000F931F93DF93CF93CDB7DEB7A2970FB6E0 -:1021C000F894DEBF0FBECDBF87E4EBD9882309F4B6 -:1021D000A3C5D3D90E94AC4F6430710509F43CC04B -:1021E0006530710554F46230710531F16330710569 -:1021F00054F577FF19C00C94F41F6A35710509F482 -:1022000027C56B35710534F46C31710511F00C94F0 -:10221000F41F64C06B35710509F41EC56C3571057A -:1022200011F00C94F41F1DC58091AB02882321F49A -:1022300091DC46DD0C9413208091AB02882319F4C5 -:102240000BDD81E006C08091AB02882329F404DD18 -:1022500080E05FDE0C94132080E5A3D9882341F051 -:102260008CD90E94B14FE62EF72E082F192F03C0EC -:10227000EE24FF24870183E594D9882369F07DD972 -:1022800020E030E04AE754E40E9412520E94B14F2D -:10229000E62EF72E082F192F0E9412410E94E220ED -:1022A0005B016C01AE0CBF1CC01ED11E0E94E2205F -:1022B0006093B4027093B5028093B6029093B70214 -:1022C00004C00E94AB4381E007DF0E94E2206A1550 -:1022D0007B058C059D05A8F30C94F41F8091F201F9 -:1022E0009091F301A091F401B091F5018093DD028A -:1022F0009093DE02A093DF02B093E0028091EA01A6 -:102300009091EB0190938B0280938A0284E690E097 -:102310009093EB018093EA010E94E2206093B40263 -:102320007093B5028093B6029093B70281E00E9449 -:10233000D43A80918D0290918E02A0918F02B0913B -:1023400090028093C8029093C902A093CA02B093EE -:10235000CB028091910290919202A0919302B09150 -:1023600094028093CC029093CD02A093CE02B093BE -:10237000CF028091950290919602A0919702B09120 -:1023800098028093D0029093D102A093D202B0938E -:10239000D3028091990290919A02A0919B02B091F0 -:1023A0009C028093D4029093D502A093D602B0935E -:1023B000D70280E090E0DC018093F2019093F3017A -:1023C000A093F401B093F50188E5EBD8882351F48C -:1023D00089E5E7D8882331F48AE5E3D8882311F426 -:1023E00081E001C080E08093F60188E5DAD8882397 -:1023F00009F4E6C089E5D5D8882309F4E1C080E076 -:1024000090E0DC0180938D0290938E02A0938F0266 -:10241000B09390028093910290939202A0939302C2 -:10242000B09394028DE892E061E972E045E952E0F0 -:1024300029E932E00E94453980E090ECA9E9B3EC4B -:102440008093C8029093C902A093CA02B093CB02B2 -:102450008093CC029093CD02A093CE02B093CF0292 -:102460002091DA013091DB014091DC015091DD01D6 -:102470002093F2013093F3014093F4015093F5015E -:10248000E090DE01F090DF010091E0011091E101A8 -:10249000C801B7010E943D4F87FF08C0E092F201DA -:1024A000F092F3010093F4011093F5016091F201B1 -:1024B0007091F3018091F4019091F50120E030E0FA -:1024C00040E752E40E94444F7B018C0188EC92E08B -:1024D0006CEC72E040ED52E024ED32E0B9EACB2E34 -:1024E000B2E0DB2E0E945E2D0E9412410F2EF0E022 -:1024F0008F2EF0E09F2EF0E0AF2EF0E0BF2EF02DFB -:1025000080928D0290928E02A0928F02B0929002E1 -:102510008092910290929202A0929302B0929402C1 -:102520008DE892E061E972E045E952E029E932E0A4 -:102530000E94453980918D0290918E02A0918F0268 -:10254000B09190028093C8029093C902A093CA02EE -:10255000B093CB028091910290919202A09193024C -:10256000B09194028093CC029093CD02A093CE02BE -:10257000B093CF026091F2017091F3018091F40168 -:102580009091F50120E030E040E752E40E94444F92 -:102590007B018C0188EC92E06CEC72E040ED52E043 -:1025A00024ED32E00E945E2D8092F2019092F301C0 -:1025B000A092F401B092F5010E9412410E94CD3A1E -:1025C0008091F601882331F488E50E94D10A88239E -:1025D00009F4DEC00F2EF0E08F2EF0E09F2EF0E029 -:1025E000AF2EF0E0BF2EF02D80928D0290928E02E1 -:1025F000A0928F02B09290028DE892E061E972E0C1 -:1026000045E952E029E932E00E94453980E090EC4A -:10261000A9E9B3EC8093C8029093C902A093CA02BF -:10262000B093CB026091DA017091DB018091DC0103 -:102630009091DD016093F2017093F3018093F401B6 -:102640009093F50120E030E040E752E40E94444FCF -:102650007B018C0188EC92E06CEC72E040ED52E082 -:1026600024ED32E0A9EACA2EA2E0DA2E0E945E2D05 -:102670000E94124180928D0290928E02A0928F024F -:10268000B09290028DE892E061E972E045E952E093 -:1026900029E932E00E94453980E090E0A0EAB0E408 -:1026A0008093C8029093C902A093CA02B093CB0250 -:1026B0006091F2017091F3018091F4019091F50124 -:1026C00020E030E040E752E40E94444F7B018C015F -:1026D00088EC92E06CEC72E040ED52E024ED32E0E8 -:1026E0000E945E2D0E94124180E090E0A0E2B1ECD9 -:1026F0008093C8029093C902A093CA02B093CB0200 -:102700006091DA017091DB018091DC019091DD0133 -:1027100020E030E040E05FE30E941252262F372F86 -:10272000482F592F2093F2013093F3014093F40185 -:102730005093F50120E030E040E752E40E94444F1E -:102740007B018C0188EC92E06CEC72E040ED52E091 -:1027500024ED32E00E945E2D0E94124180928D0293 -:1027600090928E02A0928F02B09290028092C80244 -:102770009092C902A092CA02B092CB028092F2015A -:102780009092F301A092F401B092F5010E94CD3A2B -:102790008091F601882331F489E50E94D10A8823CB -:1027A00009F4DEC00F2EF0E08F2EF0E09F2EF0E057 -:1027B000AF2EF0E0BF2EF02D809291029092920207 -:1027C000A0929302B09294028DE892E061E972E0E7 -:1027D00045E952E029E932E00E94453980E090EC79 -:1027E000A9E9B3EC8093CC029093CD02A093CE02E2 -:1027F000B093CF026091DE017091DF018091E00122 -:102800009091E1016093F2017093F3018093F401E0 -:102810009093F50120E030E040E752E40E94444FFD -:102820007B018C0188EC92E06CEC72E040ED52E0B0 -:1028300024ED32E0F9EACF2EF2E0DF2E0E945E2D89 -:102840000E9412418092910290929202A092930271 -:10285000B09294028DE892E061E972E045E952E0BD -:1028600029E932E00E94453980E090E0A0EAB0E436 -:102870008093CC029093CD02A093CE02B093CF026E -:102880006091F2017091F3018091F4019091F50152 -:1028900020E030E040E752E40E94444F7B018C018D -:1028A00088EC92E06CEC72E040ED52E024ED32E016 -:1028B0000E945E2D0E94124180E090E0A0E2B1EC07 -:1028C0008093CC029093CD02A093CE02B093CF021E -:1028D0006091DE017091DF018091E0019091E10152 -:1028E00020E030E040E05FE30E941252262F372FB5 -:1028F000482F592F2093F2013093F3014093F401B4 -:102900005093F50120E030E040E752E40E94444F4C -:102910007B018C0188EC92E06CEC72E040ED52E0BF -:1029200024ED32E00E945E2D0E94124180929102BD -:1029300090929202A0929302B09294028092CC0262 -:102940009092CD02A092CE02B092CF028092F2017C -:102950009092F301A092F401B092F5010E94CD3A59 -:102960008091F601882331F48AE50E94D10A8823F8 -:1029700009F4DEC00F2EF0E08F2EF0E09F2EF0E085 -:10298000AF2EF0E0BF2EF02D80929502909296022D -:10299000A0929702B09298028DE892E061E972E00D -:1029A00045E952E029E932E00E94453980E090E0B3 -:1029B000A4E3B3EC8093D0029093D102A093D2020F -:1029C000B093D3026091E2017091E3018091E40140 -:1029D0009091E5016093F2017093F3018093F4010B -:1029E0009093F50120E030E040E752E40E94444F2C -:1029F0007B018C0188EC92E06CEC72E040ED52E0DF -:102A000024ED32E0E9EACE2EE2E0DE2E0E945E2DD9 -:102A10000E9412418092950290929602A092970293 -:102A2000B09298028DE892E061E972E045E952E0E7 -:102A300029E932E00E94453980E090E0A0E8BFE358 -:102A40008093D0029093D102A093D202B093D3028C -:102A50006091F2017091F3018091F4019091F50180 -:102A600020E030E040E752E40E94444F7B018C01BB -:102A700088EC92E06CEC72E040ED52E024ED32E044 -:102A80000E945E2D0E94124180E090E0A0E0B0EC38 -:102A90008093D0029093D102A093D202B093D3023C -:102AA0006091E2017091E3018091E4019091E50170 -:102AB00020E030E040E05FE30E941252262F372FE3 -:102AC000482F592F2093F2013093F3014093F401E2 -:102AD0005093F50120E030E040E752E40E94444F7B -:102AE0007B018C0188EC92E06CEC72E040ED52E0EE -:102AF00024ED32E00E945E2D0E94124180929502E8 -:102B000090929602A0929702B09298028092D00280 -:102B10009092D102A092D202B092D3028092F2019E -:102B20009092F301A092F401B092F5010E94CD3A87 -:102B300088E50E94D10A8823D9F00E94C60A61154F -:102B4000710581059105A1F00E94BD0A20919D02A9 -:102B500030919E0240919F025091A0020E94644ECB -:102B600060938D0270938E0280938F0290939002F7 -:102B700089E50E94D10A8823D9F00E94C60A61150E -:102B8000710581059105A1F00E94BD0A2091A10265 -:102B90003091A2024091A3025091A4020E94644E7F -:102BA00060939102709392028093930290939402A7 -:102BB0008AE50E94D10A8823D9F00E94C60A6115CD -:102BC000710581059105A1F00E94BD0A2091A50221 -:102BD0003091A6024091A7025091A8020E94644E33 -:102BE0006093950270939602809397029093980257 -:102BF0008DE892E061E972E045E952E029E932E0CE -:102C00000E9445398091DD029091DE02A091DF02A1 -:102C1000B091E0028093F2019093F301A093F4014C -:102C2000B093F50180918A0290918B029093EB0111 -:102C30008093EA010E94E2206093B4027093B5028F -:102C40008093B6029093B7020E94CD3A0C94F41F81 -:102C50001092D8020C94F41F81E08093D8020C9457 -:102C6000F41F85E40E94D10A882311F40E941241C6 -:102C700041E1842E42E0942E3DE9E32E32E0F32E32 -:102C80000DE812E0AA24F40181914F010E94D10ABB -:102C90008823A9F10E94BD0AF70120813181428178 -:102CA00053810E94644EF801608371838283938311 -:102CB000FA2DF33061F40E94BD0AF801608371833C -:102CC0008283938389E992E00E94F23918C00E94BE -:102CD000BD0AF70120813181428153810E94644EF7 -:102CE000F80160837183828393838DE892E061E9C8 -:102CF00072E045E952E029E932E00E944539A394A7 -:102D000024E030E0E20EF31E0C5F1F4F3A2D34300A -:102D100009F0B9CF0C94F41F8DE40E94D10A8823E6 -:102D200011F40C944A1F0E94BD0A0E94AC4F6737F1 -:102D3000710509F434C6683771050CF056C0653565 -:102D4000710509F412C5663571051CF56A32710505 -:102D500009F41BC16B32710574F46231710509F419 -:102D6000C0C46F31710509F4A5C06131710511F05E -:102D70000C94F41F99C06335710509F4AEC4643531 -:102D800071050CF0AEC46235710511F00C94F41F9E -:102D9000A1C46A36710509F473C46B36710574F405 -:102DA0006836710509F434C1693671050CF0A1C1AA -:102DB0006C35710511F00C94F41FEDC46D3671057E -:102DC00009F429C26E36710534F46B36710511F0C1 -:102DD0000C94F41F7CC46237710509F407C563378E -:102DE000710511F00C94F41FF3C46C3D710509F4E6 -:102DF00028C76D3D71051CF56B3C710509F469C66A -:102E00006C3C710574F46E3B710509F49BC3693C1D -:102E1000710509F424C66C38710511F00C94F41F87 -:102E200055C16D3C710509F491C66D3C71050CF4FA -:102E30006DC66E3C710511F00C94F41FE5C681E07F -:102E40006F32780709F4F9C791E06033790784F4A9 -:102E5000E1E06D327E0709F415C7F1E06E327F07BD -:102E60000CF0E7C76D3D710511F00C94F41FFBC623 -:102E700021E0653F720709F4F2C731E0663F73074E -:102E80003CF481E06039780711F00C94F41FE4C73A -:102E900091E0663F790709F4E4C7E3E0673E7E0707 -:102EA00011F00C94F41FE1C75A9A5A9A5A9A5A9AF6 -:102EB0000C94F41F0E94E2206093E1027093E202FE -:102EC0008093E3029093E4022091E5023091E602C0 -:102ED0004091E7025091E802621B730B840B950B43 -:102EE00028EE33E040E050E00E940A538DB79EB7D1 -:102EF00008970FB6F8949EBF0FBE8DBF0DB71EB7D3 -:102F00000F5F1F4FCE010196EDB7FEB7928381830D -:102F100083E291E0F80193838283CA01B9012CE333 -:102F200030E040E050E00E940A53F80135832483EA -:102F3000778366830E943D56E6E6F1E084912DB7E3 -:102F40003EB7285F3F4F0FB6F8943EBF0FBE2DBF70 -:102F500008C09091C00095FFFCCF8093C6003196C9 -:102F600084918823B1F7FE01319606C09091C0008C -:102F700095FFFCCF8093C60081918823B9F780919B -:102F8000C00085FFFCCF0C94F11F83E50E94D10A9D -:102F9000882311F40C94F41F0E94BD0A7B018C015C -:102FA00080E50E94D10A882311F40C94F41FC80113 -:102FB000B7010E94AC4F8B0177FF02C00C94F41F45 -:102FC0006F3F710519F014F00C94F41F0E94BD0AB4 -:102FD0000E94AC4F7B01E5E1F2E0819191918E1569 -:102FE0009F0511F40C94F41F32E0E938F307A9F7B8 -:102FF000F7FE01C0F9C78E2D61E00E9403228E2DDD -:10300000602F0E9424228E2DB8010E947821ECC7E7 -:103010008091A9028093E90284E50E94D10A882365 -:1030200061F10E94BD0A0E94B14F6093E9026623DC -:1030300021F1E6E6F1E007C09091C00095FFFCCFDA -:103040008093C600319684918823B1F7E2E3F1E0E2 -:1030500006C09091C00095FFFCCF8093C60081917F -:103060008823B9F78BE095E040E050E00E946623AA -:103070008091C00085FFFCCFB4C783E50E94D10AD0 -:10308000882309F10E94BD0A7B018C01D090E902DE -:10309000AD2CBB240E94AC4FDC01CB016D2D0E94F6 -:1030A000A041F501EE0FFF1FE755F54F9183808397 -:1030B000F501EE0FFF1FEE0FFF1FEF54F54FE082FB -:1030C000F182028313830E94174C8EC783E50E940E -:1030D000D10A882309F488C70E94BD0A0E94AC4F18 -:1030E000DC01CB010E9456429093AC0A8093AB0A5C -:1030F0007BC78091A9028093E90284E50E94D10AEE -:10310000882361F10E94BD0A0E94B14F6093E902D9 -:10311000662321F1E6E6F1E007C09091C00095FF3B -:10312000FCCF8093C600319684918823B1F7E9E4FF -:10313000F1E006C09091C00095FFFCCF8093C600DF -:1031400081918823B9F78BE095E040E050E00E9440 -:1031500066238091C00085FFFCCF43C7EAE6F2E01A -:1031600007C09091C00095FFFCCF8093C6003196B8 -:1031700084918823B1F76091E902E62FF0E0EE0F29 -:10318000FF1FE355F54F808191810E94A642AB015C -:10319000BC018BE095E022E030E00E947524E6E679 -:1031A000F2E007C09091C00095FFFCCF8093C6006D -:1031B000319684918823B1F78091AF0A9091B00A3B -:1031C0000E94204BAB01BC018BE095E022E030E097 -:1031D0000E947524E2E6F2E007C09091C00095FFDE -:1031E000FCCF8093C600319684918823B1F78091FB -:1031F000E90290E00E949A41BC018BE095E04AE030 -:1032000050E00E949C238091C00085FFFCCF8AE0A3 -:103210008093C60008C78091A9028093E90284E5E3 -:103220000E94D10A882361F10E94BD0A0E94B14F19 -:103230006093E902662321F1E6E6F1E007C0909190 -:10324000C00095FFFCCF8093C600319684918823FF -:10325000B1F7E0E6F1E006C09091C00095FFFCCF29 -:103260008093C60081918823B9F78BE095E040E018 -:1032700050E00E9466238091C00085FFFCCFB1C65C -:1032800083E50E94D10A882309F10E94BD0A7B01CF -:103290008C01D090E902AD2CBB240E94AC4FDC0124 -:1032A000CB016D2D0E94A041F501EE0FFF1FE755E8 -:1032B000F54F91838083F501EE0FFF1FEE0FFF1F87 -:1032C000EF54F54FE082F182028313830E94174C82 -:1032D00079D75B016C018091E90290E0880F991F1A -:1032E000FC01E755F54F208031808355954FFC0157 -:1032F0000190F081E02DF8A3EF8FEE24EA94FE2CEC -:103300008701EFE5F2E0249129A3EBE5F2E0449098 -:10331000E7E5F2E034913AA35AE0552E04C189A1C1 -:10332000EFE5F2E008C09091C00095FFFCCF8093DC -:10333000C600319684918823B1F76091E902E62FA7 -:10334000F0E0EE0FFF1FE355F54F808191810E9461 -:10335000A642AB01BC018BE095E022E030E00E9488 -:103360007524842DEBE5F2E008C09091C00095FF34 -:10337000FCCF8093C600319684918823B1F7609189 -:10338000E9028BE095E070E04AE050E00E949C2367 -:103390008AA1E7E5F2E008C09091C00095FFFCCF5C -:1033A0008093C600319684918823B1F717FF03C03C -:1033B000E7E7F1E026C006D79B01AC01C801B701E1 -:1033C000605F784D8F4F9F4F621B730B840B950B83 -:1033D00028EE33E040E050E00E940A538BE095E095 -:1033E000BA01A9012AE030E00E9456238091C00072 -:1033F00085FFFCCF0DC09091C00095FFFCCF80935E -:10340000C60081918823B9F78091C00085FFFCCF69 -:103410005092C600D7D65B016C010E94AB4381E09D -:103420000E946C108FEFE8168FEFF8068FEF0807F9 -:103430008FEF180751F58091E902EF8DF8A1E215A1 -:10344000F30594F490E0880F991FFC01E755F54FC0 -:103450008355954F20813181FC01808191818217B4 -:1034600093070CF048C04CC090E0880F991FFC01F6 -:10347000E755F54F8355954F20813181FC018081BF -:10348000918128173907BCF53BC017FD39C0609101 -:10349000E902E62FF0E0EE0FFF1FE355F54F8081C4 -:1034A00091810E94A6423B014C016091E902E62F06 -:1034B000F0E0EE0FFF1FE755F54F808191810E94EC -:1034C000A6429B01AC01C401B3010E94634E0E945D -:1034D000AC4F262F372F482F592F57FF07C0509535 -:1034E0004095309521953F4F4F4F5F4F2430310528 -:1034F000410551052CF066D6E62EF72E082F192F20 -:10350000FFEFEF16FFEFFF06FFEF0F07FFEF1F07BD -:1035100051F017FD6CC556D66E197F0927E2603150 -:10352000720708F064C54ED66A197B098C099D099B -:10353000693E33E0730730E0830730E0930708F01B -:10354000EECE6BCF83E50E94D10A882361F00E9402 -:10355000BD0A0E94AC4FDC01CB010E945642909301 -:10356000AC0A8093AB0A2ED67B018C01E4E5F2E035 -:10357000A490E0E5F2E08490ECE4F2E0D490EAE09C -:103580006E2E71C01FD66E197F09800B910B693E9C -:10359000E3E07E07E0E08E07E0E09E0708F45EC00F -:1035A0006091A902E62FF0E0EE0FFF1FE355F54F03 -:1035B000808191810E94A642AB01BC018A2DE4E585 -:1035C000F2E008C09091C00095FFFCCF8093C60048 -:1035D000319684918823B1F78BE095E022E030E0CA -:1035E0000E947524882DE0E5F2E008C09091C000AB -:1035F00095FFFCCF8093C600319684918823B1F764 -:103600006091A9028BE095E070E04AE050E00E94F2 -:103610009C238D2DECE4F2E008C09091C00095FF52 -:10362000FCCF8093C600319684918823B1F78091B6 -:10363000AF0A9091B00A0E94204BAB01BC018BE015 -:1036400095E022E030E00E9475248091C00085FF63 -:10365000FCCF6092C600B6D57B018C010E94AB43C3 -:1036600081E00E946C102091AB0A3091AC0A8091ED -:10367000AF0A9091B00A821793070CF483CFC0C4AD -:1036800083E50E94D10A8823F1F00E94BD0A20E060 -:1036900030E0A9010E943D4F87FD0FC00E94BD0A86 -:1036A00020E030E04FE753E40E94405118163CF010 -:1036B0000E94BD0A0E94B14F03C060E001C06FEFDD -:1036C0006093AA0291C48FEF8093AA028DC41092D6 -:1036D000AA028AC41092890287C481E08093890279 -:1036E00083C483E50E94D10A882399F00E94BD0A11 -:1036F00020E030E04AE754E40E9412520E94B14FA9 -:103700006093EE017093EF018093F0019093F101CB -:103710006BC488E50E94D10A882309F07BC489E53F -:103720000E94D10A882309F075C48AE50E94D10A53 -:10373000882309F06FC485E40E94D10A882309F028 -:1037400069C40E9412415A980E947D414DC45A9802 -:1037500089E50E94D10A81115A988AE50E94D10A0E -:10376000882309F441C45A983FC483E50E94D10AD2 -:103770000E94BD0A20E030E04AE754E40E94125261 -:103780000E94B14F6093B8027093B9028093BA025D -:103790009093BB0229C401E112E050E2E52E55E00E -:1037A000F52EF80181918F010E94D10A882339F00A -:1037B0000E94BD0AF701608371838283938324E0B2 -:1037C00030E0E20EF31E32E00531130751F70CC46E -:1037D000E1EBF1E007C09091C00095FFFCCF809332 -:1037E000C600319684918823B1F7FEC3EEEAF1E07A -:1037F00007C09091C00095FFFCCF8093C600319622 -:1038000084918823B1F740918D0250918E0260918E -:103810008F02709190028BE095E022E030E00E94F0 -:103820007524EBEAF1E007C09091C00095FFFCCF52 -:103830008093C600319684918823B1F7409191021C -:103840005091920260919302709194028BE095E006 -:1038500022E030E00E947524E8EAF1E007C0909190 -:10386000C00095FFFCCF8093C600319684918823D9 -:10387000B1F7409195025091960260919702709134 -:1038800098028BE095E022E030E00E947524E5EAA2 -:10389000F1E007C09091C00095FFFCCF8093C60077 -:1038A000319684918823B1F74091990250919A0200 -:1038B00060919B0270919C028BE095E022E030E0E9 -:1038C0000E947524EBE9F1E007C09091C00095FFDC -:1038D000FCCF8093C600319684918823B1F70E9473 -:1038E0006B410E94DF4F20912005309121054091CE -:1038F0002205509123050E94444FAB01BC018BE08F -:1039000095E022E030E0F1D7E8E9F1E007C09091DE -:10391000C00095FFFCCF8093C60031968491882328 -:10392000B1F781E00E946B410E94DF4F2091240596 -:103930003091250540912605509127050E94444F5E -:10394000AB01BC018BE095E022E030E0CED7E5E9A9 -:10395000F1E007C09091C00095FFFCCF8093C600B6 -:10396000319684918823B1F782E00E946B410E94D6 -:10397000DF4F209128053091290540912A0550916B -:103980002B050E94444FAB01BC018BE095E022E087 -:1039900030E0ABD78091C00085FFFCCF22C3EEE8BA -:1039A000F1E007C09091C00095FFFCCF8093C60066 -:1039B000319684918823B1F783B180FD03C0EDE196 -:1039C000F1E009C0E0E2F1E006C09091C00095FF8F -:1039D000FCCF8093C60081918823B9F7E7E8F1E036 -:1039E00007C09091C00095FFFCCF8093C600319630 -:1039F00084918823B1F7199903C0EDE1F1E009C082 -:103A0000E0E2F1E006C09091C00095FFFCCF80930A -:103A1000C60081918823B9F7E0E8F1E007C09091F2 -:103A2000C00095FFFCCF8093C60031968491882317 -:103A3000B1F71A9903C0EDE1F1E009C0E0E2F1E06D -:103A400006C09091C00095FFFCCF8093C600819185 -:103A50008823B9F78091C00085FFFCCFC2C241E145 -:103A6000E42E42E0F42E00E010E0F70181917F01A6 -:103A70000E94D10A882339F10E94BD0A30E3A32EA7 -:103A800035E0B32EA00EB11E0E94B14FF501608348 -:103A90007183828393830E94BD0A2CE5A22E25E0C8 -:103AA000B22EA00EB11EF801E05EFA4F20813181E6 -:103AB000428153810E9412520E94B14FF5016083EE -:103AC0007183828393830C5F1F4F0031110569F668 -:103AD0008BC201E112E090E1E92E95E0F92EF801A8 -:103AE00081918F010E94D10A882339F00E94BD0A7A -:103AF000F701608371838283938324E030E0E20ED8 -:103B0000F31E32E00531130751F76EC283E50E94C0 -:103B1000D10A882351F00E94BD0A60934405709336 -:103B20004505809346059093470584E50E94D10A98 -:103B3000882309F459C20E94BD0A60934805709316 -:103B4000490580934A0590934B054EC283E50E9438 -:103B5000D10A882351F00E94BD0A609340057093FA -:103B60004105809342059093430584E50E94D10A64 -:103B7000882351F00E94BD0A60935805709359053F -:103B800080935A0590935B0582E40E94D10A8823B2 -:103B900061F00E94BD0A0E94B14F60930C057093C2 -:103BA0000D0580930E0590930F0588E50E94D10ABC -:103BB000882351F00E94BD0A60934C0570934D0517 -:103BC00080934E0590934F058AE50E94D10A882381 -:103BD00051F00E94BD0A6093500570935105809387 -:103BE00052059093530585E40E94D10A882309F475 -:103BF000FBC10E94BD0A60935405709355058093E4 -:103C0000560590935705F0C101E112E08DE9E82EC9 -:103C100082E0F82EF80181918F010E94D10A882359 -:103C200039F00E94BD0AF701608371838283938318 -:103C300024E030E0E20EF31E32E00431130751F7C6 -:103C4000D3C183E50E94D10A882309F4CDC10E9423 -:103C5000BD0A0E94AC4F7093EB016093EA0181E0D2 -:103C600080938C02C1C183E50E94D10A882309F4A4 -:103C7000BBC10E94BD0A0E94AC4F7093ED016093DE -:103C8000EC01B2C180E50E94D10A882351F00E9464 -:103C9000BD0A6093FC017093FD018093FE01909337 -:103CA000FF0189E40E94D10A882381F00E94BD0AA5 -:103CB00025E93FEB46ED5DE30E941252609300025E -:103CC00070930102809302029093030284E40E94A5 -:103CD000D10A882381F00E94BD0A25E93FEB46ED19 -:103CE0005DE30E94444F6093040270930502809349 -:103CF00006029093070283E40E94D10A882351F0C0 -:103D00000E94BD0A609308027093090280930A0220 -:103D100090930B020E948341E9E7F1E006C0909185 -:103D2000C00095FFFCCF8093C60081918823B9F72E -:103D3000ECE7F1E006C09091C00095FFFCCF8093C6 -:103D4000C60081918823B9F74091FC015091FD0193 -:103D50006091FE017091FF018BE095E022E030E080 -:103D6000C4D5E0E8F1E006C09091C00095FFFCCF1B -:103D70008093C60081918823B9F760910002709109 -:103D80000102809102029091030225E93FEB46ED8A -:103D90005DE30E94444FAB01BC018BE095E022E063 -:103DA00030E0A3D5E4E8F1E006C09091C00095FFB3 -:103DB000FCCF8093C60081918823B9F760910402FB -:103DC00070910502809106029091070225E93FEB70 -:103DD00046ED5DE30E941252AB01BC018BE095E021 -:103DE00022E030E082D5E8E8F1E006C09091C00022 -:103DF00095FFFCCF8093C60081918823B9F760912D -:103E000008027091090280910A0290910B0225E943 -:103E10003FEB46ED5DE30E941252AB01BC018BE02B -:103E200095E022E030E061D58091C00085FFFCCFB5 -:103E3000D8C081E00E940E3AD7C083E50E94D10A23 -:103E4000882319F00E94BD0A04C060E070E086E19A -:103E500093E40E949845C8C00E941241C5C080E00A -:103E600001C081E00E941A08BFC01092AB0280918D -:103E7000B0029091B102A091B202B091B3028093CE -:103E8000AC029093AD02A093AE02B093AF020E9439 -:103E90000F0BAAC084E50E94D10A882309F45DC0F3 -:103EA0000E94BD0A0E94B14F6093E902E6E6F1E08C -:103EB000662369F107C09091C00095FFFCCF809305 -:103EC000C600319684918823B1F7ECE8F1E006C092 -:103ED0009091C00095FFFCCF8093C600819188230C -:103EE000B9F78BE095E040E050E0F0D3EEE8F1E088 -:103EF00006C09091C00095FFFCCF8093C6008191D1 -:103F00008823B9F78091C00085FFFCCF6AC010926A -:103F1000A90207C09091C00095FFFCCF8093C60016 -:103F2000319684918823B1F7EFE9F1E006C09091D2 -:103F3000C00095FFFCCF8093C60081918823B9F71C -:103F40006091A9028BE095E070E04AE050E0F4D384 -:103F50008091C00085FFFCCF44C0E6E6F1E007C0D9 -:103F60009091C00095FFFCCF8093C600319684915C -:103F70008823B1F7EEE6F1E007C09091C00095FF0D -:103F8000FCCF8093C600319684918823B1F72091AD -:103F9000EA023091EB0280E690E0289FF001299F31 -:103FA000F00D389FF00D1124E451FD4F06C09091A3 -:103FB000C00095FFFCCF8093C60081918823B9F79C -:103FC000ECE6F1E007C09091C00095FFFCCF809334 -:103FD000C600319684918823B1F78091C00085FF97 -:103FE000FCCF8AE08093C6000E94F00A1CC0EAD091 -:103FF0006093E5027093E6028093E7029093E802F3 -:10400000E1D06093B4027093B5028093B6029093AE -:10401000B702EACF0E94124188E50E94D10A8823A4 -:1040200009F095CB95CBA2960FB6F894DEBF0FBEE4 -:10403000CDBFCF91DF911F910F91FF90EF90DF9057 -:10404000CF90BF90AF909F908F907F906F905F9038 -:104050004F903F902F90089580917C0490917D0423 -:104060008330910514F40E943A0B80917C04909166 -:104070007D040097C1F00E94CA1080917C04909149 -:104080007D04019790937D0480937C048091EA02E3 -:104090009091EB02019664E070E00E94F7529093D9 -:1040A000EB028093EA020E94AB4381E00E946C1015 -:1040B0000C94113A0E94184C8091AB028823A1F510 -:1040C00081E08093AB028091AC029091AD02A0910F -:1040D000AE02B091AF028093B0029093B102A09370 -:1040E000B202B093B302EBEBF0E007C09091C000D6 -:1040F00095FFFCCF8093C600319684918823B1F759 -:10410000E2ECF0E007C09091C00095FFFCCF8093F7 -:10411000C600319684918823B1F78091C00085FF55 -:10412000FCCF8AE08093C60008958091AB02089589 -:10413000A4D00E942F0990DFFECF1F920F920FB6DE -:104140000F9211242F933F938F939F93AF93BF931D -:104150008091820490918304A0918404B09185049D -:1041600030918604232F2A592D3720F02D570196A0 -:10417000A11DB11D20938604809382049093830433 -:10418000A0938404B093850480917E0490917F0471 -:10419000A0918004B09181040196A11DB11D80936E -:1041A0007E0490937F04A0938004B0938104BF9118 -:1041B000AF919F918F913F912F910F900FBE0F90D4 -:1041C0001F9018958FB7F894209182043091830442 -:1041D00040918404509185048FBFB901CA010895AC -:1041E0003FB7F89480917E0490917F04A091800461 -:1041F000B091810426B5A89B05C02F3F19F0019608 -:10420000A11DB11D3FBFBA2FA92F982F8827820F5C -:10421000911DA11DB11D9C01AD01220F331F441F33 -:10422000551F280F391F4A1F5B1FB901CA01089586 -:10423000EF92FF920F931F93CF93DF937B018C013B -:10424000CFDFEB010EC0CCDF6C1B7D0B83E0683E43 -:10425000780738F00894E108F10801091109C851FC -:10426000DC4FE114F1040105110569F7DF91CF91ED -:104270001F910F91FF90EF900895789484B582601C -:1042800084BD84B5816084BD85B5826085BD85B5FA -:10429000816085BDEEE6F0E0808181608083E1E8A9 -:1042A000F0E01082808182608083808181608083E1 -:1042B000E0E8F0E0808181608083E1EBF0E08081E4 -:1042C00084608083E0EBF0E0808181608083EAE7B6 -:1042D000F0E080818460808380818260808380813F -:1042E000816080838081806880831092C1000895FE -:1042F0001F93CF93DF93182FEB0161E084D02097B9 -:1043000009F44AC0CF3FD10509F449C0E12FF0E0DC -:10431000ED57F04FE491E330C1F0E43028F4E130A0 -:1043200051F0E230B1F50CC0E63019F1E73049F157 -:10433000E43079F514C084B5806884BDC7BD32C04F -:1043400084B5806284BDC8BD2DC080918000806826 -:1043500080938000D0938900C093880023C080910F -:104360008000806280938000D0938B00C0938A008D -:1043700019C08091B00080688093B000C093B300F2 -:1043800011C08091B00080628093B000C093B400EF -:1043900009C0C038D1051CF4812F60E002C0812F14 -:1043A00061E052D0DF91CF911F910895833071F079 -:1043B000843028F48130A1F0823021F514C0863099 -:1043C000B1F08730D1F08430E9F404C080918000EE -:1043D0008F7703C0809180008F7D80938000089547 -:1043E00084B58F7702C084B58F7D84BD0895809198 -:1043F000B0008F778093B00008958091B0008F7DDA -:104400008093B000089590E0FC01ED59F04F2491A5 -:10441000FC01ED5BF04FE491EE23A9F0F0E0EC5CE1 -:10442000F04FA491B0E0662341F49FB7F8948C91CB -:10443000209582238C939FBF08959FB7F8948C9109 -:10444000822B8C939FBF08950F931F93DF93CF937D -:104450000F92CDB7DEB7282F30E0F901ED57F04FBE -:104460008491F901ED59F04F14912D5B304FF90112 -:1044700004910023C9F0882319F0698397DF6981CB -:10448000E02FF0E0E75CF04FA491B0E0662331F458 -:104490009FB7F8948C911095812304C09FB7F8942E -:1044A0008C91812B8C939FBF0F90CF91DF911F91A7 -:1044B0000F9108951F920F920FB60F9211242F9310 -:1044C0003F934F935F936F938F939F93EF93FF93DC -:1044D0006091C6002091070530910805C901019639 -:1044E0008F7790704091090550910A0584179507C0 -:1044F00041F029573B4FF901608390930805809361 -:104500000705FF91EF919F918F916F915F914F916F -:104510003F912F910F900FBE0F901F9018959A0109 -:10452000AB0182E08093C00060E47BE48CE490E027 -:104530000E942C532150304040405040CA01B901E4 -:1045400022E030E040E050E00E942C533093C50060 -:104550002093C400E1ECF0E0808180618083808161 -:1045600088608083808180688083089580910905B8 -:1045700090910A0520910705309108052817390701 -:1045800069F0FC01E957FB4F208101968F7790700D -:1045900090930A058093090530E002C02FEF3FEFAA -:1045A000C90108958091090590910A059093080525 -:1045B0008093070508956F927F928F929F92AF929A -:1045C000BF92CF92DF92EF92FF920F931F93DF93F0 -:1045D000CF93CDB7DEB7A0970FB6F894DEBF0FBE6E -:1045E000CDBF5C01CB01BA01611571058105910553 -:1045F00031F4C50160E340E050E0A6D042C06E0156 -:104600000894C11CD11CEE24FF248701622E77245C -:1046100088249924A40193010E940A53F60161930E -:104620006F010894E11CF11C011D111DB901CA01A3 -:10463000611571058105910569F7D801C7010197D9 -:10464000A109B1096E010894C11CD11CC80ED91E64 -:1046500013C0F60160816A3010F4605D01C0695CCE -:10466000C50140E050E070D00894E108F10801096C -:1046700011090894C108D108E114F10401051105DC -:1046800041F7A0960FB6F894DEBF0FBECDBFCF9115 -:10469000DF911F910F91FF90EF90DF90CF90BF902F -:1046A000AF909F908F907F906F9008952115310566 -:1046B00039F48091C00085FFFCCF4093C600089577 -:1046C0007ACF9A01AB0160E070E0F0CF9A01462FFB -:1046D00050E060E070E0EACFEF92FF920F931F93FB -:1046E000CF93DF93EC017A018B012115310539F469 -:1046F0008091C00085FFFCCFE092C60016C02A3032 -:10470000310591F477FF0CC06DE240E050E01CD021 -:1047100010950095F094E094E11CF11C011D111D11 -:10472000CE01B801A7012AE046DFDF91CF911F91AA -:104730000F91FF90EF9008959A01FB01AF0166275A -:1047400057FD6095762FC8CF9A01462F50E060E064 -:1047500070E0C2CFCF93DF93EC016DE040E050E01A -:10476000F3DFCE016AE040E050E0EEDFDF91CF9171 -:104770000895CF93DF93EC01A4DFCE01EBDFDF914F -:10478000CF9108958F929F92BF92CF92DF92EF9236 -:10479000FF920F931F93CF93DF934C017A018B010C -:1047A000D22ECB01BA0120E030E0A9010E943D4F9A -:1047B00087FF09C0C4016DE240E050E0C5DF17FB90 -:1047C000109517F91095C0E050E040E030E02FE37D -:1047D00011C0DA01F9016B2F742F8F2F922F20E077 -:1047E00030E040E251E40E94444F562F472F382FCB -:1047F000292FCF5FCD1568F3C801B701DA01F901A0 -:104800002B2F342F4F2F5E2F0E94644EC62EF72E73 -:104810008C01912F0E94B14FC62FE72ED82FB92EB1 -:104820000E94DD4F9B01AC016C2D7F2D802F912FBD -:104830000E94634EC62EF72E182F092FC4014C2F4D -:104840005E2D6D2F7B2D2AE030E030DFDD2009F476 -:104850003EC0E1EBF1E006C09091C00095FFFCCFB7 -:104860008093C60081918823B9F731C098016C2DDF -:104870007F2D832F902F20E030E040E251E40E9412 -:1048800012528B01F82EE92E9701712F832F922F50 -:104890000E94AC4F9B01AC01EB01C401B9014AE09D -:1048A00050E04ADFBE01882777FD8095982F0E944F -:1048B000DF4F9B01AC01F701602F712F8F2F9E2FCF -:1048C0000E94634EC62EF72E182F092FDA94DD2092 -:1048D00069F6DF91CF911F910F91FF90EF90DF90DC -:1048E000CF90BF909F908F9008954CCF08950895DA -:1048F0002F923F924F925F926F927F928F929F92F0 -:10490000AF92BF92CF92DF92EF92FF920F931F93DD -:10491000DF93CF93CDB7DEB7C055D0400FB6F89434 -:10492000DEBF0FBECDBF4C017A8F698F3A012AA737 -:104930000EABEFAAA8AEB9AECAAEDBAE022F10E046 -:10494000000F111F000F111F9301200F311F3BABF0 -:104950002AABD9012D903D904D905C90FC01E00F69 -:10496000F11FC201B10120813181428153810E9436 -:10497000644E6CAF7DAF8EAF9FAFBEA9EB2EFF2410 -:10498000EE0CFF1CEE0CFF1CF301EE0DFF1DFDAB4A -:10499000ECABA080B180C280D380F401EE0DFF1D8E -:1049A000C601B50120813181428153810E94644E4C -:1049B00021966FAF219722967FAF229723968FAFD4 -:1049C000239724969FAF2497FFA98F2F90E0880FFD -:1049D000991F880F991FF401E80FF91F2081318179 -:1049E000428153812B8F3C8F4D8F5E8F498D5A8D25 -:1049F000840F951FDC016D917D918D919C912B8D84 -:104A00003C8D4D8D5E8D0E94634E262F372F482F93 -:104A1000592F2F8F38A349A35AA3E98DFA8D3C96BD -:104A20002996FFAFEEAF2997A98DBA8D1C962D91CF -:104A30003D914D915C911F972EA73FA748AB59AB75 -:104A4000D4011C962D913D914D915C911F972BA304 -:104A50003CA34DA35EA3A20191015058298B3A8B30 -:104A60004B8B5C8B1501260157FA509457F85094E4 -:104A7000E98DFA8DE00FF11F608171818281938150 -:104A8000BCADADADFEADEFAD2B2F3A2F4F2F5E2F4E -:104A90000E94634EB62EA72E882E692EE98DFA8DC0 -:104AA000EE0DFF1D60817181828193812196BFADE2 -:104AB00021972296AFAD22972396FFAD2397249698 -:104AC000EFAD24972B2F3A2F4F2F5E2F0E94634E6E -:104AD0008B01F82EE92E69897A898B899C89F701E7 -:104AE000202F312F4F2F5E2F0E9412526D8B7E8B05 -:104AF0008F8B988FC201B101D5012B2F3A2F482DF2 -:104B0000562D0E9412529B01AC016D897E898F89BE -:104B1000988D0E94634E6D8B7E8B8F8B988F6989E9 -:104B20007A898B899C89D5012B2F3A2F482D562DB8 -:104B30000E9412525B016C01C201B101F701202FEA -:104B4000312F4F2F5E2F0E9412529B01AC01C601E4 -:104B5000B5010E94644E9B01AC016D897E898F89ED -:104B6000988D0E94D74E162F072FF82EE92EA801F8 -:104B70009701652F742F832F922F20E030E0A90139 -:104B80000E943D4F87FF10C0A8019701652F742F29 -:104B9000832F922F2BED3FE049EC50E40E94644EAE -:104BA000162F072FF82EE92EAA968FADAA978823E5 -:104BB00081F0A8019701652F702F832F9E2D2BED7B -:104BC0003FE049EC50E40E94634E162F072FF82E69 -:104BD000E92EA8019701652F702F832F9E2DA9968E -:104BE0002CAD3DAD4EAD5FADA9970E9412522F8DF9 -:104BF00038A149A15AA15F770E944D515B016C0118 -:104C00002FE632E143E85AE30E943D4F87FDA6C2FA -:104C1000C601B5010E941A500E94B14F7DA76CA732 -:104C20006115710521F481E090E09DA78CA7ACA5EA -:104C3000BDA5BD0180E090E00E94DD4F5B016C01ED -:104C4000A8019701652F702F832F9E2DA601950136 -:104C50000E94444F6D8B7FA388A799A76F8D78A181 -:104C600089A19AA1A60195010E94444F2A966FAF8F -:104C70002A972B967FAF2B972C968FAF2C972D963C -:104C80009FAF2D976EA57FA588A999A92BA13CA1BF -:104C90004DA15EA10E94634EA60195010E94444F62 -:104CA0002E966FAF2E972F967FAF2F9760968FAF70 -:104CB000609761969FAF61975D894FA138A529A53F -:104CC000652F742F832F922F20E030E040E05FE3C8 -:104CD0000E941252BD89AFA1F8A5E9A52B2F3A2F4A -:104CE0004F2F5E2F0E9412529B01AC0160E070E0DA -:104CF00080E89FE30E94634E6EA725967FAF2597BD -:104D000026968FAF269727969FAF2797BFA9EB2FA1 -:104D1000F0E0EE0FFF1FEE0FFF1FCE010196E80F30 -:104D2000F91F2B8D3C8D4D8D5E8D20833183428309 -:104D300053832BA13CA14DA15EA12D873E874F87B8 -:104D4000588BBB2441E050E05CA34BA3BAA5AB2F2A -:104D5000B0E0AA0FBB1FAA0FBB1F9C012A0F3B1F6D -:104D60003C8F2B8F5EA9452F50E0440F551F440FF9 -:104D7000551F81E090E08C0F9D1F840F951F98A315 -:104D80008F8FFBA7EAA7CAC19B2D99310CF068C091 -:104D900069897A898B899C89BD89AFA1F8A5E9A524 -:104DA0002B2F3A2F4F2F5E2F0E9412527B018C0126 -:104DB000C201B101BEA52596AFAD25972696FFADE0 -:104DC00026972796EFAD27972B2F3A2F4F2F5E2F41 -:104DD0000E9412529B01AC01C801B7010E94644EAF -:104DE000D62EA72E882E692E69897A898B899C896F -:104DF000BEA52596AFAD25972696FFAD269727969B -:104E0000EFAD27972B2F3A2F4F2F5E2F0E94125274 -:104E1000162F072FF82EE92EC201B101BD89AFA1CF -:104E2000F8A5E9A52B2F3A2F4F2F5E2F0E94125283 -:104E30009B01AC01D801F7016B2F7A2F8F2F9E2F8A -:104E40000E94634E262F372F482F592F298B3A8BDC -:104E50004B8B5C8BB3942D2C3A2C482C562C6AC06F -:104E6000ABA1BCA1BD0180E090E00E94DD4FBD89F7 -:104E7000AFA1F8A5E9A52B2F3A2F4F2F5E2F0E9447 -:104E800012527B018C017F2D912F0E94414F1B01FB -:104E90002C016E2D7F2D802F912F0E9475525B016A -:104EA0006C01EAA9FBA9E080F1800281138117FB64 -:104EB000109517F91095ACA9BDA96D907D908D90B6 -:104EC0009C90C801B701A20191010E941252698B06 -:104ED0007A8B8B8B9C8BC401B301A60195010E9438 -:104EE00012529B01AC0169897A898B899C890E9445 -:104EF000644E262F372F482F592F298B3A8B4B8BF7 -:104F00005C8BC801B701A60195010E9412527B017A -:104F10008C01C401B301A20191010E9412529B01B4 -:104F2000AC01C801B7010E94634E262E372E482ED1 -:104F3000592EBB245CAD4DAD3EAD2FAD652F742F0A -:104F4000832F922F29893A894B895C890E94644E6C -:104F5000EB8DFC8D608371838283938321965FAD9B -:104F6000219722964FAD229723963FAD2397249603 -:104F70002FAD2497652F742F832F922FA2019101BB -:104F80000E94644EAF8DB8A16D937D938D939C93D9 -:104F90001397EAA5FBA560817181828193812A968E -:104FA000BFAD2A972B96AFAD2B972C96FFAD2C97C4 -:104FB0002D96EFAD2D972B2F3A2F4F2F5E2F0E945E -:104FC000644EAAA5BBA56D937D938D939C93139777 -:104FD0006D857E858F8598892E96BFAD2E972F96ED -:104FE000AFAD2F976096FFAD60976196EFAD61977B -:104FF0002B2F3A2F4F2F5E2F0E94644E6D877E8796 -:105000008F87988B69817A818B819C8120E030E049 -:10501000A9010E943D4F87FF07C080E090E0DC01BE -:1050200089839A83AB83BC836D817E818F819885D0 -:1050300020E030E0A9010E943D4F87FF07C080E0DB -:1050400090E0DC018D839E83AF83B88769857A8584 -:105050008B859C8520E030E0A9010E943D4F87FFB1 -:1050600007C080E090E0DC0189879A87AB87BC8726 -:1050700069817A818B819C8120E030E04DE453E4AA -:105080000E944051181644F480E090E0ADE4B3E48F -:1050900089839A83AB83BC836D817E818F81988560 -:1050A00020E030E04DE453E40E944051181644F4EF -:1050B00080E090E0ADE4B3E48D839E83AF83B88756 -:1050C00069857A858B859C8520E030E040EF52E44D -:1050D0000E944051181644F480E090E0A0EFB2E442 -:1050E00089879A87AB87BC87CE010196BE016B5F2B -:1050F0007F4FAE01475F5F4F9E01235F3F4FE8AC9C -:10510000F9AC0AAD1BADFAE6CF2ED12CCC0EDD1ECC -:10511000D5D4EBA1FCA13196FCA3EBA32BA13CA120 -:105120004CA55DA52417350708F42ECE698D7A8D20 -:105130006C5F7F4F498D5A8D485F5F4F898D9A8D87 -:1051400029962EAD3FAD2997E8ACF9AC0AAD1BAD61 -:10515000EAE6CE2ED12CCC0EDD1EB0D4C05BDF4FE4 -:105160000FB6F894DEBF0FBECDBFCF91DF911F9178 -:105170000F91FF90EF90DF90CF90BF90AF909F90F6 -:105180008F907F906F905F904F903F902F900895F9 -:105190008F5F803109F480E008952F923F924F9203 -:1051A0005F926F927F928F929F92AF92BF92CF92B7 -:1051B000DF92EF92FF920F931F93DF93CF93CDB7C0 -:1051C000DEB76A970FB6F894DEBF0FBECDBF9A8FD9 -:1051D000898F3A014B0178018901DC01D8966D91E4 -:1051E0007D918D919C91DB970E94DD4F5B016C015D -:1051F000A40193010E9412520E942A4F0E94B14FB3 -:10520000262F372F482F592F2D873E874F87588BB2 -:10521000C601B501A80197010E9412520E942A4FAF -:105220000E94B14F9B01AC01298B3A8B4B8B5C8B5D -:105230008D859E85AF85B88988379105A105B10513 -:1052400040F488E790E0A0E0B0E08D879E87AF87CC -:10525000B88B283731054105510540F428E730E087 -:1052600040E050E0298B3A8B4B8B5C8BE98DFA8DBB -:10527000EC5BFF4F6080718082809380A98DBA8D36 -:10528000DC966D917D918D919C91DF970E94DD4F11 -:105290006D837E838F839887C401B3010E94DF4FA3 -:1052A0001B012C0120E030E0A9010E943D4F882322 -:1052B00029F1C601B501A60195010E9412527B0198 -:1052C0008C016D817E818F8198859B01AC010E944C -:1052D00012529B01AC01C801B7010E94634E7B01D1 -:1052E0008C01C201B101A20191010E94644E9B0197 -:1052F000AC01C801B7010E94444F04C060E070E0F7 -:1053000080E090E00E942A4F0E94AC4F69837A832C -:105310008B839C83E980FA800B811C81E98DFA8D57 -:10532000E05CFF4F60817181828193810E94DD4F3B -:1053300069877A878B879C8766277727CB016619D1 -:105340007709880999090E94DF4F3B014C0120E051 -:1053500030E0A9010E943D4F882349F169857A8593 -:105360008B859C859B01AC010E9412526D8B7E8BBC -:105370008F8B988FC601B501A60195010E9412522C -:105380009B01AC016D897E898F89988D0E94634E47 -:105390005B016C01C401B301A40193010E94644E3E -:1053A0009B01AC01C601B5010E94444F04C060E0FE -:1053B00070E080E090E00E941A50E98DFA8DA0889C -:1053C000B188C288D3883501460129813A814B8151 -:1053D0005C81621A730A840A950A0E94AC4FA40188 -:1053E0009301261B370B480B590BDA01C90157FFF4 -:1053F00068C0C201B10120E030E0A9010E943D4F28 -:10540000882309F443C0C201B101A20191010E94A5 -:10541000644E7B018C01C601B5010E94DD4F9B01EA -:10542000AC01C801B7010E9412527B018C016D8151 -:105430007E818F8198859B01AC010E9412529B0155 -:10544000AC01C801B7010E94634E7B018C016985E4 -:105450007A858B859C859B01AC010E9412529B0131 -:10546000AC01C801B7010E94644E7B018C01C201EE -:10547000B10120E030E040E850E40E9412529B016C -:10548000AC01C801B7010E94444F04C060E070E065 -:1054900080E090E00E942A4F0E94AC4FE62EF72E4B -:1054A000082F192F17FF03C0EE24FF248701EA14E9 -:1054B000FB040C051D0510F08601750180E090E0ED -:1054C000DC012FB7F894E98DFA8DE45BFF4F308152 -:1054D000332311F5E98DFA8DE48AF58A068B178B53 -:1054E000E80EF91E0A1F1B1FE08EF18E028F138F2C -:1054F0008D859E85AF85B88984AF95AFA6AFB7AFD0 -:10550000AF01405C5F4F89899A89AB89BC89FA01F8 -:1055100080839183A283B3832FBF6A960FB6F894DA -:10552000DEBF0FBECDBFCF91DF911F910F91FF90D6 -:10553000EF90DF90CF90BF90AF909F908F907F9033 -:105540006F905F904F903F902F900895AF92BF92D1 -:10555000CF92DF92EF92FF920F931F93CF93DF933F -:10556000EB018A01209709F472C04115510509F435 -:105570006EC0DAA4CBA4BCA4ADA46EA17FA188A503 -:1055800099A5D601F5012B2F3A2F4F2F5E2F0E94A0 -:105590003D4F882309F45BC08FA9882309F04BC0D5 -:1055A000F801E6A0F7A000A511A5A6019501652FB9 -:1055B000742F832F922FA80197010E944051181633 -:1055C000D4F5C801B701A80197010E9412527B01CE -:1055D0008C012AA93BA94CA95DA95058CA01B9015F -:1055E0000E94644E2EA53FA548A959A90E941252B7 -:1055F0009B01AC01C801B7010E94634E0E947F521B -:10560000E62E172F082FF92EA6019501652F742F6E -:10561000832F922F2E2D312F402F5F2D0E943D4F33 -:1056200087FF04C0ED2C1C2D0B2DFA2C5E2D412F75 -:10563000302F2F2D02C0A6019501852F942FA32F67 -:10564000B22F8EA39FA3A8A7B9A781E08EABDF914D -:10565000CF911F910F91FF90EF90DF90CF90BF906F -:10566000AF900895CF92DF92EF92FF920F931F9326 -:10567000DF93CF930F92CDB7DEB780914C0A809124 -:105680004C0A20914D0A90E04096821B91098F7040 -:1056900090708430910544F120914C0A23502F7072 -:1056A00040E050E000E010E08DE4E82EF12C18C05E -:1056B000222309F420E12150822F90E08E9D600189 -:1056C0008F9DD00C9E9DD00C11248CE795E0C80EC8 -:1056D000D91EC601B801298339DFA80186012981B5 -:1056E00080914D0A281721F70F90CF91DF911F91DC -:1056F0000F91FF90EF90DF90CF9008958F929F923F -:10570000AF92BF92CF92DF92EF92FF920F931F93CF -:10571000CF93DF93EC016B01009709F467C08FA969 -:10572000882309F063C0EEA0FFA008A519A5FB011E -:10573000B6A0A7A090A481A4C801B701D501F40127 -:105740002B2F3A2F4F2F5E2F0E943D4F87FF4EC0C9 -:10575000C801B701A80197010E9412527B018C0178 -:105760002AA93BA94CA95DA95058CA01B9010E94B8 -:10577000644E2EA53FA548A959A90E9412529B012B -:10578000AC01C801B7010E94634E0E947F52E62E11 -:10579000C72FD82F192FA5019401652F742F832FA0 -:1057A000922F2E2D3C2F4D2F512F0E943D4F87FFC2 -:1057B00004C0EB2CCA2DD92D182DA5019401652FFD -:1057C0007A2D832F982D2E2D3C2F4D2F512F0E9457 -:1057D0003D4F882359F08E2D9C2FAD2FB12FF60110 -:1057E00086A397A3A0A7B1A781E086ABDF91CF9155 -:1057F0001F910F91FF90EF90DF90CF90BF90AF90EF -:105800009F908F900895DF92EF92FF920F931F93D6 -:10581000CF93DF93D0904D0A00E010E080E090E05D -:105820002DE4E22EF12C13C02D2D30E02E9DE00151 -:105830002F9DD00D3E9DD00D1124C458DA4FB801D4 -:10584000AE015CDF8D2DA4DCD82EC8018E01209125 -:105850004C0AD21649F7B80140E050E04FDFDF9123 -:10586000CF911F910F91FF90EF90DF9008952F92AD -:105870003F924F925F926F927F928F929F92AF92E0 -:10588000BF92CF92DF92EF92FF920F931F93CF932D -:10589000DF93F0904D0AC0E0D0E03DE4632E712C20 -:1058A0003EC0069D6001079DD00C169DD00C1124B2 -:1058B0008CE795E0C80ED91E209769F18EA9882340 -:1058C00021F4F60186A9882331F18AA09BA0ACA01F -:1058D000BDA06EA17FA188A599A5A50194010E94F4 -:1058E000444F1B012C01069DF001079DF00D169DF4 -:1058F000F00D1124E458FA4F66A177A180A591A577 -:10590000A50194010E94444F8B019C01CE01B2017C -:10591000A10143DC1EAA8F2D3BDCF82EE6010F2DE2 -:10592000112707FD109580914C0A90E00817190780 -:1059300009F0B7CF2097E9F0CAA0DBA0ECA0FDA04A -:105940006EA17FA188A599A5A70196010E94444F49 -:105950004B015C016DEC7CEC8CE49DE3A7019601AE -:105960000E94444F8B019C01CE01B501A40115DCBE -:105970001EAADF91CF911F910F91FF90EF90DF90C2 -:10598000CF90BF90AF909F908F907F906F905F90DF -:105990004F903F902F90089565DE35DF68CF1092CD -:1059A0004C0A10924D0A80E1ECE6F5E0DF011D9211 -:1059B0008A95E9F780E090E0DC018093530A9093A8 -:1059C000540AA093550AB093560A8093570A9093AD -:1059D000580AA093590AB0935A0A80935B0A90938D -:1059E0005C0AA0935D0AB0935E0A80935F0A90936D -:1059F000600AA093610AB093620A80934F0A909361 -:105A0000500AA093510AB093520A0895CF939091EF -:105A10004D0A80914C0A981779F140914D0A242F34 -:105A200030E08DE490E0289FF001299FF00D389F31 -:105A3000F00D1124EC53FA4FC08150E02DE430E01A -:105A400016C0842F90E0829FF001839FF00D929FFB -:105A5000F00D1124EC53FA4F80819181A281B38122 -:105A60000097A105B10509F05F5F4F5F4F7080910E -:105A70004C0A481731F70AC06091AA02662321F048 -:105A80008EE070E00E947821C0E050E08091AA0290 -:105A9000882339F4552329F48EE060E070E00E94F9 -:105AA00078218091AA02882339F0CC2329F08EE056 -:105AB0006C2F70E00E947821CF9108952F923F9231 -:105AC0004F925F926F927F928F929F92AF92BF920E -:105AD000CF92DF92EF92FF920F931F93DF93CF93BA -:105AE000CDB7DEB7C555D0400FB6F894DEBF0FBEB8 -:105AF000CDBF2C013B011A013AA329A39E2CAF2C48 -:105B0000802EB12EDCAACBAA80914C0A41DB649690 -:105B10008FAF6497082F112707FD109505C00E94CD -:105B2000AB4381E00E946C1080914D0A90E0801799 -:105B30009107A9F3D2016D917D918D919C91209156 -:105B400020053091210540912205509123050E94A6 -:105B500012520E94E2516FAB78AF89AF9AAFF30156 -:105B60006081718182819381209124053091250586 -:105B700040912605509127050E9412520E94E25141 -:105B80006BAF7CAF8DAF9EAFD1016D917D918D914B -:105B90009C91209128053091290540912A0550912A -:105BA0002B050E9412520E94E2516FAF21967FAFE7 -:105BB000219722968FAF229723969FAF2397E9A133 -:105BC000FAA1608171818281938120912C053091AD -:105BD0002D0540912E0550912F050E9412520E94D2 -:105BE000E2516FA778AB89AB9AAB80917805909121 -:105BF0007905A0917A05B0917B052FA538A949A90F -:105C00005AA9281739074A075B0709F445C060916C -:105C1000A902E62FF0E0EE0FFF1FE355F54F80815C -:105C200091810E94A64220E030E046E153E40E94C8 -:105C30003D4F87FF31C080914E0A882369F54FA5FB -:105C400058A969A97AA9409378055093790560937A -:105C50007A0570937B05EEE4F4E007C09091C000F4 -:105C600095FFFCCF8093C600319684918823B1F7CD -:105C7000E2E7F4E007C09091C00095FFFCCF80936D -:105C8000C600319684918823B1F78091C00085FFCA -:105C9000FCCF8AE08093C6008091780590917905C9 -:105CA000A0917A05B0917B052FA538A949A95AA9D9 -:105CB000281B390B4A0B5B0BCA01B90157FF07C000 -:105CC00090958095709561957F4F8F4F9F4F0E9463 -:105CD000DF4F7B018C0160912C0570912D05809127 -:105CE0002E0590912F0520E030E04DEC53E40E940A -:105CF00012529B01AC01C801B7010E944051181615 -:105D00006CF54FA558A969A97AA9409378055093D5 -:105D1000790560937A0570937B05EEE4F4E007C0A3 -:105D20009091C00095FFFCCF8093C600319684917E -:105D30008823B1F7E4E5F4E007C09091C00095FF37 -:105D4000FCCF8093C600319684918823B1F780916F -:105D5000C00085FFFCCF8AE08093C60080914C0A8A -:105D6000682F70E07AA369A38DE490E0689FF0014A -:105D7000699FF00D789FF00D1124E458FA4FDF0170 -:105D8000A45BBF4F1C9280916C0590916D05A09112 -:105D90006E05B0916F058BA39CA3ADA3BEA38FA985 -:105DA00098ADA9ADBAAD2BA13CA14DA15EA1821BBE -:105DB000930BA40BB50BB7FF07C0B095A0959095BA -:105DC00081959F4FAF4FBF4F80839183A283B38351 -:105DD0004091700550917105609172057091730545 -:105DE0004FA358A769A77AA78DE490E069A17AA18B -:105DF000689FF001699FF00D789FF00D1124E45821 -:105E0000FA4F8BAD9CADADADBEAD2FA138A549A568 -:105E10005AA5821B930BA40BB50BB7FF07C0B09517 -:105E2000A095909581959F4FAF4FBF4F84839583E9 -:105E3000A683B783409174055091750560917605EE -:105E4000709177054BA75CA76DA77EA78DE490E0C6 -:105E500069A17AA1689FF001699FF00D789FF00D0C -:105E60001124E458FA4F23968CAD9DADAEADBFAD75 -:105E700023972BA53CA54DA55EA5821B930BA40BD8 -:105E8000B50BB7FF07C0B095A095909581959F4F32 -:105E9000AF4FBF4F80879187A287B3874090780527 -:105EA0005090790560907A0570907B052091EC0107 -:105EB0003091ED016FA578A989A99AA9641975098E -:105EC0008609970997FF07C0909580957095619511 -:105ED0007F4F8F4F9F4F442737FD4095542F0E948F -:105EE000D85224E630E040E050E00E942C538DE48C -:105EF00090E069A17AA1689FF001699FF00D789FF9 -:105F0000F00D1124E458FA4F2487358746875787C8 -:105F1000C080D18072816381E480F5800681178121 -:105F200080859185A285B3858E159F05A007B10751 -:105F300014F4D801C70182179307A407B50714F416 -:105F4000DA01C901FB0196014F2F562F2817390797 -:105F50004A075B0714F49C01AD018DE490E0A9A110 -:105F6000BAA1A89FF001A99FF00DB89FF00D1124D0 -:105F7000E458FA4F208B318B428B538B26303105FE -:105F80004105510510F40C942B399F01285B3F4FBC -:105F90008091AA02482F50E060E070E0D9014D9353 -:105FA0005D936D937C93139710A22FA938AD49ADE3 -:105FB0005AAD6BA17CA18DA19EA12617370748077A -:105FC000590714F481E080A38BAD9CADADADBEAD9F -:105FD0002FA138A549A55AA582179307A407B5078D -:105FE00084F48DE490E049A15AA1489FF001499FB3 -:105FF000F00D589FF00D1124E458FA4F80A18260F3 -:1060000080A323966CAD7DAD8EAD9FAD23972BA560 -:106010003CA54DA55EA5621773078407950784F418 -:106020008DE490E049A15AA1489FF001499FF00DED -:10603000589FF00D1124E458FA4F80A1846080A38A -:106040006FA578A989A99AA964157505860597058C -:1060500084F48DE490E0A9A1BAA1A89FF001A99FC2 -:10606000F00DB89FF00D1124E458FA4F80A188601C -:1060700080A38DE490E029A13AA1289FF001299FF7 -:10608000F00D389FF00D1124E458FA4FABA9BCA9CC -:106090008C9181A380819181A281B3810097A10518 -:1060A000B10509F05A9A8DE490E029A13AA1289F00 -:1060B000F001299FF00D389FF00D1124E458FA4F9C -:1060C00084819581A681B7810097A105B10509F06A -:1060D0005A9A8DE490E049A15AA1489FF001499F46 -:1060E000F00D589FF00D1124E458FA4F80859185EA -:1060F000A285B3850097A105B10509F05A9A8DE4F0 -:1061000090E069A17AA1689FF001699FF00D789FE6 -:10611000F00D1124E458FA4F84859585A685B7853E -:106120000097A105B10509F05A9A8DE490E0A9A164 -:10613000BAA1A89FF001A99FF00DB89FF00D1124FE -:10614000E458FA4F84859585A685B7850097A10503 -:10615000B10549F4F090580510915905E0905A05A1 -:1061600000915B0508C0F090400510914105E0905A -:10617000420500914305692D7A2D882D9B2D2F2DE9 -:10618000312F4E2D502F0E943D4F87FD04C0F92C1A -:106190001A2DE82C0B2D90914C0A80914D0AE92F75 -:1061A000F0E07096E81BF109EF70F070FCA7EBA728 -:1061B000BF01882777FD8095982F0E94DF4F4B0104 -:1061C0005C0120E030E040E051E40E943D4F87FF59 -:1061D00017C02BA53CA52230310594F06F2D712FEF -:1061E0008E2D902FA50194010E94125220E030E0E4 -:1061F00040E05EE30E941252F62E172FE82E092F80 -:1062000080916C0590916D05A0916E05B0916F0520 -:106210002FA938AD49AD5AAD281B390B4A0B5B0B82 -:10622000CA01B9010E94DF4F20912005309121055C -:1062300040912205509123050E94444F762E672EEF -:106240008BA39FA3A301382F292F852F942FA32F32 -:10625000B22F89839A83AB83BC8380917005909120 -:106260007105A0917205B09173052BAD3CAD4DAD9C -:106270005EAD281B390B4A0B5B0BCA01B9010E94AA -:10628000DF4F20912405309125054091260550913E -:1062900027050E94444F2B018BAB24969FAF249778 -:1062A000382F292F862F952DA32FB22F8D839E83D4 -:1062B000AF83B8878091740590917505A09176059C -:1062C000B091770523962CAD3DAD4EAD5FAD2397D4 -:1062D000281B390B4A0B5B0BCA01B9010E94DF4F27 -:1062E000209128053091290540912A0550912B05D0 -:1062F0000E94444F362E272E28968FAF28972C9633 -:106300009FAF2C97A101382F292F852F942FA32FD2 -:10631000B22F89879A87AB87BC878090EC019090D9 -:10632000ED018091780590917905A0917A05B09161 -:106330007B052FA538A949A95AA9281B390B4A0B57 -:106340005B0BCA01B9010E94DF4F20912C053091EF -:106350002D0540912E0550912F050E94444F5B0161 -:106360006C01B401882777FD8095982F0E94DF4F3C -:106370009B01AC01C601B5010E94125220E030E041 -:1063800048EC52E40E94444F6B01B82FA92F4B01F7 -:10639000A82EB92E9B01482F592F2D873E874F8756 -:1063A000588B8DE490E049A15AA1489FF001499F84 -:1063B000F00D589FF00D1124E458FA4F20813181DF -:1063C00042815381211531054105510591F5248103 -:1063D000358146815781211531054105510549F522 -:1063E00020853185428553852115310541055105AB -:1063F00001F5B6018B2F9A2F20E030E0A9010E9411 -:106400004051181624F0B7FAB094B7F8B0948DE460 -:1064100090E069A17AA1689FF001699FF00D789FD3 -:10642000F00D1124E458FA4F86A697A6A0AAB1AAA7 -:1064300047C0A3013BA12FA1652F762D832F922F5B -:106440000E94BD524B015C013BA924962FAD2497BD -:10645000642D752D832F922F0E94BD522B013C017C -:10646000A10128963FAD28972C962FAD2C97652F2C -:10647000722D832F922F0E94BD526BA37CA38DA3FC -:106480009EA3C501B401A30192010E94644E2BA1F9 -:106490003CA14DA15EA10E94644E0E947F522DE45A -:1064A00030E0A9A1BAA1A29FF001A39FF00DB29F75 -:1064B000F00D1124E458FA4F66A777A780AB91AB93 -:1064C0008DE490E0E9A1FAA1E89F6001E99FD00C7A -:1064D000F89FD00C11242CE735E0C20ED31ED60154 -:1064E0009E968D909D90AD90BC90D19760E070E0AD -:1064F00080E89FE3A50194010E94444F9B01AC01F9 -:106500006F2D712F8E2D902F0E941252362E272E16 -:10651000782E692EC501B401D101F3012B2F3A2F3A -:106520004F2F5E2F0E941252F60162A373A384A321 -:1065300095A360897189828993890E94DD4FD10179 -:10654000F3012B2F3A2F4F2F5E2F0E9412520E94E1 -:106550002A4F0E94B14FD601D8966D937D938D93AB -:106560009C93DB978E010F5F1F4FB1E14B2E512C97 -:106570004C0E5D1E7201F8016191719181919191B2 -:106580008F01D101F3012B2F322D4F2F562D0E9459 -:106590001252D7016D937D938D939D937D010415C8 -:1065A000150549F7E0E1F5E0F8A7EFA39E012F5D9F -:1065B0003F4F66963FAF2EAF66973F011201DD2435 -:1065C000CC24A0E88A2EFFE3BF2ED101ED90FD90F0 -:1065D0000D911D911D01AA24A394C801B70120E0CB -:1065E00030E0A9010E94405118162CF0AA24C801DD -:1065F000B701905802C0C801B701D3012D913D9158 -:106600004D915D913D012BA33CA34DA35EA30E9440 -:106610004051181664F5AA2021F4A801970150589A -:1066200002C0A80197016BA17CA18DA19EA10E942F -:10663000444F9B01AC01ED2DFC2DA82DBB2DBF01BE -:10664000CD010E943D4F87FD12C0AA2021F417FB07 -:10665000109517F910956BA17CA18DA19EA1A801A1 -:1066600097010E94444FD62EC72E882EB92E6696CB -:10667000EEADFFAD66972E163F0609F0A6CFA60138 -:10668000652F7C2D882D9B2D20E030E040E85FE3D6 -:106690000E943D4F87FFA8C012015CA24BA2D1010E -:1066A000ED90FD900D911D911D01AA24A394C801A8 -:1066B000B70120E030E0A9010E94405118162CF0EB -:1066C000AA24C801B701905802C0C801B701EFA1C0 -:1066D000F8A54190519061907190F8A7EFA3A301A4 -:1066E00092010E944051181634F5AA2021F4A80105 -:1066F0009701505802C0A8019701C301B2010E943E -:10670000444F9B01AC016D2D7C2D882D9B2D0E944B -:106710003D4F87FD10C0AA2021F417FB109517F9F3 -:106720001095C301B201A80197010E94444FD62ED3 -:10673000C72E882EB92E66962EAD3FAD66972216CF -:10674000330609F0ACCF4BA05CA0D2016D917D91D6 -:106750008D919C91D6012B2F3C2D482D5B2D0E94B5 -:106760001252F20161937193819391932F01669676 -:106770002EAD3FAD6697E217F30739F78DE490E051 -:1067800049A15AA1489F8001499F100D589F100DA3 -:10679000112404581A4FD80192966D917D918D91D4 -:1067A0009C919597D6012B2F3C2D482D5B2D0E9457 -:1067B0001252F80162A373A384A395A360AD71ADD7 -:1067C00082AD93AD0E94DD4FD6012B2F3C2D482D7D -:1067D0005B2D0E9412520E94B14FD801D8966D9342 -:1067E0007D938D939C93DB978DE490E0E9A1FAA1D2 -:1067F000E89F8001E99F100DF89F100D11240458A7 -:106800001A4FD80150966D917D918D919C9153971F -:106810000E94DD4FF80126A537A540A951A90E9485 -:10682000444F562E472E382E292EF8018081918113 -:10683000A281B3810097A105B10569F58481958195 -:10684000A681B7810097A105B10529F580859185BD -:10685000A285B3850097A105B105E9F4A2019101D4 -:10686000652F742F832F922F209148053091490571 -:1068700040914A0550914B050E9412520E942A4FA6 -:106880000C5B1F4F0E94B14FD8016D937D938D9388 -:106890009C93139765C1A2019101652F742D832FDD -:1068A000922D209144053091450540914605509127 -:1068B00047050E9412520E942A4F0E94B14F2DE4B8 -:1068C00030E0E9A1FAA1E29F8001E39F100DF29F61 -:1068D000100D112404581A4FE4E46E2E712C600E32 -:1068E000711ED3016D937D938D939C93139780902C -:1068F0005C0590905D05A0905E05B0905F050E94DC -:10690000DD4F6B017C01F80160817181828193818F -:106910000E94DF4F9B01AC01C701B6010E941252D9 -:106920006B017C01D80150966D917D918D919C9168 -:1069300053970E94DD4F9B01AC01C701B6010E9435 -:10694000444F7B018C01C501B4010E94DD4F9B01C6 -:10695000AC01C801B7010E94405118162CF4F30194 -:1069600080829182A282B3828090600590906105BE -:10697000A0906205B09063058DE490E029A13AA152 -:10698000289F8001299F100D389F100D1124045855 -:106990001A4F64E4662E712C600E711ED3016D9146 -:1069A0007D918D919C910E94DD4F6B017C01F801DE -:1069B00064817581868197810E94DF4F9B01AC01C4 -:1069C000C701B6010E9412526B017C01D80150969A -:1069D0006D917D918D919C9153970E94DD4F9B010C -:1069E000AC01C701B6010E94444F7B018C01C50177 -:1069F000B4010E94DD4F9B01AC01C801B7010E94A8 -:106A0000405118162CF4F30180829182A282B38245 -:106A10008090680590906905A0906A05B0906B051C -:106A20008DE490E029A13AA1289F8001299F100DB3 -:106A3000389F100D112404581A4F54E4652E712C00 -:106A4000600E711ED3016D917D918D919C910E947C -:106A5000DD4F6B017C01F80164857585868597851E -:106A60000E94DF4F9B01AC01C701B6010E94125288 -:106A70006B017C01D80150966D917D918D919C9117 -:106A800053970E94DD4F9B01AC01C701B6010E94E4 -:106A9000444F7B018C01C501B4010E94DD4F9B0175 -:106AA000AC01C801B7010E94405118162CF4F30143 -:106AB00080829182A282B382809064059090650565 -:106AC000A0906605B09067058DE490E029A13AA1F9 -:106AD000289F8001299F100D389F100D1124045804 -:106AE0001A4F44E4642E712C600E711ED3016D9117 -:106AF0007D918D919C910E94DD4F6B017C01F8018D -:106B000060857185828593850E94DF4F9B01AC0172 -:106B1000C701B6010E9412526B017C01D801509648 -:106B20006D917D918D919C9153970E94DD4F9B01BA -:106B3000AC01C701B6010E94444F7B018C01C50125 -:106B4000B4010E94DD4F9B01AC01C801B7010E9456 -:106B5000405118162CF4F30180829182A282B382F4 -:106B60008DE490E029A13AA1289F8001299F100D72 -:106B7000389F100D112404581A4FF801EC5BFF4F99 -:106B800060817181828193810E94DD4F6B017C0164 -:106B9000D201F1012B2F342D4F2F522D0E94444F43 -:106BA000D801D2966D937D938D939C93D597C70111 -:106BB000B6012DEB37E346E051E40E9412520E94E9 -:106BC000AC4FF801648F758F868F978F20914C059D -:106BD00030914D0540914E0550914F052B962CAFAD -:106BE0003DAF4EAF5FAF2B97498D5A8D6B8D7C8D2E -:106BF0004BAB5CAB6DAB7EABCB01BA0120E030E0C0 -:106C0000A9010E94405118164CF08BA89CA8ADA871 -:106C1000BEA8B7FAB094B7F8B09404C08BA89CA8EB -:106C2000ADA8BEA8609150057091510580915205A4 -:106C3000909153052F966CAF7DAF8EAF9FAF2F977E -:106C400020E030E040E05FE30E9412527B016C01E3 -:106C5000C501B4012E2D3F2D4C2D5D2D0E944051BC -:106C6000181674F02B966CAD7DAD8EAD9FAD2B9745 -:106C700020E030E040E05FE30E9412527B016C01B3 -:106C80008DE490E0E9A1FAA1E89FD001E99FB00D61 -:106C9000F89FB00D1124A458BA4FFD01B2969296F8 -:106CA0003C90218022812BA333813FA36E2D7F2D29 -:106CB0008C2D9D2DD101FBA1EFA12B2F3A2F4F2F12 -:106CC0005E2F0E943D4F87FD04C0E32CF22CCBA029 -:106CD000DFA04D8D5E8D6F8D78A127964CAF5DAF97 -:106CE0006EAF7FAF2797CB01BA0120E030E0A9015A -:106CF0000E94405118165CF027968CAC9DACAEAC4F -:106D0000BFAC2797B7FAB094B7F8B09406C02796EF -:106D10008CAC9DACAEACBFAC279760915405709124 -:106D20005505809156059091570563966CAF7DAFE0 -:106D30008EAF9FAF639720E030E040E05FE30E94BA -:106D40001252162F072F482E792EC501B401D801F3 -:106D50002B2F3A2F442D572D0E94405118168CF49A -:106D60006E2D7F2D8C2D9D2DD8012B2F3A2F442D4C -:106D7000572D0E943D4F87FD04C0E12EF02EC42CFC -:106D8000D72C8BA59CA5823091050CF469C160912C -:106D90004F0A7091500A8091510A9091520A27E14E -:106DA00037EB41ED58E30E94405118160CF058C1E2 -:106DB0002091530A3091540A4091550A5091560A35 -:106DC0002BA73CA74DA75EA769897A898B899C89E7 -:106DD0000E94634E9B01AC010E941252162F072F96 -:106DE000782E692E8090570A9090580AA090590AE0 -:106DF000B0905A0A6D897E898F89988DA50194017A -:106E00000E94634E9B01AC010E941252B62FA72F25 -:106E1000F82FE92FB801C301272F362F492F582FFC -:106E2000CA01B9018D013F01212F302F472D562D69 -:106E30000E94644E0E947F522B013C016BA57CA5F1 -:106E40008DA59EA520E030E0A9010E9440511816B2 -:106E50006CF46BA57CA58DA59EA527E137EB41EDD4 -:106E600058E30E94405118167CF10CC06BA57CA51C -:106E70008DA59EA527E137EB41ED58EB0E943D4FD4 -:106E800087FD22C0C501B40120E030E0A9010E94C5 -:106E9000405118165CF4C501B40127E137EB41ED10 -:106EA00058E30E94405118167CF00AC0C501B40195 -:106EB00027E137EB41ED58EB0E943D4F87FD04C0C1 -:106EC0003E2C2F2CCBA2DFA2C301B2012B962CADFE -:106ED0003DAD4EAD5FAD2B970E9440511816CCF4DE -:106EE0002B966CAD7DAD8EAD9FAD2B97A30192011E -:106EF0000E94444F9B01AC01D101FBA1EFA16B2F7C -:106F0000722D8F2F9E2F0E941252362E272E8BA36A -:106F10009FA36BA97CA98DA99EA920915B0A3091A2 -:106F20005C0A40915D0A50915E0A0E94634ED62E23 -:106F3000C72EB82E892EE62EF72E082F192FAA2439 -:106F4000A39420E030E0A9010E94405118162CF0D3 -:106F5000AA24C801B701905804C06D2D7C2D8B2D3B -:106F6000982D2F962CAD3DAD4EAD5FAD2F970E9465 -:106F700040511816FCF4AA2021F417FB109517F9BC -:106F800010952F966CAD7DAD8EAD9FAD2F97A8015E -:106F900097010E94444F9B01AC01D101FBA1EFA1DD -:106FA0006B2F722D8F2F9E2F0E941252362E272E5E -:106FB0008BA39FA327966CAD7DAD8EAD9FAD27971C -:106FC00020915F0A3091600A4091610A5091620AF3 -:106FD0000E94634ED62EC72EB82E892EE62EF72E8F -:106FE000082F192FAA24A39420E030E0A9010E94C1 -:106FF000405118162CF0AA24C801B701905804C0BB -:107000006D2D7C2D8B2D982D63962CAD3DAD4EAD09 -:107010005FAD63970E9440511816F4F4AA2021F442 -:1070200017FB109517F9109563966CAD7DAD8EAD7D -:107030009FAD6397A80197010E94444F9B01AC014B -:10704000D101FBA1EFA16B2F722D8F2F9E2F0E94DC -:1070500012527B016C0104C0E32CF22CCBA0DFA008 -:107060008DE490E049A15AA1489F8001499F100DED -:10707000589F100D112404581A4F8E2D9F2DAC2DA2 -:10708000BD2DF80182A793A7A4A7B5A722A933A96C -:1070900044A955A95058CA01B9010E94644ED801AB -:1070A0009E962D913D914D915C91D1970E941252E7 -:1070B0009B01AC016BE077ED83E29BE30E94634EA2 -:1070C0000E947F52B62E872EA82E992E6E2D7F2DD0 -:1070D0008C2D9D2D2B2D382D4A2D592D0E943D4F45 -:1070E00087FD04C0EB2CF82CCA2CD92C8DE490E041 -:1070F000E9A1FAA1E89F8001E99F100DF89F100D0A -:10710000112404581A4F8E2D9F2DAC2DBD2DF80142 -:1071100086A397A3A0A7B1A762A173A184A195A1FB -:107120002B2D382D4A2D592D0E943D4F181634F025 -:1071300081E0D801D7968C93D79702C0F80117AA9F -:107140008DE490E029A13AA1289FF001299FF00D3C -:10715000389FF00D1124E458FA4F81E086ABA3E587 -:10716000BAE0FE01719680E101900D928150E1F745 -:107170008DE490E049A15AA1489F8001499F100DDC -:10718000589F100D112404581A4FD8019296CD9093 -:10719000DD90ED90FC909597C0924F0AD092500AE6 -:1071A000E092510AF092520A96966D917D918D91DE -:1071B0009C919997A70196010E94444F4B015C0155 -:1071C0006DEC7CEC8CE49DE3A70196010E94444F9A -:1071D0006B017C01C801B501A401970186010E94E1 -:1071E000CD286496BFAD6497B0934C0A2FA938ADF3 -:1071F00049AD5AAD20936C0530936D0540936E05F3 -:1072000050936F054BAD5CAD6DAD7EAD4093700599 -:1072100050937105609372057093730523966CAD5E -:107220007DAD8EAD9FAD239760937405709375050A -:1072300080937605909377058FA598A9A9A9BAA9F7 -:107240008093780590937905A0937A05B0937B0598 -:107250000E94CC2CACD1CB5ADF4F0FB6F894DEBFD6 -:107260000FBECDBFCF91DF911F910F91FF90EF9097 -:10727000DF90CF90BF90AF909F908F907F906F9056 -:107280005F904F903F902F900895CF92DF92EF92B2 -:10729000FF920F931F93CF93DF938B017A016901C4 -:1072A000FC01608171818281938120912005309160 -:1072B000210540912205509123050E9412520E94FF -:1072C000E251CCE6D5E060936C0570936D05809338 -:1072D0006E0590936F05F8016081718182819381C1 -:1072E00020912405309125054091260550912705D0 -:1072F0000E9412520E94E2518E010C5F1F4F609358 -:107300007005F801718382839383F7016081718135 -:1073100082819381209128053091290540912A0589 -:1073200050912B050E9412520E94E25128E0E22E59 -:10733000F12CEC0EFD1E60937405F70171838283BE -:107340009383F601608171818281938120912C0564 -:1073500030912D0540912E0550912F050E9412521B -:107360000E94E251FE013C9660937805718382830E -:107370009383CE01B801A7019F0160D780E090E020 -:10738000DC0180934F0A9093500AA093510AB09366 -:10739000520A8093530A9093540AA093550AB093CB -:1073A000560A8093570A9093580AA093590AB093AB -:1073B0005A0A80935B0A90935C0AA0935D0AB0938B -:1073C0005E0A80935F0A9093600AA093610AB0936B -:1073D000620ADF91CF911F910F91FF90EF90DF90A4 -:1073E000CF900895FC016081718182819381209109 -:1073F0002C0530912D0540912E0550912F050E94AE -:1074000012520E94E251609378057093790580933F -:107410007A0590937B0588E795E04CC780934E0AE8 -:1074200008958091970A882349F48091990A8823C6 -:1074300029F480919B0A882309F4AEC0ECE8FCE0B3 -:1074400007C09091C00095FFFCCF8093C600319695 -:1074500084918823B1F7EEE9FCE007C09091C00069 -:1074600095FFFCCF8093C600319684918823B1F7B5 -:107470008091970A882349F1EAE9FCE007C09091DE -:10748000C00095FFFCCF8093C6003196849188237D -:10749000B1F76091650A7091660A8091670A9091D0 -:1074A000680A0E94DF4F209120053091210540910C -:1074B0002205509123050E94444FAB01BC018BE093 -:1074C00095E022E030E00E9475248091990A88239B -:1074D00049F1E6E9FCE007C09091C00095FFFCCFC0 -:1074E0008093C600319684918823B1F76091690A30 -:1074F00070916A0A80916B0A90916C0A0E94DF4F2A -:1075000020912405309125054091260550912705AD -:107510000E94444FAB01BC018BE095E022E030E0DB -:107520000E94752480919B0A882349F1E2E9FCE0DE -:1075300007C09091C00095FFFCCF8093C6003196A4 -:1075400084918823B1F760916D0A70916E0A8091E1 -:107550006F0A9091700A0E94DF4F209128053091A8 -:10756000290540912A0550912B050E94444FAB01FB -:10757000BC018BE095E022E030E00E947524809110 -:10758000C00085FFFCCF8AE08093C6001092970A66 -:107590001092990A10929B0A08951092970A1092DD -:1075A000990A10929B0A08958093FB010895EFE6D3 -:1075B000F0E080818260808308951F920F920FB661 -:1075C0000F9211242F923F924F925F926F927F926F -:1075D0008F929F92AF92BF92CF92DF92EF92FF92E3 -:1075E0000F931F932F933F934F935F936F937F93CB -:1075F0008F939F93AF93BF93EF93FF93DF93CF93BB -:1076000000D000D0CDB7DEB78091630A9091640AB4 -:10761000009709F05DC190914C0A80914D0A98172E -:10762000A1F020914D0A30E08DE490E0289FF00118 -:10763000299FF00D389FF00D1124E458FA4FDF0117 -:10764000A45BBF4F81E08C9302C0E0E0F0E0F093D8 -:10765000640AE093630A309709F434C11092A30AD4 -:107660001092A40A1092A50A1092A60A34AD25AD74 -:107670003093A10A2093A20AC901692F782F27E22B -:107680006131720710F060E177E281E080939C0A3B -:107690006832710510F468E270E06852704038E0BA -:1076A00060307307E0F0872F90E0880F991F880FF4 -:1076B000991F84579B4FFC01329645915491AA27FC -:1076C000659F9001649F210D3A1F06942A1F3A1F5F -:1076D0001124FC0145915491421B530B1FC0CB0157 -:1076E000969587958C7F8457974FFC0145915491CF -:1076F0000296FC0125913491E62FF0E0E770F070DE -:107700002E9FC0012F9F900D3E9F900D1124E3E00E -:1077100096958795EA95E1F7481B590B4436510534 -:10772000A0F4E3EBF1E006C09091C00095FFFCCF20 -:107730008093C60081918823B9F78BE095E04AE0F9 -:1077400050E00E94B92344E650E0CA01A0E0B0E056 -:1077500080939D0A90939E0AA0939F0AB093A00ADB -:107760005093890040938800E091630AF091640A85 -:1077700090AD81AD692F782F87E26131780710F0E5 -:1077800060E177E281E080939C0A6832710510F431 -:1077900068E270E068527040E8E060307E07E0F038 -:1077A000872F90E0880F991F880F991F84579B4F50 -:1077B000FC01329645915491AA27659F9001649FE0 -:1077C000210D3A1F06942A1F3A1F1124FC014591EE -:1077D0005491421B530B1FC0CB01969587958C7F0C -:1077E0008457974FFC01459154910296FC012591D5 -:1077F0003491E62FF0E0E770F0702E9FC0012F9FCC -:10780000900D3E9F900D112403E0969587950A9563 -:10781000E1F7481B590B44365105A0F4E3EBF1E0C6 -:1078200006C09091C00095FFFCCF8093C600819167 -:107830008823B9F78BE095E04AE050E00E94B92335 -:1078400044E650E05093A80A4093A70AE091630AE7 -:10785000F091640A80899189A289B389B695A79528 -:1078600097958795B095A095909581959F4FAF4F2F -:10787000BF4F8093810A9093820AA093830AB093AA -:10788000840A8093850A9093860AA093870AB0930E -:10789000880A8093890A90938A0AA0938B0AB093EE -:1078A0008C0A80938D0A90938E0AA0938F0AB093CE -:1078B000900A1092910A1092920A1092930A1092D2 -:1078C000940A06C080ED97E0909389008093880029 -:1078D000E091630AF091640A309709F43EC480A1F4 -:1078E0008093950A80FF37C016988FEF8093F70139 -:1078F00023B1217031E0232759F18091960A882322 -:1079000039F180819181A281B381181619061A0676 -:107910001B06F4F48091710A9091720AA091730A87 -:10792000B091740A8093650A9093660AA093670ADF -:10793000B093680A3093970A80899189A289B389A4 -:107940008093910A9093920AA093930AB093940A19 -:107950002093960A04C0169A81E08093F7018091E3 -:10796000950A81FF3BC0149A8FEF8093F80121E0C4 -:10797000199B02C020E02FC08091980A882359F1FA -:10798000E091630AF091640A84819581A681B781B0 -:10799000181619061A061B06F4F48091750A9091C0 -:1079A000760AA091770AB091780A8093690A909339 -:1079B0006A0AA0936B0AB0936C0A2093990A808993 -:1079C0009189A289B3898093910A9093920AA09396 -:1079D000930AB093940A2093980A04C0149881E003 -:1079E0008093F8018091950A82FF3BC046988FEF03 -:1079F0008093F90121E01A9B02C020E02FC0809102 -:107A00009A0A882359F1E091630AF091640A80850B -:107A10009185A285B385181619061A061B06F4F47B -:107A20008091790A90917A0AA0917B0AB0917C0AA0 -:107A300080936D0A90936E0AA0936F0AB093700AB8 -:107A400020939B0A80899189A289B3898093910AA6 -:107A50009093920AA093930AB093940A20939A0A5F -:107A600004C0469A81E08093F9018091950A83FFD2 -:107A700003C045988FEF02C0459A81E08093FA01D8 -:107A800080919C0A282F30E03A8329832091810A33 -:107A90003091820A4091830A5091840A8091850A2C -:107AA0009091860AA091870AB091880AA090890ACD -:107AB000B0908A0AC0908B0AD0908C0A60908D0A90 -:107AC00070908E0A80908F0A9090900A1C821B8280 -:107AD00035C16091C00067FF19C02090C600E091D9 -:107AE0000705F0910805BF016F5F7F4F6F777070DA -:107AF000E0900905F0900A056E157F0539F0E95709 -:107B0000FB4F20827093080560930705E091630A9C -:107B1000F091640AE080F180028113812E0D3F1DF7 -:107B2000401F511F12161306140615060CF4159A61 -:107B3000E091630AF091640AE480F5800681178180 -:107B40008E0D9F1DA01FB11F181619061A061B06C1 -:107B50000CF4139AE091630AF091640AE084F184D2 -:107B600002851385AE0CBF1CC01ED11E1A141B0447 -:107B70001C041D040CF4479AE091630AF091640A16 -:107B8000E484F584068517856E0C7F1C801E911E8B -:107B900016141704180419040CF4179A1216130675 -:107BA000140615061CF5E091630AF091640AE0885A -:107BB000F188028913892E193F09400B510BE0907F -:107BC000710AF090720A0091730A1091740A609120 -:107BD000F701E60EF11C011D111DE092710AF092F1 -:107BE000720A0093730A1093740A159818161906EE -:107BF0001A061B061CF5E091630AF091640AE088FE -:107C0000F188028913898E199F09A00BB10BE090AE -:107C1000750AF090760A0091770A1091780A6091BF -:107C2000F801E60EF11C011D111DE092750AF0929B -:107C3000760A0093770A1093780A13981A141B0493 -:107C40001C041D041CF5E091630AF091640AE088AD -:107C5000F18802891389AE18BF08C00AD10AE090E2 -:107C6000790AF0907A0A00917B0A10917C0A60915F -:107C7000F901E60EF11C011D111DE092790AF09246 -:107C80007A0A00937B0A10937C0A4798161417040B -:107C9000180419041CF5E091630AF091640AE08865 -:107CA000F188028913896E187F08800A910AE09092 -:107CB0007D0AF0907E0A00917F0A1091800A6091FF -:107CC000FA01E60EF11C011D111DE0927D0AF092F1 -:107CD0007E0A00937F0A1093800A1798E090910A19 -:107CE000F090920A0091930A1091940A0894E11C72 -:107CF000F11C011D111DE092910AF092920A00936D -:107D0000930A1093940A2090910A3090920A40901E -:107D1000930A5090940A6B817C816F5F7F4F7C83C4 -:107D20006B83E091630AF091640AE088F18802892C -:107D300013892E143F044006510640F4EB81FC8168 -:107D400069817A81E617F7070CF4C3CE2093810A84 -:107D50003093820A4093830A5093840A8093850A61 -:107D60009093860AA093870AB093880AA092890A02 -:107D7000B0928A0AC0928B0AD0928C0A60928D0AC5 -:107D800070928E0A80928F0A9092900A2091910AA6 -:107D90003091920A4091930A5091940AE091630ABB -:107DA000F091640A84899589A689B7898217930717 -:107DB000A407B50708F4C8C020919D0A30919E0A17 -:107DC00040919F0A5091A00A648D758D868D978D84 -:107DD000AA27279FB12D389F7001489FF00C479F1D -:107DE000E00CF11C289FB00DE11CFA1E379FB00D6E -:107DF000E11CFA1E469FB00DE11CFA1E369FB10D24 -:107E0000EA1EFA1EB695EA1EFA1E112424AD35ADFF -:107E10002E0D3F1D3093A20A2093A10A80AD91AD93 -:107E2000A2ADB3AD40E050E082179307A407B507B9 -:107E300020F49093A20A8093A10A9091A10A8091C4 -:107E4000A20A692F782F87E26131780710F060E18C -:107E500077E281E080939C0A6832710510F468E251 -:107E600070E068527040E8E060307E07E0F0872FF5 -:107E700090E0880F991F880F991F84579B4FFC0132 -:107E8000329625913491AA27639FA001629F410DEC -:107E90005A1F06944A1F5A1F1124FC012591349140 -:107EA000241B350B1FC0CB01969587958C7F84577B -:107EB000974FFC01259134910296FC014591549114 -:107EC000E62FF0E0E770F0704E9FC0014F9F900DDD -:107ED0005E9F900D1124F3E096958795FA95E1F752 -:107EE000281B390B24363105A0F4E3EBF1E006C082 -:107EF0009091C00095FFFCCF8093C60081918823AC -:107F0000B9F78BE095E04AE050E00E94B92324E6FF -:107F100030E0309389002093880040E050E0809169 -:107F20009D0A90919E0AA0919F0AB091A00A820F8B -:107F3000931FA41FB51F80939D0A90939E0AA09340 -:107F40009F0AB093A00AE4C02091910A3091920A4E -:107F50004091930A5091940A808D918DA28DB38D9A -:107F600082179307A407B50708F0CAC02091A30A97 -:107F70003091A40A4091A50A5091A60A648D758D8E -:107F8000868D978DAA27279FB12D389F7001489F16 -:107F9000F00C479FE00CF11C289FB00DE11CFA1E6D -:107FA000379FB00DE11CFA1E469FB00DE11CFA1E72 -:107FB000369FB10DEA1EFA1EB695EA1EFA1E11246E -:107FC0006091A10A7091A20A6E157F0538F4DF0155 -:107FD000A05CBF4F6D917C91119702C06E197F0913 -:107FE000E05CFF4F80819181A281B3819B0140E0E1 -:107FF00050E0281739074A075B0708F4BC01F7E28D -:1080000061317F0710F060E177E281E080939C0AA4 -:108010006832710510F468E270E06852704028E040 -:1080200060307207E0F0872F90E0880F991F880F6B -:10803000991F84579B4FFC01329625913491AA27B2 -:10804000639FA001629F410D5A1F06944A1F5A1F49 -:108050001124FC0125913491241B350B1FC0CB0149 -:10806000969587958C7F8457974FFC012591349185 -:108070000296FC0145915491E62FF0E0E770F07014 -:108080004E9FC0014F9F900D5E9F900D112443E0C5 -:10809000969587954A95E1F7281B390B24363105CB -:1080A000A0F4E3EBF1E006C09091C00095FFFCCF97 -:1080B0008093C60081918823B9F78BE095E04AE070 -:1080C00050E00E94B92324E630E0309389002093E9 -:1080D000880040E050E08091A30A9091A40AA0910A -:1080E000A50AB091A60A820F931FA41FB51F809303 -:1080F000A30A9093A40AA093A50AB093A60A08C065 -:108100008091A70A9091A80A909389008093880093 -:108110002091910A3091920A4091930A5091940AC9 -:10812000E091630AF091640A80899189A289B389F8 -:10813000281739074A075B0780F01092640A1092EB -:10814000630A90914C0A80914D0A981731F0809102 -:108150004D0A8F5F8F7080934D0A2496DEBFCDBF8E -:10816000CF91DF91FF91EF91BF91AF919F918F914F -:108170007F916F915F914F913F912F911F910F913F -:10818000FF90EF90DF90CF90BF90AF909F908F9037 -:108190007F906F905F904F903F902F900F900FBE09 -:1081A0000F901F9018950E9A0C9A3E9A3D9A529AEB -:1081B000529A529A529A2098289A2198299A22984B -:1081C0002A9A0D9A0B9A3F9A0F9AA1E8B0E08C91E7 -:1081D0008F7E8C938C9188608C93E0E8F0E08081B6 -:1081E0008D7F808380818E7F808380818F73808369 -:1081F00080818F7C80838C91887F82608C9380E0EB -:1082000090E49093890080938800109285001092EA -:108210008400EFE6F0E080818260808381E0C4D951 -:108220007894089590914C0A80914D0A981729F0FE -:1082300092D281E00E946C10F5CF0895CF93DF9326 -:10824000EFB7F894EC0188819981AA81BB81809372 -:10825000710A9093720AA093730AB093740AEB01A7 -:1082600088819981AA81BB818093750A9093760A4F -:10827000A093770AB093780AEA0188819981AA814C -:10828000BB818093790A90937A0AA0937B0AB0937A -:108290007C0AE90188819981AA81BB8180937D0A4A -:1082A00090937E0AA0937F0AB093800AEFBFDF917C -:1082B000CF9108952FB7F894FC0180819181A2811C -:1082C000B38180937D0A90937E0AA0937F0AB09336 -:1082D000800A2FBF08959FB7F894E82FF0E0EE0FC3 -:1082E000FF1FEE0FFF1FEF58F54F208131814281B4 -:1082F00053819FBFB901CA01089594DF5A985A98D3 -:108300005A985A98089560E070E08FE793E42091BE -:1083100000023091010240910202509103020E943A -:10832000444F6093D00A7093D10A8093D20A9093FD -:10833000D30A0895FC01EB54F54F808190E0089535 -:108340000F931F93CF93DF93EC01062F662359F110 -:10835000EDEAFCE007C09091C00095FFFCCF809350 -:10836000C600319684918823B1F78BE095E0602FA9 -:1083700070E04AE050E00E949C23E9E5FEE007C07F -:108380009091C00095FFFCCF8093C60031968491F8 -:108390008823B1F78091C00085FFFCCF8AE08093ED -:1083A000C6000E944310602F70E0660F771FFB012C -:1083B000EF57FD4F80819181009709F45BC06D57A5 -:1083C0007D4FFB01A081B18101E037C0A901440FBD -:1083D000551F440F551FFA013296E80FF91F65919A -:1083E00074916C177D0744F5D9011197AA0FBB1F33 -:1083F000AA0FBB1FFC01EA0FFB1F259134911296B7 -:10840000A80FB91FFD0105911491840F951FFC0160 -:10841000A591B491A21BB30BC01BD10BAC9FC001A3 -:10842000AD9F900DBC9F900D1124601B710B0E949D -:10843000F752620F731F19C00F5F202F30E02A1709 -:108440003B070CF4C3CF2A173B0769F41197AA0F17 -:10845000BB1FAA0FBB1FA80FB91FFD0185919491E7 -:10846000682F792F02C060E070E020EF3FE3261B09 -:10847000370B16C0BE01882777FD8095982F0E9484 -:10848000DF4F2FE632E143E050E40E94125220E039 -:1084900030E040E851E40E9412520E94AC4F9B0130 -:1084A000C901DF91CF911F910F91089520E030E035 -:1084B000D9011196AD01440F551F440F551FFA0104 -:1084C000E65BF24F65917491681779073CF5D90125 -:1084D000AA0FBB1FAA0FBB1FFD01E85BF24F25913E -:1084E0003491A65BB24FFD01A591B491485B524F08 -:1084F000FA0145915491421B530BFC01EA1BFB0B03 -:108500004E9FC0014F9F900D5E9F900D11246A1BDE -:108510007B0B0E94F752620F731F12C0422F4E5FF7 -:108520009D01AC33B10509F0C3CF4D3339F4E8E315 -:10853000FEE085919491682F792F02C060E070E091 -:1085400020EF3FE3261B370BC90108952F923F927E -:108550004F925F926F927F928F929F92AF92BF9253 -:10856000CF92DF92EF92FF920F931F93CF93DF93FF -:108570008C01C62F662359F1EDEAFCE007C090910B -:10858000C00095FFFCCF8093C6003196849188236C -:10859000B1F78BE095E06C2F70E04AE050E00E946C -:1085A0009C23ECE3FEE007C09091C00095FFFCCF58 -:1085B0008093C600319684918823B1F78091C000E2 -:1085C00085FFFCCF8AE08093C6000E9443106C2F89 -:1085D00070E0660F771FFB01EF57FD4F808191819F -:1085E000009709F488C0C0EFDFE3C01BD10B6D57C3 -:1085F0007D4FFB0160817181A1E060C09A01220F73 -:10860000331F220F331FFC01E20FF31FA590B4901C -:10861000CA15DB050CF051C041505040440F551FA6 -:10862000440F551FFA013296E80FF91F0591149176 -:10863000480F591FFA01859094902E5F3F4F280FE5 -:10864000391FF90165907490B801882777FD8095EE -:10865000982F0E94DF4F1B012C01C819D909BE01B8 -:10866000882777FD8095982F0E94DF4F6B017C0152 -:10867000601A710AB301882777FD8095982F0E94B0 -:10868000DF4F9B01AC01C701B6010E9412527B0172 -:108690008C01A818B908B501882777FD8095982F17 -:1086A0000E94DF4F9B01AC01C801B7010E94444FFB -:1086B0009B01AC01C201B10134C0AF5F4A2F50E051 -:1086C000461757070CF49ACF4617570769F5660FF8 -:1086D000771F660F771F62507040680F791FFB018C -:1086E000859194919C01B901882777FD8095982FF9 -:1086F0000E94DF4F1DC0B801882777FD8095982F15 -:108700000E94DF4F20E030E04AEF5EE30E94125209 -:1087100020E030E040E85DE30E94125220E030E0CB -:10872000A9010E94644E04C060E070E080E090E027 -:10873000DF91CF911F910F91FF90EF90DF90CF903D -:10874000BF90AF909F908F907F906F905F904F9071 -:108750003F902F9008954F925F926F927F928F92E9 -:108760009F92AF92BF92CF92DF92EF92FF920F93C0 -:108770001F93CF93DF938091B60A882309F4C7C172 -:108780008FB7F8941092B60A8FBF8091AD0A90917E -:10879000AE0A60E0DBDE4B015C016091B10A7091D2 -:1087A000B20A8091B30A9091B40AA50194010E9483 -:1087B000634EEB01182F092F9801862F9D2FA32FB1 -:1087C000B22F8093D40A9093D50AA093D60AB0937F -:1087D000D70A6C2F7D2F832F922F20E030E040E2CC -:1087E00051E40E94405118160CF42DC198016C2FD1 -:1087F0007D2F832F922F20E030E040E251EC0E9449 -:108800003D4F87FD1CC18091D80A882309F009C11A -:1088100098016C2F7D2F832F902F2091FC01309198 -:10882000FD014091FE015091FF010E9412522B0167 -:108830003C01862F952DA62DB72D8093DD0A9093B0 -:10884000DE0AA093DF0AB093E00A98016C2F7D2F17 -:10885000832F902F2091D90A3091DA0A4091DB0AB8 -:108860005091DC0A0E94644EF62EE72ED82EC92EB7 -:108870000091CC0A1091CD0AD091CE0AC091CF0AB6 -:10888000A7019601652F742F832F922FFE01202FB1 -:10889000312F4F2F5E2F0E943D4F87FFA6C09E01B4 -:1088A000802F912FA32FBC2F8093D90A9093DA0A9F -:1088B000A093DB0AB093DC0A602F712F832F9C2FCB -:1088C0002091000230910102409102025091030276 -:1088D0000E941252D62FC72F182F092FAE019801D0 -:1088E000852F942FA32FB22F8093E10A9093E20A51 -:1088F000A093E30AB093E40AC501B4012091E50A0C -:108900003091E60A4091E70A5091E80A0E94634ECE -:108910002091040230910502409106025091070215 -:108920000E94125220ED3CEC4CE45DE30E94125296 -:108930006B017C016091E90A7091EA0A8091EB0A6F -:108940009091EC0A23E333E343E75FE30E94125282 -:108950009B01AC01C701B6010E94644E7B01D82E79 -:10896000C92E9601862F9F2DA32FB22F8093E90A3F -:108970009093EA0AA093EB0AB093EC0A8092E50A7E -:108980009092E60AA092E70AB092E80A642D752D4B -:10899000862D972DDE01F8012B2F3A2F4F2F5E2FBA -:1089A0000E94644EF6012E2D3F2D4F2F5E2F0E9408 -:1089B000634E8B01D82FC92F9E01712F832F922FC9 -:1089C00020E030E0A9010E943D4F87FD44C09E0198 -:1089D000602F712F832F922F20E030E04FE753E478 -:1089E0000E9440511816DCF531C00091D00A109158 -:1089F000D10AD091D20AC091D30AA7019601652F5E -:108A0000742F832F922FFE01202F312F4F2F5E2F97 -:108A10000E94405118160CF442CF0F2D1E2DE60176 -:108A20003ECF80E090E0DC018093D90A9093DA0A8F -:108A3000A093DB0AB093DC0A1092D80AE9CE81E059 -:108A40008093D80A08C081E08093D80A00E010E043 -:108A5000DFE7C3E404C000E010E0D0E0C0E08091B4 -:108A6000AD0A9091AE0A2091B70A3091B80A281742 -:108A700039071CF01092B50A12C020910C023091F7 -:108A80000D0282179307B4F79E01602F712F832F79 -:108A90009C2F0E94AC4F759567956093B50A0E9414 -:108AA000E2202091ED0A3091EE0A4091EF0A5091B8 -:108AB000F00A621B730B840B950B683823E1720775 -:108AC00020E0820720E0920710F10E94E2206093EC -:108AD000ED0A7093EE0A8093EF0A9093F00A80916A -:108AE000AF0A9091B00A1816190684F420910E026C -:108AF00030910F02821793074CF42091AB0A30910A -:108B0000AC0A8217930714F42C9A01C02C98DF91B9 -:108B1000CF911F910F91FF90EF90DF90CF90BF907A -:108B2000AF909F908F907F906F905F904F9008953F -:108B30002F923F924F925F926F927F928F929F926D -:108B4000AF92BF92CF92DF92EF92FF920F931F935B -:108B5000DF93CF93CDB7DEB7E9970FB6F894DEBFBA -:108B60000FBECDBF6D877E878F87988B8FE78093F1 -:108B7000B50A0E94E2206B8B7C8B8D8B9E8BE7EC81 -:108B8000F1E006C09091C00095FFFCCF8093C60035 -:108B900081918823B9F78091C00085FFFCCF8AE0DE -:108BA0008093C6002B893C894D895E892B8F3C8F31 -:108BB0004D8F5E8F2F8B388F498F5A8F8FE790E0C4 -:108BC000A0E0B0E089839A83AB83BC833FE7432E68 -:108BD000512C612C712C11E01A8A198AECE2FFE009 -:108BE00094919CA7E7E2FFE0A491ADA7E0E2FFE04B -:108BF000B491BEA7E9E1FFE024912FA7E3E1FFE0F4 -:108C0000349138ABEDE0FFE0449149ABE0E0FFE0A8 -:108C100054915AABEAEFFEE084918BABE4EFFEE0B7 -:108C200094919CABEEEEFEE0A491ADABEDEDFEE0D9 -:108C3000B491BEABE7EDFEE024912FAB8091B60A74 -:108C4000882309F461C48FB7F8941092B60A8FBFD5 -:108C50008091AD0A9091AE0A60E078DC6D837E83EE -:108C60008F8398875F8D48A139A12AA1652F742F22 -:108C7000832F922FBD81AE81DF80C8842B2F3A2FA6 -:108C80004D2D5C2D0E944051181634F03D813F8FD0 -:108C90004E8148A3D9A2CAA26F2D702F8E2D992D77 -:108CA000BD81AE81DF80C8842B2F3A2F4D2D5C2DE6 -:108CB0000E943D4F87FD04C0FD800E81ED2C9C2C51 -:108CC000112309F454C05D814E813F812885652FB1 -:108CD000742F832F922FBD85AE85DF84C8882B2FFC -:108CE0003A2F4D2D5C2D0E94405118160CF00CC4EB -:108CF0000E94E2202B8D3C8D4D8D5E8D621B730B8F -:108D0000840B950B693833E1730730E0830730E05B -:108D1000930708F4F9C3D301C20129813A814B8139 -:108D20005C81821B930BA40BB50BB595A79597950A -:108D300087958093B50A0E94E2206F8B788F898F88 -:108D40009A8FDC01CB012B8D3C8D4D8D5E8D821B6E -:108D5000930BA40BB50B88A799A7AAA7BBA73D8522 -:108D60003F8F4E8548A35F8559A388898AA35D817B -:108D70004E813F812885652F742F832F922FBD85CB -:108D8000AE851F85D8882B2F3A2F412F5D2D0E944D -:108D90003D4F87FFB8C30E94E2202F89388D498D4F -:108DA0005A8D621B730B840B950B693833E1730783 -:108DB00030E0830730E0930708F4A5C30E94E22067 -:108DC0006B8F7C8F8D8F9E8F49895A8941155105F4 -:108DD00009F47FC3DC01CB012F89388D498D5A8D71 -:108DE000821B930BA40BB50B28A539A54AA55BA53F -:108DF000280F391F4A1F5B1F29873A874B875C87DB -:108E000028A539A54AA55BA5281B390B4A0B5B0B86 -:108E1000CA01B90129813A814B815C810E94D852F3 -:108E200029853A854B855C850E942C53240D351D80 -:108E3000461D571D243131054105510504F1290115 -:108E40003A013CEE43165104610471042CF09BEE90 -:108E5000492E512C612C712C40E8441651046104B8 -:108E60007104DCF08EEF90E0A0E0B0E08419950989 -:108E7000A609B70989839A83AB83BC8312C084E1B6 -:108E8000482E512C612C712C24E130E040E050E060 -:108E900029833A834B835C8304C049825A826B8264 -:108EA0007C828CA5ECE2FFE008C09091C00095FFA9 -:108EB000FCCF8093C600319684918823B1F78BE074 -:108EC00095E0B301A2012AE030E00E946C238DA559 -:108ED000E7E2FFE008C09091C00095FFFCCF8093CF -:108EE000C600319684918823B1F78BE095E04981E3 -:108EF0005A816B817C812AE030E00E946C238EA530 -:108F0000E0E2FFE008C09091C00095FFFCCF8093A5 -:108F1000C600319684918823B1F78BE095E04F2D00 -:108F2000502F6E2D792D22E030E00E9475248FA500 -:108F3000E9E1FFE008C09091C00095FFFCCF80936D -:108F4000C600319684918823B1F78BE095E0FF8DC0 -:108F5000E8A139A12AA14F2F5E2F632F722F22E0A3 -:108F600030E00E9475248091C00085FFFCCF8AE02C -:108F70008093C60049895A89433051050CF4A9C22F -:108F800069817A818B819C810E94DF4F20E030E0F3 -:108F900040E850E40E9412525B016C015F8D48A1D1 -:108FA00039A12AA1652F742F832F922F2F2D302FB7 -:108FB0004E2D592D88D620ED3FE049E450E40E9423 -:108FC000125220E030E040E05FE30E9412529B0129 -:108FD000AC01C601B50158D76BA37CA38DA39EA39A -:108FE00069857A858B859C85EAD720E030E04AE761 -:108FF00054E44AD7F62ED72EC82EB92E88A9E3E11D -:10900000FFE008C09091C00095FFFCCF8093C600A0 -:10901000319684918823B1F78BE095E0FBA1ECA118 -:109020003DA12EA14F2F5E2F632F722F22E030E043 -:109030000E94752489A9EDE0FFE008C09091C0006E -:1090400095FFFCCF8093C600319684918823B1F7B9 -:109050008BE095E04F2D5D2D6C2D7B2D22E030E0D7 -:109060000E9475248091C00085FFFCCF8AE0809328 -:10907000C6005BA14CA13DA12EA1652F742F832FAB -:10908000922F2AE939E949E15FE30E94125269AF60 -:1090900078AF182F092F562F472F9801832F922F23 -:1090A000DA01F8012B2F3A2F4F2F5E2F0DD62F2DDF -:1090B0003D2D4C2D5B2DE8D6362E272E89879FA37C -:1090C00059AD48AD9801652F742F832F922F2F2D06 -:1090D0003D2D4C2D5B2D0E94125220E030E040E0EF -:1090E0005EE30E941252E62EA72E982E892E8AA9A0 -:1090F000E0E0FFE039AD98AD0AC0292F9091C000A3 -:1091000095FFFCCF922F8093C600319684918823DF -:10911000A1F78091C00085FFFCCF39AF98AF8AE0FE -:109120008093C6008BA9EAEFFEE039AD98AD0AC086 -:10913000292F9091C00095FFFCCF922F8093C600FD -:10914000319684918823A1F739AF98AF8BE095E0F1 -:10915000F32FE8AD98014F2F5E2F632F702F22E081 -:1091600030E00E9475248091C00085FFFCCF8AE02A -:109170008093C6008CA9E4EFFEE008C09091C00087 -:1091800095FFFCCF8093C600319684918823B1F778 -:109190008BE095E0F10139852FA14F2F522D632FE0 -:1091A000722F22E030E00E9475248091C00085FF7C -:1091B000FCCF8AE08093C6008DA9EEEEFEE008C0E9 -:1091C0009091C00095FFFCCF8093C60031968491AA -:1091D0008823B1F78BE095E094014E2D5A2D632F33 -:1091E000782D22E030E00E9475248091C00085FF38 -:1091F000FCCF8AE08093C6005BA14CA13DA12EA1CB -:10920000652F742F832F922F23EC35EF48EA5EE30E -:109210000E94125269AF78AF182F092F9801832F3F -:10922000922F2F2D3D2D4C2D5B2D2ED6362E272EF9 -:1092300089879FA359AD48AD9801652F742F832F5F -:10924000922F2F2D3D2D4C2D5B2D0E94125220E090 -:1092500030E040E450E418D6E62EA72E982E892E52 -:109260008EA9EDEDFEE039AD98AD0AC0292F9091A1 -:10927000C00095FFFCCF922F8093C6003196849159 -:109280008823A1F78091C00085FFFCCF39AF98AF4C -:109290008AE08093C6008FA9E7EDFEE039AD98AD76 -:1092A0000AC0292F9091C00095FFFCCF922F809388 -:1092B000C600319684918823A1F739AF98AF8BE02F -:1092C00095E0F32FE8AD98014F2F5E2F632F702F9D -:1092D00022E030E00E9475248091C00085FFFCCF21 -:1092E0008AE08093C600E1EDFEE007C09091C000E7 -:1092F00095FFFCCF8093C600319684918823B1F707 -:109300008BE095E0F10139852FA14F2F522D632F6E -:10931000722F22E030E00E9475248091C00085FF0A -:10932000FCCF8AE08093C600EBECFEE007C0909192 -:10933000C00095FFFCCF8093C600319684918823AE -:10934000B1F78BE095E094014E2D5A2D632F782DC7 -:1093500022E030E00E9475248091C00085FFFCCFA0 -:109360008AE08093C6005BA14CA13DA12EA1652F90 -:10937000742F832F922F2DEC3CEC4CE45EE30E9483 -:1093800012526987272E182F092F562F9801832FE5 -:10939000922FF801252F322D4F2F5E2F95D42F2D90 -:1093A0003D2D4C2D5B2D70D5A62E972E882E392E57 -:1093B00059859801652F722D832F922F2F2D3D2DCA -:1093C0004C2D5B2D0E94125220E030E040E450E42E -:1093D0005BD5F62EE72ED82EC92EECEBFEE084915D -:1093E00099850AC0292F9091C00095FFFCCF922F3C -:1093F0008093C600319684918823A1F78091C000A4 -:1094000085FFFCCF99878AE08093C600E6EBFEE0FB -:10941000849199850AC0292F9091C00095FFFCCFB7 -:10942000922F8093C600319684918823A1F7998763 -:109430008BE095E0F98598014F2F522D632F702F07 -:1094400022E030E00E9475248091C00085FFFCCFAF -:109450008AE08093C600E0EBFEE007C09091C00078 -:1094600095FFFCCF8093C600319684918823B1F795 -:109470008BE095E04A2D592D682D732D22E030E0C8 -:109480000E9475248091C00085FFFCCF8AE0809304 -:10949000C600EAEAFEE007C09091C00095FFFCCF4D -:1094A0008093C600319684918823B1F78BE095E0D4 -:1094B000F70196014F2F5E2D632F7C2D22E030E0C7 -:1094C0000E9475248091C00085FFFCCF8AE08093C4 -:1094D000C60089819A81AB81BC81840D951DA61D32 -:1094E000B71DB595A795979587958093B50A298956 -:1094F0003A892F5F3F4F3A8B298BFD840E85EF848D -:10950000988811E001C010E05D854E853F8528896F -:10951000652F742F832F922F20E030E040EA51E432 -:10952000D3D39B01AC01BD81AE81DF80C8846B2F9A -:109530007A2F8D2D9C2DA4D618166CF5EFE7FEE042 -:1095400007C09091C00095FFFCCF8093C600319674 -:1095500084918823B1F78091C00085FFFCCF8AE019 -:109560008093C600E9960FB6F894DEBF0FBECDBF5C -:10957000CF91DF911F910F91FF90EF90DF90CF90EF -:10958000BF90AF909F908F907F906F905F904F9023 -:109590003F902F9008950E94E2202B893C894D89AD -:1095A0005E89621B730B840B950B613D37E073077B -:1095B00030E0830730E0930708F440CB0E94E220BC -:1095C0006B8B7C8B8D8B9E8BE9E7FEE007C09091C7 -:1095D000C00095FFFCCF8093C6003196849188230C -:1095E000B1F78091AD0A9091AE0A60E00E94A64268 -:1095F000AB01BC018BE095E022E030E00E947524D5 -:10960000E5E7FEE007C09091C00095FFFCCF809396 -:10961000C600319684918823B1F780E090E00E94E3 -:109620009A41BC018BE095E04AE050E00E949C2307 -:109630008091C00085FFFCCF8AE08093C600FECAFF -:109640002F923F924F925F926F927F928F929F9252 -:10965000AF92BF92CF92DF92EF92FF920F931F9340 -:10966000CF93DF93C0EFDFE3C81BD90B80E090E01E -:10967000AC014F5F5F4F9A01220F331F220F331F40 -:10968000F901E85BF24FA590B490CA15DB050CF028 -:1096900047C0880F991F880F991FFC01E65BF24FA6 -:1096A00005911491885B924FFC0185909490265B04 -:1096B000324FF90165907490B801882777FD809545 -:1096C000982F7DD41B012C01C819D909BE01882708 -:1096D00077FD8095982F73D46B017C01601A710A15 -:1096E000B301882777FD8095982F69D49B01AC0141 -:1096F000C701B60197D67B018C01A818B908B5013E -:10970000882777FD8095982F5AD49B01AC01C8011A -:10971000B701BAD39B01AC01C201B101D5D217C0C8 -:10972000282F2E5FCA014C33510509F0A1CF2D33EC -:1097300051F4EAE3FEE065917491882777FD809506 -:10974000982F3DD404C060E070E080E090E0DF91AD -:10975000CF911F910F91FF90EF90DF90CF90BF902E -:10976000AF909F908F907F906F905F904F903F90C1 -:109770002F90089580E090E0DC018093CC0A9093D4 -:10978000CD0AA093CE0AB093CF0A60E070E08FE7D5 -:1097900093E4209100023091010240910202509125 -:1097A000030272D36093D00A7093D10A8093D20AD5 -:1097B0009093D30A239A249A569A87ED80937A003D -:1097C000EEE7F0E01082808181608083808182609A -:1097D000808380818460808380818460808380E84E -:1097E00088BDEEE6F0E08081846080836AEF70E0FF -:1097F00080E090E00E94182185E090E060E00E9407 -:10980000A0419093B80A8093B70A83E191E060E0A9 -:109810000E94A04190930D0280930C0286E990E093 -:109820000E94564290930F0280930E02089508956D -:1098300080E090E060E00E94A04180E090E0DC01E8 -:109840008093B10A9093B20AA093B30AB093B40A7A -:1098500080E090E00E9456429093AC0A8093AB0A5D -:109860001092AA0A1092A90A1092B50A83E060E049 -:109870000E9424221092AC0A1092AB0A1092B60AEF -:109880001092AE0A1092AD0A1092B70A1092AC0A6A -:109890001092AB0A84E060E00C942422CF93C82F8E -:1098A000E82FF0E0EE0FFF1FE158FD4F808160E0F0 -:1098B0000E9424220E949520882379F5EDEAFCE09D -:1098C00007C09091C00095FFFCCF8093C6003196F1 -:1098D00084918823B1F78BE095E06C2F40E050E055 -:1098E0000E9466238091C00085FFFCCF8AE08093B0 -:1098F000C600EBE1FDE007C09091C00095FFFCCFF2 -:109900008093C600319684918823B1F78091C0007E -:1099100085FFFCCF8AE08093C600CF910895CF9356 -:10992000C82FE82FF0E0EE0FFF1FE158FD4F8081B8 -:1099300060E00E9424220E949520882379F5EDEAB8 -:10994000FCE007C09091C00095FFFCCF8093C6005B -:10995000319684918823B1F78BE095E06C2F40E03D -:1099600050E00E9466238091C00085FFFCCF8AE012 -:109970008093C600EEEEFCE007C09091C00095FF1A -:10998000FCCF8093C600319684918823B1F78091F3 -:10999000C00085FFFCCF8AE08093C600CF91089578 -:1099A00084E060E00E9424220E949520882309F52B -:1099B000EDEAFCE007C09091C00095FFFCCF8093DA -:1099C000C600319684918823B1F7E4EBFCE007C030 -:1099D0009091C00095FFFCCF8093C6003196849192 -:1099E0008823B1F78091C00085FFFCCF8AE0809387 -:1099F000C60008951F920F920FB60F9211242F9355 -:109A00003F934F935F936F937F938F939F93AF9306 -:109A1000BF93EF93FF9380911002882331F49091CC -:109A2000B50A9093B90A91112B9A9091B90A8917A6 -:109A300008F02B988F5F8F77809310028091BA0A7D -:109A4000833009F448C0843028F48130E1F082305A -:109A5000C0F50DC0853009F466C0853008F457C0E4 -:109A6000863009F47CC0873009F0A6C084C010920B -:109A70007B0080E480937C0080917A0080648093F6 -:109A80007A0081E01BC0209178003091790040E09D -:109A900050E08091C70A9091C80AA091C90AB0917C -:109AA000CA0A820F931FA41FB51F8093C70A909301 -:109AB000C80AA093C90AB093CA0A82E08093BA0A7E -:109AC0007BC082E480937C0080917A0080648093E4 -:109AD0007A0083E0F3CF209178003091790040E064 -:109AE00050E08091BB0A9091BC0AA091BD0AB09150 -:109AF000BE0A820F931FA41FB51F8093BB0A9093C9 -:109B0000BC0AA093BD0AB093BE0A84E0D7CF1092DE -:109B10007B0081E480937C0080917A008064809354 -:109B20007A0085E0CBCF209178003091790040E039 -:109B300050E08091C30A9091C40AA091C50AB091E7 -:109B4000C60A820F931FA41FB51F8093C30A909368 -:109B5000C40AA093C50AB093C60A86E0AFCF10929C -:109B60007B0082E480937C0080917A008064809303 -:109B70007A0087E0A3CF209178003091790040E00F -:109B800050E08091BF0A9091C00AA091C10AB091A3 -:109B9000C20A820F931FA41FB51F8093BF0A909320 -:109BA000C00AA093C10AB093C20A1092BA0A809167 -:109BB000CB0A8F5F8093CB0A8091CB0A803108F467 -:109BC00071C02FEF3FE38091C70A9091C80AA901A5 -:109BD000481B590BCA015093AE0A4093AD0A4091FD -:109BE000BB0A5091BC0A241B350B3093B00A20935A -:109BF000AF0A21E02093B60A1092CB0A1092C70A4E -:109C00001092C80A1092C90A1092CA0A1092C30A86 -:109C10001092C40A1092C50A1092C60A1092BF0A86 -:109C20001092C00A1092C10A1092C20A1092BB0A86 -:109C30001092BC0A1092BD0A1092BE0A20910C022A -:109C400030910D028217930744F01092AA0A1092E5 -:109C5000A90A80E023DE0E945A202091AD0A3091AB -:109C6000AE0A8091B70A9091B80A8217930744F020 -:109C70001092AA0A1092A90A80E051DE0E945A208E -:109C80002091AF0A3091B00A80910E0290910F029C -:109C9000281739073CF01092AC0A1092AB0A80DE0C -:109CA0000E945A20FF91EF91BF91AF919F918F91A8 -:109CB0007F916F915F914F913F912F910F900FBEC8 -:109CC0000F901F9018955058BB27AA270ED076C228 -:109CD0003FD230F044D220F031F49F3F11F41EF413 -:109CE0000FC20EF4E095E7FBDCC1E92F89D280F3C7 -:109CF000BA17620773078407950718F071F49EF589 -:109D0000B8C20EF4E0950B2EBA2FA02D0B01B901AD -:109D100090010C01CA01A0011124FF27591B99F0E1 -:109D2000593F50F4503E68F11A16F040A22F232FED -:109D3000342F4427585FF3CF469537952795A7953D -:109D4000F0405395C9F77EF41F16BA0B620B730BE4 -:109D5000840BBAF09150A1F0FF0FBB1F661F771F55 -:109D6000881FC2F70EC0BA0F621F731F841F48F40A -:109D7000879577956795B795F7959E3F08F0B3CF90 -:109D80009395880F08F09927EE0F9795879508957A -:109D9000DFD158F080E891E009F49EEFE0D128F09F -:109DA00040E851E059F45EEF09C0AAC162C2E92F50 -:109DB000E07826D268F3092E052AC1F32617370763 -:109DC0004807590738F00E2E07F8E02569F0E0251E -:109DD000E0640AC0EF6307F8009407FADB01B901F9 -:109DE0009D01DC01CA01AD01EF935DD0E7D10AD03E -:109DF0005F91552331F02BED3FE049E450FD49ECF4 -:109E000063CF0895DF93DD27B92FBF7740E85FE385 -:109E10001616170648075B0710F4D92F96D29F93A2 -:109E20008F937F936F93A9D3E0E7F0E06CD1C6D115 -:109E30002F913F914F915F9101D3DD2349F09058CD -:109E4000A2EA2AED3FE049EC5FE3D0785D274DDFE1 -:109E5000DF91B4C1F7D180F09F3740F491110EF437 -:109E600009C260E070E080E89FE3089526F01B16C9 -:109E7000611D711D811D1BC135C1EFD008F481E04A -:109E8000089575D1E395ABC10CD098C168D140F06D -:109E90005FD130F021F45F3F19F003C15111EAC1E5 -:109EA0002FC1AED198F39923C9F35523B1F3951B74 -:109EB000550BBB27AA2762177307840738F09F5FEB -:109EC0005F4F220F331F441FAA1FA9F333D00E2E5A -:109ED0003AF0E0E830D091505040E695001CCAF7C7 -:109EE00029D0FE2F27D0660F771F881FBB1F26178C -:109EF00037074807AB07B0E809F0BB0B802DBF015F -:109F0000FF2793585F4F2AF09E3F510568F0C9C064 -:109F1000B1C15F3FECF3983EDCF38695779567958A -:109F2000B795F7959F5FC9F7880F911D969587950F -:109F300097F90895E1E0660F771F881FBB1F62172E -:109F400073078407BA0720F0621B730B840BBA0BEC -:109F5000EE1F88F7E095089504D06894B1118AC186 -:109F6000089556D188F09F5790F0B92F9927B7518F -:109F7000A0F0D1F0660F771F881F991F1AF0BA95CD -:109F8000C9F712C0B13081F074D1B1E0089571C148 -:109F9000672F782F8827B85F39F0B93FCCF38695C3 -:109FA00077956795B395D9F73EF490958095709520 -:109FB00061957F4F8F4F9F4F0895E89409C097FB9D -:109FC0003EF490958095709561957F4F8F4F9F4F90 -:109FD0009923A9F0F92F96E9BB279395F6958795D4 -:109FE00077956795B795F111F8CFFAF4BB0F11F497 -:109FF00060FF1BC06F5F7F4F8F4F9F4F16C088233E -:10A0000011F096E911C0772321F09EE8872F762F73 -:10A0100005C0662371F096E8862F70E060E02AF0B4 -:10A020009A95660F771F881FDAF7880F96958795A0 -:10A0300097F9089507D180F09F3740F491110EF001 -:10A0400019C160E070E080E89FEB089526F41B16CC -:10A05000611D711D811D2BC045C0990F0008550F52 -:10A06000AA0BE0E8FEEF16161706E807F907C0F09E -:10A0700012161306E407F50798F0621B730B840BA6 -:10A08000950B39F40A2661F0232B242B252B21F480 -:10A0900008950A2609F4A140A6958FEF811D811D20 -:10A0A000089597F99F6780E870E060E0089588233D -:10A0B00071F4772321F09850872B762F07C0662301 -:10A0C00011F499270DC09051862B70E060E02AF0C2 -:10A0D0009A95660F771F881FDAF7880F96958795F0 -:10A0E00097F908959F3F31F0915020F48795779527 -:10A0F0006795B795880F911D9695879597F908955F -:10A100009FEF80EC0895DF93CF931F930F93FF92FF -:10A11000EF92DF927B018C01689405C0DA2EEF018B -:10A120008DD1FE01E894A5912591359145915591E8 -:10A13000AEF3EF01DADDFE019701A801DA9479F7B9 -:10A14000DF90EF90FF900F911F91CF91DF910895D5 -:10A1500000240A9416161706180609060895002406 -:10A160000A9412161306140605060895C9CF50D096 -:10A17000E8F3E894E0E0BB279F57F0F02AED3FE0DA -:10A1800049EC06C0EE0FBB0F661F771F881F28F033 -:10A19000B23A62077307840728F0B25A620B730B56 -:10A1A000840BE3959A9572F7803830F49A95BB0F3B -:10A1B000661F771F881FD2F7904896CF092E039409 -:10A1C000000C11F4882352F0BB0F40F4BF2B11F4A4 -:10A1D00060FF04C06F5F7F4F8F4F9F4F0895EF93D5 -:10A1E000E0FF06C0A2EA2AED3FE049EC5FEB7DDD2F -:10A1F000E5DF0F90039401FC9058EDE9F0E0C7C152 -:10A2000057FD9058440F551F59F05F3F71F0479527 -:10A21000880F97FB991F61F09F3F79F0879508950C -:10A22000121613061406551FF2CF4695F1DF08C02B -:10A23000161617061806991FF1CF86957105610548 -:10A2400008940895E5DFA0F0BEE7B91788F4BB27AE -:10A250009F3860F41616B11D672F782F8827985FF6 -:10A26000F7CF869577956795B11D93959639C8F385 -:10A270000895E894BB2766277727CB0197F90895BF -:10A28000ECDE08F48FEF089563DF19F068DF09F062 -:10A2900037CF07CFB901CA0125CF9F775F77B0DFEE -:10A2A00098F39923B9F35523B9F3FF27951758F479 -:10A2B000E52FE91BED3070F75E3B10F0F1E41CC0B8 -:10A2C0009034E0F40AC0E92FE51BED3028F79E3BFF -:10A2D00010F0F1E411C0503488F4F9EA88232AF030 -:10A2E0009A95660F771F881FDAF744232AF05A954C -:10A2F000220F331F441FDAF79F1B5F1BFF931F932F -:10A300000F93FF92EF9279018A01BB27AB2F9B013C -:10A31000AC0196D09701A801BF937B018C01AA27BD -:10A32000BA2FB901CA018CD0AF919701A801EF9063 -:10A33000FF900F911F91D9DC41DFE1D04F9140FF99 -:10A340000895552747FD509509C09B01AC0160E079 -:10A3500070E080E89FE398CDA4CEC4CE59DFE8F347 -:10A360009923D9F3940F511DBBF39150504094F0B1 -:10A3700059F0882332F0660F771F881F91505040A4 -:10A38000C1F79E3F510544F7880F911D969587951B -:10A3900097F908955F3FACF0983E9CF0BB278695F7 -:10A3A00077956795B79508F4B1609395C1F7BB0FA2 -:10A3B00058F711F460FFE8CF6F5F7F4F8F4F9F4FCB -:10A3C000E3CF58CF25DF58F19E5758F19851A0F0B0 -:10A3D000E9F0983020F5092E9927660F771F881F1E -:10A3E000991F0A94D1F712C0062E672F782F88275D -:10A3F000985F11F4000C07C0993FB4F386957795E8 -:10A4000067959395D9F7611D711D811D3EF4909557 -:10A410008095709561957F4F8F4F9F4F08956894F9 -:10A4200029CF27CF0BD0CACE93DE28F098DE18F0C4 -:10A43000952309F036CE64CE11241CCFE1DEA0F3C3 -:10A44000959FD1F3950F50E0551F629FF001729FC9 -:10A45000BB27F00DB11D639FAA27F00DB11DAA1FE8 -:10A46000649F6627B00DA11D661F829F2227B00D35 -:10A47000A11D621F739FB00DA11D621F839FA00DC0 -:10A48000611D221F749F3327A00D611D231F849F10 -:10A49000600D211D822F762F6A2F11249F57504067 -:10A4A0008AF0E1F088234AF0EE0FFF1FBB1F661F02 -:10A4B000771F881F91505040A9F79E3F510570F0BB -:10A4C000F0CDD8CE5F3FECF3983EDCF386957795E0 -:10A4D0006795B795F795E7959F5FC1F7FE2B880FB6 -:10A4E000911D9695879597F908959F9340DE0F905B -:10A4F00007FCEE5F74CE11F40EF402CEF3CD88DECD -:10A50000D0F39923D9F3CEF39F57550B87FF38D05B -:10A510000024A0E640EA900180585695979528F4CB -:10A52000805C660F771F881F20F0261737074807C3 -:10A5300030F4621B730B840B202931294A2BA6951A -:10A5400017940794202531254A2758F7660F771F5F -:10A55000881F20F026173707480730F4620B730B6B -:10A56000840B200D311D411DA09581F7B901842F69 -:10A570009158880F9695879508959B01AC0152CF0D -:10A5800091505040660F771F881FD2F708959F9310 -:10A590008F937F936F93FF93EF939B01AC0142DF07 -:10A5A000EF91FF91B0DD2F913F914F915F913ACFA5 -:10A5B000629FD001739FF001829FE00DF11D649FA7 -:10A5C000E00DF11D929FF00D839FF00D749FF00D33 -:10A5D000659FF00D9927729FB00DE11DF91F639FD4 -:10A5E000B00DE11DF91FBD01CF011124089597FBA6 -:10A5F000092E07260AD077FD04D049D006D00020C6 -:10A600001AF4709561957F4F0895F6F790958195AE -:10A610009F4F0895A1E21A2EAA1BBB1BFD010DC07E -:10A62000AA1FBB1FEE1FFF1FA217B307E407F50702 -:10A6300020F0A21BB30BE40BF50B661F771F881FDE -:10A64000991F1A9469F760957095809590959B0174 -:10A65000AC01BD01CF01089597FB092E05260ED050 -:10A6600057FD04D0D7DF0AD0001C38F45095409530 -:10A67000309521953F4F4F4F5F4F0895F6F79095D6 -:10A680008095709561957F4F8F4F9F4F0895AA1BBE -:10A69000BB1B51E107C0AA1FBB1FA617B70710F0CD -:10A6A000A61BB70B881F991F5A95A9F780959095FF -:10A6B000BC01CD010895EE0FFF1F0590F491E02D30 -:10A6C0000994A1E0B0E0E6E6F3E576C55B0161152B -:10A6D000710521F0DB018C9311969C93482F592F23 -:10A6E0006A01F601E1906F018F018E2D90E080D21A -:10A6F0000097B9F7FE2DFD3229F4D601ED908D01BA -:10A7000021E007C0BE2DBB3219F4F601E1908F01A4 -:10A7100020E068010894C108D108C60163EA7FE01F -:10A7200043E050E029836CD22981009709F572E05B -:10A73000E72EF12CE00EF11EC70166EA7FE045E04E -:10A7400050E05ED22981009729F467E0E62EF12CD3 -:10A75000E00EF11EA114B10421F0D5011196FC9276 -:10A76000EE9220FF0AC130E020E090E88FEF0DC1AB -:10A77000C6016BEA7FE043E050E0298341D22981A2 -:10A78000009731F060E070E0CB01662477240AC0C6 -:10A79000A114B10409F4F5C00E5F1F4FF501118338 -:10A7A0000083EFC03E2D30533A30A0F52260E22FF7 -:10A7B000F0E0AF014870507022FF07C0411551050D -:10A7C00071F50894611C711C2AC04115510519F0DE -:10A7D0000894610871086B017C0152E0CC0CDD1C0F -:10A7E000EE1CFF1C5A95D1F76C0D7D1D8E1D9F1D13 -:10A7F000660F771F881F991F630F711D811D911DA3 -:10A800006839F9E97F07F9E98F07F9E19F0738F01F -:10A81000246005C03E3F39F423FD3FC02860D801C5 -:10A82000ED908D01BFCF353311F03531B1F5F80121 -:10A8300031913D3211F4206102C03B3241F4D80124 -:10A8400011963C911197319642E050E002C041E0F0 -:10A8500050E030533A3020F08F01041B150B1DC01F -:10A8600040E050E0BCE040385B075CF4DA01AA0F3E -:10A87000BB1FAA0FBB1F4A0F5B1F440F551F430F7F -:10A88000511D319130538F013A3060F324FF03C0E2 -:10A89000509541955F4F640E751EC22EDD2421FF39 -:10A8A00008C0A114B10429F001501040F501118332 -:10A8B000008383DB7B018C01F3E0CF22DD2433E0D6 -:10A8C000C316D10421F417FB109517F91095C80190 -:10A8D000B70120E030E0A901D0DA882309F448C0AC -:10A8E00077FE09C042ECC42E4FE0D42E70946194E0 -:10A8F0007108739404C03AEDC32E3FE0D32E26E0D6 -:10A90000822E912C90E2A92EB12C0EC0F601259139 -:10A91000359145915491C801B70184DDE62EF72E9B -:10A92000082F192F6A187B086A147B047CF7B594EA -:10A93000A7940894810891088114910429F08CEF60 -:10A940009FEFC80ED91EF0CFB701C801282F220FE4 -:10A95000292F221F2F3F31F020E030E0A9018DDAAE -:10A96000882331F482E290E09093F60A8093F50A0E -:10A970003E2D2F2D902F812F08C030E020E090E851 -:10A9800003C030E020E090EC8FE7F901AC016F2FBD -:10A99000722F852F942F2196EEE02AC42F923F929A -:10A9A0004F925F927F928F929F92AF92BF92CF927F -:10A9B000DF92EF92FF920F931F93CF93DF934B01A0 -:10A9C000EA016115710519F0FB01808391832097DD -:10A9D00039F09E01225030402332310508F0F1C099 -:10A9E000A82EB92EF50111915F017F01812F90E012 -:10A9F000FFD00097B9F71D3229F4F50111917F01BD -:10AA000001E006C01B3219F4F50111917F0100E04D -:10AA1000209719F0C031D105B9F4103381F4F70152 -:10AA20008081883711F0883551F4F701118182E077 -:10AA300090E0E80EF91E0260C0E1D0E005C020976A -:10AA400019F41033C1F422C0C830D105F9F0C9306F -:10AA5000D10524F4C230D10509F507C0CA30D105AB -:10AA600051F0C031D105D1F426C0A12CB12CC12C9C -:10AA7000F0E4DF2E25C0CAE0D0E0ECECAE2EECEC2A -:10AA8000BE2EECECCE2EECE0DE2E1AC0C8E0D0E0FC -:10AA9000A12CB12CC12C70E1D72E12C09E014427ED -:10AAA00037FD4095542F60E070E080E090E8B2DD23 -:10AAB00059016A0105C0A12CB12CC12C68E0D62E29 -:10AAC00040E060E070E0CB011E01442437FC40947C -:10AAD000542C50ED752E710EE72DEA3070F0212FB9 -:10AAE00021542A3118F439EC732E06C0212F215637 -:10AAF0002A3128F529EA722E710E272D30E02C1705 -:10AB00003D07ECF447FD17C0A616B706C806D906E0 -:10AB100078F0A20191014CDD670D711D811D911D21 -:10AB20006130F0E07F07F0E08F07F0E89F0710F05A -:10AB30004FEF01C041E0F70111917F01CACF8114AD -:10AB4000910491F0442339F00894E108F108F401EC -:10AB5000F182E08209C001FF1BC097012250304002 -:10AB6000F4013183208314C047FF12C000FF05C0E9 -:10AB700060E070E080E090E804C06FEF7FEF8FEF5F -:10AB80009FE722E230E03093F60A2093F50A16C0E0 -:10AB900000FF08C090958095709561957F4F8F4F0D -:10ABA0009F4F0CC097FF0AC082E290E09093F60A94 -:10ABB0008093F50A6FEF7FEF8FEF9FE79B01AC016A -:10ABC00003C020E030E0A901B901CA01DF91CF91B3 -:10ABD0001F910F91FF90EF90DF90CF90BF90AF90BB -:10ABE0009F908F907F905F904F903F902F9008950F -:10ABF00091113BC2803219F089508550D0F70895E9 -:10AC0000FB01DC014150504088F08D9181341CF0F3 -:10AC10008B350CF4805E659161341CF06B350CF45F -:10AC2000605E861B611171F3990B0895881BFCCF40 -:10AC3000FC018191861721F08823D9F7992708957F -:10AC40003197CF010895FB0151915523A9F0BF0120 -:10AC5000DC014D9145174111E1F759F4CD01019007 -:10AC6000002049F04D9140154111C9F3FB014111FC -:10AC7000EFCF81E090E001970895AEE0B0E0E2E42C -:10AC8000F6E5A4C20D891E8986E08C831A830983A8 -:10AC90008FEF9FE79E838D839E01275E3F4FCE01FE -:10ACA00001966F89788DA90108D0EF81F885E00FB2 -:10ACB000F11F10822E96E4E0A5C2ACE0B0E0E2E61F -:10ACC000F6E576C26C011B018A01FC01178216822F -:10ACD000838181FFC4C12E010894411C511CF601DF -:10ACE0009381F10193FD859193FF81911F01882349 -:10ACF00009F4B1C1853239F493FD859193FF8191B7 -:10AD00001F01853221F490E0B601C8D1E8CFEE24CE -:10AD1000FF2420E02032B0F48B3269F08C3228F42A -:10AD2000803251F0833271F40BC08D3239F08033B0 -:10AD300049F421602CC02260246029C0286027C00B -:10AD4000206125C027FD2CC0382F30533A3098F4AD -:10AD500026FF08C08E2D880FE82EEE0CEE0CE80EB4 -:10AD6000E30E15C08F2D880FF82EFF0CFF0CF80E88 -:10AD7000F30E20620CC08E3221F426FD6CC12064DB -:10AD800006C08C3611F4206802C0883649F4F101FF -:10AD900093FD859193FF81911F01882309F0BACF1C -:10ADA000982F9554933018F09052933028F40C5FFC -:10ADB0001F4FFFE3F9830DC0833631F0833771F005 -:10ADC000833509F05CC021C0F801808189830E5F62 -:10ADD0001F4F420171E0A72EB12C15C062E0662E14 -:10ADE000712C600E711EF8018080918026FF03C0D7 -:10ADF0006E2D70E002C06FEF7FEFC4012C8743D14E -:10AE00005C0183012C852F7716C052E0652E712CD2 -:10AE1000600E711EF8018080918026FF03C06E2DA8 -:10AE200070E002C06FEF7FEFC4012C8721D15C017D -:10AE30002C852068830123FD1EC007C080E290E0BE -:10AE4000B6012C872BD1FA942C858F2D90E0A81673 -:10AE5000B906A0F310C0F40127FD859127FF819169 -:10AE60004F0190E0B6012C8719D12C85F110FA948E -:10AE70000894A108B108A114B10469F7E9C08436A7 -:10AE800011F0893641F527FF08C0F8016081718112 -:10AE9000828193810C5F1F4F09C0F801608171812D -:10AEA000882777FD8095982F0E5F1F4F4FE6B42EB1 -:10AEB000B22297FF09C090958095709561957F4F5C -:10AEC0008F4F9F4FF0E8BF2AA2012AE030E012D155 -:10AED000782E741844C0853731F43FEEB32EB22279 -:10AEE0002AE030E025C099EFB92EB2228F36C1F0AA -:10AEF000803720F4883509F0AEC00DC0803721F0CE -:10AF0000883709F0A8C002C020E1B22AB4FE0BC005 -:10AF100084E0B82A08C0B4FE09C0E6E0BE2A06C034 -:10AF200028E030E005C020E130E002C020E132E05E -:10AF3000B7FE08C0F80160817181828193810C5F46 -:10AF40001F4F07C0F8016081718180E090E00E5FC3 -:10AF50001F4FA201CFD0782E7418FFE7BF22B6FE94 -:10AF60000BC02EEFB2227E1438F4B4FE07C0B2FC40 -:10AF700005C08FEEB82202C0A72C01C0AE2C8B2DCD -:10AF800090E0B4FE0DC0FE01E70DF11D20812033DD -:10AF900019F4E9EEBE2209C0A394B2FE06C004C0B3 -:10AFA00086789070009709F0A3948B2C9924B3FCB9 -:10AFB00013C0B0FE0EC0AF1428F4E72CEF0CEA1853 -:10AFC000AF2C07C0E72C05C080E290E0B60166D048 -:10AFD000A394AF14C8F304C0AF1410F4FA1801C05E -:10AFE000FF2484FE0EC080E390E0B60157D082FEBD -:10AFF0001DC081FE03C088E590E010C088E790E0A6 -:10B000000DC0C40186789070009781F081FC02C069 -:10B0100080E201C08BE2B7FC8DE290E0B6013ED049 -:10B0200005C080E390E0B60139D0EA947E14C8F3FD -:10B030007A94F201E70DF11D808190E0B6012ED0E7 -:10B040007720B1F705C080E290E0B60127D0FA94EE -:10B05000FF20C9F744CEF6012681378102C02FEFC9 -:10B060003FEFC9012C96E2E1BFC0992788270895D8 -:10B07000FC010590615070400110D8F780959095C3 -:10B080008E0F9F1F0895FC016150704001900110C8 -:10B09000D8F7809590958E0F9F1F08950F931F935B -:10B0A000CF93DF938C01EB018B8181FF1BC082FF6B -:10B0B0000DC02E813F818C819D812817390764F452 -:10B0C000E881F9810193F983E88306C0E885F98571 -:10B0D000802F0995009731F48E819F8101969F837F -:10B0E0008E8302C00FEF1FEFC801DF91CF911F9138 -:10B0F0000F910895FA01AA27283051F1203181F1EA -:10B10000E8946F936E7F6E5F7F4F8F4F9F4FAF4F6F -:10B11000B1E03ED0B4E03CD0670F781F891F9A1F82 -:10B12000A11D680F791F8A1F911DA11D6A0F711D36 -:10B13000811D911DA11D20D009F468943F912AE042 -:10B14000269F11243019305D3193DEF6CF0108952A -:10B15000462F4770405D4193B3E00FD0C9F7F6CF5B -:10B16000462F4F70405D4A3318F0495D31FD405223 -:10B17000419302D0A9F7EACFB4E0A69597958795B9 -:10B1800077956795BA95C9F7009761057105089598 -:10B190009B01AC010A2E0694579547953795279544 -:10B1A000BA95C9F7620F731F841F951FA01D0895DC -:10B1B0002F923F924F925F926F927F928F929F92C7 -:10B1C000AF92BF92CF92DF92EF92FF920F931F93B5 -:10B1D000CF93DF93CDB7DEB7CA1BDB0B0FB6F89466 -:10B1E000DEBF0FBECDBF09942A88398848885F84A6 -:10B1F0006E847D848C849B84AA84B984C884DF8017 -:10B20000EE80FD800C811B81AA81B981CE0FD11DFA -:10B210000FB6F894DEBF0FBECDBFED010895F894D0 -:02B22000FFCF5E -:10B222005573696E672044656661756C7420736539 -:10B232007474696E67733A004D31313000482000F2 -:10B242004C20002569206D696E2C202569207365CC -:10B2520063004D31303420496E76616C696420653B -:10B262007874727564657220004D31303520496EF4 -:10B2720076616C6964206578747275646572200009 -:10B282004D31303920496E76616C6964206578747D -:10B29200727564657220003F006F6B0020703A0087 -:10B2A20020693A0020643A0020633A005400496E53 -:10B2B20076616C69642065787472756465720041A8 -:10B2C20063746976652045787472756465723A2094 -:10B2D200002E00537465707261746520746F20686B -:10B2E200696768203A2000504944204175746F74A0 -:10B2F200756E652073746172740000803B45008036 -:10B302003B4500007043000000006400640060EAF6 -:10B3120000000080BB44010101010101713DE841CF -:10B32200A97E443E756089440000803FFF3FFF3F95 -:10B332000158595A45000001001A0019000A00007C -:10B3420000FFFF1C001B000A000100FFFF17001690 -:10B35200000A000200FFFFFFFFFFFF04000E0018BB -:10B362000015000A0003000000010002000200288C -:10B3720023000028230000640000001027000000C2 -:10B3820000FA430000FA430000A0400000344200EB -:10B3920000A04214AE9F4200002045F6C8154403A7 -:06B3A20000480D3D000013 +:1014B0008111F6CFB6DE4AE050E0BC0181E894E04D +:1014C0000E943C24EEE5F1E007C09091C00095FF3A +:1014D000FCCF8093C600319684918111F6CF4AE00B +:1014E00050E060ED74E081E894E00E943C2480913B +:1014F000C00085FFFCCF8AE08093C60010922A04CA +:1015000010922B0410922C0410922D0480E094DD94 +:1015100025E1C22E2AE0D22E35E2E32E3AE0F32E68 +:1015200009EE19E0F60161917191819191916F013C +:10153000F70121913191419151917F0129833A83A2 +:101540004B835C830E94744C29813A814B815C817E +:101550000E94A94E0E94484CF801619371938193B7 +:1015600091938F01F5E2CF16FAE0DF06D9F60E94DB +:101570005E440E94FD2C0F900F900F900F90DF9112 +:10158000CF911F910F91FF90EF90DF90CF900C942F +:10159000773F809134049091350460E070E00196CB +:1015A0000C94FE4F80913404909135044AE050E051 +:1015B00060E070E001960C944A5140912E045091E5 +:1015C0002F0490E6949F9001959F300D1124682F71 +:1015D00070E0C90186559D4F0E947C52909335045E +:1015E0008093340421E0892B09F420E0822F0895B0 +:1015F0000E94782160933E0470933F0480934004DE +:1016000090934104EBEAF3E007C09091C00095FF8E +:10161000FCCF8093C600319684918111F6CF8091E2 +:10162000C00085FFFCCF8AE08093C600089581E862 +:1016300094E00E945B23E3EAF3E007C09091C000CE +:1016400095FFFCCF8093C600319684918111F6CF2F +:1016500040913A0450913B0460913C0470913D04E8 +:101660004F5F5F4F6F4F7F4F2AE030E081E894E09B +:101670000E9406248091C00085FFFCCF8AE0809301 +:10168000C600B6CF4F925F927F928F929F92AF9299 +:10169000BF92CF92DF92EF92FF920F931F93CF935F +:1016A000DF9340E6742E54E0452E512CE1E2F2E047 +:1016B00084906AE0B62EEEE1F2E0A490992493942F +:1016C0008091020590910305209104053091050554 +:1016D000821B930B8F779927892B09F0FEC111C2CA +:1016E0008D3051F08A3321F490913104992321F007 +:1016F0002F3531050CF4D4C12115310519F41092A0 +:101700003104FFC18091A8029091A902789EE00166 +:10171000799ED00D1124FE01E20FF31FE655FD4F17 +:101720001082209131042111B6C110923104FC01C4 +:10173000E65DFB4F10828E0106551D4F6EE470E092 +:10174000C8010E947C52009709F403C190933504AC +:1017500080933404801B910B8C0F9D1F4AE050E056 +:1017600060E070E085559D4F0E944A5160933604B9 +:10177000709337048093380490933904C0903A04EE +:10178000D0903B04E0903C04F0903D04970186012A +:101790000F5F1F4F2F4F3F4F60177107820793074F +:1017A000C1F12091A8023091A902729EC001739EDE +:1017B000900D11246FE771E086559D4F0E9487526E +:1017C000892B39F5E5E7F1E007C09091C00095FF5E +:1017D000FCCF8093C600319684918111F6CFECE75F +:1017E000F1E007C09091C00095FFFCCF8093C60048 +:1017F000319684918111F6CF2AE030E0B701A6013D +:1018000081E894E00E9406248091C00085FFFCCF0F +:101810008AC08091A8029091A902789E8001799E49 +:10182000100D1124E801C655DD4F6AE270E0CE01CB +:101830000E947C52009721F450C0F3262F5F02C013 +:1018400020E0F12CF801E20FF11DE655FD4F30814B +:101850003A3299F790933504809334048C1B9D0B96 +:10186000800F911F60E070E085559D4F0E94FE4FF4 +:101870000E94434C2F2D30E02617370709F458C03B +:10188000E5E7F1E007C09091C00095FFFCCF8093A1 +:10189000C600319684918111F6CFEEEAF1E007C0DF +:1018A0009091C00095FFFCCF8093C6003196849143 +:1018B0008111F6CF40913A0450913B0460913C0471 +:1018C00070913D042AE030E081E894E00E94062413 +:1018D0008091C00085FFFCCF26C0E5E7F1E007C09E +:1018E0009091C00095FFFCCF8093C6003196849103 +:1018F0008111F6CFECECF1E007C09091C00095FFAC +:10190000FCCF8093C600319684918111F6CF2AE0F6 +:1019100030E0B701A60181E894E00E94062480919E +:10192000C00085FFFCCF8AE08093C60080DE47C000 +:101930008091360490913704A0913804B091390415 +:1019400080933A0490933B04A0933C04B0933D04ED +:101950003BC06AE270E0C8010E947C52892BA1F171 +:10196000E5E7F1E007C09091C00095FFFCCF8093C0 +:10197000C600319684918111F6CFE5EFF1E007C002 +:101980009091C00095FFFCCF8093C6003196849162 +:101990008111F6CF40913A0450913B0460913C0490 +:1019A00070913D042AE030E081E894E00E94062432 +:1019B0008091C00085FFFCCF8AE08093C600109222 +:1019C0003304109232049DC08091A8029091A90224 +:1019D000789EE001799ED00D11248E0106551D4F91 +:1019E00067E470E0C8010E947C52009709F43EC091 +:1019F0009093350480933404801B910B8C0F9D1FB2 +:101A000060E070E085559D4F0E94FE4F0E94434C60 +:101A10006430710558F580918002811113C08A2DC0 +:101A2000EEE1F2E008C09091C00095FFFCCF8093FA +:101A3000C600319684918111F6CF8091C00085FF58 +:101A4000FCCF12C0882DE1E2F2E008C09091C00006 +:101A500095FFFCCF8093C600319684918111F6CF1B +:101A60008091C00085FFFCCFB092C6008091A80293 +:101A70009091A9020196B2010E948E4F9093A90203 +:101A80008093A8028091A6029091A702019690935C +:101A9000A7028093A602109233041092320410CE53 +:101AA0008B3311F49092310490913104911108CE4E +:101AB0004091A8025091A902749ED001759EB00D6C +:101AC0001124A20FB31FA655BD4F8C932F5F3F4F1C +:101AD0003093330420933204F3CD8091A602909189 +:101AE000A702049774F481E894E00E943F23809356 +:101AF000300420913204309133048A3009F0F0CD63 +:101B0000FBCDDF91CF911F910F91FF90EF90DF9070 +:101B1000CF90BF90AF909F908F907F905F904F90AD +:101B200008958F929F92AF92BF92CF92DF92EF92E1 +:101B3000FF920F931F93CF93DF9378E1A72E72E06C +:101B4000B72E0FE812E0C6E4D4E0E2EA8E2EE2E01F +:101B50009E2EF50181915F0130DD882311F119DDA1 +:101B60006B017C01F4018081811103C060915604F6 +:101B700001C061E070E080E090E00E94764CF801E6 +:101B800020813181428153810E94A94E9B01AC0189 +:101B9000C701B6010E94FB4A688379838A839B83CD +:101BA00009C0F80180819181A281B38188839983E2 +:101BB000AA83BB830C5F1F4F2496FFEF8F1A9F0AE7 +:101BC0008CE1A81682E0B80621F686E4F6DC8823CC +:101BD000D1F0DFDC6B017C016093680470936904D1 +:101BE00080936A0490936B0420E030E0A9010E9486 +:101BF000D74D181644F4C0921401D0921501E0920A +:101C00001601F0921701DF91CF911F910F91FF9074 +:101C1000EF90DF90CF90BF90AF909F908F900895FE +:101C200080DF89E4CADC882351F0B3DC60936C0464 +:101C300070936D0480936E0490936F0408C01092AB +:101C40006C0410926D0410926E0410926F048AE47A +:101C5000B4DC882351F09DDC6093700470937104B0 +:101C600080937204909373040895109270041092FC +:101C7000710410927204109273040895CF92DF924F +:101C8000EF92FF920F931F9320E030E0A901609143 +:101C900046047091470480914804909149040E9441 +:101CA000D44B87FF08C0109246041092470410924C +:101CB00048041092490420E030E0A90160914A04F0 +:101CC00070914B0480914C0490914D040E94D44B30 +:101CD00087FF08C010924A0410924B0410924C04E3 +:101CE00010924D0420E030E0A90160914E04709103 +:101CF0004F0480915004909151040E94D44B87FF6F +:101D000008C010924E0410924F041092500410928A +:101D1000510420E030E04DE453E4609146047091BA +:101D2000470480914804909149040E94D74D1816A9 +:101D300064F480E090E0ADE4B3E4809346049093D3 +:101D40004704A0934804B093490420E030E04DE4F8 +:101D500053E460914A0470914B0480914C0490913B +:101D60004D040E94D74D181664F480E090E0ADE475 +:101D7000B3E480934A0490934B04A0934C04B09333 +:101D80004D0420E030E040EF52E460914E04709149 +:101D90004F0480915004909151040E94D74D181621 +:101DA00064F480E090E0A0EFB2E480934E0490935E +:101DB0004F04A0935004B09351040E947821609383 +:101DC0003E0470933F0480934004909341046091DB +:101DD000020170910301882777FD8095982F0E945A +:101DE000764C2091140130911501409116015091CB +:101DF00017010E94A94E20E030E040E752E40E9423 +:101E0000DB4B20E030E048EC52E40E94DB4BF2E890 +:101E1000CF2EF2E0DF2E7B018C0122E534E04EE490 +:101E200054E06AE474E086E494E00E947C2D8091A2 +:101E3000460490914704A0914804B09149048093CE +:101E40008F0290939002A0939102B093920280919E +:101E50004A0490914B04A0914C04B0914D0480939E +:101E6000930290939402A0939502B093960280916E +:101E70004E0490914F04A0915004B091510480936E +:101E8000970290939802A0939902B0939A0280913E +:101E9000520490915304A0915404B091550480933E +:101EA0009B0290939C02A0939D02B0939E021F916F +:101EB0000F91FF90EF90DF90CF900895AF92BF9277 +:101EC000CF92DF92EF92FF920F931F93CF93DF9306 +:101ED000182F209170043091710440917204509138 +:101EE000730460916C0470916D0480916E04909104 +:101EF0006F040E94E44DEB01082FF92E609102015E +:101F000070910301882777FD8095982F0E94764C69 +:101F10002091140130911501409116015091170143 +:101F20000E94A94E20E030E040E752E40E94DB4BE3 +:101F300020E030E048EC52E40E94DB4B209182022A +:101F40002F931F93FF920F93DF93CF935B016C014D +:101F5000A2E0EA2E01E020E04CE654E066E474E002 +:101F60008FE892E00E9400258091460490914704FA +:101F7000A0914804B091490480938F0290939002FD +:101F8000A0939102B093920280914A0490914B04E5 +:101F9000A0914C04B0914D048093930290939402CD +:101FA000A0939502B093960280914E0490914F04B5 +:101FB000A0915004B091510480939702909398029D +:101FC000A0939902B0939A02809152049091530485 +:101FD000A0915404B091550480939B0290939C026D +:101FE000A0939D02B0939E020E94782160933E04CC +:101FF00070933F0480934004909341040F900F909E +:102000000F900F900F900F90DF91CF911F910F9134 +:10201000FF90EF90DF90CF90BF90AF900895F8942D +:102020000E94BB445A985A985A985A98E5E7F1E0AA +:1020300007C09091C00095FFFCCF8093C6003196F9 +:1020400084918111F6CFEEEAF3E007C09091C000D1 +:1020500095FFFCCF8093C600319684918111F6CF15 +:102060008091C00085FFFCCF8AE08093C600FFCF3F +:10207000CF92DF92EF92FF920F931F930E947821ED +:102080000091600410916104209162043091630416 +:10209000C0903E04D0903F04E0904004F090410492 +:1020A0006C197D098E099F0906171707280739073C +:1020B00028F4012B022B032B09F0B1DF80911901C9 +:1020C00090911A01A0911B01B0911C01892B8A2BC0 +:1020D0008B2B09F10E94782100913E0410913F045E +:1020E0002091400430914104601B710B820B930BD3 +:1020F0000091190110911A0120911B0130911C01CE +:10210000061717072807390730F4909108058091C2 +:102110000705981721F00E94312D1EBA05C05A9864 +:102120005A985A985A98F7CF1F910F91FF90EF90B5 +:10213000DF90CF9008952F923F924F925F926F92CF +:102140007F928F929F92AF92BF92CF92DF92EF9247 +:10215000FF920F931F93CF93DF93CDB7DEB7A69770 +:102160000FB6F894DEBF0FBECDBF87E426DA882312 +:1021700009F489C20EDA0E94434C64307105B1F152 +:1021800044F46230710511F144F577FF17C00C94E7 +:10219000501D6A35710509F422C234F46C317105A1 +:1021A00011F00C94501D60C06B35710509F41BC211 +:1021B0006C35710511F00C94501D1AC2809180028B +:1021C000811104C0AEDC5ADD0C9495208091800210 +:1021D000811103C025DD81E006C08091800281115C +:1021E00005C01EDD80E06ADE0C94952080E5E5D90F +:1021F000882331F0CED90E94484C6B017C0103C08A +:10220000C12CD12C760183E5D8D9882359F0C1D9C6 +:1022100020E030E04AE754E40E94A94E0E94484C76 +:102220006B017C010E94B63F0E9478214B015C014A +:102230008C0C9D1CAE1CBF1C0E94782160933E0438 +:1022400070933F04809340049093410404C00E9423 +:10225000E24181E00DDF0E947821681579058A0549 +:102260009B05A8F30C94501D8091140190911501C9 +:10227000A0911601B09117018093420490934304FA +:10228000A0934404B093450480910201909103010E +:102290009093A1028093A00284E690E090930301C2 +:1022A000809302010E94782160933E0470933F0462 +:1022B000809340049093410481E00E94763980919C +:1022C0008F0290919002A0919102B091920280931E +:1022D000460490934704A0934804B0934904809126 +:1022E000930290919402A0919502B09196028093EE +:1022F0004A0490934B04A0934C04B0934D048091F6 +:10230000970290919802A0919902B0919A028093BD +:102310004E0490934F04A0935004B09351048091C5 +:102320009B0290919C02A0919D02B0919E0280938D +:10233000520490935304A0935404B0935504109204 +:10234000140110921501109216011092170188E5E0 +:1023500034D9882311F090E008C089E52ED9811185 +:10236000FACF8AE52AD991E0982790931801911124 +:102370000C94531D88E521D9882309F48EC089E582 +:102380001CD981110C94531D88C0C0921401D092A5 +:102390001501E0921601F092170120E030E040E7CD +:1023A00052E4609114017091150180911601909191 +:1023B00017010E94DB4BE2E8CE2EE2E0DE2E7B012D +:1023C0008C0122E534E04EE454E06AE474E086E4F3 +:1023D00094E00E947C2D0E94B63F10928F021092D2 +:1023E0009002109291021092920210929302109217 +:1023F000940210929502109296022BE932E047E97E +:1024000052E063E972E08FE892E00E94FC3780912D +:102410008F0290919002A0919102B09192028093CC +:10242000460490934704A0934804B09349048091D4 +:10243000930290919402A0919502B091960280939C +:102440004A0490934B04A0934C04B0934D0420E0B5 +:1024500030E040E752E460911401709115018091E1 +:102460001601909117010E94DB4B7B018C0122E544 +:1024700034E04EE454E06AE474E086E494E00E94C0 +:102480007C2D1092140110921501109216011092D9 +:1024900017010E94B63F0E946F3980911801811187 +:1024A0000C94A31D88E589D881110C94A31D8091FB +:1024B000180181110C947B1E89E57FD881110C9441 +:1024C0007B1E8091180181110C94531F8AE575D8E9 +:1024D00081110C94531F88E570D88823C1F062D80D +:1024E000672B682B692B99F054D820918302309187 +:1024F000840240918502509186020E94FB4A6093BB +:102500008F0270939002809391029093920289E5DA +:1025100054D88823C1F046D8672B682B692B99F0D3 +:1025200038D82091870230918802409189025091D9 +:102530008A020E94FB4A60939302709394028093F4 +:102540009502909396028AE538D88823C1F02AD85C +:10255000672B682B692B99F01CD820918B02309146 +:102560008C0240918D0250918E020E94FB4A609332 +:102570009702709398028093990290939A022BE9A4 +:1025800032E047E952E063E972E08FE892E00E94AE +:10259000FC378091420490914304A0914404B0918F +:1025A00045048093140190931501A0931601B093F4 +:1025B00017018091A0029091A10290930301809352 +:1025C00002010E94782160933E0470933F0480933F +:1025D0004004909341040E946F390C94501D109256 +:1025E00056040C94501D81E0809356040C94501DA9 +:1025F00085E40E94DD0A811102C00E94B63F48E1D5 +:10260000C42E42E0D42E53E8E52E52E0F52E0FE81A +:1026100012E0B12CF60181916F010E94DD0A88233E +:1026200039F1F3E0BF120CC00E94C90AF8016083BF +:102630007183828393838BE992E00E94973818C05C +:102640000E94C90AF70120813181428153810E9491 +:10265000FB4AF80160837183828393832BE932E024 +:1026600047E952E063E972E08FE892E00E94FC37AC +:10267000B394F4E0EF0EF11C0C5F1F4F24E0B21294 +:10268000C9CF0C94501D8DE40E94DD0A882311F4FB +:102690000C94A51C0E94C90A0E94434C683771051E +:1026A00009F4D1C60CF053C06C35710509F44FC55F +:1026B00044F56A32710509F406C174F4623171059A +:1026C00009F4F4C46F31710509F4A4C061317105D6 +:1026D00011F00C94501D98C06335710509F4E2C4E3 +:1026E00034F46235710511F00C94501DD8C4643572 +:1026F000710509F4DBC46535710511F00C94501DAA +:1027000010C56B36710509F4C7C464F469367105E8 +:1027100009F48FC10CF099C46836710511F00C945E +:10272000501D11C16237710509F4B1C534F46D361D +:10273000710511F00C94501D4DC26337710509F4F9 +:1027400098C56737710511F00C94501D82C66C3D19 +:10275000710509F4CDC744F5693C710509F4D8C683 +:1027600074F46C38710509F450C16E3B710509F4BD +:10277000D0C36937710511F00C94501D66C66C3CCE +:10278000710509F41BC734F46B3C710511F00C940E +:10279000501DF8C66D3C710509F430C76E3C7105DB +:1027A00011F00C94501D88C76F3231E0730711F49B +:1027B0000C94781C74F46D3291E0790709F4B9C770 +:1027C00014F00C94741C6D3D710511F00C94501DA7 +:1027D000A1C7653FF1E07F0711F40C948A1C3CF41B +:1027E0006039714011F00C94501D0C94871C663FA9 +:1027F00081E0780711F40C948C1C673E734011F053 +:102800000C94501D0C94901C5A9A5A9A5A9A5A9A9F +:102810000C94501D0E9478216093570470935804C3 +:102820008093590490935A0400915B0410915C04C6 +:1028300020915D0430915E04601B710B820B930B41 +:1028400028EE33E040E050E00E94A14FCA01B901F8 +:102850002CE330E040E050E00E94A14F7F936F9363 +:102860003F932F938AE891E09F938F93CE01019637 +:102870009F938F930E94A152EBEBF0E084910FB6EF +:10288000F894DEBF0FBECDBFEBEBF0E008C0909137 +:10289000C00095FFFCCF8093C600319684918111D2 +:1028A000F6CFFE01319606C09091C00095FFFCCF97 +:1028B0008093C60081918111F7CF8091C00085FF80 +:1028C000FCCF0C944D1D83E50E94DD0A882311F492 +:1028D0000C94501D0E94C90A6B017C0180E50E9486 +:1028E000DD0A882311F40C94501DC701B6010E9423 +:1028F000434C7B0177FF02C00C94501D6F3F710564 +:1029000009F014F40C942B200C94501D819191919A +:102910008017910711F40C94501D22E0E039F20762 +:10292000A9F717FF02C00C94501D61E0802F0E9490 +:1029300092226E2D802F0E94AE22B701802F0E941E +:1029400009220C94501D8091820280935F0484E5DB +:102950000E94DD0A882379F10E94C90A0E94484C2E +:1029600060935F04662339F1EBEBF0E007C09091D0 +:10297000C00095FFFCCF8093C600319684918111F1 +:10298000F6CFE9E9F1E006C09091C00095FFFCCFD9 +:102990008093C60081918111F7CF40E050E06091B3 +:1029A0005F0481E894E00E9400248091C00085FFCC +:1029B000FCCF0C944D1D83E50E94DD0A882309F1AC +:1029C000B0905F040E94C90A6B017C010B2D10E0DE +:1029D0000E94434CDC01CB016B2D0E944640F80164 +:1029E000EE0FFF1FE255F54F91838083F801EE0F44 +:1029F000FF1FEE0FFF1FEC55F54FC082D182E28220 +:102A0000F3820E94BA440C94501D83E50E94DD0AB3 +:102A1000882311F40C94501D0E94C90A0E94434C53 +:102A2000CB010E94CA409093AD0A8093AC0A0C94EB +:102A3000501D8091820280935F0484E50E94DD0A2C +:102A4000882371F10E94C90A0E94484C60935F0478 +:102A5000662331F1EBEBF0E007C09091C00095FFE9 +:102A6000FCCF8093C600319684918111F6CFE0EBC4 +:102A7000F1E006C09091C00095FFFCCF8093C600A6 +:102A800081918111F7CF40E050E060915F0481E8CF +:102A900094E00E9400248091C00085FFFCCFFDC718 +:102AA000E9E9F2E007C09091C00095FFFCCF809368 +:102AB000C600319684918111F6CF60915F04E62FB4 +:102AC000F0E0EE0FFF1FE655F54F808191810E94E7 +:102AD0001641AB01BC0121E030E081E894E00E94A6 +:102AE000FF24EFE9F2E007C09091C00095FFFCCF12 +:102AF0008093C600319684918111F6CF60915F0476 +:102B0000E62FF0E0EE0FFF1FE255F54F8081918137 +:102B10000E941641AB01BC0121E030E081E894E065 +:102B20000E94FF24E2EAF2E007C09091C00095FF06 +:102B3000FCCF8093C600319684918111F6CF8091AD +:102B4000A80A9091A90A0E94C943AB01BC0121E0E7 +:102B500030E081E894E00E94FF24E6EAF2E007C05A +:102B60009091C00095FFFCCF8093C6003196849170 +:102B70008111F6CF8091AC0A9091AD0A0E94C943B1 +:102B8000AB01BC0121E030E081E894E00E94FF2429 +:102B9000E9EAF2E007C09091C00095FFFCCF809376 +:102BA000C600319684918111F6CF80915F0490E048 +:102BB0000E9440404AE050E0BC0181E894E00E945D +:102BC0003C248091C00085FFFCCF8AE08093C60042 +:102BD0000C9495208091820280935F0484E50E948A +:102BE000DD0A882371F10E94C90A0E94484C609353 +:102BF0005F04662331F1EBEBF0E007C09091C00079 +:102C000095FFFCCF8093C600319684918111F6CF59 +:102C1000E7ECF1E006C09091C00095FFFCCF8093F7 +:102C2000C60081918111F7CF40E050E060915F04D0 +:102C300081E894E00E9400248091C00085FFFCCFD1 +:102C40002CC783E50E94DD0A882309F1B0905F0458 +:102C50000E94C90A6B017C010B2D10E00E94434CBD +:102C6000DC01CB016B2D0E944640F801EE0FFF1FE7 +:102C7000E255F54F91838083F801EE0FFF1FEE0FB1 +:102C8000FF1FEC55F54FC082D182E282F3820E9491 +:102C9000BA440E9478214B015C0180915F0490E06E +:102CA000880F991FFC01E255F54F2081318138A32F +:102CB0002F8FFC01E655F54F808191819EA38DA356 +:102CC000CC24CA94DC2C7601EDEAF2E02490E0EB0F +:102CD000F2E03490E4EBF2E0049178EE472E73E0FA +:102CE000572E612C712C1AE00C944C20822DEDEAA9 +:102CF000F2E008C09091C00095FFFCCF8093C60021 +:102D0000319684918111F6CF60915F04E62FF0E057 +:102D1000EE0FFF1FE655F54F808191810E9416410D +:102D2000AB01BC0121E030E081E894E00E94FF2487 +:102D3000832DE0EBF2E008C09091C00095FFFCCF3E +:102D40008093C600319684918111F6CF60915F0423 +:102D50004AE050E070E081E894E00E943C24802F3B +:102D6000E4EBF2E008C09091C00095FFFCCF8093A7 +:102D7000C600319684918111F6CFF7FE03C0EEEDC7 +:102D8000F1E027C00E9478214B015C01C701B60128 +:102D9000605F784D8F4F9F4F681979098A099B09A9 +:102DA000A30192010E94A14F49015A012AE030E09B +:102DB000B501A40181E894E00E94F0238091C00055 +:102DC00085FFFCCF0DC09091C00095FFFCCF809394 +:102DD000C60081918111F7CF8091C00085FFFCCFA3 +:102DE0001093C6000E9478214B015C010E94E241D1 +:102DF00081E03ED99FEFC916D906E906F906C1F56B +:102E000060915F04EF8DF8A12DA13EA12E173F0721 +:102E100014F00C946820E62FF0E0EE0FFF1FE6554B +:102E2000F54F808191810E94164169A37AA38BA3FB +:102E30009CA360915F04E62FF0E0EE0FFF1FE255C8 +:102E4000F54F808191810E94164120E030E040E8FA +:102E50005FE30E94FA4A9B01AC0169A17AA18BA1B0 +:102E60009CA10E94D74D87FD02C00C9434203AC02B +:102E7000F7FC38C060915F04E62FF0E0EE0FFF1F13 +:102E8000E655F54F808191810E94164169A37AA38E +:102E90008BA39CA360915F04E62FF0E0EE0FFF1F71 +:102EA000E255F54F808191810E9416419B01AC0152 +:102EB00069A17AA18BA19CA10E94FA4A0E94434C6D +:102EC000AB01BC0177FF07C07095609550954195A7 +:102ED0005F4F6F4F7F4F443051056105710514F00E +:102EE0000C9434203FEFC316D306E306F30611F427 +:102EF0000C944C20F7FE02C00C9439200E947821DB +:102F00006C197D096031774210F40C944C200C94BC +:102F1000392083E50E94DD0A882359F00E94C90AFE +:102F20000E94434CCB010E94CA409093AD0A80930B +:102F3000AC0A0E9478216B017C01E8EBF2E0A490DE +:102F4000EBEBF2E0B490EFEBF2E014910AE06FC02B +:102F50000E9478216C197D098E099F09693E734092 +:102F60008105910508F45FC060918202A62FB0E050 +:102F7000AA0FBB1FA655B54F8D919C910E9416417B +:102F8000AB01BC018A2DE8EBF2E008C09091C000D3 +:102F900095FFFCCF8093C600319684918111F6CFC6 +:102FA00022E030E081E894E00E94FF248B2DEBEBDF +:102FB000F2E008C09091C00095FFFCCF8093C6005E +:102FC000319684918111F6CF609182024AE050E0FF +:102FD00070E081E894E00E943C24812FEFEBF2E066 +:102FE00008C09091C00095FFFCCF8093C600319639 +:102FF00084918111F6CF8091A80A9091A90A0E942C +:10300000C943AB01BC0121E030E081E894E00E94BB +:10301000FF248091C00085FFFCCF0093C6000E9472 +:1030200078216B017C010E94E24181E021D820914E +:10303000AC0A3091AD0A8091A80A9091A90A821732 +:1030400093070CF485CF0C94422083E50E94DD0A9F +:103050008823F1F00E94C90A20E030E0A9010E9413 +:10306000D44B87FD0FC00E94C90A20E030E04FE733 +:1030700053E40E94D74D18163CF00E94C90A0E94E2 +:10308000484C03C060E001C06FEF6093810208C547 +:103090008FEF8093810204C51092810201C51092C6 +:1030A000A502FEC481E08093A502FAC483E50E94D4 +:1030B000DD0A882399F00E94C90A20E030E04AE73F +:1030C00054E40E94A94E0E94484C609319017093E9 +:1030D0001A0180931B0190931C01E2C488E50E94B1 +:1030E000DD0A8111EDC789E50E94DD0A8111E8C77B +:1030F0008AE50E94DD0A8111E3C785E40E94DD0AAA +:103100008111DEC7D7C75A9889E50E94DD0A81116F +:103110005A988AE50E94DD0A882309F4C1C45A98A6 +:10312000BFC483E50E94DD0A0E94C90A20E030E0A6 +:103130004AE754E40E94A94E0E94484C6093600400 +:10314000709361048093620490936304A9C428E19E +:1031500032E03EA32DA3B5E22B2EBAE03B2E85E351 +:103160009AE098A38F8F19EE812E19E0912E10E02E +:10317000EDA1FEA18191FEA3EDA30E94DD0A8823AB +:1031800009F466C0133009F05CC00E94C90A6B01E3 +:103190007C0120E030E040EA51E40E94D44B87FFFC +:1031A0004AC0A7019601F1016081718182819381FA +:1031B0000E94DB4B762EA72EB82E092F762F272FB5 +:1031C0003A2D4B2D502F6091FD097091FE09809191 +:1031D000FF099091000A0E94A94E6093FD09709327 +:1031E000FE098093FF099093000A272D3A2D4B2D5D +:1031F000502FEF8DF8A160817181828193810E94AF +:10320000A94EEF8DF8A16083718382839383F401CB +:1032100060817181828193810E94744C272D3A2DA7 +:103220004B2D502F0E94A94E0E94484CF401608300 +:10323000718382839383F101C082D182E282F3821F +:1032400007C00E94C90AF10160837183828393835E +:103250001F5FF4E02F0E311C2F8D38A12C5F3F4FE4 +:1032600038A32F8F34E0830E911C143009F080CFE7 +:1032700017C4E3ECF2E007C09091C00095FFFCCFCB +:103280008093C600319684918111F6CF09C4EEE592 +:10329000F3E007C09091C00095FFFCCF8093C6007B +:1032A000319684918111F6CF40918F025091900216 +:1032B000609191027091920222E030E081E894E006 +:1032C0000E94FF24E1E6F3E007C09091C00095FF63 +:1032D000FCCF8093C600319684918111F6CF409146 +:1032E000930250919402609195027091960222E0AF +:1032F00030E081E894E00E94FF24E4E6F3E007C0B8 +:103300009091C00095FFFCCF8093C60031968491C8 +:103310008111F6CF409197025091980260919902E5 +:1033200070919A0222E030E081E894E00E94FF244C +:10333000E7E6F3E007C09091C00095FFFCCF8093D3 +:10334000C600319684918111F6CF40919B02509135 +:103350009C0260919D0270919E0222E030E081E823 +:1033600094E00E94FF24EAE6F3E007C09091C000D9 +:1033700095FFFCCF8093C600319684918111F6CFE2 +:103380000E940F400E94764C2091250A3091260A17 +:103390004091270A5091280A0E94DB4BAB01BC01E7 +:1033A00022E030E081E894E00E94FF24E4E7F3E0CB +:1033B00007C09091C00095FFFCCF8093C600319666 +:1033C00084918111F6CF81E00E940F400E94764CDB +:1033D0002091290A30912A0A40912B0A50912C0AF7 +:1033E0000E94DB4BAB01BC0122E030E081E894E0BD +:1033F0000E94FF24E7E7F3E007C09091C00095FF2B +:10340000FCCF8093C600319684918111F6CF82E083 +:103410000E940F400E94764C20912D0A30912E0A76 +:1034200040912F0A5091300A0E94DB4BAB01BC0146 +:1034300022E030E081E894E00E94FF248091C00007 +:1034400085FFFCCF2AC380E001C081E00E9476396D +:1034500027C3EAE7F3E007C09091C00095FFFCCFD7 +:103460008093C600319684918111F6CF189903C0DC +:10347000E4E8F1E009C0E7E8F1E006C09091C0009F +:1034800095FFFCCF8093C60081918111F7CFE1E8D1 +:10349000F3E007C09091C00095FFFCCF8093C60079 +:1034A000319684918111F6CF199903C0E4E8F1E0D7 +:1034B00009C0E7E8F1E006C09091C00095FFFCCF9D +:1034C0008093C60081918111F7CFE8E8F3E007C04F +:1034D0009091C00095FFFCCF8093C60031968491F7 +:1034E0008111F6CF1A9903C0E4E8F1E009C0E7E8DA +:1034F000F1E006C09091C00095FFFCCF8093C6001C +:1035000081918111F7CF8091C00085FFFCCFC5C2AA +:10351000A8E1EA2EA2E0FA2E00E010E0F701819186 +:103520007F010E94DD0A882339F10E94C90AE5E182 +:10353000CE2EEAE0DE2EC00ED11E0E94484CF601CF +:1035400060837183828393830E94C90AF9EECF2E30 +:10355000F9E0DF2EC00ED11EF801EB5DF54F2081A2 +:103560003181428153810E94A94E0E94484CF6014C +:1035700060837183828393830C5F1F4F0031110539 +:1035800069F68EC208E112E065E3E62E6AE0F62EE7 +:10359000F80181918F010E94DD0A882339F00E9491 +:1035A000C90AF7016083718382839383F4E0EF0E8D +:1035B000F11C22E00C31120759F772C283E50E9418 +:1035C000DD0A882351F00E94C90A60930D0A7093A6 +:1035D0000E0A80930F0A9093100A84E50E94DD0A78 +:1035E000882309F45DC20E94C90A6093090A709396 +:1035F0000A0A80930B0A90930C0A52C283E50E9438 +:10360000DD0A882351F00E94C90A6093110A709361 +:10361000120A8093130A9093140A84E50E94DD0A2B +:10362000882351F00E94C90A6093F9097093FA093E +:103630008093FB099093FC0982E40E94DD0A8823B1 +:1036400061F00E94C90A0E94484C6093450A709339 +:10365000460A8093470A9093480A88E50E94DD0A4B +:10366000882351F00E94C90A6093050A7093060AE4 +:103670008093070A9093080A8AE50E94DD0A88234E +:1036800051F00E94C90A6093010A7093020A809364 +:10369000030A9093040A85E40E94DD0A882309F452 +:1036A000FFC10E94C90A6093FD097093FE098093CF +:1036B000FF099093000AF4C108E112E053E8E52EF7 +:1036C00052E0F52EF80181918F010E94DD0A8823D6 +:1036D00039F00E94C90AF701608371838283938362 +:1036E000F4E0EF0EF11C22E00B31120759F7D8C1BC +:1036F00083E50E94DD0A882309F4D2C10E94C90A29 +:103700000E94434C709303016093020181E0809317 +:103710009F02C6C183E50E94DD0A882309F4C0C167 +:103720000E94C90A0E94434C7093010160930001FA +:10373000B7C180E50E94DD0A882351F00E94C90AC2 +:1037400060932E0170932F0180933001909331018B +:1037500089E40E94DD0A882381F00E94C90A25E9D4 +:103760003FEB46ED5DE30E94A94E60932A01709302 +:103770002B0180932C0190932D0184E40E94DD0A9B +:10378000882381F00E94C90A25E93FEB46ED5DE3FD +:103790000E94DB4B609326017093270180932801E0 +:1037A0009093290183E40E94DD0A882351F00E944E +:1037B000C90A60932201709323018093240190939E +:1037C00025010E942940E0EEF1E006C09091C00082 +:1037D00095FFFCCF8093C60081918111F7CFE3EE76 +:1037E000F1E006C09091C00095FFFCCF8093C60029 +:1037F00081918111F7CF40912E0150912F0160915D +:1038000030017091310122E030E081E894E00E94C3 +:10381000FF24E7EEF1E006C09091C00095FFFCCFD9 +:103820008093C60081918111F7CF25E93FEB46EDEA +:103830005DE360912A0170912B0180912C019091A0 +:103840002D010E94DB4BAB01BC0122E030E081E89E +:1038500094E00E94FF24EBEEF1E006C09091C000DE +:1038600095FFFCCF8093C60081918111F7CF25E9A8 +:103870003FEB46ED5DE36091260170912701809159 +:103880002801909129010E94A94EAB01BC0122E0C0 +:1038900030E081E894E00E94FF24EFEEF1E006C002 +:1038A0009091C00095FFFCCF8093C600819181115B +:1038B000F7CF25E93FEB46ED5DE360912201709182 +:1038C000230180912401909125010E94A94EAB0112 +:1038D000BC0122E030E081E894E00E94FF24809166 +:1038E000C00085FFFCCFD9C081E00E94B038D8C0AD +:1038F00083E50E94DD0A882319F00E94C90A04C0EA +:1039000060E070E086E193E40E94E744C9C00E9451 +:10391000B63FC6C080E001C081E00E941C08C0C064 +:10392000109280028091640490916504A0916604D5 +:10393000B091670480933A0490933B04A0933C04B5 +:10394000B0933D040E94170BABC084E50E94DD0AD2 +:10395000882309F461C00E94C90A0E94484C609300 +:103960005F04662389F1EBEBF0E007C09091C000A3 +:1039700095FFFCCF8093C600319684918111F6CFDC +:10398000E3EFF1E006C09091C00095FFFCCF80937B +:10399000C60081918111F7CF40E050E060915F0453 +:1039A00081E894E02DD7E5EFF1E006C09091C000EA +:1039B00095FFFCCF8093C60081918111F7CF809154 +:1039C000C00085FFFCCF69C010928202EBEBF0E0F3 +:1039D00007C09091C00095FFFCCF8093C600319640 +:1039E00084918111F6CFE6E0F2E006C09091C0002C +:1039F00095FFFCCF8093C60081918111F7CF609134 +:103A000082024AE050E070E081E894E035D780918E +:103A1000C00085FFFCCF41C0EBEBF0E007C0909108 +:103A2000C00095FFFCCF8093C60031968491811130 +:103A3000F6CFEFE8F3E007C09091C00095FFFCCF10 +:103A40008093C600319684918111F6CF80912E0427 +:103A500090912F0420E6289FF001299FF00D11245A +:103A6000E655FD4F06C09091C00095FFFCCF8093B6 +:103A7000C60081918111F7CFE1EAF3E007C0909190 +:103A8000C00095FFFCCF8093C600319684918111D0 +:103A9000F6CF8091C00085FFFCCF8AE08093C600FE +:103AA0000E94F80A42C310928F0210929002109264 +:103AB000910210929202109293021092940210922C +:103AC0009502109296022BE932E047E952E063E951 +:103AD00072E08FE892E00E94FC3780E090ECA9E968 +:103AE000B3EC8093460490934704A0934804B093AA +:103AF000490480934A0490934B04A0934C04B093E0 +:103B00004D0420910401309105014091060150912E +:103B1000070120931401309315014093160150932F +:103B20001701C0900801D0900901E0900A01F090BF +:103B30000B01C701B6010E94D44B87FF02C00C9451 +:103B4000C5110C94CD1110928F0210929002109218 +:103B50009102109292022BE932E047E952E063E9C8 +:103B600072E08FE892E00E94FC3780E090ECA9E9D7 +:103B7000B3EC8093460490934704A0934804B09319 +:103B800049046091040170910501809106019091B2 +:103B900007016093140170931501809316019093AF +:103BA000170120E030E040E752E40E94DB4B42E89E +:103BB000C42E42E0D42E7B018C0122E534E04EE499 +:103BC00054E06AE474E086E494E00E947C2D0E9454 +:103BD000B63F10928F0210929002109291021092B2 +:103BE00092022BE932E047E952E063E972E08FE8A4 +:103BF00092E00E94FC3780E090E0A0EAB0E480937D +:103C0000460490934704A0934804B093490420E0ED +:103C100030E040E752E46091140170911501809109 +:103C20001601909117010E94DB4B7B018C0122E56C +:103C300034E04EE454E06AE474E086E494E00E94E8 +:103C40007C2D0E94B63F80E090E0A0E2B1EC809332 +:103C5000460490934704A0934804B093490420E09D +:103C600030E040E05FE360910401709105018091D4 +:103C70000601909107010E94A94EFB01462F5F2F7C +:103C8000682F792F4093140150931501609316010A +:103C90007093170120E030E040E752E4BF010E943A +:103CA000DB4B7B018C0122E534E04EE454E06AE416 +:103CB00074E086E494E00E947C2D0E94B63F10924E +:103CC0008F02109290021092910210929202109222 +:103CD000460410924704109248041092490410922E +:103CE00014011092150110921601109217010E94F2 +:103CF0006F390C9457121092930210929402109202 +:103D00009502109296022BE932E047E952E063E90E +:103D100072E08FE892E00E94FC3780E090ECA9E925 +:103D2000B3EC80934A0490934B04A0934C04B0935B +:103D30004D04609108017091090180910A019091F0 +:103D40000B016093140170931501809316019093F9 +:103D5000170120E030E040E752E40E94DB4B32E8FC +:103D6000C32E32E0D32E7B018C0122E534E04EE4F9 +:103D700054E06AE474E086E494E00E947C2D0E94A2 +:103D8000B63F1092930210929402109295021092F4 +:103D900096022BE932E047E952E063E972E08FE8EE +:103DA00092E00E94FC3780E090E0A0EAB0E48093CB +:103DB0004A0490934B04A0934C04B0934D0420E02C +:103DC00030E040E752E46091140170911501809158 +:103DD0001601909117010E94DB4B7B018C0122E5BB +:103DE00034E04EE454E06AE474E086E494E00E9437 +:103DF0007C2D0E94B63F80E090E0A0E2B1EC809381 +:103E00004A0490934B04A0934C04B0934D0420E0DB +:103E100030E040E05FE3609108017091090180911A +:103E20000A0190910B010E94A94EFB01462F5F2FC2 +:103E3000682F792F40931401509315016093160158 +:103E40007093170120E030E040E752E4BF010E9488 +:103E5000DB4B7B018C0122E534E04EE454E06AE464 +:103E600074E086E494E00E947C2D0E94B63F10929C +:103E70009302109294021092950210929602109260 +:103E80004A0410924B0410924C0410924D0410926C +:103E900014011092150110921601109217010E9440 +:103EA0006F390C946112109297021092980210923E +:103EB000990210929A022BE932E047E952E063E955 +:103EC00072E08FE892E00E94FC3780E090E0A4E38B +:103ED000B3EC80934E0490934F04A0935004B0939E +:103EE000510460910C0170910D0180910E0190912F +:103EF0000F01609314017093150180931601909344 +:103F0000170120E030E040E752E40E94DB4B22E85A +:103F1000C22E22E0D22E7B018C0122E534E04EE459 +:103F200054E06AE474E086E494E00E947C2D0E94F0 +:103F3000B63F109297021092980210929902109236 +:103F40009A022BE932E047E952E063E972E08FE838 +:103F500092E00E94FC3780E090E0A0E8BFE380930D +:103F60004E0490934F04A0935004B093510420E06A +:103F700030E040E752E460911401709115018091A6 +:103F80001601909117010E94DB4B7B018C0122E509 +:103F900034E04EE454E06AE474E086E494E00E9485 +:103FA0007C2D0E94B63F80E090E0A0E0B0EC8093D2 +:103FB0004E0490934F04A0935004B093510420E01A +:103FC00030E040E05FE360910C0170910D01809161 +:103FD0000E0190910F010E94A94EFB01462F5F2F09 +:103FE000682F792F409314015093150160931601A7 +:103FF0007093170120E030E040E752E4BF010E94D7 +:10400000DB4B7B018C0122E534E04EE454E06AE4B2 +:1040100074E086E494E00E947C2D0E94B63F1092EA +:104020009702109298021092990210929A0210929E +:104030004E0410924F0410925004109251041092AA +:1040400014011092150110921601109217010E948E +:104050006F390C946B120E94C90A0E94434C8B0169 +:10406000ECE1F2E00C94861443D16B017C010C94DA +:1040700072173ED160935B0470935C0480935D047F +:1040800090935E0435D160933E0470933F04809317 +:1040900040049093410404CD2BD1681979098A0911 +:1040A0009B09693E73408105910510F00C947616CA +:1040B0000C94F6160E94B63F5A980E942340F0CC0A +:1040C0000E94B63F88E50E94DD0A81111CC81CC809 +:1040D000E62FF0E0EE0FFF1FE655F54F808191814E +:1040E0000E94164169A37AA38BA39CA360915F04ED +:1040F000E62FF0E0EE0FFF1FE255F54F8081918132 +:104100000E94164120E030E040E85FE30E94FB4A55 +:104110009B01AC0169A17AA18BA19CA10E94D44B07 +:1041200018160CF0A1CF0C947217A6960FB6F8943F +:10413000DEBF0FBECDBFDF91CF911F910F91FF90DA +:10414000EF90DF90CF90BF90AF909F908F907F9037 +:104150006F905F904F903F902F9008958091A602AE +:104160009091A702039714F40E94420B8091A6023B +:104170009091A702892BC1F00E949B108091A6020A +:104180009091A70201979093A7028093A602809135 +:104190002E0490912F04019664E070E00E948E4FEF +:1041A00090932F0480932E040E94E24181E00E94AC +:1041B00038100C94B3380E94BB4480918002811166 +:1041C00034C081E08093800280913A0490913B0456 +:1041D000A0913C04B0913D048093640490936504E5 +:1041E000A0936604B0936704E5E7F1E007C09091FF +:1041F000C00095FFFCCF8093C60031968491811159 +:10420000F6CFEFECF3E007C09091C00095FFFCCF34 +:104210008093C600319684918111F6CF8091C000C1 +:1042200085FFFCCF8AE08093C600089580918002CC +:104230000895E82FF0E0E95BFB4FE491E650E230AF +:1042400060F48091B1008C7F8093B1008091B100C7 +:1042500067707727862B8093B10008959FD00E94C6 +:104260002D097CDFFECF1F920F920FB60F92112403 +:104270002F933F938F939F93AF93BF938091780435 +:1042800090917904A0917A04B0917B0430918004DC +:10429000232F2A592D3720F02D570196A11DB11D2E +:1042A000209380048093780490937904A0937A04F7 +:1042B000B0937B0480917C0490917D04A0917E0456 +:1042C000B0917F040196A11DB11D80937C04909351 +:1042D0007D04A0937E04B0937F04BF91AF919F9122 +:1042E0008F913F912F910F900FBE0F901F901895B7 +:1042F0000F931F938FB7F89400917804109179046D +:1043000020917A0430917B048FBFB801C9011F91BD +:104310000F9108959FB7F89440917C0450917D04CB +:1043200060917E0470917F0486B5A89B06C08F3F84 +:1043300021F04F5F5F4F6F4F7F4F9FBF2227342F7A +:10434000452F562F280F311D411D511DA3E0B0E010 +:104350000C946F4FCF92DF92EF92FF92CF93DF9347 +:104360006B017C01D7DFEB010DC0D4DF6C1B7D0B33 +:10437000683E734038F081E0C81AD108E108F108BE +:10438000C851DC4FC114D104E104F10471F7DF918D +:10439000CF91FF90EF90DF90CF900895789484B5FF +:1043A000826084BD84B5816084BD85B5826085BD31 +:1043B00085B5816085BDEEE6F0E080818160808317 +:1043C000E1E8F0E0108280818260808380818160FA +:1043D0008083E0E8F0E0808181608083E1EBF0E0C1 +:1043E000808184608083E0EBF0E080818160808365 +:1043F000EAE7F0E08081846080838081826080834E +:104400008081816080838081806880831092C10078 +:1044100008951F93CF93DF93182FEB0161E082D0B3 +:10442000209711F460E004C0CF3FD10531F461E082 +:10443000812FDF91CF911F9191C0E12FF0E0E95BD7 +:10444000FB4FE491E330B9F028F4E13051F0E23071 +:10445000B1F50CC0E63019F1E73049F1E43079F5F7 +:1044600014C084B5806884BDC7BD2EC084B5806289 +:1044700084BDC8BD29C08091800080688093800081 +:10448000D0938900C09388001FC080918000806213 +:1044900080938000D0938B00C0938A0015C08091D8 +:1044A000B00080688093B000C093B3000DC08091CD +:1044B000B00080628093B000C093B40005C0C038E3 +:1044C000D1050CF0B4CFAECFDF91CF911F910895FD +:1044D000833069F028F48130A1F0823011F514C0E6 +:1044E0008630B1F08730C1F08430D9F404C08091B7 +:1044F00080008F7703C0809180008F7D8093800043 +:10450000089584B58F7702C084B58F7D84BD0895EA +:104510008091B0008F7703C08091B0008F7D809331 +:10452000B000089590E0FC01E959FB4F2491FC0193 +:10453000E957FB4FE491EE2381F0F0E0E455FB4FA7 +:10454000A491B0E09FB7F8948C91611103C02095BD +:10455000822301C0822B8C939FBF08950F931F93DA +:10456000CF93DF931F92CDB7DEB7A82FB0E0FD0148 +:10457000E95BFB4F8491FD01E959FB4F1491FD016B +:10458000E957FB4F04910023B1F0882319F06983A8 +:104590009FDF6981E02FF0E0E955FB4FA491B0E087 +:1045A0009FB7F8948C91611103C01095812301C0CD +:1045B000812B8C939FBF0F90DF91CF911F910F9113 +:1045C00008951F920F920FB60F9211242F933F93CD +:1045D0004F935F936F938F939F93EF93FF936091AC +:1045E000C6002091020530910305C90101968F771D +:1045F000992740910405509105058417950741F0CE +:10460000F901EE57FB4F60839093030580930205F9 +:10461000FF91EF919F918F916F915F914F913F919A +:104620002F910F900FBE0F901F9018959A01AB011C +:1046300082E08093C00060E47BE48CE490E00E9420 +:10464000C34F2150310941095109CA01B90122E082 +:1046500030E040E050E00E94C34F832F99278093C1 +:10466000C5002093C400E1ECF0E08081806180838C +:1046700080818860808380818068808308958091B4 +:104680000405909105052091020530910305281736 +:10469000390769F0FC01EE57FB4F208101968F77B7 +:1046A0009927909305058093040530E002C02FEF11 +:1046B0003FEFC901089580910405909105059093FD +:1046C00003058093020508956F927F928F929F92C7 +:1046D000AF92BF92CF92DF92EF92FF920F931F9310 +:1046E000CF93DF93CDB7DEB7A0970FB6F894DEBFB8 +:1046F0000FBECDBF8C014115510561057105C1F497 +:1047000040E050E060E3A0960FB6F894DEBF0FBE25 +:10471000CDBFDF91CF911F910F91FF90EF90DF9070 +:10472000CF90BF90AF909F908F907F906F90ABC0D5 +:1047300066246394712C6C0E7D1EC12CD12C7601E5 +:10474000822E912CA12CB12CCB01BA01A501940190 +:104750000E94A14FFA01D3016D933D01BFEFCB1A27 +:10476000DB0AEB0AFB0AA901BF01411551056105EE +:10477000710551F781E0C81AD108E108F10815C0A8 +:10478000E1E0F0E0EC0FFD1FEC0DFD1D60816A30F3 +:1047900010F4605D01C0695C40E050E0C80173D076 +:1047A000A1E0CA1AD108E108F108BFEFCB16DB0679 +:1047B000EB06FB0629F7A0960FB6F894DEBF0FBEF6 +:1047C000CDBFDF91CF911F910F91FF90EF90DF90C0 +:1047D000CF90BF90AF909F908F907F906F900895F3 +:1047E0002115310539F48091C00085FFFCCF40933D +:1047F000C600089569CF9A01AB0160E070E0F0CF88 +:104800009A01462F50E060E070E0EACFCF92DF924D +:10481000EF92FF92CF93DF93EC016A017B012115A8 +:10482000310539F48091C00085FFFCCFC092C600ED +:104830001CC02A30310579F477FF0CC040E050E00D +:104840006DE221D0F094E094D094C094C11CD11CAE +:10485000E11CF11C2AE0B701A601CE01DF91CF9146 +:10486000FF90EF90DF90CF902FCFDF91CF91FF900F +:10487000EF90DF90CF9008959A01AB01662757FD26 +:104880006095762FC3CF9A01462F50E060E070E02C +:10489000BDCFCF93DF93EC0140E050E06DE0F3DF5C +:1048A00040E050E06AE0CE01DF91CF91ECCFCF93B2 +:1048B000DF93EC01A0DFCE01DF91CF91EACF8F92A1 +:1048C0009F92AF92BF92CF92DF92EF92FF920F939F +:1048D0001F93CF93DF938C014A015B01C22F20E02D +:1048E00030E0A901C501B4010E94D44B87FF09C083 +:1048F00040E050E06DE2C801C6DFB7FAB094B7F807 +:10490000B094D0E060E070E080E09FE307C020E07A +:1049100030E040E251E40E94DB4BDF5FDC13F7CF75 +:10492000262F372F482F592FC501B4010E94FB4A6B +:10493000D62EE72EF82ED92F0E94484C962EA72E61 +:10494000B82EC92E0E94744C9B01AC016D2D7E2D9A +:104950008F2D9D2F0E94FA4AD62FF72EE82ED92EA2 +:104960002AE030E0492D5A2D6B2D7C2DC80138DF0F +:10497000CC23B1F1E6E5F2E006C09091C00095FFCE +:10498000FCCF8093C60081918111F7CF29C020E030 +:1049900030E040E251E46D2F7F2D8E2D9D2D0E9441 +:1049A000A94E6B017C017D2D9F2D0E94434C5B0124 +:1049B0004AE050E0C80160DFB501882777FD8095A7 +:1049C000982F0E94764C9B01AC016C2D7D2D8E2D75 +:1049D0009F2D0E94FA4AD62FF72EE82ED92EC150CD +:1049E000C111D5CFDF91CF911F910F91FF90EF9023 +:1049F000DF90CF90BF90AF909F908F9008955FCF42 +:104A00002F923F924F925F926F927F928F929F92DE +:104A1000AF92BF92CF92DF92EF92FF920F931F93CC +:104A2000CF93DF93CDB7DEB7CA54D1090FB6F89450 +:104A3000DEBF0FBECDBF1C017E8B6D8B3A012BA359 +:104A40000EA3E8A6AEAABFAAC8AED9AE34E0239F93 +:104A500080011124400F511F5BAB4AABDA018D90EE +:104A60009D90AD90BC90FC01E00FF11F2081318141 +:104A700042815381C501B4010E94FB4A6AAF7BAFFA +:104A80008CAF9DAFEEA1B4E0EB9F700111249301B8 +:104A90002E0D3F1D3DAB2CABD9014D905D906D901F +:104AA0007C90F101EE0DFF1D208131814281538107 +:104AB000C301B2010E94FB4A6EAF7FAF21968FAF58 +:104AC000219722969FAF2297E8A5B4E0EB9FC00103 +:104AD0001124F101E80FF91F2081318142815381B6 +:104AE0002B8F3C8F4D8F5E8FED89FE89E80FF91F6C +:104AF00060817181828193810E94FA4A462F572FEB +:104B0000682F792F498B5A8B6B8B7C8BAD89BE8933 +:104B10001C968D919D910D90BC91A02D8AA79BA76D +:104B2000ACA7BDA7D1011C962D913D914D915C91F3 +:104B30001F972F8F38A349A35AA3B7FAB094B7F899 +:104B4000B09477FA709477F87094ED89FE89E00F4D +:104B5000F11F7AAD6BAD9CAD8DAD272F362F492F50 +:104B6000582F60817181828193810E94FA4A6F8BF4 +:104B7000788F898F9DA3ED89FE89EE0DFF1D7EAD97 +:104B80006FAD21969FAD219722968FAD2297272F4B +:104B9000362F492F582F60817181828193810E9425 +:104BA000FA4A162F072F382E292E7F89688D998D66 +:104BB0008DA1272F362F492F582FC501B4010E94F0 +:104BC000A94E6B017C01B801C101272F362F492F57 +:104BD000582FC301B2010E94A94E9B01AC01C7012D +:104BE000B6010E94FB4A6B017C01B801C101272F6D +:104BF000362F492F582FC501B4010E94A94E6EA728 +:104C00007FA788AB99AB7F89688D998D8DA1272F60 +:104C1000362F492F582FC301B2010E94A94E9B0184 +:104C2000AC016EA57FA588A999A90E94FA4AA7019F +:104C300096010E946E4B362E272E182F092F20E04A +:104C400030E0A901D101F8016B2F7A2F8F2F9E2F11 +:104C50000E94D44B87FF10C02BED3FE049EC50E49D +:104C6000D101F8016B2F7A2F8F2F9E2F0E94FB4AC4 +:104C7000362E272E182F092FA4968FADA4978823A0 +:104C800081F02BED3FE049EC50E4D101F8016B2FAE +:104C9000722D8F2F902F0E94FA4A362E272E182F12 +:104CA000092FC988DA88EB88FC88E894F7F8A3967E +:104CB0002CAD3DAD4EAD5FADA397D101F8016B2F8B +:104CC000722D8F2F902F0E94A94EA70196010E944E +:104CD000E44D6B017C012FE632E143E85AE30E9488 +:104CE000D44B87FD79C2C701B6010E94B14C0E9426 +:104CF000484C7A8F698FFB01EF2B21F421E030E0E3 +:104D00003A8F298F498D5A8DBA0180E090E00E9438 +:104D1000744C6B017C019B01AC01D101F8016B2F3C +:104D2000722D8F2F902F0E94DB4B6F8B788F1C0181 +:104D3000A701960169897A898B899C890E94DB4B3E +:104D400024966FAF249725967FAF259726968FAF31 +:104D5000269727969FAF27972F8D38A149A15AA153 +:104D60006AA57BA58CA59DA50E94FA4AA70196017C +:104D70000E94DB4B28966FAF289729967FAF299723 +:104D80002A968FAF2A972B969FAF2B9720E030E083 +:104D900040E05FE3BF89A88D6B2F7A2F822D932D82 +:104DA0000E94A94EBF89A88D2B2F3A2F422D532D3B +:104DB0000E94A94E9B01AC0160E070E080E89FE397 +:104DC0000E94FA4A6DA37AA78EA723969FAF2397D6 +:104DD000CE010196FC01A8A554E0A59FE00DF11DB0 +:104DE00011242B8D3C8D4D8D5E8D2083318342832C +:104DF00053832F8D38A149A15AA12D873E874F8714 +:104E0000588B198A41E050E05C8F4B8F81E090E035 +:104E10008C0F9D1FBBA1A4E0BA9F800D911D112492 +:104E200099A788A721E030E02C0F3D1F5EA144E048 +:104E3000549F200D311D11243FA32EA3FCA3EBA3EF +:104E4000ABC1898989310CF050C07F89688D272FCB +:104E5000362F422D532DC501B4010E94A94E6B017E +:104E60007C017DA16AA59EA523968FAD2397272F50 +:104E7000362F492F582FC301B2010E94A94E9B0122 +:104E8000AC01C701B6010E94FB4A7B018C017DA1E8 +:104E90006AA59EA523968FAD2397272F362F492FDE +:104EA000582FC501B4010E94A94E5B016C017F8996 +:104EB000688D272F362F422D532DC301B2010E943A +:104EC000A94E9B01AC016A2D7B2D8C2D9D2D0E943E +:104ED000FA4A862E972EA82EB92E99899F5F998B14 +:104EE0004E2C5F2C602E712E72C0AB8DBC8DBD011F +:104EF00080E090E00E94744CBF89A88D2B2F3A2F40 +:104F0000422D532D0E94A94E7B018C017F2D802FB5 +:104F1000912F0E94D84B2B013C016E2D7F2D802FAD +:104F2000912F0E940C4F698B7A8B8B8B9C8BEAA9FB +:104F3000FBA980819181A281B3819C01AD01505870 +:104F40002F8F38A349A35AA3ACA9BDA9CD90DD905A +:104F5000ED90FC90A30192016F8D78A189A19AA197 +:104F60000E94A94E4B015C0129893A894B895C89D1 +:104F7000C701B6010E94A94E9B01AC01C501B40155 +:104F80000E94FB4A862E972EA82EB92E29893A898F +:104F90004B895C896F8D78A189A19AA10E94A94E45 +:104FA000698B7A8B8B8B9C8BA3019201C701B60115 +:104FB0000E94A94E9B01AC0169897A898B899C89E1 +:104FC0000E94FA4A462E572E682E792E198AA5017C +:104FD0009401BAADABADFCADEDAD6B2F7A2F8F2F39 +:104FE0009E2F0E94FB4AE8A5F9A560837183828306 +:104FF0009383A3019201BEADAFAD2196FFAD219782 +:105000002296EFAD22976B2F7A2F8F2F9E2F0E9423 +:10501000FB4AAEA1BFA16D937D938D939C93139793 +:1050200024967FAD249725966FAD259726969FAD44 +:10503000269727968FAD2797272F362F492F582F42 +:10504000EBA1FCA160817181828193810E94FB4A66 +:10505000ABA1BCA16D937D938D939C9313972896E0 +:105060007FAD289729966FAD29972A969FAD2A97ED +:105070002B968FAD2B97272F362F492F582F6D85C5 +:105080007E858F8598890E94FB4A6D877E878F87F2 +:10509000988B20E030E0A90169817A818B819C8125 +:1050A0000E94D44B87FF04C019821A821B821C8283 +:1050B00020E030E0A9016D817E818F8198850E947A +:1050C000D44B87FF04C01D821E821F82188620E0F9 +:1050D00030E0A90169857A858B859C850E94D44B37 +:1050E00087FF04C019861A861B861C8620E030E0E4 +:1050F0004DE453E469817A818B819C810E94D74D74 +:10510000181644F480E090E0ADE4B3E489839A8318 +:10511000AB83BC8320E030E04DE453E46D817E81BD +:105120008F8198850E94D74D181644F480E090E056 +:10513000ADE4B3E48D839E83AF83B88720E030E095 +:1051400040EF52E469857A858B859C850E94D74D16 +:10515000181644F480E090E0A0EFB2E489879A87C3 +:10516000AB87BC8794E6C92ED12CCC0EDD1EEEA8F1 +:10517000FFA808AD19AD9E01235F3F4FAE01475F09 +:105180005F4FBE016B5F7F4FCE010196B5D4EB8DB3 +:10519000FC8D3196FC8FEB8F2B8D3C8D498D5A8D7C +:1051A0002417350708F44DCE2D893E89245F3F4FE3 +:1051B0004D895E89485F5F4F6D897E896C5F7F4F47 +:1051C00084E6C82ED12CCC0EDD1EEEA8FFA808ADBB +:1051D00019AD8D899E8990D4C65BDF4F0FB6F894C8 +:1051E000DEBF0FBECDBFDF91CF911F910F91FF901A +:1051F000EF90DF90CF90BF90AF909F908F907F9077 +:105200006F905F904F903F902F9008958F5F803107 +:1052100009F480E008952F923F924F925F926F922F +:105220007F928F929F92AF92BF92CF92DF92EF9236 +:10523000FF920F931F93CF93DF93CDB7DEB768979D +:105240000FB6F894DEBF0FBECDBF1C014A015B0153 +:1052500068017901DC01D8966D917D918D919C91C9 +:10526000DB970E94744C69837A838B839C83A501AE +:1052700094010E94A94E0E94C14B0E94484C6D832C +:105280007E838F839887A701960169817A818B81BC +:105290009C810E94A94E0E94C14B0E94484C698784 +:1052A0007A878B879C872D813E814F81588528374F +:1052B00031054105510540F488E790E0A0E0B0E0F9 +:1052C0008D839E83AF83B88729853A854B855C851E +:1052D000283731054105510540F488E790E0A0E00A +:1052E000B0E089879A87AB87BC87F101EC5BFF4F01 +:1052F0004080518062807380C301B2010E94764C6D +:105300006B017C01D101DC966D917D918D919C9119 +:10531000DF970E94744C6D877E878F87988B20E083 +:1053200030E0A901C701B6010E94D44B882339F1AE +:1053300029813A814B815C81CA01B9010E94A94E41 +:105340004B015C012D853E854F855889CA01B90105 +:105350000E94A94E9B01AC01C501B4010E94FA4A0A +:105360004B015C01A7019601C701B6010E94FB4AEF +:105370009B01AC01C501B4010E94DB4B04C060E09D +:1053800070E080E090E00E94C14B0E94434C4B01D2 +:105390005C0166277727CB0164197509860997098F +:1053A0000E94764C2B013C01F101E05CFF4F6081D3 +:1053B0007181828193810E94744C698B7A8B8B8B73 +:1053C0009C8B20E030E0A901C301B2010E94D44BC4 +:1053D000882379F129893A894B895C89CA01B90105 +:1053E0000E94A94E6D8B7E8B8F8B988F29813A817D +:1053F0004B815C81CA01B9010E94A94E9B01AC019D +:105400006D897E898F89988D0E94FA4A69837A8393 +:105410008B839C83A3019201C301B2010E94FB4ACA +:105420009B01AC0169817A818B819C810E94DB4B5D +:1054300004C060E070E080E090E00E94B14CD101D7 +:1054400050962D913D914D915C91539729833A83CC +:105450004B835C8329013A01481859086A087B0884 +:105460000E94434C461A570A680A790A77FE6CC0B4 +:1054700020E030E0A901C701B6010E94D44B882387 +:1054800009F445C0A7019601C701B6010E94FB4A75 +:105490002B013C0169817A818B819C810E94744C33 +:1054A0009B01AC01C301B2010E94A94E2B013C013A +:1054B0002D853E854F855889CA01B9010E94A94EA4 +:1054C0009B01AC01C301B2010E94FA4A2B013C01CD +:1054D00029893A894B895C89CA01B9010E94A94E80 +:1054E0009B01AC01C301B2010E94FB4A4B015C016C +:1054F00020E030E040E850E4C701B6010E94A94E28 +:105500009B01AC01C501B4010E94DB4B04C060E00B +:1055100070E080E090E00E94C14B0E94434C4B0140 +:105520005C01B7FE03C0812C912C540129813A8182 +:105530004B815C8182169306A406B50610F04901E2 +:105540005A01412C512C32018FB7F894F101E45BE0 +:10555000FF4F9081911125C0D10154968D929D925B +:10556000AD92BC925797480C591C6A1C7B1CF101E8 +:10557000408E518E628E738E2D813E814F81588573 +:10558000DC962D933D934D935C93DF97A05CBF4FCA +:1055900029853A854B855C852D933D934D935C938E +:1055A00013978FBF68960FB6F894DEBF0FBECDBFBE +:1055B000DF91CF911F910F91FF90EF90DF90CF90EF +:1055C000BF90AF909F908F907F906F905F904F9023 +:1055D0003F902F900895AF92BF92CF92DF92EF92BB +:1055E000FF920F931F93CF93DF935B017A016115B5 +:1055F000710509F475C04115510509F471C0FB012D +:1056000002A513A5D4A5C5A5CE01202F312F492F62 +:10561000582F66A177A180A591A50E94D44B88231D +:1056200009F45EC0F50187A981114BC0F701C6A03E +:10563000D7A0E0A4F1A4A7019601DE01602F712F8D +:105640008B2F9A2F0E94D74D1816DCF5A7019601D3 +:10565000C701B6010E94A94E6B017C01F50182A928 +:1056600093A9A4A9B5A9BC01CD0190589B01AC0197 +:105670000E94FB4AF50126A537A540A951A90E9421 +:10568000A94E9B01AC01C701B6010E94FA4A0E94D3 +:10569000164F6B017C01762F272F3D2D4E2D5F2D50 +:1056A000FE01602F712F8F2F9E2F0E94D44B87FFFA +:1056B00003C06801ED2EFC2E5C2D4D2D3E2D2F2DAF +:1056C00003C0502F412F9E01852F942FA32FB22F5F +:1056D000F50186A397A3A0A7B1A781E0F50186AB4A +:1056E000DF91CF911F910F91FF90EF90DF90CF90BE +:1056F000BF90AF900895CF92DF92FF920F931F93C8 +:10570000CF93DF931F92CDB7DEB7809108058091CC +:1057100008052091070590E0821B91098F70992759 +:1057200004970CF12091080523502F7040E050E0C1 +:1057300000E010E08DE4F82E12C0211101C020E13C +:105740002150F29E6001112489E095E0C80ED91E17 +:10575000B801C60129833FDFA80186012981809114 +:1057600007052813EACF0F90DF91CF911F910F917A +:10577000FF90DF90CF9008952F923F924F925F92CB +:105780006F927F928F929F92AF92BF92CF92DF9251 +:10579000EF92FF920F931F93CF93DF93EC011B01C6 +:1057A000009709F464C08FA9811161C08EA09FA0E9 +:1057B000A8A4B9A4FB01C6A0D7A0E0A4F1A42C2DF5 +:1057C0003D2D4E2D5F2DC501B4010E94D44B87FFA6 +:1057D0004EC0A5019401C501B4010E94A94E2B0140 +:1057E0003C018AA89BA8ACA8BDA8C501B4019058EB +:1057F0009B01AC010E94FB4A2EA53FA548A959A9CF +:105800000E94A94E9B01AC01C301B2010E94FA4A59 +:105810000E94164F8B01D82FC92F762FCE01272F2C +:10582000312F492F582F6C2D7D2D8E2D9F2D0E94AD +:10583000D44B87FF03C08601DE2DCF2DCE01202F54 +:10584000312F492F5C2F6C2D7D2D8E2D9F2D0E9489 +:10585000D44B882361F09E01802F912FA32FBC2F62 +:10586000F10186A397A3A0A7B1A781E086ABDF9142 +:10587000CF911F910F91FF90EF90DF90CF90BF904D +:10588000AF909F908F907F906F905F904F903F90E0 +:105890002F900895EF92FF920F931F93CF93DF9372 +:1058A000F0900705C0E0D0E080E090E02DE4E22E2B +:1058B0000DC0EF9C80011124075F1A4FA801BE01A3 +:1058C0005BDF8F2DA3DCF82ECE01E80120910805C7 +:1058D000F212EFCF40E050E0BE01DF91CF911F9177 +:1058E0000F91FF90EF9048CF4F925F926F927F920F +:1058F0008F929F92AF92BF92CF92DF92EF92FF92E0 +:105900000F931F93CF93DF9350900705C0E0D0E033 +:105910003DE4432E34C0429E3001439E700C11245E +:1059200089E095E0680E791E209729F18EA98111F2 +:1059300004C0F30186A98823F1F0CAA0DBA0ECA083 +:10594000FDA0A7019601F30166A177A180A591A50D +:105950000E94DB4B4B015C01A70196016EA17FA168 +:1059600088A599A50E94DB4BAB01BC019501840180 +:10597000CE0151DC1EAA852D49DC582EE301252DD0 +:10598000332727FD30958091080590E028173907C7 +:1059900009F0C1CF2097E9F0CAA0DBA0ECA0FDA0E0 +:1059A000A70196016DEC7CEC8CE49DE30E94DB4B3F +:1059B0004B015C01A70196016EA17FA188A599A565 +:1059C0000E94DB4BAB01BC0195018401CE0123DCBD +:1059D0001EAADF91CF911F910F91FF90EF90DF9062 +:1059E000CF90BF90AF909F908F907F906F905F907F +:1059F0004F90089580DE4EDF77CF10920805109209 +:105A0000070580E1E9EDF9E0DF011D928A95E9F7EC +:105A10001092490A10924A0A10924B0A10924C0AAC +:105A200010924D0A10924E0A10924F0A1092500A8C +:105A30001092510A1092520A1092530A1092540A6C +:105A40001092550A1092560A1092570A1092580A4C +:105A50001092590A10925A0A10925B0A10925C0A2C +:105A60000895CF939091070580910805981709F143 +:105A7000209107058DE4289FF0011124EF5AFA4F79 +:105A8000C08130E04DE410C0429FF0011124EF5A74 +:105A9000FA4F80819181A281B381892B8A2B8B2B34 +:105AA00009F03F5F2F5F2F70809108052813ECCF1E +:105AB0000AC060918102662321F070E08EE00E94AE +:105AC0000922C0E030E080918102811107C03111CC +:105AD00005C060E070E08EE00E94092280918102A2 +:105AE000882341F0CC2331F06C2F70E08EE0CF9111 +:105AF0000C940922CF9108952F923F924F925F927A +:105B00006F927F928F929F92AF92BF92CF92DF92CD +:105B1000EF92FF920F931F93CF93DF93CDB7DEB732 +:105B2000CD56D1090FB6F894DEBF0FBECDBF2C0104 +:105B30003B014A015901EFA6FBAA0CAB19AFDEAE3F +:105B4000CDAE8091080562DBAA968FAFAA97082F89 +:105B5000112707FD109505C00E94E24181E00E94D7 +:105B600038108091070590E080179107A9F32091E4 +:105B7000250A3091260A4091270A5091280AD2011D +:105B80006D917D918D919C910E94A94E0E94794EBC +:105B900060966FAF609761967FAF619762968FAFA7 +:105BA000629763969FAF63972091290A30912A0AE2 +:105BB00040912B0A50912C0AF301608171818281FE +:105BC00093810E94A94E0E94794E64966FAF6497AC +:105BD00065967FAF659766968FAF669767969FAF1E +:105BE000679720912D0A30912E0A40912F0A5091EB +:105BF000300AD4016D917D918D919C910E94A94EA6 +:105C00000E94794E68966FAF689769967FAF6997E3 +:105C10006A968FAF6A976B969FAF6B972091310A08 +:105C20003091320A4091330A5091340AF501608173 +:105C30007181828193810E94A94E0E94794E2296A1 +:105C40006FAF229723967FAF239724968FAF249729 +:105C500025969FAF25978091E5099091E609A0913F +:105C6000E709B091E80925962CAD3DAD4EAD5FAD8D +:105C70002597281739074A075B07C1F1609182020F +:105C8000E62FF0E0EE0FFF1FE655F54F8081918182 +:105C90000E94164120E030E046E153E40E94D44BDC +:105CA00087FF24C080910605811120C00C94D03755 +:105CB0009091C00095FFFCCF8093C60031968491EF +:105CC0008111F6CFE7EBF4E007C09091C00095FF9B +:105CD000FCCF8093C600319684918111F6CF8091DC +:105CE000C00085FFFCCF8AE08093C6008091E50963 +:105CF0009091E609A091E709B091E80925962CADAD +:105D00003DAD4EAD5FAD2597281B390B4A0B5B0BA4 +:105D1000CA01B90157FF07C09095809570956195AC +:105D20007F4F8F4F9F4F0E94764C4B015C0120E0CC +:105D300030E04DEC53E46091310A7091320A809169 +:105D4000330A9091340A0E94A94E9B01AC01C5010F +:105D5000B4010E94D74D18167CF525968CAD9DADEB +:105D6000AEADBFAD25978093E5099093E609A0936A +:105D7000E709B093E809E1EBF4E007C09091C000B7 +:105D800095FFFCCF8093C600319684918111F6CFA8 +:105D9000E1EDF4E007C09091C00095FFFCCF809347 +:105DA000C600319684918111F6CF8091C00085FFA5 +:105DB000FCCF8AE08093C600809108059DE4899F0E +:105DC00010011124A9E0B5E02A0E3B1EF101E45BAD +:105DD000FF4F10822091D9093091DA094091DB09F7 +:105DE0005091DC092BA33CA34DA35EA363964CAC5E +:105DF0005DAC6EAC7FAC6397421A530A640A750AB5 +:105E000077FE08C07094609450944094411C511CDB +:105E1000611C711CD1014D925D926D927C92139721 +:105E20002091DD093091DE094091DF095091E009B0 +:105E30002FA338A749A75AA767968CAC9DACAEACE8 +:105E4000BFAC6797821A930AA40AB50AB7FE08C0C6 +:105E5000B094A09490948094811C911CA11CB11CBE +:105E6000D10114968D929D92AD92BC92179720917C +:105E7000E1093091E2094091E3095091E4092BA72F +:105E80003CA74DA75EA76B964CAD5DAD6EAD7FADEB +:105E90006B978BA59CA5ADA5BEA5481B590B6A0B9E +:105EA0007B0B77FF07C070956095509541955F4FCC +:105EB0006F4F7F4F142F052F26966FAF26977DAB20 +:105EC000D10118964C93189719965C9319971A96C6 +:105ED0006C931A971B967C93C090E509D090E609C5 +:105EE000E090E709F090E809A0910001B09101016C +:105EF00025962CAD3DAD4EAD5FAD25972C193D09D6 +:105F00004E095F0957FF07C0509540953095219580 +:105F10003F4F4F4F5F4F0E94794F24E630E040E003 +:105F200050E00E94C34FF101248735874687578789 +:105F3000812F902F2696AFAD2697BDA9881599057C +:105F4000AA05BB0514F4D501C40182179307A40761 +:105F5000B50714F4DA01C901930182014816590604 +:105F60006A067B0614F48C019D01D10150960D93B5 +:105F70001D932D933C935397063011052105310550 +:105F800010F40C94E237F101E85BFF4F809181023D +:105F900090E0A0E0B0E080839183A283B383639616 +:105FA0002CAD3DAD4EAD5FAD63978BA19CA1ADA176 +:105FB000BEA1281739074A075B0724F0D101909644 +:105FC0001C9203C081E0F10180A367962CAD3DAD2A +:105FD0004EAD5FAD67978FA198A5A9A5BAA5281763 +:105FE00039074A075B073CF4D10190968C91909752 +:105FF000826090968C936B962CAD3DAD4EAD5FADAF +:106000006B978BA59CA5ADA5BEA5281739074A0798 +:106010005B073CF4D10190968C91909784609096A8 +:106020008C9325962CAD3DAD4EAD5FAD25972C15CF +:106030003D054E055F053CF4D10190968C919097FB +:10604000886090968C93EDADFEAD8081D1019196E4 +:106050008C9345284628472809F05A9AF1018481F3 +:106060009581A681B781892B8A2B8B2B09F05A9AAF +:10607000F10180859185A285B385892B8A2B8B2B95 +:1060800009F05A9AF10184859585A685B785892BF3 +:106090008A2B8B2B09F05A9AD1011C962D913D9198 +:1060A0004D915C911F972F962CAF3DAF4EAF5FAFD8 +:1060B0002F97232B242B252BE9F44090F90950909E +:1060C000FA096090FB097090FC09242D352D462DAE +:1060D000572DBFA5ABA9FCA9E9AD6B2F7A2F8F2F48 +:1060E0009E2F0E94D44B87FD0EC04FA45BA86CA8C6 +:1060F00079AC09C04090110A5090120A6090130ABE +:106100007090140AE2CF63966CAD7DAD8EAD9FADFD +:1061100063972BA13CA14DA15EA1621B730B840B65 +:10612000950B0E94764C2091250A3091260A4091C9 +:10613000270A5091280A0E94DB4B6BA37FA78BABE9 +:106140009CAB362F272F982F8CA9432F522F692FC6 +:10615000782F498B5A8B6B8B7C8B67966CAD7DADA2 +:106160008EAD9FAD67972FA138A549A55AA5621B93 +:10617000730B840B950B0E94764C2091290A309169 +:106180002A0A40912B0A50912C0A0E94DB4B162FB1 +:10619000072F8FA399AF9801982F89AD432F522FC6 +:1061A000692F782F4D8B5E8B6F8B788F6B966CADD4 +:1061B0007DAD8EAD9FAD6B972BA53CA54DA55EA586 +:1061C000621B730B840B950B0E94764C20912D0A59 +:1061D00030912E0A40912F0A5091300A0E94DB4BD9 +:1061E0006BA77DAF26968FAF26979DAB362F272FB7 +:1061F000982F8DA9432F522F692F782F498F5A8FAF +:106200006B8F7C8FA0900001B090010125966CAD42 +:106210007DAD8EAD9FAD25976C197D098E099F09C7 +:106220000E94764C2091310A3091320A4091330A13 +:106230005091340A0E94DB4B6B017C01B501882729 +:1062400077FD8095982F0E94764C9B01AC01C70189 +:10625000B6010E94A94E20E030E048EC52E40E94D2 +:10626000DB4B462F572F682F792FDB01CA014D8F4B +:106270005E8F6F8F78A3F10180809180A280B380C0 +:10628000F6E08F169104A104B104DCF4F10144811D +:1062900055816681778146305105610571058CF421 +:1062A00040855185628573854630510561057105CC +:1062B00044F4AC01BD017F7746A757A760AB71AB33 +:1062C0003CC05BA14FA53BA92CA9652F742F832F40 +:1062D000922F0E94544F6B017C01A8013FA129AD70 +:1062E000652F702F832F922F0E94544F9B01AC017A +:1062F000C701B6010E94FB4A162F072FF82EE92E80 +:106300005BA54DAD26963FAD26972DA9652F742F21 +:10631000832F922F0E94544F9B01AC01D801F701AB +:106320006B2F7A2F8F2F9E2F0E94FB4A0E94164FB1 +:10633000F10166A777A780AB91ABD1019E962D9115 +:106340003D914D915C91D19729962CAF3DAF4EAFC9 +:106350005FAF299760E070E080E89FE30E94DB4B2D +:106360009B01AC01642D752D862D972D0E94A94EA1 +:106370006FA77BAB8CAB9DAF909108058091070513 +:10638000E92FF0E0E81BF109EF70FF27FAAFE9AF62 +:10639000762F6BA99CA98DAD272F362F492F582F0B +:1063A00060E074E284E799E40E94DB4B0E94794E3E +:1063B0006BA37FA38C0129AD3AAD223031050CF4DB +:1063C0004BC06901EE24D7FCE094FE2CC701B60156 +:1063D0000E94764C20E030E040E051E40E94D44B33 +:1063E00087FF3AC04BA05FA038018091450A909189 +:1063F000460AA091470AB091480A481659066A060B +:106400007B0650F5BC01CD01641975098609970911 +:10641000660F771F881F991FA70196010E94A14F41 +:10642000CA01B9010E94744C0E94794EAB01BC01B3 +:10643000CB01BA01640D751D861D971D0E94744C19 +:106440009B01AC0160E074E284E799E40E94DB4BBD +:106450006FA77BAB8CAB9DAF7FA56BA99CA98DADC6 +:10646000272F362F492F582F29966CAD7DAD8EAD35 +:106470009FAD29970E94A94EA6966FAFA697A796A3 +:106480007FAFA797A8968FAFA897A9969FAFA99718 +:10649000362F272F982FA9968FADA997432F522FCC +:1064A000692F782FD10192964D935D936D937C93D4 +:1064B000959750966D917D918D919C9153970E94E7 +:1064C000744C6B017C017FA56BA99CA98DAD272F16 +:1064D000362F492F582FC701B6010E94A94E0E949E +:1064E000C14B0E94484C6F966CAF7DAF8EAF9FAF93 +:1064F0006F97F10160AF71AF82AF93AF9E012F5ED6 +:106500003F4F3EAB2DABAE014F5F5F4F5CA74BA73C +:1065100085E39AE0A5969FAF8EAFA597DE01919691 +:10652000BAA3A9A32B965FAF4EAF2B971BA21FA2B6 +:1065300000E81FE3EDA9FEA961917191819191910C +:10654000FEABEDABBFA5ABA9FCA9EDAD2B2F3A2F50 +:106550004F2F5E2F0E94A94EAB01BC012B96AEAD12 +:10656000BFAD2B974D935D936D937D932B96BFAFEE +:10657000AEAF2B97DB01CA01BF77A3968CAF9DAF5F +:10658000AEAFBFAFA397A596AEADBFADA5974D90EB +:106590005D906D907D90A596BFAFAEAFA597A3011E +:1065A0009201A3966CAD7DAD8EAD9FADA3970E9479 +:1065B000D74D18160CF5A3962CAD3DAD4EAD5FAD85 +:1065C000A397C301B2010E94DB4B2B01782E692EE9 +:1065D000762FC301272F352D492F582FBBA1AFA1EF +:1065E0006B2F7A2F802F912F0E94D44B87FD04C0F0 +:1065F0004BA25FA2072D162DEDA9FEA929A13AA154 +:10660000E217F30709F096CF20E030E040E85FE3BF +:10661000BBA1AFA16B2F7A2F802F912F0E94D44B5B +:1066200087FF53C03E0131E1630E711C7BA16FA156 +:10663000272F362F402F512FABA5BCA56D917D91F3 +:106640008D919C910E94A94EEBA5FCA5619371933D +:1066500081939193FCA7EBA7E615F70539F77BA18A +:106660006FA1272F362F402F512FA696BFADA6978B +:10667000A796AFADA797A896FFADA897A996EFAD3F +:10668000A9976B2F7A2F8F2F9E2F0E94A94ED10191 +:1066900092966D937D938D939C9395976F966CAD29 +:1066A0007DAD8EAD9FAD6F970E94744CBBA1AFA125 +:1066B0002B2F3A2F402F512F0E94A94E0E94484C59 +:1066C000F10160AF71AF82AF93AF29962CAD3DADB4 +:1066D0004EAD5FAD2997C701B6010E94DB4B162F67 +:1066E000072F8FA39BA781149104A104B10489F5FE +:1066F000F10184819581A681B781892B8A2B8B2B0F +:1067000041F580859185A285B385892B8A2B8B2BBA +:1067100001F52091090A30910A0A40910B0A509123 +:106720000C0AD801FFA1EBA56B2F7A2F8F2F9E2F7C +:106730000E94A94E0E94C14B7101F4E4EF0EF11CBE +:106740000E94484CD7016D937D938D939C93139732 +:10675000FDC020910D0A30910E0A40910F0A509110 +:10676000100AD801FFA1EBA56B2F702F8F2F9E2F42 +:106770000E94A94E0E94C14B0E94484CF101EC5B63 +:10678000FF4FFCA3EBA360837183828393834090CC +:10679000E9095090EA096090EB097090EC090E94B9 +:1067A000744C6FA778AB89AB9AABC501B4010E945A +:1067B000764C9B01AC016FA578A989A99AA90E9482 +:1067C000A94EA70196010E94DB4B4B015C01C3015E +:1067D000B2010E94744C9B01AC01C501B4010E943E +:1067E000D74D181634F4EBA1FCA14082518262828D +:1067F00073824090ED095090EE096090EF0970901F +:10680000F009ABA1BCA16D917D918D919C910E94ED +:10681000744C4B015C01F101648175818681978123 +:106820000E94764C9B01AC01C501B4010E94A94EA7 +:10683000A70196010E94DB4B4B015C01C301B20131 +:106840000E94744C9B01AC01C501B4010E94D74D5C +:1068500018163CF4ABA1BCA14D925D926D927C9256 +:1068600013974090F5095090F6096090F7097090E1 +:10687000F809F101EC5BFF4FFCA3EBA36081718190 +:10688000828193810E94744C4B015C012F966CAD08 +:106890007DAD8EAD9FAD2F970E94764C9B01AC01D4 +:1068A000C501B4010E94A94EA70196010E94DB4BCD +:1068B0004B015C01C301B2010E94744C9B01AC010D +:1068C000C501B4010E94D74D18163CF4ABA1BCA180 +:1068D0004D925D926D927C9213974090F109509089 +:1068E000F2096090F3097090F409EBA1FCA16081BA +:1068F0007181828193810E94744C4B015C01D101B2 +:1069000018966D917D918D919C911B970E94764C6C +:106910009B01AC01C501B4010E94A94EA7019601DB +:106920000E94DB4B6B017C01C301B2010E94744CDD +:106930009B01AC01C701B6010E94D74D181634F473 +:10694000EBA1FCA14082518262827382F101EC5B77 +:10695000FF4F60817181828193810E94744C6B0131 +:106960007C01B8019FA18BA5272F302F492F582FCD +:10697000C701B6010E94DB4B462F572F682F792F96 +:10698000AE964CAF5DAF6EAF7FAFAE97D101D296F2 +:106990004D935D936D937C93D5972DEB37E346E054 +:1069A00051E4C701B6010E94A94E0E94434CF10177 +:1069B000648F758F868F978F4090050A5090060AD6 +:1069C0006090070A7090080A29853A854B855C8596 +:1069D0006F962CAF3DAF4EAF5FAF6F978090010ABF +:1069E0009090020AA090030AB090040A20E030E0E0 +:1069F00040E05FE3C501B4010E94A94E6BA37FA3F1 +:106A00008C016F966CAD7DAD8EAD9FAD6F979F770E +:106A1000BBA1AFA12B2F3A2F402F512F0E94D74D52 +:106A200018165CF020E030E040E05FE3C301B20103 +:106A30000E94A94E6BA37FA38C01D1019296BC91B9 +:106A4000BBA7F101F3A1FFA7D1019496BC91BBAB09 +:106A5000F101F5A1FCAB7BA56FA5272F362F4B2F9E +:106A60005F2FBBA1AFA16B2F7A2F802F912F0E9498 +:106A7000D44B87FD06C02BA52BA33FA53FA30BA995 +:106A80001CA98D859E85AF85B889A3968CAF9DAFD7 +:106A9000AEAFBFAFA397C090FD09D090FE09E090C4 +:106AA000FF09F090000A20E030E040E05FE3C7011A +:106AB000B6010E94A94E6DAF7DAB2A968FAF2A9783 +:106AC0002C969FAF2C97A3966CAD7DAD8EAD9FADF0 +:106AD000A3979F77BDADADA92A96FFAD2A972C96B7 +:106AE000EFAD2C972B2F3A2F4F2F5E2F0E94D74DB3 +:106AF000181604F57DAD6DA92A969FAD2A972C96A0 +:106B00008FAD2C97272F362F492F582FBBA1AFA120 +:106B10006B2F7A2F802F912F0E94D44B87FD0AC0B4 +:106B20009DAD9BA3ADA9AFA32A960FAD2A972C9636 +:106B30001FAD2C97E9ADFAAD32970CF434C127E1C3 +:106B400037EB41ED58E36091590A70915A0A8091F0 +:106B50005B0A90915C0A0E94D74D18160CF023C175 +:106B60002091490A30914A0A40914B0A50914C0AAF +:106B700029AF3AAF4BAF5CAF69817A818B819C8141 +:106B80000E94FA4A6DAB2A967FAF2A972C968FAF58 +:106B90002C97A4969FAFA49780914D0A90914E0A8E +:106BA000A0914F0AB091500A21968CAF9DAFAEAF25 +:106BB000BFAF21979C01AD016D817E818F8198854A +:106BC0000E94FA4AA6966FAFA697A7967FAFA7979F +:106BD000A8968FAFA897A9969FAFA9977DA92A9647 +:106BE0006FAD2A972C969FAD2C97A4968FADA49746 +:106BF000272F362F492F582FDB01FC016B2F7A2FBF +:106C00008F2F9E2F0E94A94E6DAB7EAB8FAB98AF9E +:106C1000A6967FADA697A7966FADA797A8969FADAE +:106C2000A897A9968FADA997272F362F492F582FB0 +:106C3000DB01FC016B2F7A2F8F2F9E2F0E94A94E14 +:106C40009B01AC016DA97EA98FA998AD0E94FB4A5A +:106C50000E94164F6DAB7EAB8FAB98AF69AD7AAD2E +:106C60008BAD9CAD9F7727E137EB41ED58E30E9458 +:106C7000D74D181684F021966CAD7DAD8EAD9FADCD +:106C800021979F7727E137EB41ED58E30E94D74DDD +:106C9000181634F00BC09BA59BA3AFA5AFA304C0EF +:106CA000BBA5BBA3EFA5EFA30BA91CA9A301920150 +:106CB0006DA97EA98FA998AD0E94D74D1816ACF486 +:106CC0002DA93EA94FA958ADC301B2010E94DB4BCB +:106CD0009B01AC01BBA1AFA16B2F7A2F802F912F0D +:106CE0000E94A94E6BA37FA38C012091510A309181 +:106CF000520A4091530A5091540A6F966CAD7DAD83 +:106D00008EAD9FAD6F970E94FA4A2B013C01E8942B +:106D100077F8A5019401C301B2010E94D74D18165E +:106D20009CF4A3019201C501B4010E94DB4B9B01BD +:106D3000AC01BBA1AFA16B2F7A2F802F912F0E94A6 +:106D4000A94E6BA37FA38C012091550A3091560A5E +:106D50004091570A5091580AA3966CAD7DAD8EAD07 +:106D60009FADA3970E94FA4A4B015C01E894B7F8E3 +:106D7000A7019601C501B4010E94D74D18169CF4D5 +:106D8000A5019401C701B6010E94DB4B9B01AC0138 +:106D9000BBA1AFA16B2F7A2F802F912F0E94A94EFC +:106DA0006BA37FA38C013BA12FA1432F522F602FF8 +:106DB000712FD1019A964D935D936D937C939D971E +:106DC000AE966CAD7DAD8EAD9FADAE9790589B01EC +:106DD000AC010E94FB4A29962CAD3DAD4EAD5FAD96 +:106DE00029970E94A94E9B01AC016BE077ED83E2ED +:106DF0009BE30E94FA4A0E94164F6B01F82EE92E7F +:106E0000762FC701272F3D2D492F582FBBA1AFA1AA +:106E10006B2F7A2F802F912F0E94D44B87FD04C0B7 +:106E2000CBA2DFA20F2D1E2D3BA12FA1432F522F4E +:106E3000602F712FF10146A357A360A771A7C70167 +:106E40002C2D3D2D492F5E2DBBA5AFA5FBA9ECA98F +:106E50006B2F7A2F8F2F9E2F0E94D44B18162CF059 +:106E600081E0D101D7968C9302C0F10117AA81E08D +:106E7000D101D6968C9380E1FE013196A9E4BAE067 +:106E800001900D928A95E1F73BA52FA59BA98CA9AE +:106E9000432F522F692F782F4093590A50935A0A43 +:106EA00060935B0A70935C0A232F352F492F582F6C +:106EB0006DEC7CEC8CE49DE30E94DB4B6B017C0170 +:106EC0007BA56FA59BA98CA9272F362F492F582F5B +:106ED000BBA1AFA16B2F7A2F802F912F0E94DB4B8C +:106EE000AB01BC0197018601C1010E940B29AA9642 +:106EF000BFADAA97B093080563962CAD3DAD4EADDE +:106F00005FAD63972093D9093093DA094093DB0989 +:106F10005093DC0967968CAD9DADAEADBFAD679764 +:106F20008093DD099093DE09A093DF09B093E00917 +:106F30006B962CAD3DAD4EAD5FAD6B972093E109E7 +:106F40003093E2094093E3095093E40925968CAD10 +:106F50009DADAEADBFAD25978093E5099093E60951 +:106F6000A093E709B093E8090E94FA2CC359DF4FB8 +:106F70000FB6F894DEBF0FBECDBFDF91CF911F914A +:106F80000F91FF90EF90DF90CF90BF90AF909F90C8 +:106F90008F907F906F905F904F903F902F90A9C1FE +:106FA00025962CAD3DAD4EAD5FAD25972093E509FF +:106FB0003093E6094093E7095093E809E1EBF4E0E8 +:106FC0000C945F2EC359DF4F0FB6F894DEBF0FBE8F +:106FD000CDBFDF91CF911F910F91FF90EF90DF9088 +:106FE000CF90BF90AF909F908F907F906F905F9069 +:106FF0004F903F902F900895EF92FF920F931F9321 +:10700000CF93DF937B018A01E9012091250A30911A +:10701000260A4091270A5091280AFC01608171815B +:10702000828193810E94A94E0E94794EE9EDF9E098 +:1070300060837183828393832091290A30912A0A85 +:1070400040912B0A50912C0AF70160817181828155 +:1070500093810E94A94E0E94794EEDEDF9E0608384 +:1070600071838283938320912D0A30912E0A40915F +:107070002F0A5091300AF8016081718182819381D9 +:107080000E94A94E0E94794EE1EEF9E0608371837F +:10709000828393832091310A3091320A4091330ADE +:1070A0005091340A688179818A819B810E94A94E1E +:1070B0000E94794EE5EEF9E06083718382839383C9 +:1070C0009F0141EE59E06DED79E089ED99E05AD7E5 +:1070D0001092590A10925A0A10925B0A10925C0A96 +:1070E0001092490A10924A0A10924B0A10924C0AC6 +:1070F00010924D0A10924E0A10924F0A1092500AA6 +:107100001092510A1092520A1092530A1092540A85 +:107110001092550A1092560A1092570A1092580A65 +:10712000DF91CF911F910F91FF90EF9008952091E3 +:10713000310A3091320A4091330A5091340AFC01ED +:1071400060817181828193810E94A94E0E94794E53 +:10715000E5EEF9E06083718382839383CF014EC7AC +:1071600080930605089580916F0A8111B5C08091C2 +:107170006E0A8111B1C080916D0A8111ADC0089570 +:107180009091C00095FFFCCF8093C600319684910A +:107190008111F6CFE5EFF4E007C09091C00095FFB4 +:1071A000FCCF8093C600319684918111F6CF8091F7 +:1071B0006F0A882349F1E4E0F5E007C09091C00030 +:1071C00095FFFCCF8093C600319684918111F6CF54 +:1071D0006091700A7091710A8091720A9091730A9D +:1071E0000E94764C2091250A3091260A4091270A68 +:1071F0005091280A0E94DB4BAB01BC0122E030E039 +:1072000081E894E00E94FF2480916E0A882349F16E +:10721000E8E0F5E007C09091C00095FFFCCF8093B7 +:10722000C600319684918111F6CF6091740A7091F5 +:10723000750A8091760A9091770A0E94764C209187 +:10724000290A30912A0A40912B0A50912C0A0E9457 +:10725000DB4BAB01BC0122E030E081E894E00E940E +:10726000FF2480916D0A882349F1ECE0F5E007C026 +:107270009091C00095FFFCCF8093C6003196849119 +:107280008111F6CF6091780A7091790A80917A0A1B +:1072900090917B0A0E94764C20912D0A30912E0A03 +:1072A00040912F0A5091300A0E94DB4BAB01BC0188 +:1072B00022E030E081E894E00E94FF248091C00049 +:1072C00085FFFCCF8AE08093C60010926F0A10926F +:1072D0006E0A10926D0A0895EFEEF4E058CF109206 +:1072E0006F0A10926E0A10926D0A08958093210120 +:1072F0000895EFE6F0E080818260808308951F9218 +:107300000F920FB60F9211240F931F932F933F9359 +:107310004F935F936F937F938F939F93AF93BF939D +:10732000EF93FF938091800A9091810A892B09F055 +:1073300056C19091080580910705981771F0E0916A +:1073400007058DE4E89FF0011124E75FFA4FDF01A4 +:10735000A45BBF4F81E08C9302C0E0E0F0E0F093CB +:10736000810AE093800A309709F433C1DF01A45BFE +:10737000BF4F81E08C931092820A1092830A109280 +:10738000840A1092850A94AD85AD9093860A809305 +:10739000870A692F782F613187E2780710F060E162 +:1073A00077E281E08093880A6832710510F468E220 +:1073B00070E068527109611588E07807E0F0872F66 +:1073C0009927880F991F880F991F805F9A4FFC019A +:1073D000329625913491AA27639FA001629F410DA7 +:1073E0005A1F06944A1F5A1F1124FC0125913491FB +:1073F000241B350B1EC0CB01969587958C7F805F33 +:10740000964FFC01259134910296FC0145915491CF +:10741000FB01E770FF274E9FC0014F9F900D5E9FBD +:10742000900D1124A3E096958795AA95E1F7281B66 +:10743000390B24363105A0F4E8E5F2E006C090915E +:10744000C00095FFFCCF8093C60081918111F7CFDA +:107450004AE050E081E894E00E94572424E630E0BE +:10746000C901A0E0B0E08093890A90938A0AA093B2 +:107470008B0AB0938C0A3093890020938800E091A6 +:10748000800AF091810A60AD71AD613187E27807C1 +:1074900010F060E177E281E08093880A683271053C +:1074A00010F468E270E068527109611588E07807AD +:1074B000D0F0872F9927880F991F880F991F805F19 +:1074C0009A4FFC01329645915491AA27659F9001ED +:1074D000649F210D3A1F06942A1F3A1F1124FC01B4 +:1074E000859194911DC09B01369527952C7F205F37 +:1074F000364FF901859194912E5F3F4FF9014591E7 +:107500005491FB01E770FF274E9F90014F9F300D74 +:107510005E9F300D112443E0369527954A95E1F79B +:10752000821B930B84369105A0F4E8E5F2E006C0D7 +:107530009091C00095FFFCCF8093C600819181118E +:10754000F7CF4AE050E081E894E00E94572484E6B7 +:1075500090E090938E0A80938D0AE091800AF091DA +:10756000810A80899189A289B389B695A795979553 +:107570008795B095A095909581959F4FAF4FBF4F40 +:1075800080938F0A9093900AA093910AB093920AE5 +:107590008093930A9093940AA093950AB093960AC5 +:1075A0008093970A9093980AA093990AB0939A0AA5 +:1075B00080939B0A90939C0AA0939D0AB0939E0A85 +:1075C00010927C0A10927D0A10927E0A10927F0A15 +:1075D00006C080ED97E09093890080938800E09149 +:1075E000800AF091810A309709F46EC480A18093DB +:1075F0009F0A80FF3BC016988FEF80931D018091FA +:1076000021018823B9F123B1217031E0232759F1F9 +:107610008091A00A882339F180819181A281B38170 +:10762000181619061A061B06F4F480915D0A90914B +:107630005E0AA0915F0AB091600A8093700A9093ED +:10764000710AA093720AB093730A30936F0A80890B +:107650009189A289B38980937C0A90937D0AA09333 +:107660007E0AB0937F0A2093A00A04C0169A81E094 +:1076700080931D0180919F0A81FF40C0149A8FEF73 +:1076800080931E01809121018823E1F123B131E033 +:1076900026952170232779F18091A10A882359F139 +:1076A000E091800AF091810A84819581A681B78159 +:1076B000181619061A061B06F4F48091610A9091B7 +:1076C000620AA091630AB091640A8093740A90934D +:1076D000750AA093760AB093770A30936E0A808970 +:1076E0009189A289B38980937C0A90937D0AA093A3 +:1076F0007E0AB0937F0A2093A10A04C0149881E007 +:1077000080931E0180919F0A82FF41C046988FEFAF +:1077100080931F01809121018823E9F123B131E099 +:1077200022FB222720F9232779F18091A20A8823BE +:1077300059F1E091800AF091810A80859185A285B6 +:10774000B385181619061A061B06F4F48091650A0B +:107750009091660AA091670AB091680A8093780AAE +:107760009093790AA0937A0AB0937B0A30936D0ABA +:1077700080899189A289B38980937C0A90937D0A3C +:10778000A0937E0AB0937F0A2093A20A04C0469A6F +:1077900081E080931F0180919F0A83FF03C0459879 +:1077A0008FEF02C0459A81E08093200120E030E015 +:1077B000BDC18091C00087FF19C0E091C600409113 +:1077C000020550910305CA0101968F7799276091B0 +:1077D0000405709105058617970741F0DA01AE5749 +:1077E000BB4FEC939093030580930205E091800AD0 +:1077F000F091810A80918F0A9091900AA091910A4C +:10780000B091920A4081518162817381840F951FEA +:10781000A61FB71F80938F0A9093900AA093910A96 +:10782000B093920A181619061A061B060CF4159A3C +:107830008091930A9091940AA091950AB091960A2A +:107840004481558166817781840F951FA61FB71FDC +:107850008093930A9093940AA093950AB093960A02 +:10786000181619061A061B060CF4139AE091800AE2 +:10787000F091810A8091970A9091980AA091990AB3 +:10788000B0919A0A4085518562857385840F951F52 +:10789000A61FB71F8093970A9093980AA093990AFE +:1078A000B0939A0A181619061A061B060CF4479A82 +:1078B00080919B0A90919C0AA0919D0AB0919E0A8A +:1078C0004485558566857785840F951FA61FB71F4C +:1078D00080939B0A90939C0AA0939D0AB0939E0A62 +:1078E000181619061A061B060CF4179A80918F0AAF +:1078F0009091900AA091910AB091920A18161906D7 +:107900001A061B065CF5E091800AF091810A408915 +:10791000518962897389841B950BA60BB70B8093E1 +:107920008F0A9093900AA093910AB093920A409183 +:107930001D0180915D0A90915E0AA0915F0AB0914D +:10794000600A840F911DA11DB11D80935D0A909363 +:107950005E0AA0935F0AB093600A15988091930A1B +:107960009091940AA091950AB091960A181619065A +:107970001A061B065CF5E091800AF091810A4089A5 +:10798000518962897389841B950BA60BB70B809371 +:10799000930A9093940AA093950AB093960A409103 +:1079A0001E018091610A9091620AA091630AB091D0 +:1079B000640A840F911DA11DB11D8093610A9093EB +:1079C000620AA093630AB093640A13988091970A9D +:1079D0009091980AA091990AB0919A0A18161906DE +:1079E0001A061B065CF5E091800AF091810A408935 +:1079F000518962897389841B950BA60BB70B809301 +:107A0000970A9093980AA093990AB0939A0A409182 +:107A10001F018091650A9091660AA091670AB09152 +:107A2000680A840F911DA11DB11D8093650A909372 +:107A3000660AA093670AB093680A479880919B0AE8 +:107A400090919C0AA0919D0AB0919E0A1816190661 +:107A50001A061B065CF5E091800AF091810A4089C4 +:107A6000518962897389841B950BA60BB70B809390 +:107A70009B0A90939C0AA0939D0AB0939E0A409102 +:107A800020018091690A90916A0AA0916B0AB091D5 +:107A90006C0A840F911DA11DB11D8093690A9093FA +:107AA0006A0AA0936B0AB0936C0A179880917C0ABB +:107AB00090917D0AA0917E0AB0917F0A0196A11D46 +:107AC000B11D80937C0A90937D0AA0937E0AB093A7 +:107AD0007F0A40917C0A50917D0A60917E0A7091E4 +:107AE0007F0A2F5F3F4FE091800AF091810A8089E1 +:107AF0009189A289B389481759076A077B07B0F0B3 +:107B000040917C0A50917D0A60917E0A70917F0AB3 +:107B1000E091800AF091810A84899589A689B789C4 +:107B200084179507A607B70748F4CBC08091880A49 +:107B300090E0281739070CF43CCEE2CF4091890A37 +:107B400050918A0A60918B0A70918C0A048D158D70 +:107B5000268D378DAA27419FB12D529FC001629F6C +:107B6000900D619F800D911D429FB00D811D9A1F48 +:107B7000519FB00D811D9A1F609FB00D811D9A1FEE +:107B8000509FB10D8A1F9A1FB6958A1F9A1F112404 +:107B900044AD55AD480F591F5093870A4093860A4C +:107BA00080AD91ADA2ADB3AD60E070E084179507F4 +:107BB000A607B70720F49093870A8093860A6091FE +:107BC000860A7091870A613187E2780710F060E1D8 +:107BD00077E281E08093880A6832710510F468E2E8 +:107BE00070E068527109611588E07807E0F0872F2E +:107BF0009927880F991F880F991F805F9A4FFC0162 +:107C0000329625913491AA27639FA001629F410D6E +:107C10005A1F06944A1F5A1F1124FC0125913491C2 +:107C2000241B350B1EC0CB01969587958C7F805FFA +:107C3000964FFC01259134910296FC014591549197 +:107C4000FB01E770FF274E9FC0014F9F900D5E9F85 +:107C5000900D1124A3E096958795AA95E1F7281B2E +:107C6000390B24363105A0F4E8E5F2E006C0909126 +:107C7000C00095FFFCCF8093C60081918111F7CFA2 +:107C80004AE050E081E894E00E94572424E630E086 +:107C900030938900209388008091890A90918A0A04 +:107CA000A0918B0AB0918C0A820F931FA11DB11D68 +:107CB0008093890A90938A0AA0938B0AB0938C0AC6 +:107CC000DEC040917C0A50917D0A60917E0A7091DD +:107CD0007F0A808D918DA28DB38D84179507A6079D +:107CE000B70708F0C4C04091820A5091830A60919E +:107CF000840A7091850A048D158D268D378DAA27EB +:107D0000419FB12D529FC001629F900D619F800DD8 +:107D1000911D429FB00D811D9A1F519FB00D811D75 +:107D20009A1F609FB00D811D9A1F509FB10D8A1F31 +:107D30009A1FB6958A1F9A1F11242091860A3091A6 +:107D4000870AE05CFF4F2817390718F4208131813A +:107D500002C0281B390B80819181A281B381A901C6 +:107D600060E070E0481759076A077B0708F49C0138 +:107D7000B901213187E2380710F060E177E281E054 +:107D80008093880A6832710510F468E270E06852E6 +:107D90007109611588E07807E0F0872F9927880F2F +:107DA000991F880F991F805F9A4FFC013296259189 +:107DB0003491AA27639FA001629F410D5A1F069428 +:107DC0004A1F5A1F1124FC0125913491241B350BA5 +:107DD0001EC0CB01969587958C7F805F964FFC01E6 +:107DE000259134910296FC0145915491FB01E77075 +:107DF000FF274E9FC0014F9F900D5E9F900D112455 +:107E000043E0969587954A95E1F7281B390B243670 +:107E10003105A0F4E8E5F2E006C09091C00095FFBE +:107E2000FCCF8093C60081918111F7CF4AE050E0EA +:107E300081E894E00E94572424E630E030938900E2 +:107E4000209388008091820A9091830AA091840AED +:107E5000B091850A820F931FA11DB11D8093820AE4 +:107E60009093830AA093840AB093850A08C08091F6 +:107E70008D0A90918E0A909389008093880040919A +:107E80007C0A50917D0A60917E0A70917F0AE09190 +:107E9000800AF091810A80899189A289B389481763 +:107EA00059076A077B0780F01092810A1092800AB6 +:107EB0009091080580910705981731F0809107058A +:107EC0008F5F8F7080930705FF91EF91BF91AF9106 +:107ED0009F918F917F916F915F914F913F912F91E2 +:107EE0001F910F910F900FBE0F901F9018950E9A33 +:107EF0000C9A3E9A3D9A529A529A529A529A2098C5 +:107F0000289A2198299A22982A9A0D9A0B9A3F9A90 +:107F10000F9AA1E8B0E08C918F7E8C938C91886051 +:107F20008C93E0E8F0E080818D7F808380818E7F7C +:107F3000808380818F73808380818F7C80838C910C +:107F4000887F82608C9380E090E490938900809396 +:107F500088001092850010928400EFE6F0E08081A6 +:107F60008260808381E0C2D9789408959091080559 +:107F700080910705981729F025D281E00E943810DA +:107F8000F5CF0895CF93DF93EFB7F894EC01888194 +:107F90009981AA81BB8180935D0A90935E0AA09328 +:107FA0005F0AB093600AEB0188819981AA81BB8145 +:107FB0008093610A9093620AA093630AB093640A63 +:107FC000EA0188819981AA81BB818093650A909397 +:107FD000660AA093670AB093680AE90188819981CB +:107FE000AA81BB818093690A90936A0AA0936B0A65 +:107FF000B0936C0AEFBFDF91CF9108952FB7F8943B +:10800000FC0180819181A281B3818093690A909360 +:108010006A0AA0936B0AB0936C0A2FBF08950F935E +:108020001F939FB7F89424E0829FF0011124E35A34 +:10803000F54F00811181228133819FBFB801C901B1 +:108040001F910F91089592DF5A985A985A985A980A +:10805000089520912A0130912B0140912C015091DB +:108060002D0160E070E08FE793E40E94DB4B6093AA +:10807000B10A7093B20A8093B30A9093B40A089538 +:108080008055954FFC01808190E008950F931F93D8 +:10809000CF93DF93EC01662309F461C0E7EFFDE0C5 +:1080A00007C09091C00095FFFCCF8093C600319629 +:1080B00084918111F6CF4AE050E070E081E894E0CD +:1080C0000E943C24EEEFFDE007C09091C00095FFB8 +:1080D000FCCF8093C600319684918111F6CF8091B8 +:1080E000C00085FFFCCF8AE08093C6000E940F107D +:1080F00036C0C901880F991F880F991FFC01E45EE3 +:10810000F14F659174916C177D073CF52150310951 +:10811000220F331F220F331FF901E65EF14F059145 +:108120001491245E314FF90145915491FC01E65EB2 +:10813000F14F25913491C41BD50B201B310BC29FED +:10814000C001C39F900DD29F900D1124641B750B2D +:108150000E948E4F600F711F13C04F5F01C041E03E +:10816000242F30E04D3309F0C4CF2D33310531F4E5 +:10817000EAE0FFE085919491BC0102C060E070E00C +:1081800020EF3FE3261B370BC901DF91CF911F91F1 +:108190000F910895CF93DF9321E030E0D901AA0F2A +:1081A000BB1FAA0FBB1FFD01E45EF14F65917491E7 +:1081B0006817790744F521503109220F331F220F28 +:1081C000331FF901E65EF14FC591D491245E314F22 +:1081D000F90145915491FD01E65EF14F25913491ED +:1081E000FC01E41BF50B2C1B3D0BE29FC001E39F40 +:1081F000900DF29F900D1124641B750B0E948E4F01 +:108200006C0F7D1F0BC02F5F3F4F2D33310509F0E1 +:10821000C5CFEAE0FFE085919491BC0120EF3FE3F8 +:10822000261B370BC901DF91CF9108952F923F9202 +:108230004F925F926F927F928F929F92AF92BF9276 +:10824000CF92DF92EF92FF920F931F93CF93DF9322 +:108250008C01662351F1E7EFFDE007C09091C0006B +:1082600095FFFCCF8093C600319684918111F6CFA3 +:108270004AE050E070E081E894E00E943C24EEE0A7 +:10828000FFE007C09091C00095FFFCCF8093C6002F +:10829000319684918111F6CF8091C00085FFFCCF8B +:1082A0008AE08093C6000E940F10C0EFDFE3C01B7E +:1082B000D10B41E05EC09C01220F331F220F331F00 +:1082C000F901E65EF14F65907490C615D7050CF084 +:1082D0004FC00197880F991F880F991FFC01E45E1A +:1082E000F14F25903490865E914FFC0105911491D9 +:1082F000F901E45EF14F45905490B101882777FD74 +:108300008095982F0E94764C6B017C01BE01601B0A +:10831000710B882777FD8095982F0E94764C4B0132 +:108320005C01B20162197309882777FD8095982F47 +:108330000E94764C9B01AC01C501B4010E94A94E7C +:108340004B015C01B301601B710B882777FD8095A1 +:10835000982F0E94764C9B01AC01C501B4010E948C +:10836000DB4B9B01AC01C701B6010E94FB4A17C061 +:108370004F5F842F90E04D3309F09DCFCD9759F496 +:10838000ECE0FFE065917491882777FD8095982F48 +:108390000E94764C04C060E070E080E090E0DF91E5 +:1083A000CF911F910F91FF90EF90DF90CF90BF90F2 +:1083B000AF909F908F907F906F905F904F903F9085 +:1083C0002F9008952F923F924F925F926F927F92DB +:1083D0008F929F92AF92BF92CF92DF92EF92FF92D5 +:1083E0000F931F93CF93DF9300D0CDB7DEB780916B +:1083F000A30A882309F4B8C18FB7F8941092A30A8E +:108400008FBF60E08091AA0A9091AB0A0FDF6B01E9 +:108410007C019B01AC016091A40A7091A50A809136 +:10842000A60A9091A70A0E94FA4AB62EA72E182FE4 +:10843000092FA5019801852F942FA32FB22F809388 +:10844000B50A9093B60AA093B70AB093B80A20E091 +:1084500030E040E251E4D501F8016B2F7A2F8F2FE5 +:108460009E2F0E94D74D18160CF41BC120E030E05F +:1084700040E251ECD501F8016B2F7A2F8F2F9E2F00 +:108480000E94D44B87FD09C18091B90A8111FAC0BD +:1084900020912E0130912F014091300150913101F6 +:1084A000D501F8016B2F7A2D8F2F902F0E94A94EA6 +:1084B000762E672E89839A83A301382F292F852F43 +:1084C000942FA32FB22F8093BE0A9093BF0AA0933C +:1084D000C00AB093C10A2091BA0A3091BB0A4091F8 +:1084E000BC0A5091BD0AD501F8016B2F7A2D8F2F50 +:1084F000902F0E94FB4A8B012C018090C20A909021 +:10850000C30AA090C40AB090C50A282D392D4A2D5F +:108510005B2D602F712F842D952D0E94D44B87FFEA +:108520009BC084012501802F912FA42DB52D809310 +:10853000BA0A9093BB0AA093BC0AB093BD0A2091DB +:108540002A0130912B0140912C0150912D01602F77 +:10855000712F842D952D0E94A94E4B015C01862F11 +:10856000992DAA2DBB2D8093C60A9093C70AA0937C +:10857000C80AB093C90A2091CA0A3091CB0A409127 +:10858000CC0A5091CD0AC701B6010E94FA4A209147 +:1085900026013091270140912801509129010E9424 +:1085A000A94E20ED3CEC4CE45DE30E94A94E1B017A +:1085B0002C0123E333E343E75FE36091CE0A70913C +:1085C000CF0A8091D00A9091D10A0E94A94E9B01B6 +:1085D000AC01C201B1010E94FB4A8B012C01862F24 +:1085E000912FA42DB52D8093CE0A9093CF0AA093FE +:1085F000D00AB093D10AC092CA0AD092CB0AE092B4 +:10860000CC0AF092CD0A282D392D4A2D5B2DD301AD +:10861000F980EA806B2F762D8F2D9E2DECD7202FA1 +:10862000312F442D552DE6D78B017C0120E030E021 +:10863000A901712F9F2D0E94D44B87FD3CC020E0E3 +:1086400030E04FE753E4602F712F8E2D9F2D0E9455 +:10865000D74D1816A4F528C08090B10A9090B20AA0 +:10866000A090B30AB090B40A282D392D4A2D5B2D65 +:10867000602F712F842D952D0E94D74D18160CF068 +:1086800052CF4FCF1092BA0A1092BB0A1092BC0A76 +:108690001092BD0A1092B90AFBCE81E08093B90A0C +:1086A0000AC081E08093B90A00E010E08FE7E82E6D +:1086B00093E4F92E04C000E010E0E12CF12C2091AD +:1086C000AA0A3091AB0A4091D20A5091D30A4217BC +:1086D00053071CF01092B00A11C040913201509122 +:1086E000330124173507B4F7602F712F8E2D9F2D7E +:1086F0000E94434C759567956093B00A0E9478215B +:108700000091D40A1091D50A2091D60A3091D70A47 +:10871000601B710B820B930B6838734181059105C7 +:1087200018F10E9478216093D40A7093D50A80933F +:10873000D60A9093D70A8091A80A9091A90A181690 +:1087400019068CF42091340130913501821793077A +:1087500054F42091AC0A3091AD0A821793070CF0C3 +:1087600002C02C9A01C02C980F900F90DF91CF91EE +:108770001F910F91FF90EF90DF90CF90BF90AF903F +:108780009F908F907F906F905F904F903F902F9031 +:1087900008952F923F924F925F926F927F928F92A5 +:1087A0009F92AF92BF92CF92DF92EF92FF920F9380 +:1087B0001F93CF93DF93C0EFDFE3C81BD90B81E09A +:1087C00090E09C01220F331F220F331FF901E65E58 +:1087D000F14F65907490C615D7050CF04DC0019708 +:1087E000880F991F880F991FFC01E45EF14F2590B7 +:1087F0003490865E914FFC0105911491F901E45E7D +:10880000F14F45905490B101882777FD8095982FBE +:108810000E94764C6B017C01BE01601B710B8827A6 +:1088200077FD8095982F0E94764C4B015C01B20138 +:1088300062197309882777FD8095982F0E94764CDE +:108840009B01AC01C501B4010E94A94E4B015C0122 +:10885000B301601B710B882777FD8095982F0E94CC +:10886000764C9B01AC01C501B401A5D79B01AC01BD +:10887000C701B601C0D60FC001968D33910509F02E +:10888000A0CFECE0FFE065917491882777FD80959B +:10889000982F0E94764CDF91CF911F910F91FF90FE +:1088A000EF90DF90CF90BF90AF909F908F907F9090 +:1088B0006F905F904F903F902F9008951092C20A52 +:1088C0001092C30A1092C40A1092C50A20912A017C +:1088D00030912B0140912C0150912D0160E070E00E +:1088E0008FE793E468D76093B10A7093B20A8093DC +:1088F000B30A9093B40A239A249A569A61E070E0DE +:108900008EE00E94192187ED80937A00EEE7F0E077 +:1089100010828081816080838081826080838081F9 +:108920008460808380818460808380E888BDEEE6F7 +:10893000F0E08081846080836AEF70E080E090E006 +:108940000E94AA2160E085E090E0A0DB9093D30A2A +:108950008093D20A60E083E191E098DB9093330149 +:108960008093320186E990E015DC90933501809385 +:1089700034010895089560E080E090E087DB109274 +:10898000A40A1092A50A1092A60A1092A70A80E0E3 +:1089900090E000DC9093AD0A8093AC0A1092AF0A8D +:1089A0001092AE0A1092B00A2B981092B10A10924F +:1089B000B00A1092B10A1092B30A1092B20A109241 +:1089C000B20A1092AD0A1092AC0A2C9808952F9218 +:1089D0003F924F925F926F927F928F929F92AF924F +:1089E000BF92CF92DF92EF92FF920F931F93CF939C +:1089F000DF93CDB7DEB7E1970FB6F894DEBF0FBEB9 +:108A0000CDBF688B798B8A8B9B8B0E9478216C8B76 +:108A10007D8B8E8B9F8BECE6F2E006C09091C000C0 +:108A200095FFFCCF8093C60081918111F7CF809193 +:108A3000C00085FFFCCF8AE08093C6009CDF8FE7F3 +:108A40008093B00A4C885D886E887F884C865D86EE +:108A50006E867F86AFE7CA2ED12CE12CF12CBFE7C2 +:108A60008B2E912CA12CB12C8EA69FA6A8AAB9AAB8 +:108A700021E02CA31B861A86E0E1FDE084908FA202 +:108A8000E8E1FDE0949098A6EDE1FDE0A490A9A6B0 +:108A9000E4E2FDE0B490BAA6EBE2FDE084908BA6A0 +:108AA000E1E3FDE094909CA68091A30A882309F459 +:108AB000A9C28FB7F8941092A30A8FBF60E080918B +:108AC000AA0A9091AB0AB2DB6E837F83888799876D +:108AD000762F6F81982F8985272F362F492F582F72 +:108AE000B88DA98DEA8DFB8D6B2F7A2FCF010E9457 +:108AF000D74D181644F0AE80A88EBF80B98E8884FA +:108B00008A8E99849B8E7E816F8198858985272F97 +:108B1000362F492F582F612F722D832D902F44D639 +:108B200087FD04C01E812F8038840985ACA0AA204F +:108B300009F42FC3788969899A898B89272F362F61 +:108B4000492F582FBE81AF81E885F9856B2F7A2F89 +:108B5000CF010E94D74D18160CF054C20E94782104 +:108B6000641975098609970969387341810591056A +:108B700008F448C28EA59FA5A8A9B9A98C199D097A +:108B8000AE09BF09B595A795979587958093B00ACB +:108B90000E9478216C877D878E879F874B015C01BF +:108BA00084189508A608B70888A299A2AAA2BBA211 +:108BB0009888988EA988A98EBA88BA8E8B888B8E51 +:108BC000E8C20E9478218C849D84AE84BF84681999 +:108BD00079098A099B09693873418105910508F46F +:108BE00010C20E9478212B013C018A849B84892831 +:108BF00009F4EDC1DC01CB018C849D84AE84BF847B +:108C000088199909AA09BB0988A099A0AAA0BBA0A4 +:108C1000880E991EAA1EBB1E28A139A14AA15BA1DC +:108C2000281B390B4A0B5B0BCA01B901A70196013E +:108C30000E947F4FA50194010E94C34F8EA59FA55E +:108C4000A8A9B9A9280F391F4A1F5B1F2431310574 +:108C50004105510524F12EA73FA748AB59AB2C3E47 +:108C600031054105510544F02BEE30E040E050E085 +:108C70002EA73FA748AB59AB8EA59FA5A8A9B9A918 +:108C800080389105A105B105C4F0EEEFCE2ED12CB0 +:108C9000E12CF12CC81AD90AEA0AFB0A12C024E115 +:108CA00030E040E050E02EA73FA748AB59AB74E15D +:108CB000C72ED12CE12CF12C04C0CEA4DFA4E8A84F +:108CC000F9A88FA1E0E1FDE008C09091C00095FFF8 +:108CD000FCCF8093C600319684918111F6CF2AE0B3 +:108CE00030E04EA55FA568A979A981E894E00E94CB +:108CF000062488A5E8E1FDE008C09091C00095FF3A +:108D0000FCCF8093C600319684918111F6CF2AE082 +:108D100030E0B701A60181E894E00E94062489A50D +:108D2000EDE1FDE008C09091C00095FFFCCF80937D +:108D3000C600319684918111F6CF22E030E0412FB8 +:108D4000522D632D702F81E894E00E94FF248AA5A4 +:108D5000E4E2FDE008C09091C00095FFFCCF809355 +:108D6000C600319684918111F6CF22E030E0F88D73 +:108D7000E98D9A8D8B8D4F2F5E2F692F782F81E88B +:108D800094E00E94FF248091C00085FFFCCF8AE020 +:108D90008093C6004A855B85433051050CF417C1AA +:108DA000C701B601A3D520E030E040E850E4D1D7B8 +:108DB0006C8F7D8F8E8F9F8F212F322D432D502FC3 +:108DC000B88DA98DEA8D1B8D6B2F7A2F8E2F912F49 +:108DD00011D420ED3FE049E450E4BBD720E030E07F +:108DE00040E05FE3B6D79B01AC016C8D7D8D8E8D2D +:108DF0009F8DE1D4362E072F182F9C8FC501B4010B +:108E000075D520E030E04AE754E4D5D4A62E972E5D +:108E1000282E892E8BA5EBE2FDE008C09091C000C2 +:108E200095FFFCCF8093C600319684918111F6CFD7 +:108E300022E030E08C8D432D502F612F782F81E878 +:108E400094E00E94FF248CA5E1E3FDE008C090912E +:108E5000C00095FFFCCF8093C600319684918111AC +:108E6000F6CF22E030E04A2D592D622D782D81E891 +:108E700094E00E94FF248091C00085FFFCCF8AE02F +:108E80008093C6002AE939E949E15FE3EC8D632D5F +:108E9000702F812F9E2F5DD7362E072F182FB92EBA +:108EA000762F272F302F412F5B2D632D702F812F91 +:108EB0009B2DA1D32A2D392D422D582D7CD46C8F7A +:108EC0007CA38DA39EA32A2D392D422D582D632DD1 +:108ED000702F812F9B2D3DD720E030E040E05EE3F6 +:108EE00038D7A62E972E282E892EE7E3FDE007C05F +:108EF0009091C00095FFFCCF8093C600319684917D +:108F00008111F6CF8091C00085FFFCCF8AE080936D +:108F1000C600E4E4FDE007C09091C00095FFFCCFDF +:108F20008093C600319684918111F6CF22E030E023 +:108F3000432D502F612F7B2D81E894E00E94FF2468 +:108F40008091C00085FFFCCF8AE08093C600EAE4F0 +:108F5000FDE007C09091C00095FFFCCF8093C60054 +:108F6000319684918111F6CF22E030E0FC8DECA1A6 +:108F70009DA18EA14F2F5E2F692F782F81E894E05D +:108F80000E94FF248091C00085FFFCCF8AE080937F +:108F9000C600E0E5FDE007C09091C00095FFFCCF62 +:108FA0008093C600319684918111F6CF22E030E0A3 +:108FB0004A2D592D622D782D81E894E00E94FF24DE +:108FC0008091C00085FFFCCF8AE08093C6008EA50B +:108FD0009FA5A8A9B9A98C0D9D1DAE1DBF1DB59556 +:108FE000A795979587958093B00A8A859B8501966A +:108FF0009B878A87188929883A880B8991E09CA3E6 +:1090000001C01CA220E030E040EA51E4B889A989FF +:10901000EA89FB896B2F7A2FCF01EDD29B01AC013E +:10902000BE81AF81E885F9856B2F7A2FCF01BFD53F +:10903000181694F4E6E5FDE007C09091C00095FF96 +:10904000FCCF8093C600319684918111F6CF809138 +:10905000C00085FFFCCF99C00E9478218C889D8834 +:10906000AE88BF88681979098A099B09613D7740F4 +:109070008105910508F440C00E9478216C8B7D8B9E +:109080008E8B9F8BEFE7FDE007C09091C00095FFAE +:10909000FCCF8093C600319684918111F6CF60E0B9 +:1090A0008091AA0A9091AB0AC1D8AB01BC0122E021 +:1090B00030E081E894E00E94FF24E5E8FDE007C08D +:1090C0009091C00095FFFCCF8093C60031968491AB +:1090D0008111F6CF80E090E00E9440404AE050E0ED +:1090E000BC0181E894E00E943C248091C00085FF8F +:1090F000FCCF8AE08093C6000E9478216A837B833C +:109100008C839D830E9478218C849D84AE84BF844F +:10911000840C951CA61CB71C2A813B814C815D8167 +:10912000281939094A095B09260F371F481F591F9B +:1091300021383F444241510590F0E9E8FDE007C085 +:109140009091C00095FFFCCF8093C600319684912A +:109150008111F6CF8091C00085FFFCCF16C0AA8593 +:10916000BB8516970CF4A0CCE6EAFDE007C0909111 +:10917000C00095FFFCCF8093C60031968491811189 +:10918000F6CF8091C00085FFFCCF8AE08093C600B7 +:1091900013C0788969899A898B89272F362F492F9F +:1091A000582FBE81AF81E885F9856B2F7A2FCF01CB +:1091B000FBD287FD06CD25CFE1960FB6F894DEBF32 +:1091C0000FBECDBFDF91CF911F910F91FF90EF9018 +:1091D000DF90CF90BF90AF909F908F907F906F90D7 +:1091E0005F904F903F902F900895CF93DF931F9201 +:1091F000CDB7DEB78983BFDB0E941621698181115B +:109200002FC0E7EFFDE007C08091C00085FFFCCFD5 +:109210009093C600319694919111F6CF4AE050E0B8 +:1092200070E081E894E00E943C248091C00085FFBA +:10923000FCCF8AE08093C600EBE2FFE007C090918C +:10924000C00095FFFCCF8093C600319684918111B8 +:10925000F6CF8091C00085FFFCCF8AE08093C600E6 +:109260000F90DF91CF910895CF93DF931F92CDB7E9 +:10927000DEB7898380DB0E941621698181112FC0AE +:10928000E7EFFDE007C08091C00085FFFCCF909321 +:10929000C600319694919111F6CF4AE050E070E00B +:1092A00081E894E00E943C248091C00085FFFCCFBF +:1092B0008AE08093C600E8E5FFE007C09091C00017 +:1092C00095FFFCCF8093C600319684918111F6CF33 +:1092D0008091C00085FFFCCF8AE08093C6000F908C +:1092E000DF91CF9108952C980E941621811121C001 +:1092F000E7EFFDE007C09091C00095FFFCCF8093A1 +:10930000C600319684918111F6CFE5E8FFE007C0F1 +:109310009091C00095FFFCCF8093C6003196849158 +:109320008111F6CF8091C00085FFFCCF8AE0809349 +:10933000C60008951F920F920FB60F9211242F931B +:109340003F934F935F936F937F938F939F93AF93CD +:10935000BF93EF93FF9380913601811106C08091F6 +:10936000B00A8093D80A81112B9A9091D80A8091E3 +:109370003601891708F02B988F5F8F77809336011D +:109380008091D90A833009F443C020F48130D1F0B0 +:10939000A8F50CC0853009F461C008F453C08630CC +:1093A00009F476C0873009F09EC07EC010927B0021 +:1093B00080E480937C0080917A00806480937A00BE +:1093C00081E019C020917800309179008091DA0A0B +:1093D0009091DB0AA091DC0AB091DD0A820F931F05 +:1093E000A11DB11D8093DA0A9093DB0AA093DC0AD9 +:1093F000B093DD0A82E08093D90A75C082E480933D +:109400007C0080917A00806480937A0083E0F3CFBF +:1094100020917800309179008091DE0A9091DF0AE6 +:10942000A091E00AB091E10A820F931FA11DB11D26 +:109430008093DE0A9093DF0AA093E00AB093E10ADA +:1094400084E0D9CF10927B0081E480937C008091EE +:109450007A00806480937A0085E0CDCF20917800F7 +:10946000309179008091E20A9091E30AA091E40A98 +:10947000B091E50A820F931FA11DB11D8093E20AEE +:109480009093E30AA093E40AB093E50A86E0B3CF91 +:1094900010927B0082E480937C0080917A0080644B +:1094A00080937A0087E0A7CF2091780030917900EF +:1094B0008091E60A9091E70AA091E80AB091E90A42 +:1094C000820F931FA11DB11D8093E60A9093E70AB6 +:1094D000A093E80AB093E90A1092D90A8091EA0AA7 +:1094E0008F5F8093EA0A8091EA0A803108F471C0A4 +:1094F0002FEF3FE38091DA0A9091DB0AA901481B24 +:10950000590BCA015093AB0A4093AA0A4091DE0A54 +:109510005091DF0A241B350B3093A90A2093A80A27 +:1095200021E02093A30A1092EA0A1092DA0A10921C +:10953000DB0A1092DC0A1092DD0A1092E20A109205 +:10954000E30A1092E40A1092E50A1092E60A1092D9 +:10955000E70A1092E80A1092E90A1092DE0A1092C5 +:10956000DF0A1092E00A1092E10A20913201309154 +:1095700033018217930744F01092AF0A1092AE0A9B +:1095800080E033DE0E94DB202091AA0A3091AB0AF2 +:109590008091D20A9091D30A8217930744F01092D7 +:1095A000AF0A1092AE0A80E05FDE0E94DB202091BD +:1095B000A80A3091A90A80913401909135012817A9 +:1095C00039073CF01092AD0A1092AC0A8CDE0E9472 +:1095D000DB20FF91EF91BF91AF919F918F917F9190 +:1095E0006F915F914F913F912F910F900FBE0F9010 +:1095F0001F9018955058BB27AA270ED076C23FD28D +:1096000030F044D220F031F49F3F11F41EF40FC229 +:109610000EF4E095E7FBDCC1E92F89D280F3BA179D +:10962000620773078407950718F071F49EF5B8C2B6 +:109630000EF4E0950B2EBA2FA02D0B01B90190016D +:109640000C01CA01A0011124FF27591B99F0593FB1 +:1096500050F4503E68F11A16F040A22F232F342FF9 +:109660004427585FF3CF469537952795A795F04047 +:109670005395C9F77EF41F16BA0B620B730B840B5C +:10968000BAF09150A1F0FF0FBB1F661F771F881F14 +:10969000C2F70EC0BA0F621F731F841F48F487956C +:1096A00077956795B795F7959E3F08F0B3CF93955B +:1096B000880F08F09927EE0F979587950895DFD1C9 +:1096C00058F080E891E009F49EEFE0D128F040E8FE +:1096D00051E059F45EEF09C0AAC162C2E92FE078F7 +:1096E00026D268F3092E052AC1F326173707480743 +:1096F000590738F00E2E07F8E02569F0E025E06400 +:109700000AC0EF6307F8009407FADB01B9019D0175 +:10971000DC01CA01AD01EF935DD0E7D10AD05F91C2 +:10972000552331F02BED3FE049E450FD49EC63CF88 +:109730000895DF93DD27B92FBF7740E85FE3161662 +:10974000170648075B0710F4D92F96D29F938F9383 +:109750007F936F93A9D3E0E7F0E06CD1C6D12F914E +:109760003F914F915F9101D3DD2349F09058A2EAD8 +:109770002AED3FE049EC5FE3D0785D274DDFDF91D4 +:10978000B4C1F7D180F09F3740F491110EF409C2B3 +:1097900060E070E080E89FE3089526F01B16611DED +:1097A000711D811D1BC135C1EFD008F481E0089502 +:1097B00075D1E395ABC10CD098C168D140F05FD1B1 +:1097C00030F021F45F3F19F003C15111EAC12FC1FC +:1097D000AED198F39923C9F35523B1F3951B550BDB +:1097E000BB27AA2762177307840738F09F5F5F4F74 +:1097F000220F331F441FAA1FA9F333D00E2E3AF0B5 +:10980000E0E830D091505040E695001CCAF729D0CE +:10981000FE2F27D0660F771F881FBB1F261737071D +:109820004807AB07B0E809F0BB0B802DBF01FF274D +:1098300093585F4F2AF09E3F510568F0C9C0B1C1EF +:109840005F3FECF3983EDCF3869577956795B79587 +:10985000F7959F5FC9F7880F911D9695879597F9A2 +:109860000895E1E0660F771F881FBB1F621773071B +:109870008407BA0720F0621B730B840BBA0BEE1F30 +:1098800088F7E095089504D06894B1118AC10895CD +:1098900056D188F09F5790F0B92F9927B751A0F073 +:1098A000D1F0660F771F881F991F1AF0BA95C9F774 +:1098B00012C0B13081F074D1B1E0089571C1672F49 +:1098C000782F8827B85F39F0B93FCCF38695779524 +:1098D0006795B395D9F73EF490958095709561950D +:1098E0007F4F8F4F9F4F0895E89409C097FB3EF438 +:1098F00090958095709561957F4F8F4F9F4F9923DD +:10990000A9F0F92F96E9BB279395F695879577955A +:109910006795B795F111F8CFFAF4BB0F11F460FF1A +:109920001BC06F5F7F4F8F4F9F4F16C0882311F072 +:1099300096E911C0772321F09EE8872F762F05C086 +:10994000662371F096E8862F70E060E02AF09A9521 +:10995000660F771F881FDAF7880F9695879597F916 +:10996000089507D180F09F3740F491110EF019C18E +:1099700060E070E080E89FEB089526F41B16611DFF +:10998000711D811D2BC045C0990F0008550FAA0BF2 +:10999000E0E8FEEF16161706E807F907C0F0121602 +:1099A0001306E407F50798F0621B730B840B950B05 +:1099B00039F40A2661F0232B242B252B21F408955A +:1099C0000A2609F4A140A6958FEF811D811D0895F7 +:1099D00097F99F6780E870E060E00895882371F44C +:1099E000772321F09850872B762F07C0662311F438 +:1099F00099270DC09051862B70E060E02AF09A956F +:109A0000660F771F881FDAF7880F9695879597F965 +:109A100008959F3F31F0915020F487957795679591 +:109A2000B795880F911D9695879597F908959FEFA3 +:109A300080EC0895DF93CF931F930F93FF92EF92E3 +:109A4000DF927B018C01689405C0DA2EEF018DD185 +:109A5000FE01E894A5912591359145915591AEF37C +:109A6000EF01DADDFE019701A801DA9479F7DF90C2 +:109A7000EF90FF900F911F91CF91DF9108950024F7 +:109A80000A941616170618060906089500240A9463 +:109A900012161306140605060895C9CF50D0E8F330 +:109AA000E894E0E0BB279F57F0F02AED3FE049EC57 +:109AB00006C0EE0FBB0F661F771F881F28F0B23A53 +:109AC00062077307840728F0B25A620B730B840B8A +:109AD000E3959A9572F7803830F49A95BB0F661F1C +:109AE000771F881FD2F7904896CF092E0394000C59 +:109AF00011F4882352F0BB0F40F4BF2B11F460FF28 +:109B000004C06F5F7F4F8F4F9F4F0895EF93E0FF2B +:109B100006C0A2EA2AED3FE049EC5FEB7DDDE5DF20 +:109B20000F90039401FC9058EDE9F0E0C7C157FD98 +:109B30009058440F551F59F05F3F71F04795880FBB +:109B400097FB991F61F09F3F79F087950895121652 +:109B500013061406551FF2CF4695F1DF08C01616FE +:109B600017061806991FF1CF8695710561050894AF +:109B70000895E5DFA0F0BEE7B91788F4BB279F384A +:109B800060F41616B11D672F782F8827985FF7CFDE +:109B9000869577956795B11D93959639C8F3089585 +:109BA000E894BB2766277727CB0197F90895ECDE69 +:109BB00008F48FEF089563DF19F068DF09F037CFFD +:109BC00007CFB901CA0125CF9F775F77B0DF98F340 +:109BD0009923B9F35523B9F3FF27951758F4E52FC7 +:109BE000E91BED3070F75E3B10F0F1E41CC09034DF +:109BF000E0F40AC0E92FE51BED3028F79E3B10F09A +:109C0000F1E411C0503488F4F9EA88232AF09A95D7 +:109C1000660F771F881FDAF744232AF05A95220F20 +:109C2000331F441FDAF79F1B5F1BFF931F930F9394 +:109C3000FF92EF9279018A01BB27AB2F9B01AC0108 +:109C400096D09701A801BF937B018C01AA27BA2F58 +:109C5000B901CA018CD0AF919701A801EF90FF9094 +:109C60000F911F91D9DC41DFE1D04F9140FF089562 +:109C7000552747FD509509C09B01AC0160E070E09D +:109C800080E89FE398CDA4CEC4CE59DFE8F39923B2 +:109C9000D9F3940F511DBBF39150504094F059F0FB +:109CA000882332F0660F771F881F91505040C1F70C +:109CB0009E3F510544F7880F911D9695879597F91A +:109CC00008955F3FACF0983E9CF0BB278695779552 +:109CD0006795B79508F4B1609395C1F7BB0F58F736 +:109CE00011F460FFE8CF6F5F7F4F8F4F9F4FE3CF3F +:109CF00058CF25DF58F19E5758F19851A0F0E9F060 +:109D0000983020F5092E9927660F771F881F991F15 +:109D10000A94D1F712C0062E672F782F8827985FF4 +:109D200011F4000C07C0993FB4F3869577956795B9 +:109D30009395D9F7611D711D811D3EF49095809515 +:109D4000709561957F4F8F4F9F4F0895689429CFED +:109D500027CF0BD0CACE93DE28F098DE18F09523DB +:109D600009F036CE64CE11241CCFE1DEA0F3959F1E +:109D7000D1F3950F50E0551F629FF001729FBB27F2 +:109D8000F00DB11D639FAA27F00DB11DAA1F649F9E +:109D90006627B00DA11D661F829F2227B00DA11D51 +:109DA000621F739FB00DA11D621F839FA00D611DD7 +:109DB000221F749F3327A00D611D231F849F600DF8 +:109DC000211D822F762F6A2F11249F5750408AF031 +:109DD000E1F088234AF0EE0FFF1FBB1F661F771FBD +:109DE000881F91505040A9F79E3F510570F0F0CD6B +:109DF000D8CE5F3FECF3983EDCF386957795679578 +:109E0000B795F795E7959F5FC1F7FE2B880F911DDA +:109E10009695879597F908959F9340DE0F9007FCDC +:109E2000EE5F74CE11F40EF402CEF3CD88DED0F3E3 +:109E30009923D9F3CEF39F57550B87FF38D00024D1 +:109E4000A0E640EA900180585695979528F4805CEA +:109E5000660F771F881F20F026173707480730F452 +:109E6000621B730B840B202931294A2BA69517946A +:109E70000794202531254A2758F7660F771F881F3A +:109E800020F026173707480730F4620B730B840B5A +:109E9000200D311D411DA09581F7B901842F9158E6 +:109EA000880F9695879508959B01AC0152CF9150EC +:109EB0005040660F771F881FD2F708959F938F93A6 +:109EC0007F936F93FF93EF939B01AC0142DFEF9180 +:109ED000FF91B0DD2F913F914F915F913ACF6ED0BE +:109EE000A59F900DB49F900DA49F800D911D1124EE +:109EF0000895B7FFF4CFF3DF821B930B0895DB01C6 +:109F00008F939F93ECDFBF91AF91A29F800D911D26 +:109F1000A39F900DB29F900D1124089597FB072EDB +:109F200016F4009406D077FD08D054D007FC05D075 +:109F30003EF4909581959F4F0895709561957F4F60 +:109F40000895A1E21A2EAA1BBB1BFD010DC0AA1F7A +:109F5000BB1FEE1FFF1FA217B307E407F50720F092 +:109F6000A21BB30BE40BF50B661F771F881F991F0D +:109F70001A9469F760957095809590959B01AC0156 +:109F8000BD01CF010895052E97FB16F4009406D06D +:109F900057FD0CD0D6DF07FC09D07EF49095809554 +:109FA000709561957F4F8F4F9F4F089550954095C5 +:109FB000309521953F4F4F4F5F4F0895A29FB001BD +:109FC000B39FC001A39F01D0B29F700D811D1124CA +:109FD000911D0895AA1BBB1B51E107C0AA1FBB1FFF +:109FE000A617B70710F0A61BB70B881F991F5A9525 +:109FF000A9F780959095BC01CD010895A0E0B0E04F +:10A00000E3E0F0E536C58B016115710519F0FB0140 +:10A01000808391837C01F701C1907F01EF018C2D3A +:10A0200090E04AD2892BB9F7FDE2CF1204C0C99063 +:10A03000DD24D39405C02BE2C21201C0C990D12CFB +:10A040007E0141E0E41AF10843E050E06FEB7FE06D +:10A05000C7013AD2892BE1F47E0182E0E80EF11CBF +:10A0600045E050E062EC7FE0C7012ED2892B21F45D +:10A070007E01E7E0EE0EF11C0115110519F0F80163 +:10A08000F182E08210E0D0E0C0E8D110F5C0F9C064 +:10A0900043E050E067EC7FE0C70116D2892B49F41A +:10A0A0000115110509F4EAC02296F801D183C08395 +:10A0B000E5C060E070E0CB01E12CF12CEC2DE05329 +:10A0C000EA3040F5FD2DF2602D2D2870D2FE06C03D +:10A0D000211126C02FEFE21AF20A22C0222319F022 +:10A0E00041E0E41AF108A5E0B0E09B01AC01F7DE25 +:10A0F000660F771F881F991F6E0F711D811D911D9F +:10A100006839E9E97E078E07E9E19E0748F0FD2DF1 +:10A11000F66006C0EE3F39F4D3FC3DC0FD2DF8607B +:10A12000C990DF2ECBCFE53311F0E531A1F5A88141 +:10A13000AD3219F4F0E1DF2A06C0AB3221F02196EE +:10A1400021E030E004C0A981229622E030E0A05353 +:10A15000AA3018F0C21BD30B1EC0FE0120E030E075 +:10A1600020384CE034075CF4A901440F551F440F1C +:10A17000551F240F351F220F331F2A0F311DA191A8 +:10A18000A053EF01AA3060F3D4FE03C031952195AE +:10A190003109E20EF31ED1FE07C00115110521F0B1 +:10A1A0002197F801D183C0839FDB2D2D23702330AD +:10A1B00029F0162FD72FC82F092F07C0DC01CB019C +:10A1C000B058182FD92FCA2F0B2F20E030E0A9014B +:10A1D000612F7D2F8C2F902FE7DA882309F452C04E +:10A1E000F7FE08C0F194E194F10836EFC32E3FE08A +:10A1F000D32E04C02EEDC22E2FE0D22E4601F8E160 +:10A200008F1A910890E2A92EB12C14C0F601459145 +:10A21000559165917491242F352F462F572F612F1B +:10A220007D2F8C2F902F95DD162FD72FC82F092F1C +:10A23000EA18FB08EA14FB044CF724E0C21AD10820 +:10A24000B594A794C814D904A9F7612F7D2F8C2F3A +:10A25000902F282F220F292F221F2F3F31F020E08F +:10A2600030E0A901A1DA81110DC082E290E0909363 +:10A27000F00A8093EF0A06C00FEF04C010E0D0E0B0 +:10A28000C0EC0FE7612F7D2F8C2F902FCDB7DEB75D +:10A29000ECE00BC4A0E0B0E0EFE4F1E5E6C32B0195 +:10A2A0008A016115710519F0FB0180839183011505 +:10A2B000110539F09801225031092332310508F097 +:10A2C000E3C07C01F701C1917F013F018C2F90E039 +:10A2D000F3D0892BB9F7CD3229F4F701C1913F01B1 +:10A2E000D1E006C0CB3219F4F701C1913F01D0E0B3 +:10A2F0000115110509F4D6C00031110581F4CEC055 +:10A30000F3018081883719F0883509F0C1C0F30165 +:10A31000C181F2E06F0E711CD26000E110E00830E4 +:10A320001105D9F024F402301105F9F407C00A3000 +:10A33000110551F000311105C1F424C0C12CD12CFC +:10A34000E12C30E4F32E23C00AE010E02CECC22E06 +:10A35000DC2CEC2C2CE0F22E1AC008E010E0C12C12 +:10A36000D12CE12C90E1F92E12C09801442737FD41 +:10A370004095542F60E070E080E090E8E2DD6901F4 +:10A380007A0105C0C12CD12CE12C88E0F82E40E0E8 +:10A3900060E070E0CB014801AA2497FCA094BA2C9D +:10A3A000EC2FE053EA3060F02C2F21542A3110F4C6 +:10A3B000E75006C02C2F21562A3120F5EC2FE75507 +:10A3C0002E2F30E020173107ECF447FD17C0C616DA +:10A3D000D706E806F90678F09B01AC01C501B40187 +:10A3E0008EDD6E0F711D811D911D6130710581051E +:10A3F00020E8920710F04FEF01C041E0F301C19156 +:10A400003F01CECF4114510491F0442339F0F1E0E3 +:10A410006F1A7108F2017182608209C0D1FF1BC0FE +:10A42000F2E06F1A7108F2017182608214C047FF76 +:10A4300012C0D0FF05C060E070E080E090E804C08A +:10A440006FEF7FEF8FEF9FE722E230E03093F00A6B +:10A450002093EF0A16C0D0FF08C0909580957095A4 +:10A4600061957F4F8F4F9F4F0CC097FF0AC082E2CC +:10A4700090E09093F00A8093EF0A6FEF7FEF8FEFF9 +:10A480009FE76B017C0112C0C12CD12C76010EC05C +:10A49000C0E30115110509F460CF41CFC03309F0C5 +:10A4A0003ECF2ECFC03309F04FCF2ACFB601C70120 +:10A4B000CDB7DEB7E0E1F5C2911132C2803219F0BA +:10A4C00089508550D0F70895FB01DC014150504080 +:10A4D00088F08D9181341CF08B350CF4805E659191 +:10A4E00061341CF06B350CF4605E861B611171F3F6 +:10A4F000990B0895881BFCCFFC018191861721F0F0 +:10A500008823D9F7992708953197CF010895FB0142 +:10A5100051915523A9F0BF01DC014D91451741111F +:10A52000E1F759F4CD010190002049F04D9140151B +:10A530004111C9F3FB014111EFCF81E090E0019798 +:10A540000895A0E1B0E0E6EAF2E59BC20F89188D1C +:10A5500086E08C831A8309838FEF9FE79E838D8328 +:10A56000AE01455E5F4F588B4F87698D7A8DCE0166 +:10A57000019608D0EF81F885E00FF11F10826096F8 +:10A58000E4E09BC2ACE0B0E0E7ECF2E56CC27C0139 +:10A590006B018A01FC0117821682838181FFBAC197 +:10A5A00088248394912C8C0E9D1EF7019381F601D3 +:10A5B00093FD859193FF81916F01882309F4A6C1D2 +:10A5C000853239F493FD859193FF81916F01853236 +:10A5D00021F4B70190E0BDD1E8CF712C312C20E0FF +:10A5E0002032A8F48B3261F028F4803251F08332AB +:10A5F00071F40BC08D3239F0803349F4216028C0EA +:10A600002260246025C0286023C0206121C027FD6E +:10A6100027C0382F30533A3078F426FF06C0FAE0CE +:10A620007F9E300D1124732E13C08AE0389E300DAA +:10A630001124332E20620CC08E3221F426FD66C117 +:10A64000206406C08C3611F4206802C0883641F4BC +:10A65000F60193FD859193FF81916F018111C0CF28 +:10A66000982F9554933018F09052933028F40C5F43 +:10A670001F4FFFE3F9830DC0833631F0833771F04C +:10A68000833509F05AC022C0F801808189830E5FAA +:10A690001F4F66246394712C540114C02801F2E00A +:10A6A0004F0E511CF801A080B18026FF03C0672D1A +:10A6B00070E002C06FEF7FEFC5012C873FD13C01F6 +:10A6C00082012C856FE7262E222217C02801F2E096 +:10A6D0004F0E511CF801A080B18026FF03C0672DEA +:10A6E00070E002C06FEF7FEFC5012C871CD13C01E9 +:10A6F0002C8550E8252E222A820123FC1AC005C091 +:10A70000B70180E290E025D13A94832D90E068165D +:10A710007906B0F30EC0F50127FC859127FE8191E3 +:10A720005F01B70190E015D131103A94F1E06F1A52 +:10A7300071086114710479F7E6C0843611F0893626 +:10A7400039F5F80127FF07C060817181828193810B +:10A750000C5F1F4F08C060817181882777FD80954D +:10A76000982F0E5F1F4F4FE6642E622297FF09C09D +:10A7700090958095709561957F4F8F4F9F4FF0E832 +:10A780006F2A2AE030E0A40110D1A82EA81843C0F7 +:10A79000853731F43FEEB32EB2222AE030E024C0F8 +:10A7A00099EFB92EB2228F36B9F020F4883509F02E +:10A7B000ADC00DC0803721F0883709F0A7C002C0B6 +:10A7C00020E1B22AB4FE0BC084E0B82A08C024FFFE +:10A7D00009C0E6E0BE2A06C028E030E005C020E15E +:10A7E00030E002C020E132E0F801B7FE07C060812E +:10A7F0007181828193810C5F1F4F06C060817181DE +:10A8000080E090E00E5F1F4FA401CFD0A82EA818C3 +:10A810008FE7682E6B2066FE0BC0362D3E7FA71497 +:10A8200050F464FE0AC062FC08C0362D3E7E05C0AE +:10A83000BA2C362D03C0BA2C01C0B72C34FF0DC082 +:10A84000FE01EA0DF11D8081803311F4397E09C0CB +:10A8500032FF06C0B394B39404C0832F867809F006 +:10A86000B39433FD13C030FF0EC07A2CB31458F4E8 +:10A87000730C7B18B32C07C0B70180E290E03C87D3 +:10A8800068D0B3943C85B314B8F304C0B31410F487 +:10A890003B1801C0312C34FF11C0B70180E390E0B8 +:10A8A0003C8757D03C8532FF1CC031FF03C088E590 +:10A8B00090E002C088E790E0B7010CC0832F867853 +:10A8C00081F031FD02C080E201C08BE237FD8DE2F4 +:10A8D000B70190E03ED005C0B70180E390E039D0E9 +:10A8E0007A94A714C8F3AA94F401EA0DF11DB701F4 +:10A8F000808190E02ED0A110F6CF05C0B70180E294 +:10A9000090E027D03A943110F9CF4FCEF70126814D +:10A91000378102C02FEF3FEFC9012C96E2E1BFC0A3 +:10A92000992788270895FC01059061507040011017 +:10A93000D8F7809590958E0F9F1F0895FC01615068 +:10A94000704001900110D8F7809590958E0F9F1F51 +:10A9500008950F931F93CF93DF938C01EB018B81AD +:10A9600081FD03C00FEF1FEF1AC082FF0DC02E81C3 +:10A970003F818C819D812817390764F4E881F98132 +:10A980000193F983E88306C0E885F985802F09954E +:10A99000892B41F78E819F8101969F838E83C80109 +:10A9A000DF91CF911F910F910895FA01AA272830C6 +:10A9B00051F1203181F1E8946F936E7F6E5F7F4F8C +:10A9C0008F4F9F4FAF4FB1E03ED0B4E03CD0670F08 +:10A9D000781F891F9A1FA11D680F791F8A1F911D5B +:10A9E000A11D6A0F711D811D911DA11D20D009F4AB +:10A9F00068943F912AE0269F11243019305D3193ED +:10AA0000DEF6CF010895462F4770405D4193B3E0D5 +:10AA10000FD0C9F7F6CF462F4F70405D4A3318F07C +:10AA2000495D31FD4052419302D0A9F7EACFB4E02D +:10AA3000A6959795879577956795BA95C9F70097E5 +:10AA40006105710508959B01AC010A2E0694579586 +:10AA5000479537952795BA95C9F7620F731F841FDD +:10AA6000951FA01D08952F923F924F925F926F9273 +:10AA70007F928F929F92AF92BF92CF92DF92EF928E +:10AA8000FF920F931F93CF93DF93CDB7DEB7CA1B0F +:10AA9000DB0B0FB6F894DEBF0FBECDBF09942A883A +:10AAA000398848885F846E847D848C849B84AA84E2 +:10AAB000B984C884DF80EE80FD800C811B81AA816F +:10AAC000B981CE0FD11D0FB6F894DEBF0FBECDBF3A +:08AAD000ED010895F894FFCF99 +:10AAD8006400640000803B4500803B4500007043F3 +:10AAE800000000000080BB440160EA000001010191 +:10AAF80001010000803F75608944A97E443E713D94 +:10AB0800E841FF3FFF3F010000A04214AE9F420012 +:10AB1800002045F6C815440000FA430000FA430037 +:10AB280000A04000003442282300002823000064CD +:10AB3800000000102700005573696E6720446566A1 +:10AB480061756C742073657474696E67733A004D2F +:10AB5800313130004820004C20002569206D696E95 +:10AB68002C20256920736563004D31303420496EEF +:10AB780076616C696420657874727564657220000A +:10AB88004D31303520496E76616C69642065787482 +:10AB9800727564657220004D31303920496E7661D6 +:10ABA8006C696420657874727564657220003F0072 +:10ABB8006F6B0020703A0020693A0020643A002048 +:10ABC800633A005400496E76616C69642065787454 +:10ABD800727564657200416374697665204578749E +:10ABE80072756465723A200058595A450000010090 +:10ABF8001A0019000A000000FFFF1C001B000A00D1 +:10AC08000100FFFF170016000A000200FFFFFFFF08 +:10AC1800FFFF04000E00180015000A0003000000E2 +:10AC28000100020002002E005374657072617465A1 +:10AC380020746F2068696768203A200050494420D2 +:10AC48004175746F74756E65207374617274000059 :00000001FF diff --git a/examples/board_reprap/reprap_flash.bin b/examples/board_reprap/reprap_flash.bin new file mode 100644 index 0000000..c97c12f Binary files /dev/null and b/examples/board_reprap/reprap_flash.bin differ diff --git a/examples/board_reprap/src/c3/README.md b/examples/board_reprap/src/c3/README.md deleted file mode 100644 index 31207ab..0000000 --- a/examples/board_reprap/src/c3/README.md +++ /dev/null @@ -1,77 +0,0 @@ -libc3 - No frill 'scene' graph library in C -===== -(C) 2012 Michel Pollet - -**WARNING** This API is not your nanny. It is made to be lean, mean, efficient -with no frill, no asserts, no bounds checking, no sugar coating. - -On the other hand it's fast, reasonably clean and is a micro-fraction of the -other giganormous 'scene graphs' or 'game engine' libraries around. - -It's vaguely inspired by THREE.js funnily enough, because it allows you to -hack around and quickly get stuff on screen with the minimal amount of -effort. - -The API has various bits: -* c3algebra: C derivative of an old C++ piece of code I had lying around and that has -been present in my toolset for a long time. It gives you *vectors* (c3vec2, c3vec3, c3vec4) -and *matrices* (c3mat3, c3mat4) with various tools to manipulate them. -* c3quaternion: Quaternion implementation using c3algebra -* c3camera/c3arcball: camera manipulation, not perfect - -The basic data structure is as follow: -* *c3context*: - Mostly placeholder for now, hosts a "root" object, can reproject the - objects & geometry, and call the callbacks to draw them. -* *c3object*: - * Has a list of (sub) c3objects - * Has a list of c3transforms (ie matrices) - * Has a list of c3geometry (ie real vertices and stuff) - The object is a container for other objects, and for geometry itself. Objects don't - necessary have geometry and/or sub objects, and don't even need transforms if their - vertices are already projected. -* *c3geometry*: - * Has a 'type' (raw for simple vertices, texture, triangles etc) - * Has a 'subtype' (mostly can be used to draw GL types) - * Has a 'material' (ie color, texture... to be completed) - * Has a list of vertices - * Has a list of texture coordinates (optional) - * Has a list of vertices colors (optional) - * Has a cached copy of a vertices when it has been 'projected' -* *c3transform*: - Is just a sugar coated matrix, with an optional name. - -Also there are: -* *c3pixels*: - Is just a wrapper/holder for some pixels, either allocated, or inherited, - it's mostly used for *c3texture* -* *c3texture*: - Associates a *c3geometry* with a *c3pixels* and has a standard Quad - for vertices. The OpenGL drawing is not done there, it's done by the application using - the generic *c3context* driver. -* *c3cairo*: - Placeholder for now, inherits from *c3texture* and will contain a - cairo surface mapped to a GL texture. -* *c3pango*: - A text label, inherits from *c3cairo* - -Draw Drivers "Inheritance" ------------- -Various object uses static tables of callbacks to implement their behaviours -it's kinda cheap c++ inheritance, without the usual bloat. - -There just a couple macros to call the driver chain for a particular function call. -The relevant bits are in c3driver*.h. - -Mostly the code looks for a matching callback in a static table, and call it if found. -If that callback wants, it can also call the inherited object callback too. - -Dirtyness ---------- -There is a notion of 'dirtyness' in the tree, when you touch a *c3transform*, and/remove -objects and geometry, a dirty bit is propagated up the tree of object. This tells the -rendering it needs to reproject the dirty bits and repopulate the projected vertice -cache. - -The 'dirty' bit moves both ways, when setting a dirty bit to true, it propagates upward, -when you set it to false, it propagates downward in the tree. diff --git a/examples/board_reprap/src/c3/c3.c b/examples/board_reprap/src/c3/c3.c deleted file mode 100644 index 38fcf83..0000000 --- a/examples/board_reprap/src/c3/c3.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - c3.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3.h" - diff --git a/examples/board_reprap/src/c3/c3.h b/examples/board_reprap/src/c3/c3.h deleted file mode 100644 index 410fa3e..0000000 --- a/examples/board_reprap/src/c3/c3.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - c3.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3_H___ -#define __C3_H___ - -#include "c3/c3context.h" -#include "c3/c3object.h" -#include "c3/c3geometry.h" -#include "c3/c3transform.h" -#include "c3/c3texture.h" - -#endif /* __C3_H___ */ diff --git a/examples/board_reprap/src/c3/c3algebra.c b/examples/board_reprap/src/c3/c3algebra.c deleted file mode 100644 index af816b1..0000000 --- a/examples/board_reprap/src/c3/c3algebra.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - c3algebra.c - - Copyright 2008-2012 Michel Pollet - - Derivative and inspiration from original C++: - Paul Rademacher & Jean-Francois DOUEG, - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include "c3/c3algebra.h" - -#ifndef MAX -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#define MIN(a,b) ((a)<(b) ? (a) : (b)) -#endif - -/**************************************************************** - * * - * c3vec2 Member functions * - * * - ****************************************************************/ - -/******************** c3vec2 CONSTRUCTORS ********************/ - -c3vec2 c3vec2_zero() -{ - c3vec2 n = { .x = 0, .y = 0 }; - return n; -} - -c3vec2 c3vec2f(c3f x, c3f y) -{ - c3vec2 v = { .x = x, .y = y }; - return v; -} - -/******************** c3vec2 ASSIGNMENT OPERATORS ******************/ - -c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v) -{ - a.n[VX] += v.n[VX]; - a.n[VY] += v.n[VY]; - return a; -} - -c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v) -{ - a.n[VX] -= v.n[VX]; - a.n[VY] -= v.n[VY]; - return a; -} - -c3vec2 c3vec2_mulf(c3vec2 a, c3f d) -{ - a.n[VX] *= d; - a.n[VY] *= d; - return a; -} - -c3vec2 c3vec2_divf(c3vec2 a, c3f d) -{ - c3f d_inv = 1.0f/d; - a.n[VX] *= d_inv; - a.n[VY] *= d_inv; - return a; -} - -/******************** c3vec2 SPECIAL FUNCTIONS ********************/ - - -c3f c3vec2_length2(const c3vec2 a) -{ - return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY]; -} - -c3f c3vec2_length(const c3vec2 a) -{ - return (c3f) sqrt(c3vec2_length2(a)); -} - -c3vec2 c3vec2_normalize(const c3vec2 a) // it is up to caller to avoid divide-by-zero -{ - return c3vec2_divf(a, c3vec2_length(a)); -} - -c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct) -{ - a.n[VX] = fct(a.n[VX]); - a.n[VY] = fct(a.n[VY]); - return a; -} - - -/******************** c3vec2 FRIENDS *****************************/ - -c3vec2 c3vec2_minus(const c3vec2 a) -{ - return c3vec2f(-a.n[VX],-a.n[VY]); -} - -c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v) -{ - c3vec2 av; - - av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ]; - av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ]; -// av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]; - - return av; -} - -c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a) -{ - c3mat3 t = c3mat3_transpose(a); - return c3mat3_mulv2(&t, v); -} - -c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v) -{ - c3vec3 av; - - av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ]*v.n[VZ]; - av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ]*v.n[VZ]; - av.n[VZ] = a->v[2].n[VX]*v.n[VX] + a->v[2].n[VY]*v.n[VY] + a->v[2].n[VZ]*v.n[VZ]; - - return av; -} - -c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a) -{ - c3mat3 t = c3mat3_transpose(a); - return c3mat3_mulv3(&t, v); -} - -c3f c3vec2_dot(const c3vec2 a, const c3vec2 b) -{ - return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]; -} - -c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b) -{ - return c3vec3f(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); -} - -int c3vec2_equal(const c3vec2 a, const c3vec2 b) -{ - return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); -} - - -c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b) -{ - return c3vec2f(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); -} - -c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b) -{ - return c3vec2f(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); -} - -c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b) -{ - return c3vec2f(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); -} - -/**************************************************************** - * * - * c3vec3 Member functions * - * * - ****************************************************************/ - -// CONSTRUCTORS - -c3vec3 c3vec3_zero() -{ - c3vec3 n = { .x = 0, .y = 0, .z = 0 }; - return n; -} - -c3vec3 c3vec3f(c3f x, c3f y, c3f z) -{ - c3vec3 v = { .x = x, .y = y, .z = z }; - return v; -} - -c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d) -{ - c3vec3 n = { .x = v.x, .y = v.y, .z = d }; - return n; -} - -c3vec3 c3vec3_vec2(const c3vec2 v) -{ - return c3vec3_vec2f(v, 1.0); -} - -c3vec3 c3vec3_vec4(const c3vec4 v) // it is up to caller to avoid divide-by-zero -{ - c3vec3 n; - n.n[VX] = v.n[VX] / v.n[VW]; - n.n[VY] = v.n[VY] / v.n[VW]; - n.n[VZ] = v.n[VZ] / v.n[VW]; - return n; -} - - -c3vec3 c3vec3_add(c3vec3 a, const c3vec3 v) -{ - a.n[VX] += v.n[VX]; - a.n[VY] += v.n[VY]; - a.n[VZ] += v.n[VZ]; - return a; -} - -c3vec3 c3vec3_sub(c3vec3 a, const c3vec3 v) -{ - a.n[VX] -= v.n[VX]; - a.n[VY] -= v.n[VY]; - a.n[VZ] -= v.n[VZ]; - return a; -} - -c3vec3 c3vec3_mulf(c3vec3 a, c3f d) -{ - a.n[VX] *= d; - a.n[VY] *= d; - a.n[VZ] *= d; - return a; -} - -c3vec3 c3vec3_divf(c3vec3 a, c3f d) -{ - c3f d_inv = 1.0f/d; - a.n[VX] *= d_inv; - a.n[VY] *= d_inv; - a.n[VZ] *= d_inv; - return a; -} - -// SPECIAL FUNCTIONS - -c3f c3vec3_length2(const c3vec3 a) -{ - return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ]; -} - -c3f c3vec3_length(const c3vec3 a) -{ - return (c3f) sqrt(c3vec3_length2(a)); -} - -c3vec3 c3vec3_normalize(const c3vec3 a) // it is up to caller to avoid divide-by-zero -{ - return c3vec3_divf(a, c3vec3_length(a)); -} - -c3vec3 c3vec3_homogenize(c3vec3 a) // it is up to caller to avoid divide-by-zero -{ - a.n[VX] /= a.n[VZ]; - a.n[VY] /= a.n[VZ]; - a.n[VZ] = 1.0; - return a; -} - -c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct) -{ - a.n[VX] = fct(a.n[VX]); - a.n[VY] = fct(a.n[VY]); - a.n[VZ] = fct(a.n[VZ]); - return a; -} - -// FRIENDS - -c3vec3 c3vec3_minus(const c3vec3 a) -{ - return c3vec3f(-a.n[VX],-a.n[VY],-a.n[VZ]); -} - -#if later -c3vec3 operator*(const c3mat4 &a, const c3vec3 &v) -{ - return a*c3vec4(v); -} - -c3vec3 operator*(const c3vec3 &v, c3mat4 &a) -{ - return a.transpose()*v; -} -#endif - -c3f c3vec3_dot(const c3vec3 a, const c3vec3 b) -{ - return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]; -} - -c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b) -{ - return - c3vec3f(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY], - a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ], - a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]); -} - -int c3vec3_equal(const c3vec3 a, const c3vec3 b) -{ - return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]); -} - - -c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b) -{ - return c3vec3f( - MIN(a.n[VX], b.n[VX]), - MIN(a.n[VY], b.n[VY]), - MIN(a.n[VZ], b.n[VZ])); -} - -c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b) -{ - return c3vec3f( - MAX(a.n[VX], b.n[VX]), - MAX(a.n[VY], b.n[VY]), - MAX(a.n[VZ], b.n[VZ])); -} - -c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b) -{ - return c3vec3f(a.n[VX]*b.n[VX], a.n[VY]*b.n[VY], a.n[VZ]*b.n[VZ]); -} - -/**************************************************************** - * * - * c3vec4 Member functions * - * * - ****************************************************************/ - -// CONSTRUCTORS - -c3vec4 c3vec4_zero() -{ - c3vec4 n = { .x = 0, .y = 0, .z = 0, .w = 1.0 }; - return n; -} - -c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w) -{ - c3vec4 n = { .x = x, .y = y, .z = z, .w = w }; - return n; -} - -c3vec4 c3vec4_vec3(const c3vec3 v) -{ - return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], 1.0); -} - -c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d) -{ - return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], d); -} - -// ASSIGNMENT OPERATORS - -c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v) -{ - a.n[VX] += v.n[VX]; - a.n[VY] += v.n[VY]; - a.n[VZ] += v.n[VZ]; - a.n[VW] += v.n[VW]; - return a; -} - -c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v) -{ - a.n[VX] -= v.n[VX]; - a.n[VY] -= v.n[VY]; - a.n[VZ] -= v.n[VZ]; - a.n[VW] -= v.n[VW]; - return a; -} - -c3vec4 c3vec4_mulf(c3vec4 a, c3f d) -{ - a.n[VX] *= d; - a.n[VY] *= d; - a.n[VZ] *= d; - a.n[VW] *= d; - return a; -} - -c3vec4 c3vec4_divf(c3vec4 a, c3f d) -{ - c3f d_inv = 1.0f/d; - a.n[VX] *= d_inv; - a.n[VY] *= d_inv; - a.n[VZ] *= d_inv; - a.n[VW] *= d_inv; - return a; -} - -// SPECIAL FUNCTIONS - -c3f c3vec4_length2(const c3vec4 a) -{ - return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ] + a.n[VW]*a.n[VW]; -} - -c3f c3vec4_length(const c3vec4 a) -{ - return (c3f) sqrt(c3vec4_length2(a)); -} - -c3vec4 c3vec4_normalize(c3vec4 a) // it is up to caller to avoid divide-by-zero -{ - return c3vec4_divf(a, c3vec4_length(a)); -} - -c3vec4 c3vec4_homogenize(c3vec4 a) // it is up to caller to avoid divide-by-zero -{ - a.n[VX] /= a.n[VW]; - a.n[VY] /= a.n[VW]; - a.n[VZ] /= a.n[VW]; - a.n[VW] = 1.0; - return a; -} - -c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct) -{ - a.n[VX] = fct(a.n[VX]); - a.n[VY] = fct(a.n[VY]); - a.n[VZ] = fct(a.n[VZ]); - a.n[VW] = fct(a.n[VW]); - return a; -} - -c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v) -{ - #define ROWCOL(i) \ - a->v[i].n[0]*v.n[VX] + \ - a->v[i].n[1]*v.n[VY] + \ - a->v[i].n[2]*v.n[VZ] + \ - a->v[i].n[3]*v.n[VW] - - return c3vec4f(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3)); - - #undef ROWCOL -} - -c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a) -{ - c3mat4 m = c3mat4_transpose(a); - return c3mat4_mulv4(&m, v); -} - -c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v) -{ - return c3vec3_vec4(c3mat4_mulv4(a, c3vec4_vec3(v))); -} - -c3vec4 c3vec4_minus(const c3vec4 a) -{ - return c3vec4f(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); -} - -int c3vec4_equal(const c3vec4 a, const c3vec4 b) -{ - return - (a.n[VX] == b.n[VX]) && - (a.n[VY] == b.n[VY]) && - (a.n[VZ] == b.n[VZ]) && - (a.n[VW] == b.n[VW]); -} - -c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b) -{ - return c3vec4f( - MIN(a.n[VX], b.n[VX]), - MIN(a.n[VY], b.n[VY]), - MIN(a.n[VZ], b.n[VZ]), - MIN(a.n[VW], b.n[VW])); -} - -c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b) -{ - return c3vec4f( - MAX(a.n[VX], b.n[VX]), - MAX(a.n[VY], b.n[VY]), - MAX(a.n[VZ], b.n[VZ]), - MAX(a.n[VW], b.n[VW])); -} - -c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b) -{ - return c3vec4f( - a.n[VX] * b.n[VX], - a.n[VY] * b.n[VY], - a.n[VZ] * b.n[VZ], - a.n[VW] * b.n[VW]); -} - -/**************************************************************** - * * - * c3mat3 member functions * - * * - ****************************************************************/ - -// CONSTRUCTORS - -c3mat3 c3mat3_identity() -{ - return identity2D(); -} - -c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2) -{ - c3mat3 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2 }; - return m; -} - -c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m) -{ - a->v[0] = c3vec3_add(a->v[0], m->v[0]); - a->v[1] = c3vec3_add(a->v[1], m->v[1]); - a->v[2] = c3vec3_add(a->v[2], m->v[2]); - return a; -} - -c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m) -{ - a->v[0] = c3vec3_sub(a->v[0], m->v[0]); - a->v[1] = c3vec3_sub(a->v[1], m->v[1]); - a->v[2] = c3vec3_sub(a->v[2], m->v[2]); - return a; -} - -c3mat3p c3mat3_mulf(const c3mat3p a, c3f d) -{ - a->v[0] = c3vec3_mulf(a->v[0], d); - a->v[1] = c3vec3_mulf(a->v[1], d); - a->v[2] = c3vec3_mulf(a->v[2], d); - return a; -} - -c3mat3p c3mat3_divf(const c3mat3p a, c3f d) -{ - a->v[0] = c3vec3_divf(a->v[0], d); - a->v[1] = c3vec3_divf(a->v[1], d); - a->v[2] = c3vec3_divf(a->v[2], d); - return a; -} - -// SPECIAL FUNCTIONS - -c3mat3 c3mat3_transpose(const c3mat3p a) -{ - return c3mat3_vec3( - c3vec3f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0]), - c3vec3f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1]), - c3vec3f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2])); -} - -c3mat3 c3mat3_inverse(const c3mat3p m) // Gauss-Jordan elimination with partial pivoting -{ - c3mat3 a = *m; // As a evolves from original mat into identity - c3mat3 b = c3mat3_identity(); // b evolves from identity into inverse(a) - int i, j, i1; - - // Loop over cols of a from left to right, eliminating above and below diag - for (j = 0; j < 3; j++) { // Find largest pivot in column j among rows j..2 - i1 = j; // Row with largest pivot candidate - for (i = j + 1; i < 3; i++) - if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) - i1 = i; - - // Swap rows i1 and j in a and b to put pivot on diagonal - c3vec3 _s; - _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]); - _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; //swap(b.v[i1], b.v[j]); - - // Scale row j to have a unit diagonal - if (a.v[j].n[j] == 0.) { - // VEC_ERROR("c3mat3::inverse: singular matrix; can't invert\n"); - return *m; - } - - b.v[j] = c3vec3_divf(b.v[j], a.v[j].n[j]); - a.v[j] = c3vec3_divf(a.v[j], a.v[j].n[j]); - - // Eliminate off-diagonal elems in col j of a, doing identical ops to b - for (i = 0; i < 3; i++) - if (i != j) { - b.v[i] = c3vec3_sub(b.v[i], c3vec3_mulf(b.v[j], a.v[i].n[j])); - a.v[i] = c3vec3_sub(a.v[i], c3vec3_mulf(a.v[j], a.v[i].n[j])); - } - } - - return b; -} - -c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct) -{ - a->v[0] = c3vec3_apply(a->v[0], fct); - a->v[1] = c3vec3_apply(a->v[1], fct); - a->v[2] = c3vec3_apply(a->v[2], fct); - return a; -} - - -c3mat3 c3mat3_minus(const c3mat3p a) -{ - return c3mat3_vec3( - c3vec3_minus(a->v[0]), - c3vec3_minus(a->v[1]), - c3vec3_minus(a->v[2])); -} - -c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b) -{ - #define ROWCOL(i, j) \ - a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j] - - return c3mat3_vec3( - c3vec3f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)), - c3vec3f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)), - c3vec3f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2))); - - #undef ROWCOL -} - -int c3mat3_equal(const c3mat3p a, const c3mat3p b) -{ - return - c3vec3_equal(a->v[0], b->v[0]) && - c3vec3_equal(a->v[1], b->v[1]) && - c3vec3_equal(a->v[2], b->v[2]); -} - -/**************************************************************** - * * - * c3mat4 member functions * - * * - ****************************************************************/ - -// CONSTRUCTORS - -c3mat4 c3mat4_identity() -{ - return identity3D(); -} - -c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3) -{ - c3mat4 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2, .v[3] = v3 }; - return m; -} - -c3mat4 c3mat4f( - c3f a00, c3f a01, c3f a02, c3f a03, - c3f a10, c3f a11, c3f a12, c3f a13, - c3f a20, c3f a21, c3f a22, c3f a23, - c3f a30, c3f a31, c3f a32, c3f a33 ) -{ - c3mat4 m; - m.v[0] = c3vec4f(a00, a01, a01, a03); - m.v[1] = c3vec4f(a10, a11, a11, a13); - m.v[2] = c3vec4f(a20, a21, a21, a23); - m.v[3] = c3vec4f(a30, a31, a21, a33); - return m; -} - -c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m) -{ - a->v[0] = c3vec4_add(a->v[0], m->v[0]); - a->v[1] = c3vec4_add(a->v[1], m->v[1]); - a->v[2] = c3vec4_add(a->v[2], m->v[2]); - a->v[3] = c3vec4_add(a->v[3], m->v[3]); - return a; -} - -c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m) -{ - a->v[0] = c3vec4_sub(a->v[0], m->v[0]); - a->v[1] = c3vec4_sub(a->v[1], m->v[1]); - a->v[2] = c3vec4_sub(a->v[2], m->v[2]); - a->v[3] = c3vec4_sub(a->v[3], m->v[3]); - return a; -} - -c3mat4p c3mat4p_mulf(c3mat4p a, c3f d) -{ - a->v[0] = c3vec4_mulf(a->v[0], d); - a->v[1] = c3vec4_mulf(a->v[1], d); - a->v[2] = c3vec4_mulf(a->v[2], d); - a->v[3] = c3vec4_mulf(a->v[3], d); - return a; -} - -c3mat4p c3mat4p_divf(c3mat4p a, c3f d) -{ - a->v[0] = c3vec4_divf(a->v[0], d); - a->v[1] = c3vec4_divf(a->v[1], d); - a->v[2] = c3vec4_divf(a->v[2], d); - a->v[3] = c3vec4_divf(a->v[3], d); - return a; -} - -// SPECIAL FUNCTIONS; - -c3mat4 c3mat4_transpose(const c3mat4p a) -{ - return c3mat4_vec4( - c3vec4f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0], a->v[3].n[0]), - c3vec4f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1], a->v[3].n[1]), - c3vec4f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2], a->v[3].n[2]), - c3vec4f(a->v[0].n[3], a->v[1].n[3], a->v[2].n[3], a->v[3].n[3])); -} - -c3mat4 c3mat4_inverse(const c3mat4p m) // Gauss-Jordan elimination with partial pivoting -{ - c3mat4 a = *m; // As a evolves from original mat into identity - c3mat4 b = identity3D(); // b evolves from identity into inverse(a) - int i, j, i1; - - // Loop over cols of a from left to right, eliminating above and below diag - for (j = 0; j < 4; j++) { // Find largest pivot in column j among rows j..3 - i1 = j; // Row with largest pivot candidate - for (i = j + 1; i < 4; i++) - if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) - i1 = i; - - // Swap rows i1 and j in a and b to put pivot on diagonal - c3vec4 _s; - _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]); - _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; // swap(b.v[i1], b.v[j]); - - // Scale row j to have a unit diagonal - if (a.v[j].n[j] == 0.) { - // VEC_ERROR("c3mat4::inverse: singular matrix; can't invert\n"); - return a; - } - b.v[j] = c3vec4_divf(b.v[j], a.v[j].n[j]); - a.v[j] = c3vec4_divf(a.v[j], a.v[j].n[j]); - - // Eliminate off-diagonal elems in col j of a, doing identical ops to b - for (i = 0; i < 4; i++) - if (i != j) { - b.v[i] = c3vec4_sub(b.v[i], c3vec4_mulf(b.v[j], a.v[i].n[j])); - a.v[i] = c3vec4_sub(a.v[i], c3vec4_mulf(a.v[j], a.v[i].n[j])); - } - } - - return b; -} - -c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct) -{ - a->v[0] = c3vec4_apply(a->v[0], fct); - a->v[1] = c3vec4_apply(a->v[1], fct); - a->v[2] = c3vec4_apply(a->v[2], fct); - a->v[3] = c3vec4_apply(a->v[3], fct); - return a; -} - -c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j) -{ - c3vec4 t; - - t = a->v[i]; - a->v[i] = a->v[j]; - a->v[j] = t; - return a; -} - -c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j) -{ - c3f t; - - for (int k = 0; k < 4; k++) { - t = a->v[k].n[i]; - a->v[k].n[i] = a->v[k].n[j]; - a->v[k].n[j] = t; - } - return a; -} - - -// FRIENDS - -c3mat4 c3mat4_minus(const c3mat4p a) -{ - return c3mat4_vec4( - c3vec4_minus(a->v[0]), - c3vec4_minus(a->v[1]), - c3vec4_minus(a->v[2]), - c3vec4_minus(a->v[3])); -} - -c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b) -{ - return c3mat4_vec4( - c3vec4_add(a->v[0], b->v[0]), - c3vec4_add(a->v[1], b->v[1]), - c3vec4_add(a->v[2], b->v[2]), - c3vec4_add(a->v[3], b->v[3])); -} - -c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b) -{ - return c3mat4_vec4( - c3vec4_sub(a->v[0], b->v[0]), - c3vec4_sub(a->v[1], b->v[1]), - c3vec4_sub(a->v[2], b->v[2]), - c3vec4_sub(a->v[3], b->v[3])); -} - -c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b) -{ - #define ROWCOL(i, j) \ - a->v[i].n[0]*b->v[0].n[j] + \ - a->v[i].n[1]*b->v[1].n[j] + \ - a->v[i].n[2]*b->v[2].n[j] + \ - a->v[i].n[3]*b->v[3].n[j] - - return c3mat4_vec4( - c3vec4f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)), - c3vec4f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)), - c3vec4f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)), - c3vec4f(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3)) - ); - - #undef ROWCOL -} - -c3mat4 c3mat4_mulf(const c3mat4p a, c3f d) -{ - c3mat4 r = *a; - return *c3mat4p_mulf(&r, d); -} - -c3mat4 c3mat4_divf(const c3mat4p a, c3f d) -{ - c3mat4 r = *a; - return *c3mat4p_divf(&r, d); -} - -int c3mat4_equal(const c3mat4p a, const c3mat4p b) -{ - return !memcmp(a->n, b->n, sizeof(a->n)); -#if 0 - return - c3vec4_equal(a->v[0], b->v[0]) && - c3vec4_equal(a->v[1], b->v[1]) && - c3vec4_equal(a->v[2], b->v[2]) && - c3vec4_equal(a->v[3], b->v[3]); -#endif -} - -/**************************************************************** - * * - * 2D functions and 3D functions * - * * - ****************************************************************/ - -c3mat3 identity2D() -{ - return c3mat3_vec3( - c3vec3f(1.0, 0.0, 0.0), - c3vec3f(0.0, 1.0, 0.0), - c3vec3f(0.0, 0.0, 1.0)); -} - -c3mat3 translation2D(const c3vec2 v) -{ - return c3mat3_vec3( - c3vec3f(1.0, 0.0, v.n[VX]), - c3vec3f(0.0, 1.0, v.n[VY]), - c3vec3f(0.0, 0.0, 1.0)); -} - -c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg) -{ - c3f angleRad = (c3f) (angleDeg * M_PI / 180.0); - c3f c = (c3f) cos(angleRad); - c3f s = (c3f) sin(angleRad); - - return c3mat3_vec3( - c3vec3f(c, -s, Center.n[VX] * (1.0f-c) + Center.n[VY] * s), - c3vec3f(s, c, Center.n[VY] * (1.0f-c) - Center.n[VX] * s), - c3vec3f(0.0, 0.0, 1.0)); -} - -c3mat3 scaling2D(const c3vec2 scaleVector) -{ - return c3mat3_vec3( - c3vec3f(scaleVector.n[VX], 0.0, 0.0), - c3vec3f(0.0, scaleVector.n[VY], 0.0), - c3vec3f(0.0, 0.0, 1.0)); -} - -c3mat4 identity3D() -{ - return c3mat4_vec4( - c3vec4f(1.0, 0.0, 0.0, 0.0), - c3vec4f(0.0, 1.0, 0.0, 0.0), - c3vec4f(0.0, 0.0, 1.0, 0.0), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} - -c3mat4 translation3D(const c3vec3 v) -{ - return c3mat4_vec4( - c3vec4f(1.0, 0.0, 0.0, v.n[VX]), - c3vec4f(0.0, 1.0, 0.0, v.n[VY]), - c3vec4f(0.0, 0.0, 1.0, v.n[VZ]), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} - -c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg) -{ - c3f angleRad = (c3f) (angleDeg * M_PI / 180.0); - c3f c = (c3f) cos(angleRad); - c3f s = (c3f) sin(angleRad); - c3f t = 1.0f - c; - - c3vec3 axis = c3vec3_normalize(Axis); - - return c3mat4_vec4( - c3vec4f(t * axis.n[VX] * axis.n[VX] + c, - t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ], - t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY], - 0.0), - c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ], - t * axis.n[VY] * axis.n[VY] + c, - t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX], - 0.0), - c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY], - t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX], - t * axis.n[VZ] * axis.n[VZ] + c, - 0.0), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} - -c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad) -{ - c3f c = (c3f) cos(angleRad); - c3f s = (c3f) sin(angleRad); - c3f t = 1.0f - c; - - c3vec3 axis = c3vec3_normalize(Axis); - - return c3mat4_vec4( - c3vec4f(t * axis.n[VX] * axis.n[VX] + c, - t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ], - t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY], - 0.0), - c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ], - t * axis.n[VY] * axis.n[VY] + c, - t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX], - 0.0), - c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY], - t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX], - t * axis.n[VZ] * axis.n[VZ] + c, - 0.0), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} - -c3mat4 scaling3D(const c3vec3 scaleVector) -{ - return c3mat4_vec4( - c3vec4f(scaleVector.n[VX], 0.0, 0.0, 0.0), - c3vec4f(0.0, scaleVector.n[VY], 0.0, 0.0), - c3vec4f(0.0, 0.0, scaleVector.n[VZ], 0.0), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} - -c3mat4 perspective3D(c3f d) -{ - return c3mat4_vec4( - c3vec4f(1.0f, 0.0f, 0.0f, 0.0f), - c3vec4f(0.0f, 1.0f, 0.0f, 0.0f), - c3vec4f(0.0f, 0.0f, 1.0f, 0.0f), - c3vec4f(0.0f, 0.0f, 1.0f/d, 0.0f)); -} - diff --git a/examples/board_reprap/src/c3/c3algebra.h b/examples/board_reprap/src/c3/c3algebra.h deleted file mode 100644 index d2b71a1..0000000 --- a/examples/board_reprap/src/c3/c3algebra.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - c3algebra.h - - Copyright 2008-2012 Michel Pollet - - Derivative and inspiration from original C++: - Paul Rademacher & Jean-Francois DOUEG, - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3ALGEBRA_H___ -#define __C3ALGEBRA_H___ - - -#ifndef M_PI -#define M_PI 3.141592654 -#endif - -enum {VX, VY, VZ, VW}; // axes -enum {PA, PB, PC, PD}; // planes -enum {RED, GREEN, BLUE, ALPHA}; // colors -enum {KA, KD, KS, ES}; // phong coefficients - -typedef float c3f; -typedef c3f (*V_FCT_PTR)(c3f); - -typedef union c3vec2 { - struct { c3f x,y; }; - c3f n[2]; -} c3vec2; - -typedef union c3vec3 { - struct { c3f x,y,z; }; - c3f n[3]; -} c3vec3; - -typedef union c3vec4 { - struct { c3f x,y,z,w; }; - c3f n[4]; -} c3vec4, * c3vec4p; - -typedef union c3mat3 { - c3vec3 v[3]; - c3f n[3*3]; -} c3mat3, * c3mat3p; - -typedef union c3mat4 { - c3vec4 v[4]; - c3f n[4*4]; -} c3mat4, * c3mat4p; - -/* - * c3vec2 related - */ - -c3vec2 c3vec2_zero(); -c3vec2 c3vec2f(c3f x, c3f y); - -c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v); -c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v); -c3vec2 c3vec2_mulf(c3vec2 a, c3f d); -c3vec2 c3vec2_divf(c3vec2 a, c3f d); - -c3f c3vec2_length2(const c3vec2 a); -c3f c3vec2_length(const c3vec2 a); -c3vec2 c3vec2_normalize(const c3vec2 a); // it is up to caller to avoid divide-by-zero -c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct); -c3vec2 c3vec2_minus(const c3vec2 a); -c3f c3vec2_dot(const c3vec2 a, const c3vec2 b); -c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b); -c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b); -c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b); - -/* - * c3vec4 related - */ - -c3vec3 c3vec3_zero(); -c3vec3 c3vec3f(c3f x, c3f y, c3f z); -c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d); -c3vec3 c3vec3_vec2(const c3vec2 v); -c3vec3 c3vec3_vec4(const c3vec4 v); // it is up to caller to avoid divide-by-zero - -c3vec3 c3vec3_add(const c3vec3 a, const c3vec3 v); -c3vec3 c3vec3_sub(const c3vec3 a, const c3vec3 v); -c3vec3 c3vec3_mulf(const c3vec3 a, c3f d); -c3vec3 c3vec3_divf(const c3vec3 a, c3f d); - -c3f c3vec3_length2(const c3vec3 a); -c3f c3vec3_length(const c3vec3 a); -c3vec3 c3vec3_normalize(const c3vec3 a); // it is up to caller to avoid divide-by-zero -c3vec3 c3vec3_homogenize(c3vec3 a); // it is up to caller to avoid divide-by-zero -c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct); -c3vec3 c3vec3_minus(const c3vec3 a); -c3f c3vec3_dot(const c3vec3 a, const c3vec3 b); -int c3vec3_equal(const c3vec3 a, const c3vec3 b); -c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b); -c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b); -c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b); - -c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b); -c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b); - -/* - * c3vec4 related - */ - -c3vec4 c3vec4_zero(); -c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w); -c3vec4 c3vec4_vec3(const c3vec3 v); -c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d); - -c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v); -c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v); -c3vec4 c3vec4_mulf(c3vec4 a, c3f d); -c3vec4 c3vec4_divf(c3vec4 a, c3f d); - -c3f c3vec4_length2(const c3vec4 a); -c3f c3vec4_length(const c3vec4 a); -c3vec4 c3vec4_normalize(c3vec4 a); // it is up to caller to avoid divide-by-zero -c3vec4 c3vec4_homogenize(c3vec4 a); // it is up to caller to avoid divide-by-zero -c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct); -c3vec4 c3vec4_minus(const c3vec4 a); -int c3vec4_equal(const c3vec4 a, const c3vec4 b); -c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b); -c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b); -c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b); - -/* - * c3mat3 related - */ - -c3mat3 c3mat3_identity(); -c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2); -c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m); -c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m); -c3mat3p c3mat3_mulf(const c3mat3p a, c3f d); -c3mat3p c3mat3_divf(const c3mat3p a, c3f d); - -c3mat3 c3mat3_transpose(const c3mat3p a); -c3mat3 c3mat3_inverse(const c3mat3p m); // Gauss-Jordan elimination with partial pivoting -c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct); -c3mat3 c3mat3_minus(const c3mat3p a); - -c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b); -int c3mat3_equal(const c3mat3p a, const c3mat3p b); - -c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v); -c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v); -c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a); -c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a); - -c3mat3 identity2D(); -c3mat3 translation2D(const c3vec2 v); -c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg); -c3mat3 scaling2D(const c3vec2 scaleVector); - -/* - * c3mat4 related - */ - -c3mat4 c3mat4_identity(); -c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3); -c3mat4 c3mat4f( - c3f a00, c3f a01, c3f a02, c3f a03, - c3f a10, c3f a11, c3f a12, c3f a13, - c3f a20, c3f a21, c3f a22, c3f a23, - c3f a30, c3f a31, c3f a32, c3f a33 ); - -c3mat4 c3mat4_minus(const c3mat4p a); -c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m); -c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b); -c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m); -c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b); -c3mat4p c3mat4p_mulf(c3mat4p a, c3f d); -c3mat4 c3mat4_mulf(const c3mat4p a, c3f d); -c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b); -c3mat4p c3mat4p_divf(c3mat4p a, c3f d); -c3mat4 c3mat4_divf(const c3mat4p a, c3f d); - -c3mat4 c3mat4_transpose(const c3mat4p a); -c3mat4 c3mat4_inverse(const c3mat4p m); // Gauss-Jordan elimination with partial pivoting -c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct); -c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j); -c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j); -int c3mat4_equal(const c3mat4p a, const c3mat4p b); - -c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a); -c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v); -c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v); - -c3mat4 identity3D(); -c3mat4 translation3D(const c3vec3 v); -c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg); -c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad); -c3mat4 scaling3D(const c3vec3 scaleVector); -c3mat4 perspective3D(c3f d); - -#endif /* __C3ALGEBRA_H___ */ diff --git a/examples/board_reprap/src/c3/c3arcball.c b/examples/board_reprap/src/c3/c3arcball.c deleted file mode 100644 index ff412d8..0000000 --- a/examples/board_reprap/src/c3/c3arcball.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - c3arcball.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "c3/c3arcball.h" - - -/**************************************** c3arcball_init_mat4() ****/ -/* Takes as argument a c3mat4 to use instead of the internal rot */ - -void -c3arcball_init_mat4( - c3arcballp a, - c3mat4p mtx ) -{ - c3arcball_init(a); - a->rot_ptr = mtx; -} - - -/**************************************** c3arcball_init_center() ****/ -/* A constructor that accepts the screen center and arcball radius*/ - -void -c3arcball_init_center( - c3arcballp a, - const c3vec2 center, - c3f radius ) -{ - c3arcball_init(a); - c3arcball_set_params(a, center, radius); -} - - -/************************************** c3arcball_set_params() ****/ - -void -c3arcball_set_params( - c3arcballp a, - const c3vec2 center, - c3f radius) -{ - a->center = center; - a->radius = radius; -} - -/*************************************** c3arcball_init() **********/ - -void -c3arcball_init( - c3arcballp a ) -{ - a->center = c3vec2f( 0.0, 0.0 ); - a->radius = 1.0; - a->q_now = c3quat_identity(); - a->rot_ptr = &a->rot; - a->rot = identity3D(); - a->q_increment = c3quat_identity(); - a->rot_increment = identity3D(); - a->is_mouse_down = false; - a->is_spinning = false; - a->damp_factor = 0.0; - a->zero_increment = true; -} - -/*********************************** c3arcball_mouse_to_sphere() ****/ - -c3vec3 -c3arcball_mouse_to_sphere( - c3arcballp a, - const c3vec2 p) -{ - c3f mag; - c3vec2 v2 = c3vec2_divf(c3vec2_sub(p, a->center), a->radius); - c3vec3 v3 = c3vec3f( v2.n[0], v2.n[1], 0.0 ); - - mag = c3vec2_dot(v2, v2); - - if ( mag > 1.0 ) - v3 = c3vec3_normalize(v3); - else - v3.n[VZ] = (c3f) sqrt( 1.0 - mag ); - - /* Now we add constraints - X takes precedence over Y */ - if ( a->constraint_x ) { - v3 = c3arcball_constrain_vector( v3, c3vec3f( 1.0, 0.0, 0.0 )); - } else if ( a->constraint_y ) { - v3 = c3arcball_constrain_vector( v3, c3vec3f( 0.0, 1.0, 0.0 )); - } - - return v3; -} - - -/************************************ c3arcball_constrain_vector() ****/ - -c3vec3 -c3arcball_constrain_vector( - const c3vec3 vector, - const c3vec3 axis) -{ -// return (vector - (vector * axis) * axis).normalize(); - return vector; -} - -/************************************ c3arcball_mouse_down() **********/ - -void -c3arcball_mouse_down( - c3arcballp a, - int x, - int y) -{ - a->down_pt = c3vec2f( (c3f)x, (c3f) y ); - a->is_mouse_down = true; - - a->q_increment = c3quat_identity(); - a->rot_increment = identity3D(); - a->zero_increment = true; -} - - -/************************************ c3arcball_mouse_up() **********/ - -void -c3arcball_mouse_up( - c3arcballp a) -{ - a->q_now = c3quat_mul(a->q_drag, a->q_now); - a->is_mouse_down = false; -} - - -/********************************** c3arcball_mouse_motion() **********/ - -void -c3arcball_mouse_motion( - c3arcballp a, - int x, - int y, - int shift, - int ctrl, - int alt) -{ - /* Set the X constraint if CONTROL key is pressed, Y if ALT key */ - c3arcball_set_constraints(a, ctrl != 0, alt != 0 ); - - c3vec2 new_pt = c3vec2f( (c3f)x, (c3f) y ); - c3vec3 v0 = c3arcball_mouse_to_sphere(a, a->down_pt ); - c3vec3 v1 = c3arcball_mouse_to_sphere(a, new_pt ); - - c3vec3 cross = c3vec3_cross(v0, v1); - - a->q_drag = c3quat_vec3(cross, c3vec3_dot(v0, v1)); - - // *rot_ptr = (q_drag * q_now).to_mat4(); - c3mat4 temp = c3quat_to_mat4(a->q_drag); - *a->rot_ptr = c3mat4_mul(a->rot_ptr, &temp); - - a->down_pt = new_pt; - - /* We keep a copy of the current incremental rotation (= q_drag) */ - a->q_increment = a->q_drag; - a->rot_increment = c3quat_to_mat4(a->q_increment); - - c3arcball_set_constraints(a, false, false); - - if (a->q_increment.s < .999999) { - a->is_spinning = true; - a->zero_increment = false; - } else { - a->is_spinning = false; - a->zero_increment = true; - } -} - - -/********************************** c3arcball_mouse_motion() **********/ -#if 0 -void -c3arcball_mouse_motion( - c3arcballp a, - int x, - int y) -{ - mouse_motion(x, y, 0, 0, 0); -} -#endif - -/***************************** c3arcball_set_constraints() **********/ - -void -c3arcball_set_constraints( - c3arcballp a, - bool _constraint_x, - bool _constraint_y) -{ - a->constraint_x = _constraint_x; - a->constraint_y = _constraint_y; -} - -/***************************** c3arcball_idle() *********************/ - -void -c3arcball_idle( - c3arcballp a) -{ - if (a->is_mouse_down) { - a->is_spinning = false; - a->zero_increment = true; - } - - if (a->damp_factor < 1.0f) - c3quat_scale_angle(&a->q_increment, 1.0f - a->damp_factor); - - a->rot_increment = c3quat_to_mat4(a->q_increment); - - if (a->q_increment.s >= .999999f) { - a->is_spinning = false; - a->zero_increment = true; - } -} - - -/************************ c3arcball_set_damping() *********************/ - -void -c3arcball_set_damping( - c3arcballp a, - c3f d) -{ - a->damp_factor = d; -} - - - diff --git a/examples/board_reprap/src/c3/c3arcball.h b/examples/board_reprap/src/c3/c3arcball.h deleted file mode 100644 index 2adba8b..0000000 --- a/examples/board_reprap/src/c3/c3arcball.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - c3arcball.h - - Copyright 2008-2012 Michel Pollet - Copyright (c) 1998 Paul Rademacher - Feb 1998, Paul Rademacher (rademach@cs.unc.edu) - Oct 2003, Nigel Stewart - GLUI Code Cleaning - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -/* - Arcball, as described by Ken - Shoemake in Graphics Gems IV. - This class takes as input mouse events (mouse down, mouse drag, - mouse up), and creates the appropriate quaternions and 4x4 matrices - to represent the rotation given by the mouse. - - This class is used as follows: - - initialize [either in the constructor or with set_params()], the - center position (x,y) of the arcball on the screen, and the radius - - on mouse down, call mouse_down(x,y) with the mouse position - - as the mouse is dragged, repeatedly call mouse_motion() with the - current x and y positions. One can optionally pass in the current - state of the SHIFT, ALT, and CONTROL keys (passing zero if keys - are not pressed, non-zero otherwise), which constrains - the rotation to certain axes (X for CONTROL, Y for ALT). - - when the mouse button is released, call mouse_up() - - Axis constraints can also be explicitly set with the - set_constraints() function. - - The current rotation is stored in the 4x4 float matrix 'rot'. - It is also stored in the quaternion 'q_now'. - */ - -#ifndef __C3ARCBALL_H___ -#define __C3ARCBALL_H___ - -#include "c3/c3quaternion.h" - -typedef struct c3arcball { - int is_mouse_down : 1, /* true for down, false for up */ - is_spinning : 1, - constraint_x : 1, - constraint_y : 1, - zero_increment : 1; - c3quat q_now, q_down, q_drag, q_increment; - c3vec2 down_pt; - c3mat4 rot, rot_increment; - c3mat4 *rot_ptr; - - c3vec2 center; - c3f radius, damp_factor; -} c3arcball, *c3arcballp; - -void -c3arcball_init( - c3arcballp a ); -void -c3arcball_init_mat4( - c3arcballp a, - c3mat4p mtx ); -void -c3arcball_init_center( - c3arcballp a, - const c3vec2 center, - c3f radius ); -void -c3arcball_set_params( - c3arcballp a, - const c3vec2 center, - c3f radius); -c3vec3 -c3arcball_mouse_to_sphere( - c3arcballp a, - const c3vec2 p); -c3vec3 -c3arcball_constrain_vector( - const c3vec3 vector, - const c3vec3 axis); -void -c3arcball_mouse_down( - c3arcballp a, - int x, - int y); -void -c3arcball_mouse_up( - c3arcballp a); - -void -c3arcball_mouse_motion( - c3arcballp a, - int x, - int y, - int shift, - int ctrl, - int alt); -void -c3arcball_set_constraints( - c3arcballp a, - bool _constraint_x, - bool _constraint_y); -void -c3arcball_idle( - c3arcballp a); -void -c3arcball_set_damping( - c3arcballp a, - c3f d); - -#endif /* __C3ARCBALL_H___ */ diff --git a/examples/board_reprap/src/c3/c3cairo.c b/examples/board_reprap/src/c3/c3cairo.c deleted file mode 100644 index 840822c..0000000 --- a/examples/board_reprap/src/c3/c3cairo.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - c3cairo.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3cairo.h" -#include "c3/c3driver_geometry.h" - -void -_c3cairo_dispose( - c3geometry_p g, - const c3driver_geometry_t * d) -{ - c3cairo_p c = (c3cairo_p)g; - - if (c->cr) - cairo_destroy(c->cr); - if (c->surface) - cairo_surface_destroy(c->surface); - C3_DRIVER_INHERITED(g, d, dispose); -} - -static void -_c3cairo_project( - c3geometry_p g, - const struct c3driver_geometry_t *d, - c3mat4p m) -{ - C3_DRIVER_INHERITED(g, d, project, m); -} - -const c3driver_geometry_t c3cairo_base_driver = { - .dispose = _c3cairo_dispose, - .project = _c3cairo_project, -}; -const c3driver_geometry_t c3texture_driver; -const c3driver_geometry_t c3geometry_driver; - -c3cairo_p -c3cairo_new( - struct c3object_t * parent) -{ - c3cairo_p res = malloc(sizeof(*res)); - return c3cairo_init(res, parent); -} - -c3cairo_p -c3cairo_init( - c3cairo_p o, - struct c3object_t * parent) -{ - memset(o, 0, sizeof(*o)); - c3texture_init(&o->tex, parent); - - static const c3driver_geometry_t * list[] = { - &c3cairo_base_driver, &c3texture_driver, &c3geometry_driver, NULL, - }; - ((c3geometry_p)o)->driver = list; - - return o; -} - -c3cairo_p -c3cairo_new_offscreen( - struct c3object_t * parent, - int w, int h) -{ - c3cairo_p o = c3cairo_new(parent); - - o->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - o->cr = cairo_create(o->surface); - - c3pixels_init(&o->tex.pixels, w, h, 4, - cairo_image_surface_get_stride(o->surface), - cairo_image_surface_get_data(o->surface)); - - return o; -} - -#if 0 -cairo_surface_destroy(_surface); -else -cairo_surface_finish(_surface); -#endif diff --git a/examples/board_reprap/src/c3/c3cairo.h b/examples/board_reprap/src/c3/c3cairo.h deleted file mode 100644 index 75082b3..0000000 --- a/examples/board_reprap/src/c3/c3cairo.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - c3cairo.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3CAIRO_H___ -#define __C3CAIRO_H___ - -#include "c3/c3texture.h" -#include "c3/c3pixels.h" -#include - -typedef struct c3cairo_t { - c3texture_t tex; - cairo_t * cr; - cairo_surface_t * surface; -} c3cairo_t, *c3cairo_p; - -c3cairo_p -c3cairo_new( - struct c3object_t * parent /* = NULL */); - -c3cairo_p -c3cairo_init( - c3cairo_p o, - struct c3object_t * parent /* = NULL */); - -c3cairo_p -c3cairo_new_offscreen( - struct c3object_t * parent /* = NULL */, - int w, int h); - -#endif /* __C3CAIRO_H___ */ diff --git a/examples/board_reprap/src/c3/c3camera.c b/examples/board_reprap/src/c3/c3camera.c deleted file mode 100644 index 009672b..0000000 --- a/examples/board_reprap/src/c3/c3camera.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - c3camera.c - - Copyright 2008-2012 Michel Pollet - Copyright (c) 1998 Paul Rademacher - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3camera.h" - - -void -c3cam_set_distance( - c3camp c, - const c3f new_distance) -{ - if ( new_distance <= 0.0 ) /* Distance has to be positive */ - return; - - /* We find the current forward vector */ -// forward = lookat - eye; - c->forward = c3vec3_normalize(c3vec3_sub(c->lookat, c->eye)); - - /* Set distance */ - c->distance = new_distance; - - /* Find new eye point */ - c->eye = c3vec3_sub(c->lookat, c3vec3_mulf(c->forward, c->distance)); - c3cam_update(c); -} - -void -c3cam_set_upv( - c3camp c, - const c3vec3 new_up) -{ - c->up = new_up; - c3cam_update(c); -} - -void -c3cam_set_upf( - c3camp c, - const c3f x, - const c3f y, - const c3f z) -{ - c3cam_set_upv(c, c3vec3f(x,y,z)); -} - -void -c3cam_set_eyev( - c3camp c, - const c3vec3 new_eye) -{ - c->eye = new_eye; - c3cam_update(c); -} - -void -c3cam_set_eyef( - c3camp c, - const c3f x, - const c3f y, - const c3f z) -{ - c3cam_set_eyev(c, c3vec3f(x,y,z)); -} - -void -c3cam_set_lookatv( - c3camp c, - const c3vec3 new_lookat) -{ - c->lookat = new_lookat; - c3cam_update(c); -} - -void -c3cam_set_lookatf( - c3camp c, - const c3f x, - const c3f y, - const c3f z) -{ - c3cam_set_lookatv(c, c3vec3f(x,y,z)); -} - - -void -c3cam_roll( - c3camp c, - const c3f angle) -{ - c3mat4 rot = rotation3D(c->forward, angle ); - c->up = c3mat4_mulv3(&rot, c->up); - c3cam_update(c); -} - -void -c3cam_eye_yaw( - c3camp c, - const c3f angle) -{ - c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ - c3mat4 rot = rotation3D( c->up, angle ); - - eye_pt = c3mat4_mulv3(&rot, eye_pt); - c->eye = c3vec3_add(c->lookat, eye_pt); - - c3cam_update(c); -} - -void -c3cam_eye_yaw_abs( - c3camp c, - const c3f angle, - const c3vec3 axis) -{ - c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ - c3mat4 rot = rotation3D( axis, angle ); - - eye_pt = c3mat4_mulv3(&rot, eye_pt); - c->eye = c3vec3_add(c->lookat, eye_pt); - - c->up = c3mat4_mulv3(&rot, c->up); - - c3cam_update(c); -} - - -void -c3cam_eye_pitch( - c3camp c, - const c3f angle) -{ - c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ - c3mat4 rot = rotation3D( c->side, angle ); - - eye_pt = c3mat4_mulv3(&rot, eye_pt); - c->eye = c3vec3_add(c->lookat, eye_pt); - - c->up = c3mat4_mulv3(&rot, c->up); - - c3cam_update(c); -} - -void -c3cam_lookat_yaw( - c3camp c, - const c3f angle) -{ - c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ - c3mat4 rot = rotation3D( c->up, -angle ); - - lookat_pt = c3mat4_mulv3(&rot, lookat_pt); - c->lookat = c3vec3_add(c->eye, lookat_pt); - - c3cam_update(c); -} - -void -c3cam_lookat_pitch( - c3camp c, - const c3f angle) -{ - c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ - c3mat4 rot = rotation3D( c->side, -angle ); - - lookat_pt = c3mat4_mulv3(&rot, lookat_pt); - c->lookat = c3vec3_add(c->eye, lookat_pt); - - c->up = c3mat4_mulv3(&rot, c->up); - - c3cam_update(c); -} - -void -c3cam_reset_up_axis( - c3camp c, - const int axis_num) -{ - c3vec3 eye_pt = c3vec3_sub(c->lookat, c->eye); /* eye w/lookat at center */ - c3f eye_distance = c3vec3_length(eye_pt); - c->eye.n[axis_num] = c->lookat.n[axis_num]; - /* Bring eye to same level as lookat */ - - c3vec3 vector = c3vec3_sub(c->eye, c->lookat); - vector = c3vec3_normalize(vector); - vector = c3vec3_mulf(vector, eye_distance); - - c->eye = c3vec3_add(c->lookat, vector); - c->up = c3vec3f( 0.0, 0.0, 0.0 ); - c->up.n[axis_num] = 1.0; - - c3cam_update(c); -} - -void -c3cam_reset_up( - c3camp c) -{ - c3cam_reset_up_axis(c, VY ); /* Resets to the Y axis */ -} - -void -c3cam_movef( - c3camp c, - const c3f side_move, - const c3f up_move, - const c3f forw_move) -{ - c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->forward, forw_move)); - c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->side, side_move)); - c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->up, up_move)); - c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->forward, forw_move)); - c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->side, side_move)); - c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->up, up_move)); - c3cam_update(c); -} - -void -c3cam_movev( - c3camp c, - const c3vec3 v) /* A vector version of the above command */ -{ - c3cam_movef(c, v.n[VX], v.n[VY], v.n[VZ] ); -} - -void -c3cam_move_by_eye( - c3camp c, - const c3vec3 new_eye) -{ - c3vec3 diff = c3vec3_sub(new_eye, c->eye); - - c->lookat = c3vec3_add(c->lookat, diff); - c->eye = c3vec3_add(c->eye, diff); - - c3cam_update(c); -} - -void -c3cam_move_by_lookat( - c3camp c, - const c3vec3 new_lookat) -{ - c3vec3 diff = c3vec3_sub(new_lookat, c->lookat); - - c->lookat = c3vec3_add(c->lookat, diff); - c->eye = c3vec3_add(c->eye, diff); - - c3cam_update(c); -} - -void -c3cam_move_abs( - c3camp c, - const c3vec3 v) -{ - c->lookat = c3vec3_add(c->lookat, v); - c->eye = c3vec3_add(c->eye, v); - - c3cam_update(c); -} - -void -c3cam_rot_about_eye( - c3camp c, - const c3mat4p rot) -{ - c3vec3 view = c3vec3_sub(c->lookat, c->eye); - - view = c3mat4_mulv3(rot, view); - c->up = c3mat4_mulv3(rot, c->up); - - c->lookat = c3vec3_add(c->eye, view); - - c3cam_update(c); -} - -void -c3cam_rot_about_lookat( - c3camp c, - const c3mat4p rot) -{ - // NOT QUITE RIGHT YET - - c3vec3 view = c3vec3_sub(c->eye, c->lookat); - - view = c3mat4_mulv3(rot, view); - c->up = c3mat4_mulv3(rot, c->up); - - c->eye = c3vec3_add(c->lookat, view); - - c3cam_update(c); -} - -void -c3cam_update_matrix( - c3camp c) -{ - c3cam_update(c); - - c->mtx = c3mat4_vec4( - c3vec4f(c->side.n[VX], c->up.n[VX], c->forward.n[VX], 0.0), - c3vec4f(c->side.n[VY], c->up.n[VY], c->forward.n[VY], 0.0), - c3vec4f(c->side.n[VZ], c->up.n[VZ], c->forward.n[VZ], 0.0), - c3vec4f(0.0, 0.0, 0.0, 1.0)); -} -#if 0 -void -c3cam_load_to_openGL(c3camp c) -{ - c3mat4 m; - - make_mtx(); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - glMultMatrixf( (c3f*) &mtx[0][0]); - glTranslatef( -eye[VX], -eye[VY], -eye[VZ] ); -} - -void -c3cam_load_to_openGL_noident(c3camp c) -{ - c3mat4 m; - - make_mtx(); - - glMatrixMode( GL_MODELVIEW ); - glMultMatrixf( (c3f*) &mtx[0][0]); - glTranslatef( -eye[VX], -eye[VY], -eye[VZ] ); -} -#endif - -void -c3cam_reset( - c3camp c) -{ - c->up = c3vec3f( 0.0, 1.0, 0.0 ); - c->eye = c3vec3f(0.0, 0.0, 10.0); - c->lookat = c3vec3f(0.0,0.0,0.0); - - c->mtx = identity3D(); - - c3cam_update(c); -} - -c3cam -c3cam_new() -{ - c3cam c; - c3cam_reset(&c); - return c; -} - -void -c3cam_update( - c3camp c) -{ - /* get proper side and forward vectors, and distance */ - c->forward = c3vec3_minus(c3vec3_sub(c->lookat, c->eye)); - c->distance = c3vec3_length(c->forward); - c->forward = c3vec3_divf(c->forward, c->distance); - - c->side = c3vec3_cross(c->up, c->forward); - c->up = c3vec3_cross(c->forward, c->side); - - c->forward = c3vec3_normalize(c->forward); - c->up = c3vec3_normalize(c->up); - c->side = c3vec3_normalize(c->side); -} - -# if 0 -void -c3cam_dump(c3camp c, FILE *output) const -{ - fprintf( output, "Viewmodel: \n" ); - eye.print( output, " eye" ); - lookat.print( output, " lookat" ); - up.print( output, " up" ); - side.print( output, " side" ); - forward.print(output, " forward"); - mtx.print( output, " mtx" ); -} -#endif diff --git a/examples/board_reprap/src/c3/c3camera.h b/examples/board_reprap/src/c3/c3camera.h deleted file mode 100644 index cc27c14..0000000 --- a/examples/board_reprap/src/c3/c3camera.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - c3camera.h - - Copyright 2008-2012 Michel Pollet - Copyright (c) 1998 Paul Rademacher - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __C3VIEW_H___ -#define __C3VIEW_H___ - -#include "c3/c3algebra.h" - -typedef struct c3cam { - c3vec3 eye, lookat; - c3vec3 up, side, forward; - c3mat4 mtx; - c3f distance; -} c3cam, *c3camp; - -/******************************* set_distance() ***********/ -/* This readjusts the distance from the eye to the lookat */ -/* (changing the eye point in the process) */ -/* The lookat point is unaffected */ -void -c3cam_set_distance( - c3camp c, - const c3f new_distance); - -/******************************* set_up() ***************/ -void -c3cam_set_upv( - c3camp c, - const c3vec3 new_up); -void -c3cam_set_upf( - c3camp c, - const c3f x, - const c3f y, - const c3f z); - -/******************************* set_eye() ***************/ -void -c3cam_set_eyev( - c3camp c, - const c3vec3 new_eye); -void -c3cam_set_eyef( - c3camp c, - const c3f x, - const c3f y, - const c3f z); - -/******************************* set_lookat() ***************/ -void -c3cam_set_lookatv( - c3camp c, - const c3vec3 new_lookat); -void -c3cam_set_lookatf( - c3camp c, - const c3f x, - const c3f y, - const c3f z); - -/******************************* roll() *****************/ -/* Rotates about the forward vector */ -/* eye and lookat remain unchanged */ -void -c3cam_roll( - c3camp c, - const c3f angle); - -/******************************* eye_yaw() *********************/ -/* Rotates the eye about the lookat point, using the up vector */ -/* Lookat is unaffected */ -void -c3cam_eye_yaw( - c3camp c, - const c3f angle); - -/******************************* eye_yaw_abs() ******************/ -/* Rotates the eye about the lookat point, with a specific axis */ -/* Lookat is unaffected */ -void -c3cam_eye_yaw_abs( - c3camp c, - const c3f angle, - const c3vec3 axis); - -/******************************* eye_pitch() ************/ -/* Rotates the eye about the side vector */ -/* Lookat is unaffected */ -void -c3cam_eye_pitch( - c3camp c, - const c3f angle); - -/******************************* lookat_yaw()************/ -/* This assumes the up vector is correct. */ -/* Rotates the lookat about the side vector */ -/* Eye point is unaffected */ -void -c3cam_lookat_yaw( - c3camp c, - const c3f angle); - -/******************************* lookat_pitch() *********/ -/* Rotates the lookat point about the side vector */ -/* This assumes the side vector is correct. */ -/* Eye point is unaffected */ -void -c3cam_lookat_pitch( - c3camp c, - const c3f angle); - -/******************************* reset_up() ******************/ -/* Resets the up vector to a specified axis (0=X, 1=Y, 2=Z) */ -/* Also sets the eye point level with the lookat point, */ -/* along the specified axis */ -void -c3cam_reset_up_axis( - c3camp c, - const int axis_num); -void -c3cam_reset_up( - c3camp c); - -/******************************* move() ********************/ -/* Moves a specified distance in the forward, side, and up */ -/* directions. This function does NOT move by world */ -/* coordinates. To move by world coords, use the move_abs */ -/* function. */ -void -c3cam_movef( - c3camp c, - const c3f side_move, - const c3f up_move, - const c3f forw_move); -void -c3cam_movev( - c3camp c, - const c3vec3 v); /* A vector version of the above command */ - -/******************************* move_by_eye() ***********/ -/* Sets the eye point, AND moves the lookat point by the */ -/* same amount as the eye is moved. */ -void -c3cam_move_by_eye( - c3camp c, - const c3vec3 new_eye); - -/******************************* move_by_lookat() *********/ -/* Sets the lookat point, AND moves the eye point by the */ -/* same amount as the lookat is moved. */ -void -c3cam_move_by_lookat( - c3camp c, - const c3vec3 new_lookat); - -/******************************* move_abs() *****************/ -/* Move the eye and lookat in world coordinates */ -void -c3cam_move_abs( - c3camp c, - const c3vec3 v); - -/****************************** rot_about_eye() ************/ -/* Rotates the lookat point about the eye, based on a 4x4 */ -/* (pure) rotation matrix */ -void -c3cam_rot_about_eye( - c3camp c, - const c3mat4p rot); - -/****************************** rot_about_lookat() ************/ -/* Rotates the lookat point about the lookat, based on a 4x4 */ -/* (pure) rotation matrix */ -void -c3cam_rot_about_lookat( - c3camp c, - const c3mat4p rot); - -/******************************* make_mtx() *************/ -/* Constructs a 4x4 matrix - used by load_to_openGL() */ -void -c3cam_update_matrix( - c3camp c); - -/******************************* load_to_openGL() ********/ -/* Sets the OpenGL modelview matrix based on the current */ -/* camera coordinates */ -//void c3cam_load_to_openGL(); - -/******************************* load_to_openGL_noident() ******/ -/* Multiplies the current camera matrix by the existing openGL */ -/* modelview matrix. This is same as above function, but */ -/* does not set the OpenGL matrix to identity first */ -//void c3cam_load_to_openGL_noident(); - -/******************************* reset() ****************/ -/* Resets the parameters of this class */ -void -c3cam_reset( - c3camp c); - -/******************************* ViewModel() ************/ -/* Constructor */ -c3cam c3cam_new(); - -/******************************* update() ****************/ -/* updates the view params. Call this after making */ -/* direct changes to the vectors or points of this class */ -void c3cam_update( - c3camp c); - -/******************************* dump() *******************/ -/* Prints the contents of this class to a file, typically */ -/* stdin or stderr */ -//void c3cam_dump(FILE *output); - -#endif /* __C3VIEW_H___ */ diff --git a/examples/board_reprap/src/c3/c3context.c b/examples/board_reprap/src/c3/c3context.c deleted file mode 100644 index 0c0f26a..0000000 --- a/examples/board_reprap/src/c3/c3context.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - c3context.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3context.h" -#include "c3/c3object.h" -#include "c3/c3driver_context.h" - -c3context_p -c3context_new( - int w, - int h) -{ - c3context_p res = malloc(sizeof(*res)); - return c3context_init(res, w, h); -} - -c3context_p -c3context_init( - c3context_p c, - int w, - int h) -{ - memset(c, 0, sizeof(*c)); - c->size.x = w; - c->size.y = h; - c->root = c3object_new(NULL); - c->root->context = c; - return c; -} - -void -c3context_dispose( - c3context_p c) -{ - c3object_dispose(c->root); - c3geometry_array_free(&c->projected); - free(c); -} - -void -c3context_project( - c3context_p c) -{ - if (!c->root || !c->root->dirty) - return; - - c3mat4 m = identity3D(); - c3object_project(c->root, &m); - c3geometry_array_clear(&c->projected); - c3object_get_geometry(c->root, &c->projected); -} - -void -c3context_draw( - c3context_p c) -{ - c3context_project(c); - for (int gi = 0; gi < c->projected.count; gi++) { - c3geometry_p g = c->projected.e[gi]; - c3geometry_draw(g); - } -} diff --git a/examples/board_reprap/src/c3/c3context.h b/examples/board_reprap/src/c3/c3context.h deleted file mode 100644 index 00af7e6..0000000 --- a/examples/board_reprap/src/c3/c3context.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - c3context.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3CONTEXT_H___ -#define __C3CONTEXT_H___ - -#include "c3/c3algebra.h" -#include "c3/c3geometry.h" - -//! c3context_t is a container for a 'scene' to be drawn -/*! - * A c3context_t holds a root object, a list of already cached projected - * version of the geometry, and a driver that can be customized to draw it. - * - * This is a wrapper around a "top level object", the list of projected - * geometries is kept, purged and resorted if the root object becomes - * dirty - * TODO: Add the camera/eye/arcball control there - */ -typedef struct c3context_t { - c3vec2 size; - struct c3object_t * root; - c3geometry_array_t projected; - - const struct c3driver_context_t ** driver; -} c3context_t, *c3context_p; - -//! Allocates a new context of size w=width, h=height -c3context_p -c3context_new( - int w, - int h); - -//! Initializes a new context 'c' of size w=width, h=height -c3context_p -c3context_init( - c3context_p c, - int w, - int h); - -//! Disposes the context, and everything underneath -void -c3context_dispose( - c3context_p c); - -//! Reproject geometry for dirty objects -void -c3context_project( - c3context_p c); -//! Draws the context -void -c3context_draw( - c3context_p c); - -#endif /* __C3CONTEXT_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver.h b/examples/board_reprap/src/c3/c3driver.h deleted file mode 100644 index 901c32d..0000000 --- a/examples/board_reprap/src/c3/c3driver.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - c3driver.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3DRIVER_H___ -#define __C3DRIVER_H___ - -#define C3_DRIVER_CALL(__o, __callback, __args...) { \ - if ((__o) && (__o)->driver) \ - for (int _di = 0; (__o)->driver[_di]; _di++) \ - if ((__o)->driver[_di]->__callback) { \ - (__o)->driver[_di]->__callback(__o, (__o)->driver[_di], ##__args); \ - break; \ - } \ - } -#define C3_DRIVER(__o, __callback, __args...) \ - C3_DRIVER_CALL(__o, __callback, ##__args) -#define C3_DRIVER_INHERITED(__o, __driver, __callback, __args...) { \ - if ((__o) && (__o)->driver) \ - for (int _di = 0; (__o)->driver[_di]; _di++) \ - if ((__o)->driver[_di] == __driver && (__o)->driver[_di+1]) { \ - (__o)->driver[_di+1]->__callback(__o, (__o)->driver[_di+1], ##__args); \ - break; \ - } \ - } -#endif /* __C3DRIVER_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver_context.h b/examples/board_reprap/src/c3/c3driver_context.h deleted file mode 100644 index 0f780d4..0000000 --- a/examples/board_reprap/src/c3/c3driver_context.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - c3driver_context.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3DRIVER_CONTEXT_H___ -#define __C3DRIVER_CONTEXT_H___ - -#include "c3/c3driver.h" - -struct c3context_t; -struct c3driver_context_t; -struct c3geometry_t; - -typedef struct c3driver_context_t { - void (*geometry_project)( - struct c3context_t * c, - const struct c3driver_context_t *d, - struct c3geometry_t * g, - union c3mat4 * mat); - void (*geometry_draw)( - struct c3context_t * c, - const struct c3driver_context_t *d, - struct c3geometry_t * g); -} c3driver_context_t, *c3driver_context_p; - -#endif /* __C3DRIVER_CONTEXT_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver_geometry.h b/examples/board_reprap/src/c3/c3driver_geometry.h deleted file mode 100644 index 46bd101..0000000 --- a/examples/board_reprap/src/c3/c3driver_geometry.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - c3driver_geometry.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3DRIVER_GEOMETRY_H___ -#define __C3DRIVER_GEOMETRY_H___ - -#include "c3/c3driver.h" - -struct c3geometry_t; - -typedef struct c3driver_geometry_t { - void (*dispose)( - struct c3geometry_t * geometry, - const struct c3driver_geometry_t *d); - void (*project)( - struct c3geometry_t * geometry, - const struct c3driver_geometry_t *d, - union c3mat4 * mat); - void (*draw)( - struct c3geometry_t * geometry, - const struct c3driver_geometry_t *d); -} c3driver_geometry_t, *c3driver_geometry_p; - - -#endif /* __C3DRIVER_GEOMETRY_H___ */ diff --git a/examples/board_reprap/src/c3/c3driver_object.h b/examples/board_reprap/src/c3/c3driver_object.h deleted file mode 100644 index 05a11f2..0000000 --- a/examples/board_reprap/src/c3/c3driver_object.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - c3driver_object.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3DRIVER_OBJECT_H___ -#define __C3DRIVER_OBJECT_H___ - -#include "c3/c3driver.h" - -struct c3object_t; -struct c3geometry_array_t; -union c3mat4; - -typedef struct c3driver_object_t { - /* - * Delete any object related to this object, geometry etc - * The object will still exist, just empty - */ - void (*clear)( - struct c3object_t * object, - const struct c3driver_object_t * d); - /* - * Dispose of the remaining memory for an object, detaches it - * and frees remaining traces of it - */ - void (*dispose)( - struct c3object_t * object, - const struct c3driver_object_t * d); - /* - * Adds sub objects geometry and self geometry to array 'out' - */ - void (*get_geometry)( - struct c3object_t * object, - const struct c3driver_object_t * d, - struct c3geometry_array_t * out); - /* - * Reproject geometry along matrix 'mat', applies our own - * transform and call down the chain for sub-objects - */ - void (*project)( - struct c3object_t * object, - const struct c3driver_object_t * d, - union c3mat4 * mat); -} c3driver_object_t, *c3driver_object_p; - - -#endif /* __C3DRIVER_OBJECT_H___ */ diff --git a/examples/board_reprap/src/c3/c3geometry.c b/examples/board_reprap/src/c3/c3geometry.c deleted file mode 100644 index e041ff2..0000000 --- a/examples/board_reprap/src/c3/c3geometry.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - c3geometry.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3object.h" -#include "c3/c3context.h" -#include "c3/c3driver_geometry.h" -#include "c3/c3driver_context.h" - -static void -_c3geometry_dispose( - c3geometry_p g, - const struct c3driver_geometry_t *d) -{ - /* - * If we're still attached to an object, detach - */ - if (g->object) { - for (int oi = 0; oi < g->object->geometry.count; oi++) - if (g->object->geometry.e[oi] == g) { - c3geometry_array_delete(&g->object->geometry, oi, 1); - c3object_set_dirty(g->object, true); - break; - } - g->object = NULL; - } - str_free(g->name); - c3vertex_array_free(&g->vertice); - c3vertex_array_free(&g->projected); - c3tex_array_free(&g->textures); - c3colorf_array_free(&g->colorf); - free(g); -// C3_DRIVER_INHERITED(g, d, dispose); -} - -static void -_c3geometry_project( - c3geometry_p g, - const struct c3driver_geometry_t *d, - c3mat4p m) -{ - if (g->vertice.count) { - c3vertex_array_realloc(&g->projected, g->vertice.count); - g->projected.count = g->vertice.count; - for (int vi = 0; vi < g->vertice.count; vi++) { - g->projected.e[vi] = c3mat4_mulv3(m, g->vertice.e[vi]); - if (vi == 0) - g->bbox.min = g->bbox.max = g->projected.e[vi]; - else { - g->bbox.max = c3vec3_min(g->bbox.min, g->projected.e[vi]); - g->bbox.max = c3vec3_max(g->bbox.max, g->projected.e[vi]); - } - } - } - - if (g->object && g->object->context) - C3_DRIVER(g->object->context, geometry_project, g, m); - g->dirty = 0; -// C3_DRIVER_INHERITED(g, d, project); -} - -static void -_c3geometry_draw( - c3geometry_p g, - const struct c3driver_geometry_t *d) -{ - if (g->object && g->object->context) - C3_DRIVER(g->object->context, geometry_draw, g); -// C3_DRIVER_INHERITED(g, d, draw); -} - -const c3driver_geometry_t c3geometry_driver = { - .dispose = _c3geometry_dispose, - .project = _c3geometry_project, - .draw = _c3geometry_draw, -}; - -c3geometry_p -c3geometry_new( - c3geometry_type_t type, - c3object_p o /* = NULL */) -{ - c3geometry_p res = malloc(sizeof(c3geometry_t)); - return c3geometry_init(res, type, o); -} - -c3geometry_p -c3geometry_init( - c3geometry_p g, - c3geometry_type_t type, - struct c3object_t * o /* = NULL */) -{ - memset(g, 0, sizeof(*g)); - static const c3driver_geometry_t * list[] = { - &c3geometry_driver, NULL, - }; - g->driver = list; - g->type = type; - g->dirty = 1; - if (o) - c3object_add_geometry(o, g); - return g; -} - -c3driver_geometry_p -c3geometry_get_custom( - c3geometry_p g ) -{ - if (g->custom) - return (c3driver_geometry_p)g->driver[0]; - int cnt = 0; - for (int di = 0; g->driver[di]; di++) - cnt++; - c3driver_geometry_p * newd = malloc(sizeof(c3driver_geometry_p) * (cnt + 2)); - memcpy(&newd[1], g->driver, (cnt + 1) * sizeof(c3driver_geometry_p)); - newd[0] = malloc(sizeof(c3driver_geometry_t)); - memset(newd[0], 0, sizeof(c3driver_geometry_t)); - g->custom = 1; - g->driver = (typeof(g->driver))newd; - return newd[0]; -} - -void -c3geometry_dispose( - c3geometry_p g) -{ - C3_DRIVER(g, dispose); -} - -void -c3geometry_project( - c3geometry_p g, - c3mat4p m) -{ - if (!g->dirty) - return; - C3_DRIVER(g, project, m); -} - -void -c3geometry_draw( - c3geometry_p g ) -{ - C3_DRIVER(g, draw); -} diff --git a/examples/board_reprap/src/c3/c3geometry.h b/examples/board_reprap/src/c3/c3geometry.h deleted file mode 100644 index 2364fb3..0000000 --- a/examples/board_reprap/src/c3/c3geometry.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - c3geometry.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -/* - * c3geometry is a structure containing one set of vertices and various - * bits related to it. Ultimately it contains a pre-cached projected - * version of the vertices that the drawing code can use directly. - * c3geometry is aways attached to a c3object as a parent. - */ - -#ifndef __C3GEOMETRY_H___ -#define __C3GEOMETRY_H___ - -#include "c3/c3algebra.h" -#include "c_utils.h" - -typedef c3vec3 c3vertex; -typedef c3vec4 c3colorf; -typedef c3vec2 c3tex; - -struct c3object_t; - -DECLARE_C_ARRAY(c3vertex, c3vertex_array, 16); -DECLARE_C_ARRAY(c3tex, c3tex_array, 16); -DECLARE_C_ARRAY(c3colorf, c3colorf_array, 16); - -//! Geometry material. TODO: Beef up. Add vertex/fragment programs.. -typedef struct c3material_t { - c3colorf color; - uint32_t texture; - uint32_t mode; -} c3material_t; - -//! Bounding box. TODO: Move to a separate file? -typedef struct c3bbox_t { - c3vec3 min, max; -} c3bbox_t; - -//! Generic geometry type -enum { - C3_RAW_TYPE = 0, - C3_LINES_TYPE, - C3_TRIANGLE_TYPE, - C3_TEXTURE_TYPE, -}; - -/*! - * geometry type. - * The type is used as non-opengl description of what the geometry - * contains, like "texture", and the subtype can be used to store the - * real format of the vertices. like GL_LINES etc - */ -typedef union { - struct { uint32_t type : 16, subtype : 16; }; - uint32_t value; -} c3geometry_type_t; - -/*! - * Geometry object. Describes a set of vertices, texture coordinates, - * normals, colors and material - * The projection is not set here, a geometry is always attached to a - * c3object that has the projection - */ -typedef struct c3geometry_t { - c3geometry_type_t type; // C3_TRIANGLE_TYPE, GL_LINES etc - int dirty : 1, - texture : 1, // has a valid material.texture - custom : 1; // has a custom driver - str_p name; // optional - c3material_t mat; - struct c3object_t * object; - const struct c3driver_geometry_t ** driver; - - c3vertex_array_t vertice; - c3tex_array_t textures; - c3colorf_array_t colorf; - c3vertex_array_t normals; - - // projected version of the vertice - c3vertex_array_t projected; - c3bbox_t bbox; -} c3geometry_t, *c3geometry_p; - -DECLARE_C_ARRAY(c3geometry_p, c3geometry_array, 4); - -//! Allocates a new geometry, init it, and attached it to parent 'o' (optional) -c3geometry_p -c3geometry_new( - c3geometry_type_t type, - struct c3object_t * o /* = NULL */); -//! Init an existing new geometry, and attached it to parent 'o' (optional) -c3geometry_p -c3geometry_init( - c3geometry_p g, - c3geometry_type_t type, - struct c3object_t * o /* = NULL */); -//! Disposes (via the driver interface) the geometry -void -c3geometry_dispose( - c3geometry_p g); - -//! Prepares a geometry. -/*! - * The project phase is called only when the container object is 'dirty' - * for example if it's projection has changed. - * The project call is responsible for reprojecting the geometry and that - * sort of things - */ -void -c3geometry_project( - c3geometry_p g, - c3mat4p m); - -//! Draw the geometry -/* - * Called when drawing the context. Typicaly this calls the geometry - * driver, which in turn will call the 'context' draw method, and the - * application to draw this particular geometry - */ -void -c3geometry_draw( - c3geometry_p g ); - - -//! allocate (if not there) and return a custom driver for this geometry -/*! - * Geometries come with a default, read only driver stack.. It is a constant - * global to save memory for each of the 'generic' object. - * This call will duplicate that stack and allocate (if not there) a read/write - * empty driver that the application can use to put their own, per object, - * callback. For example you can add your own project() or draw() function - * and have it called first - */ -struct c3driver_geometry_t * -c3geometry_get_custom( - c3geometry_p g ); - -IMPLEMENT_C_ARRAY(c3geometry_array); -IMPLEMENT_C_ARRAY(c3vertex_array); -IMPLEMENT_C_ARRAY(c3tex_array); -IMPLEMENT_C_ARRAY(c3colorf_array); - -static inline c3geometry_type_t -c3geometry_type(int type, int subtype) -{ - c3geometry_type_t r = { .type = type, .subtype = subtype }; - return r; -} - -#endif /* __C3GEOMETRY_H___ */ diff --git a/examples/board_reprap/src/c3/c3object.c b/examples/board_reprap/src/c3/c3object.c deleted file mode 100644 index 50d46e4..0000000 --- a/examples/board_reprap/src/c3/c3object.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - c3object.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3object.h" -#include "c3/c3driver_object.h" - -void -_c3object_clear( - c3object_p o, - const c3driver_object_t * d) -{ - for (int oi = 0; oi < o->transform.count; oi++) { - o->transform.e[oi]->object = NULL; - c3transform_dispose(o->transform.e[oi]); - } - for (int oi = 0; oi < o->geometry.count; oi++) { - o->geometry.e[oi]->object = NULL; // don't try to detach - c3geometry_dispose(o->geometry.e[oi]); - } - for (int oi = 0; oi < o->objects.count; oi++) { - o->objects.e[oi]->parent = NULL; // don't try to detach - c3object_dispose(o->objects.e[oi]); - } - c3object_array_free(&o->objects); - c3geometry_array_free(&o->geometry); - c3transform_array_free(&o->transform); -} - -void -_c3object_dispose( - c3object_p o, - const c3driver_object_t * d) -{ - if (o->parent) { - for (int oi = 0; oi < o->parent->objects.count; oi++) - if (o->parent->objects.e[oi] == o) { - c3object_array_delete(&o->parent->objects, oi, 1); - c3object_set_dirty(o->parent, true); - break; - } - o->parent = NULL; - } - //C3O_DRIVER_INHERITED(dispose, d); - free(o); -} - -void -_c3object_get_geometry( - c3object_p o, - const c3driver_object_t * d, - c3geometry_array_p out) -{ - for (int oi = 0; oi < o->geometry.count; oi++) - c3geometry_array_add(out, o->geometry.e[oi]); - for (int oi = 0; oi < o->objects.count; oi++) - c3object_get_geometry(o->objects.e[oi], out); -} - -void -_c3object_project( - c3object_p o, - const c3driver_object_t * d, - c3mat4p m) -{ - if (!o->dirty) - return; - -// c3mat4 identity = identity3D(); - c3mat4 p = *m; - for (int pi = 0; pi < o->transform.count; pi++) - p = c3mat4_mul(&p, &o->transform.e[pi]->matrix); -// bool is_identity = c3mat4_equal(m, &identity); - - for (int gi = 0; gi < o->geometry.count; gi++) { - c3geometry_p g = o->geometry.e[gi]; - c3vertex_array_clear(&g->projected); - - g->bbox.min = g->bbox.max = c3vec3f(0,0,0); - c3geometry_project(g, &p); - } - for (int oi = 0; oi < o->objects.count; oi++) - c3object_project(o->objects.e[oi], &p); - o->dirty = false; -} - -const c3driver_object_t c3object_driver = { - .clear = _c3object_clear, - .dispose = _c3object_dispose, - .get_geometry = _c3object_get_geometry, - .project = _c3object_project, -}; - - -c3object_p -c3object_init( - c3object_p o /* = NULL */, - c3object_p parent) -{ - memset(o, 0, sizeof(*o)); - o->parent = parent; - static const c3driver_object_t * list[] = - { &c3object_driver, NULL }; - o->driver = list; - if (parent) { - c3object_array_add(&parent->objects, o); - o->context = parent->context; - } - return o; -} - -c3object_p -c3object_new( - c3object_p o /* = NULL */) -{ - c3object_p res = malloc(sizeof(*o)); - return c3object_init(res, o); -} - -void -c3object_clear( - c3object_p o) -{ - C3_DRIVER(o, clear); -} - -void -c3object_dispose( - c3object_p o) -{ - c3object_clear(o); - C3_DRIVER(o, dispose); -} - -void -c3object_set_dirty( - c3object_p o, - bool dirty) -{ - if (dirty) { - while (o) { - o->dirty = true; - o = o->parent; - } - } else { - for (int oi = 0; oi < o->objects.count; oi++) - if (o->objects.e[oi]->dirty) - c3object_set_dirty(o->objects.e[oi], false); - o->dirty = false; - } -} - -void -c3object_add_object( - c3object_p o, - c3object_p sub) -{ - if (sub->parent == o) - return; - if (sub->parent) { - for (int oi = 0; oi < sub->parent->objects.count; oi++) { - if (sub->parent->objects.e[oi] == sub) { - c3object_array_delete(&sub->parent->objects, oi, 1); - c3object_set_dirty(sub->parent, true); - break; - } - } - sub->parent = NULL; - } - sub->parent = o; - if (o) { - c3object_array_add(&o->objects, sub); - c3object_set_dirty(o, true); - } -} - -void -c3object_add_geometry( - c3object_p o, - c3geometry_p g) -{ - if (g->object == o) - return; - if (g->object) { - for (int oi = 0; oi < g->object->geometry.count; oi++) { - if (g->object->geometry.e[oi] == g) { - c3geometry_array_delete(&g->object->geometry, oi, 1); - c3object_set_dirty(g->object, true); - break; - } - } - g->object = NULL; - } - g->object = o; - if (o) { - c3geometry_array_add(&o->geometry, g); - c3object_set_dirty(o, true); - } -} - -void -c3object_get_geometry( - c3object_p o, - c3geometry_array_p array ) -{ - C3_DRIVER(o, get_geometry, array); -} - -void -c3object_project( - c3object_p o, - const c3mat4p m) -{ - C3_DRIVER(o, project, m); -} diff --git a/examples/board_reprap/src/c3/c3object.h b/examples/board_reprap/src/c3/c3object.h deleted file mode 100644 index 1ee1d9c..0000000 --- a/examples/board_reprap/src/c3/c3object.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - c3object.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3OBJECT_H___ -#define __C3OBJECT_H___ - -#include -#include "c3/c3transform.h" -#include "c3/c3geometry.h" - -struct c3object_t; - -DECLARE_C_ARRAY(struct c3object_t*, c3object_array, 4); - -//! c3object is a container for child object, and geometry -/*! - * a c3object is a node in a c3object tree, it contains sub-objects and/or - * geometry. It also contains it's own list of transform matrices, so can - * be seen as a "anchor" that can be moved around and where you can - * attach other objects or geometry. - * - * An object has a notion of 'dirty bit' -- something that signals that - * something has changed and deserved reprojection. the dirty bit - * is propagated upward when 1 (up to the root object) and downward when 0 - * (to allow clearing the bit on a subtree) - */ -typedef struct c3object_t { - str_p name; //! optional name - int dirty : 1, - visible : 1 /* TODO: Implement visible */; - struct c3context_t * context; //! context this object is attached to - struct c3object_t * parent; //! Parent object - const struct c3driver_object_t ** driver; //! Driver stack - c3transform_array_t transform; - c3object_array_t objects; //! child object list - c3geometry_array_t geometry; //! Object geometri(es) -} c3object_t, *c3object_p; - -//! Allocates and initialize an emty object, attaches it to parent 'o' -c3object_p -c3object_new( - c3object_p o /* = NULL */); -//! Disposes of everything under this object -void -c3object_dispose( - c3object_p o); -//! Clears every sub-object, geometry, and transform, but do not dispose of o -void -c3object_clear( - c3object_p o); -//! Initializes 'o' as a new object, attaches it to parent (optional) -c3object_p -c3object_init( - c3object_p o, - c3object_p parent /* = NULL */); -//! sets the dirty bit for 'o' and related tree -/*! - * When dirty is 1, sets the dirty bit of this object and all the parent - * objects up to the root object. - * When dirty is 0, clear the dirty bit of this object, and all the - * sub objects. - */ -void -c3object_set_dirty( - c3object_p o, - bool dirty); -//! Adds a new geometry g to object o -void -c3object_add_geometry( - c3object_p o, - c3geometry_p g); -//! Adds a new sub-object sub to object o -void -c3object_add_object( - c3object_p o, - c3object_p sub); -//! Adds a new transform matrix, initialized as identity -c3transform_p -c3object_add_transform( - c3object_p o ); -//! Iterates all the sub-objects and collects all the geometries -/*! - * This call iterates the sub-objects and collects all their 'projected' - * geometry, and add them to the array - */ -void -c3object_get_geometry( - c3object_p o, - c3geometry_array_p array ); -//! Project object 'o' using it's own transformations, relative to matrix 'm' -/*! - * Multiply this objects transformation(s) to matrix 'm' and calls - * reprojects the geometries using that matrix as an anchor. also call - * recursively to sub-objects to follow the projection down. - */ -void -c3object_project( - c3object_p o, - const c3mat4p m); - -IMPLEMENT_C_ARRAY(c3object_array); - -#endif /* __C3OBJECT_H___ */ diff --git a/examples/board_reprap/src/c3/c3pixels.c b/examples/board_reprap/src/c3/c3pixels.c deleted file mode 100644 index cdaef7e..0000000 --- a/examples/board_reprap/src/c3/c3pixels.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - c3pixels.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include "c3pixels.h" - -c3pixels_p -c3pixels_new( - uint32_t w, - uint32_t h, - int psize /* in bytes */, - size_t row, - void * base) -{ - c3pixels_p p = malloc(sizeof(*p)); - c3pixels_init(p, w, h, psize, row, base); - p->alloc = 1; - return p; -} - -c3pixels_p -c3pixels_init( - c3pixels_p p, - uint32_t w, - uint32_t h, - int psize /* in bytes */, - size_t row, - void * base) -{ - memset (p, 0, sizeof(*p)); - p->w = w; - p->h = h; - p->row = row; - p->psize = psize; - p->base = base; - c3pixels_alloc(p); - return p; -} - -void -c3pixels_dispose( - c3pixels_p p ) -{ - if (p->own && p->base) - free(p->base); - if (p->alloc) - free(p); - else - memset(p, 0, sizeof(*p)); -} - -void -c3pixels_alloc( - c3pixels_p p ) -{ - if (p->base) - return; - p->base = malloc(p->row * p->h); - p->own = p->base != NULL; -} - -void -c3pixels_purge( - c3pixels_p p ) -{ - if (!p->base) - return; - if (p->own) - free(p->base); - p->own = 0; - p->base = NULL; -} - -void -c3pixels_zero( - c3pixels_p p) -{ - if (!p->base) - return; - memset(p->base, 0, p->h * p->row); -} diff --git a/examples/board_reprap/src/c3/c3pixels.h b/examples/board_reprap/src/c3/c3pixels.h deleted file mode 100644 index 8e7d1d2..0000000 --- a/examples/board_reprap/src/c3/c3pixels.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - c3pixels.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3PIXELS_H___ -#define __C3PIXELS_H___ - -#include - -//! for format hint -enum { - C3PIXEL_ARGB = 0, - C3PIXEL_RGB, - C3PIXEL_A -}; - -typedef struct c3pixels_t { - uint32_t w, h; // width & height in pixels - size_t row; // size of one row in bytes - void * base; // base address - - union { - struct { - uint32_t own : 1, // is the base our own to delete - alloc : 1, // is the c3pixels_p our own to delete - dirty : 1, // pixels have been changed - psize : 4, // pixel size in byte - format : 8; // not used internally - }; - uint32_t flags; - }; - int refCount; // TODO: Implement reference counting ? -} c3pixels_t, *c3pixels_p; - -//! Allocates a new c3pixels, also allocates the pixels if row == NULL -c3pixels_p -c3pixels_new( - uint32_t w, - uint32_t h, - int psize /* in bytes */, - size_t row, - void * base); - -//! Initializes p, also allocates the pixels if row == NULL -c3pixels_p -c3pixels_init( - c3pixels_p p, - uint32_t w, - uint32_t h, - int psize /* in bytes */, - size_t row, - void * base); - -//! Dispose of the pixels, and potentially p if it was allocated with c3pixels_new -void -c3pixels_dispose( - c3pixels_p p ); - -//! Disposes of the pixels, only -void -c3pixels_purge( - c3pixels_p p ); - -//! (Re)allocate pixels if pixels had been purged -void -c3pixels_alloc( - c3pixels_p p ); - -//! Get a pixel address -static inline void * -c3pixels_get( - c3pixels_p p, - int x, int y) -{ - return ((uint8_t*)p->base) + (y * p->row) + (x * p->psize); -} - -//! Zeroes the pixels -void -c3pixels_zero( - c3pixels_p p); - -#endif /* __C3PIXELS_H___ */ diff --git a/examples/board_reprap/src/c3/c3quaternion.c b/examples/board_reprap/src/c3/c3quaternion.c deleted file mode 100644 index a0816bf..0000000 --- a/examples/board_reprap/src/c3/c3quaternion.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - c3quaternion.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "c3/c3quaternion.h" - -#ifndef DEG2RAD -#define DEG2RAD(x) ((x)/180.0*M_PI) -#define RAD2DEG(x) ((x)/M_PI*180.0) -#endif -#ifndef FUDGE -#define FUDGE .00001 -#endif - -c3quat -c3quat_new() -{ - return c3quat_identity(); -} - -/************************************************* c3quat_identity() *****/ -/* Returns quaternion identity element */ - -c3quat -c3quat_identity() -{ - return c3quat_vec3( c3vec3f( 0.0, 0.0, 0.0 ), 1.0 ); -} - -c3quat -c3quatf( - const c3f x, - const c3f y, - const c3f z, - const c3f w) -{ - c3quat q = { .v = c3vec3f(x,y,z), .s = w }; - return q; -} - -c3quat -c3quat_vec3( - const c3vec3 v, - const c3f s) -{ - c3quat q = { .v = v, .s = s }; - return q; -} - -c3quat -c3quat_vec4( - const c3vec4 v) -{ - c3quat q = { .v = c3vec3f(v.n[0], v.n[1], v.n[2]), .s = v.n[3] }; - return q; -} - -c3quat -c3quat_double( - const double *d) -{ - c3quat q; - q.v.n[0] = (c3f) d[0]; - q.v.n[1] = (c3f) d[1]; - q.v.n[2] = (c3f) d[2]; - q.s = (c3f) d[3]; - return q; -} - - -c3quat -c3quat_add( - const c3quat a, - const c3quat b) -{ - return c3quat_vec3(c3vec3_add(a.v, b.v), a.s + b.s ); -} - -c3quat -c3quat_sub( - const c3quat a, - const c3quat b) -{ - return c3quat_vec3(c3vec3_sub(a.v, b.v), a.s - b.s ); -} - -c3quat -c3quat_minus( - const c3quat a ) -{ - return c3quat_vec3(c3vec3_minus(a.v), -a.s); -} - -c3quat -c3quat_mul( - const c3quat a, - const c3quat b) -{ -// return c3quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v ); - return c3quat_vec3( - c3vec3_add(c3vec3_mulf(b.v, a.s), c3vec3_add(c3vec3_mulf(a.v, b.s), c3vec3_cross(a.v, b.v))), - (a.s * b.s) - c3vec3_dot(a.v, b.v)); -} - -c3quat -c3quat_mulf( const c3quat a, const c3f t) -{ - return c3quat_vec3(c3vec3_mulf(a.v, t), a.s * t ); -} - -c3mat4 -c3quat_to_mat4( - const c3quat a ) -{ - c3f xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; - - c3f t = 2.0f / (c3vec3_dot(a.v, a.v) + (a.s * a.s)); - - xs = a.v.n[VX]*t; ys = a.v.n[VY]*t; zs = a.v.n[VZ]*t; - wx = a.s*xs; wy = a.s*ys; wz = a.s*zs; - xx = a.v.n[VX]*xs; xy = a.v.n[VX]*ys; xz = a.v.n[VX]*zs; - yy = a.v.n[VY]*ys; yz = a.v.n[VY]*zs; zz = a.v.n[VZ]*zs; - - c3mat4 m = c3mat4_vec4( - c3vec4f(1.0f-(yy+zz), xy+wz, xz-wy, 0.0f), - c3vec4f(xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f), - c3vec4f(xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f), - c3vec4f(0.0f, 0.0f, 0.0f, 1.0f )); - - return m; -} - - -/************************************************ quat_slerp() ********/ -/* Quaternion spherical interpolation */ - -c3quat -quat_slerp( - const c3quat from, - const c3quat to, - c3f t) -{ - c3quat to1; - c3f omega, cosom, sinom, scale0, scale1; - - /* calculate cosine */ - cosom = c3vec3_dot(from.v, to.v) + from.s + to.s; - - /* Adjust signs (if necessary) */ - if (cosom < 0.0) { - cosom = -cosom; - to1 = c3quat_minus(to); - } else { - to1 = to; - } - - /* Calculate coefficients */ - if ((1.0 - cosom) > FUDGE ) { - /* standard case (slerp) */ - omega = (c3f) acos( cosom ); - sinom = (c3f) sin( omega ); - scale0 = (c3f) sin((1.0 - t) * omega) / sinom; - scale1 = (c3f) sin(t * omega) / sinom; - } else { - /* 'from' and 'to' are very close - just do linear interpolation */ - scale0 = 1.0f - t; - scale1 = t; - } - - return c3quat_add(c3quat_mulf(from, scale0), c3quat_mulf(to1, scale1)); -} - -/********************************************** set_angle() ************/ -/* set rot angle (degrees) */ - -c3quatp -c3quat_set_angle( - c3quatp a, - c3f f) -{ - c3vec3 axis = c3quat_get_axis(a); - - a->s = (c3f) cos( DEG2RAD( f ) / 2.0 ); - - a->v = c3vec3_mulf(axis, (c3f) sin(DEG2RAD(f) / 2.0)); - return a; -} - -/********************************************** scale_angle() ************/ -/* scale rot angle (degrees) */ - -c3quatp -c3quat_scale_angle( - c3quatp a, - c3f f) -{ - return c3quat_set_angle(a, f * c3quat_get_angle(a) ); -} - -/********************************************** get_angle() ************/ -/* get rot angle (degrees). Assumes s is between -1 and 1 */ - -c3f -c3quat_get_angle( - const c3quatp a) -{ - return (c3f) RAD2DEG( 2.0 * acos( a->s ) ); -} - -/********************************************* get_axis() **************/ - -c3vec3 -c3quat_get_axis( - c3quatp a) -{ - c3f scale = (c3f) sin( acos( a->s ) ); - - if ( scale < FUDGE && scale > -FUDGE ) - return c3vec3f( 0.0, 0.0, 0.0 ); - else - return c3vec3_divf(a->v, scale); -} - -/******************************************* c3quat_print() ************/ -#if 0 -void c3quat_print(FILE *dest, const char *name) const -{ - fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n", - name, v[0], v[1], v[2], s ); -} -#endif diff --git a/examples/board_reprap/src/c3/c3quaternion.h b/examples/board_reprap/src/c3/c3quaternion.h deleted file mode 100644 index 6e3f042..0000000 --- a/examples/board_reprap/src/c3/c3quaternion.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - c3quaternion.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3QUATERNION_H___ -#define __C3QUATERNION_H___ - -#include -#include "c3/c3algebra.h" - -typedef struct c3quat { - c3vec3 v; /* vector component */ - c3f s; /* scalar component */ -} c3quat, *c3quatp; - -c3quat -c3quat_new(); -c3quat -c3quat_identity(); - -c3quat -c3quatf( - const c3f x, - const c3f y, - const c3f z, - const c3f w); -c3quat -c3quat_vec3( - const c3vec3 v, - const c3f s); -c3quat -c3quat_vec4( - const c3vec4 v); - -c3quat -c3quat_double( - const double *d); - -c3quat -c3quat_add( - const c3quat a, - const c3quat b); -c3quat -c3quat_sub( - const c3quat a, - const c3quat b); -c3quat -c3quat_minus( - const c3quat a ); - -c3quat -c3quat_mul( - const c3quat a, - const c3quat b); - -c3mat4 -c3quat_to_mat4( - const c3quat a ); - -c3quatp -c3quat_set_angle( - c3quatp a, - c3f f); -c3quatp -c3quat_scale_angle( - c3quatp a, - c3f f); -c3f -c3quat_get_angle( - const c3quatp a); -c3vec3 -c3quat_get_axis( - c3quatp a); - -#endif /* __C3QUATERNION_H___ */ diff --git a/examples/board_reprap/src/c3/c3stl.c b/examples/board_reprap/src/c3/c3stl.c deleted file mode 100644 index 248094e..0000000 --- a/examples/board_reprap/src/c3/c3stl.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - c3stl.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "c3/c3algebra.h" -#include "c3/c3geometry.h" -#include "c3/c3object.h" -#include "c3/c3stl.h" - -enum { - vertex_None = -1, - vertex_Vertex, - vertex_Normal, -}; - -static int -_c3stl_read_vertex( - char * vt, - c3vec3 * out ) -{ - int res = 1; - char *l = vt; - /*char * key =*/ strsep(&l, " \t"); - char * x = strsep(&l, " \t"); - char * y = strsep(&l, " \t"); - char * z = strsep(&l, " \t"); - - if (x) sscanf(x, "%f", out->n); - if (y) sscanf(y, "%f", out->n + 1); - if (z) sscanf(z, "%f", out->n + 2); -// printf("'%s' '%s' '%s' '%s' = %.2f %.2f %.2f\n", -// key, x, y, z, out->n[0], out->n[1], out->n[2]); - return res; -} - -struct c3object_t * -c3stl_load( - const char * filename, - c3object_p parent) -{ - FILE *f = fopen(filename, "r"); - if (!f) { - perror(filename); - return NULL; - } - - c3object_p o = c3object_new(parent); - c3geometry_p current_g = NULL; - - int state = 0; - while (!feof(f)) { - char line[256]; - - fgets(line, sizeof(line), f); - - int l = strlen(line); - while (l && line[l-1] < ' ') - line[--l] = 0; - if (!l) - continue; - char * keyword = line; - while (*keyword && *keyword <= ' ') - keyword++; - l = strlen(keyword); - // printf("%d>'%s'\n", state, keyword); - - switch (state) { - case 0: // - if (!strncmp(keyword, "solid ", 6)) { - char * n = keyword + 6; - current_g = c3geometry_new(c3geometry_type(C3_TRIANGLE_TYPE, 0), o); - current_g->name = str_new(n); - - state = 1; - } - break; - case 1: // - if (!strncmp(keyword, "facet ", 6)) { - c3vec3 normal; - _c3stl_read_vertex(keyword + 6, &normal); - c3vertex_array_add(¤t_g->normals, normal); - c3vertex_array_add(¤t_g->normals, normal); - c3vertex_array_add(¤t_g->normals, normal); - state = 2; - } else if (!strncmp(keyword, "endsolid ", 9)) - state = 0; - break; - case 2: - if (!strncmp(keyword, "outer loop", 10)) - state = 3; - else if (!strncmp(keyword, "endfacet", 8)) - state = 1; - break; - case 3: - if (!strncmp(keyword, "vertex ", 7)) { - c3vec3 v; - _c3stl_read_vertex(keyword, &v); - c3vertex_array_add(¤t_g->vertice, v); - state = 3; - } else if (!strncmp(keyword, "endloop", 7)) - state = 2; - break; - } - } - - fclose(f); - return o; -} diff --git a/examples/board_reprap/src/c3/c3stl.h b/examples/board_reprap/src/c3/c3stl.h deleted file mode 100644 index d8bd250..0000000 --- a/examples/board_reprap/src/c3/c3stl.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - c3stl.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3STL_H___ -#define __C3STL_H___ - -struct c3object_t * -c3stl_load( - const char * filename, - struct c3object_t * parent); - -#endif /* __C3STL_H___ */ diff --git a/examples/board_reprap/src/c3/c3texture.c b/examples/board_reprap/src/c3/c3texture.c deleted file mode 100644 index 2230378..0000000 --- a/examples/board_reprap/src/c3/c3texture.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - c3texture.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3texture.h" -#include "c3/c3driver_geometry.h" - -void -_c3texture_dispose( - c3geometry_p g, - const c3driver_geometry_t * d) -{ - c3texture_p t = (c3texture_p)g; - c3pixels_dispose(&t->pixels); - C3_DRIVER_INHERITED(g, d, dispose); -} - -void -_c3texture_project( - c3geometry_p g, - const c3driver_geometry_t * d, - c3mat4p m) -{ - c3texture_p t = (c3texture_p)g; - if (!t->pixels.base) { - C3_DRIVER_INHERITED(g, d, project, m); - return; - } - c3vec3 v[4] = { - c3vec3f(0, 0, 0), c3vec3f(t->pixels.w, 0, 0), - c3vec3f(t->pixels.w, t->pixels.h, 0), c3vec3f(0, t->pixels.h, 0) - }; - c3vertex_array_clear(&g->vertice); - c3vertex_array_realloc(&g->vertice, 4); - c3vertex_array_insert(&g->vertice, 0, v, 4); - - c3vec2 ti[4] = { - c3vec2f(0, 0), c3vec2f(1, 0), - c3vec2f(1, 1), c3vec2f(0, 1) -// c3vec2f(0, 0), c3vec2f(t->pixels.w, 0), -// c3vec2f(t->pixels.w, t->pixels.h), c3vec2f(0, t->pixels.h) - }; - c3tex_array_clear(&t->geometry.textures); - c3tex_array_realloc(&t->geometry.textures, 4); - c3tex_array_insert(&t->geometry.textures, 0, ti, 4); - - C3_DRIVER_INHERITED(g, d, project, m); -} - -const c3driver_geometry_t c3texture_driver = { - .dispose = _c3texture_dispose, - .project = _c3texture_project, -}; -const c3driver_geometry_t c3geometry_driver; - -c3texture_p -c3texture_new( - struct c3object_t * o /* = NULL */) -{ - c3texture_p res = malloc(sizeof(*res)); - return c3texture_init(res, o); -} - -c3texture_p -c3texture_init( - c3texture_p t, - struct c3object_t * o /* = NULL */) -{ - memset(t, 0, sizeof(*t)); - c3geometry_init(&t->geometry, - c3geometry_type(C3_TEXTURE_TYPE, 0 /* GL_TRIANGLE_FAN */), - o); - static const c3driver_geometry_t * list[] = { - &c3texture_driver, &c3geometry_driver, NULL, - }; - t->geometry.driver = list; - - return t; -} - -void -c3texture_setpixels( - ) -{ - -} diff --git a/examples/board_reprap/src/c3/c3texture.h b/examples/board_reprap/src/c3/c3texture.h deleted file mode 100644 index 97328c5..0000000 --- a/examples/board_reprap/src/c3/c3texture.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - c3texture.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3TEXTURE_H___ -#define __C3TEXTURE_H___ - -#include "c3/c3geometry.h" -#include "c3/c3pixels.h" - -typedef struct c3texture_t { - c3geometry_t geometry; - c3pixels_t pixels; -} c3texture_t, *c3texture_p; - -c3texture_p -c3texture_new( - struct c3object_t * parent /* = NULL */); -c3texture_p -c3texture_init( - c3texture_p t, - struct c3object_t * parent /* = NULL */); - -#endif /* __C3TEXTURE_H___ */ diff --git a/examples/board_reprap/src/c3/c3transform.c b/examples/board_reprap/src/c3/c3transform.c deleted file mode 100644 index 4c68b6b..0000000 --- a/examples/board_reprap/src/c3/c3transform.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - c3transform.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c3/c3object.h" - -c3transform_p -c3transform_new( - c3object_p o ) -{ - c3transform_p res = malloc(sizeof(*res)); - res->matrix = identity3D(); - res->object = o; - res->name = NULL; - c3transform_array_add(&o->transform, res); - return res; -} - -void -c3transform_dispose( - c3transform_p t ) -{ - if (t->object) { - for (int oi = 0; oi < t->object->transform.count; oi++) - if (t->object->transform.e[oi] == t) { - c3transform_array_delete(&t->object->transform, oi, 1); - c3object_set_dirty(t->object, true); - break; - } - t->object = NULL; - } - str_free(t->name); - free(t); -} - -void -c3transform_set( - c3transform_p t, - const c3mat4p m ) -{ - if (c3mat4_equal(m, &t->matrix)) - return; - t->matrix = *m; - c3object_set_dirty(t->object, true); -} diff --git a/examples/board_reprap/src/c3/c3transform.h b/examples/board_reprap/src/c3/c3transform.h deleted file mode 100644 index 9a50e3b..0000000 --- a/examples/board_reprap/src/c3/c3transform.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - c3transform.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __C3TRANSFORM_H___ -#define __C3TRANSFORM_H___ - -#include "c3/c3algebra.h" -#include "c_utils.h" - -typedef struct c3transform_t { - str_p name; - struct c3object_t * object; - c3mat4 matrix; -} c3transform_t, *c3transform_p; - -c3transform_p -c3transform_new( - struct c3object_t * o ); -void -c3transform_set( - c3transform_p t, - c3mat4p m ); -void -c3transform_dispose( - c3transform_p t ); - -DECLARE_C_ARRAY(c3transform_p, c3transform_array, 4); -IMPLEMENT_C_ARRAY(c3transform_array); - -#endif /* __C3TRANSFORM_H___ */ diff --git a/examples/board_reprap/src/c3/c_array.h b/examples/board_reprap/src/c3/c_array.h deleted file mode 100644 index 8c08efa..0000000 --- a/examples/board_reprap/src/c3/c_array.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - c_array.h - - Copyright 2012 Michel Pollet - - This file is part of gcodepp. - - gcodepp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - gcodepp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with gcodepp. If not, see . - */ - - -#ifndef __C_ARRAY_H___ -#define __C_ARRAY_H___ - -#include -#include -#include - -#ifndef C_ARRAY_INLINE -#define C_ARRAY_INLINE inline -#endif -#ifndef C_ARRAY_SIZE_TYPE -#define C_ARRAY_SIZE_TYPE uint32_t -#endif - -#define DECLARE_C_ARRAY(__type, __name, __page) \ -enum { __name##_page_size = __page }; \ -typedef __type __name##_element_t; \ -typedef C_ARRAY_SIZE_TYPE __name##_count_t; \ -typedef struct __name##_t {\ - volatile __name##_count_t count;\ - volatile __name##_count_t size;\ - __name##_element_t * e;\ -} __name##_t, *__name##_p; - -#define C_ARRAY_NULL { 0, 0, NULL } - -#define IMPLEMENT_C_ARRAY(__name) \ -static const __name##_t __name##_zero = C_ARRAY_NULL; \ -static C_ARRAY_INLINE \ - void __name##_free(\ - __name##_p a) \ -{\ - if (!a) return;\ - if (a->e) free(a->e);\ - *a = __name##_zero;\ -}\ -static C_ARRAY_INLINE \ - void __name##_clear(\ - __name##_p a) \ -{\ - if (!a) return;\ - a->count = 0;\ -}\ -static C_ARRAY_INLINE \ - void __name##_realloc(\ - __name##_p a, __name##_count_t size) \ -{\ - if (!a || a->size == size) return; \ - a->e = realloc(a->e, size * sizeof(__name##_element_t));\ - a->size = size; \ -}\ -static C_ARRAY_INLINE \ - void __name##_trim(\ - __name##_p a) \ -{\ - if (!a) return;\ - __name##_count_t n = a->count + __name##_page_size;\ - n -= (n % __name##_page_size);\ - if (n != a->size)\ - __name##_realloc(a, n);\ -}\ -static C_ARRAY_INLINE \ - __name##_element_t * __name##_get_ptr(\ - __name##_p a, __name##_count_t index) \ -{\ - if (!a) return NULL;\ - if (index > a->count) index = a->count;\ - return index < a->count ? a->e + index : NULL;\ -}\ -static C_ARRAY_INLINE \ - __name##_count_t __name##_add(\ - __name##_p a, __name##_element_t e) \ -{\ - if (!a) return 0;\ - if (a->count + 1 >= a->size)\ - __name##_realloc(a, a->size + __name##_page_size);\ - a->e[a->count++] = e;\ - return a->count;\ -}\ -static C_ARRAY_INLINE \ - __name##_count_t __name##_insert(\ - __name##_p a, __name##_count_t index, \ - __name##_element_t * e, __name##_count_t count) \ -{\ - if (!a) return 0;\ - if (index > a->count) index = a->count;\ - if (a->count + count >= a->size) \ - __name##_realloc(a, (((a->count + count) / __name##_page_size)+1) * __name##_page_size);\ - if (index < a->count)\ - memmove(&a->e[index + count], &a->e[index], \ - (a->count - index + count) * sizeof(__name##_element_t));\ - memmove(&a->e[index], e, count * sizeof(__name##_element_t));\ - a->count += count;\ - return a->count;\ -}\ -static C_ARRAY_INLINE \ - __name##_count_t __name##_delete(\ - __name##_p a, __name##_count_t index, __name##_count_t count) \ -{\ - if (!a) return 0;\ - if (index > a->count) index = a->count;\ - if (index + count > a->count) \ - count = a->count - index;\ - if (count && a->count - index) { \ - memmove(&a->e[index], &a->e[index + count], \ - (a->count - index - count) * sizeof(__name##_element_t));\ - }\ - a->count -= count;\ - return a->count;\ -} - -#endif /* __C_ARRAY_H___ */ diff --git a/examples/board_reprap/src/c3/c_utils.c b/examples/board_reprap/src/c3/c_utils.c deleted file mode 100644 index e3bb673..0000000 --- a/examples/board_reprap/src/c3/c_utils.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - c_utils.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - simavr is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include "c_utils.h" - -void -str_hash_init(str_hash_p h) -{ - memset(h, 0, sizeof(*h)); -} - -void -str_hash_add( - str_hash_p h, - str_p k, - void * v) -{ - uint16_t hv = str_hash(k); - hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; - int inserti = bin->count; - - for (int i = 0; i < bin->count; i++) - if (bin->e[i].key->hash >= hv) { - inserti = i; - break; - } - str_hashval_t n = { .key = str_dup(k), .val = v }; - hashval_array_insert(bin, inserti, &n, 1); - return; -} - -void * -str_hash_lookup( - str_hash_p h, - str_p k ) -{ - uint16_t hv = str_hash(k); - hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; - - for (int i = 0; i < bin->count; i++) { - uint16_t h = bin->e[i].key->hash; - if (h == hv && !str_cmp(k, bin->e[i].key)) - return bin->e[i].val; - else if (h > hv) - break; - } - return NULL; -} diff --git a/examples/board_reprap/src/c3/c_utils.h b/examples/board_reprap/src/c3/c_utils.h deleted file mode 100644 index 2360fd8..0000000 --- a/examples/board_reprap/src/c3/c_utils.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - c_utils.h - - Copyright 2008-11 Michel Pollet - - This program cross examines a root filesystem, loads all the elf - files it can find, see what other library they load and then - find the orphans. In then remove the orphans as "user" for it's - dependencies and continues removing until everything has at least - one user, OR is a program itself (ie, not a shared library) - - cross_linker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cross_linker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cross_linker. If not, see . - */ - -#ifndef __C_UTILS_H__ -#define __C_UTILS_H__ - -#ifndef NO_ALLOCA -#include -#endif -#include "c_array.h" - -/******************************************************************** - * CRC16 - ********************************************************************/ - -static uint8_t _crc16_lh[16] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, - 0x70, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1 }; -static uint8_t _crc16_ll[16] = { 0x00, 0x21, 0x42, 0x63, 0x84, 0xA5, 0xC6, - 0xE7, 0x08, 0x29, 0x4A, 0x6B, 0x8C, 0xAD, 0xCE, 0xEF }; - -static uint16_t crc16_u4(uint16_t crc, uint8_t val) -{ - uint8_t h = crc >> 8, l = crc & 0xff; - uint8_t t = (h >> 4) ^ val; - - // Shift the CRC Register left 4 bits - h = (h << 4) | (l >> 4); - l = l << 4; - // Do the table lookups and XOR the result into the CRC Tables - h = h ^ _crc16_lh[t]; - l = l ^ _crc16_ll[t]; - return (h << 8) | l; -} - -static uint16_t crc16_update(uint16_t crc, uint8_t val) -{ - crc = crc16_u4(crc, val >> 4); // High nibble first - crc = crc16_u4(crc, val & 0x0F); // Low nibble - return crc; -} - -static uint16_t crc16_string(char * str) -{ - uint16_t crc = 0xffff; - while (*str) - crc = crc16_update(crc, *str++); - return crc; -} - -/******************************************************************** - * Hashed strings - ********************************************************************/ - -#include -typedef struct str_t { - uint32_t hash : 16, rom : 1, len : 15; - char str[0]; -} str_t, *str_p; - -static inline str_p str_new_i(const char *s, void * (*_alloc)(size_t)) -{ - int l = s ? strlen(s) : 0; - str_p r = (str_p)_alloc(sizeof(*r) + l + 1); - r->hash = 0; r->len = l; - if (s) - strcpy(r->str, s); - return r; -} -static inline void str_free(str_p s) -{ - if (s && !s->rom) - free(s); -} -static inline str_p str_new(const char *s) -{ - return str_new_i(s, malloc); -} -static inline str_p str_anew(const char *s) -{ - str_p r = str_new_i(s, alloca); - r->rom = 1; - return r; -} -static inline str_p str_dup(const str_p s) -{ - size_t l = sizeof(*s) + s->len + 1; - str_p r = (str_p)malloc(l); - memcpy(r, s, l); - return r; -} -#ifndef NO_ALLOCA -static inline str_p str_adup(const str_p s) -{ - size_t l = sizeof(*s) + s->len + 1; - str_p r = (str_p)alloca(l); - memcpy(r, s, l); - r->rom = 1; - return r; -} -#endif -static inline uint16_t str_hash(str_p s) -{ - if (!s->hash) s->hash = crc16_string(s->str); - return s->hash; -} -static inline int str_cmp(str_p s1, str_p s2) -{ - if (s1 == s2) return 1; - if (s1->len != s2->len) return 1; - str_hash(s1); - str_hash(s2); - return s1->hash == s2->hash ? strcmp(s1->str, s2->str) : 1; -} - -/******************************************************************** - * Hash table of strings. Key/value pair - ********************************************************************/ - -typedef struct str_hashval_t { - str_p key; - void * val; -} str_hashval_t; - -DECLARE_C_ARRAY(str_hashval_t, hashval_array, 16); -IMPLEMENT_C_ARRAY(hashval_array); - -#ifndef STR_HASH_SIZE -#define STR_HASH_SIZE 512 // use 9 bits of the 16 of the CRC -#endif -/* uses bins to store the strings as per their hash values */ -typedef struct str_hash_t { - hashval_array_t bin[STR_HASH_SIZE]; -} str_hash_t, *str_hash_p; - -void -str_hash_init( - str_hash_p h); -void -str_hash_add( - str_hash_p h, - str_p k, - void * v); - -void * -str_hash_lookup( - str_hash_p h, - str_p k ); - -#endif /* __C_UTILS_H__ */ diff --git a/examples/board_reprap/src/reprap_gl.c b/examples/board_reprap/src/reprap_gl.c index 8bfe8a9..1d66cbd 100644 --- a/examples/board_reprap/src/reprap_gl.c +++ b/examples/board_reprap/src/reprap_gl.c @@ -20,9 +20,15 @@ */ #if __APPLE__ +#define GL_GLEXT_PROTOTYPES #include +#include +#include #else +#define GL_GLEXT_PROTOTYPES +#include #include +#include #endif #include @@ -31,21 +37,24 @@ #include "reprap.h" #include "reprap_gl.h" -#include "c3/c3.h" -#include "c3/c3camera.h" -#include "c3/c3arcball.h" -#include "c3/c3driver_context.h" -#include "c3/c3stl.h" +#include "c3.h" +#include "c3camera.h" +#include "c3driver_context.h" +#include "c3stl.h" +#include "c3lines.h" #include +struct cairo_surface_t; + int _w = 800, _h = 600; -c3cam cam; -c3arcball arcball; +//c3cam cam; c3context_p c3; c3context_p hud; c3object_p head; +c3texture_p fbo_c3; + extern reprap_t reprap; static int dumpError(const char * what) @@ -59,6 +68,200 @@ static int dumpError(const char * what) return count; } +#define GLCHECK(_w) {_w; dumpError(#_w);} + +void print_log(GLuint obj) +{ + int infologLength = 0; + int maxLength; + + if(glIsShader(obj)) + glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength); + else + glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength); + + char infoLog[maxLength]; + + if (glIsShader(obj)) + glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog); + else + glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog); + + if (infologLength > 0) + printf("%s\n",infoLog); +} +/* Global */ +GLuint fbo, fbo_texture, rbo_depth; +//GLuint vbo_fbo_vertices; + +static void +gl_offscreenInit( + int screen_width, + int screen_height) +{ + /* init_resources */ + /* Create back-buffer, used for post-processing */ + + /* Texture */ + GLCHECK(glActiveTexture(GL_TEXTURE0)); + glGenTextures(1, &fbo_texture); + glBindTexture(GL_TEXTURE_2D, fbo_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + /* Depth buffer */ + GLCHECK(glGenRenderbuffers(1, &rbo_depth)); + glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screen_width, + screen_height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + /* Framebuffer to link everything together */ + GLCHECK(glGenFramebuffers(1, &fbo)); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + fbo_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, rbo_depth); + + GLenum status; + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) + != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "glCheckFramebufferStatus: error %d", (int)status); + return ; + } +#if 0 + // Set the list of draw buffers. + GLenum DrawBuffers[2] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +void +gl_offscreenReshape( + int screen_width, + int screen_height) +{ +// Rescale FBO and RBO as well + glBindTexture(GL_TEXTURE_2D, fbo_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screen_width, + screen_height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + +// glBindFramebuffer(GL_FRAMEBUFFER, fbo); +// glViewport(0, 0, screen_width, screen_height); +// glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void gl_offscreenFree() +{ + /* free_resources */ + glDeleteRenderbuffers(1, &rbo_depth); + glDeleteTextures(1, &fbo_texture); + glDeleteFramebuffers(1, &fbo); +// glDeleteBuffers(1, &vbo_fbo_vertices); +} + +GLuint program_postproc = 0, uniform_fbo_texture; + +static GLuint create_shader(const char * fname, GLuint pid) +{ + const GLchar * buf; + + FILE *f = fopen(fname, "r"); + if (!f) { + perror(fname); + return 0; + } + fseek(f, 0, SEEK_END); + long fs = ftell(f); + fseek(f, 0, SEEK_SET); + buf = malloc(fs + 1); + fread((void*)buf, 1, fs, f); + ((char*)buf)[fs] = 0; + fclose(f); + + GLuint vs = glCreateShader(pid); + glShaderSource(vs, 1, &buf, NULL); + glCompileShader(vs); + dumpError("glCompileShader"); + print_log(vs); + free((void*)buf); + return vs; +} + + +int gl_ppProgram() +{ + int vs, fs; + int link_ok, validate_ok; + /* init_resources */ + /* Post-processing */ + if ((vs = create_shader("gfx/postproc.vs", GL_VERTEX_SHADER)) == 0) + return 0; + if ((fs = create_shader("gfx/postproc.fs", GL_FRAGMENT_SHADER)) == 0) + return 0; + + program_postproc = glCreateProgram(); + glAttachShader(program_postproc, vs); + glAttachShader(program_postproc, fs); + glLinkProgram(program_postproc); + glGetProgramiv(program_postproc, GL_LINK_STATUS, &link_ok); + if (!link_ok) { + fprintf(stderr, "glLinkProgram:"); + goto error; + } + glValidateProgram(program_postproc); + glGetProgramiv(program_postproc, GL_VALIDATE_STATUS, &validate_ok); + if (!validate_ok) { + fprintf(stderr, "glValidateProgram:"); + goto error; + } + + char * uniform_name = "m_Texture"; + uniform_fbo_texture = glGetUniformLocation(program_postproc, uniform_name); + if (uniform_fbo_texture == -1) { + fprintf(stderr, "Could not bind uniform %s\n", uniform_name); + goto error; + } + return 0; +error: + print_log(program_postproc); + glDeleteProgram(program_postproc); + program_postproc = 0; + return -1; +} + +void +gl_ppFree() +{ + if (program_postproc) + glDeleteProgram(program_postproc); + program_postproc = 0; +} + +static void +_gl_reshape_cb(int w, int h) +{ + _w = w; + _h = h; + + glViewport(0, 0, _w, _h); + gl_offscreenReshape(_w, _h); + glutPostRedisplay(); +} + static void _gl_key_cb( unsigned char key, @@ -79,9 +282,71 @@ _gl_key_cb( printf("Stopping VCD trace\n"); // avr_vcd_stop(&vcd_file); break; + case '1': + if (fbo_c3->geometry.mat.program.pid) + fbo_c3->geometry.mat.program.pid = 0; + else + fbo_c3->geometry.mat.program.pid = program_postproc; + glutPostRedisplay(); + break; } } +static void +_c3_load_pixels( + c3pixels_p pix) +{ + GLuint mode = pix->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB; + if (!pix->texture) { + printf("Creating texture %s %dx%d\n", pix->name ? pix->name->str : "", pix->w, pix->h); + pix->dirty = 1; + GLuint texID = 0; + dumpError("cp_gl_texture_load_argb flush"); + GLCHECK(glEnable(mode)); + + glGenTextures(1, &texID); +// glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, +// GL_MODULATE); //set texture environment parameters +// dumpError("glTexEnvf"); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, pix->row / pix->psize); + glTexParameteri(mode, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + dumpError("GL_TEXTURE_MAG_FILTER");// + glTexParameteri(mode, GL_TEXTURE_MIN_FILTER, + pix->normalize ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + dumpError("GL_TEXTURE_MIN_FILTER"); + glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + dumpError("GL_TEXTURE_WRAP_S"); + glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + dumpError("GL_TEXTURE_WRAP_T"); + if (pix->normalize) + GLCHECK(glTexParameteri(mode, GL_GENERATE_MIPMAP, GL_TRUE)); + #if 1 + GLfloat fLargest; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); + //printf("fLargest = %f\n", fLargest); + GLCHECK(glTexParameterf(mode, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest)); + #endif + if (pix->normalize) + GLCHECK(glGenerateMipmap(mode)); + + pix->texture = texID; + pix->dirty = 1; + } + if (pix->dirty) { + pix->dirty = 0; + GLCHECK(glBindTexture(mode, pix->texture)); + glTexImage2D(mode, 0, + pix->format == C3PIXEL_A ? GL_ALPHA16 : GL_RGBA8, + pix->w, pix->h, 0, + pix->format == C3PIXEL_A ? GL_ALPHA : GL_BGRA, + GL_UNSIGNED_BYTE, + pix->base); + dumpError("glTexImage2D"); + if (pix->normalize) + GLCHECK(glGenerateMipmap(mode)); + } +} static void _c3_geometry_project( @@ -90,142 +355,24 @@ _c3_geometry_project( c3geometry_p g, c3mat4p m) { + if (g->mat.texture) { +// printf("_c3_geometry_project xrure %d!\n", g->textures.count); + _c3_load_pixels(g->mat.texture); + } + switch(g->type.type) { - case C3_TRIANGLE_TYPE: { + case C3_TRIANGLE_TYPE: g->type.subtype = GL_TRIANGLES; - //g->mat.color = c3vec4f(0.0, 0.0, 1.0, 1.0); - } break; + break; case C3_TEXTURE_TYPE: { - c3texture_p t = (c3texture_p)g; - g->type.subtype = GL_TRIANGLE_FAN; - g->mat.color = c3vec4f(0.0, 1.0, 0.0, 0.5); - printf("_c3_geometry_project xrure %d!\n", g->textures.count); - if (!g->texture) { - GLuint texID = 0; - dumpError("cp_gl_texture_load_argb flush"); - - if (g->mat.mode == 0) - g->mat.mode = GL_TEXTURE_RECTANGLE_ARB; - - printf("C3_TEXTURE_TYPE %d\n",g->mat.mode); - glEnable(g->mat.mode); - dumpError("cp_gl_texture_load_argb GL_TEXTURE_RECTANGLE_ARB"); - - glGenTextures(1, &texID); - dumpError("cp_gl_texture_load_argb glBindTexture GL_TEXTURE_RECTANGLE_ARB"); - -// glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, -// GL_MODULATE ); //set texture environment parameters - dumpError("glTexEnvf"); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, t->pixels.row / t->pixels.psize); - glTexParameteri(g->mat.mode, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - dumpError("GL_TEXTURE_MAG_FILTER"); - glTexParameteri(g->mat.mode, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - dumpError("GL_TEXTURE_MIN_FILTER"); - glTexParameteri(g->mat.mode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - dumpError("GL_TEXTURE_WRAP_S"); - glTexParameteri(g->mat.mode, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - dumpError("GL_TEXTURE_WRAP_T"); - glTexParameteri(g->mat.mode, GL_GENERATE_MIPMAP, GL_TRUE); - dumpError("GL_GENERATE_MIPMAP"); - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - dumpError("GL_GENERATE_MIPMAP_HINT"); - - g->mat.texture = texID; - g->texture = 1; + // c3texture_p t = (c3texture_p)g; + if (g->mat.texture) { + g->type.subtype = GL_TRIANGLE_FAN; } - glBindTexture(g->mat.mode, g->mat.texture); - dumpError("glBindTexture"); - glTexImage2D(g->mat.mode, 0, - t->pixels.format == C3PIXEL_A ? GL_ALPHA8 : GL_RGBA8, - t->pixels.w, t->pixels.h, 0, - t->pixels.format == C3PIXEL_A ? GL_ALPHA : GL_BGRA, - GL_UNSIGNED_BYTE, - t->pixels.base); - dumpError("glTexImage2D"); - glGenerateMipmap(GL_TEXTURE_2D); - dumpError("glGenerateMipmap"); - } break; - case C3_LINES_TYPE: { - // glLineWidth(1); - float lineWidth = 0.2; - - c3vertex_array_p v = &g->projected; - c3tex_array_p tex = &g->textures; - c3tex_array_clear(tex); - c3vertex_array_clear(v); - for (int l = 0; l < g->vertice.count; l += 2) { - c3vec3 a = c3mat4_mulv3(m, g->vertice.e[l]); - c3vec3 b = c3mat4_mulv3(m, g->vertice.e[l+1]); - - c3vec3 e = c3vec3_mulf(c3vec3_normalize(c3vec3_sub(b, a)), lineWidth); - - c3vec3 N = c3vec3f(-e.y, e.x, 0); - c3vec3 S = c3vec3_minus(N); - c3vec3 NE = c3vec3_add(N, e); - c3vec3 NW = c3vec3_sub(N, e); - c3vec3 SW = c3vec3_minus(NE); - c3vec3 SE = c3vec3_minus(NW); -#if 0 - c3vertex_array_add(v, c3vec3_add(a, SW)); - c3vertex_array_add(v, c3vec3_add(a, NW)); - c3vertex_array_add(v, c3vec3_add(a, S)); - c3vertex_array_add(v, c3vec3_add(a, N)); - c3vertex_array_add(v, c3vec3_add(b, S)); - c3vertex_array_add(v, c3vec3_add(b, N)); - c3vertex_array_add(v, c3vec3_add(b, SE)); - c3vertex_array_add(v, c3vec3_add(b, NE)); -#endif - - const float ts = 1; - - c3vertex_array_add(v, c3vec3_add(a, SW)); - c3vertex_array_add(v, c3vec3_add(a, S)); - c3vertex_array_add(v, c3vec3_add(a, NW)); - c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); - - c3vertex_array_add(v, c3vec3_add(a, S)); - c3vertex_array_add(v, c3vec3_add(a, N)); - c3vertex_array_add(v, c3vec3_add(a, NW)); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); - - c3vertex_array_add(v, c3vec3_add(a, N)); - c3vertex_array_add(v, c3vec3_add(b, S)); - c3vertex_array_add(v, c3vec3_add(b, N)); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - - c3vertex_array_add(v, c3vec3_add(a, N)); - c3vertex_array_add(v, c3vec3_add(a, S)); - c3vertex_array_add(v, c3vec3_add(b, S)); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - - c3vertex_array_add(v, c3vec3_add(b, N)); - c3vertex_array_add(v, c3vec3_add(b, S)); - c3vertex_array_add(v, c3vec3_add(b, SE)); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); - - c3vertex_array_add(v, c3vec3_add(b, N)); - c3vertex_array_add(v, c3vec3_add(b, SE)); - c3vertex_array_add(v, c3vec3_add(b, NE)); - c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); - c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); - c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 1 )); - - } + case C3_LINES_TYPE: g->type.subtype = GL_TRIANGLES; - } break; + break; default: break; } @@ -245,26 +392,37 @@ _c3_geometry_draw( glEnableClientState(GL_VERTEX_ARRAY); dumpError("GL_VERTEX_ARRAY"); glDisable(GL_TEXTURE_2D); - if (g->textures.count && g->texture) { - glEnable(g->mat.mode); + if (g->mat.texture) { + GLuint mode = g->mat.texture->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB; + glEnable(mode); + if (g->mat.texture->trace) + printf("%s uses texture %s (%d tex)\n", + __func__, g->mat.texture->name->str, g->textures.count); // printf("tex mode %d texture %d\n", g->mat.mode, g->mat.texture); dumpError("glEnable texture"); - glBindTexture(g->mat.mode, g->mat.texture); + glBindTexture(mode, g->mat.texture->texture); dumpError("glBindTexture"); glTexCoordPointer(2, GL_FLOAT, 0, g->textures.e); glEnableClientState(GL_TEXTURE_COORD_ARRAY); dumpError("GL_TEXTURE_COORD_ARRAY"); } + if (g->mat.program.pid) { + glUseProgram(g->mat.program.pid); + dumpError("glUseProgram program_postproc"); + } if (g->normals.count) { glNormalPointer(GL_FLOAT, 0, g->normals.e); glEnableClientState(GL_NORMAL_ARRAY); } - glDrawArrays(g->type.subtype, 0, g->projected.count ? g->projected.count : g->vertice.count); + glDrawArrays(g->type.subtype, 0, + g->projected.count ? g->projected.count : g->vertice.count); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - if (g->textures.count && g->texture) - glDisable(g->mat.mode); + if (g->mat.texture) + glDisable(g->mat.texture->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB); + if (g->mat.program.pid) + glUseProgram(0); } const c3driver_context_t c3context_driver = { @@ -272,6 +430,7 @@ const c3driver_context_t c3context_driver = { .geometry_draw = _c3_geometry_draw, }; +float z_min, z_max; /* * Computes the distance from the eye, sort by this value */ @@ -286,9 +445,13 @@ _c3_z_sorter( c3vec3 c1 = c3vec3_add(g1->bbox.min, c3vec3_divf(c3vec3_sub(g1->bbox.max, g1->bbox.min), 2)); c3vec3 c2 = c3vec3_add(g2->bbox.min, c3vec3_divf(c3vec3_sub(g2->bbox.max, g2->bbox.min), 2)); - c3f d1 = c3vec3_length2(c3vec3_sub(c1, cam.eye)); - c3f d2 = c3vec3_length2(c3vec3_sub(c2, cam.eye)); + c3f d1 = c3vec3_length2(c3vec3_sub(c1, c3->cam.eye)); + c3f d2 = c3vec3_length2(c3vec3_sub(c2, c3->cam.eye)); + if (d1 > z_max) z_max = d1; + if (d1 < z_min) z_min = d1; + if (d2 > z_max) z_max = d2; + if (d2 < z_min) z_min = d2; /* * make sure transparent items are drawn after everyone else */ @@ -300,9 +463,52 @@ _c3_z_sorter( return d1 < d2 ? 1 : d1 > d2 ? -1 : 0; } +#define FBO 0 + static void _gl_display_cb(void) /* function called whenever redisplay needed */ { +#if FBO + if (program_postproc) { + /* + * Draw in FBO object + */ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + // draw (without glutSwapBuffers) + dumpError("glBindFramebuffer fbo"); + glViewport(0, 0, _w, _h); + } +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + + c3vec3 headp = c3vec3f( + stepper_get_position_mm(&reprap.step_x), + stepper_get_position_mm(&reprap.step_y), + stepper_get_position_mm(&reprap.step_z)); + c3mat4 headmove = translation3D(headp); + c3transform_set(head->transform.e[0], &headmove); + + if (c3->root->dirty) { + printf("reproject head %.2f,%.2f,%.2f\n", headp.x, headp.y,headp.z); + c3context_project(c3); + + z_min = 1000000000; + z_max = -1000000000; + qsort(c3->projected.e, c3->projected.count, sizeof(c3->projected.e[0]), + _c3_z_sorter); + z_min = sqrt(z_min); + z_max = sqrt(z_max); + // printf("z_min %f, z_max %f\n", z_min, z_max); + //z_min -= 50; + if (z_min < 0) + z_min = 10; + z_min = 10; + if (z_max < z_min || z_max > 1000) + z_max = 1000; + } + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -310,50 +516,71 @@ _gl_display_cb(void) /* function called whenever redisplay needed */ glMatrixMode(GL_PROJECTION); // Select projection matrix glLoadIdentity(); // Start with an identity matrix - gluPerspective(60, _w / _h, 60, 400); + gluPerspective(50, (float)_w / (float)_h, z_min, z_max); #if 0 glCullFace(GL_BACK); glEnable(GL_CULL_FACE); #endif glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - glEnable(GL_BLEND); // Enable Blending - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - // glMultMatrixf(arcball.rot.n); - glMultMatrixf(cam.mtx.n); - glTranslatef( -cam.eye.n[VX], -cam.eye.n[VY], -cam.eye.n[VZ] ); - // glMultMatrixf(arcball.rot.n); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 1.0f / 255.0f); + glEnable(GL_BLEND); // Enable Blending + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use - c3vec3 headp = c3vec3f( - stepper_get_position_mm(&reprap.step_x), - stepper_get_position_mm(&reprap.step_y), - stepper_get_position_mm(&reprap.step_z)); - c3mat4 headmove = translation3D(headp); - c3transform_set(head->transform.e[0], &headmove); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMultMatrixf(c3->cam.mtx.n); + glTranslatef(-c3->cam.eye.n[VX], -c3->cam.eye.n[VY], -c3->cam.eye.n[VZ]); - if (c3->root->dirty) { - // printf("reproject\n"); - c3context_project(c3); + dumpError("flush"); - qsort(c3->projected.e, c3->projected.count, - sizeof(c3->projected.e[0]), _c3_z_sorter); - } c3context_draw(c3); - glMatrixMode(GL_PROJECTION); // Select projection matrix +#if FBO + /* + * Draw back FBO over the screen + */ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + dumpError("glBindFramebuffer 0"); + glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); + glDisable(GL_ALPHA_TEST); + + glMatrixMode(GL_PROJECTION); // Select projection matrix + glLoadIdentity(); // Start with an identity matrix + + glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); // Select modelview matrix + glLoadIdentity(); // Start with an identity matrix + +#if 0 + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, fbo_texture); + dumpError("glBindTexture fbo"); +#if 0 + glUseProgram(program_postproc); + dumpError("glUseProgram program_postproc"); + glUniform1i(uniform_fbo_texture, /*GL_TEXTURE*/0); +#endif + glUseProgram(0); +#endif +#endif + + glMatrixMode(GL_PROJECTION); // Select projection matrix glLoadIdentity(); // Start with an identity matrix glOrtho(0, _w, 0, _h, 0, 10); - glScalef(1,-1,1); + glScalef(1, -1, 1); glTranslatef(0, -1 * _h, 0); glMatrixMode(GL_MODELVIEW); // Select modelview matrix + glLoadIdentity(); // Start with an identity matrix if (hud) c3context_draw(hud); @@ -361,9 +588,14 @@ _gl_display_cb(void) /* function called whenever redisplay needed */ glutSwapBuffers(); } +#if !defined(GLUT_WHEEL_UP) +# define GLUT_WHEEL_UP 3 +# define GLUT_WHEEL_DOWN 4 +#endif + + int button; c3vec2 move; -c3cam startcam; static void _gl_button_cb( @@ -373,12 +605,22 @@ void _gl_button_cb( int y) { button = s == GLUT_DOWN ? b : 0; - startcam = cam; move = c3vec2f(x, y); - if (s == GLUT_DOWN) - c3arcball_mouse_down(&arcball, x, y); - else - c3arcball_mouse_up(&arcball); +// printf("button %d: %.1f,%.1f\n", b, move.x, move.y); + switch (b) { + case GLUT_LEFT_BUTTON: + case GLUT_RIGHT_BUTTON: // call motion + break; + case GLUT_WHEEL_UP: + case GLUT_WHEEL_DOWN: + if (c3->cam.distance > 10) { + const float d = 0.004; + c3cam_set_distance(&c3->cam, c3->cam.distance * ((b == GLUT_WHEEL_DOWN) ? (1.0+d) : (1.0-d))); + c3cam_update_matrix(&c3->cam); + c3->root->dirty = 1; // resort the array + } + break; + } } void @@ -389,26 +631,32 @@ _gl_motion_cb( c3vec2 m = c3vec2f(x, y); c3vec2 delta = c3vec2_sub(move, m); -// printf("%s b%d click %.1f,%.1f now %d,%d\n", -// __func__, button, move.n[0], move.n[1], x, y); +// printf("%s b%d click %.1f,%.1f now %d,%d delta %.1f,%.1f\n", +// __func__, button, move.n[0], move.n[1], x, y, delta.x, delta.y); switch (button) { case GLUT_LEFT_BUTTON: { - // c3cam_eye_yaw(&cam, delta.n[0] / 4); - // c3cam_eye_pitch(&cam, delta.n[1] / 4); +// c3mat4 rotx = rotation3D(c3vec3f(1.0, 0, 0), delta.n[1] / 4); +// c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4); - c3mat4 rotx = rotation3D(c3vec3f(1.0, 0, 0), delta.n[1] / 4); + c3mat4 rotx = rotation3D(c3->cam.side, delta.n[1] / 4); c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4); rotx = c3mat4_mul(&rotx, &roty); - c3cam_rot_about_lookat(&cam, &rotx); + c3cam_rot_about_lookat(&c3->cam, &rotx); - c3cam_update_matrix(&cam); + c3cam_update_matrix(&c3->cam); c3->root->dirty = 1; // resort the array -// c3arcball_mouse_motion(&arcball, x, y, 0,0,0); } break; case GLUT_RIGHT_BUTTON: { + // offset both points, but following the plane + c3vec3 f = c3vec3_mulf(c3vec3f(-c3->cam.side.y, c3->cam.side.x, 0), -delta.n[1] / 4); + c3->cam.eye = c3vec3_add(c3->cam.eye, f); + c3->cam.lookat = c3vec3_add(c3->cam.lookat, f); + c3cam_movef(&c3->cam, delta.n[0] / 8, 0, 0); + c3cam_update_matrix(&c3->cam); + c3->root->dirty = 1; // resort the array } break; } move = m; @@ -419,9 +667,6 @@ static void _gl_timer_cb( int i) { - //static int oldstate = -1; - // restart timer - c3arcball_idle(&arcball); glutTimerFunc(1000 / 24, _gl_timer_cb, 0); glutPostRedisplay(); } @@ -433,7 +678,7 @@ gl_init( { glutInit(&argc, argv); /* initialize GLUT system */ - glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA); glutInitWindowSize(_w, _h); /* width=400pixels height=500pixels */ /*window =*/ glutCreateWindow("Press 'q' to quit"); /* create window */ @@ -443,8 +688,10 @@ gl_init( glutMouseFunc(_gl_button_cb); glutMotionFunc(_gl_motion_cb); + glutReshapeFunc(_gl_reshape_cb); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); /* glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); @@ -479,28 +726,41 @@ gl_init( glEnable(GL_LIGHT0); } #endif -// glEnable(GL_BLEND); - // Works for the UI !! -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - cam = c3cam_new(); - cam.lookat = c3vec3f(100.0, 100.0, 0.0); - cam.eye = c3vec3f(100.0, -100.0, 100.0); - c3cam_update_matrix(&cam); - - c3arcball_init_center(&arcball, c3vec2f(_w/2, _h/2), 100); -// hd44780_gl_init(); + gl_offscreenInit(_w, _h); + gl_ppProgram(); c3 = c3context_new(_w, _h); static const c3driver_context_t * list[] = { &c3context_driver, NULL }; c3->driver = list; - c3texture_p line_aa_tex = NULL; + c3->cam.lookat = c3vec3f(100.0, 100.0, 0.0); + c3->cam.eye = c3vec3f(100.0, -100.0, 100.0); + c3cam_update_matrix(&c3->cam); + { - cairo_surface_t * image = cairo_image_surface_create_from_png ("gfx/BlurryCircle.png"); + const char *path = "gfx/hb.png"; + cairo_surface_t * image = cairo_image_surface_create_from_png (path); printf("image = %p %p\n", image, cairo_image_surface_get_data (image)); c3texture_p b = c3texture_new(c3->root); + c3pixels_p dst = c3pixels_new( + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 4, cairo_image_surface_get_stride(image), + cairo_image_surface_get_data (image)); + dst->name = str_new(path); + b->geometry.mat.texture = dst; + b->size = c3vec2f(200, 200); + b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); +// c3transform_new(head); + } + c3pixels_p line_aa_tex = NULL; + { + const char *path = "gfx/BlurryCircle.png"; + cairo_surface_t * image = cairo_image_surface_create_from_png (path); + printf("image = %p %p\n", image, cairo_image_surface_get_data (image)); + +#if 0 c3pixels_p dst = &b->pixels; c3pixels_init(dst, cairo_image_surface_get_width (image), @@ -508,6 +768,8 @@ gl_init( 1, cairo_image_surface_get_width (image), NULL); c3pixels_alloc(dst); + b->size = c3vec2f(32, 32); + b->normalized = 1; c3pixels_p src = c3pixels_new( cairo_image_surface_get_width (image), @@ -523,56 +785,62 @@ gl_init( max = _s[i] & 0xff; for (int i = 0; i < dst->h * dst->w; i++) *_d++ = ((_s[i] & 0xff) * 255) / max;// + (0xff - max); - - b->geometry.dirty = 1; - c3mat4 i = identity3D(); - b->geometry.mat.mode = GL_TEXTURE_2D; b->pixels.format = C3PIXEL_A; - c3geometry_project(&b->geometry, &i); - //_c3_geometry_project(NULL, NULL, &b->geometry, &i); - line_aa_tex = b; +#else + c3pixels_p dst = c3pixels_new( + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 4, cairo_image_surface_get_stride(image), + cairo_image_surface_get_data (image)); + dst->format = C3PIXEL_ARGB; + dst->normalize = 1; + dst->name = str_new(path); + uint8_t * line = dst->base; + for (int y = 0; y < dst->h; y++, line += dst->row) { + uint32_t *p = (uint32_t *)line; + for (int x = 0; x < dst->w; x++, p++) { + uint8_t b = *p; + *p = ((0xff - b) << 24);//|(b << 16)|(b << 8)|(b); + } + } +#endif + line_aa_tex = dst; - c3pixels_p p = &b->pixels; + c3pixels_p p = dst; printf("struct { int w, h, stride, size, format; uint8_t pix[] } img = {\n" "%d, %d, %d, %d, %d\n", p->w, p->h, (int)p->row, p->psize, cairo_image_surface_get_format(image)); for (int i = 0; i < 32; i++) - printf("0x%08x", ((uint32_t*)src->base)[i]); + printf("0x%08x ", ((uint32_t*)p->base)[i]); printf("\n"); } c3object_p grid = c3object_new(c3->root); { - for (int x = 0; x < 20; x++) { - for (int y = 0; y < 20; y++) { + for (int x = 0; x <= 20; x++) { + for (int y = 0; y <= 20; y++) { c3vec3 p[4] = { - c3vec3f(-1+x*10,y*10,0), c3vec3f(1+x*10,y*10,0), - c3vec3f(x*10,-1+y*10,0), c3vec3f(x*10,1+y*10,0), + c3vec3f(-1+x*10,y*10,0.01), c3vec3f(1+x*10,y*10,0.01), + c3vec3f(x*10,-1+y*10,0.02), c3vec3f(x*10,1+y*10,0.02), }; c3geometry_p g = c3geometry_new( c3geometry_type(C3_LINES_TYPE, 0), grid); - g->mat.color = c3vec4f(0.0, 0.0, 0.0, 1.0); - g->mat.texture = line_aa_tex->geometry.mat.texture; - g->mat.mode = GL_TEXTURE_2D;//GL_TEXTURE_RECTANGLE_ARB; - g->texture = 1; - c3vertex_array_insert(&g->vertice, - g->vertice.count, p, 4); + g->mat.color = c3vec4f(0.0, 0.0, 0.0, 0.8); + g->mat.texture = line_aa_tex; + c3lines_init(g, p, 4, 0.2); } } } - { + if (0) { c3vec3 p[4] = { - c3vec3f(-5,-5,0), c3vec3f(205,-5,0), + c3vec3f(-5,-5,1), c3vec3f(205,-5,1), }; c3geometry_p g = c3geometry_new( c3geometry_type(C3_LINES_TYPE, 0), grid); - g->mat.color = c3vec4f(0.0, 0.0, 0.0, 0.8); - g->mat.texture = line_aa_tex->geometry.mat.texture; - g->mat.mode = GL_TEXTURE_2D;//GL_TEXTURE_RECTANGLE_ARB; -// g->mat.mode = GL_TEXTURE_RECTANGLE_ARB; - g->texture = 1; + g->mat.color = c3vec4f(0.0, 0.0, 0.0, 1.0); + g->mat.texture = line_aa_tex; + g->line.width = 2; - printf("AA texture is %d\n", line_aa_tex->geometry.mat.texture); c3vertex_array_insert(&g->vertice, g->vertice.count, p, 2); @@ -594,20 +862,34 @@ gl_init( hud = c3context_new(_w, _h); hud->driver = list; + /* + * This is the offscreen framebuffer where the 3D scene is drawn + */ + if (program_postproc) { + c3texture_p b = c3texture_new(hud->root); + + c3pixels_p dst = c3pixels_new(_w, _h, 4, _w * 4, NULL); + dst->name = str_new("fbo"); + dst->texture = fbo_texture; + dst->normalize = 1; + dst->dirty = 0; + // dst->trace = 1; + b->geometry.mat.texture = dst; + b->geometry.mat.program.pid = program_postproc; + b->size = c3vec2f(_w, _h); + b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); + fbo_c3 = b; + } { c3vec3 p[4] = { - c3vec3f(10,10,0), c3vec3f(700,40,0), + c3vec3f(10,10,0), c3vec3f(800-10,10,0), }; c3geometry_p g = c3geometry_new( c3geometry_type(C3_LINES_TYPE, 0), hud->root); - g->mat.color = c3vec4f(0.0, 0.0, 0.0, 0.8); - g->mat.texture = line_aa_tex->geometry.mat.texture; - g->mat.mode = GL_TEXTURE_2D;//GL_TEXTURE_RECTANGLE_ARB; -// g->mat.mode = GL_TEXTURE_RECTANGLE_ARB; - g->texture = 1; - c3vertex_array_insert(&g->vertice, - g->vertice.count, p, 2); + g->mat.color = c3vec4f(0.5, 0.5, 1.0, .3f); + g->mat.texture = line_aa_tex; + c3lines_init(g, p, 2, 10); } return 1; } diff --git a/examples/shared/libc3/Makefile b/examples/shared/libc3/Makefile new file mode 100644 index 0000000..25ab1db --- /dev/null +++ b/examples/shared/libc3/Makefile @@ -0,0 +1,80 @@ + +VERSION = 0.1.0 +REVISION = 1 + +SHELL := ${shell which bash} + +IPATH += src +VPATH += src + +OBJ = obj-${shell $(CC) -dumpmachine} + +C3SRC = ${wildcard src/*.c} +C3OBJ = ${patsubst src/%,${OBJ}/%,${C3SRC:.c=.lo}} + +CC = clang +PKGCONFIG = pkg-config +LIBTOOL = libtool +INSTALL = install + +CFLAGS = -g -O2 +CPPFLAGS += --std=gnu99 -fPIC +CPPFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} +CPPFLAGS += ${shell $(PKGCONFIG) --cflags pango cairo} + +LDFLAGS += + +DESTDIR = /usr/local + +-include ${wildcard .make.options*} + +all: ${OBJ} src/c3config.h ${OBJ}/libc3.la + +${OBJ}: + mkdir -p ${OBJ} + +ifneq (${V}, 1) +E=@ +LIBTOOL += --quiet +endif + +src/c3config.h: + $(E)rm -f $@ + $(E)echo CONFIG $@ + $(E)( \ + printf "#ifndef __C3_CONFIG__\n#define __C3_CONFIG__\n"; \ + printf "#define CONFIG_C3_VERSION \"$(VERSION)\"\n"; \ + $(PKGCONFIG) --exists pango cairo || printf "// " ; \ + printf "#define CONFIG_C3_CAIRO 1\n"; \ + printf "#endif\n"; \ + ) >$@ + +${OBJ}/libc3.la: ${C3OBJ} + @echo LINK $@ + $(E)$(LIBTOOL) --mode=link --tag=CC \ + $(CC) $(CPPFLAGS) $(CFLAGS) \ + $^ -o $@ \ + -version-info 0:1:0 \ + -rpath $(DESTDIR)/lib $(LDFLAGS) + +${OBJ}/%.lo: src/c3config.h +${OBJ}/%.lo: %.c + @echo CC $< + $(E)$(LIBTOOL) --mode=compile --tag=CC \ + $(CC) $(CPPFLAGS) $(CFLAGS) -MT $@ -MMD \ + $< -c -o $@ + +install: + mkdir -p $(DESTDIR)/lib/pkgconfig $(DESTDIR)/include/c3 + rm -f $(DESTDIR)/lib/libc3* $(DESTDIR)/include/c3/* + $(INSTALL) src/*.h $(DESTDIR)/include/c3/ + cp -a ${OBJ}/.libs/*.a ${OBJ}/.libs/*.so* $(DESTDIR)/lib/ + sed -e 's|PREFIX|${DESTDIR}|g' -e 's|VERSION|${VERSION}|g' \ + libc3.pc >$(DESTDIR)/lib/pkgconfig/libc3.pc + +clean: + rm -rf ${OBJ} + +# include the dependency files generated by gcc, if any +-include ${wildcard ${OBJ}/*.d} + \ No newline at end of file diff --git a/examples/shared/libc3/README.md b/examples/shared/libc3/README.md new file mode 100644 index 0000000..31207ab --- /dev/null +++ b/examples/shared/libc3/README.md @@ -0,0 +1,77 @@ +libc3 - No frill 'scene' graph library in C +===== +(C) 2012 Michel Pollet + +**WARNING** This API is not your nanny. It is made to be lean, mean, efficient +with no frill, no asserts, no bounds checking, no sugar coating. + +On the other hand it's fast, reasonably clean and is a micro-fraction of the +other giganormous 'scene graphs' or 'game engine' libraries around. + +It's vaguely inspired by THREE.js funnily enough, because it allows you to +hack around and quickly get stuff on screen with the minimal amount of +effort. + +The API has various bits: +* c3algebra: C derivative of an old C++ piece of code I had lying around and that has +been present in my toolset for a long time. It gives you *vectors* (c3vec2, c3vec3, c3vec4) +and *matrices* (c3mat3, c3mat4) with various tools to manipulate them. +* c3quaternion: Quaternion implementation using c3algebra +* c3camera/c3arcball: camera manipulation, not perfect + +The basic data structure is as follow: +* *c3context*: + Mostly placeholder for now, hosts a "root" object, can reproject the + objects & geometry, and call the callbacks to draw them. +* *c3object*: + * Has a list of (sub) c3objects + * Has a list of c3transforms (ie matrices) + * Has a list of c3geometry (ie real vertices and stuff) + The object is a container for other objects, and for geometry itself. Objects don't + necessary have geometry and/or sub objects, and don't even need transforms if their + vertices are already projected. +* *c3geometry*: + * Has a 'type' (raw for simple vertices, texture, triangles etc) + * Has a 'subtype' (mostly can be used to draw GL types) + * Has a 'material' (ie color, texture... to be completed) + * Has a list of vertices + * Has a list of texture coordinates (optional) + * Has a list of vertices colors (optional) + * Has a cached copy of a vertices when it has been 'projected' +* *c3transform*: + Is just a sugar coated matrix, with an optional name. + +Also there are: +* *c3pixels*: + Is just a wrapper/holder for some pixels, either allocated, or inherited, + it's mostly used for *c3texture* +* *c3texture*: + Associates a *c3geometry* with a *c3pixels* and has a standard Quad + for vertices. The OpenGL drawing is not done there, it's done by the application using + the generic *c3context* driver. +* *c3cairo*: + Placeholder for now, inherits from *c3texture* and will contain a + cairo surface mapped to a GL texture. +* *c3pango*: + A text label, inherits from *c3cairo* + +Draw Drivers "Inheritance" +------------ +Various object uses static tables of callbacks to implement their behaviours +it's kinda cheap c++ inheritance, without the usual bloat. + +There just a couple macros to call the driver chain for a particular function call. +The relevant bits are in c3driver*.h. + +Mostly the code looks for a matching callback in a static table, and call it if found. +If that callback wants, it can also call the inherited object callback too. + +Dirtyness +--------- +There is a notion of 'dirtyness' in the tree, when you touch a *c3transform*, and/remove +objects and geometry, a dirty bit is propagated up the tree of object. This tells the +rendering it needs to reproject the dirty bits and repopulate the projected vertice +cache. + +The 'dirty' bit moves both ways, when setting a dirty bit to true, it propagates upward, +when you set it to false, it propagates downward in the tree. diff --git a/examples/shared/libc3/libc3.pc b/examples/shared/libc3/libc3.pc new file mode 100644 index 0000000..3413e95 --- /dev/null +++ b/examples/shared/libc3/libc3.pc @@ -0,0 +1,12 @@ +libc3.pc: +prefix=PREFIX +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: libc3 +Description: Lightweight scene graph library in C +Version: VERSION +Cflags: -I${includedir} +Requires.private: pangocairo +Libs: -L${libdir} -llibc3 diff --git a/examples/shared/libc3/src/c3.c b/examples/shared/libc3/src/c3.c new file mode 100644 index 0000000..38fcf83 --- /dev/null +++ b/examples/shared/libc3/src/c3.c @@ -0,0 +1,24 @@ +/* + c3.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3.h" + diff --git a/examples/shared/libc3/src/c3.h b/examples/shared/libc3/src/c3.h new file mode 100644 index 0000000..190ba23 --- /dev/null +++ b/examples/shared/libc3/src/c3.h @@ -0,0 +1,32 @@ +/* + c3.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3_H___ +#define __C3_H___ + +#include "c3context.h" +#include "c3object.h" +#include "c3geometry.h" +#include "c3transform.h" +#include "c3texture.h" + +#endif /* __C3_H___ */ diff --git a/examples/shared/libc3/src/c3algebra.c b/examples/shared/libc3/src/c3algebra.c new file mode 100644 index 0000000..b47525d --- /dev/null +++ b/examples/shared/libc3/src/c3algebra.c @@ -0,0 +1,1008 @@ +/* + c3algebra.c + + Copyright 2008-2012 Michel Pollet + + Derivative and inspiration from original C++: + Paul Rademacher & Jean-Francois DOUEG, + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include +#include "c3algebra.h" + +#ifndef MAX +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#define MIN(a,b) ((a)<(b) ? (a) : (b)) +#endif + +/**************************************************************** + * * + * c3vec2 Member functions * + * * + ****************************************************************/ + +/******************** c3vec2 CONSTRUCTORS ********************/ + +c3vec2 c3vec2_zero() +{ + c3vec2 n;// = { .x = 0, .y = 0 };// older gcc <4.6 doesn't like this + n.x = n.y = 0; + return n; +} + +c3vec2 c3vec2f(c3f x, c3f y) +{ + c3vec2 v;// = { .x = x, .y = y };// older gcc <4.6 doesn't like this + v.x = x; v.y = y; + return v; +} + +/******************** c3vec2 ASSIGNMENT OPERATORS ******************/ + +c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v) +{ + a.n[VX] += v.n[VX]; + a.n[VY] += v.n[VY]; + return a; +} + +c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v) +{ + a.n[VX] -= v.n[VX]; + a.n[VY] -= v.n[VY]; + return a; +} + +c3vec2 c3vec2_mulf(c3vec2 a, c3f d) +{ + a.n[VX] *= d; + a.n[VY] *= d; + return a; +} + +c3vec2 c3vec2_divf(c3vec2 a, c3f d) +{ + c3f d_inv = 1.0f/d; + a.n[VX] *= d_inv; + a.n[VY] *= d_inv; + return a; +} + +/******************** c3vec2 SPECIAL FUNCTIONS ********************/ + + +c3f c3vec2_length2(const c3vec2 a) +{ + return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY]; +} + +c3f c3vec2_length(const c3vec2 a) +{ + return (c3f) sqrt(c3vec2_length2(a)); +} + +c3vec2 c3vec2_normalize(const c3vec2 a) // it is up to caller to avoid divide-by-zero +{ + return c3vec2_divf(a, c3vec2_length(a)); +} + +c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct) +{ + a.n[VX] = fct(a.n[VX]); + a.n[VY] = fct(a.n[VY]); + return a; +} + + +/******************** c3vec2 FRIENDS *****************************/ + +c3vec2 c3vec2_minus(const c3vec2 a) +{ + return c3vec2f(-a.n[VX],-a.n[VY]); +} + +c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v) +{ + c3vec2 av; + + av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ]; + av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ]; +// av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]; + + return av; +} + +c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a) +{ + c3mat3 t = c3mat3_transpose(a); + return c3mat3_mulv2(&t, v); +} + +c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v) +{ + c3vec3 av; + + av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ]*v.n[VZ]; + av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ]*v.n[VZ]; + av.n[VZ] = a->v[2].n[VX]*v.n[VX] + a->v[2].n[VY]*v.n[VY] + a->v[2].n[VZ]*v.n[VZ]; + + return av; +} + +c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a) +{ + c3mat3 t = c3mat3_transpose(a); + return c3mat3_mulv3(&t, v); +} + +c3f c3vec2_dot(const c3vec2 a, const c3vec2 b) +{ + return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]; +} + +c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b) +{ + return c3vec3f(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); +} + +int c3vec2_equal(const c3vec2 a, const c3vec2 b) +{ + return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); +} + + +c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b) +{ + return c3vec2f(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); +} + +c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b) +{ + return c3vec2f(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); +} + +c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b) +{ + return c3vec2f(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); +} + +/**************************************************************** + * * + * c3vec3 Member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +c3vec3 c3vec3_zero() +{ + c3vec3 n;// = { .x = 0, .y = 0, .z = 0 };// older gcc <4.6 doesn't like this + n.x = n.y = n.z = 0; + return n; +} + +c3vec3 c3vec3f(c3f x, c3f y, c3f z) +{ + c3vec3 v;// = { .x = x, .y = y, .z = z };// older gcc <4.6 doesn't like this + v.x = x; v.y = y; v.z = z; + return v; +} + +c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d) +{ + c3vec3 n;// = { .x = v.x, .y = v.y, .z = d }; // older gcc <4.6 doesn't like this + n.x = v.x; n.y = v.y; n.z = d; + return n; +} + +c3vec3 c3vec3_vec2(const c3vec2 v) +{ + return c3vec3_vec2f(v, 1.0); +} + +c3vec3 c3vec3_vec4(const c3vec4 v) // it is up to caller to avoid divide-by-zero +{ + c3vec3 n; + n.n[VX] = v.n[VX] / v.n[VW]; + n.n[VY] = v.n[VY] / v.n[VW]; + n.n[VZ] = v.n[VZ] / v.n[VW]; + return n; +} + + +c3vec3 c3vec3_add(c3vec3 a, const c3vec3 v) +{ + a.n[VX] += v.n[VX]; + a.n[VY] += v.n[VY]; + a.n[VZ] += v.n[VZ]; + return a; +} + +c3vec3 c3vec3_sub(c3vec3 a, const c3vec3 v) +{ + a.n[VX] -= v.n[VX]; + a.n[VY] -= v.n[VY]; + a.n[VZ] -= v.n[VZ]; + return a; +} + +c3vec3 c3vec3_mulf(c3vec3 a, c3f d) +{ + a.n[VX] *= d; + a.n[VY] *= d; + a.n[VZ] *= d; + return a; +} + +c3vec3 c3vec3_divf(c3vec3 a, c3f d) +{ + c3f d_inv = 1.0f/d; + a.n[VX] *= d_inv; + a.n[VY] *= d_inv; + a.n[VZ] *= d_inv; + return a; +} + +// SPECIAL FUNCTIONS + +c3f c3vec3_length2(const c3vec3 a) +{ + return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ]; +} + +c3f c3vec3_length(const c3vec3 a) +{ + return (c3f) sqrt(c3vec3_length2(a)); +} + +c3vec3 c3vec3_normalize(const c3vec3 a) // it is up to caller to avoid divide-by-zero +{ + return c3vec3_divf(a, c3vec3_length(a)); +} + +c3vec3 c3vec3_homogenize(c3vec3 a) // it is up to caller to avoid divide-by-zero +{ + a.n[VX] /= a.n[VZ]; + a.n[VY] /= a.n[VZ]; + a.n[VZ] = 1.0; + return a; +} + +c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct) +{ + a.n[VX] = fct(a.n[VX]); + a.n[VY] = fct(a.n[VY]); + a.n[VZ] = fct(a.n[VZ]); + return a; +} + +// FRIENDS + +c3vec3 c3vec3_minus(const c3vec3 a) +{ + return c3vec3f(-a.n[VX],-a.n[VY],-a.n[VZ]); +} + +#if later +c3vec3 operator*(const c3mat4 &a, const c3vec3 &v) +{ + return a*c3vec4(v); +} + +c3vec3 operator*(const c3vec3 &v, c3mat4 &a) +{ + return a.transpose()*v; +} +#endif + +c3f c3vec3_dot(const c3vec3 a, const c3vec3 b) +{ + return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]; +} + +c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b) +{ + return + c3vec3f(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY], + a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ], + a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]); +} + +int c3vec3_equal(const c3vec3 a, const c3vec3 b) +{ + return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]); +} + + +c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b) +{ + return c3vec3f( + MIN(a.n[VX], b.n[VX]), + MIN(a.n[VY], b.n[VY]), + MIN(a.n[VZ], b.n[VZ])); +} + +c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b) +{ + return c3vec3f( + MAX(a.n[VX], b.n[VX]), + MAX(a.n[VY], b.n[VY]), + MAX(a.n[VZ], b.n[VZ])); +} + +c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b) +{ + return c3vec3f(a.n[VX]*b.n[VX], a.n[VY]*b.n[VY], a.n[VZ]*b.n[VZ]); +} + +/**************************************************************** + * * + * c3vec4 Member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +c3vec4 c3vec4_zero() +{ + c3vec4 n ;//= { .x = 0, .y = 0, .z = 0, .w = 1.0 }; // older gcc <4.6 doesn't like this + n.x = n.y = n.z = 0; n.w = 1.0; + return n; +} + +c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w) +{ + c3vec4 n;// = { .x = x, .y = y, .z = z, .w = w }; // older gcc <4.6 doesn't like this + n.x =x; n.y = y; n.z = z; n.w = w; + return n; +} + +c3vec4 c3vec4_vec3(const c3vec3 v) +{ + return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], 1.0); +} + +c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d) +{ + return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], d); +} + +// ASSIGNMENT OPERATORS + +c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v) +{ + a.n[VX] += v.n[VX]; + a.n[VY] += v.n[VY]; + a.n[VZ] += v.n[VZ]; + a.n[VW] += v.n[VW]; + return a; +} + +c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v) +{ + a.n[VX] -= v.n[VX]; + a.n[VY] -= v.n[VY]; + a.n[VZ] -= v.n[VZ]; + a.n[VW] -= v.n[VW]; + return a; +} + +c3vec4 c3vec4_mulf(c3vec4 a, c3f d) +{ + a.n[VX] *= d; + a.n[VY] *= d; + a.n[VZ] *= d; + a.n[VW] *= d; + return a; +} + +c3vec4 c3vec4_divf(c3vec4 a, c3f d) +{ + c3f d_inv = 1.0f/d; + a.n[VX] *= d_inv; + a.n[VY] *= d_inv; + a.n[VZ] *= d_inv; + a.n[VW] *= d_inv; + return a; +} + +// SPECIAL FUNCTIONS + +c3f c3vec4_length2(const c3vec4 a) +{ + return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ] + a.n[VW]*a.n[VW]; +} + +c3f c3vec4_length(const c3vec4 a) +{ + return (c3f) sqrt(c3vec4_length2(a)); +} + +c3vec4 c3vec4_normalize(c3vec4 a) // it is up to caller to avoid divide-by-zero +{ + return c3vec4_divf(a, c3vec4_length(a)); +} + +c3vec4 c3vec4_homogenize(c3vec4 a) // it is up to caller to avoid divide-by-zero +{ + a.n[VX] /= a.n[VW]; + a.n[VY] /= a.n[VW]; + a.n[VZ] /= a.n[VW]; + a.n[VW] = 1.0; + return a; +} + +c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct) +{ + a.n[VX] = fct(a.n[VX]); + a.n[VY] = fct(a.n[VY]); + a.n[VZ] = fct(a.n[VZ]); + a.n[VW] = fct(a.n[VW]); + return a; +} + +c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v) +{ + #define ROWCOL(i) \ + a->v[i].n[0]*v.n[VX] + \ + a->v[i].n[1]*v.n[VY] + \ + a->v[i].n[2]*v.n[VZ] + \ + a->v[i].n[3]*v.n[VW] + + return c3vec4f(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3)); + + #undef ROWCOL +} + +c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a) +{ + c3mat4 m = c3mat4_transpose(a); + return c3mat4_mulv4(&m, v); +} + +c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v) +{ + return c3vec3_vec4(c3mat4_mulv4(a, c3vec4_vec3(v))); +} + +c3vec4 c3vec4_minus(const c3vec4 a) +{ + return c3vec4f(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); +} + +int c3vec4_equal(const c3vec4 a, const c3vec4 b) +{ + return + (a.n[VX] == b.n[VX]) && + (a.n[VY] == b.n[VY]) && + (a.n[VZ] == b.n[VZ]) && + (a.n[VW] == b.n[VW]); +} + +c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b) +{ + return c3vec4f( + MIN(a.n[VX], b.n[VX]), + MIN(a.n[VY], b.n[VY]), + MIN(a.n[VZ], b.n[VZ]), + MIN(a.n[VW], b.n[VW])); +} + +c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b) +{ + return c3vec4f( + MAX(a.n[VX], b.n[VX]), + MAX(a.n[VY], b.n[VY]), + MAX(a.n[VZ], b.n[VZ]), + MAX(a.n[VW], b.n[VW])); +} + +c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b) +{ + return c3vec4f( + a.n[VX] * b.n[VX], + a.n[VY] * b.n[VY], + a.n[VZ] * b.n[VZ], + a.n[VW] * b.n[VW]); +} + +/**************************************************************** + * * + * c3mat3 member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +c3mat3 c3mat3_identity() +{ + return identity2D(); +} + +c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2) +{ + c3mat3 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2 }; + return m; +} + +c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m) +{ + a->v[0] = c3vec3_add(a->v[0], m->v[0]); + a->v[1] = c3vec3_add(a->v[1], m->v[1]); + a->v[2] = c3vec3_add(a->v[2], m->v[2]); + return a; +} + +c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m) +{ + a->v[0] = c3vec3_sub(a->v[0], m->v[0]); + a->v[1] = c3vec3_sub(a->v[1], m->v[1]); + a->v[2] = c3vec3_sub(a->v[2], m->v[2]); + return a; +} + +c3mat3p c3mat3_mulf(const c3mat3p a, c3f d) +{ + a->v[0] = c3vec3_mulf(a->v[0], d); + a->v[1] = c3vec3_mulf(a->v[1], d); + a->v[2] = c3vec3_mulf(a->v[2], d); + return a; +} + +c3mat3p c3mat3_divf(const c3mat3p a, c3f d) +{ + a->v[0] = c3vec3_divf(a->v[0], d); + a->v[1] = c3vec3_divf(a->v[1], d); + a->v[2] = c3vec3_divf(a->v[2], d); + return a; +} + +// SPECIAL FUNCTIONS + +c3mat3 c3mat3_transpose(const c3mat3p a) +{ + return c3mat3_vec3( + c3vec3f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0]), + c3vec3f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1]), + c3vec3f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2])); +} + +c3mat3 c3mat3_inverse(const c3mat3p m) // Gauss-Jordan elimination with partial pivoting +{ + c3mat3 a = *m; // As a evolves from original mat into identity + c3mat3 b = c3mat3_identity(); // b evolves from identity into inverse(a) + int i, j, i1; + + // Loop over cols of a from left to right, eliminating above and below diag + for (j = 0; j < 3; j++) { // Find largest pivot in column j among rows j..2 + i1 = j; // Row with largest pivot candidate + for (i = j + 1; i < 3; i++) + if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) + i1 = i; + + // Swap rows i1 and j in a and b to put pivot on diagonal + c3vec3 _s; + _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]); + _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; //swap(b.v[i1], b.v[j]); + + // Scale row j to have a unit diagonal + if (a.v[j].n[j] == 0.) { + // VEC_ERROR("c3mat3::inverse: singular matrix; can't invert\n"); + return *m; + } + + b.v[j] = c3vec3_divf(b.v[j], a.v[j].n[j]); + a.v[j] = c3vec3_divf(a.v[j], a.v[j].n[j]); + + // Eliminate off-diagonal elems in col j of a, doing identical ops to b + for (i = 0; i < 3; i++) + if (i != j) { + b.v[i] = c3vec3_sub(b.v[i], c3vec3_mulf(b.v[j], a.v[i].n[j])); + a.v[i] = c3vec3_sub(a.v[i], c3vec3_mulf(a.v[j], a.v[i].n[j])); + } + } + + return b; +} + +c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct) +{ + a->v[0] = c3vec3_apply(a->v[0], fct); + a->v[1] = c3vec3_apply(a->v[1], fct); + a->v[2] = c3vec3_apply(a->v[2], fct); + return a; +} + + +c3mat3 c3mat3_minus(const c3mat3p a) +{ + return c3mat3_vec3( + c3vec3_minus(a->v[0]), + c3vec3_minus(a->v[1]), + c3vec3_minus(a->v[2])); +} + +c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b) +{ + #define ROWCOL(i, j) \ + a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j] + + return c3mat3_vec3( + c3vec3f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)), + c3vec3f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)), + c3vec3f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2))); + + #undef ROWCOL +} + +int c3mat3_equal(const c3mat3p a, const c3mat3p b) +{ + return + c3vec3_equal(a->v[0], b->v[0]) && + c3vec3_equal(a->v[1], b->v[1]) && + c3vec3_equal(a->v[2], b->v[2]); +} + +/**************************************************************** + * * + * c3mat4 member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +c3mat4 c3mat4_identity() +{ + return identity3D(); +} + +c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3) +{ + c3mat4 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2, .v[3] = v3 }; + return m; +} + +c3mat4 c3mat4f( + c3f a00, c3f a01, c3f a02, c3f a03, + c3f a10, c3f a11, c3f a12, c3f a13, + c3f a20, c3f a21, c3f a22, c3f a23, + c3f a30, c3f a31, c3f a32, c3f a33 ) +{ + c3mat4 m; + m.v[0] = c3vec4f(a00, a01, a01, a03); + m.v[1] = c3vec4f(a10, a11, a11, a13); + m.v[2] = c3vec4f(a20, a21, a21, a23); + m.v[3] = c3vec4f(a30, a31, a21, a33); + return m; +} + +c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m) +{ + a->v[0] = c3vec4_add(a->v[0], m->v[0]); + a->v[1] = c3vec4_add(a->v[1], m->v[1]); + a->v[2] = c3vec4_add(a->v[2], m->v[2]); + a->v[3] = c3vec4_add(a->v[3], m->v[3]); + return a; +} + +c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m) +{ + a->v[0] = c3vec4_sub(a->v[0], m->v[0]); + a->v[1] = c3vec4_sub(a->v[1], m->v[1]); + a->v[2] = c3vec4_sub(a->v[2], m->v[2]); + a->v[3] = c3vec4_sub(a->v[3], m->v[3]); + return a; +} + +c3mat4p c3mat4p_mulf(c3mat4p a, c3f d) +{ + a->v[0] = c3vec4_mulf(a->v[0], d); + a->v[1] = c3vec4_mulf(a->v[1], d); + a->v[2] = c3vec4_mulf(a->v[2], d); + a->v[3] = c3vec4_mulf(a->v[3], d); + return a; +} + +c3mat4p c3mat4p_divf(c3mat4p a, c3f d) +{ + a->v[0] = c3vec4_divf(a->v[0], d); + a->v[1] = c3vec4_divf(a->v[1], d); + a->v[2] = c3vec4_divf(a->v[2], d); + a->v[3] = c3vec4_divf(a->v[3], d); + return a; +} + +// SPECIAL FUNCTIONS; + +c3mat4 c3mat4_transpose(const c3mat4p a) +{ + return c3mat4_vec4( + c3vec4f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0], a->v[3].n[0]), + c3vec4f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1], a->v[3].n[1]), + c3vec4f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2], a->v[3].n[2]), + c3vec4f(a->v[0].n[3], a->v[1].n[3], a->v[2].n[3], a->v[3].n[3])); +} + +c3mat4 c3mat4_inverse(const c3mat4p m) // Gauss-Jordan elimination with partial pivoting +{ + c3mat4 a = *m; // As a evolves from original mat into identity + c3mat4 b = identity3D(); // b evolves from identity into inverse(a) + int i, j, i1; + + // Loop over cols of a from left to right, eliminating above and below diag + for (j = 0; j < 4; j++) { // Find largest pivot in column j among rows j..3 + i1 = j; // Row with largest pivot candidate + for (i = j + 1; i < 4; i++) + if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) + i1 = i; + + // Swap rows i1 and j in a and b to put pivot on diagonal + c3vec4 _s; + _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]); + _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; // swap(b.v[i1], b.v[j]); + + // Scale row j to have a unit diagonal + if (a.v[j].n[j] == 0.) { + // VEC_ERROR("c3mat4::inverse: singular matrix; can't invert\n"); + return a; + } + b.v[j] = c3vec4_divf(b.v[j], a.v[j].n[j]); + a.v[j] = c3vec4_divf(a.v[j], a.v[j].n[j]); + + // Eliminate off-diagonal elems in col j of a, doing identical ops to b + for (i = 0; i < 4; i++) + if (i != j) { + b.v[i] = c3vec4_sub(b.v[i], c3vec4_mulf(b.v[j], a.v[i].n[j])); + a.v[i] = c3vec4_sub(a.v[i], c3vec4_mulf(a.v[j], a.v[i].n[j])); + } + } + + return b; +} + +c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct) +{ + a->v[0] = c3vec4_apply(a->v[0], fct); + a->v[1] = c3vec4_apply(a->v[1], fct); + a->v[2] = c3vec4_apply(a->v[2], fct); + a->v[3] = c3vec4_apply(a->v[3], fct); + return a; +} + +c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j) +{ + c3vec4 t; + + t = a->v[i]; + a->v[i] = a->v[j]; + a->v[j] = t; + return a; +} + +c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j) +{ + c3f t; + + for (int k = 0; k < 4; k++) { + t = a->v[k].n[i]; + a->v[k].n[i] = a->v[k].n[j]; + a->v[k].n[j] = t; + } + return a; +} + + +// FRIENDS + +c3mat4 c3mat4_minus(const c3mat4p a) +{ + return c3mat4_vec4( + c3vec4_minus(a->v[0]), + c3vec4_minus(a->v[1]), + c3vec4_minus(a->v[2]), + c3vec4_minus(a->v[3])); +} + +c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b) +{ + return c3mat4_vec4( + c3vec4_add(a->v[0], b->v[0]), + c3vec4_add(a->v[1], b->v[1]), + c3vec4_add(a->v[2], b->v[2]), + c3vec4_add(a->v[3], b->v[3])); +} + +c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b) +{ + return c3mat4_vec4( + c3vec4_sub(a->v[0], b->v[0]), + c3vec4_sub(a->v[1], b->v[1]), + c3vec4_sub(a->v[2], b->v[2]), + c3vec4_sub(a->v[3], b->v[3])); +} + +c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b) +{ + #define ROWCOL(i, j) \ + a->v[i].n[0]*b->v[0].n[j] + \ + a->v[i].n[1]*b->v[1].n[j] + \ + a->v[i].n[2]*b->v[2].n[j] + \ + a->v[i].n[3]*b->v[3].n[j] + + return c3mat4_vec4( + c3vec4f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)), + c3vec4f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)), + c3vec4f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)), + c3vec4f(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3)) + ); + + #undef ROWCOL +} + +c3mat4 c3mat4_mulf(const c3mat4p a, c3f d) +{ + c3mat4 r = *a; + return *c3mat4p_mulf(&r, d); +} + +c3mat4 c3mat4_divf(const c3mat4p a, c3f d) +{ + c3mat4 r = *a; + return *c3mat4p_divf(&r, d); +} + +int c3mat4_equal(const c3mat4p a, const c3mat4p b) +{ + return !memcmp(a->n, b->n, sizeof(a->n)); +#if 0 + return + c3vec4_equal(a->v[0], b->v[0]) && + c3vec4_equal(a->v[1], b->v[1]) && + c3vec4_equal(a->v[2], b->v[2]) && + c3vec4_equal(a->v[3], b->v[3]); +#endif +} + +/**************************************************************** + * * + * 2D functions and 3D functions * + * * + ****************************************************************/ + +c3mat3 identity2D() +{ + return c3mat3_vec3( + c3vec3f(1.0, 0.0, 0.0), + c3vec3f(0.0, 1.0, 0.0), + c3vec3f(0.0, 0.0, 1.0)); +} + +c3mat3 translation2D(const c3vec2 v) +{ + return c3mat3_vec3( + c3vec3f(1.0, 0.0, v.n[VX]), + c3vec3f(0.0, 1.0, v.n[VY]), + c3vec3f(0.0, 0.0, 1.0)); +} + +c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg) +{ + c3f angleRad = (c3f) (angleDeg * M_PI / 180.0); + c3f c = (c3f) cos(angleRad); + c3f s = (c3f) sin(angleRad); + + return c3mat3_vec3( + c3vec3f(c, -s, Center.n[VX] * (1.0f-c) + Center.n[VY] * s), + c3vec3f(s, c, Center.n[VY] * (1.0f-c) - Center.n[VX] * s), + c3vec3f(0.0, 0.0, 1.0)); +} + +c3mat3 scaling2D(const c3vec2 scaleVector) +{ + return c3mat3_vec3( + c3vec3f(scaleVector.n[VX], 0.0, 0.0), + c3vec3f(0.0, scaleVector.n[VY], 0.0), + c3vec3f(0.0, 0.0, 1.0)); +} + +c3mat4 identity3D() +{ + return c3mat4_vec4( + c3vec4f(1.0, 0.0, 0.0, 0.0), + c3vec4f(0.0, 1.0, 0.0, 0.0), + c3vec4f(0.0, 0.0, 1.0, 0.0), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} + +c3mat4 translation3D(const c3vec3 v) +{ + return c3mat4_vec4( + c3vec4f(1.0, 0.0, 0.0, v.n[VX]), + c3vec4f(0.0, 1.0, 0.0, v.n[VY]), + c3vec4f(0.0, 0.0, 1.0, v.n[VZ]), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} + +c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg) +{ + c3f angleRad = (c3f) (angleDeg * M_PI / 180.0); + c3f c = (c3f) cos(angleRad); + c3f s = (c3f) sin(angleRad); + c3f t = 1.0f - c; + + c3vec3 axis = c3vec3_normalize(Axis); + + return c3mat4_vec4( + c3vec4f(t * axis.n[VX] * axis.n[VX] + c, + t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ], + t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY], + 0.0), + c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ], + t * axis.n[VY] * axis.n[VY] + c, + t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX], + 0.0), + c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY], + t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX], + t * axis.n[VZ] * axis.n[VZ] + c, + 0.0), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} + +c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad) +{ + c3f c = (c3f) cos(angleRad); + c3f s = (c3f) sin(angleRad); + c3f t = 1.0f - c; + + c3vec3 axis = c3vec3_normalize(Axis); + + return c3mat4_vec4( + c3vec4f(t * axis.n[VX] * axis.n[VX] + c, + t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ], + t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY], + 0.0), + c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ], + t * axis.n[VY] * axis.n[VY] + c, + t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX], + 0.0), + c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY], + t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX], + t * axis.n[VZ] * axis.n[VZ] + c, + 0.0), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} + +c3mat4 scaling3D(const c3vec3 scaleVector) +{ + return c3mat4_vec4( + c3vec4f(scaleVector.n[VX], 0.0, 0.0, 0.0), + c3vec4f(0.0, scaleVector.n[VY], 0.0, 0.0), + c3vec4f(0.0, 0.0, scaleVector.n[VZ], 0.0), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} + +c3mat4 perspective3D(c3f d) +{ + return c3mat4_vec4( + c3vec4f(1.0f, 0.0f, 0.0f, 0.0f), + c3vec4f(0.0f, 1.0f, 0.0f, 0.0f), + c3vec4f(0.0f, 0.0f, 1.0f, 0.0f), + c3vec4f(0.0f, 0.0f, 1.0f/d, 0.0f)); +} + diff --git a/examples/shared/libc3/src/c3algebra.h b/examples/shared/libc3/src/c3algebra.h new file mode 100644 index 0000000..d2b71a1 --- /dev/null +++ b/examples/shared/libc3/src/c3algebra.h @@ -0,0 +1,214 @@ +/* + c3algebra.h + + Copyright 2008-2012 Michel Pollet + + Derivative and inspiration from original C++: + Paul Rademacher & Jean-Francois DOUEG, + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3ALGEBRA_H___ +#define __C3ALGEBRA_H___ + + +#ifndef M_PI +#define M_PI 3.141592654 +#endif + +enum {VX, VY, VZ, VW}; // axes +enum {PA, PB, PC, PD}; // planes +enum {RED, GREEN, BLUE, ALPHA}; // colors +enum {KA, KD, KS, ES}; // phong coefficients + +typedef float c3f; +typedef c3f (*V_FCT_PTR)(c3f); + +typedef union c3vec2 { + struct { c3f x,y; }; + c3f n[2]; +} c3vec2; + +typedef union c3vec3 { + struct { c3f x,y,z; }; + c3f n[3]; +} c3vec3; + +typedef union c3vec4 { + struct { c3f x,y,z,w; }; + c3f n[4]; +} c3vec4, * c3vec4p; + +typedef union c3mat3 { + c3vec3 v[3]; + c3f n[3*3]; +} c3mat3, * c3mat3p; + +typedef union c3mat4 { + c3vec4 v[4]; + c3f n[4*4]; +} c3mat4, * c3mat4p; + +/* + * c3vec2 related + */ + +c3vec2 c3vec2_zero(); +c3vec2 c3vec2f(c3f x, c3f y); + +c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v); +c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v); +c3vec2 c3vec2_mulf(c3vec2 a, c3f d); +c3vec2 c3vec2_divf(c3vec2 a, c3f d); + +c3f c3vec2_length2(const c3vec2 a); +c3f c3vec2_length(const c3vec2 a); +c3vec2 c3vec2_normalize(const c3vec2 a); // it is up to caller to avoid divide-by-zero +c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct); +c3vec2 c3vec2_minus(const c3vec2 a); +c3f c3vec2_dot(const c3vec2 a, const c3vec2 b); +c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b); +c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b); +c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b); + +/* + * c3vec4 related + */ + +c3vec3 c3vec3_zero(); +c3vec3 c3vec3f(c3f x, c3f y, c3f z); +c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d); +c3vec3 c3vec3_vec2(const c3vec2 v); +c3vec3 c3vec3_vec4(const c3vec4 v); // it is up to caller to avoid divide-by-zero + +c3vec3 c3vec3_add(const c3vec3 a, const c3vec3 v); +c3vec3 c3vec3_sub(const c3vec3 a, const c3vec3 v); +c3vec3 c3vec3_mulf(const c3vec3 a, c3f d); +c3vec3 c3vec3_divf(const c3vec3 a, c3f d); + +c3f c3vec3_length2(const c3vec3 a); +c3f c3vec3_length(const c3vec3 a); +c3vec3 c3vec3_normalize(const c3vec3 a); // it is up to caller to avoid divide-by-zero +c3vec3 c3vec3_homogenize(c3vec3 a); // it is up to caller to avoid divide-by-zero +c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct); +c3vec3 c3vec3_minus(const c3vec3 a); +c3f c3vec3_dot(const c3vec3 a, const c3vec3 b); +int c3vec3_equal(const c3vec3 a, const c3vec3 b); +c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b); +c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b); +c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b); + +c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b); +c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b); + +/* + * c3vec4 related + */ + +c3vec4 c3vec4_zero(); +c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w); +c3vec4 c3vec4_vec3(const c3vec3 v); +c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d); + +c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v); +c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v); +c3vec4 c3vec4_mulf(c3vec4 a, c3f d); +c3vec4 c3vec4_divf(c3vec4 a, c3f d); + +c3f c3vec4_length2(const c3vec4 a); +c3f c3vec4_length(const c3vec4 a); +c3vec4 c3vec4_normalize(c3vec4 a); // it is up to caller to avoid divide-by-zero +c3vec4 c3vec4_homogenize(c3vec4 a); // it is up to caller to avoid divide-by-zero +c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct); +c3vec4 c3vec4_minus(const c3vec4 a); +int c3vec4_equal(const c3vec4 a, const c3vec4 b); +c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b); +c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b); +c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b); + +/* + * c3mat3 related + */ + +c3mat3 c3mat3_identity(); +c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2); +c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m); +c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m); +c3mat3p c3mat3_mulf(const c3mat3p a, c3f d); +c3mat3p c3mat3_divf(const c3mat3p a, c3f d); + +c3mat3 c3mat3_transpose(const c3mat3p a); +c3mat3 c3mat3_inverse(const c3mat3p m); // Gauss-Jordan elimination with partial pivoting +c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct); +c3mat3 c3mat3_minus(const c3mat3p a); + +c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b); +int c3mat3_equal(const c3mat3p a, const c3mat3p b); + +c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v); +c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v); +c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a); +c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a); + +c3mat3 identity2D(); +c3mat3 translation2D(const c3vec2 v); +c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg); +c3mat3 scaling2D(const c3vec2 scaleVector); + +/* + * c3mat4 related + */ + +c3mat4 c3mat4_identity(); +c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3); +c3mat4 c3mat4f( + c3f a00, c3f a01, c3f a02, c3f a03, + c3f a10, c3f a11, c3f a12, c3f a13, + c3f a20, c3f a21, c3f a22, c3f a23, + c3f a30, c3f a31, c3f a32, c3f a33 ); + +c3mat4 c3mat4_minus(const c3mat4p a); +c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m); +c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b); +c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m); +c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b); +c3mat4p c3mat4p_mulf(c3mat4p a, c3f d); +c3mat4 c3mat4_mulf(const c3mat4p a, c3f d); +c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b); +c3mat4p c3mat4p_divf(c3mat4p a, c3f d); +c3mat4 c3mat4_divf(const c3mat4p a, c3f d); + +c3mat4 c3mat4_transpose(const c3mat4p a); +c3mat4 c3mat4_inverse(const c3mat4p m); // Gauss-Jordan elimination with partial pivoting +c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct); +c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j); +c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j); +int c3mat4_equal(const c3mat4p a, const c3mat4p b); + +c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a); +c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v); +c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v); + +c3mat4 identity3D(); +c3mat4 translation3D(const c3vec3 v); +c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg); +c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad); +c3mat4 scaling3D(const c3vec3 scaleVector); +c3mat4 perspective3D(c3f d); + +#endif /* __C3ALGEBRA_H___ */ diff --git a/examples/shared/libc3/src/c3arcball.c b/examples/shared/libc3/src/c3arcball.c new file mode 100644 index 0000000..f801651 --- /dev/null +++ b/examples/shared/libc3/src/c3arcball.c @@ -0,0 +1,254 @@ +/* + c3arcball.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include "c3arcball.h" + + +/**************************************** c3arcball_init_mat4() ****/ +/* Takes as argument a c3mat4 to use instead of the internal rot */ + +void +c3arcball_init_mat4( + c3arcballp a, + c3mat4p mtx ) +{ + c3arcball_init(a); + a->rot_ptr = mtx; +} + + +/**************************************** c3arcball_init_center() ****/ +/* A constructor that accepts the screen center and arcball radius*/ + +void +c3arcball_init_center( + c3arcballp a, + const c3vec2 center, + c3f radius ) +{ + c3arcball_init(a); + c3arcball_set_params(a, center, radius); +} + + +/************************************** c3arcball_set_params() ****/ + +void +c3arcball_set_params( + c3arcballp a, + const c3vec2 center, + c3f radius) +{ + a->center = center; + a->radius = radius; +} + +/*************************************** c3arcball_init() **********/ + +void +c3arcball_init( + c3arcballp a ) +{ + a->center = c3vec2f( 0.0, 0.0 ); + a->radius = 1.0; + a->q_now = c3quat_identity(); + a->rot_ptr = &a->rot; + a->rot = identity3D(); + a->q_increment = c3quat_identity(); + a->rot_increment = identity3D(); + a->is_mouse_down = false; + a->is_spinning = false; + a->damp_factor = 0.0; + a->zero_increment = true; +} + +/*********************************** c3arcball_mouse_to_sphere() ****/ + +c3vec3 +c3arcball_mouse_to_sphere( + c3arcballp a, + const c3vec2 p) +{ + c3f mag; + c3vec2 v2 = c3vec2_divf(c3vec2_sub(p, a->center), a->radius); + c3vec3 v3 = c3vec3f( v2.n[0], v2.n[1], 0.0 ); + + mag = c3vec2_dot(v2, v2); + + if ( mag > 1.0 ) + v3 = c3vec3_normalize(v3); + else + v3.n[VZ] = (c3f) sqrt( 1.0 - mag ); + + /* Now we add constraints - X takes precedence over Y */ + if ( a->constraint_x ) { + v3 = c3arcball_constrain_vector( v3, c3vec3f( 1.0, 0.0, 0.0 )); + } else if ( a->constraint_y ) { + v3 = c3arcball_constrain_vector( v3, c3vec3f( 0.0, 1.0, 0.0 )); + } + + return v3; +} + + +/************************************ c3arcball_constrain_vector() ****/ + +c3vec3 +c3arcball_constrain_vector( + const c3vec3 vector, + const c3vec3 axis) +{ +// return (vector - (vector * axis) * axis).normalize(); + return vector; +} + +/************************************ c3arcball_mouse_down() **********/ + +void +c3arcball_mouse_down( + c3arcballp a, + int x, + int y) +{ + a->down_pt = c3vec2f( (c3f)x, (c3f) y ); + a->is_mouse_down = true; + + a->q_increment = c3quat_identity(); + a->rot_increment = identity3D(); + a->zero_increment = true; +} + + +/************************************ c3arcball_mouse_up() **********/ + +void +c3arcball_mouse_up( + c3arcballp a) +{ + a->q_now = c3quat_mul(a->q_drag, a->q_now); + a->is_mouse_down = false; +} + + +/********************************** c3arcball_mouse_motion() **********/ + +void +c3arcball_mouse_motion( + c3arcballp a, + int x, + int y, + int shift, + int ctrl, + int alt) +{ + /* Set the X constraint if CONTROL key is pressed, Y if ALT key */ + c3arcball_set_constraints(a, ctrl != 0, alt != 0 ); + + c3vec2 new_pt = c3vec2f( (c3f)x, (c3f) y ); + c3vec3 v0 = c3arcball_mouse_to_sphere(a, a->down_pt ); + c3vec3 v1 = c3arcball_mouse_to_sphere(a, new_pt ); + + c3vec3 cross = c3vec3_cross(v0, v1); + + a->q_drag = c3quat_vec3(cross, c3vec3_dot(v0, v1)); + + // *rot_ptr = (q_drag * q_now).to_mat4(); + c3mat4 temp = c3quat_to_mat4(a->q_drag); + *a->rot_ptr = c3mat4_mul(a->rot_ptr, &temp); + + a->down_pt = new_pt; + + /* We keep a copy of the current incremental rotation (= q_drag) */ + a->q_increment = a->q_drag; + a->rot_increment = c3quat_to_mat4(a->q_increment); + + c3arcball_set_constraints(a, false, false); + + if (a->q_increment.s < .999999) { + a->is_spinning = true; + a->zero_increment = false; + } else { + a->is_spinning = false; + a->zero_increment = true; + } +} + + +/********************************** c3arcball_mouse_motion() **********/ +#if 0 +void +c3arcball_mouse_motion( + c3arcballp a, + int x, + int y) +{ + mouse_motion(x, y, 0, 0, 0); +} +#endif + +/***************************** c3arcball_set_constraints() **********/ + +void +c3arcball_set_constraints( + c3arcballp a, + bool _constraint_x, + bool _constraint_y) +{ + a->constraint_x = _constraint_x; + a->constraint_y = _constraint_y; +} + +/***************************** c3arcball_idle() *********************/ + +void +c3arcball_idle( + c3arcballp a) +{ + if (a->is_mouse_down) { + a->is_spinning = false; + a->zero_increment = true; + } + + if (a->damp_factor < 1.0f) + c3quat_scale_angle(&a->q_increment, 1.0f - a->damp_factor); + + a->rot_increment = c3quat_to_mat4(a->q_increment); + + if (a->q_increment.s >= .999999f) { + a->is_spinning = false; + a->zero_increment = true; + } +} + + +/************************ c3arcball_set_damping() *********************/ + +void +c3arcball_set_damping( + c3arcballp a, + c3f d) +{ + a->damp_factor = d; +} + + + diff --git a/examples/shared/libc3/src/c3arcball.h b/examples/shared/libc3/src/c3arcball.h new file mode 100644 index 0000000..d61c815 --- /dev/null +++ b/examples/shared/libc3/src/c3arcball.h @@ -0,0 +1,125 @@ +/* + c3arcball.h + + Copyright 2008-2012 Michel Pollet + Copyright (c) 1998 Paul Rademacher + Feb 1998, Paul Rademacher (rademach@cs.unc.edu) + Oct 2003, Nigel Stewart - GLUI Code Cleaning + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +/* + Arcball, as described by Ken + Shoemake in Graphics Gems IV. + This class takes as input mouse events (mouse down, mouse drag, + mouse up), and creates the appropriate quaternions and 4x4 matrices + to represent the rotation given by the mouse. + + This class is used as follows: + - initialize [either in the constructor or with set_params()], the + center position (x,y) of the arcball on the screen, and the radius + - on mouse down, call mouse_down(x,y) with the mouse position + - as the mouse is dragged, repeatedly call mouse_motion() with the + current x and y positions. One can optionally pass in the current + state of the SHIFT, ALT, and CONTROL keys (passing zero if keys + are not pressed, non-zero otherwise), which constrains + the rotation to certain axes (X for CONTROL, Y for ALT). + - when the mouse button is released, call mouse_up() + + Axis constraints can also be explicitly set with the + set_constraints() function. + + The current rotation is stored in the 4x4 float matrix 'rot'. + It is also stored in the quaternion 'q_now'. + */ + +#ifndef __C3ARCBALL_H___ +#define __C3ARCBALL_H___ + +#include "c3quaternion.h" + +typedef struct c3arcball { + int is_mouse_down : 1, /* true for down, false for up */ + is_spinning : 1, + constraint_x : 1, + constraint_y : 1, + zero_increment : 1; + c3quat q_now, q_down, q_drag, q_increment; + c3vec2 down_pt; + c3mat4 rot, rot_increment; + c3mat4 *rot_ptr; + + c3vec2 center; + c3f radius, damp_factor; +} c3arcball, *c3arcballp; + +void +c3arcball_init( + c3arcballp a ); +void +c3arcball_init_mat4( + c3arcballp a, + c3mat4p mtx ); +void +c3arcball_init_center( + c3arcballp a, + const c3vec2 center, + c3f radius ); +void +c3arcball_set_params( + c3arcballp a, + const c3vec2 center, + c3f radius); +c3vec3 +c3arcball_mouse_to_sphere( + c3arcballp a, + const c3vec2 p); +c3vec3 +c3arcball_constrain_vector( + const c3vec3 vector, + const c3vec3 axis); +void +c3arcball_mouse_down( + c3arcballp a, + int x, + int y); +void +c3arcball_mouse_up( + c3arcballp a); + +void +c3arcball_mouse_motion( + c3arcballp a, + int x, + int y, + int shift, + int ctrl, + int alt); +void +c3arcball_set_constraints( + c3arcballp a, + bool _constraint_x, + bool _constraint_y); +void +c3arcball_idle( + c3arcballp a); +void +c3arcball_set_damping( + c3arcballp a, + c3f d); + +#endif /* __C3ARCBALL_H___ */ diff --git a/examples/shared/libc3/src/c3cairo.c b/examples/shared/libc3/src/c3cairo.c new file mode 100644 index 0000000..390a5c3 --- /dev/null +++ b/examples/shared/libc3/src/c3cairo.c @@ -0,0 +1,105 @@ +/* + c3cairo.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3cairo.h" +#include "c3driver_geometry.h" + +#if CONFIG_C3_CAIRO + +void +_c3cairo_dispose( + c3geometry_p g, + const c3driver_geometry_t * d) +{ + c3cairo_p c = (c3cairo_p)g; + + if (c->cr) + cairo_destroy(c->cr); + if (c->surface) + cairo_surface_destroy(c->surface); + C3_DRIVER_INHERITED(g, d, dispose); +} + +static void +_c3cairo_project( + c3geometry_p g, + const struct c3driver_geometry_t *d, + c3mat4p m) +{ + C3_DRIVER_INHERITED(g, d, project, m); +} + +const c3driver_geometry_t c3cairo_base_driver = { + .dispose = _c3cairo_dispose, + .project = _c3cairo_project, +}; +const c3driver_geometry_t c3texture_driver; +const c3driver_geometry_t c3geometry_driver; + +c3cairo_p +c3cairo_new( + struct c3object_t * parent) +{ + c3cairo_p res = malloc(sizeof(*res)); + return c3cairo_init(res, parent); +} + +c3cairo_p +c3cairo_init( + c3cairo_p o, + struct c3object_t * parent) +{ + memset(o, 0, sizeof(*o)); + c3texture_init(&o->tex, parent); + + static const c3driver_geometry_t * list[] = { + &c3cairo_base_driver, &c3texture_driver, &c3geometry_driver, NULL, + }; + ((c3geometry_p)o)->driver = list; + + return o; +} + +c3cairo_p +c3cairo_new_offscreen( + struct c3object_t * parent, + int w, int h) +{ + c3cairo_p o = c3cairo_new(parent); + + o->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + o->cr = cairo_create(o->surface); + + c3pixels_p dst = c3pixels_new(w, h, 4, + cairo_image_surface_get_stride(o->surface), + cairo_image_surface_get_data(o->surface)); + o->tex.geometry.mat.texture = dst; + + return o; +} + +#if 0 +cairo_surface_destroy(_surface); +else +cairo_surface_finish(_surface); +#endif +#endif // CONFIG_C3_CAIRO diff --git a/examples/shared/libc3/src/c3cairo.h b/examples/shared/libc3/src/c3cairo.h new file mode 100644 index 0000000..75d64b6 --- /dev/null +++ b/examples/shared/libc3/src/c3cairo.h @@ -0,0 +1,55 @@ +/* + c3cairo.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3CAIRO_H___ +#define __C3CAIRO_H___ + +#include "c3config.h" +#include "c3texture.h" +#include "c3pixels.h" + +#if CONFIG_C3_CAIRO +#include + +typedef struct c3cairo_t { + c3texture_t tex; + cairo_t * cr; + cairo_surface_t * surface; +} c3cairo_t, *c3cairo_p; + +c3cairo_p +c3cairo_new( + struct c3object_t * parent /* = NULL */); + +c3cairo_p +c3cairo_init( + c3cairo_p o, + struct c3object_t * parent /* = NULL */); + +c3cairo_p +c3cairo_new_offscreen( + struct c3object_t * parent /* = NULL */, + int w, int h); + +#endif // CONFIG_C3_CAIRO + +#endif /* __C3CAIRO_H___ */ diff --git a/examples/shared/libc3/src/c3camera.c b/examples/shared/libc3/src/c3camera.c new file mode 100644 index 0000000..8e5fef1 --- /dev/null +++ b/examples/shared/libc3/src/c3camera.c @@ -0,0 +1,403 @@ +/* + c3camera.c + + Copyright 2008-2012 Michel Pollet + Copyright (c) 1998 Paul Rademacher + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3camera.h" + + +void +c3cam_set_distance( + c3camp c, + const c3f new_distance) +{ + if ( new_distance <= 0.0 ) /* Distance has to be positive */ + return; + + /* We find the current forward vector */ +// forward = lookat - eye; + c->forward = c3vec3_normalize(c3vec3_sub(c->lookat, c->eye)); + + /* Set distance */ + c->distance = new_distance; + + /* Find new eye point */ + c->eye = c3vec3_sub(c->lookat, c3vec3_mulf(c->forward, c->distance)); + c3cam_update(c); +} + +void +c3cam_set_upv( + c3camp c, + const c3vec3 new_up) +{ + c->up = new_up; + c3cam_update(c); +} + +void +c3cam_set_upf( + c3camp c, + const c3f x, + const c3f y, + const c3f z) +{ + c3cam_set_upv(c, c3vec3f(x,y,z)); +} + +void +c3cam_set_eyev( + c3camp c, + const c3vec3 new_eye) +{ + c->eye = new_eye; + c3cam_update(c); +} + +void +c3cam_set_eyef( + c3camp c, + const c3f x, + const c3f y, + const c3f z) +{ + c3cam_set_eyev(c, c3vec3f(x,y,z)); +} + +void +c3cam_set_lookatv( + c3camp c, + const c3vec3 new_lookat) +{ + c->lookat = new_lookat; + c3cam_update(c); +} + +void +c3cam_set_lookatf( + c3camp c, + const c3f x, + const c3f y, + const c3f z) +{ + c3cam_set_lookatv(c, c3vec3f(x,y,z)); +} + + +void +c3cam_roll( + c3camp c, + const c3f angle) +{ + c3mat4 rot = rotation3D(c->forward, angle ); + c->up = c3mat4_mulv3(&rot, c->up); + c3cam_update(c); +} + +void +c3cam_eye_yaw( + c3camp c, + const c3f angle) +{ + c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ + c3mat4 rot = rotation3D( c->up, angle ); + + eye_pt = c3mat4_mulv3(&rot, eye_pt); + c->eye = c3vec3_add(c->lookat, eye_pt); + + c3cam_update(c); +} + +void +c3cam_eye_yaw_abs( + c3camp c, + const c3f angle, + const c3vec3 axis) +{ + c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ + c3mat4 rot = rotation3D( axis, angle ); + + eye_pt = c3mat4_mulv3(&rot, eye_pt); + c->eye = c3vec3_add(c->lookat, eye_pt); + + c->up = c3mat4_mulv3(&rot, c->up); + + c3cam_update(c); +} + + +void +c3cam_eye_pitch( + c3camp c, + const c3f angle) +{ + c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ + c3mat4 rot = rotation3D( c->side, angle ); + + eye_pt = c3mat4_mulv3(&rot, eye_pt); + c->eye = c3vec3_add(c->lookat, eye_pt); + + c->up = c3mat4_mulv3(&rot, c->up); + + c3cam_update(c); +} + +void +c3cam_lookat_yaw( + c3camp c, + const c3f angle) +{ + c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ + c3mat4 rot = rotation3D( c->up, -angle ); + + lookat_pt = c3mat4_mulv3(&rot, lookat_pt); + c->lookat = c3vec3_add(c->eye, lookat_pt); + + c3cam_update(c); +} + +void +c3cam_lookat_pitch( + c3camp c, + const c3f angle) +{ + c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ + c3mat4 rot = rotation3D( c->side, -angle ); + + lookat_pt = c3mat4_mulv3(&rot, lookat_pt); + c->lookat = c3vec3_add(c->eye, lookat_pt); + + c->up = c3mat4_mulv3(&rot, c->up); + + c3cam_update(c); +} + +void +c3cam_reset_up_axis( + c3camp c, + const int axis_num) +{ + c3vec3 eye_pt = c3vec3_sub(c->lookat, c->eye); /* eye w/lookat at center */ + c3f eye_distance = c3vec3_length(eye_pt); + c->eye.n[axis_num] = c->lookat.n[axis_num]; + /* Bring eye to same level as lookat */ + + c3vec3 vector = c3vec3_sub(c->eye, c->lookat); + vector = c3vec3_normalize(vector); + vector = c3vec3_mulf(vector, eye_distance); + + c->eye = c3vec3_add(c->lookat, vector); + c->up = c3vec3f( 0.0, 0.0, 0.0 ); + c->up.n[axis_num] = 1.0; + + c3cam_update(c); +} + +void +c3cam_reset_up( + c3camp c) +{ + c3cam_reset_up_axis(c, VY ); /* Resets to the Y axis */ +} + +void +c3cam_movef( + c3camp c, + const c3f side_move, + const c3f up_move, + const c3f forw_move) +{ + c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->forward, forw_move)); + c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->side, side_move)); + c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->up, up_move)); + c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->forward, forw_move)); + c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->side, side_move)); + c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->up, up_move)); + c3cam_update(c); +} + +void +c3cam_movev( + c3camp c, + const c3vec3 v) /* A vector version of the above command */ +{ + c3cam_movef(c, v.n[VX], v.n[VY], v.n[VZ] ); +} + +void +c3cam_move_by_eye( + c3camp c, + const c3vec3 new_eye) +{ + c3vec3 diff = c3vec3_sub(new_eye, c->eye); + + c->lookat = c3vec3_add(c->lookat, diff); + c->eye = c3vec3_add(c->eye, diff); + + c3cam_update(c); +} + +void +c3cam_move_by_lookat( + c3camp c, + const c3vec3 new_lookat) +{ + c3vec3 diff = c3vec3_sub(new_lookat, c->lookat); + + c->lookat = c3vec3_add(c->lookat, diff); + c->eye = c3vec3_add(c->eye, diff); + + c3cam_update(c); +} + +void +c3cam_move_abs( + c3camp c, + const c3vec3 v) +{ + c->lookat = c3vec3_add(c->lookat, v); + c->eye = c3vec3_add(c->eye, v); + + c3cam_update(c); +} + +void +c3cam_rot_about_eye( + c3camp c, + const c3mat4p rot) +{ + c3vec3 view = c3vec3_sub(c->lookat, c->eye); + + view = c3mat4_mulv3(rot, view); + c->up = c3mat4_mulv3(rot, c->up); + + c->lookat = c3vec3_add(c->eye, view); + + c3cam_update(c); +} + +void +c3cam_rot_about_lookat( + c3camp c, + const c3mat4p rot) +{ + // NOT QUITE RIGHT YET + + c3vec3 view = c3vec3_sub(c->eye, c->lookat); + + view = c3mat4_mulv3(rot, view); + c->up = c3mat4_mulv3(rot, c->up); + + c->eye = c3vec3_add(c->lookat, view); + + c3cam_update(c); +} + +void +c3cam_update_matrix( + c3camp c) +{ + c3cam_update(c); + + c->mtx = c3mat4_vec4( + c3vec4f(c->side.n[VX], c->up.n[VX], c->forward.n[VX], 0.0), + c3vec4f(c->side.n[VY], c->up.n[VY], c->forward.n[VY], 0.0), + c3vec4f(c->side.n[VZ], c->up.n[VZ], c->forward.n[VZ], 0.0), + c3vec4f(0.0, 0.0, 0.0, 1.0)); +} +#if 0 +void +c3cam_load_to_openGL(c3camp c) +{ + c3mat4 m; + + make_mtx(); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glMultMatrixf( (c3f*) &mtx[0][0]); + glTranslatef( -eye[VX], -eye[VY], -eye[VZ] ); +} + +void +c3cam_load_to_openGL_noident(c3camp c) +{ + c3mat4 m; + + make_mtx(); + + glMatrixMode( GL_MODELVIEW ); + glMultMatrixf( (c3f*) &mtx[0][0]); + glTranslatef( -eye[VX], -eye[VY], -eye[VZ] ); +} +#endif + +void +c3cam_reset( + c3camp c) +{ + c->up = c3vec3f( 0.0, 1.0, 0.0 ); + c->eye = c3vec3f(0.0, 0.0, 10.0); + c->lookat = c3vec3f(0.0,0.0,0.0); + + c->mtx = identity3D(); + + c3cam_update(c); +} + +c3cam +c3cam_new() +{ + c3cam c; + c3cam_reset(&c); + return c; +} + +void +c3cam_update( + c3camp c) +{ + /* get proper side and forward vectors, and distance */ + c->forward = c3vec3_minus(c3vec3_sub(c->lookat, c->eye)); + c->distance = c3vec3_length(c->forward); + c->forward = c3vec3_divf(c->forward, c->distance); + + c->side = c3vec3_cross(c->up, c->forward); + c->up = c3vec3_cross(c->forward, c->side); + + c->forward = c3vec3_normalize(c->forward); + c->up = c3vec3_normalize(c->up); + c->side = c3vec3_normalize(c->side); +} + +# if 0 +void +c3cam_dump(c3camp c, FILE *output) const +{ + fprintf( output, "Viewmodel: \n" ); + eye.print( output, " eye" ); + lookat.print( output, " lookat" ); + up.print( output, " up" ); + side.print( output, " side" ); + forward.print(output, " forward"); + mtx.print( output, " mtx" ); +} +#endif diff --git a/examples/shared/libc3/src/c3camera.h b/examples/shared/libc3/src/c3camera.h new file mode 100644 index 0000000..1bfc66c --- /dev/null +++ b/examples/shared/libc3/src/c3camera.h @@ -0,0 +1,236 @@ +/* + c3camera.h + + Copyright 2008-2012 Michel Pollet + Copyright (c) 1998 Paul Rademacher + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#ifndef __C3VIEW_H___ +#define __C3VIEW_H___ + +#include "c3algebra.h" + +typedef struct c3cam { + c3vec3 eye, lookat; + c3vec3 up, side, forward; + c3mat4 mtx; + c3f distance; +} c3cam, *c3camp; + +/******************************* set_distance() ***********/ +/* This readjusts the distance from the eye to the lookat */ +/* (changing the eye point in the process) */ +/* The lookat point is unaffected */ +void +c3cam_set_distance( + c3camp c, + const c3f new_distance); + +/******************************* set_up() ***************/ +void +c3cam_set_upv( + c3camp c, + const c3vec3 new_up); +void +c3cam_set_upf( + c3camp c, + const c3f x, + const c3f y, + const c3f z); + +/******************************* set_eye() ***************/ +void +c3cam_set_eyev( + c3camp c, + const c3vec3 new_eye); +void +c3cam_set_eyef( + c3camp c, + const c3f x, + const c3f y, + const c3f z); + +/******************************* set_lookat() ***************/ +void +c3cam_set_lookatv( + c3camp c, + const c3vec3 new_lookat); +void +c3cam_set_lookatf( + c3camp c, + const c3f x, + const c3f y, + const c3f z); + +/******************************* roll() *****************/ +/* Rotates about the forward vector */ +/* eye and lookat remain unchanged */ +void +c3cam_roll( + c3camp c, + const c3f angle); + +/******************************* eye_yaw() *********************/ +/* Rotates the eye about the lookat point, using the up vector */ +/* Lookat is unaffected */ +void +c3cam_eye_yaw( + c3camp c, + const c3f angle); + +/******************************* eye_yaw_abs() ******************/ +/* Rotates the eye about the lookat point, with a specific axis */ +/* Lookat is unaffected */ +void +c3cam_eye_yaw_abs( + c3camp c, + const c3f angle, + const c3vec3 axis); + +/******************************* eye_pitch() ************/ +/* Rotates the eye about the side vector */ +/* Lookat is unaffected */ +void +c3cam_eye_pitch( + c3camp c, + const c3f angle); + +/******************************* lookat_yaw()************/ +/* This assumes the up vector is correct. */ +/* Rotates the lookat about the side vector */ +/* Eye point is unaffected */ +void +c3cam_lookat_yaw( + c3camp c, + const c3f angle); + +/******************************* lookat_pitch() *********/ +/* Rotates the lookat point about the side vector */ +/* This assumes the side vector is correct. */ +/* Eye point is unaffected */ +void +c3cam_lookat_pitch( + c3camp c, + const c3f angle); + +/******************************* reset_up() ******************/ +/* Resets the up vector to a specified axis (0=X, 1=Y, 2=Z) */ +/* Also sets the eye point level with the lookat point, */ +/* along the specified axis */ +void +c3cam_reset_up_axis( + c3camp c, + const int axis_num); +void +c3cam_reset_up( + c3camp c); + +/******************************* move() ********************/ +/* Moves a specified distance in the forward, side, and up */ +/* directions. This function does NOT move by world */ +/* coordinates. To move by world coords, use the move_abs */ +/* function. */ +void +c3cam_movef( + c3camp c, + const c3f side_move, + const c3f up_move, + const c3f forw_move); +void +c3cam_movev( + c3camp c, + const c3vec3 v); /* A vector version of the above command */ + +/******************************* move_by_eye() ***********/ +/* Sets the eye point, AND moves the lookat point by the */ +/* same amount as the eye is moved. */ +void +c3cam_move_by_eye( + c3camp c, + const c3vec3 new_eye); + +/******************************* move_by_lookat() *********/ +/* Sets the lookat point, AND moves the eye point by the */ +/* same amount as the lookat is moved. */ +void +c3cam_move_by_lookat( + c3camp c, + const c3vec3 new_lookat); + +/******************************* move_abs() *****************/ +/* Move the eye and lookat in world coordinates */ +void +c3cam_move_abs( + c3camp c, + const c3vec3 v); + +/****************************** rot_about_eye() ************/ +/* Rotates the lookat point about the eye, based on a 4x4 */ +/* (pure) rotation matrix */ +void +c3cam_rot_about_eye( + c3camp c, + const c3mat4p rot); + +/****************************** rot_about_lookat() ************/ +/* Rotates the lookat point about the lookat, based on a 4x4 */ +/* (pure) rotation matrix */ +void +c3cam_rot_about_lookat( + c3camp c, + const c3mat4p rot); + +/******************************* make_mtx() *************/ +/* Constructs a 4x4 matrix - used by load_to_openGL() */ +void +c3cam_update_matrix( + c3camp c); + +/******************************* load_to_openGL() ********/ +/* Sets the OpenGL modelview matrix based on the current */ +/* camera coordinates */ +//void c3cam_load_to_openGL(); + +/******************************* load_to_openGL_noident() ******/ +/* Multiplies the current camera matrix by the existing openGL */ +/* modelview matrix. This is same as above function, but */ +/* does not set the OpenGL matrix to identity first */ +//void c3cam_load_to_openGL_noident(); + +/******************************* reset() ****************/ +/* Resets the parameters of this class */ +void +c3cam_reset( + c3camp c); + +/******************************* ViewModel() ************/ +/* Constructor */ +c3cam c3cam_new(); + +/******************************* update() ****************/ +/* updates the view params. Call this after making */ +/* direct changes to the vectors or points of this class */ +void c3cam_update( + c3camp c); + +/******************************* dump() *******************/ +/* Prints the contents of this class to a file, typically */ +/* stdin or stderr */ +//void c3cam_dump(FILE *output); + +#endif /* __C3VIEW_H___ */ diff --git a/examples/shared/libc3/src/c3config.h b/examples/shared/libc3/src/c3config.h new file mode 100644 index 0000000..4457994 --- /dev/null +++ b/examples/shared/libc3/src/c3config.h @@ -0,0 +1,5 @@ +#ifndef __C3_CONFIG__ +#define __C3_CONFIG__ +#define CONFIG_C3_VERSION "0.1.0" +#define CONFIG_C3_CAIRO 1 +#endif diff --git a/examples/shared/libc3/src/c3context.c b/examples/shared/libc3/src/c3context.c new file mode 100644 index 0000000..0ba8367 --- /dev/null +++ b/examples/shared/libc3/src/c3context.c @@ -0,0 +1,84 @@ +/* + c3context.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3context.h" +#include "c3object.h" +#include "c3driver_context.h" + +c3context_p +c3context_new( + int w, + int h) +{ + c3context_p res = malloc(sizeof(*res)); + return c3context_init(res, w, h); +} + +c3context_p +c3context_init( + c3context_p c, + int w, + int h) +{ + memset(c, 0, sizeof(*c)); + c->size.x = w; + c->size.y = h; + c->root = c3object_new(NULL); + c->root->context = c; + + c->cam = c3cam_new(); + + return c; +} + +void +c3context_dispose( + c3context_p c) +{ + c3object_dispose(c->root); + c3geometry_array_free(&c->projected); + free(c); +} + +void +c3context_project( + c3context_p c) +{ + if (!c->root || !c->root->dirty) + return; + + c3mat4 m = identity3D(); + c3object_project(c->root, &m); + c3geometry_array_clear(&c->projected); + c3object_get_geometry(c->root, &c->projected); +} + +void +c3context_draw( + c3context_p c) +{ + c3context_project(c); + for (int gi = 0; gi < c->projected.count; gi++) { + c3geometry_p g = c->projected.e[gi]; + c3geometry_draw(g); + } +} diff --git a/examples/shared/libc3/src/c3context.h b/examples/shared/libc3/src/c3context.h new file mode 100644 index 0000000..f659cf8 --- /dev/null +++ b/examples/shared/libc3/src/c3context.h @@ -0,0 +1,80 @@ +/* + c3context.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3CONTEXT_H___ +#define __C3CONTEXT_H___ + +#include "c3algebra.h" +#include "c3geometry.h" +#include "c3pixels.h" +#include "c3camera.h" + +//! c3context_t is a container for a 'scene' to be drawn +/*! + * A c3context_t holds a root object, a list of already cached projected + * version of the geometry, and a driver that can be customized to draw it. + * + * This is a wrapper around a "top level object", the list of projected + * geometries is kept, purged and resorted if the root object becomes + * dirty + * TODO: Add the camera/eye/arcball control there + */ +typedef struct c3context_t { + c3vec2 size; + c3cam cam; + + struct c3object_t * root; // root object + c3pixels_array_t pixels; // pixels, textures... + + c3geometry_array_t projected; + + const struct c3driver_context_t ** driver; +} c3context_t, *c3context_p; + +//! Allocates a new context of size w=width, h=height +c3context_p +c3context_new( + int w, + int h); + +//! Initializes a new context 'c' of size w=width, h=height +c3context_p +c3context_init( + c3context_p c, + int w, + int h); + +//! Disposes the context, and everything underneath +void +c3context_dispose( + c3context_p c); + +//! Reproject geometry for dirty objects +void +c3context_project( + c3context_p c); +//! Draws the context +void +c3context_draw( + c3context_p c); + +#endif /* __C3CONTEXT_H___ */ diff --git a/examples/shared/libc3/src/c3driver.h b/examples/shared/libc3/src/c3driver.h new file mode 100644 index 0000000..901c32d --- /dev/null +++ b/examples/shared/libc3/src/c3driver.h @@ -0,0 +1,44 @@ +/* + c3driver.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_H___ +#define __C3DRIVER_H___ + +#define C3_DRIVER_CALL(__o, __callback, __args...) { \ + if ((__o) && (__o)->driver) \ + for (int _di = 0; (__o)->driver[_di]; _di++) \ + if ((__o)->driver[_di]->__callback) { \ + (__o)->driver[_di]->__callback(__o, (__o)->driver[_di], ##__args); \ + break; \ + } \ + } +#define C3_DRIVER(__o, __callback, __args...) \ + C3_DRIVER_CALL(__o, __callback, ##__args) +#define C3_DRIVER_INHERITED(__o, __driver, __callback, __args...) { \ + if ((__o) && (__o)->driver) \ + for (int _di = 0; (__o)->driver[_di]; _di++) \ + if ((__o)->driver[_di] == __driver && (__o)->driver[_di+1]) { \ + (__o)->driver[_di+1]->__callback(__o, (__o)->driver[_di+1], ##__args); \ + break; \ + } \ + } +#endif /* __C3DRIVER_H___ */ diff --git a/examples/shared/libc3/src/c3driver_context.h b/examples/shared/libc3/src/c3driver_context.h new file mode 100644 index 0000000..98f34ab --- /dev/null +++ b/examples/shared/libc3/src/c3driver_context.h @@ -0,0 +1,44 @@ +/* + c3driver_context.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_CONTEXT_H___ +#define __C3DRIVER_CONTEXT_H___ + +#include "c3driver.h" + +struct c3context_t; +struct c3driver_context_t; +struct c3geometry_t; + +typedef struct c3driver_context_t { + void (*geometry_project)( + struct c3context_t * c, + const struct c3driver_context_t *d, + struct c3geometry_t * g, + union c3mat4 * mat); + void (*geometry_draw)( + struct c3context_t * c, + const struct c3driver_context_t *d, + struct c3geometry_t * g); +} c3driver_context_t, *c3driver_context_p; + +#endif /* __C3DRIVER_CONTEXT_H___ */ diff --git a/examples/shared/libc3/src/c3driver_geometry.h b/examples/shared/libc3/src/c3driver_geometry.h new file mode 100644 index 0000000..fa23eb5 --- /dev/null +++ b/examples/shared/libc3/src/c3driver_geometry.h @@ -0,0 +1,44 @@ +/* + c3driver_geometry.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_GEOMETRY_H___ +#define __C3DRIVER_GEOMETRY_H___ + +#include "c3driver.h" + +struct c3geometry_t; + +typedef struct c3driver_geometry_t { + void (*dispose)( + struct c3geometry_t * geometry, + const struct c3driver_geometry_t *d); + void (*project)( + struct c3geometry_t * geometry, + const struct c3driver_geometry_t *d, + union c3mat4 * mat); + void (*draw)( + struct c3geometry_t * geometry, + const struct c3driver_geometry_t *d); +} c3driver_geometry_t, *c3driver_geometry_p; + + +#endif /* __C3DRIVER_GEOMETRY_H___ */ diff --git a/examples/shared/libc3/src/c3driver_object.h b/examples/shared/libc3/src/c3driver_object.h new file mode 100644 index 0000000..a809439 --- /dev/null +++ b/examples/shared/libc3/src/c3driver_object.h @@ -0,0 +1,65 @@ +/* + c3driver_object.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3DRIVER_OBJECT_H___ +#define __C3DRIVER_OBJECT_H___ + +#include "c3driver.h" + +struct c3object_t; +struct c3geometry_array_t; +union c3mat4; + +typedef struct c3driver_object_t { + /* + * Delete any object related to this object, geometry etc + * The object will still exist, just empty + */ + void (*clear)( + struct c3object_t * object, + const struct c3driver_object_t * d); + /* + * Dispose of the remaining memory for an object, detaches it + * and frees remaining traces of it + */ + void (*dispose)( + struct c3object_t * object, + const struct c3driver_object_t * d); + /* + * Adds sub objects geometry and self geometry to array 'out' + */ + void (*get_geometry)( + struct c3object_t * object, + const struct c3driver_object_t * d, + struct c3geometry_array_t * out); + /* + * Reproject geometry along matrix 'mat', applies our own + * transform and call down the chain for sub-objects + */ + void (*project)( + struct c3object_t * object, + const struct c3driver_object_t * d, + union c3mat4 * mat); +} c3driver_object_t, *c3driver_object_p; + + +#endif /* __C3DRIVER_OBJECT_H___ */ diff --git a/examples/shared/libc3/src/c3geometry.c b/examples/shared/libc3/src/c3geometry.c new file mode 100644 index 0000000..3abaacc --- /dev/null +++ b/examples/shared/libc3/src/c3geometry.c @@ -0,0 +1,165 @@ +/* + c3geometry.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3object.h" +#include "c3context.h" +#include "c3driver_geometry.h" +#include "c3driver_context.h" + +static void +_c3geometry_dispose( + c3geometry_p g, + const struct c3driver_geometry_t *d) +{ + /* + * If we're still attached to an object, detach + */ + if (g->object) { + for (int oi = 0; oi < g->object->geometry.count; oi++) + if (g->object->geometry.e[oi] == g) { + c3geometry_array_delete(&g->object->geometry, oi, 1); + c3object_set_dirty(g->object, true); + break; + } + g->object = NULL; + } + str_free(g->name); + c3vertex_array_free(&g->vertice); + c3vertex_array_free(&g->projected); + c3tex_array_free(&g->textures); + c3colorf_array_free(&g->colorf); + free(g); +// C3_DRIVER_INHERITED(g, d, dispose); +} + +static void +_c3geometry_project( + c3geometry_p g, + const struct c3driver_geometry_t *d, + c3mat4p m) +{ + if (g->vertice.count) { + c3vertex_array_realloc(&g->projected, g->vertice.count); + g->projected.count = g->vertice.count; + for (int vi = 0; vi < g->vertice.count; vi++) { + g->projected.e[vi] = c3mat4_mulv3(m, g->vertice.e[vi]); + if (vi == 0) + g->bbox.min = g->bbox.max = g->projected.e[vi]; + else { + g->bbox.max = c3vec3_min(g->bbox.min, g->projected.e[vi]); + g->bbox.max = c3vec3_max(g->bbox.max, g->projected.e[vi]); + } + } + } + + if (g->object && g->object->context) + C3_DRIVER(g->object->context, geometry_project, g, m); + g->dirty = 0; +// C3_DRIVER_INHERITED(g, d, project); +} + +static void +_c3geometry_draw( + c3geometry_p g, + const struct c3driver_geometry_t *d) +{ + if (g->object && g->object->context) + C3_DRIVER(g->object->context, geometry_draw, g); +// C3_DRIVER_INHERITED(g, d, draw); +} + +const c3driver_geometry_t c3geometry_driver = { + .dispose = _c3geometry_dispose, + .project = _c3geometry_project, + .draw = _c3geometry_draw, +}; + +c3geometry_p +c3geometry_new( + c3geometry_type_t type, + c3object_p o /* = NULL */) +{ + c3geometry_p res = malloc(sizeof(c3geometry_t)); + return c3geometry_init(res, type, o); +} + +c3geometry_p +c3geometry_init( + c3geometry_p g, + c3geometry_type_t type, + struct c3object_t * o /* = NULL */) +{ + memset(g, 0, sizeof(*g)); + static const c3driver_geometry_t * list[] = { + &c3geometry_driver, NULL, + }; + g->driver = list; + g->type = type; + g->dirty = 1; + if (o) + c3object_add_geometry(o, g); + return g; +} + +c3driver_geometry_p +c3geometry_get_custom( + c3geometry_p g ) +{ + if (g->custom) + return (c3driver_geometry_p)g->driver[0]; + int cnt = 0; + for (int di = 0; g->driver[di]; di++) + cnt++; + c3driver_geometry_p * newd = malloc(sizeof(c3driver_geometry_p) * (cnt + 2)); + memcpy(&newd[1], g->driver, (cnt + 1) * sizeof(c3driver_geometry_p)); + newd[0] = malloc(sizeof(c3driver_geometry_t)); + memset(newd[0], 0, sizeof(c3driver_geometry_t)); + g->custom = 1; + g->driver = (typeof(g->driver))newd; + return newd[0]; +} + +void +c3geometry_dispose( + c3geometry_p g) +{ + C3_DRIVER(g, dispose); +} + +void +c3geometry_project( + c3geometry_p g, + c3mat4p m) +{ + if (!g->dirty) + return; + C3_DRIVER(g, project, m); +} + +void +c3geometry_draw( + c3geometry_p g ) +{ + C3_DRIVER(g, draw); +} + + diff --git a/examples/shared/libc3/src/c3geometry.h b/examples/shared/libc3/src/c3geometry.h new file mode 100644 index 0000000..82b6156 --- /dev/null +++ b/examples/shared/libc3/src/c3geometry.h @@ -0,0 +1,184 @@ +/* + c3geometry.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +/* + * c3geometry is a structure containing one set of vertices and various + * bits related to it. Ultimately it contains a pre-cached projected + * version of the vertices that the drawing code can use directly. + * c3geometry is aways attached to a c3object as a parent. + */ + +#ifndef __C3GEOMETRY_H___ +#define __C3GEOMETRY_H___ + +#include "c3algebra.h" +#include "c_utils.h" + +typedef c3vec3 c3vertex, *c3vertex_p; +typedef c3vec4 c3colorf, *c3colorf_p; +typedef c3vec2 c3tex, *c3tex_p; + +struct c3object_t; +struct c3pixels_t; + +DECLARE_C_ARRAY(c3vertex, c3vertex_array, 16); +DECLARE_C_ARRAY(c3tex, c3tex_array, 16); +DECLARE_C_ARRAY(c3colorf, c3colorf_array, 16); + +//! Geometry material. TODO: Beef up. Add vertex/fragment programs.. +typedef struct c3material_t { + c3colorf color; + struct c3pixels_t * texture; +// uint32_t texmode; + struct { + uint32_t src, dst; + } blend; + struct { + uint32_t pid; + } program; +} c3material_t; + +//! Bounding box. TODO: Move to a separate file? +typedef struct c3bbox_t { + c3vec3 min, max; +} c3bbox_t; + +//! Generic geometry type +enum { + C3_RAW_TYPE = 0, + C3_LINES_TYPE, + C3_TRIANGLE_TYPE, + C3_TEXTURE_TYPE, +}; + +/*! + * geometry type. + * The type is used as non-opengl description of what the geometry + * contains, like "texture", and the subtype can be used to store the + * real format of the vertices. like GL_LINES etc + */ +typedef union c3geometry_type_t { + struct { uint32_t type : 16, subtype : 16; }; + uint32_t value; +} c3geometry_type_t; + +/*! + * Geometry object. Describes a set of vertices, texture coordinates, + * normals, colors and material + * The projection is not set here, a geometry is always attached to a + * c3object that has the projection + */ +typedef struct c3geometry_t { + c3geometry_type_t type; // C3_TRIANGLE_TYPE, GL_LINES etc + int dirty : 1, + custom : 1; // has a custom driver + str_p name; // optional + c3material_t mat; + struct c3object_t * object; + const struct c3driver_geometry_t ** driver; + + c3vertex_array_t vertice; + c3tex_array_t textures; + c3colorf_array_t colorf; + c3vertex_array_t normals; + + // projected version of the vertice + c3vertex_array_t projected; + c3bbox_t bbox; + + /* + * Some shared attributes + */ + union { + struct { + float width; + } line; + }; +} c3geometry_t, *c3geometry_p; + +DECLARE_C_ARRAY(c3geometry_p, c3geometry_array, 4); + +//! Allocates a new geometry, init it, and attached it to parent 'o' (optional) +c3geometry_p +c3geometry_new( + c3geometry_type_t type, + struct c3object_t * o /* = NULL */); +//! Init an existing new geometry, and attached it to parent 'o' (optional) +c3geometry_p +c3geometry_init( + c3geometry_p g, + c3geometry_type_t type, + struct c3object_t * o /* = NULL */); +//! Disposes (via the driver interface) the geometry +void +c3geometry_dispose( + c3geometry_p g); + +//! Prepares a geometry. +/*! + * The project phase is called only when the container object is 'dirty' + * for example if it's projection has changed. + * The project call is responsible for reprojecting the geometry and that + * sort of things + */ +void +c3geometry_project( + c3geometry_p g, + c3mat4p m); + +//! Draw the geometry +/* + * Called when drawing the context. Typicaly this calls the geometry + * driver, which in turn will call the 'context' draw method, and the + * application to draw this particular geometry + */ +void +c3geometry_draw( + c3geometry_p g ); + + +//! allocate (if not there) and return a custom driver for this geometry +/*! + * Geometries come with a default, read only driver stack.. It is a constant + * global to save memory for each of the 'generic' object. + * This call will duplicate that stack and allocate (if not there) a read/write + * empty driver that the application can use to put their own, per object, + * callback. For example you can add your own project() or draw() function + * and have it called first + */ +struct c3driver_geometry_t * +c3geometry_get_custom( + c3geometry_p g ); + +IMPLEMENT_C_ARRAY(c3geometry_array); +IMPLEMENT_C_ARRAY(c3vertex_array); +IMPLEMENT_C_ARRAY(c3tex_array); +IMPLEMENT_C_ARRAY(c3colorf_array); + +static inline c3geometry_type_t +c3geometry_type(int type, int subtype) +{ + c3geometry_type_t r;// = { .type = type, .subtype = subtype }; // older gcc <4.6 doesn't like this + r.type = type; r.subtype = subtype; + return r; +} + +#endif /* __C3GEOMETRY_H___ */ diff --git a/examples/shared/libc3/src/c3lines.c b/examples/shared/libc3/src/c3lines.c new file mode 100644 index 0000000..9db9047 --- /dev/null +++ b/examples/shared/libc3/src/c3lines.c @@ -0,0 +1,142 @@ +/* + c3lines.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3object.h" +#include "c3context.h" +#include "c3driver_geometry.h" +#include "c3lines.h" + + +void +c3lines_prepare( + c3vertex_p vertices, // points A,B pairs + size_t count, + c3vertex_array_p v, // triangles + c3tex_array_p tex, + c3f lineWidth, + c3mat4p m) +{ + c3tex_array_clear(tex); + c3vertex_array_clear(v); + for (int l = 0; l < count; l += 2) { + c3vec3 a = c3mat4_mulv3(m, vertices[l]); + c3vec3 b = c3mat4_mulv3(m, vertices[l+1]); + + c3vec3 e = c3vec3_mulf(c3vec3_normalize(c3vec3_sub(b, a)), lineWidth); + + c3vec3 N = c3vec3f(-e.y, e.x, 0); + c3vec3 S = c3vec3_minus(N); + c3vec3 NE = c3vec3_add(N, e); + c3vec3 NW = c3vec3_sub(N, e); + c3vec3 SW = c3vec3_minus(NE); + c3vec3 SE = c3vec3_minus(NW); +#if 0 + c3vertex_array_add(v, c3vec3_add(a, SW)); + c3vertex_array_add(v, c3vec3_add(a, NW)); + c3vertex_array_add(v, c3vec3_add(a, S)); + c3vertex_array_add(v, c3vec3_add(a, N)); + c3vertex_array_add(v, c3vec3_add(b, S)); + c3vertex_array_add(v, c3vec3_add(b, N)); + c3vertex_array_add(v, c3vec3_add(b, SE)); + c3vertex_array_add(v, c3vec3_add(b, NE)); +#endif + + const float ts = 1; + + c3vertex_array_add(v, c3vec3_add(a, SW)); + c3vertex_array_add(v, c3vec3_add(a, S)); + c3vertex_array_add(v, c3vec3_add(a, NW)); + c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); + + c3vertex_array_add(v, c3vec3_add(a, S)); + c3vertex_array_add(v, c3vec3_add(a, N)); + c3vertex_array_add(v, c3vec3_add(a, NW)); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); + + c3vertex_array_add(v, c3vec3_add(a, N)); + c3vertex_array_add(v, c3vec3_add(b, S)); + c3vertex_array_add(v, c3vec3_add(b, N)); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + + c3vertex_array_add(v, c3vec3_add(a, N)); + c3vertex_array_add(v, c3vec3_add(a, S)); + c3vertex_array_add(v, c3vec3_add(b, S)); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + + c3vertex_array_add(v, c3vec3_add(b, N)); + c3vertex_array_add(v, c3vec3_add(b, S)); + c3vertex_array_add(v, c3vec3_add(b, SE)); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); + + c3vertex_array_add(v, c3vec3_add(b, N)); + c3vertex_array_add(v, c3vec3_add(b, SE)); + c3vertex_array_add(v, c3vec3_add(b, NE)); + c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); + c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); + c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 1 )); + + } +} + +void +c3lines_init( + c3geometry_p g, + c3vertex_p vertices, // points A,B pairs + size_t count, + c3f lineWidth) +{ + c3mat4 i = identity3D(); + c3lines_prepare(vertices, count, &g->vertice, &g->textures, lineWidth, &i); + g->type.type = C3_LINES_TYPE; +} + +#if 0 +static void +_c3lines_project( + c3geometry_p g, + const struct c3driver_geometry_t *d, + c3mat4p m) + +const c3driver_geometry_t c3lines_driver = { + .project = _c3lines_project, +}; + +const c3driver_geometry_t c3geometry_driver; + +c3geometry_set_lines( + c3f lineWidth) +{ + static const c3driver_geometry_t * list[] = { + &c3lines_driver, &c3geometry_driver, NULL, + }; +} +#endif diff --git a/examples/shared/libc3/src/c3lines.h b/examples/shared/libc3/src/c3lines.h new file mode 100644 index 0000000..7befe47 --- /dev/null +++ b/examples/shared/libc3/src/c3lines.h @@ -0,0 +1,50 @@ +/* + c3lines.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3LINES_H___ +#define __C3LINES_H___ + +#include "c3geometry.h" + +/* + * Takes an array of points A,B and split it into 'fat' lines around + * lineWidth, generates an array of triangles and an array of corresponding + * texture cordinates. Can also do a projection at the same time + * TODO: Add array indexes + */ +void +c3lines_prepare( + c3vertex_p vertices, // points A,B pairs + size_t count, + c3vertex_array_p v, // triangles + c3tex_array_p tex, + c3f lineWidth, + c3mat4p m); + +void +c3lines_init( + c3geometry_p g, + c3vertex_p vertices, // points A,B pairs + size_t count, + c3f lineWidth); + +#endif /* __C3LINES_H___ */ diff --git a/examples/shared/libc3/src/c3object.c b/examples/shared/libc3/src/c3object.c new file mode 100644 index 0000000..52cbab3 --- /dev/null +++ b/examples/shared/libc3/src/c3object.c @@ -0,0 +1,238 @@ +/* + c3object.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3object.h" +#include "c3driver_object.h" + +void +_c3object_clear( + c3object_p o, + const c3driver_object_t * d) +{ + for (int oi = 0; oi < o->transform.count; oi++) { + o->transform.e[oi]->object = NULL; + c3transform_dispose(o->transform.e[oi]); + } + for (int oi = 0; oi < o->geometry.count; oi++) { + o->geometry.e[oi]->object = NULL; // don't try to detach + c3geometry_dispose(o->geometry.e[oi]); + } + for (int oi = 0; oi < o->objects.count; oi++) { + o->objects.e[oi]->parent = NULL; // don't try to detach + c3object_dispose(o->objects.e[oi]); + } + c3object_array_free(&o->objects); + c3geometry_array_free(&o->geometry); + c3transform_array_free(&o->transform); +} + +void +_c3object_dispose( + c3object_p o, + const c3driver_object_t * d) +{ + if (o->parent) { + for (int oi = 0; oi < o->parent->objects.count; oi++) + if (o->parent->objects.e[oi] == o) { + c3object_array_delete(&o->parent->objects, oi, 1); + c3object_set_dirty(o->parent, true); + break; + } + o->parent = NULL; + } + //C3O_DRIVER_INHERITED(dispose, d); + free(o); +} + +void +_c3object_get_geometry( + c3object_p o, + const c3driver_object_t * d, + c3geometry_array_p out) +{ + for (int oi = 0; oi < o->geometry.count; oi++) + c3geometry_array_add(out, o->geometry.e[oi]); + for (int oi = 0; oi < o->objects.count; oi++) + c3object_get_geometry(o->objects.e[oi], out); +} + +void +_c3object_project( + c3object_p o, + const c3driver_object_t * d, + c3mat4p m) +{ + if (!o->dirty) + return; + +// c3mat4 identity = identity3D(); + c3mat4 p = *m; + for (int pi = 0; pi < o->transform.count; pi++) + p = c3mat4_mul(&p, &o->transform.e[pi]->matrix); +// bool is_identity = c3mat4_equal(m, &identity); + o->world = p; + + for (int gi = 0; gi < o->geometry.count; gi++) { + c3geometry_p g = o->geometry.e[gi]; + c3vertex_array_clear(&g->projected); + + g->bbox.min = g->bbox.max = c3vec3f(0,0,0); + c3geometry_project(g, &p); + } + for (int oi = 0; oi < o->objects.count; oi++) + c3object_project(o->objects.e[oi], &p); + o->dirty = false; +} + +const c3driver_object_t c3object_driver = { + .clear = _c3object_clear, + .dispose = _c3object_dispose, + .get_geometry = _c3object_get_geometry, + .project = _c3object_project, +}; + + +c3object_p +c3object_init( + c3object_p o /* = NULL */, + c3object_p parent) +{ + memset(o, 0, sizeof(*o)); + o->parent = parent; + static const c3driver_object_t * list[] = + { &c3object_driver, NULL }; + o->driver = list; + if (parent) { + c3object_array_add(&parent->objects, o); + o->context = parent->context; + } + return o; +} + +c3object_p +c3object_new( + c3object_p o /* = NULL */) +{ + c3object_p res = malloc(sizeof(*o)); + return c3object_init(res, o); +} + +void +c3object_clear( + c3object_p o) +{ + C3_DRIVER(o, clear); +} + +void +c3object_dispose( + c3object_p o) +{ + c3object_clear(o); + C3_DRIVER(o, dispose); +} + +void +c3object_set_dirty( + c3object_p o, + bool dirty) +{ + if (dirty) { + // also mark all our geometry dirty + for (int oi = 0; oi < o->geometry.count; oi++) + if (o->geometry.e[oi]) + o->geometry.e[oi]->dirty = 1; + while (o) { + o->dirty = true; + o = o->parent; + } + } else { + for (int oi = 0; oi < o->objects.count; oi++) + if (o->objects.e[oi]->dirty) + c3object_set_dirty(o->objects.e[oi], false); + o->dirty = false; + } +} + +void +c3object_add_object( + c3object_p o, + c3object_p sub) +{ + if (sub->parent == o) + return; + if (sub->parent) { + for (int oi = 0; oi < sub->parent->objects.count; oi++) { + if (sub->parent->objects.e[oi] == sub) { + c3object_array_delete(&sub->parent->objects, oi, 1); + c3object_set_dirty(sub->parent, true); + break; + } + } + sub->parent = NULL; + } + sub->parent = o; + if (o) { + c3object_array_add(&o->objects, sub); + c3object_set_dirty(o, true); + } +} + +void +c3object_add_geometry( + c3object_p o, + c3geometry_p g) +{ + if (g->object == o) + return; + if (g->object) { + for (int oi = 0; oi < g->object->geometry.count; oi++) { + if (g->object->geometry.e[oi] == g) { + c3geometry_array_delete(&g->object->geometry, oi, 1); + c3object_set_dirty(g->object, true); + break; + } + } + g->object = NULL; + } + g->object = o; + if (o) { + c3geometry_array_add(&o->geometry, g); + c3object_set_dirty(o, true); + } +} + +void +c3object_get_geometry( + c3object_p o, + c3geometry_array_p array ) +{ + C3_DRIVER(o, get_geometry, array); +} + +void +c3object_project( + c3object_p o, + const c3mat4p m) +{ + C3_DRIVER(o, project, m); +} diff --git a/examples/shared/libc3/src/c3object.h b/examples/shared/libc3/src/c3object.h new file mode 100644 index 0000000..78122fa --- /dev/null +++ b/examples/shared/libc3/src/c3object.h @@ -0,0 +1,124 @@ +/* + c3object.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3OBJECT_H___ +#define __C3OBJECT_H___ + +#include +#include "c3transform.h" +#include "c3geometry.h" + +struct c3object_t; + +DECLARE_C_ARRAY(struct c3object_t*, c3object_array, 4); + +//! c3object is a container for child object, and geometry +/*! + * a c3object is a node in a c3object tree, it contains sub-objects and/or + * geometry. It also contains it's own list of transform matrices, so can + * be seen as a "anchor" that can be moved around and where you can + * attach other objects or geometry. + * + * An object has a notion of 'dirty bit' -- something that signals that + * something has changed and deserved reprojection. the dirty bit + * is propagated upward when 1 (up to the root object) and downward when 0 + * (to allow clearing the bit on a subtree) + */ +typedef struct c3object_t { + str_p name; //! optional name + int dirty : 1, + visible : 1 /* TODO: Implement visible */; + struct c3context_t * context; //! context this object is attached to + struct c3object_t * parent; //! Parent object + const struct c3driver_object_t ** driver; //! Driver stack + + c3mat4 world; // calculated world coordinates + c3transform_array_t transform; + c3object_array_t objects; //! child object list + c3geometry_array_t geometry; //! Object geometri(es) +} c3object_t, *c3object_p; + +//! Allocates and initialize an emty object, attaches it to parent 'o' +c3object_p +c3object_new( + c3object_p o /* = NULL */); +//! Disposes of everything under this object +void +c3object_dispose( + c3object_p o); +//! Clears every sub-object, geometry, and transform, but do not dispose of o +void +c3object_clear( + c3object_p o); +//! Initializes 'o' as a new object, attaches it to parent (optional) +c3object_p +c3object_init( + c3object_p o, + c3object_p parent /* = NULL */); +//! sets the dirty bit for 'o' and related tree +/*! + * When dirty is 1, sets the dirty bit of this object and all the parent + * objects up to the root object. + * When dirty is 0, clear the dirty bit of this object, and all the + * sub objects. + */ +void +c3object_set_dirty( + c3object_p o, + bool dirty); +//! Adds a new geometry g to object o +void +c3object_add_geometry( + c3object_p o, + c3geometry_p g); +//! Adds a new sub-object sub to object o +void +c3object_add_object( + c3object_p o, + c3object_p sub); +//! Adds a new transform matrix, initialized as identity +c3transform_p +c3object_add_transform( + c3object_p o ); +//! Iterates all the sub-objects and collects all the geometries +/*! + * This call iterates the sub-objects and collects all their 'projected' + * geometry, and add them to the array + */ +void +c3object_get_geometry( + c3object_p o, + c3geometry_array_p array ); +//! Project object 'o' using it's own transformations, relative to matrix 'm' +/*! + * Multiply this objects transformation(s) to matrix 'm' and calls + * reprojects the geometries using that matrix as an anchor. also call + * recursively to sub-objects to follow the projection down. + */ +void +c3object_project( + c3object_p o, + const c3mat4p m); + +IMPLEMENT_C_ARRAY(c3object_array); + +#endif /* __C3OBJECT_H___ */ diff --git a/examples/shared/libc3/src/c3pixels.c b/examples/shared/libc3/src/c3pixels.c new file mode 100644 index 0000000..cdaef7e --- /dev/null +++ b/examples/shared/libc3/src/c3pixels.c @@ -0,0 +1,100 @@ +/* + c3pixels.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include +#include "c3pixels.h" + +c3pixels_p +c3pixels_new( + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base) +{ + c3pixels_p p = malloc(sizeof(*p)); + c3pixels_init(p, w, h, psize, row, base); + p->alloc = 1; + return p; +} + +c3pixels_p +c3pixels_init( + c3pixels_p p, + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base) +{ + memset (p, 0, sizeof(*p)); + p->w = w; + p->h = h; + p->row = row; + p->psize = psize; + p->base = base; + c3pixels_alloc(p); + return p; +} + +void +c3pixels_dispose( + c3pixels_p p ) +{ + if (p->own && p->base) + free(p->base); + if (p->alloc) + free(p); + else + memset(p, 0, sizeof(*p)); +} + +void +c3pixels_alloc( + c3pixels_p p ) +{ + if (p->base) + return; + p->base = malloc(p->row * p->h); + p->own = p->base != NULL; +} + +void +c3pixels_purge( + c3pixels_p p ) +{ + if (!p->base) + return; + if (p->own) + free(p->base); + p->own = 0; + p->base = NULL; +} + +void +c3pixels_zero( + c3pixels_p p) +{ + if (!p->base) + return; + memset(p->base, 0, p->h * p->row); +} diff --git a/examples/shared/libc3/src/c3pixels.h b/examples/shared/libc3/src/c3pixels.h new file mode 100644 index 0000000..1952123 --- /dev/null +++ b/examples/shared/libc3/src/c3pixels.h @@ -0,0 +1,110 @@ +/* + c3pixels.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3PIXELS_H___ +#define __C3PIXELS_H___ + +#include +#include "c_utils.h" + +//! for format hint +enum { + C3PIXEL_ARGB = 0, + C3PIXEL_RGB, + C3PIXEL_A +}; + +typedef struct c3pixels_t { + str_p name; // optional + uint32_t w, h; // width & height in pixels + size_t row; // size of one row in bytes + void * base; // base address + + union { + struct { + uint32_t own : 1, // is the base our own to delete + alloc : 1, // is the c3pixels_p our own to delete + dirty : 1, // pixels have been changed + psize : 4, // pixel size in byte + normalize : 1, // texture coordinates are 0...1 + trace : 1, // debug + format : 8; // not used internally + }; + uint32_t flags; + }; + uint32_t texture; + int refCount; // TODO: Implement reference counting ? +} c3pixels_t, *c3pixels_p; + +DECLARE_C_ARRAY(c3pixels_p, c3pixels_array, 4); + +//! Allocates a new c3pixels, also allocates the pixels if row == NULL +c3pixels_p +c3pixels_new( + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base); + +//! Initializes p, also allocates the pixels if row == NULL +c3pixels_p +c3pixels_init( + c3pixels_p p, + uint32_t w, + uint32_t h, + int psize /* in bytes */, + size_t row, + void * base); + +//! Dispose of the pixels, and potentially p if it was allocated with c3pixels_new +void +c3pixels_dispose( + c3pixels_p p ); + +//! Disposes of the pixels, only +void +c3pixels_purge( + c3pixels_p p ); + +//! (Re)allocate pixels if pixels had been purged +void +c3pixels_alloc( + c3pixels_p p ); + +//! Get a pixel address +static inline void * +c3pixels_get( + c3pixels_p p, + int x, int y) +{ + return ((uint8_t*)p->base) + (y * p->row) + (x * p->psize); +} + +//! Zeroes the pixels +void +c3pixels_zero( + c3pixels_p p); + +IMPLEMENT_C_ARRAY(c3pixels_array); + +#endif /* __C3PIXELS_H___ */ diff --git a/examples/shared/libc3/src/c3quaternion.c b/examples/shared/libc3/src/c3quaternion.c new file mode 100644 index 0000000..10dd468 --- /dev/null +++ b/examples/shared/libc3/src/c3quaternion.c @@ -0,0 +1,249 @@ +/* + c3quaternion.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include "c3quaternion.h" + +#ifndef DEG2RAD +#define DEG2RAD(x) ((x)/180.0*M_PI) +#define RAD2DEG(x) ((x)/M_PI*180.0) +#endif +#ifndef FUDGE +#define FUDGE .00001 +#endif + +c3quat +c3quat_new() +{ + return c3quat_identity(); +} + +/************************************************* c3quat_identity() *****/ +/* Returns quaternion identity element */ + +c3quat +c3quat_identity() +{ + return c3quat_vec3( c3vec3f( 0.0, 0.0, 0.0 ), 1.0 ); +} + +c3quat +c3quatf( + const c3f x, + const c3f y, + const c3f z, + const c3f w) +{ + c3quat q = { .v = c3vec3f(x,y,z), .s = w }; + return q; +} + +c3quat +c3quat_vec3( + const c3vec3 v, + const c3f s) +{ + c3quat q = { .v = v, .s = s }; + return q; +} + +c3quat +c3quat_vec4( + const c3vec4 v) +{ + c3quat q = { .v = c3vec3f(v.n[0], v.n[1], v.n[2]), .s = v.n[3] }; + return q; +} + +c3quat +c3quat_double( + const double *d) +{ + c3quat q; + q.v.n[0] = (c3f) d[0]; + q.v.n[1] = (c3f) d[1]; + q.v.n[2] = (c3f) d[2]; + q.s = (c3f) d[3]; + return q; +} + + +c3quat +c3quat_add( + const c3quat a, + const c3quat b) +{ + return c3quat_vec3(c3vec3_add(a.v, b.v), a.s + b.s ); +} + +c3quat +c3quat_sub( + const c3quat a, + const c3quat b) +{ + return c3quat_vec3(c3vec3_sub(a.v, b.v), a.s - b.s ); +} + +c3quat +c3quat_minus( + const c3quat a ) +{ + return c3quat_vec3(c3vec3_minus(a.v), -a.s); +} + +c3quat +c3quat_mul( + const c3quat a, + const c3quat b) +{ +// return c3quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v ); + return c3quat_vec3( + c3vec3_add(c3vec3_mulf(b.v, a.s), c3vec3_add(c3vec3_mulf(a.v, b.s), c3vec3_cross(a.v, b.v))), + (a.s * b.s) - c3vec3_dot(a.v, b.v)); +} + +c3quat +c3quat_mulf( const c3quat a, const c3f t) +{ + return c3quat_vec3(c3vec3_mulf(a.v, t), a.s * t ); +} + +c3mat4 +c3quat_to_mat4( + const c3quat a ) +{ + c3f xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; + + c3f t = 2.0f / (c3vec3_dot(a.v, a.v) + (a.s * a.s)); + + xs = a.v.n[VX]*t; ys = a.v.n[VY]*t; zs = a.v.n[VZ]*t; + wx = a.s*xs; wy = a.s*ys; wz = a.s*zs; + xx = a.v.n[VX]*xs; xy = a.v.n[VX]*ys; xz = a.v.n[VX]*zs; + yy = a.v.n[VY]*ys; yz = a.v.n[VY]*zs; zz = a.v.n[VZ]*zs; + + c3mat4 m = c3mat4_vec4( + c3vec4f(1.0f-(yy+zz), xy+wz, xz-wy, 0.0f), + c3vec4f(xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f), + c3vec4f(xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f), + c3vec4f(0.0f, 0.0f, 0.0f, 1.0f )); + + return m; +} + + +/************************************************ quat_slerp() ********/ +/* Quaternion spherical interpolation */ + +c3quat +quat_slerp( + const c3quat from, + const c3quat to, + c3f t) +{ + c3quat to1; + c3f omega, cosom, sinom, scale0, scale1; + + /* calculate cosine */ + cosom = c3vec3_dot(from.v, to.v) + from.s + to.s; + + /* Adjust signs (if necessary) */ + if (cosom < 0.0) { + cosom = -cosom; + to1 = c3quat_minus(to); + } else { + to1 = to; + } + + /* Calculate coefficients */ + if ((1.0 - cosom) > FUDGE ) { + /* standard case (slerp) */ + omega = (c3f) acos( cosom ); + sinom = (c3f) sin( omega ); + scale0 = (c3f) sin((1.0 - t) * omega) / sinom; + scale1 = (c3f) sin(t * omega) / sinom; + } else { + /* 'from' and 'to' are very close - just do linear interpolation */ + scale0 = 1.0f - t; + scale1 = t; + } + + return c3quat_add(c3quat_mulf(from, scale0), c3quat_mulf(to1, scale1)); +} + +/********************************************** set_angle() ************/ +/* set rot angle (degrees) */ + +c3quatp +c3quat_set_angle( + c3quatp a, + c3f f) +{ + c3vec3 axis = c3quat_get_axis(a); + + a->s = (c3f) cos( DEG2RAD( f ) / 2.0 ); + + a->v = c3vec3_mulf(axis, (c3f) sin(DEG2RAD(f) / 2.0)); + return a; +} + +/********************************************** scale_angle() ************/ +/* scale rot angle (degrees) */ + +c3quatp +c3quat_scale_angle( + c3quatp a, + c3f f) +{ + return c3quat_set_angle(a, f * c3quat_get_angle(a) ); +} + +/********************************************** get_angle() ************/ +/* get rot angle (degrees). Assumes s is between -1 and 1 */ + +c3f +c3quat_get_angle( + const c3quatp a) +{ + return (c3f) RAD2DEG( 2.0 * acos( a->s ) ); +} + +/********************************************* get_axis() **************/ + +c3vec3 +c3quat_get_axis( + c3quatp a) +{ + c3f scale = (c3f) sin( acos( a->s ) ); + + if ( scale < FUDGE && scale > -FUDGE ) + return c3vec3f( 0.0, 0.0, 0.0 ); + else + return c3vec3_divf(a->v, scale); +} + +/******************************************* c3quat_print() ************/ +#if 0 +void c3quat_print(FILE *dest, const char *name) const +{ + fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n", + name, v[0], v[1], v[2], s ); +} +#endif diff --git a/examples/shared/libc3/src/c3quaternion.h b/examples/shared/libc3/src/c3quaternion.h new file mode 100644 index 0000000..92bf35d --- /dev/null +++ b/examples/shared/libc3/src/c3quaternion.h @@ -0,0 +1,93 @@ +/* + c3quaternion.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3QUATERNION_H___ +#define __C3QUATERNION_H___ + +#include +#include "c3algebra.h" + +typedef struct c3quat { + c3vec3 v; /* vector component */ + c3f s; /* scalar component */ +} c3quat, *c3quatp; + +c3quat +c3quat_new(); +c3quat +c3quat_identity(); + +c3quat +c3quatf( + const c3f x, + const c3f y, + const c3f z, + const c3f w); +c3quat +c3quat_vec3( + const c3vec3 v, + const c3f s); +c3quat +c3quat_vec4( + const c3vec4 v); + +c3quat +c3quat_double( + const double *d); + +c3quat +c3quat_add( + const c3quat a, + const c3quat b); +c3quat +c3quat_sub( + const c3quat a, + const c3quat b); +c3quat +c3quat_minus( + const c3quat a ); + +c3quat +c3quat_mul( + const c3quat a, + const c3quat b); + +c3mat4 +c3quat_to_mat4( + const c3quat a ); + +c3quatp +c3quat_set_angle( + c3quatp a, + c3f f); +c3quatp +c3quat_scale_angle( + c3quatp a, + c3f f); +c3f +c3quat_get_angle( + const c3quatp a); +c3vec3 +c3quat_get_axis( + c3quatp a); + +#endif /* __C3QUATERNION_H___ */ diff --git a/examples/shared/libc3/src/c3stl.c b/examples/shared/libc3/src/c3stl.c new file mode 100644 index 0000000..c42709b --- /dev/null +++ b/examples/shared/libc3/src/c3stl.c @@ -0,0 +1,127 @@ +/* + c3stl.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include "c3algebra.h" +#include "c3geometry.h" +#include "c3object.h" +#include "c3stl.h" + +enum { + vertex_None = -1, + vertex_Vertex, + vertex_Normal, +}; + +static int +_c3stl_read_vertex( + char * vt, + c3vec3 * out ) +{ + int res = 1; + char *l = vt; + /*char * key =*/ strsep(&l, " \t"); + char * x = strsep(&l, " \t"); + char * y = strsep(&l, " \t"); + char * z = strsep(&l, " \t"); + + if (x) sscanf(x, "%f", out->n); + if (y) sscanf(y, "%f", out->n + 1); + if (z) sscanf(z, "%f", out->n + 2); +// printf("'%s' '%s' '%s' '%s' = %.2f %.2f %.2f\n", +// key, x, y, z, out->n[0], out->n[1], out->n[2]); + return res; +} + +struct c3object_t * +c3stl_load( + const char * filename, + c3object_p parent) +{ + FILE *f = fopen(filename, "r"); + if (!f) { + perror(filename); + return NULL; + } + + c3object_p o = c3object_new(parent); + c3geometry_p current_g = NULL; + o->name = str_new(filename); + + int state = 0; + while (!feof(f)) { + char line[256]; + + fgets(line, sizeof(line), f); + + int l = strlen(line); + while (l && line[l-1] < ' ') + line[--l] = 0; + if (!l) + continue; + char * keyword = line; + while (*keyword && *keyword <= ' ') + keyword++; + l = strlen(keyword); + // printf("%d>'%s'\n", state, keyword); + + switch (state) { + case 0: // + if (!strncmp(keyword, "solid ", 6)) { + char * n = keyword + 6; + current_g = c3geometry_new(c3geometry_type(C3_TRIANGLE_TYPE, 0), o); + current_g->name = str_new(n); + + state = 1; + } + break; + case 1: // + if (!strncmp(keyword, "facet ", 6)) { + c3vec3 normal; + _c3stl_read_vertex(keyword + 6, &normal); + c3vertex_array_add(¤t_g->normals, normal); + c3vertex_array_add(¤t_g->normals, normal); + c3vertex_array_add(¤t_g->normals, normal); + state = 2; + } else if (!strncmp(keyword, "endsolid ", 9)) + state = 0; + break; + case 2: + if (!strncmp(keyword, "outer loop", 10)) + state = 3; + else if (!strncmp(keyword, "endfacet", 8)) + state = 1; + break; + case 3: + if (!strncmp(keyword, "vertex ", 7)) { + c3vec3 v; + _c3stl_read_vertex(keyword, &v); + c3vertex_array_add(¤t_g->vertice, v); + state = 3; + } else if (!strncmp(keyword, "endloop", 7)) + state = 2; + break; + } + } + + fclose(f); + return o; +} diff --git a/examples/shared/libc3/src/c3stl.h b/examples/shared/libc3/src/c3stl.h new file mode 100644 index 0000000..d8bd250 --- /dev/null +++ b/examples/shared/libc3/src/c3stl.h @@ -0,0 +1,31 @@ +/* + c3stl.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3STL_H___ +#define __C3STL_H___ + +struct c3object_t * +c3stl_load( + const char * filename, + struct c3object_t * parent); + +#endif /* __C3STL_H___ */ diff --git a/examples/shared/libc3/src/c3texture.c b/examples/shared/libc3/src/c3texture.c new file mode 100644 index 0000000..9d9d427 --- /dev/null +++ b/examples/shared/libc3/src/c3texture.c @@ -0,0 +1,110 @@ +/* + c3texture.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include +#include "c3texture.h" +#include "c3driver_geometry.h" + +void +_c3texture_dispose( + c3geometry_p g, + const c3driver_geometry_t * d) +{ +// c3texture_p t = (c3texture_p)g; + C3_DRIVER_INHERITED(g, d, dispose); +} + +void +_c3texture_project( + c3geometry_p g, + const c3driver_geometry_t * d, + c3mat4p m) +{ + c3texture_p t = (c3texture_p)g; + c3pixels_p p = t->geometry.mat.texture; + if (!p) { + C3_DRIVER_INHERITED(g, d, project, m); + return; + } + c3vec2 qs = c3vec2f( + t->size.x > 0 ? t->size.x : p->w, + t->size.y > 0 ? t->size.y : p->h); + c3vec3 v[4] = { + c3vec3f(0, 0, 0), c3vec3f(qs.x, 0, 0), + c3vec3f(qs.x, qs.y, 0), c3vec3f(0, qs.y, 0) + }; + c3vertex_array_clear(&g->vertice); + c3vertex_array_realloc(&g->vertice, 4); + c3vertex_array_insert(&g->vertice, 0, v, 4); + + c3f tw = p->normalize ? 1.0 : p->w, + th = p->normalize ? 1.0 : p->h; + c3vec2 ti[4] = { + c3vec2f(0, th), c3vec2f(tw, th), + c3vec2f(tw, 0), c3vec2f(0, 0) + }; + if (p->trace) + printf("%s size %.0fx%.0f tex %.0fx%.0f\n", __func__, qs.x, qs.y, tw, th); + c3tex_array_clear(&t->geometry.textures); + c3tex_array_realloc(&t->geometry.textures, 4); + c3tex_array_insert(&t->geometry.textures, 0, ti, 4); + + C3_DRIVER_INHERITED(g, d, project, m); +} + +const c3driver_geometry_t c3texture_driver = { + .dispose = _c3texture_dispose, + .project = _c3texture_project, +}; +const c3driver_geometry_t c3geometry_driver; + +c3texture_p +c3texture_new( + struct c3object_t * o /* = NULL */) +{ + c3texture_p res = malloc(sizeof(*res)); + return c3texture_init(res, o); +} + +c3texture_p +c3texture_init( + c3texture_p t, + struct c3object_t * o /* = NULL */) +{ + memset(t, 0, sizeof(*t)); + c3geometry_init(&t->geometry, + c3geometry_type(C3_TEXTURE_TYPE, 0 /* GL_TRIANGLE_FAN */), + o); + static const c3driver_geometry_t * list[] = { + &c3texture_driver, &c3geometry_driver, NULL, + }; + t->geometry.driver = list; + + return t; +} + +void +c3texture_setpixels( + ) +{ + +} diff --git a/examples/shared/libc3/src/c3texture.h b/examples/shared/libc3/src/c3texture.h new file mode 100644 index 0000000..1a3af62 --- /dev/null +++ b/examples/shared/libc3/src/c3texture.h @@ -0,0 +1,44 @@ +/* + c3texture.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3TEXTURE_H___ +#define __C3TEXTURE_H___ + +#include "c3geometry.h" +#include "c3pixels.h" + +typedef struct c3texture_t { + c3geometry_t geometry; +// c3pixels_t pixels; +// int normalized : 1; // use 0.. 1 texture coordinates + c3vec2 size; // quad size +} c3texture_t, *c3texture_p; + +c3texture_p +c3texture_new( + struct c3object_t * parent /* = NULL */); +c3texture_p +c3texture_init( + c3texture_p t, + struct c3object_t * parent /* = NULL */); + +#endif /* __C3TEXTURE_H___ */ diff --git a/examples/shared/libc3/src/c3transform.c b/examples/shared/libc3/src/c3transform.c new file mode 100644 index 0000000..a453ad7 --- /dev/null +++ b/examples/shared/libc3/src/c3transform.c @@ -0,0 +1,63 @@ +/* + c3transform.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c3object.h" + +c3transform_p +c3transform_new( + c3object_p o ) +{ + c3transform_p res = malloc(sizeof(*res)); + res->matrix = identity3D(); + res->object = o; + res->name = NULL; + c3transform_array_add(&o->transform, res); + return res; +} + +void +c3transform_dispose( + c3transform_p t ) +{ + if (t->object) { + for (int oi = 0; oi < t->object->transform.count; oi++) + if (t->object->transform.e[oi] == t) { + c3transform_array_delete(&t->object->transform, oi, 1); + c3object_set_dirty(t->object, true); + break; + } + t->object = NULL; + } + str_free(t->name); + free(t); +} + +void +c3transform_set( + c3transform_p t, + const c3mat4p m ) +{ + if (c3mat4_equal(m, &t->matrix)) + return; + t->matrix = *m; + c3object_set_dirty(t->object, true); +} diff --git a/examples/shared/libc3/src/c3transform.h b/examples/shared/libc3/src/c3transform.h new file mode 100644 index 0000000..63e8f38 --- /dev/null +++ b/examples/shared/libc3/src/c3transform.h @@ -0,0 +1,49 @@ +/* + c3transform.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __C3TRANSFORM_H___ +#define __C3TRANSFORM_H___ + +#include "c3algebra.h" +#include "c_utils.h" + +typedef struct c3transform_t { + str_p name; + struct c3object_t * object; + c3mat4 matrix; +} c3transform_t, *c3transform_p; + +c3transform_p +c3transform_new( + struct c3object_t * o ); +void +c3transform_set( + c3transform_p t, + c3mat4p m ); +void +c3transform_dispose( + c3transform_p t ); + +DECLARE_C_ARRAY(c3transform_p, c3transform_array, 4); +IMPLEMENT_C_ARRAY(c3transform_array); + +#endif /* __C3TRANSFORM_H___ */ diff --git a/examples/shared/libc3/src/c_array.h b/examples/shared/libc3/src/c_array.h new file mode 100644 index 0000000..8c08efa --- /dev/null +++ b/examples/shared/libc3/src/c_array.h @@ -0,0 +1,134 @@ +/* + c_array.h + + Copyright 2012 Michel Pollet + + This file is part of gcodepp. + + gcodepp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + gcodepp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with gcodepp. If not, see . + */ + + +#ifndef __C_ARRAY_H___ +#define __C_ARRAY_H___ + +#include +#include +#include + +#ifndef C_ARRAY_INLINE +#define C_ARRAY_INLINE inline +#endif +#ifndef C_ARRAY_SIZE_TYPE +#define C_ARRAY_SIZE_TYPE uint32_t +#endif + +#define DECLARE_C_ARRAY(__type, __name, __page) \ +enum { __name##_page_size = __page }; \ +typedef __type __name##_element_t; \ +typedef C_ARRAY_SIZE_TYPE __name##_count_t; \ +typedef struct __name##_t {\ + volatile __name##_count_t count;\ + volatile __name##_count_t size;\ + __name##_element_t * e;\ +} __name##_t, *__name##_p; + +#define C_ARRAY_NULL { 0, 0, NULL } + +#define IMPLEMENT_C_ARRAY(__name) \ +static const __name##_t __name##_zero = C_ARRAY_NULL; \ +static C_ARRAY_INLINE \ + void __name##_free(\ + __name##_p a) \ +{\ + if (!a) return;\ + if (a->e) free(a->e);\ + *a = __name##_zero;\ +}\ +static C_ARRAY_INLINE \ + void __name##_clear(\ + __name##_p a) \ +{\ + if (!a) return;\ + a->count = 0;\ +}\ +static C_ARRAY_INLINE \ + void __name##_realloc(\ + __name##_p a, __name##_count_t size) \ +{\ + if (!a || a->size == size) return; \ + a->e = realloc(a->e, size * sizeof(__name##_element_t));\ + a->size = size; \ +}\ +static C_ARRAY_INLINE \ + void __name##_trim(\ + __name##_p a) \ +{\ + if (!a) return;\ + __name##_count_t n = a->count + __name##_page_size;\ + n -= (n % __name##_page_size);\ + if (n != a->size)\ + __name##_realloc(a, n);\ +}\ +static C_ARRAY_INLINE \ + __name##_element_t * __name##_get_ptr(\ + __name##_p a, __name##_count_t index) \ +{\ + if (!a) return NULL;\ + if (index > a->count) index = a->count;\ + return index < a->count ? a->e + index : NULL;\ +}\ +static C_ARRAY_INLINE \ + __name##_count_t __name##_add(\ + __name##_p a, __name##_element_t e) \ +{\ + if (!a) return 0;\ + if (a->count + 1 >= a->size)\ + __name##_realloc(a, a->size + __name##_page_size);\ + a->e[a->count++] = e;\ + return a->count;\ +}\ +static C_ARRAY_INLINE \ + __name##_count_t __name##_insert(\ + __name##_p a, __name##_count_t index, \ + __name##_element_t * e, __name##_count_t count) \ +{\ + if (!a) return 0;\ + if (index > a->count) index = a->count;\ + if (a->count + count >= a->size) \ + __name##_realloc(a, (((a->count + count) / __name##_page_size)+1) * __name##_page_size);\ + if (index < a->count)\ + memmove(&a->e[index + count], &a->e[index], \ + (a->count - index + count) * sizeof(__name##_element_t));\ + memmove(&a->e[index], e, count * sizeof(__name##_element_t));\ + a->count += count;\ + return a->count;\ +}\ +static C_ARRAY_INLINE \ + __name##_count_t __name##_delete(\ + __name##_p a, __name##_count_t index, __name##_count_t count) \ +{\ + if (!a) return 0;\ + if (index > a->count) index = a->count;\ + if (index + count > a->count) \ + count = a->count - index;\ + if (count && a->count - index) { \ + memmove(&a->e[index], &a->e[index + count], \ + (a->count - index - count) * sizeof(__name##_element_t));\ + }\ + a->count -= count;\ + return a->count;\ +} + +#endif /* __C_ARRAY_H___ */ diff --git a/examples/shared/libc3/src/c_utils.c b/examples/shared/libc3/src/c_utils.c new file mode 100644 index 0000000..e3bb673 --- /dev/null +++ b/examples/shared/libc3/src/c_utils.c @@ -0,0 +1,67 @@ +/* + c_utils.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#include "c_utils.h" + +void +str_hash_init(str_hash_p h) +{ + memset(h, 0, sizeof(*h)); +} + +void +str_hash_add( + str_hash_p h, + str_p k, + void * v) +{ + uint16_t hv = str_hash(k); + hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; + int inserti = bin->count; + + for (int i = 0; i < bin->count; i++) + if (bin->e[i].key->hash >= hv) { + inserti = i; + break; + } + str_hashval_t n = { .key = str_dup(k), .val = v }; + hashval_array_insert(bin, inserti, &n, 1); + return; +} + +void * +str_hash_lookup( + str_hash_p h, + str_p k ) +{ + uint16_t hv = str_hash(k); + hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; + + for (int i = 0; i < bin->count; i++) { + uint16_t h = bin->e[i].key->hash; + if (h == hv && !str_cmp(k, bin->e[i].key)) + return bin->e[i].val; + else if (h > hv) + break; + } + return NULL; +} diff --git a/examples/shared/libc3/src/c_utils.h b/examples/shared/libc3/src/c_utils.h new file mode 100644 index 0000000..2360fd8 --- /dev/null +++ b/examples/shared/libc3/src/c_utils.h @@ -0,0 +1,171 @@ +/* + c_utils.h + + Copyright 2008-11 Michel Pollet + + This program cross examines a root filesystem, loads all the elf + files it can find, see what other library they load and then + find the orphans. In then remove the orphans as "user" for it's + dependencies and continues removing until everything has at least + one user, OR is a program itself (ie, not a shared library) + + cross_linker is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cross_linker is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cross_linker. If not, see . + */ + +#ifndef __C_UTILS_H__ +#define __C_UTILS_H__ + +#ifndef NO_ALLOCA +#include +#endif +#include "c_array.h" + +/******************************************************************** + * CRC16 + ********************************************************************/ + +static uint8_t _crc16_lh[16] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, + 0x70, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1 }; +static uint8_t _crc16_ll[16] = { 0x00, 0x21, 0x42, 0x63, 0x84, 0xA5, 0xC6, + 0xE7, 0x08, 0x29, 0x4A, 0x6B, 0x8C, 0xAD, 0xCE, 0xEF }; + +static uint16_t crc16_u4(uint16_t crc, uint8_t val) +{ + uint8_t h = crc >> 8, l = crc & 0xff; + uint8_t t = (h >> 4) ^ val; + + // Shift the CRC Register left 4 bits + h = (h << 4) | (l >> 4); + l = l << 4; + // Do the table lookups and XOR the result into the CRC Tables + h = h ^ _crc16_lh[t]; + l = l ^ _crc16_ll[t]; + return (h << 8) | l; +} + +static uint16_t crc16_update(uint16_t crc, uint8_t val) +{ + crc = crc16_u4(crc, val >> 4); // High nibble first + crc = crc16_u4(crc, val & 0x0F); // Low nibble + return crc; +} + +static uint16_t crc16_string(char * str) +{ + uint16_t crc = 0xffff; + while (*str) + crc = crc16_update(crc, *str++); + return crc; +} + +/******************************************************************** + * Hashed strings + ********************************************************************/ + +#include +typedef struct str_t { + uint32_t hash : 16, rom : 1, len : 15; + char str[0]; +} str_t, *str_p; + +static inline str_p str_new_i(const char *s, void * (*_alloc)(size_t)) +{ + int l = s ? strlen(s) : 0; + str_p r = (str_p)_alloc(sizeof(*r) + l + 1); + r->hash = 0; r->len = l; + if (s) + strcpy(r->str, s); + return r; +} +static inline void str_free(str_p s) +{ + if (s && !s->rom) + free(s); +} +static inline str_p str_new(const char *s) +{ + return str_new_i(s, malloc); +} +static inline str_p str_anew(const char *s) +{ + str_p r = str_new_i(s, alloca); + r->rom = 1; + return r; +} +static inline str_p str_dup(const str_p s) +{ + size_t l = sizeof(*s) + s->len + 1; + str_p r = (str_p)malloc(l); + memcpy(r, s, l); + return r; +} +#ifndef NO_ALLOCA +static inline str_p str_adup(const str_p s) +{ + size_t l = sizeof(*s) + s->len + 1; + str_p r = (str_p)alloca(l); + memcpy(r, s, l); + r->rom = 1; + return r; +} +#endif +static inline uint16_t str_hash(str_p s) +{ + if (!s->hash) s->hash = crc16_string(s->str); + return s->hash; +} +static inline int str_cmp(str_p s1, str_p s2) +{ + if (s1 == s2) return 1; + if (s1->len != s2->len) return 1; + str_hash(s1); + str_hash(s2); + return s1->hash == s2->hash ? strcmp(s1->str, s2->str) : 1; +} + +/******************************************************************** + * Hash table of strings. Key/value pair + ********************************************************************/ + +typedef struct str_hashval_t { + str_p key; + void * val; +} str_hashval_t; + +DECLARE_C_ARRAY(str_hashval_t, hashval_array, 16); +IMPLEMENT_C_ARRAY(hashval_array); + +#ifndef STR_HASH_SIZE +#define STR_HASH_SIZE 512 // use 9 bits of the 16 of the CRC +#endif +/* uses bins to store the strings as per their hash values */ +typedef struct str_hash_t { + hashval_array_t bin[STR_HASH_SIZE]; +} str_hash_t, *str_hash_p; + +void +str_hash_init( + str_hash_p h); +void +str_hash_add( + str_hash_p h, + str_p k, + void * v); + +void * +str_hash_lookup( + str_hash_p h, + str_p k ); + +#endif /* __C_UTILS_H__ */