diff --git a/.github/workflows/sokol_shader_examples.yml b/.github/workflows/sokol_shader_examples.yml new file mode 100644 index 0000000000..2a09015c46 --- /dev/null +++ b/.github/workflows/sokol_shader_examples.yml @@ -0,0 +1,44 @@ +name: Sokol Shader Examples + +on: + push: + branches: + - master + paths-ignore: + - "**.md" + pull_request: + branches: + - master + paths-ignore: + - "**.md" + +jobs: + sokol-shaders-can-be-compiled: + runs-on: ubuntu-20.04 + timeout-minutes: 30 + env: + VFLAGS: -cc tcc -no-retry-compilation + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: | + sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; + sudo apt-get install --quiet -y libglfw3 libglfw3-dev libfreetype6-dev libxi-dev libxcursor-dev libasound2-dev xfonts-75dpi xfonts-base + - name: Build v + run: | + echo $VFLAGS + make -j4 + ./v -cg -cflags -Werror -o v cmd/v + - name: Shader examples can be build + run: | + wget https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz + tar -xf pre-feb2021-api-changes.tar.gz + for f in examples/sokol/02_cubes_glsl/cube_glsl \ + examples/sokol/03_march_tracing_glsl/rt_glsl \ + examples/sokol/04_multi_shader_glsl/rt_glsl_puppy \ + examples/sokol/04_multi_shader_glsl/rt_glsl_march \ + ; do \ + echo "compiling shader $f.glsl ..."; \ + sokol-tools-bin-pre-feb2021-api-changes/bin/linux/sokol-shdc --input $f.glsl --output $f.h --slang glsl330 ; \ + done + for vfile in examples/sokol/0?*/*.v; do echo "compiling $vfile ..."; ./v $vfile ; done diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 0634b91754..4ae40a95db 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -128,6 +128,13 @@ pub fn new_test_session(_vargs string) TestSession { skip_files << 'examples/database/orm.v' // try fix it } } + if testing.github_job != 'sokol-shaders-can-be-compiled' { + // These examples need .h files that are produced from the supplied .glsl files, + // using by the shader compiler tools in https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz + skip_files << 'examples/sokol/02_cubes_glsl/cube_glsl.v' + skip_files << 'examples/sokol/03_march_tracing_glsl/rt_glsl.v' + skip_files << 'examples/sokol/04_multi_shader_glsl/rt_glsl.v' + } if testing.github_job != 'ubuntu-tcc' { skip_files << 'examples/wkhtmltopdf.v' // needs installation of wkhtmltopdf from https://github.com/wkhtmltopdf/packaging/releases // the ttf_test.v is not interactive, but needs X11 headers to be installed, which is done only on ubuntu-tcc for now diff --git a/examples/sokol/01_cubes/cube.v b/examples/sokol/01_cubes/cube.v new file mode 100644 index 0000000000..b59e024aac --- /dev/null +++ b/examples/sokol/01_cubes/cube.v @@ -0,0 +1,426 @@ +/********************************************************************** +* +* Sokol 3d cube demo +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* TODO: +* - add instancing +* - add an exampel with shaders +**********************************************************************/ +import gg +import gx +import math +import sokol.sapp +import sokol.gfx +import sokol.sgl + +const ( + win_width = 800 + win_height = 800 + bg_color = gx.white +) + +struct App { +mut: + gg &gg.Context + pip_3d C.sgl_pipeline + texture C.sg_image + init_flag bool + frame_count int + mouse_x int = -1 + mouse_y int = -1 +} + +/****************************************************************************** +* +* Texture functions +* +******************************************************************************/ +fn create_texture(w int, h int, buf byteptr) C.sg_image { + sz := w * h * 4 + mut img_desc := C.sg_image_desc{ + width: w + height: h + num_mipmaps: 0 + min_filter: .linear + mag_filter: .linear + // usage: .dynamic + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + label: &byte(0) + d3d11_texture: 0 + } + // commen if .dynamic is enabled + img_desc.content.subimage[0][0] = C.sg_subimage_content{ + ptr: buf + size: sz + } + + sg_img := C.sg_make_image(&img_desc) + return sg_img +} + +fn destroy_texture(sg_img C.sg_image) { + C.sg_destroy_image(sg_img) +} + +// Use only if usage: .dynamic is enabled +fn update_text_texture(sg_img C.sg_image, w int, h int, buf byteptr) { + sz := w * h * 4 + mut tmp_sbc := C.sg_image_content{} + tmp_sbc.subimage[0][0] = C.sg_subimage_content{ + ptr: buf + size: sz + } + C.sg_update_image(sg_img, &tmp_sbc) +} + +/****************************************************************************** +* +* Draw functions +* +******************************************************************************/ +fn draw_triangle() { + sgl.defaults() + sgl.begin_triangles() + sgl.v2f_c3b(0.0, 0.5, 255, 0, 0) + sgl.v2f_c3b(-0.5, -0.5, 0, 0, 255) + sgl.v2f_c3b(0.5, -0.5, 0, 255, 0) + sgl.end() +} + +// vertex specification for a cube with colored sides and texture coords +fn cube() { + sgl.begin_quads() + // edge color + sgl.c3f(1.0, 0.0, 0.0) + // edge coord + // x,y,z, texture cord: u,v + sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0) + sgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, 1.0) + sgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, -1.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0) + sgl.c3f(0.0, 1.0, 0.0) + sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0) + sgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0) + sgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0) + sgl.v3f_t2f(-1.0, 1.0, 1.0, -1.0, -1.0) + sgl.c3f(0.0, 0.0, 1.0) + sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0) + sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0) + sgl.v3f_t2f(-1.0, 1.0, -1.0, 1.0, -1.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0) + sgl.c3f(1.0, 0.5, 0.0) + sgl.v3f_t2f(1.0, -1.0, 1.0, -1.0, 1.0) + sgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, 1.0) + sgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, -1.0) + sgl.v3f_t2f(1.0, 1.0, 1.0, -1.0, -1.0) + sgl.c3f(0.0, 0.5, 1.0) + sgl.v3f_t2f(1.0, -1.0, -1.0, -1.0, 1.0) + sgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0) + sgl.v3f_t2f(-1.0, -1.0, 1.0, 1.0, -1.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0) + sgl.c3f(1.0, 0.0, 0.5) + sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0) + sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0) + sgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0) + sgl.v3f_t2f(1.0, 1.0, -1.0, -1.0, -1.0) + sgl.end() +} + +fn draw_cubes(app App) { + rot := [f32(1.0) * (app.frame_count % 360), 0.5 * f32(app.frame_count % 360)] + // rot := [f32(app.mouse_x), f32(app.mouse_y)] + + sgl.defaults() + sgl.load_pipeline(app.pip_3d) + + sgl.matrix_mode_projection() + sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0) + + sgl.matrix_mode_modelview() + sgl.translate(0.0, 0.0, -12.0) + sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0) + cube() + sgl.push_matrix() + sgl.translate(0.0, 0.0, 3.0) + sgl.scale(0.5, 0.5, 0.5) + sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0) + cube() + sgl.push_matrix() + sgl.translate(0.0, 0.0, 3.0) + sgl.scale(0.5, 0.5, 0.5) + sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0) + cube() + sgl.pop_matrix() + sgl.pop_matrix() +} + +fn cube_t(r f32, g f32, b f32) { + sgl.begin_quads() + // edge color + sgl.c3f(r, g, b) + // edge coord + // x,y,z, texture cord: u,v + sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25) + sgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.25) + sgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0) + sgl.c3f(r, g, b) + sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25) + sgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25) + sgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0) + sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.0, 0.0) + sgl.c3f(r, g, b) + sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25) + sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25) + sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.25, 0.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0) + sgl.c3f(r, g, b) + sgl.v3f_t2f(1.0, -1.0, 1.0, 0.0, 0.25) + sgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.25) + sgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.0) + sgl.v3f_t2f(1.0, 1.0, 1.0, 0.0, 0.0) + sgl.c3f(r, g, b) + sgl.v3f_t2f(1.0, -1.0, -1.0, 0.0, 0.25) + sgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25) + sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.25, 0.0) + sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0) + sgl.c3f(r, g, b) + sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25) + sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25) + sgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0) + sgl.v3f_t2f(1.0, 1.0, -1.0, 0.0, 0.0) + sgl.end() +} + +fn draw_texture_cubes(app App) { + rot := [f32(app.mouse_x), f32(app.mouse_y)] + sgl.defaults() + sgl.load_pipeline(app.pip_3d) + + sgl.enable_texture() + sgl.texture(app.texture) + + sgl.matrix_mode_projection() + sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0) + + sgl.matrix_mode_modelview() + sgl.translate(0.0, 0.0, -12.0) + sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0) + cube_t(1, 1, 1) + sgl.push_matrix() + sgl.translate(0.0, 0.0, 3.0) + sgl.scale(0.5, 0.5, 0.5) + sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0) + cube_t(1, 1, 1) + sgl.push_matrix() + sgl.translate(0.0, 0.0, 3.0) + sgl.scale(0.5, 0.5, 0.5) + sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0) + sgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0) + cube_t(1, 1, 1) + sgl.pop_matrix() + sgl.pop_matrix() + + sgl.disable_texture() +} + +fn cube_field(app App) { + rot := [f32(app.mouse_x), f32(app.mouse_y)] + xyz_sz := f32(2.0) + field_size := 20 + + sgl.defaults() + sgl.load_pipeline(app.pip_3d) + + sgl.enable_texture() + sgl.texture(app.texture) + + sgl.matrix_mode_projection() + sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 200.0) + + sgl.matrix_mode_modelview() + + sgl.translate(field_size, 0.0, -120.0) + sgl.rotate(sgl.rad(rot[0]), 0.0, 1.0, 0.0) + sgl.rotate(sgl.rad(rot[1]), 1.0, 0.0, 0.0) + + // draw field_size*field_size cubes + for y in 0 .. field_size { + for x in 0 .. field_size { + sgl.push_matrix() + z := f32(math.cos(f32(x * 2) / field_size) * math.sin(f32(y * 2) / field_size) * xyz_sz) * (xyz_sz * 5) + sgl.translate(x * xyz_sz, z, y * xyz_sz) + cube_t(f32(f32(x) / field_size), f32(f32(y) / field_size), 1) + sgl.pop_matrix() + } + } + sgl.disable_texture() +} + +fn frame(mut app App) { + ws := gg.window_size() + ratio := f32(ws.width) / ws.height + dw := ws.width + dh := ws.height + ww := int(dh / 3) // not a bug + hh := int(dh / 3) + x0 := int(f32(dw) * 0.05) + // x1 := dw/2 + y0 := 0 + y1 := int(f32(dh) * 0.5) + + app.gg.begin() + // sgl.defaults() + + // 2d triangle + sgl.viewport(x0, y0, ww, hh, true) + draw_triangle() + + // colored cubes with viewport + sgl.viewport(x0, y1, ww, hh, true) + draw_cubes(app) + + // textured cubed with viewport + sgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true) + draw_texture_cubes(app) + + // textured field of cubes with viewport + sgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true) + cube_field(app) + + app.frame_count++ + + app.gg.end() +} + +/****************************************************************************** +* +* Init / Cleanup +* +******************************************************************************/ +fn my_init(mut app App) { + app.init_flag = true + + // set max vertices, + // for a large number of the same type of object it is better use the instances!! + desc := sapp.create_desc() + gfx.setup(&desc) + sgl_desc := C.sgl_desc_t{ + max_vertices: 50 * 65536 + } + sgl.setup(&sgl_desc) + + // 3d pipeline + mut pipdesc := C.sg_pipeline_desc{} + unsafe { C.memset(&pipdesc, 0, sizeof(pipdesc)) } + pipdesc.blend.enabled = true + pipdesc.blend.src_factor_rgb = gfx.BlendFactor(C.SG_BLENDFACTOR_SRC_ALPHA) + pipdesc.blend.dst_factor_rgb = gfx.BlendFactor(C.SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA) + pipdesc.depth_stencil = C.sg_depth_stencil_state{ + depth_write_enabled: true + depth_compare_func: gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL) + } + pipdesc.rasterizer = C.sg_rasterizer_state{ + cull_mode: .back + } + app.pip_3d = sgl.make_pipeline(&pipdesc) + + // create chessboard texture 256*256 RGBA + w := 256 + h := 256 + sz := w * h * 4 + tmp_txt := unsafe { malloc(sz) } + mut i := 0 + for i < sz { + unsafe { + y := (i >> 0x8) >> 5 // 8 cell + x := (i & 0xFF) >> 5 // 8 cell + // upper left corner + if x == 0 && y == 0 { + tmp_txt[i] = byte(0xFF) + tmp_txt[i + 1] = byte(0) + tmp_txt[i + 2] = byte(0) + tmp_txt[i + 3] = byte(0xFF) + } + // low right corner + else if x == 7 && y == 7 { + tmp_txt[i] = byte(0) + tmp_txt[i + 1] = byte(0xFF) + tmp_txt[i + 2] = byte(0) + tmp_txt[i + 3] = byte(0xFF) + } else { + col := if ((x + y) & 1) == 1 { 0xFF } else { 0 } + tmp_txt[i] = byte(col) // red + tmp_txt[i + 1] = byte(col) // green + tmp_txt[i + 2] = byte(col) // blue + tmp_txt[i + 3] = byte(0xFF) // alpha + } + i += 4 + } + } + unsafe { + app.texture = create_texture(w, h, tmp_txt) + free(tmp_txt) + } +} + +fn cleanup(mut app App) { + gfx.shutdown() +} + +/****************************************************************************** +* +* event +* +******************************************************************************/ +fn my_event_manager(mut ev sapp.Event, mut app App) { + if ev.typ == .mouse_move { + app.mouse_x = int(ev.mouse_x) + app.mouse_y = int(ev.mouse_y) + } + if ev.typ == .touches_began || ev.typ == .touches_moved { + if ev.num_touches > 0 { + touch_point := ev.touches[0] + app.mouse_x = int(touch_point.pos_x) + app.mouse_y = int(touch_point.pos_y) + } + } +} + +/****************************************************************************** +* +* Main +* +******************************************************************************/ +fn main() { + // App init + mut app := &App{ + gg: 0 + } + + app.gg = gg.new_context( + width: win_width + height: win_height + use_ortho: true // This is needed for 2D drawing + create_window: true + window_title: '3D Cube Demo' + user_data: app + bg_color: bg_color + frame_fn: frame + init_fn: my_init + cleanup_fn: cleanup + event_fn: my_event_manager + ) + + app.gg.run() +} diff --git a/examples/sokol/02_cubes_glsl/cube_glsl.glsl b/examples/sokol/02_cubes_glsl/cube_glsl.glsl new file mode 100644 index 0000000000..e19e93687a --- /dev/null +++ b/examples/sokol/02_cubes_glsl/cube_glsl.glsl @@ -0,0 +1,95 @@ +//------------------------------------------------------------------------------ +// Shader code for texcube-sapp sample. +// +// NOTE: This source file also uses the '#pragma sokol' form of the +// custom tags. +//------------------------------------------------------------------------------ +//#pragma sokol @ctype mat4 my_mat4 + +#pragma sokol @vs vs +uniform vs_params { + mat4 mvp; +}; + +in vec4 pos; +in vec4 color0; +in vec2 texcoord0; + +out vec4 color; +out vec2 uv; + +void main() { + gl_Position = mvp * pos; + color = color0; + uv = texcoord0; +} +#pragma sokol @end + +#pragma sokol @fs fs +uniform sampler2D tex; +uniform fs_params { + vec2 text_res; + float iTime; +}; + +in vec4 color; +in vec2 uv; +out vec4 frag_color; + +//********************************************************* +// RAY TRACE +// original code from: https://www.shadertoy.com/view/ldS3DW +//********************************************************* +float sphere(vec3 ray, vec3 dir, vec3 center, float radius) +{ + vec3 rc = ray-center; + float c = dot(rc, rc) - (radius*radius); + float b = dot(dir, rc); + float d = b*b - c; + float t = -b - sqrt(abs(d)); + float st = step(0.0, min(t,d)); + return mix(-1.0, t, st); +} + +vec3 background(float t, vec3 rd) +{ + vec3 light = normalize(vec3(sin(t), 0.6, cos(t))); + float sun = max(0.0, dot(rd, light)); + float sky = max(0.0, dot(rd, vec3(0.0, 1.0, 0.0))); + float ground = max(0.0, -dot(rd, vec3(0.0, 1.0, 0.0))); + return (pow(sun, 256.0)+0.2*pow(sun, 2.0))*vec3(2.0, 1.6, 1.0) + + pow(ground, 0.5)*vec3(0.4, 0.3, 0.2) + + pow(sky, 1.0)*vec3(0.5, 0.6, 0.7); +} + +vec4 mainImage(vec2 fragCoord) +{ + vec2 uv = (fragCoord-vec2(0.4,0.4))*2.0; + + //vec2 uv = (-1.0 + 2.0*fc.xy / text_res.xy) * vec2(text_res.x/text_res.y, 1.0); + vec3 ro = vec3(0.0, 0.0, -3.0); + vec3 rd = normalize(vec3(uv, 1.0)); + vec3 p = vec3(0.0, 0.0, 0.0); + float t = sphere(ro, rd, p, 1.0); + vec3 nml = normalize(p - (ro+rd*t)); + vec3 bgCol = background(iTime, rd); + rd = reflect(rd, nml); + vec3 col = background(iTime, rd) * vec3(0.9, 0.8, 1.0); + vec4 fragColor = vec4( mix(bgCol, col, step(0.0, t)), 1.0 ); + return fragColor; +} +//********************************************************* +//********************************************************* + +void main() { + vec4 c = color; + vec4 txt = texture(tex, uv/4.0); + c = txt * c; + vec4 col_ray = mainImage(uv); + float txt_mix = mod(iTime,5); + frag_color = c*txt_mix*0.1 + col_ray ; +} + +#pragma sokol @end + +#pragma sokol @program cube vs fs diff --git a/examples/sokol/cube.v b/examples/sokol/02_cubes_glsl/cube_glsl.v similarity index 57% rename from examples/sokol/cube.v rename to examples/sokol/02_cubes_glsl/cube_glsl.v index ee40fe0763..5770dfc960 100644 --- a/examples/sokol/cube.v +++ b/examples/sokol/02_cubes_glsl/cube_glsl.v @@ -6,17 +6,44 @@ * Use of this source code is governed by an MIT license * that can be found in the LICENSE file. * +* HOW TO COMPILE SHADERS: +* - download the sokol shader convertor tool from https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz +* ( also look at https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md ) +* - compile the .glsl shader with: +* linux : sokol-shdc --input cube_glsl.glsl --output cube_glsl.h --slang glsl330 +* windows: sokol-shdc.exe --input cube_glsl.glsl --output cube_glsl.h --slang glsl330 +* +* --slang parameter can be: +* - glsl330: desktop GL +* - glsl100: GLES2 / WebGL +* - glsl300es: GLES3 / WebGL2 +* - hlsl4: D3D11 +* - hlsl5: D3D11 +* - metal_macos: Metal on macOS +* - metal_ios: Metal on iOS device +* - metal_sim: Metal on iOS simulator +* - wgpu: WebGPU +* +* you can have multiple platforms at the same time passing prameter like this: --slang glsl330:hlsl5:metal_macos +* for further infos have a look at the sokol shader tool docs. +* * TODO: * - add instancing -* - add an exampel with shaders **********************************************************************/ import gg import gx -import math +//import math import sokol.sapp import sokol.gfx import sokol.sgl +import time +import gg.m4 + +// GLSL Include and functions +#flag -I @VROOT/. +#include "cube_glsl.h" #Please use sokol-shdc to generate the necessary cube_glsl.h file from cube_glsl.glsl (see the instructions at the top of this file) +fn C.cube_shader_desc() &C.sg_shader_desc const ( win_width = 800 @@ -34,6 +61,13 @@ mut: mouse_x int = -1 mouse_y int = -1 + + // glsl + cube_pip_glsl C.sg_pipeline + cube_bind C.sg_bindings + + // time + ticks i64 } /****************************************************************************** @@ -55,7 +89,7 @@ fn create_texture(w int, h int, buf byteptr) C.sg_image{ label: &byte(0) d3d11_texture: 0 } - // commen if .dynamic is enabled + // comment if .dynamic is enabled img_desc.content.subimage[0][0] = C.sg_subimage_content{ ptr: buf size: sz @@ -164,7 +198,7 @@ fn draw_cubes(app App) { sgl.pop_matrix() } -fn cube_t(r f32,g f32,b f32) { +fn cube_texture(r f32,g f32,b f32) { sgl.begin_quads() // edge color sgl.c3f(r, g, b) @@ -202,6 +236,166 @@ fn cube_t(r f32,g f32,b f32) { sgl.end() } +/* + Cube vertex buffer with packed vertex formats for color and texture coords. + Note that a vertex format which must be portable across all + backends must only use the normalized integer formats + (BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted + to floating point formats in the vertex shader inputs. + The reason is that D3D11 cannot convert from non-normalized + formats to floating point inputs (only to integer inputs), + and WebGL2 / GLES2 don't support integer vertex shader inputs. +*/ + +struct Vertex_t { + x f32 + y f32 + z f32 + color u32 + + //u u16 + //v u16 + u f32 + v f32 +} + +fn init_cube_glsl(mut app App) { + /* cube vertex buffer */ + //d := u16(32767/8) // for compatibility with D3D11, 32767 stand for 1 + d := f32(1.0) //0.05) + c := u32(0xFFFFFF_FF) // color RGBA8 + vertices := [ + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, d}, + Vertex_t{-1.0, 1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, 1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, 1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, 1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, 1.0, -1.0, c, 0, d}, + ] + + mut vert_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&vert_buffer_desc, 0, sizeof(vert_buffer_desc))} + vert_buffer_desc.size = vertices.len * int(sizeof(Vertex_t)) + vert_buffer_desc.content = byteptr(vertices.data) + vert_buffer_desc.@type = .vertexbuffer + //vert_buffer_desc.usage = .immutable + vert_buffer_desc.label = "cube-vertices".str + vbuf := gfx.make_buffer(&vert_buffer_desc) + + /* create an index buffer for the cube */ + indices := [ + u16(0), 1, 2, 0, 2, 3, + 6, 5, 4, 7, 6, 4, + 8, 9, 10, 8, 10, 11, + 14, 13, 12, 15, 14, 12, + 16, 17, 18, 16, 18, 19, + 22, 21, 20, 23, 22, 20 + ] + + mut index_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&index_buffer_desc, 0, sizeof(index_buffer_desc))} + index_buffer_desc.size = indices.len * int(sizeof(u16)) + index_buffer_desc.content = byteptr(indices.data) + index_buffer_desc.@type = .indexbuffer + index_buffer_desc.label = "cube-indices".str + ibuf := gfx.make_buffer(&index_buffer_desc) + + /* create shader */ + shader := gfx.make_shader(C.cube_shader_desc()) + + mut pipdesc := C.sg_pipeline_desc{} + unsafe {C.memset(&pipdesc, 0, sizeof(pipdesc))} + + pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t)) + // the constants [C.ATTR_vs_pos, C.ATTR_vs_color0, C.ATTR_vs_texcoord0] are generated bysokol-shdc + pipdesc.layout.attrs[C.ATTR_vs_pos ].format = .float3 // x,y,z as f32 + pipdesc.layout.attrs[C.ATTR_vs_color0 ].format = .ubyte4n // color as u32 + pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .float2 // u,v as f32 + //pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .short2n // u,v as u16 + + pipdesc.shader = shader + pipdesc.index_type = .uint16 + + pipdesc.depth_stencil = C.sg_depth_stencil_state{ + depth_write_enabled: true + depth_compare_func : gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL) + } + pipdesc.rasterizer = C.sg_rasterizer_state { + cull_mode: .back + } + pipdesc.label = "glsl_shader pipeline".str + + app.cube_bind.vertex_buffers[0] = vbuf + app.cube_bind.index_buffer = ibuf + app.cube_bind.fs_images[C.SLOT_tex] = app.texture + app.cube_pip_glsl = gfx.make_pipeline(&pipdesc) + println("GLSL init DONE!") +} + +fn draw_cube_glsl(app App){ + if app.init_flag == false { + return + } + + rot := [f32(app.mouse_y), f32(app.mouse_x)] + + ws := gg.window_size() + //ratio := f32(ws.width)/ws.height + dw := f32(ws.width/2) + dh := f32(ws.height/2) + + tr_matrix := m4.calc_tr_matrices(dw, dh, rot[0], rot[1] ,2.0) + gfx.apply_viewport(ws.width/2, 0, ws.width/2, ws.height/2, true) + + // apply the pipline and bindings + gfx.apply_pipeline(app.cube_pip_glsl) + gfx.apply_bindings(app.cube_bind) + + //*************** + // Uniforms + //*************** + // passing the view matrix as uniform + // res is a 4x4 matrix of f32 thus: 4*16 byte of size + gfx.apply_uniforms(C.SG_SHADERSTAGE_VS, C.SLOT_vs_params, &tr_matrix, 4*16 ) + + // fs uniforms + time_ticks := f32(time.ticks() - app.ticks) / 1000 + mut text_res := [ + f32(512), 512, // x,y resolution to pass to FS + time_ticks, // time as f32 + 0 // padding 4 Bytes == 1 f32 + ]! + gfx.apply_uniforms(C.SG_SHADERSTAGE_FS, C.SLOT_fs_params, &text_res, 4*4 ) + + gfx.draw(0, (3*2)*6, 1) + gfx.end_pass() + gfx.commit() +} + fn draw_texture_cubes(app App) { rot := [f32(app.mouse_x), f32(app.mouse_y)] sgl.defaults() @@ -217,58 +411,25 @@ fn draw_texture_cubes(app App) { sgl.translate(0.0, 0.0, -12.0) sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0) sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0) - cube_t(1,1,1) + cube_texture(1,1,1) sgl.push_matrix() sgl.translate(0.0, 0.0, 3.0) sgl.scale(0.5, 0.5, 0.5) sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0) sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0) - cube_t(1,1,1) + cube_texture(1,1,1) sgl.push_matrix() sgl.translate(0.0, 0.0, 3.0) sgl.scale(0.5, 0.5, 0.5) sgl.rotate(-3.0 * sgl.rad(2*rot[0]), 1.0, 0.0, 0.0) sgl.rotate(3.0 * sgl.rad(2*rot[1]), 0.0, 0.0, 1.0) - cube_t(1,1,1) + cube_texture(1,1,1) sgl.pop_matrix() sgl.pop_matrix() sgl.disable_texture() } -fn cube_field(app App){ - rot := [f32(app.mouse_x), f32(app.mouse_y)] - xyz_sz := f32(2.0) - field_size := 20 - - sgl.defaults() - sgl.load_pipeline(app.pip_3d) - - sgl.enable_texture() - sgl.texture(app.texture) - - sgl.matrix_mode_projection() - sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 200.0) - - sgl.matrix_mode_modelview() - - sgl.translate(field_size, 0.0, -120.0) - sgl.rotate(sgl.rad(rot[0]), 0.0, 1.0, 0.0) - sgl.rotate(sgl.rad(rot[1]), 1.0, 0.0, 0.0) - - // draw field_size*field_size cubes - for y in 0..field_size { - for x in 0..field_size { - sgl.push_matrix() - z := f32(math.cos(f32(x*2)/field_size)*math.sin(f32(y*2)/field_size)*xyz_sz)*(xyz_sz*5) - sgl.translate(x*xyz_sz, z, y*xyz_sz) - cube_t(f32(f32(x)/field_size), f32(f32(y)/field_size),1) - sgl.pop_matrix() - } - } - sgl.disable_texture() -} - fn frame(mut app App) { ws := gg.window_size() ratio := f32(ws.width)/ws.height @@ -281,8 +442,10 @@ fn frame(mut app App) { y0 := 0 y1 := int(f32(dh) * 0.5) + //app.gg.begin() + app.gg.begin() - //sgl.defaults() + sgl.defaults() // 2d triangle sgl.viewport(x0, y0, ww, hh, true) @@ -296,13 +459,26 @@ fn frame(mut app App) { sgl.viewport(0, int(dh/5), dw, int(dh*ratio), true) draw_texture_cubes(app) - // textured field of cubes with viewport - sgl.viewport(0, int(dh/5), dw, int(dh*ratio), true) - cube_field(app) + app.gg.end() + + // clear + mut color_action := C.sg_color_attachment_action{ + action: gfx.Action(C.SG_ACTION_DONTCARE) //C.SG_ACTION_CLEAR) + } + color_action.val[0] = 1 + color_action.val[1] = 1 + color_action.val[2] = 1 + color_action.val[3] = 1.0 + mut pass_action := C.sg_pass_action{} + pass_action.colors[0] = color_action + gfx.begin_default_pass(&pass_action, ws.width, ws.height) + + // glsl cube + draw_cube_glsl(app) + app.frame_count++ - app.gg.end() } /****************************************************************************** @@ -311,7 +487,7 @@ fn frame(mut app App) { * ******************************************************************************/ fn my_init(mut app App) { - app.init_flag = true + // set max vertices, // for a large number of the same type of object it is better use the instances!! @@ -341,7 +517,7 @@ fn my_init(mut app App) { w := 256 h := 256 sz := w * h * 4 - tmp_txt := unsafe {malloc(sz)} + tmp_txt := unsafe{ malloc(sz) } mut i := 0 for i < sz { unsafe { @@ -361,7 +537,7 @@ fn my_init(mut app App) { tmp_txt[i+2] = byte(0) tmp_txt[i+3] = byte(0xFF) } else { - col := if ((x+y) & 1) == 1 {0xFF} else {0} + col := if ((x+y) & 1) == 1 {0xFF} else {128} tmp_txt[i ] = byte(col) // red tmp_txt[i+1] = byte(col) // green tmp_txt[i+2] = byte(col) // blue @@ -370,10 +546,12 @@ fn my_init(mut app App) { i += 4 } } - unsafe { - app.texture = create_texture(w, h, tmp_txt) - free(tmp_txt) - } + app.texture = create_texture(w, h, tmp_txt) + unsafe{ free(tmp_txt) } + + // glsl + init_cube_glsl(mut app) + app.init_flag = true } fn cleanup(mut app App) { @@ -404,12 +582,17 @@ fn my_event_manager(mut ev sapp.Event, mut app App) { * Main * ******************************************************************************/ +[console] fn main(){ // App init mut app := &App{ gg: 0 } + mut a := [5]int{} + a[0]=2 + println(a) + app.gg = gg.new_context({ width: win_width height: win_height @@ -424,5 +607,6 @@ fn main(){ event_fn: my_event_manager }) + app.ticks = time.ticks() app.gg.run() } diff --git a/examples/sokol/rt_glsl/v.mod b/examples/sokol/02_cubes_glsl/v.mod similarity index 100% rename from examples/sokol/rt_glsl/v.mod rename to examples/sokol/02_cubes_glsl/v.mod diff --git a/examples/sokol/rt_glsl/rt_glsl.glsl b/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl similarity index 99% rename from examples/sokol/rt_glsl/rt_glsl.glsl rename to examples/sokol/03_march_tracing_glsl/rt_glsl.glsl index 0d31ef7fd2..3490873ea3 100644 --- a/examples/sokol/rt_glsl/rt_glsl.glsl +++ b/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl @@ -4,7 +4,7 @@ // NOTE: This source file also uses the '#pragma sokol' form of the // custom tags. //------------------------------------------------------------------------------ -#pragma sokol @ctype mat4 hmm_mat4 +//#pragma sokol @ctype mat4 hmm_mat4 #pragma sokol @vs vs uniform vs_params { diff --git a/examples/sokol/rt_glsl/rt_glsl.v b/examples/sokol/03_march_tracing_glsl/rt_glsl.v similarity index 89% rename from examples/sokol/rt_glsl/rt_glsl.v rename to examples/sokol/03_march_tracing_glsl/rt_glsl.v index c5b2b9e751..b81721756f 100644 --- a/examples/sokol/rt_glsl/rt_glsl.v +++ b/examples/sokol/03_march_tracing_glsl/rt_glsl.v @@ -7,10 +7,11 @@ * that can be found in the LICENSE file. * * HOW TO COMPILE SHADERS: -* - donwload sokol shader tool from: https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md -* - compile shader with: +* - download the sokol shader convertor tool from https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz +* ( also look at https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md ) +* - compile the .glsl shader with: * linux : sokol-shdc --input rt_glsl.glsl --output rt_glsl.h --slang glsl330 -* windows: sokol-shdc.exe --input rt_glsl.glsl --output rt_glsl.h --slang glsl330 +* windows: sokol-shdc.exe --input rt_glsl.glsl --output rt_glsl.h --slang glsl330 * * --slang parameter can be: * - glsl330: desktop GL @@ -29,7 +30,9 @@ * TODO: * - frame counter **********************************************************************/ + import gg +import gg.m4 import gx //import math @@ -39,6 +42,12 @@ import sokol.sgl import time +// GLSL Include and functions + +#flag -I @VROOT/. +#include "rt_glsl.h" #Please use sokol-shdc to generate the necessary rt_glsl.h file from rt_glsl.glsl (see the instructions at the top of this file) +fn C.rt_shader_desc() &C.sg_shader_desc + const ( win_width = 800 win_height = 800 @@ -54,28 +63,15 @@ mut: mouse_x int = -1 mouse_y int = -1 - + // glsl cube_pip_glsl C.sg_pipeline cube_bind C.sg_bindings - + // time ticks i64 } -/****************************************************************************** -* -* GLSL Include and functions -* -******************************************************************************/ -#flag -I @VROOT/. -#include "HandmadeMath.h" -#include "rt_glsl.h" -#include "default_include.h" -fn C.rt_shader_desc() &C.sg_shader_desc - -fn C.calc_matrices(res voidptr,w f32, h f32, rx f32, ry f32, scale f32) - /****************************************************************************** * * Texture functions @@ -141,12 +137,12 @@ struct Vertex_t { y f32 z f32 color u32 - + //u u16 // for compatibility with D3D11 //v u16 // for compatibility with D3D11 u f32 v f32 -} +} fn init_cube_glsl(mut app App) { /* cube vertex buffer */ @@ -154,7 +150,7 @@ fn init_cube_glsl(mut app App) { d := f32(1.0) c := u32(0xFFFFFF_FF) // color RGBA8 vertices := [ - + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, Vertex_t{ 1.0, 1.0, -1.0, c, d, d}, @@ -194,7 +190,7 @@ fn init_cube_glsl(mut app App) { vert_buffer_desc.@type = .vertexbuffer vert_buffer_desc.label = "cube-vertices".str vbuf := gfx.make_buffer(&vert_buffer_desc) - + /* create an index buffer for the cube */ indices := [ u16(0), 1, 2, 0, 2, 3, @@ -204,7 +200,7 @@ fn init_cube_glsl(mut app App) { 16, 17, 18, 16, 18, 19, 22, 21, 20, 23, 22, 20 ] - + mut index_buffer_desc := C.sg_buffer_desc{} unsafe {C.memset(&index_buffer_desc, 0, sizeof(index_buffer_desc))} index_buffer_desc.size = indices.len * int(sizeof(u16)) @@ -212,23 +208,23 @@ fn init_cube_glsl(mut app App) { index_buffer_desc.@type = .indexbuffer index_buffer_desc.label = "cube-indices".str ibuf := gfx.make_buffer(&index_buffer_desc) - + /* create shader */ shader := gfx.make_shader(C.rt_shader_desc()) mut pipdesc := C.sg_pipeline_desc{} unsafe {C.memset(&pipdesc, 0, sizeof(pipdesc))} pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t)) - + // the constants [C.ATTR_vs_pos, C.ATTR_vs_color0, C.ATTR_vs_texcoord0] are generated by sokol-shdc pipdesc.layout.attrs[C.ATTR_vs_pos ].format = .float3 // x,y,z as f32 pipdesc.layout.attrs[C.ATTR_vs_color0 ].format = .ubyte4n // color as u32 pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .float2 // u,v as f32 //pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .short2n // u,v as u16 - + pipdesc.shader = shader pipdesc.index_type = .uint16 - + pipdesc.depth_stencil = C.sg_depth_stencil_state{ depth_write_enabled: true depth_compare_func : gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL) @@ -237,7 +233,7 @@ fn init_cube_glsl(mut app App) { cull_mode: .back } pipdesc.label = "glsl_shader pipeline".str - + app.cube_bind.vertex_buffers[0] = vbuf app.cube_bind.index_buffer = ibuf app.cube_bind.fs_images[C.SLOT_tex] = app.texture @@ -245,6 +241,21 @@ fn init_cube_glsl(mut app App) { println("GLSL init DONE!") } +fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4{ + proj := m4.perspective(60, w/h, 0.01, 10.0) + view := m4.look_at(m4.Vec4{e:[f32(0.0),0.0,6,0]!}, m4.Vec4{e:[f32(0),0,0,0]!}, m4.Vec4{e:[f32(0),1.0,0,0]!}) + view_proj := view * proj + + rxm := m4.rotate(m4.rad(rx), m4.Vec4{e:[f32(1),0,0,0]!}) + rym := m4.rotate(m4.rad(ry), m4.Vec4{e:[f32(0),1,0,0]!}) + + model := rym * rxm + scale_m := m4.scale(m4.Vec4{e:[in_scale, in_scale, in_scale, 1]!}) + + res := (scale_m * model)* view_proj + return res +} + fn draw_cube_glsl(app App){ if app.init_flag == false { return @@ -254,26 +265,24 @@ fn draw_cube_glsl(app App){ ratio := f32(ws.width) / ws.height dw := f32(ws.width / 2) dh := f32(ws.height / 2) - - mut res := [f32(0),0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]! // use the following commented lines to rotate the 3d glsl cube // rot := [f32(app.mouse_y), f32(app.mouse_x)] - // C.calc_matrices( voidptr(&res), dw, dh, rot[0], rot[1] ,2.3) - C.calc_matrices( voidptr(&res), dw, dh, 0, 0 ,2.3) + // calc_tr_matrices(dw, dh, rot[0], rot[1] ,2.3) + tr_matrix := calc_tr_matrices(dw, dh, 0, 0 ,2.3) gfx.apply_viewport(0, 0, ws.width, ws.height, true) // apply the pipline and bindings gfx.apply_pipeline(app.cube_pip_glsl) gfx.apply_bindings(app.cube_bind) - + //*************** // Uniforms //*************** // passing the view matrix as uniform // res is a 4x4 matrix of f32 thus: 4*16 byte of size - gfx.apply_uniforms(C.SG_SHADERSTAGE_VS, C.SLOT_vs_params, &res, int(sizeof(res)) ) - + gfx.apply_uniforms(C.SG_SHADERSTAGE_VS, C.SLOT_vs_params, &tr_matrix, 4*16 ) + // fragment shader uniforms time_ticks := f32(time.ticks() - app.ticks) / 1000 mut tmp_fs_params := [ @@ -282,10 +291,10 @@ fn draw_cube_glsl(app App){ ws.height - app.mouse_y*2, // mouse y scaled time_ticks, // time as f32 app.frame_count, // frame count - 0,0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h + 0,0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h ]! gfx.apply_uniforms(C.SG_SHADERSTAGE_FS, C.SLOT_fs_params, &tmp_fs_params, int(sizeof(tmp_fs_params))) - + // 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw gfx.draw(0, (3 * 2) * 6, 1) gfx.end_pass() @@ -306,11 +315,11 @@ fn frame(mut app App) { mut pass_action := C.sg_pass_action{} pass_action.colors[0] = color_action gfx.begin_default_pass(&pass_action, ws.width, ws.height) - + // glsl cube draw_cube_glsl(app) app.frame_count++ -} +} /****************************************************************************** * @@ -331,7 +340,7 @@ fn my_init(mut app App) { w := 256 h := 256 sz := w * h * 4 - tmp_txt := unsafe {malloc(sz)} + tmp_txt := unsafe { malloc(sz) } mut i := 0 for i < sz { unsafe { @@ -418,6 +427,6 @@ fn main(){ event_fn: my_event_manager }) - app.ticks = time.ticks() + app.ticks = time.ticks() app.gg.run() } diff --git a/examples/sokol/03_march_tracing_glsl/v.mod b/examples/sokol/03_march_tracing_glsl/v.mod new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl.v b/examples/sokol/04_multi_shader_glsl/rt_glsl.v new file mode 100644 index 0000000000..3f727e5e97 --- /dev/null +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl.v @@ -0,0 +1,625 @@ +/********************************************************************** +* +* Sokol 3d cube multishader demo +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* HOW TO COMPILE SHADERS: +* - download the sokol shader convertor tool from https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz +* ( also look at https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md ) +* - compile the .glsl shared file with: +* linux : sokol-shdc --input rt_glsl_puppy.glsl --output rt_glsl_puppy.h --slang glsl330 + sokol-shdc --input rt_glsl_march.glsl --output rt_glsl_march.h --slang glsl330 +* windows: sokol-shdc.exe --input rt_glsl_puppy.glsl --output rt_glsl_puppy.h --slang glsl330 +* sokol-shdc.exe --input rt_glsl_march.glsl --output rt_glsl_march.h --slang glsl330 +* +* --slang parameter can be: +* - glsl330: desktop GL +* - glsl100: GLES2 / WebGL +* - glsl300es: GLES3 / WebGL2 +* - hlsl4: D3D11 +* - hlsl5: D3D11 +* - metal_macos: Metal on macOS +* - metal_ios: Metal on iOS device +* - metal_sim: Metal on iOS simulator +* - wgpu: WebGPU +* +* you can have multiple platforms at the same time passing parameters like this: --slang glsl330:hlsl5:metal_macos +* for further infos have a look at the sokol shader tool docs. +* +* TODO: +* - frame counter +**********************************************************************/ +import gg +import gg.m4 +import gx +//import math + +import sokol.sapp +import sokol.gfx +import sokol.sgl + +import time + +// GLSL Include and functions + +#flag -I @VROOT/. +#include "rt_glsl_march.h" #Please use sokol-shdc to generate the necessary rt_glsl_march.h file from rt_glsl_march.glsl (see the instructions at the top of this file) +#include "rt_glsl_puppy.h" #Please use sokol-shdc to generate the necessary rt_glsl_puppy.h file from rt_glsl_puppy.glsl (see the instructions at the top of this file) +fn C.rt_march_shader_desc() &C.sg_shader_desc +fn C.rt_puppy_shader_desc() &C.sg_shader_desc + +const ( + win_width = 800 + win_height = 800 + bg_color = gx.white +) + +struct App { +mut: + gg &gg.Context + texture C.sg_image + init_flag bool + frame_count int + + mouse_x int = -1 + mouse_y int = -1 + mouse_down bool + + // glsl + cube_pip_glsl C.sg_pipeline + cube_bind C.sg_bindings + + pipe map[string]C.sg_pipeline + bind map[string]C.sg_bindings + + // time + ticks i64 +} + +/****************************************************************************** +* +* Texture functions +* +******************************************************************************/ +fn create_texture(w int, h int, buf byteptr) C.sg_image{ + sz := w * h * 4 + mut img_desc := C.sg_image_desc{ + width: w + height: h + num_mipmaps: 0 + min_filter: .linear + mag_filter: .linear + //usage: .dynamic + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + label: &byte(0) + d3d11_texture: 0 + } + // comment if .dynamic is enabled + img_desc.content.subimage[0][0] = C.sg_subimage_content{ + ptr: buf + size: sz + } + + sg_img := C.sg_make_image(&img_desc) + return sg_img +} + +fn destroy_texture(sg_img C.sg_image){ + C.sg_destroy_image(sg_img) +} + +// Use only if usage: .dynamic is enabled +fn update_text_texture(sg_img C.sg_image, w int, h int, buf byteptr){ + sz := w * h * 4 + mut tmp_sbc := C.sg_image_content{} + tmp_sbc.subimage[0][0] = C.sg_subimage_content { + ptr: buf + size: sz + } + C.sg_update_image(sg_img, &tmp_sbc) +} + +/****************************************************************************** +* +* Draw functions +* +******************************************************************************/ +/* + Cube vertex buffer with packed vertex formats for color and texture coords. + Note that a vertex format which must be portable across all + backends must only use the normalized integer formats + (BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted + to floating point formats in the vertex shader inputs. + The reason is that D3D11 cannot convert from non-normalized + formats to floating point inputs (only to integer inputs), + and WebGL2 / GLES2 don't support integer vertex shader inputs. +*/ + +struct Vertex_t { + x f32 + y f32 + z f32 + color u32 + + //u u16 // for compatibility with D3D11 + //v u16 // for compatibility with D3D11 + u f32 + v f32 +} + +// march shader init +fn init_cube_glsl_m(mut app App) { + /* cube vertex buffer */ + //d := u16(32767) // for compatibility with D3D11, 32767 stand for 1 + d := f32(1.0) + c := u32(0xFFFFFF_FF) // color RGBA8 + vertices := [ + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, d}, + Vertex_t{-1.0, 1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, 1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, 1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, 1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, 1.0, -1.0, c, 0, d}, + + ] + + mut vert_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&vert_buffer_desc, 0, sizeof(vert_buffer_desc))} + vert_buffer_desc.size = vertices.len * int(sizeof(Vertex_t)) + vert_buffer_desc.content = byteptr(vertices.data) + vert_buffer_desc.@type = .vertexbuffer + vert_buffer_desc.label = "cube-vertices".str + vbuf := gfx.make_buffer(&vert_buffer_desc) + + /* create an index buffer for the cube */ + indices := [ + u16(0), 1, 2, 0, 2, 3, + 6, 5, 4, 7, 6, 4, + 8, 9, 10, 8, 10, 11, +/* + u16(14), 13, 12, 15, 14, 12, + 16, 17, 18, 16, 18, 19, + 22, 21, 20, 23, 22, 20 +*/ + ] + + mut index_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&index_buffer_desc, 0, sizeof(index_buffer_desc))} + index_buffer_desc.size = indices.len * int(sizeof(u16)) + index_buffer_desc.content = byteptr(indices.data) + index_buffer_desc.@type = .indexbuffer + index_buffer_desc.label = "cube-indices".str + ibuf := gfx.make_buffer(&index_buffer_desc) + + /* create shader */ + shader := gfx.make_shader(C.rt_march_shader_desc()) + + mut pipdesc := C.sg_pipeline_desc{} + unsafe {C.memset(&pipdesc, 0, sizeof(pipdesc))} + pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t)) + + // the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc + pipdesc.layout.attrs[C.ATTR_vs_m_pos ].format = .float3 // x,y,z as f32 + pipdesc.layout.attrs[C.ATTR_vs_m_color0 ].format = .ubyte4n // color as u32 + pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .float2 // u,v as f32 + //pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .short2n // u,v as u16 + + pipdesc.shader = shader + pipdesc.index_type = .uint16 + + pipdesc.depth_stencil = C.sg_depth_stencil_state{ + depth_write_enabled: true + depth_compare_func : gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL) + } + pipdesc.rasterizer = C.sg_rasterizer_state { + cull_mode: .back + } + pipdesc.label = "glsl_shader pipeline".str + + mut bind := C.sg_bindings{} + unsafe {C.memset(&bind, 0, sizeof(bind))} + bind.vertex_buffers[0] = vbuf + bind.index_buffer = ibuf + bind.fs_images[C.SLOT_tex] = app.texture + app.bind['march'] = bind + + app.pipe['march'] = gfx.make_pipeline(&pipdesc) + + println("GLSL March init DONE!") +} + +// putty shader init +fn init_cube_glsl_p(mut app App) { + /* cube vertex buffer */ + //d := u16(32767) // for compatibility with D3D11, 32767 stand for 1 + d := f32(1.0) + c := u32(0xFFFFFF_FF) // color RGBA8 + vertices := [ + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, d}, + Vertex_t{-1.0, 1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, 1.0, c, 0, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, 1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, d}, + Vertex_t{-1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{ 1.0, 1.0, -1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, 1.0, c, 0, d}, + + Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, -1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, -1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, -1.0, -1.0, c, 0, d}, + + Vertex_t{-1.0, 1.0, -1.0, c, 0, 0}, + Vertex_t{-1.0, 1.0, 1.0, c, d, 0}, + Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, + Vertex_t{ 1.0, 1.0, -1.0, c, 0, d}, + + ] + + mut vert_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&vert_buffer_desc, 0, sizeof(vert_buffer_desc))} + vert_buffer_desc.size = vertices.len * int(sizeof(Vertex_t)) + vert_buffer_desc.content = byteptr(vertices.data) + vert_buffer_desc.@type = .vertexbuffer + vert_buffer_desc.label = "cube-vertices".str + vbuf := gfx.make_buffer(&vert_buffer_desc) + + /* create an index buffer for the cube */ + indices := [ +/* + u16(0), 1, 2, 0, 2, 3, + 6, 5, 4, 7, 6, 4, + 8, 9, 10, 8, 10, 11, +*/ + u16(14), 13, 12, 15, 14, 12, + 16, 17, 18, 16, 18, 19, + 22, 21, 20, 23, 22, 20 + + ] + + mut index_buffer_desc := C.sg_buffer_desc{} + unsafe {C.memset(&index_buffer_desc, 0, sizeof(index_buffer_desc))} + index_buffer_desc.size = indices.len * int(sizeof(u16)) + index_buffer_desc.content = byteptr(indices.data) + index_buffer_desc.@type = .indexbuffer + index_buffer_desc.label = "cube-indices".str + ibuf := gfx.make_buffer(&index_buffer_desc) + + /* create shader */ + shader := gfx.make_shader(C.rt_puppy_shader_desc()) + + mut pipdesc := C.sg_pipeline_desc{} + unsafe {C.memset(&pipdesc, 0, sizeof(pipdesc))} + pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t)) + + // the constants [C.ATTR_vs_p_pos, C.ATTR_vs_p_color0, C.ATTR_vs_p_texcoord0] are generated by sokol-shdc + pipdesc.layout.attrs[C.ATTR_vs_p_pos ].format = .float3 // x,y,z as f32 + pipdesc.layout.attrs[C.ATTR_vs_p_color0 ].format = .ubyte4n // color as u32 + pipdesc.layout.attrs[C.ATTR_vs_p_texcoord0].format = .float2 // u,v as f32 + //pipdesc.layout.attrs[C.ATTR_vs_p_texcoord0].format = .short2n // u,v as u16 + + pipdesc.shader = shader + pipdesc.index_type = .uint16 + + pipdesc.depth_stencil = C.sg_depth_stencil_state{ + depth_write_enabled: true + depth_compare_func : gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL) + } + pipdesc.rasterizer = C.sg_rasterizer_state { + cull_mode: .back + } + pipdesc.label = "glsl_shader pipeline".str + + mut bind := C.sg_bindings{} + unsafe {C.memset(&bind, 0, sizeof(bind))} + bind.vertex_buffers[0] = vbuf + bind.index_buffer = ibuf + bind.fs_images[C.SLOT_tex] = app.texture + app.bind['puppy'] = bind + + app.pipe['puppy'] = gfx.make_pipeline(&pipdesc) + + println("GLSL Puppy init DONE!") +} + +fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4{ + proj := m4.perspective(60, w/h, 0.01, 10.0) + view := m4.look_at(m4.Vec4{e:[f32(0.0),0.0,6,0]!}, m4.Vec4{e:[f32(0),0,0,0]!}, m4.Vec4{e:[f32(0),1.0,0,0]!}) + view_proj := view * proj + + rxm := m4.rotate(m4.rad(rx), m4.Vec4{e:[f32(1),0,0,0]!}) + rym := m4.rotate(m4.rad(ry), m4.Vec4{e:[f32(0),1,0,0]!}) + + model := rym * rxm + scale_m := m4.scale(m4.Vec4{e:[in_scale, in_scale, in_scale, 1]!}) + + res := (scale_m * model)* view_proj + return res +} + +// march triangles draw +fn draw_cube_glsl_m(app App){ + if app.init_flag == false { + return + } + + ws := gg.window_size() + ratio := f32(ws.width) / ws.height + dw := f32(ws.width / 2) + dh := f32(ws.height / 2) + + rot := [f32(app.mouse_y), f32(app.mouse_x)] + tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3) + + gfx.apply_pipeline(app.pipe['march']) + gfx.apply_bindings(app.bind['march']) + + //*************** + // Uniforms + //*************** + // passing the view matrix as uniform + // res is a 4x4 matrix of f32 thus: 4*16 byte of size + gfx.apply_uniforms(C.SG_SHADERSTAGE_VS, C.SLOT_vs_params_m, &tr_matrix, 4*16 ) + + // fragment shader uniforms + time_ticks := f32(time.ticks() - app.ticks) / 1000 + mut tmp_fs_params := [ + f32(ws.width), ws.height * ratio, // x,y resolution to pass to FS + 0,0, // dont send mouse position + //app.mouse_x, // mouse x + //ws.height - app.mouse_y*2, // mouse y scaled + time_ticks, // time as f32 + app.frame_count, // frame count + 0,0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h + ]! + gfx.apply_uniforms(C.SG_SHADERSTAGE_FS, C.SLOT_fs_params_m, &tmp_fs_params, int(sizeof(tmp_fs_params))) + + // 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw + gfx.draw(0, (3 * 2) * 3, 1) +} + +// puppy triangles draw +fn draw_cube_glsl_p(app App){ + if app.init_flag == false { + return + } + + ws := gg.window_size() + ratio := f32(ws.width) / ws.height + dw := f32(ws.width / 2) + dh := f32(ws.height / 2) + + rot := [f32(app.mouse_y), f32(app.mouse_x)] + tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3) + + // apply the pipline and bindings + gfx.apply_pipeline(app.pipe['puppy']) + gfx.apply_bindings(app.bind['puppy']) + + //*************** + // Uniforms + //*************** + // passing the view matrix as uniform + // res is a 4x4 matrix of f32 thus: 4*16 byte of size + gfx.apply_uniforms(C.SG_SHADERSTAGE_VS, C.SLOT_vs_params_p, &tr_matrix, 4*16 ) + + // fragment shader uniforms + time_ticks := f32(time.ticks() - app.ticks) / 1000 + mut tmp_fs_params := [ + f32(ws.width), ws.height * ratio, // x,y resolution to pass to FS + 0,0, // dont send mouse position + //app.mouse_x, // mouse x + //ws.height - app.mouse_y*2, // mouse y scaled + time_ticks, // time as f32 + app.frame_count, // frame count + 0,0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h + ]! + gfx.apply_uniforms(C.SG_SHADERSTAGE_FS, C.SLOT_fs_params_p, &tmp_fs_params, int(sizeof(tmp_fs_params))) + + // 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw + gfx.draw(0, (3 * 2) * 3, 1) +} + +fn draw_start_glsl(app App){ + if app.init_flag == false { + return + } + + ws := gg.window_size() + //ratio := f32(ws.width) / ws.height + //dw := f32(ws.width / 2) + //dh := f32(ws.height / 2) + + gfx.apply_viewport(0, 0, ws.width, ws.height, true) +} + +fn draw_end_glsl(app App){ + gfx.end_pass() + gfx.commit() +} + +fn frame(mut app App) { + ws := gg.window_size() + + // clear + mut color_action := C.sg_color_attachment_action{ + action: gfx.Action(C.SG_ACTION_CLEAR) + } + color_action.val[0] = 0 + color_action.val[1] = 0 + color_action.val[2] = 0 + color_action.val[3] = 1.0 + mut pass_action := C.sg_pass_action{} + pass_action.colors[0] = color_action + gfx.begin_default_pass(&pass_action, ws.width, ws.height) + +/* + // glsl cube + if app.frame_count % 1 == 1{ + draw_cube_glsl_m(app) + } else { + draw_cube_glsl_p(app) + } +*/ + draw_start_glsl(app) + draw_cube_glsl_m(app) + draw_cube_glsl_p(app) + draw_end_glsl(app) + app.frame_count++ +} + +/****************************************************************************** +* +* Init / Cleanup +* +******************************************************************************/ +fn my_init(mut app App) { + // set max vertices, + // for a large number of the same type of object it is better use the instances!! + desc := sapp.create_desc() + gfx.setup(&desc) + sgl_desc := C.sgl_desc_t{ + max_vertices: 50 * 65536 + } + sgl.setup(&sgl_desc) + + // create chessboard texture 256*256 RGBA + w := 256 + h := 256 + sz := w * h * 4 + tmp_txt := unsafe { malloc(sz) } + mut i := 0 + for i < sz { + unsafe { + y := (i >> 0x8) >> 5 // 8 cell + x := (i & 0xFF) >> 5 // 8 cell + // upper left corner + if x==0 && y==0 { + tmp_txt[i ] = byte(0xFF) + tmp_txt[i+1] = byte(0) + tmp_txt[i+2] = byte(0) + tmp_txt[i+3] = byte(0xFF) + } + // low right corner + else if x==7 && y==7 { + tmp_txt[i ] = byte(0) + tmp_txt[i+1] = byte(0xFF) + tmp_txt[i+2] = byte(0) + tmp_txt[i+3] = byte(0xFF) + } else { + col := if ((x+y) & 1) == 1 {0xFF} else {128} + tmp_txt[i ] = byte(col) // red + tmp_txt[i+1] = byte(col) // green + tmp_txt[i+2] = byte(col) // blue + tmp_txt[i+3] = byte(0xFF) // alpha + } + i += 4 + } + } + app.texture = create_texture(w, h, tmp_txt) + unsafe { free(tmp_txt) } + + // glsl + init_cube_glsl_m(mut app) + init_cube_glsl_p(mut app) + app.init_flag = true +} + +fn cleanup(mut app App) { + gfx.shutdown() +} + +/****************************************************************************** +* +* event +* +******************************************************************************/ +fn my_event_manager(mut ev sapp.Event, mut app App) { + if ev.typ == .mouse_down{ + app.mouse_down = true + } + if ev.typ == .mouse_up{ + app.mouse_down = false + } + if app.mouse_down == true && ev.typ == .mouse_move { + app.mouse_x = int(ev.mouse_x) + app.mouse_y = int(ev.mouse_y) + } + if ev.typ == .touches_began || ev.typ == .touches_moved { + if ev.num_touches > 0 { + touch_point := ev.touches[0] + app.mouse_x = int(touch_point.pos_x) + app.mouse_y = int(touch_point.pos_y) + } + } +} + +/****************************************************************************** +* +* Main +* +******************************************************************************/ +[console] +fn main(){ + // App init + mut app := &App{ + gg: 0 + } + + app.gg = gg.new_context({ + width: win_width + height: win_height + use_ortho: true // This is needed for 2D drawing + create_window: true + window_title: '3D Ray Marching Cube' + user_data: app + bg_color: bg_color + frame_fn: frame + init_fn: my_init + cleanup_fn: cleanup + event_fn: my_event_manager + }) + + app.ticks = time.ticks() + app.gg.run() +} diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl b/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl new file mode 100644 index 0000000000..ed76e25147 --- /dev/null +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl @@ -0,0 +1,695 @@ +//------------------------------------------------------------------------------ +// Shader code for texcube-sapp sample. +// +// NOTE: This source file also uses the '#pragma sokol' form of the +// custom tags. +//------------------------------------------------------------------------------ +//#pragma sokol @ctype mat4 hmm_mat4 + +#pragma sokol @vs vs_m +uniform vs_params_m { + mat4 mvp; +}; + +in vec4 pos; +in vec4 color0; +in vec2 texcoord0; + +out vec4 color; +out vec2 uv; + +void main() { + gl_Position = mvp * pos; + color = color0; + uv = texcoord0; +} +#pragma sokol @end + +#pragma sokol @fs fs_m +uniform sampler2D tex; +uniform fs_params_m { + vec2 iResolution; + vec2 iMouse; + float iTime; + float iFrame; +}; + +in vec4 color; +in vec2 uv; +out vec4 frag_color; + +// change to 0 to 4 to increment the AntiAliasing, +// increase AA will SLOW the rendering!! +#define AA 1 + +//********************************************************* +// Ray Marching +// original code from: https://www.shadertoy.com/view/Xds3zN +//********************************************************* +// The MIT License +// Copyright © 2013 Inigo Quilez +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A list of useful distance function to simple primitives. All +// these functions (except for ellipsoid) return an exact +// euclidean distance, meaning they produce a better SDF than +// what you'd get if you were constructing them from boolean +// operations. +// +// More info here: +// +// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +//------------------------------------------------------------------ +float dot2( in vec2 v ) { return dot(v,v); } +float dot2( in vec3 v ) { return dot(v,v); } +float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; } + +float sdPlane( vec3 p ) +{ + return p.y; +} + +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +float sdBox( vec3 p, vec3 b ) +{ + vec3 d = abs(p) - b; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float sdBoundingBox( vec3 p, vec3 b, float e ) +{ + p = abs(p )-b; + vec3 q = abs(p+e)-e; + + return min(min( + length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0), + length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)), + length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0)); +} +float sdEllipsoid( in vec3 p, in vec3 r ) // approximated +{ + float k0 = length(p/r); + float k1 = length(p/(r*r)); + return k0*(k0-1.0)/k1; +} + +float sdTorus( vec3 p, vec2 t ) +{ + return length( vec2(length(p.xz)-t.x,p.y) )-t.y; +} + +float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb) +{ + p.x = abs(p.x); + float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy); + return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb; +} + +float sdHexPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); + + const vec3 k = vec3(-0.8660254, 0.5, 0.57735); + p = abs(p); + p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy; + vec2 d = vec2( + length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x), + p.z-h.y ); + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdOctogonPrism( in vec3 p, in float r, float h ) +{ + const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2 + 0.3826834323, // sqrt(2-sqrt(2))/2 + 0.4142135623 ); // sqrt(2)-1 + // reflections + p = abs(p); + p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y); + p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y); + // polygon side + p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r); + vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h ); + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +float sdRoundCone( in vec3 p, in float r1, float r2, float h ) +{ + vec2 q = vec2( length(p.xz), p.y ); + + float b = (r1-r2)/h; + float a = sqrt(1.0-b*b); + float k = dot(q,vec2(-b,a)); + + if( k < 0.0 ) return length(q) - r1; + if( k > a*h ) return length(q-vec2(0.0,h)) - r2; + + return dot(q, vec2(a,b) ) - r1; +} + +float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2) +{ + // sampling independent computations (only depend on shape) + vec3 ba = b - a; + float l2 = dot(ba,ba); + float rr = r1 - r2; + float a2 = l2 - rr*rr; + float il2 = 1.0/l2; + + // sampling dependant computations + vec3 pa = p - a; + float y = dot(pa,ba); + float z = y - l2; + float x2 = dot2( pa*l2 - ba*y ); + float y2 = y*y*l2; + float z2 = z*z*l2; + + // single square root! + float k = sign(rr)*rr*rr*x2; + if( sign(z)*a2*z2 > k ) return sqrt(x2 + z2) *il2 - r2; + if( sign(y)*a2*y2 < k ) return sqrt(x2 + y2) *il2 - r1; + return (sqrt(x2*a2*il2)+y*rr)*il2 - r1; +} + +float sdTriPrism( vec3 p, vec2 h ) +{ + const float k = sqrt(3.0); + h.x *= 0.5*k; + p.xy /= h.x; + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0; + p.x -= clamp( p.x, -2.0, 0.0 ); + float d1 = length(p.xy)*sign(-p.y)*h.x; + float d2 = abs(p.z)-h.y; + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +// vertical +float sdCylinder( vec3 p, vec2 h ) +{ + vec2 d = abs(vec2(length(p.xz),p.y)) - h; + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +// arbitrary orientation +float sdCylinder(vec3 p, vec3 a, vec3 b, float r) +{ + vec3 pa = p - a; + vec3 ba = b - a; + float baba = dot(ba,ba); + float paba = dot(pa,ba); + + float x = length(pa*baba-ba*paba) - r*baba; + float y = abs(paba-baba*0.5)-baba*0.5; + float x2 = x*x; + float y2 = y*y*baba; + float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0)); + return sign(d)*sqrt(abs(d))/baba; +} + +// vertical +float sdCone( in vec3 p, in vec2 c, float h ) +{ + vec2 q = h*vec2(c.x,-c.y)/c.y; + vec2 w = vec2( length(p.xz), p.y ); + + vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 ); + vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 ); + float k = sign( q.y ); + float d = min(dot( a, a ),dot(b, b)); + float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y) ); + return sqrt(d)*sign(s); +} + +float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 ) +{ + vec2 q = vec2( length(p.xz), p.y ); + + vec2 k1 = vec2(r2,h); + vec2 k2 = vec2(r2-r1,2.0*h); + vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h); + vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 ); + float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0; + return s*sqrt( min(dot2(ca),dot2(cb)) ); +} + +float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb) +{ + float rba = rb-ra; + float baba = dot(b-a,b-a); + float papa = dot(p-a,p-a); + float paba = dot(p-a,b-a)/baba; + + float x = sqrt( papa - paba*paba*baba ); + + float cax = max(0.0,x-((paba<0.5)?ra:rb)); + float cay = abs(paba-0.5)-0.5; + + float k = rba*rba + baba; + float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 ); + + float cbx = x-ra - f*rba; + float cby = paba - f; + + float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0; + + return s*sqrt( min(cax*cax + cay*cay*baba, + cbx*cbx + cby*cby*baba) ); +} + +// c is the sin/cos of the desired cone angle +float sdSolidAngle(vec3 pos, vec2 c, float ra) +{ + vec2 p = vec2( length(pos.xz), pos.y ); + float l = length(p) - ra; + float m = length(p - c*clamp(dot(p,c),0.0,ra) ); + return max(l,m*sign(c.y*p.x-c.x*p.y)); +} + +float sdOctahedron(vec3 p, float s) +{ + p = abs(p); + float m = p.x + p.y + p.z - s; + +// exact distance +#if 0 + vec3 o = min(3.0*p - m, 0.0); + o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0); + return length(p - s*o/(o.x+o.y+o.z)); +#endif + +// exact distance +#if 1 + vec3 q; + if( 3.0*p.x < m ) q = p.xyz; + else if( 3.0*p.y < m ) q = p.yzx; + else if( 3.0*p.z < m ) q = p.zxy; + else return m*0.57735027; + float k = clamp(0.5*(q.z-q.y+s),0.0,s); + return length(vec3(q.x,q.y-s+k,q.z-k)); +#endif + +// bound, not exact +#if 0 + return m*0.57735027; +#endif +} + +float sdPyramid( in vec3 p, in float h ) +{ + float m2 = h*h + 0.25; + + // symmetry + p.xz = abs(p.xz); + p.xz = (p.z>p.x) ? p.zx : p.xz; + p.xz -= 0.5; + + // project into face plane (2D) + vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y); + + float s = max(-q.x,0.0); + float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 ); + + float a = m2*(q.x+s)*(q.x+s) + q.y*q.y; + float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t); + + float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b); + + // recover 3D and scale, and add sign + return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y)); +} + +// la,lb=semi axis, h=height, ra=corner +float sdRhombus(vec3 p, float la, float lb, float h, float ra) +{ + p = abs(p); + vec2 b = vec2(la,lb); + float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 ); + vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h); + return min(max(q.x,q.y),0.0) + length(max(q,0.0)); +} + +//------------------------------------------------------------------ + +vec2 opU( vec2 d1, vec2 d2 ) +{ + return (d1.x0.0 ) + { + tmax = min( tmax, tp1 ); + res = vec2( tp1, 1.0 ); + } + //else return res; + + // raymarch primitives + vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) ); + if( tb.x0.0 && tb.x0.0 ) tmax = min( tmax, tp ); + + float res = 1.0; + float t = mint; + for( int i=ZERO; i<24; i++ ) + { + float h = map( ro + rd*t ).x; + float s = clamp(8.0*h/t,0.0,1.0); + res = min( res, s*s*(3.0-2.0*s) ); + t += clamp( h, 0.02, 0.2 ); + if( res<0.004 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm +vec3 calcNormal( in vec3 pos ) +{ +#if 0 + vec2 e = vec2(1.0,-1.0)*0.5773*0.0005; + return normalize( e.xyy*map( pos + e.xyy ).x + + e.yyx*map( pos + e.yyx ).x + + e.yxy*map( pos + e.yxy ).x + + e.xxx*map( pos + e.xxx ).x ); +#else + // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times + vec3 n = vec3(0.0); + for( int i=ZERO; i<4; i++ ) + { + vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0); + n += e*map(pos+0.0005*e).x; + //if( n.x+n.y+n.z>100.0 ) break; + } + return normalize(n); +#endif +} + +float calcAO( in vec3 pos, in vec3 nor ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=ZERO; i<5; i++ ) + { + float h = 0.01 + 0.12*float(i)/4.0; + float d = map( pos + h*nor ).x; + occ += (h-d)*sca; + sca *= 0.95; + if( occ>0.35 ) break; + } + return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y); +} + +// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm +float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy ) +{ + // filter kernel + vec2 w = abs(dpdx)+abs(dpdy) + 0.001; + // analytical integral (box filter) + vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; + // xor pattern + return 0.5 - 0.5*i.x*i.y; +} + +vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) +{ + // background + vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; + + // raycast scene + vec2 res = raycast(ro,rd); + float t = res.x; + float m = res.y; + if( m>-0.5 ) + { + vec3 pos = ro + t*rd; + vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos ); + vec3 ref = reflect( rd, nor ); + + // material + col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) ); + float ks = 1.0; + + if( m<1.5 ) + { + // project pixel footprint into the plane + vec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y); + vec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y); + + float f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz ); + col = 0.15 + f*vec3(0.05); + ks = 0.4; + } + + // lighting + float occ = calcAO( pos, nor ); + + vec3 lin = vec3(0.0); + + // sun + { + vec3 lig = normalize( vec3(-0.5, 0.4, -0.6) ); + vec3 hal = normalize( lig-rd ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + //if( dif>0.0001 ) + dif *= calcSoftshadow( pos, lig, 0.02, 2.5 ); + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0); + spe *= dif; + spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0); + lin += col*2.20*dif*vec3(1.30,1.00,0.70); + lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks; + } + // sky + { + float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 )); + dif *= occ; + float spe = smoothstep( -0.2, 0.2, ref.y ); + spe *= dif; + spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 ); + //if( spe>0.001 ) + spe *= calcSoftshadow( pos, ref, 0.02, 2.5 ); + lin += col*0.60*dif*vec3(0.40,0.60,1.15); + lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks; + } + // back + { + float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0); + dif *= occ; + lin += col*0.55*dif*vec3(0.25,0.25,0.25); + } + // sss + { + float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0); + dif *= occ; + lin += col*0.25*dif*vec3(1.00,1.00,1.00); + } + + col = lin; + + col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ); + } + + return vec3( clamp(col,0.0,1.0) ); +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = ( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +vec4 mainImage( vec2 fragCoord ) +{ + vec2 mo = iMouse.xy/iResolution.xy; + float time = 32.0 + iTime*1.5; + + // camera + vec3 ta = vec3( 0.5, -0.5, -0.6 ); + vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) ); + // camera-to-world transformation + mat3 ca = setCamera( ro, ta, 0.0 ); + + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=ZERO; m1 + } + tot /= float(AA*AA); +#endif + + //fragColor = vec4( tot, 1.0 ); + return vec4( tot, 1.0 ); +} + +//********************************************************* +// END Ray Marching +//********************************************************* + +void main() { + vec4 c = color; + vec4 txt = texture(tex, uv); + c = txt * c; + vec2 uv1 = uv * iResolution; + vec4 col_ray = mainImage(uv1); + + // use this to mix the chessboart texture with the ray marching + //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ; + + frag_color = c*0.00001 + col_ray ; +} + +#pragma sokol @end + +#pragma sokol @program rt_march vs_m fs_m diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl b/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl new file mode 100644 index 0000000000..bea60d595f --- /dev/null +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl @@ -0,0 +1,568 @@ +//------------------------------------------------------------------------------ +// Shader code for texcube-sapp sample. +// +// NOTE: This source file also uses the '#pragma sokol' form of the +// custom tags. +//------------------------------------------------------------------------------ +//#pragma sokol @ctype mat4 hmm_mat4 + +#pragma sokol @vs vs_p +uniform vs_params_p { + mat4 mvp; +}; + +in vec4 pos; +in vec4 color0; +in vec2 texcoord0; + +out vec4 color; +out vec2 uv; + +void main() { + gl_Position = mvp * pos; + color = color0; + uv = texcoord0; +} +#pragma sokol @end + +#pragma sokol @fs fs_p +uniform sampler2D tex; +uniform fs_params_p { + vec2 iResolution; + vec2 iMouse; + float iTime; + float iFrame; +}; + +in vec4 color; +in vec2 uv; +out vec4 frag_color; + +// change to 0 to 4 to increment the AntiAliasing, +// increase AA will SLOW the rendering!! +#define AA 1 + +//********************************************************* +// Ray Marching +// original code from: https://www.shadertoy.com/view/Xds3zN +//********************************************************* +// Created by inigo quilez - iq/2019 +// I share this piece (art and code) here in Shadertoy and through its Public API, only for educational purposes. +// You cannot use, share or host this piece or modifications of it as part of your own commercial or non-commercial product, website or project. +// You can share a link to it or an unmodified screenshot of it provided you attribute "by Inigo Quilez, @iquilezles and iquilezles.org". +// If you are a teacher, lecturer, educator or similar and these conditions are too restrictive for your needs, please contact me and we'll work it out. + + +// An animation test - a happy and blobby creature +// jumping and looking around. It gets off-model very +// often, but it looks good enough I think. +// +// Making-of with math/shader/art explanations (6 hours +// long): https://www.youtube.com/watch?v=Cfe5UQ-1L9Q +// +// Video capture: https://www.youtube.com/watch?v=s_UOFo2IULQ +// +// Buy a metal print here: https://www.redbubble.com/i/metal-print/Happy-Jumping-by-InigoQuilez/43594745.0JXQP + +//------------------------------------------------------------------ + + +// http://iquilezles.org/www/articles/smin/smin.htm +float smin( float a, float b, float k ) +{ + float h = max(k-abs(a-b),0.0); + return min(a, b) - h*h*0.25/k; +} + +// http://iquilezles.org/www/articles/smin/smin.htm +vec2 smin( vec2 a, vec2 b, float k ) +{ + float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 ); + return mix( b, a, h ) - k*h*(1.0-h); +} + +// http://iquilezles.org/www/articles/smin/smin.htm +float smax( float a, float b, float k ) +{ + float h = max(k-abs(a-b),0.0); + return max(a, b) + h*h*0.25/k; +} + +// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +float sdEllipsoid( in vec3 p, in vec3 r ) // approximated +{ + float k0 = length(p/r); + float k1 = length(p/(r*r)); + return k0*(k0-1.0)/k1; +} + +vec2 sdStick(vec3 p, vec3 a, vec3 b, float r1, float r2) // approximated +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return vec2( length( pa - ba*h ) - mix(r1,r2,h*h*(3.0-2.0*h)), h ); +} + +// http://iquilezles.org/www/articles/smin/smin.htm +vec4 opU( vec4 d1, vec4 d2 ) +{ + return (d1.x0.0 ) tmax = min( tmax, tp ); + #endif + + // raymarch scene + float t = tmin; + for( int i=0; i<256 && t0.0 ) tmax = min( tmax, tp ); + #endif + + float t = 0.02; + for( int i=0; i<50; i++ ) + { + float h = map( ro + rd*t, time ).x; + res = min( res, mix(1.0,16.0*h/t, hsha) ); + t += clamp( h, 0.05, 0.40 ); + if( res<0.005 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm +vec3 calcNormal( in vec3 pos, float time ) +{ + +#if 0 + vec2 e = vec2(1.0,-1.0)*0.5773*0.001; + return normalize( e.xyy*map( pos + e.xyy, time ).x + + e.yyx*map( pos + e.yyx, time ).x + + e.yxy*map( pos + e.yxy, time ).x + + e.xxx*map( pos + e.xxx, time ).x ); +#else + // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times + vec3 n = vec3(0.0); + for( int i=ZERO; i<4; i++ ) + { + vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0); + n += e*map(pos+0.001*e,time).x; + } + return normalize(n); +#endif +} + +float calcOcclusion( in vec3 pos, in vec3 nor, float time ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=ZERO; i<5; i++ ) + { + float h = 0.01 + 0.11*float(i)/4.0; + vec3 opos = pos + h*nor; + float d = map( opos, time ).x; + occ += (h-d)*sca; + sca *= 0.95; + } + return clamp( 1.0 - 2.0*occ, 0.0, 1.0 ); +} + +vec3 render( in vec3 ro, in vec3 rd, float time ) +{ + // sky dome + vec3 col = vec3(0.5, 0.8, 0.9) - max(rd.y,0.0)*0.5; + // sky clouds + vec2 uv = 1.5*rd.xz/rd.y; + float cl = 1.0*(sin(uv.x)+sin(uv.y)); uv *= mat2(0.8,0.6,-0.6,0.8)*2.1; + cl += 0.5*(sin(uv.x)+sin(uv.y)); + col += 0.1*(-1.0+2.0*smoothstep(-0.1,0.1,cl-0.4)); + // sky horizon + col = mix( col, vec3(0.5, 0.7, .9), exp(-10.0*max(rd.y,0.0)) ); + + + // scene geometry + vec4 res = raycast(ro,rd, time); + if( res.y>-0.5 ) + { + float t = res.x; + vec3 pos = ro + t*rd; + vec3 nor = calcNormal( pos, time ); + vec3 ref = reflect( rd, nor ); + float focc = res.w; + + // material + col = vec3(0.2); + float ks = 1.0; + + if( res.y>4.5 ) // candy + { + col = vec3(0.14,0.048,0.0); + vec2 id = floor(5.0*pos.xz+0.5); + col += 0.036*cos((id.x*11.1+id.y*37.341) + vec3(0.0,1.0,2.0) ); + col = max(col,0.0); + focc = clamp(4.0*res.z,0.0,1.0); + } + else if( res.y>3.5 ) // eyeball + { + col = vec3(0.0); + } + else if( res.y>2.5 ) // iris + { + col = vec3(0.4); + } + else if( res.y>1.5 ) // body + { + col = mix(vec3(0.144,0.09,0.0036),vec3(0.36,0.1,0.04),res.z*res.z); + col = mix(col,vec3(0.14,0.09,0.06)*2.0, (1.0-res.z)*smoothstep(-0.15, 0.15, -href)); + } + else // terrain + { + // base green + col = vec3(0.05,0.09,0.02); + float f = 0.2*(-1.0+2.0*smoothstep(-0.2,0.2,sin(18.0*pos.x)+sin(18.0*pos.y)+sin(18.0*pos.z))); + col += f*vec3(0.06,0.06,0.02); + ks = 0.5 + pos.y*0.15; + + // footprints + vec2 mp = vec2(pos.x-0.5*(mod(floor(pos.z+0.5),2.0)*2.0-1.0), fract(pos.z+0.5)-0.5 ); + float mark = 1.0-smoothstep(0.1, 0.5, length(mp)); + mark *= smoothstep(0.0, 0.1, floor(time) - floor(pos.z+0.5) ); + col *= mix( vec3(1.0), vec3(0.5,0.5,0.4), mark ); + ks *= 1.0-0.5*mark; + } + + // lighting (sun, sky, bounce, back, sss) + float occ = calcOcclusion( pos, nor, time )*focc; + float fre = clamp(1.0+dot(nor,rd),0.0,1.0); + + vec3 sun_lig = normalize( vec3(0.6, 0.35, 0.5) ); + float sun_dif = clamp(dot( nor, sun_lig ), 0.0, 1.0 ); + vec3 sun_hal = normalize( sun_lig-rd ); + float sun_sha = calcSoftshadow( pos, sun_lig, time ); + float sun_spe = ks*pow(clamp(dot(nor,sun_hal),0.0,1.0),8.0)*sun_dif*(0.04+0.96*pow(clamp(1.0+dot(sun_hal,rd),0.0,1.0),5.0)); + float sky_dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 )); + float sky_spe = ks*smoothstep( 0.0, 0.5, ref.y )*(0.04+0.96*pow(fre,4.0)); + float bou_dif = sqrt(clamp( 0.1-0.9*nor.y, 0.0, 1.0 ))*clamp(1.0-0.1*pos.y,0.0,1.0); + float bac_dif = clamp(0.1+0.9*dot( nor, normalize(vec3(-sun_lig.x,0.0,-sun_lig.z))), 0.0, 1.0 ); + float sss_dif = fre*sky_dif*(0.25+0.75*sun_dif*sun_sha); + + vec3 lin = vec3(0.0); + lin += sun_dif*vec3(8.10,6.00,4.20)*vec3(sun_sha,sun_sha*sun_sha*0.5+0.5*sun_sha,sun_sha*sun_sha); + lin += sky_dif*vec3(0.50,0.70,1.00)*occ; + lin += bou_dif*vec3(0.20,0.70,0.10)*occ; + lin += bac_dif*vec3(0.45,0.35,0.25)*occ; + lin += sss_dif*vec3(3.25,2.75,2.50)*occ; + col = col*lin; + col += sun_spe*vec3(9.90,8.10,6.30)*sun_sha; + col += sky_spe*vec3(0.20,0.30,0.65)*occ*occ; + + col = pow(col,vec3(0.8,0.9,1.0) ); + + // fog + col = mix( col, vec3(0.5,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ); + } + + return col; +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = ( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +//void mainImage( out vec4 fragColor, in vec2 fragCoord ) +vec4 mainImage( vec2 fragCoord ) +{ + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=ZERO; m1 + } + tot /= float(AA*AA); +#endif + + // s-surve + tot = clamp(tot,0.0,1.0); + tot = tot*tot*(3.0-2.0*tot); + + // vignetting + vec2 q = fragCoord/iResolution.xy; + tot *= 0.5 + 0.5*pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.25); + + // output + //fragColor = vec4( tot, 1.0 ); + return vec4( tot, 1.0 ); +} + +//********************************************************* +// END Ray Marching +//********************************************************* + +void main() { + vec4 c = color; + vec4 txt = texture(tex, uv); + c = txt * c; + vec2 uv1 = uv * iResolution; + vec4 col_ray = mainImage(uv1); + + // use this to mix the chessboart texture with the ray marching + //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ; + + frag_color = c*0.00001 + col_ray ; +} + +#pragma sokol @end + +#pragma sokol @program rt_puppy vs_p fs_p diff --git a/examples/sokol/04_multi_shader_glsl/v.mod b/examples/sokol/04_multi_shader_glsl/v.mod new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/sokol/rt_glsl/HandmadeMath.h b/examples/sokol/rt_glsl/HandmadeMath.h deleted file mode 100644 index a33e0ef715..0000000000 --- a/examples/sokol/rt_glsl/HandmadeMath.h +++ /dev/null @@ -1,3240 +0,0 @@ -/* - HandmadeMath.h v1.11.0 - - This is a single header file with a bunch of useful functions for game and - graphics math operations. - - ============================================================================= - - You MUST - - #define HANDMADE_MATH_IMPLEMENTATION - - in EXACTLY one C or C++ file that includes this header, BEFORE the - include, like this: - - #define HANDMADE_MATH_IMPLEMENTATION - #include "HandmadeMath.h" - - All other files should just #include "HandmadeMath.h" without the #define. - - ============================================================================= - - To disable SSE intrinsics, you MUST - - #define HANDMADE_MATH_NO_SSE - - in EXACTLY one C or C++ file that includes this header, BEFORE the - include, like this: - - #define HANDMADE_MATH_IMPLEMENTATION - #define HANDMADE_MATH_NO_SSE - #include "HandmadeMath.h" - - ============================================================================= - - If you would prefer not to use the HMM_ prefix on function names, you can - - #define HMM_PREFIX - - To use a custom prefix instead, you can - - #define HMM_PREFIX(name) YOUR_PREFIX_##name - - ============================================================================= - - To use HandmadeMath without the CRT, you MUST - - #define HMM_SINF MySinF - #define HMM_COSF MyCosF - #define HMM_TANF MyTanF - #define HMM_SQRTF MySqrtF - #define HMM_EXPF MyExpF - #define HMM_LOGF MyLogF - #define HMM_ACOSF MyACosF - #define HMM_ATANF MyATanF - #define HMM_ATAN2F MYATan2F - - Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, - ExpF, and LogF in EXACTLY one C or C++ file that includes this header, - BEFORE the include, like this: - - #define HMM_SINF MySinF - #define HMM_COSF MyCosF - #define HMM_TANF MyTanF - #define HMM_SQRTF MySqrtF - #define HMM_EXPF MyExpF - #define HMM_LOGF MyLogF - #define HMM_ACOSF MyACosF - #define HMM_ATANF MyATanF - #define HMM_ATAN2F MyATan2F - #define HANDMADE_MATH_IMPLEMENTATION - #include "HandmadeMath.h" - - If you do not define all of these, HandmadeMath.h will use the - versions of these functions that are provided by the CRT. - - ============================================================================= - - LICENSE - - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy, - distribute, and modify this file as you see fit. - - CREDITS - - Written by Zakary Strange (strangezak@gmail.com && @strangezak) - - Functionality: - Matt Mascarenhas (@miblo_) - Aleph - FieryDrake (@fierydrake) - Gingerbill (@TheGingerBill) - Ben Visness (@bvisness) - Trinton Bullard (@Peliex_Dev) - @AntonDan - - Fixes: - Jeroen van Rijn (@J_vanRijn) - Kiljacken (@Kiljacken) - Insofaras (@insofaras) - Daniel Gibson (@DanielGibson) -*/ - -// Dummy macros for when test framework is not present. -#ifndef COVERAGE -#define COVERAGE(a, b) -#endif - -#ifndef ASSERT_COVERED -#define ASSERT_COVERED(a) -#endif - -/* let's figure out if SSE is really available (unless disabled anyway) - (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) - => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */ -#ifndef HANDMADE_MATH_NO_SSE - -# ifdef _MSC_VER - /* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */ -# if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 ) -# define HANDMADE_MATH__USE_SSE 1 -# endif -# else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */ -# ifdef __SSE__ /* they #define __SSE__ if it's supported */ -# define HANDMADE_MATH__USE_SSE 1 -# endif /* __SSE__ */ -# endif /* not _MSC_VER */ - -#endif /* #ifndef HANDMADE_MATH_NO_SSE */ - -#ifdef HANDMADE_MATH__USE_SSE -#include -#endif - -#ifndef HANDMADE_MATH_H -#define HANDMADE_MATH_H - -#ifdef _MSC_VER -#pragma warning(disable:4201) -#endif - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8) -#pragma GCC diagnostic ignored "-Wmissing-braces" -#endif -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" -#endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -#define HMM_DEPRECATED(msg) __attribute__((deprecated(msg))) -#elif defined(_MSC_VER) -#define HMM_DEPRECATED(msg) __declspec(deprecated(msg)) -#else -#define HMM_DEPRECATED(msg) -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define HMM_INLINE static inline -#define HMM_EXTERN extern - -#if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ - !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ - !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) -#include -#endif - -#ifndef HMM_SINF -#define HMM_SINF sinf -#endif - -#ifndef HMM_COSF -#define HMM_COSF cosf -#endif - -#ifndef HMM_TANF -#define HMM_TANF tanf -#endif - -#ifndef HMM_SQRTF -#define HMM_SQRTF sqrtf -#endif - -#ifndef HMM_EXPF -#define HMM_EXPF expf -#endif - -#ifndef HMM_LOGF -#define HMM_LOGF logf -#endif - -#ifndef HMM_ACOSF -#define HMM_ACOSF acosf -#endif - -#ifndef HMM_ATANF -#define HMM_ATANF atanf -#endif - -#ifndef HMM_ATAN2F -#define HMM_ATAN2F atan2f -#endif - -#define HMM_PI32 3.14159265359f -#define HMM_PI 3.14159265358979323846 - -#define HMM_MIN(a, b) (a) > (b) ? (b) : (a) -#define HMM_MAX(a, b) (a) < (b) ? (b) : (a) -#define HMM_ABS(a) ((a) > 0 ? (a) : -(a)) -#define HMM_MOD(a, m) ((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)) -#define HMM_SQUARE(x) ((x) * (x)) - -#ifndef HMM_PREFIX -#define HMM_PREFIX(name) HMM_##name -#endif - -typedef union hmm_vec2 -{ - struct - { - float X, Y; - }; - - struct - { - float U, V; - }; - - struct - { - float Left, Right; - }; - - struct - { - float Width, Height; - }; - - float Elements[2]; - -#ifdef __cplusplus - inline float &operator[](const int &Index) - { - return Elements[Index]; - } -#endif -} hmm_vec2; - -typedef union hmm_vec3 -{ - struct - { - float X, Y, Z; - }; - - struct - { - float U, V, W; - }; - - struct - { - float R, G, B; - }; - - struct - { - hmm_vec2 XY; - float Ignored0_; - }; - - struct - { - float Ignored1_; - hmm_vec2 YZ; - }; - - struct - { - hmm_vec2 UV; - float Ignored2_; - }; - - struct - { - float Ignored3_; - hmm_vec2 VW; - }; - - float Elements[3]; - -#ifdef __cplusplus - inline float &operator[](const int &Index) - { - return Elements[Index]; - } -#endif -} hmm_vec3; - -typedef union hmm_vec4 -{ - struct - { - union - { - hmm_vec3 XYZ; - struct - { - float X, Y, Z; - }; - }; - - float W; - }; - struct - { - union - { - hmm_vec3 RGB; - struct - { - float R, G, B; - }; - }; - - float A; - }; - - struct - { - hmm_vec2 XY; - float Ignored0_; - float Ignored1_; - }; - - struct - { - float Ignored2_; - hmm_vec2 YZ; - float Ignored3_; - }; - - struct - { - float Ignored4_; - float Ignored5_; - hmm_vec2 ZW; - }; - - float Elements[4]; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 InternalElementsSSE; -#endif - -#ifdef __cplusplus - inline float &operator[](const int &Index) - { - return Elements[Index]; - } -#endif -} hmm_vec4; - -typedef union hmm_mat4 -{ - float Elements[4][4]; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Columns[4]; - - HMM_DEPRECATED("Our matrices are column-major, so this was named incorrectly. Use Columns instead.") - __m128 Rows[4]; -#endif - -#ifdef __cplusplus - inline hmm_vec4 operator[](const int &Index) - { - float* col = Elements[Index]; - - hmm_vec4 result; - result.Elements[0] = col[0]; - result.Elements[1] = col[1]; - result.Elements[2] = col[2]; - result.Elements[3] = col[3]; - - return result; - } -#endif -} hmm_mat4; - -typedef union hmm_quaternion -{ - struct - { - union - { - hmm_vec3 XYZ; - struct - { - float X, Y, Z; - }; - }; - - float W; - }; - - float Elements[4]; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 InternalElementsSSE; -#endif -} hmm_quaternion; - -typedef signed int hmm_bool; - -typedef hmm_vec2 hmm_v2; -typedef hmm_vec3 hmm_v3; -typedef hmm_vec4 hmm_v4; -typedef hmm_mat4 hmm_m4; - - -/* - * Floating-point math functions - */ - -COVERAGE(HMM_SinF, 1) -HMM_INLINE float HMM_PREFIX(SinF)(float Radians) -{ - ASSERT_COVERED(HMM_SinF); - - float Result = HMM_SINF(Radians); - - return (Result); -} - -COVERAGE(HMM_CosF, 1) -HMM_INLINE float HMM_PREFIX(CosF)(float Radians) -{ - ASSERT_COVERED(HMM_CosF); - - float Result = HMM_COSF(Radians); - - return (Result); -} - -COVERAGE(HMM_TanF, 1) -HMM_INLINE float HMM_PREFIX(TanF)(float Radians) -{ - ASSERT_COVERED(HMM_TanF); - - float Result = HMM_TANF(Radians); - - return (Result); -} - -COVERAGE(HMM_ACosF, 1) -HMM_INLINE float HMM_PREFIX(ACosF)(float Radians) -{ - ASSERT_COVERED(HMM_ACosF); - - float Result = HMM_ACOSF(Radians); - - return (Result); -} - -COVERAGE(HMM_ATanF, 1) -HMM_INLINE float HMM_PREFIX(ATanF)(float Radians) -{ - ASSERT_COVERED(HMM_ATanF); - - float Result = HMM_ATANF(Radians); - - return (Result); -} - -COVERAGE(HMM_ATan2F, 1) -HMM_INLINE float HMM_PREFIX(ATan2F)(float Left, float Right) -{ - ASSERT_COVERED(HMM_ATan2F); - - float Result = HMM_ATAN2F(Left, Right); - - return (Result); -} - -COVERAGE(HMM_ExpF, 1) -HMM_INLINE float HMM_PREFIX(ExpF)(float Float) -{ - ASSERT_COVERED(HMM_ExpF); - - float Result = HMM_EXPF(Float); - - return (Result); -} - -COVERAGE(HMM_LogF, 1) -HMM_INLINE float HMM_PREFIX(LogF)(float Float) -{ - ASSERT_COVERED(HMM_LogF); - - float Result = HMM_LOGF(Float); - - return (Result); -} - -COVERAGE(HMM_SquareRootF, 1) -HMM_INLINE float HMM_PREFIX(SquareRootF)(float Float) -{ - ASSERT_COVERED(HMM_SquareRootF); - - float Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 In = _mm_set_ss(Float); - __m128 Out = _mm_sqrt_ss(In); - Result = _mm_cvtss_f32(Out); -#else - Result = HMM_SQRTF(Float); -#endif - - return(Result); -} - -COVERAGE(HMM_RSquareRootF, 1) -HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float) -{ - ASSERT_COVERED(HMM_RSquareRootF); - - float Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 In = _mm_set_ss(Float); - __m128 Out = _mm_rsqrt_ss(In); - Result = _mm_cvtss_f32(Out); -#else - Result = 1.0f/HMM_PREFIX(SquareRootF)(Float); -#endif - - return(Result); -} - -HMM_EXTERN float HMM_PREFIX(Power)(float Base, int Exponent); - -COVERAGE(HMM_PowerF, 1) -HMM_INLINE float HMM_PREFIX(PowerF)(float Base, float Exponent) -{ - ASSERT_COVERED(HMM_PowerF); - - float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); - - return (Result); -} - - -/* - * Utility functions - */ - -COVERAGE(HMM_ToRadians, 1) -HMM_INLINE float HMM_PREFIX(ToRadians)(float Degrees) -{ - ASSERT_COVERED(HMM_ToRadians); - - float Result = Degrees * (HMM_PI32 / 180.0f); - - return (Result); -} - -COVERAGE(HMM_Lerp, 1) -HMM_INLINE float HMM_PREFIX(Lerp)(float A, float Time, float B) -{ - ASSERT_COVERED(HMM_Lerp); - - float Result = (1.0f - Time) * A + Time * B; - - return (Result); -} - -COVERAGE(HMM_Clamp, 1) -HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max) -{ - ASSERT_COVERED(HMM_Clamp); - - float Result = Value; - - if(Result < Min) - { - Result = Min; - } - - if(Result > Max) - { - Result = Max; - } - - return (Result); -} - - -/* - * Vector initialization - */ - -COVERAGE(HMM_Vec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2)(float X, float Y) -{ - ASSERT_COVERED(HMM_Vec2); - - hmm_vec2 Result; - - Result.X = X; - Result.Y = Y; - - return (Result); -} - -COVERAGE(HMM_Vec2i, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2i)(int X, int Y) -{ - ASSERT_COVERED(HMM_Vec2i); - - hmm_vec2 Result; - - Result.X = (float)X; - Result.Y = (float)Y; - - return (Result); -} - -COVERAGE(HMM_Vec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3)(float X, float Y, float Z) -{ - ASSERT_COVERED(HMM_Vec3); - - hmm_vec3 Result; - - Result.X = X; - Result.Y = Y; - Result.Z = Z; - - return (Result); -} - -COVERAGE(HMM_Vec3i, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3i)(int X, int Y, int Z) -{ - ASSERT_COVERED(HMM_Vec3i); - - hmm_vec3 Result; - - Result.X = (float)X; - Result.Y = (float)Y; - Result.Z = (float)Z; - - return (Result); -} - -COVERAGE(HMM_Vec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4)(float X, float Y, float Z, float W) -{ - ASSERT_COVERED(HMM_Vec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); -#else - Result.X = X; - Result.Y = Y; - Result.Z = Z; - Result.W = W; -#endif - - return (Result); -} - -COVERAGE(HMM_Vec4i, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4i)(int X, int Y, int Z, int W) -{ - ASSERT_COVERED(HMM_Vec4i); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps((float)X, (float)Y, (float)Z, (float)W); -#else - Result.X = (float)X; - Result.Y = (float)Y; - Result.Z = (float)Z; - Result.W = (float)W; -#endif - - return (Result); -} - -COVERAGE(HMM_Vec4v, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4v)(hmm_vec3 Vector, float W) -{ - ASSERT_COVERED(HMM_Vec4v); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); -#else - Result.XYZ = Vector; - Result.W = W; -#endif - - return (Result); -} - - -/* - * Binary vector operations - */ - -COVERAGE(HMM_AddVec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(AddVec2)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_AddVec2); - - hmm_vec2 Result; - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - - return (Result); -} - -COVERAGE(HMM_AddVec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(AddVec3)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_AddVec3); - - hmm_vec3 Result; - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - - return (Result); -} - -COVERAGE(HMM_AddVec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(AddVec4)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_AddVec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - Result.W = Left.W + Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_SubtractVec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(SubtractVec2)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_SubtractVec2); - - hmm_vec2 Result; - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - - return (Result); -} - -COVERAGE(HMM_SubtractVec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(SubtractVec3)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_SubtractVec3); - - hmm_vec3 Result; - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - - return (Result); -} - -COVERAGE(HMM_SubtractVec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(SubtractVec4)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_SubtractVec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - Result.W = Left.W - Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2); - - hmm_vec2 Result; - - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2f, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2f)(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2f); - - hmm_vec2 Result; - - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3); - - hmm_vec3 Result; - - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - Result.Z = Left.Z * Right.Z; - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3f, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3f)(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3f); - - hmm_vec3 Result; - - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - Result.Z = Left.Z * Right; - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - Result.Z = Left.Z * Right.Z; - Result.W = Left.W * Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4f, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4f)(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4f); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Right); - Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - Result.Z = Left.Z * Right; - Result.W = Left.W * Right; -#endif - - return (Result); -} - -COVERAGE(HMM_DivideVec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_DivideVec2); - - hmm_vec2 Result; - - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - - return (Result); -} - -COVERAGE(HMM_DivideVec2f, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2f)(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec2f); - - hmm_vec2 Result; - - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - - return (Result); -} - -COVERAGE(HMM_DivideVec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_DivideVec3); - - hmm_vec3 Result; - - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - Result.Z = Left.Z / Right.Z; - - return (Result); -} - -COVERAGE(HMM_DivideVec3f, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3f)(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec3f); - - hmm_vec3 Result; - - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - Result.Z = Left.Z / Right; - - return (Result); -} - -COVERAGE(HMM_DivideVec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_DivideVec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - Result.Z = Left.Z / Right.Z; - Result.W = Left.W / Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_DivideVec4f, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4f)(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec4f); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Right); - Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - Result.Z = Left.Z / Right; - Result.W = Left.W / Right; -#endif - - return (Result); -} - -COVERAGE(HMM_EqualsVec2, 1) -HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec2)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_EqualsVec2); - - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); - - return (Result); -} - -COVERAGE(HMM_EqualsVec3, 1) -HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec3)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_EqualsVec3); - - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); - - return (Result); -} - -COVERAGE(HMM_EqualsVec4, 1) -HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec4)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_EqualsVec4); - - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); - - return (Result); -} - -COVERAGE(HMM_DotVec2, 1) -HMM_INLINE float HMM_PREFIX(DotVec2)(hmm_vec2 VecOne, hmm_vec2 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec2); - - float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); - - return (Result); -} - -COVERAGE(HMM_DotVec3, 1) -HMM_INLINE float HMM_PREFIX(DotVec3)(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec3); - - float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); - - return (Result); -} - -COVERAGE(HMM_DotVec4, 1) -HMM_INLINE float HMM_PREFIX(DotVec4)(hmm_vec4 VecOne, hmm_vec4 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec4); - - float Result; - - // NOTE(zak): IN the future if we wanna check what version SSE is support - // we can use _mm_dp_ps (4.3) but for now we will use the old way. - // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); - __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - _mm_store_ss(&Result, SSEResultOne); -#else - Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); -#endif - - return (Result); -} - -COVERAGE(HMM_Cross, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Cross)(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - ASSERT_COVERED(HMM_Cross); - - hmm_vec3 Result; - - Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); - Result.Y = (VecOne.Z * VecTwo.X) - (VecOne.X * VecTwo.Z); - Result.Z = (VecOne.X * VecTwo.Y) - (VecOne.Y * VecTwo.X); - - return (Result); -} - - -/* - * Unary vector operations - */ - -COVERAGE(HMM_LengthSquaredVec2, 1) -HMM_INLINE float HMM_PREFIX(LengthSquaredVec2)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec2); - - float Result = HMM_PREFIX(DotVec2)(A, A); - - return (Result); -} - -COVERAGE(HMM_LengthSquaredVec3, 1) -HMM_INLINE float HMM_PREFIX(LengthSquaredVec3)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec3); - - float Result = HMM_PREFIX(DotVec3)(A, A); - - return (Result); -} - -COVERAGE(HMM_LengthSquaredVec4, 1) -HMM_INLINE float HMM_PREFIX(LengthSquaredVec4)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec4); - - float Result = HMM_PREFIX(DotVec4)(A, A); - - return (Result); -} - -COVERAGE(HMM_LengthVec2, 1) -HMM_INLINE float HMM_PREFIX(LengthVec2)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_LengthVec2); - - float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec2)(A)); - - return (Result); -} - -COVERAGE(HMM_LengthVec3, 1) -HMM_INLINE float HMM_PREFIX(LengthVec3)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_LengthVec3); - - float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec3)(A)); - - return (Result); -} - -COVERAGE(HMM_LengthVec4, 1) -HMM_INLINE float HMM_PREFIX(LengthVec4)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_LengthVec4); - - float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec4)(A)); - - return(Result); -} - -COVERAGE(HMM_NormalizeVec2, 2) -HMM_INLINE hmm_vec2 HMM_PREFIX(NormalizeVec2)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_NormalizeVec2); - - hmm_vec2 Result = {0}; - - float VectorLength = HMM_PREFIX(LengthVec2)(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - ASSERT_COVERED(HMM_NormalizeVec2); - - Result.X = A.X * (1.0f / VectorLength); - Result.Y = A.Y * (1.0f / VectorLength); - } - - return (Result); -} - -COVERAGE(HMM_NormalizeVec3, 2) -HMM_INLINE hmm_vec3 HMM_PREFIX(NormalizeVec3)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_NormalizeVec3); - - hmm_vec3 Result = {0}; - - float VectorLength = HMM_PREFIX(LengthVec3)(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - ASSERT_COVERED(HMM_NormalizeVec3); - - Result.X = A.X * (1.0f / VectorLength); - Result.Y = A.Y * (1.0f / VectorLength); - Result.Z = A.Z * (1.0f / VectorLength); - } - - return (Result); -} - -COVERAGE(HMM_NormalizeVec4, 2) -HMM_INLINE hmm_vec4 HMM_PREFIX(NormalizeVec4)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_NormalizeVec4); - - hmm_vec4 Result = {0}; - - float VectorLength = HMM_PREFIX(LengthVec4)(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - ASSERT_COVERED(HMM_NormalizeVec4); - - float Multiplier = 1.0f / VectorLength; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEMultiplier = _mm_set1_ps(Multiplier); - Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); -#else - Result.X = A.X * Multiplier; - Result.Y = A.Y * Multiplier; - Result.Z = A.Z * Multiplier; - Result.W = A.W * Multiplier; -#endif - } - - return (Result); -} - -COVERAGE(HMM_FastNormalizeVec2, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalizeVec2)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec2); - - return HMM_PREFIX(MultiplyVec2f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec2)(A, A))); -} - -COVERAGE(HMM_FastNormalizeVec3, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalizeVec3)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec3); - - return HMM_PREFIX(MultiplyVec3f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec3)(A, A))); -} - -COVERAGE(HMM_FastNormalizeVec4, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalizeVec4)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec4); - - return HMM_PREFIX(MultiplyVec4f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec4)(A, A))); -} - - -/* - * SSE stuff - */ - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_LinearCombineSSE, 1) -HMM_INLINE __m128 HMM_PREFIX(LinearCombineSSE)(__m128 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_LinearCombineSSE); - - __m128 Result; - Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Columns[0]); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Columns[1])); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Columns[2])); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Columns[3])); - - return (Result); -} -#endif - - -/* - * Matrix functions - */ - -COVERAGE(HMM_Mat4, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4)(void) -{ - ASSERT_COVERED(HMM_Mat4); - - hmm_mat4 Result = {0}; - - return (Result); -} - -COVERAGE(HMM_Mat4d, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4d)(float Diagonal) -{ - ASSERT_COVERED(HMM_Mat4d); - - hmm_mat4 Result = HMM_PREFIX(Mat4)(); - - Result.Elements[0][0] = Diagonal; - Result.Elements[1][1] = Diagonal; - Result.Elements[2][2] = Diagonal; - Result.Elements[3][3] = Diagonal; - - return (Result); -} - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_Transpose, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) -{ - ASSERT_COVERED(HMM_Transpose); - - hmm_mat4 Result = Matrix; - - _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix); -#endif - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_AddMat4, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_AddMat4); - - hmm_mat4 Result; - - Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]); - Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]); - Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]); - Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right); -#endif - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_SubtractMat4, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_SubtractMat4); - - hmm_mat4 Result; - - Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]); - Result.Columns[1] = _mm_sub_ps(Left.Columns[1], Right.Columns[1]); - Result.Columns[2] = _mm_sub_ps(Left.Columns[2], Right.Columns[2]); - Result.Columns[3] = _mm_sub_ps(Left.Columns[3], Right.Columns[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right); -#endif - -HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right); - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_MultiplyMat4f, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) -{ - ASSERT_COVERED(HMM_MultiplyMat4f); - - hmm_mat4 Result; - - __m128 SSEScalar = _mm_set1_ps(Scalar); - Result.Columns[0] = _mm_mul_ps(Matrix.Columns[0], SSEScalar); - Result.Columns[1] = _mm_mul_ps(Matrix.Columns[1], SSEScalar); - Result.Columns[2] = _mm_mul_ps(Matrix.Columns[2], SSEScalar); - Result.Columns[3] = _mm_mul_ps(Matrix.Columns[3], SSEScalar); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar); -#endif - -HMM_EXTERN hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector); - -#ifdef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_DivideMat4f, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) -{ - ASSERT_COVERED(HMM_DivideMat4f); - - hmm_mat4 Result; - - __m128 SSEScalar = _mm_set1_ps(Scalar); - Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar); - Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar); - Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar); - Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar); -#endif - - -/* - * Common graphics transformations - */ - -COVERAGE(HMM_Orthographic, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Orthographic)(float Left, float Right, float Bottom, float Top, float Near, float Far) -{ - ASSERT_COVERED(HMM_Orthographic); - - hmm_mat4 Result = HMM_PREFIX(Mat4)(); - - Result.Elements[0][0] = 2.0f / (Right - Left); - Result.Elements[1][1] = 2.0f / (Top - Bottom); - Result.Elements[2][2] = 2.0f / (Near - Far); - Result.Elements[3][3] = 1.0f; - - Result.Elements[3][0] = (Left + Right) / (Left - Right); - Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top); - Result.Elements[3][2] = (Far + Near) / (Near - Far); - - return (Result); -} - -COVERAGE(HMM_Perspective, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Perspective)(float FOV, float AspectRatio, float Near, float Far) -{ - ASSERT_COVERED(HMM_Perspective); - - hmm_mat4 Result = HMM_PREFIX(Mat4)(); - - // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml - - float Cotangent = 1.0f / HMM_PREFIX(TanF)(FOV * (HMM_PI32 / 360.0f)); - - Result.Elements[0][0] = Cotangent / AspectRatio; - Result.Elements[1][1] = Cotangent; - Result.Elements[2][3] = -1.0f; - Result.Elements[2][2] = (Near + Far) / (Near - Far); - Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far); - Result.Elements[3][3] = 0.0f; - - return (Result); -} - -COVERAGE(HMM_Translate, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation) -{ - ASSERT_COVERED(HMM_Translate); - - hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); - - Result.Elements[3][0] = Translation.X; - Result.Elements[3][1] = Translation.Y; - Result.Elements[3][2] = Translation.Z; - - return (Result); -} - -HMM_EXTERN hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis); - -COVERAGE(HMM_Scale, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale) -{ - ASSERT_COVERED(HMM_Scale); - - hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); - - Result.Elements[0][0] = Scale.X; - Result.Elements[1][1] = Scale.Y; - Result.Elements[2][2] = Scale.Z; - - return (Result); -} - -HMM_EXTERN hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up); - - -/* - * Quaternion operations - */ - -COVERAGE(HMM_Quaternion, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Quaternion)(float X, float Y, float Z, float W) -{ - ASSERT_COVERED(HMM_Quaternion); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); -#else - Result.X = X; - Result.Y = Y; - Result.Z = Z; - Result.W = W; -#endif - - return (Result); -} - -COVERAGE(HMM_QuaternionV4, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionV4)(hmm_vec4 Vector) -{ - ASSERT_COVERED(HMM_QuaternionV4); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = Vector.InternalElementsSSE; -#else - Result.X = Vector.X; - Result.Y = Vector.Y; - Result.Z = Vector.Z; - Result.W = Vector.W; -#endif - - return (Result); -} - -COVERAGE(HMM_AddQuaternion, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(AddQuaternion)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_AddQuaternion); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - Result.W = Left.W + Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_SubtractQuaternion, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(SubtractQuaternion)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_SubtractQuaternion); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - Result.W = Left.W - Right.W; -#endif - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternion, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternion)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternion); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); - __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); - __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); - - SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); - SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); - - SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); - SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); - - SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); - Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); -#else - Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); - Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); - Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X) + (Left.Z * Right.W) + (Left.W * Right.Z); - Result.W = (-Left.X * Right.X) - (Left.Y * Right.Y) - (Left.Z * Right.Z) + (Left.W * Right.W); -#endif - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionF, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternionF)(hmm_quaternion Left, float Multiplicative) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionF); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Multiplicative); - Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X * Multiplicative; - Result.Y = Left.Y * Multiplicative; - Result.Z = Left.Z * Multiplicative; - Result.W = Left.W * Multiplicative; -#endif - - return (Result); -} - -COVERAGE(HMM_DivideQuaternionF, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(DivideQuaternionF)(hmm_quaternion Left, float Dividend) -{ - ASSERT_COVERED(HMM_DivideQuaternionF); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Dividend); - Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X / Dividend; - Result.Y = Left.Y / Dividend; - Result.Z = Left.Z / Dividend; - Result.W = Left.W / Dividend; -#endif - - return (Result); -} - -HMM_EXTERN hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left); - -COVERAGE(HMM_DotQuaternion, 1) -HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_DotQuaternion); - - float Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); - __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - _mm_store_ss(&Result, SSEResultOne); -#else - Result = (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z) + (Left.W * Right.W); -#endif - - return (Result); -} - -COVERAGE(HMM_NormalizeQuaternion, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(NormalizeQuaternion)(hmm_quaternion Left) -{ - ASSERT_COVERED(HMM_NormalizeQuaternion); - - hmm_quaternion Result; - - float Length = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); - Result = HMM_PREFIX(DivideQuaternionF)(Left, Length); - - return (Result); -} - -COVERAGE(HMM_NLerp, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_NLerp); - - hmm_quaternion Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 ScalarLeft = _mm_set1_ps(1.0f - Time); - __m128 ScalarRight = _mm_set1_ps(Time); - __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, ScalarLeft); - __m128 SSEResultTwo = _mm_mul_ps(Right.InternalElementsSSE, ScalarRight); - Result.InternalElementsSSE = _mm_add_ps(SSEResultOne, SSEResultTwo); -#else - Result.X = HMM_PREFIX(Lerp)(Left.X, Time, Right.X); - Result.Y = HMM_PREFIX(Lerp)(Left.Y, Time, Right.Y); - Result.Z = HMM_PREFIX(Lerp)(Left.Z, Time, Right.Z); - Result.W = HMM_PREFIX(Lerp)(Left.W, Time, Right.W); -#endif - Result = HMM_PREFIX(NormalizeQuaternion)(Result); - - return (Result); -} - -HMM_EXTERN hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right); -HMM_EXTERN hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left); -HMM_EXTERN hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 Left); -HMM_EXTERN hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -COVERAGE(HMM_LengthVec2CPP, 1) -HMM_INLINE float HMM_PREFIX(Length)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_LengthVec2CPP); - - float Result = HMM_PREFIX(LengthVec2)(A); - - return (Result); -} - -COVERAGE(HMM_LengthVec3CPP, 1) -HMM_INLINE float HMM_PREFIX(Length)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_LengthVec3CPP); - - float Result = HMM_PREFIX(LengthVec3)(A); - - return (Result); -} - -COVERAGE(HMM_LengthVec4CPP, 1) -HMM_INLINE float HMM_PREFIX(Length)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_LengthVec4CPP); - - float Result = HMM_PREFIX(LengthVec4)(A); - - return (Result); -} - -COVERAGE(HMM_LengthSquaredVec2CPP, 1) -HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec2CPP); - - float Result = HMM_PREFIX(LengthSquaredVec2)(A); - - return (Result); -} - -COVERAGE(HMM_LengthSquaredVec3CPP, 1) -HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec3CPP); - - float Result = HMM_PREFIX(LengthSquaredVec3)(A); - - return (Result); -} - -COVERAGE(HMM_LengthSquaredVec4CPP, 1) -HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_LengthSquaredVec4CPP); - - float Result = HMM_PREFIX(LengthSquaredVec4)(A); - - return (Result); -} - -COVERAGE(HMM_NormalizeVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Normalize)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_NormalizeVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(NormalizeVec2)(A); - - return (Result); -} - -COVERAGE(HMM_NormalizeVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Normalize)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_NormalizeVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(NormalizeVec3)(A); - - return (Result); -} - -COVERAGE(HMM_NormalizeVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Normalize)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_NormalizeVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(NormalizeVec4)(A); - - return (Result); -} - -COVERAGE(HMM_FastNormalizeVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalize)(hmm_vec2 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(FastNormalizeVec2)(A); - - return (Result); -} - -COVERAGE(HMM_FastNormalizeVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalize)(hmm_vec3 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(FastNormalizeVec3)(A); - - return (Result); -} - -COVERAGE(HMM_FastNormalizeVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalize)(hmm_vec4 A) -{ - ASSERT_COVERED(HMM_FastNormalizeVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(FastNormalizeVec4)(A); - - return (Result); -} - -COVERAGE(HMM_NormalizeQuaternionCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Normalize)(hmm_quaternion A) -{ - ASSERT_COVERED(HMM_NormalizeQuaternionCPP); - - hmm_quaternion Result = HMM_PREFIX(NormalizeQuaternion)(A); - - return (Result); -} - -COVERAGE(HMM_DotVec2CPP, 1) -HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec2 VecOne, hmm_vec2 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec2CPP); - - float Result = HMM_PREFIX(DotVec2)(VecOne, VecTwo); - - return (Result); -} - -COVERAGE(HMM_DotVec3CPP, 1) -HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec3CPP); - - float Result = HMM_PREFIX(DotVec3)(VecOne, VecTwo); - - return (Result); -} - -COVERAGE(HMM_DotVec4CPP, 1) -HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec4 VecOne, hmm_vec4 VecTwo) -{ - ASSERT_COVERED(HMM_DotVec4CPP); - - float Result = HMM_PREFIX(DotVec4)(VecOne, VecTwo); - - return (Result); -} - -COVERAGE(HMM_DotQuaternionCPP, 1) -HMM_INLINE float HMM_PREFIX(Dot)(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) -{ - ASSERT_COVERED(HMM_DotQuaternionCPP); - - float Result = HMM_PREFIX(DotQuaternion)(QuatOne, QuatTwo); - - return (Result); -} - -COVERAGE(HMM_AddVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Add)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_AddVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Add)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_AddVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Add)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_AddVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddMat4CPP, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Add)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_AddMat4CPP); - - hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddQuaternionCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Add)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_AddQuaternionCPP); - - hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Subtract)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_SubtractVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Subtract)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_SubtractVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Subtract)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_SubtractVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractMat4CPP, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Subtract)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_SubtractMat4CPP); - - hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractQuaternionCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Subtract)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_SubtractQuaternionCPP); - - hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2fCPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2fCPP); - - hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3fCPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3fCPP); - - hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4fCPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4fCPP); - - hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4CPP, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4CPP); - - hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4fCPP, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4fCPP); - - hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4ByVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - ASSERT_COVERED(HMM_MultiplyMat4ByVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionCPP); - - hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionFCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionFCPP); - - hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec2CPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_DivideVec2CPP); - - hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec2fCPP, 1) -HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec2fCPP); - - hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec3CPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_DivideVec3CPP); - - hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec3fCPP, 1) -HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec3fCPP); - - hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec4CPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_DivideVec4CPP); - - hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec4fCPP, 1) -HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec4fCPP); - - hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideMat4fCPP, 1) -HMM_INLINE hmm_mat4 HMM_PREFIX(Divide)(hmm_mat4 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideMat4fCPP); - - hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideQuaternionFCPP, 1) -HMM_INLINE hmm_quaternion HMM_PREFIX(Divide)(hmm_quaternion Left, float Right) -{ - ASSERT_COVERED(HMM_DivideQuaternionFCPP); - - hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_EqualsVec2CPP, 1) -HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_EqualsVec2CPP); - - hmm_bool Result = HMM_PREFIX(EqualsVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_EqualsVec3CPP, 1) -HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_EqualsVec3CPP); - - hmm_bool Result = HMM_PREFIX(EqualsVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_EqualsVec4CPP, 1) -HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_EqualsVec4CPP); - - hmm_bool Result = HMM_PREFIX(EqualsVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec2Op, 1) -HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_AddVec2Op); - - hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec3Op, 1) -HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_AddVec3Op); - - hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec4Op, 1) -HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_AddVec4Op); - - hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddMat4Op, 1) -HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_AddMat4Op); - - hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddQuaternionOp, 1) -HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_AddQuaternionOp); - - hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec2Op, 1) -HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_SubtractVec2Op); - - hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec3Op, 1) -HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_SubtractVec3Op); - - hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractVec4Op, 1) -HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_SubtractVec4Op); - - hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractMat4Op, 1) -HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_SubtractMat4Op); - - hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_SubtractQuaternionOp, 1) -HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_SubtractQuaternionOp); - - hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2Op, 1) -HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2Op); - - hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3Op, 1) -HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3Op); - - hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4Op, 1) -HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4Op); - - hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4Op, 1) -HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4Op); - - hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionOp, 1) -HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionOp); - - hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2fOp, 1) -HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2fOp); - - hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3fOp, 1) -HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3fOp); - - hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4fOp, 1) -HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4fOp); - - hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4fOp, 1) -HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4fOp); - - hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionFOp, 1) -HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionFOp); - - hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec2fOpLeft, 1) -HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2fOpLeft); - - hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Right, Left); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec3fOpLeft, 1) -HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3fOpLeft); - - hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Right, Left); - - return (Result); -} - -COVERAGE(HMM_MultiplyVec4fOpLeft, 1) -HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4fOpLeft); - - hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Right, Left); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4fOpLeft, 1) -HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4fOpLeft); - - hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Right, Left); - - return (Result); -} - -COVERAGE(HMM_MultiplyQuaternionFOpLeft, 1) -HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionFOpLeft); - - hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Right, Left); - - return (Result); -} - -COVERAGE(HMM_MultiplyMat4ByVec4Op, 1) -HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - ASSERT_COVERED(HMM_MultiplyMat4ByVec4Op); - - hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); - - return (Result); -} - -COVERAGE(HMM_DivideVec2Op, 1) -HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_DivideVec2Op); - - hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec3Op, 1) -HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_DivideVec3Op); - - hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec4Op, 1) -HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_DivideVec4Op); - - hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec2fOp, 1) -HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec2fOp); - - hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec3fOp, 1) -HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec3fOp); - - hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideVec4fOp, 1) -HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec4fOp); - - hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideMat4fOp, 1) -HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) -{ - ASSERT_COVERED(HMM_DivideMat4fOp); - - hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_DivideQuaternionFOp, 1) -HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) -{ - ASSERT_COVERED(HMM_DivideQuaternionFOp); - - hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); - - return (Result); -} - -COVERAGE(HMM_AddVec2Assign, 1) -HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_AddVec2Assign); - - return (Left = Left + Right); -} - -COVERAGE(HMM_AddVec3Assign, 1) -HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_AddVec3Assign); - - return (Left = Left + Right); -} - -COVERAGE(HMM_AddVec4Assign, 1) -HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_AddVec4Assign); - - return (Left = Left + Right); -} - -COVERAGE(HMM_AddMat4Assign, 1) -HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_AddMat4Assign); - - return (Left = Left + Right); -} - -COVERAGE(HMM_AddQuaternionAssign, 1) -HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_AddQuaternionAssign); - - return (Left = Left + Right); -} - -COVERAGE(HMM_SubtractVec2Assign, 1) -HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_SubtractVec2Assign); - - return (Left = Left - Right); -} - -COVERAGE(HMM_SubtractVec3Assign, 1) -HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_SubtractVec3Assign); - - return (Left = Left - Right); -} - -COVERAGE(HMM_SubtractVec4Assign, 1) -HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_SubtractVec4Assign); - - return (Left = Left - Right); -} - -COVERAGE(HMM_SubtractMat4Assign, 1) -HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_SubtractMat4Assign); - - return (Left = Left - Right); -} - -COVERAGE(HMM_SubtractQuaternionAssign, 1) -HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_SubtractQuaternionAssign); - - return (Left = Left - Right); -} - -COVERAGE(HMM_MultiplyVec2Assign, 1) -HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2Assign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyVec3Assign, 1) -HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3Assign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyVec4Assign, 1) -HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4Assign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyVec2fAssign, 1) -HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec2fAssign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyVec3fAssign, 1) -HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec3fAssign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyVec4fAssign, 1) -HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyVec4fAssign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyMat4fAssign, 1) -HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4fAssign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_MultiplyQuaternionFAssign, 1) -HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) -{ - ASSERT_COVERED(HMM_MultiplyQuaternionFAssign); - - return (Left = Left * Right); -} - -COVERAGE(HMM_DivideVec2Assign, 1) -HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_DivideVec2Assign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideVec3Assign, 1) -HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_DivideVec3Assign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideVec4Assign, 1) -HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_DivideVec4Assign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideVec2fAssign, 1) -HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec2fAssign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideVec3fAssign, 1) -HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec3fAssign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideVec4fAssign, 1) -HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) -{ - ASSERT_COVERED(HMM_DivideVec4fAssign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideMat4fAssign, 1) -HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) -{ - ASSERT_COVERED(HMM_DivideMat4fAssign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_DivideQuaternionFAssign, 1) -HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) -{ - ASSERT_COVERED(HMM_DivideQuaternionFAssign); - - return (Left = Left / Right); -} - -COVERAGE(HMM_EqualsVec2Op, 1) -HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_EqualsVec2Op); - - return HMM_PREFIX(EqualsVec2)(Left, Right); -} - -COVERAGE(HMM_EqualsVec3Op, 1) -HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_EqualsVec3Op); - - return HMM_PREFIX(EqualsVec3)(Left, Right); -} - -COVERAGE(HMM_EqualsVec4Op, 1) -HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_EqualsVec4Op); - - return HMM_PREFIX(EqualsVec4)(Left, Right); -} - -COVERAGE(HMM_EqualsVec2OpNot, 1) -HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) -{ - ASSERT_COVERED(HMM_EqualsVec2OpNot); - - return !HMM_PREFIX(EqualsVec2)(Left, Right); -} - -COVERAGE(HMM_EqualsVec3OpNot, 1) -HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) -{ - ASSERT_COVERED(HMM_EqualsVec3OpNot); - - return !HMM_PREFIX(EqualsVec3)(Left, Right); -} - -COVERAGE(HMM_EqualsVec4OpNot, 1) -HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) -{ - ASSERT_COVERED(HMM_EqualsVec4OpNot); - - return !HMM_PREFIX(EqualsVec4)(Left, Right); -} - -#endif /* __cplusplus */ - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif - -#endif /* HANDMADE_MATH_H */ - -#ifdef HANDMADE_MATH_IMPLEMENTATION - -COVERAGE(HMM_Power, 2) -float HMM_PREFIX(Power)(float Base, int Exponent) -{ - ASSERT_COVERED(HMM_Power); - - float Result = 1.0f; - float Mul = Exponent < 0 ? 1.f / Base : Base; - int X = Exponent < 0 ? -Exponent : Exponent; - while (X) - { - if (X & 1) - { - ASSERT_COVERED(HMM_Power); - - Result *= Mul; - } - - Mul *= Mul; - X >>= 1; - } - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_Transpose, 1) -hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) -{ - ASSERT_COVERED(HMM_Transpose); - - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -#ifndef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_AddMat4, 1) -hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_AddMat4); - - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -#ifndef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_SubtractMat4, 1) -hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_SubtractMat4); - - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -COVERAGE(HMM_MultiplyMat4, 1) -hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right) -{ - ASSERT_COVERED(HMM_MultiplyMat4); - - hmm_mat4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.Columns[0] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[0], Left); - Result.Columns[1] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[1], Left); - Result.Columns[2] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[2], Left); - Result.Columns[3] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[3], Left); -#else - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - float Sum = 0; - int CurrentMatrice; - for(CurrentMatrice = 0; CurrentMatrice < 4; ++CurrentMatrice) - { - Sum += Left.Elements[CurrentMatrice][Rows] * Right.Elements[Columns][CurrentMatrice]; - } - - Result.Elements[Columns][Rows] = Sum; - } - } -#endif - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_MultiplyMat4f, 1) -hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) -{ - ASSERT_COVERED(HMM_MultiplyMat4f); - - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar; - } - } - - return (Result); -} -#endif - -COVERAGE(HMM_MultiplyMat4ByVec4, 1) -hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - ASSERT_COVERED(HMM_MultiplyMat4ByVec4); - - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = HMM_PREFIX(LinearCombineSSE)(Vector.InternalElementsSSE, Matrix); -#else - int Columns, Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - float Sum = 0; - for(Columns = 0; Columns < 4; ++Columns) - { - Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; - } - - Result.Elements[Rows] = Sum; - } -#endif - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -COVERAGE(HMM_DivideMat4f, 1); -hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) -{ - ASSERT_COVERED(HMM_DivideMat4f); - - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar; - } - } - - return (Result); -} -#endif - -COVERAGE(HMM_Rotate, 1) -hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis) -{ - ASSERT_COVERED(HMM_Rotate); - - hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); - - Axis = HMM_PREFIX(NormalizeVec3)(Axis); - - float SinTheta = HMM_PREFIX(SinF)(HMM_PREFIX(ToRadians)(Angle)); - float CosTheta = HMM_PREFIX(CosF)(HMM_PREFIX(ToRadians)(Angle)); - float CosValue = 1.0f - CosTheta; - - Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; - Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); - Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); - - Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); - Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; - Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); - - Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); - Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); - Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; - - return (Result); -} - -COVERAGE(HMM_LookAt, 1) -hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) -{ - ASSERT_COVERED(HMM_LookAt); - - hmm_mat4 Result; - - hmm_vec3 F = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(SubtractVec3)(Center, Eye)); - hmm_vec3 S = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(Cross)(F, Up)); - hmm_vec3 U = HMM_PREFIX(Cross)(S, F); - - Result.Elements[0][0] = S.X; - Result.Elements[0][1] = U.X; - Result.Elements[0][2] = -F.X; - Result.Elements[0][3] = 0.0f; - - Result.Elements[1][0] = S.Y; - Result.Elements[1][1] = U.Y; - Result.Elements[1][2] = -F.Y; - Result.Elements[1][3] = 0.0f; - - Result.Elements[2][0] = S.Z; - Result.Elements[2][1] = U.Z; - Result.Elements[2][2] = -F.Z; - Result.Elements[2][3] = 0.0f; - - Result.Elements[3][0] = -HMM_PREFIX(DotVec3)(S, Eye); - Result.Elements[3][1] = -HMM_PREFIX(DotVec3)(U, Eye); - Result.Elements[3][2] = HMM_PREFIX(DotVec3)(F, Eye); - Result.Elements[3][3] = 1.0f; - - return (Result); -} - -COVERAGE(HMM_InverseQuaternion, 1) -hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left) -{ - ASSERT_COVERED(HMM_InverseQuaternion); - - hmm_quaternion Conjugate; - hmm_quaternion Result; - float Norm = 0; - float NormSquared = 0; - - Conjugate.X = -Left.X; - Conjugate.Y = -Left.Y; - Conjugate.Z = -Left.Z; - Conjugate.W = Left.W; - - Norm = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); - NormSquared = Norm * Norm; - - Result = HMM_PREFIX(DivideQuaternionF)(Conjugate, NormSquared); - - return (Result); -} - -COVERAGE(HMM_Slerp, 1) -hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) -{ - ASSERT_COVERED(HMM_Slerp); - - hmm_quaternion Result; - hmm_quaternion QuaternionLeft; - hmm_quaternion QuaternionRight; - - float Cos_Theta = HMM_PREFIX(DotQuaternion)(Left, Right); - float Angle = HMM_PREFIX(ACosF)(Cos_Theta); - - float S1 = HMM_PREFIX(SinF)((1.0f - Time) * Angle); - float S2 = HMM_PREFIX(SinF)(Time * Angle); - float Is = 1.0f / HMM_PREFIX(SinF)(Angle); - - QuaternionLeft = HMM_PREFIX(MultiplyQuaternionF)(Left, S1); - QuaternionRight = HMM_PREFIX(MultiplyQuaternionF)(Right, S2); - - Result = HMM_PREFIX(AddQuaternion)(QuaternionLeft, QuaternionRight); - Result = HMM_PREFIX(MultiplyQuaternionF)(Result, Is); - - return (Result); -} - -COVERAGE(HMM_QuaternionToMat4, 1) -hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left) -{ - ASSERT_COVERED(HMM_QuaternionToMat4); - - hmm_mat4 Result; - - hmm_quaternion NormalizedQuaternion = HMM_PREFIX(NormalizeQuaternion)(Left); - - float XX, YY, ZZ, - XY, XZ, YZ, - WX, WY, WZ; - - XX = NormalizedQuaternion.X * NormalizedQuaternion.X; - YY = NormalizedQuaternion.Y * NormalizedQuaternion.Y; - ZZ = NormalizedQuaternion.Z * NormalizedQuaternion.Z; - XY = NormalizedQuaternion.X * NormalizedQuaternion.Y; - XZ = NormalizedQuaternion.X * NormalizedQuaternion.Z; - YZ = NormalizedQuaternion.Y * NormalizedQuaternion.Z; - WX = NormalizedQuaternion.W * NormalizedQuaternion.X; - WY = NormalizedQuaternion.W * NormalizedQuaternion.Y; - WZ = NormalizedQuaternion.W * NormalizedQuaternion.Z; - - Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ); - Result.Elements[0][1] = 2.0f * (XY + WZ); - Result.Elements[0][2] = 2.0f * (XZ - WY); - Result.Elements[0][3] = 0.0f; - - Result.Elements[1][0] = 2.0f * (XY - WZ); - Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ); - Result.Elements[1][2] = 2.0f * (YZ + WX); - Result.Elements[1][3] = 0.0f; - - Result.Elements[2][0] = 2.0f * (XZ + WY); - Result.Elements[2][1] = 2.0f * (YZ - WX); - Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY); - Result.Elements[2][3] = 0.0f; - - Result.Elements[3][0] = 0.0f; - Result.Elements[3][1] = 0.0f; - Result.Elements[3][2] = 0.0f; - Result.Elements[3][3] = 1.0f; - - return (Result); -} - -// This method taken from Mike Day at Insomniac Games. -// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf -// -// Note that as mentioned at the top of the paper, the paper assumes the matrix -// would be *post*-multiplied to a vector to rotate it, meaning the matrix is -// the transpose of what we're dealing with. But, because our matrices are -// stored in column-major order, the indices *appear* to match the paper. -// -// For example, m12 in the paper is row 1, column 2. We need to transpose it to -// row 2, column 1. But, because the column comes first when referencing -// elements, it looks like M.Elements[1][2]. -// -// Don't be confused! Or if you must be confused, at least trust this -// comment. :) -COVERAGE(HMM_Mat4ToQuaternion, 4) -hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M) -{ - float T; - hmm_quaternion Q; - - if (M.Elements[2][2] < 0.0f) { - if (M.Elements[0][0] > M.Elements[1][1]) { - ASSERT_COVERED(HMM_Mat4ToQuaternion); - - T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2]; - Q = HMM_PREFIX(Quaternion)( - T, - M.Elements[0][1] + M.Elements[1][0], - M.Elements[2][0] + M.Elements[0][2], - M.Elements[1][2] - M.Elements[2][1] - ); - } else { - ASSERT_COVERED(HMM_Mat4ToQuaternion); - - T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2]; - Q = HMM_PREFIX(Quaternion)( - M.Elements[0][1] + M.Elements[1][0], - T, - M.Elements[1][2] + M.Elements[2][1], - M.Elements[2][0] - M.Elements[0][2] - ); - } - } else { - if (M.Elements[0][0] < -M.Elements[1][1]) { - ASSERT_COVERED(HMM_Mat4ToQuaternion); - - T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2]; - Q = HMM_PREFIX(Quaternion)( - M.Elements[2][0] + M.Elements[0][2], - M.Elements[1][2] + M.Elements[2][1], - T, - M.Elements[0][1] - M.Elements[1][0] - ); - } else { - ASSERT_COVERED(HMM_Mat4ToQuaternion); - - T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2]; - Q = HMM_PREFIX(Quaternion)( - M.Elements[1][2] - M.Elements[2][1], - M.Elements[2][0] - M.Elements[0][2], - M.Elements[0][1] - M.Elements[1][0], - T - ); - } - } - - Q = HMM_PREFIX(MultiplyQuaternionF)(Q, 0.5f / HMM_PREFIX(SquareRootF)(T)); - - return Q; -} - -COVERAGE(HMM_QuaternionFromAxisAngle, 1) -hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation) -{ - ASSERT_COVERED(HMM_QuaternionFromAxisAngle); - - hmm_quaternion Result; - - hmm_vec3 AxisNormalized = HMM_PREFIX(NormalizeVec3)(Axis); - float SineOfRotation = HMM_PREFIX(SinF)(AngleOfRotation / 2.0f); - - Result.XYZ = HMM_PREFIX(MultiplyVec3f)(AxisNormalized, SineOfRotation); - Result.W = HMM_PREFIX(CosF)(AngleOfRotation / 2.0f); - - return (Result); -} - -#endif /* HANDMADE_MATH_IMPLEMENTATION */ diff --git a/examples/sokol/rt_glsl/default_include.h b/examples/sokol/rt_glsl/default_include.h deleted file mode 100644 index da79e01100..0000000000 --- a/examples/sokol/rt_glsl/default_include.h +++ /dev/null @@ -1,27 +0,0 @@ -#define HANDMADE_MATH_IMPLEMENTATION -#define HANDMADE_MATH_NO_SSE -#include "HandmadeMath.h" - -void calc_matrices(void *res, float w, float h, float rx, float ry, float scale){ - hmm_mat4 proj = HMM_Perspective(60.0f, w/h, 0.01f, 10.0f); - hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 0.0f, 6.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f)); - hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view); - //state.rx += 1.0f; state.ry += 2.0f; - - - hmm_mat4 rxm = HMM_Rotate(rx, HMM_Vec3(1.0f, 0.0f, 0.0f)); - hmm_mat4 rym = HMM_Rotate(ry, HMM_Vec3(0.0f, 1.0f, 0.0f)); - - hmm_mat4 model = HMM_MultiplyMat4(rxm, rym); - hmm_mat4 scale_mx = HMM_Scale(HMM_Vec3(scale, scale, scale)); - model = HMM_MultiplyMat4(model, scale_mx); - hmm_mat4 tmp_res = HMM_MultiplyMat4(view_proj, model); - - // copy the matrix to V - int i = 0; - float *p = &tmp_res.Elements[0]; - while(i < 16){ - ((float*)(res))[i]= p[i]; - i++; - } -} \ No newline at end of file diff --git a/examples/sokol/rt_glsl/rt_glsl.h b/examples/sokol/rt_glsl/rt_glsl.h deleted file mode 100644 index a4b3b2ffaf..0000000000 --- a/examples/sokol/rt_glsl/rt_glsl.h +++ /dev/null @@ -1,2686 +0,0 @@ -#pragma once -/* - #version:1# (machine generated, don't edit!) - - Generated by sokol-shdc (https://github.com/floooh/sokol-tools) - - Overview: - - Shader program 'rt': - Get shader desc: rt_shader_desc() - Vertex shader: vs - Attribute slots: - ATTR_vs_pos = 0 - ATTR_vs_color0 = 1 - ATTR_vs_texcoord0 = 2 - Uniform block 'vs_params': - C struct: vs_params_t - Bind slot: SLOT_vs_params = 0 - Fragment shader: fs - Uniform block 'fs_params': - C struct: fs_params_t - Bind slot: SLOT_fs_params = 0 - Image 'tex': - Type: SG_IMAGETYPE_2D - Component Type: SG_SAMPLERTYPE_FLOAT - Bind slot: SLOT_tex = 0 - - - Shader descriptor structs: - - sg_shader rt = sg_make_shader(rt_shader_desc()); - - Vertex attribute locations for vertex shader 'vs': - - sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){ - .layout = { - .attrs = { - [ATTR_vs_pos] = { ... }, - [ATTR_vs_color0] = { ... }, - [ATTR_vs_texcoord0] = { ... }, - }, - }, - ...}); - - Image bind slots, use as index in sg_bindings.vs_images[] or .fs_images[] - - SLOT_tex = 0; - - Bind slot and C-struct for uniform block 'vs_params': - - vs_params_t vs_params = { - .mvp = ...; - }; - sg_apply_uniforms(SG_SHADERSTAGE_[VS|FS], SLOT_vs_params, &vs_params, sizeof(vs_params)); - - Bind slot and C-struct for uniform block 'fs_params': - - fs_params_t fs_params = { - .iResolution = ...; - .iMouse = ...; - .iTime = ...; - .iFrame = ...; - }; - sg_apply_uniforms(SG_SHADERSTAGE_[VS|FS], SLOT_fs_params, &fs_params, sizeof(fs_params)); - -*/ -#include -#include -#if !defined(SOKOL_SHDC_ALIGN) - #if defined(_MSC_VER) - #define SOKOL_SHDC_ALIGN(a) __declspec(align(a)) - #else - #define SOKOL_SHDC_ALIGN(a) __attribute__((aligned(a))) - #endif -#endif -#define ATTR_vs_pos (0) -#define ATTR_vs_color0 (1) -#define ATTR_vs_texcoord0 (2) -#define SLOT_tex (0) -#define SLOT_vs_params (0) -#pragma pack(push,1) -SOKOL_SHDC_ALIGN(16) typedef struct vs_params_t { - hmm_mat4 mvp; -} vs_params_t; -#pragma pack(pop) -#define SLOT_fs_params (0) -#pragma pack(push,1) -SOKOL_SHDC_ALIGN(16) typedef struct fs_params_t { - float iResolution[2]; - float iMouse[2]; - float iTime; - float iFrame; - uint8_t _pad_24[8]; -} fs_params_t; -#pragma pack(pop) -/* - #version 330 - - uniform vec4 vs_params[4]; - layout(location = 0) in vec4 pos; - out vec4 color; - layout(location = 1) in vec4 color0; - out vec2 uv; - layout(location = 2) in vec2 texcoord0; - - void main() - { - gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * pos; - color = color0; - uv = texcoord0; - } - -*/ -static const char vs_source_glsl330[326] = { - 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x33,0x30,0x0a,0x0a,0x75,0x6e, - 0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61, - 0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28, - 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e, - 0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76, - 0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75, - 0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20, - 0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a, - 0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79, - 0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32, - 0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f, - 0x72,0x64,0x30,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28, - 0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74, - 0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61, - 0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61, - 0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73, - 0x5b,0x32,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33, - 0x5d,0x29,0x20,0x2a,0x20,0x70,0x6f,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f, - 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30, - 0x3b,0x0a,0x7d,0x0a,0x0a,0x00, -}; -/* - #version 330 - - uniform vec4 fs_params[2]; - uniform sampler2D tex; - - in vec4 color; - in vec2 uv; - layout(location = 0) out vec4 frag_color; - - mat3 setCamera(vec3 ro, vec3 ta, float cr) - { - vec3 _2646 = normalize(ta - ro); - vec3 _2657 = normalize(cross(_2646, vec3(sin(cr), cos(cr), 0.0))); - return mat3(_2657, cross(_2657, _2646), _2646); - } - - vec2 iBox(vec3 ro, vec3 rd, vec3 rad) - { - vec3 _1959 = vec3(1.0) / rd; - vec3 _1968 = abs(_1959) * rad; - vec3 _1971 = -(_1959 * ro); - vec3 _1973 = _1971 - _1968; - vec3 _1978 = _1971 + _1968; - return vec2(max(max(_1973.x, _1973.y), _1973.z), min(min(_1978.x, _1978.y), _1978.z)); - } - - float sdSphere(vec3 p, float s) - { - return length(p) - s; - } - - vec2 opU(vec2 d1, vec2 d2) - { - bvec2 _1585 = bvec2(d1.x < d2.x); - return vec2(_1585.x ? d1.x : d2.x, _1585.y ? d1.y : d2.y); - } - - float sdBox(vec3 p, vec3 b) - { - vec3 _240 = abs(p) - b; - return min(max(_240.x, max(_240.y, _240.z)), 0.0) + length(max(_240, vec3(0.0))); - } - - float sdBoundingBox(inout vec3 p, vec3 b, float e) - { - p = abs(p) - b; - vec3 _271 = abs(p + vec3(e)) - vec3(e); - float _275 = _271.y; - float _277 = _271.z; - float _293 = _271.x; - return min(min(length(max(vec3(p.x, _275, _277), vec3(0.0))) + min(max(p.x, max(_275, _277)), 0.0), length(max(vec3(_293, p.y, _277), vec3(0.0))) + min(max(_293, max(p.y, _277)), 0.0)), length(max(vec3(_293, _275, p.z), vec3(0.0))) + min(max(_293, max(_275, p.z)), 0.0)); - } - - float sdTorus(vec3 p, vec2 t) - { - return length(vec2(length(p.xz) - t.x, p.y)) - t.y; - } - - float sdCone(vec3 p, vec2 c, float h) - { - vec2 _965 = (vec2(c.x, -c.y) * h) / vec2(c.y); - float _969 = length(p.xz); - vec2 _972 = vec2(_969, p.y); - vec2 _985 = _972 - (_965 * clamp(dot(_972, _965) / dot(_965, _965), 0.0, 1.0)); - float _992 = _965.x; - vec2 _997 = _972 - (_965 * vec2(clamp(_969 / _992, 0.0, 1.0), 1.0)); - float _1000 = _965.y; - float _1001 = sign(_1000); - return sqrt(min(dot(_985, _985), dot(_997, _997))) * sign(max(_1001 * ((_969 * _1000) - (p.y * _992)), _1001 * (p.y - _1000))); - } - - float dot2(vec2 v) - { - return dot(v, v); - } - - float sdCappedCone(vec3 p, float h, float r1, float r2) - { - float _1042 = length(p.xz); - vec2 _1045 = vec2(_1042, p.y); - vec2 _1049 = vec2(r2, h); - vec2 _1056 = vec2(r2 - r1, 2.0 * h); - float _1074 = abs(p.y) - h; - vec2 param = _1056; - vec2 _1092 = (_1045 - _1049) + (_1056 * clamp(dot(_1049 - _1045, _1056) / dot2(param), 0.0, 1.0)); - bool _1096 = _1092.x < 0.0; - bool _1102; - if (_1096) - { - _1102 = _1074 < 0.0; - } - else - { - _1102 = _1096; - } - vec2 param_1 = vec2(_1042 - min(_1042, (p.y < 0.0) ? r1 : r2), _1074); - vec2 param_2 = _1092; - return (_1102 ? (-1.0) : 1.0) * sqrt(min(dot2(param_1), dot2(param_2))); - } - - float sdSolidAngle(vec3 pos, vec2 c, float ra) - { - float _1235 = length(pos.xz); - vec2 _1238 = vec2(_1235, pos.y); - return max(length(_1238) - ra, length(_1238 - (c * clamp(dot(_1238, c), 0.0, ra))) * sign((c.y * _1235) - (c.x * pos.y))); - } - - float sdCappedTorus(inout vec3 p, vec2 sc, float ra, float rb) - { - p.x = abs(p.x); - float _389; - if ((sc.y * p.x) > (sc.x * p.y)) - { - _389 = dot(p.xy, sc); - } - else - { - _389 = length(p.xy); - } - return sqrt((dot(p, p) + (ra * ra)) - ((2.0 * ra) * _389)) - rb; - } - - float sdCapsule(vec3 p, vec3 a, vec3 b, float r) - { - vec3 _557 = p - a; - vec3 _561 = b - a; - return length(_557 - (_561 * clamp(dot(_557, _561) / dot(_561, _561), 0.0, 1.0))) - r; - } - - float sdCylinder(vec3 p, vec2 h) - { - vec2 _858 = abs(vec2(length(p.xz), p.y)) - h; - return min(max(_858.x, _858.y), 0.0) + length(max(_858, vec2(0.0))); - } - - float sdHexPrism(inout vec3 p, vec2 h) - { - p = abs(p); - vec2 _435 = p.xy - (vec2(-0.866025388240814208984375, 0.5) * (2.0 * min(dot(vec2(-0.866025388240814208984375, 0.5), p.xy), 0.0))); - p = vec3(_435.x, _435.y, p.z); - float _463 = length(p.xy - vec2(clamp(p.x, (-0.57735002040863037109375) * h.x, 0.57735002040863037109375 * h.x), h.x)) * sign(p.y - h.x); - float _468 = p.z - h.y; - return min(max(_463, _468), 0.0) + length(max(vec2(_463, _468), vec2(0.0))); - } - - float sdPyramid(inout vec3 p, float h) - { - float _1350 = h * h; - float _1352 = _1350 + 0.25; - vec2 _1355 = abs(p.xz); - p = vec3(_1355.x, p.y, _1355.y); - vec2 _1363; - if (p.z > p.x) - { - _1363 = p.zx; - } - else - { - _1363 = p.xz; - } - p = vec3(_1363.x, p.y, _1363.y); - vec2 _1377 = p.xz - vec2(0.5); - p = vec3(_1377.x, p.y, _1377.y); - float _1390 = (h * p.y) - (0.5 * p.x); - float _1398 = (h * p.x) + (0.5 * p.y); - float _1403 = -p.z; - float _1415 = clamp((_1390 - (0.5 * p.z)) / (_1350 + 0.5), 0.0, 1.0); - float _1421 = p.z + max(_1403, 0.0); - float _1440 = p.z + (0.5 * _1415); - float _1453 = _1390 - (_1352 * _1415); - float _1476; - if (min(_1390, (_1403 * _1352) - (_1390 * 0.5)) > 0.0) - { - _1476 = 0.0; - } - else - { - _1476 = min(((_1352 * _1421) * _1421) + (_1390 * _1390), ((_1352 * _1440) * _1440) + (_1453 * _1453)); - } - return sqrt((_1476 + (_1398 * _1398)) / _1352) * sign(max(_1398, -p.y)); - } - - float sdOctahedron(inout vec3 p, float s) - { - p = abs(p); - float _1285 = ((p.x + p.y) + p.z) - s; - vec3 q; - if ((3.0 * p.x) < _1285) - { - q = p; - } - else - { - if ((3.0 * p.y) < _1285) - { - q = p.yzx; - } - else - { - if ((3.0 * p.z) < _1285) - { - q = p.zxy; - } - else - { - return _1285 * 0.57735025882720947265625; - } - } - } - float _1330 = clamp(0.5 * ((q.z - q.y) + s), 0.0, s); - return length(vec3(q.x, (q.y - s) + _1330, q.z - _1330)); - } - - float sdTriPrism(inout vec3 p, inout vec2 h) - { - h.x *= 0.866025388240814208984375; - vec2 _768 = p.xy / vec2(h.x); - p = vec3(_768.x, _768.y, p.z); - p.x = abs(p.x) - 1.0; - p.y += 0.57735025882720947265625; - if ((p.x + (1.73205077648162841796875 * p.y)) > 0.0) - { - vec2 _806 = vec2(p.x - (1.73205077648162841796875 * p.y), ((-1.73205077648162841796875) * p.x) - p.y) * vec2(0.5); - p = vec3(_806.x, _806.y, p.z); - } - p.x -= clamp(p.x, -2.0, 0.0); - float _828 = (length(p.xy) * sign(-p.y)) * h.x; - float _835 = abs(p.z) - h.y; - return length(max(vec2(_828, _835), vec2(0.0))) + min(max(_828, _835), 0.0); - } - - float sdEllipsoid(vec3 p, vec3 r) - { - float _340 = length(p / r); - return (_340 * (_340 - 1.0)) / length(p / (r * r)); - } - - float ndot(vec2 a, vec2 b) - { - return (a.x * b.x) - (a.y * b.y); - } - - float sdRhombus(inout vec3 p, float la, float lb, float h, float ra) - { - p = abs(p); - vec2 _1509 = vec2(la, lb); - vec2 param = _1509; - vec2 param_1 = _1509 - (p.xz * 2.0); - float _1524 = clamp(ndot(param, param_1) / dot(_1509, _1509), -1.0, 1.0); - float _1558 = (length(p.xz - ((_1509 * 0.5) * vec2(1.0 - _1524, 1.0 + _1524))) * sign(((p.x * lb) + (p.z * la)) - (la * lb))) - ra; - float _1562 = p.y - h; - return min(max(_1558, _1562), 0.0) + length(max(vec2(_1558, _1562), vec2(0.0))); - } - - float sdOctogonPrism(inout vec3 p, float r, float h) - { - p = abs(p); - vec2 _496 = p.xy - (vec2(-0.92387950420379638671875, 0.3826834261417388916015625) * (2.0 * min(dot(vec2(-0.92387950420379638671875, 0.3826834261417388916015625), p.xy), 0.0))); - p = vec3(_496.x, _496.y, p.z); - vec2 _509 = p.xy - (vec2(0.92387950420379638671875, 0.3826834261417388916015625) * (2.0 * min(dot(vec2(0.92387950420379638671875, 0.3826834261417388916015625), p.xy), 0.0))); - p = vec3(_509.x, _509.y, p.z); - vec2 _525 = p.xy - vec2(clamp(p.x, (-0.4142135679721832275390625) * r, 0.4142135679721832275390625 * r), r); - p = vec3(_525.x, _525.y, p.z); - float _535 = length(p.xy) * sign(p.y); - float _539 = p.z - h; - return min(max(_535, _539), 0.0) + length(max(vec2(_535, _539), vec2(0.0))); - } - - float sdCylinder(vec3 p, vec3 a, vec3 b, float r) - { - vec3 _875 = p - a; - vec3 _879 = b - a; - float _883 = dot(_879, _879); - float _887 = dot(_875, _879); - float _900 = length((_875 * _883) - (_879 * _887)) - (r * _883); - float _904 = _883 * 0.5; - float _909 = abs(_887 - _904) - _904; - float _913 = _900 * _900; - float _919 = (_909 * _909) * _883; - float _925; - if (max(_900, _909) < 0.0) - { - _925 = -min(_913, _919); - } - else - { - _925 = ((_900 > 0.0) ? _913 : 0.0) + ((_909 > 0.0) ? _919 : 0.0); - } - return (sign(_925) * sqrt(abs(_925))) / _883; - } - - float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb) - { - float _1120 = rb - ra; - float _1128 = dot(b - a, b - a); - float _1144 = dot(p - a, b - a); - float _1146 = _1144 / _1128; - float _1155 = sqrt(dot(p - a, p - a) - ((_1146 * _1146) * _1128)); - float _1164 = max(0.0, _1155 - ((_1146 < 0.5) ? ra : rb)); - float _1169 = abs(_1146 - 0.5) - 0.5; - float _1188 = clamp(((_1120 * (_1155 - ra)) + _1144) / ((_1120 * _1120) + _1128), 0.0, 1.0); - float _1196 = (_1155 - ra) - (_1188 * _1120); - float _1200 = _1146 - _1188; - return (((_1196 < 0.0) && (_1169 < 0.0)) ? (-1.0) : 1.0) * sqrt(min((_1164 * _1164) + ((_1169 * _1169) * _1128), (_1196 * _1196) + ((_1200 * _1200) * _1128))); - } - - float dot2(vec3 v) - { - return dot(v, v); - } - - float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2) - { - vec3 _643 = b - a; - float _647 = dot(_643, _643); - float _651 = r1 - r2; - float _657 = _647 - (_651 * _651); - float _660 = 1.0 / _647; - vec3 _664 = p - a; - float _668 = dot(_664, _643); - float _672 = _668 - _647; - vec3 param = (_664 * _647) - (_643 * _668); - float _682 = dot2(param); - float _688 = (_668 * _668) * _647; - float _694 = (_672 * _672) * _647; - float _703 = ((sign(_651) * _651) * _651) * _682; - if (((sign(_672) * _657) * _694) > _703) - { - return (sqrt(_682 + _694) * _660) - r2; - } - if (((sign(_668) * _657) * _688) < _703) - { - return (sqrt(_682 + _688) * _660) - r1; - } - return ((sqrt((_682 * _657) * _660) + (_668 * _651)) * _660) - r1; - } - - float sdRoundCone(vec3 p, float r1, float r2, float h) - { - vec2 _587 = vec2(length(p.xz), p.y); - float _593 = (r1 - r2) / h; - float _599 = sqrt(1.0 - (_593 * _593)); - float _606 = dot(_587, vec2(-_593, _599)); - if (_606 < 0.0) - { - return length(_587) - r1; - } - if (_606 > (_599 * h)) - { - return length(_587 - vec2(0.0, h)) - r2; - } - return dot(_587, vec2(_599, _593)) - r1; - } - - vec2 map(vec3 pos) - { - vec2 res = vec2(10000000000.0, 0.0); - vec3 param = pos - vec3(-2.0, 0.25, 0.0); - float param_1 = 0.25; - vec2 param_2 = res; - vec2 param_3 = vec2(sdSphere(param, param_1), 26.8999996185302734375); - res = opU(param_2, param_3); - vec3 param_4 = pos - vec3(0.0, 0.300000011920928955078125, -1.0); - vec3 param_5 = vec3(0.3499999940395355224609375, 0.300000011920928955078125, 2.5); - if (sdBox(param_4, param_5) < res.x) - { - vec3 param_6 = pos - vec3(0.0, 0.25, 0.0); - vec3 param_7 = vec3(0.300000011920928955078125, 0.25, 0.20000000298023223876953125); - float param_8 = 0.02500000037252902984619140625; - float _1628 = sdBoundingBox(param_6, param_7, param_8); - vec2 param_9 = res; - vec2 param_10 = vec2(_1628, 16.8999996185302734375); - res = opU(param_9, param_10); - vec3 param_11 = (pos - vec3(0.0, 0.300000011920928955078125, 1.0)).xzy; - vec2 param_12 = vec2(0.25, 0.0500000007450580596923828125); - vec2 param_13 = res; - vec2 param_14 = vec2(sdTorus(param_11, param_12), 25.0); - res = opU(param_13, param_14); - vec3 param_15 = pos - vec3(0.0, 0.449999988079071044921875, -1.0); - vec2 param_16 = vec2(0.60000002384185791015625, 0.800000011920928955078125); - float param_17 = 0.449999988079071044921875; - vec2 param_18 = res; - vec2 param_19 = vec2(sdCone(param_15, param_16, param_17), 55.0); - res = opU(param_18, param_19); - vec3 param_20 = pos - vec3(0.0, 0.25, -2.0); - float param_21 = 0.25; - float param_22 = 0.25; - float param_23 = 0.100000001490116119384765625; - vec2 param_24 = res; - vec2 param_25 = vec2(sdCappedCone(param_20, param_21, param_22, param_23), 13.6700000762939453125); - res = opU(param_24, param_25); - vec3 param_26 = pos - vec3(0.0, 0.0, -3.0); - vec2 param_27 = vec2(0.60000002384185791015625, 0.800000011920928955078125); - float param_28 = 0.4000000059604644775390625; - vec2 param_29 = res; - vec2 param_30 = vec2(sdSolidAngle(param_26, param_27, param_28), 49.130001068115234375); - res = opU(param_29, param_30); - } - vec3 param_31 = pos - vec3(1.0, 0.300000011920928955078125, -1.0); - vec3 param_32 = vec3(0.3499999940395355224609375, 0.300000011920928955078125, 2.5); - if (sdBox(param_31, param_32) < res.x) - { - vec3 param_33 = (pos - vec3(1.0, 0.300000011920928955078125, 1.0)) * vec3(1.0, -1.0, 1.0); - vec2 param_34 = vec2(0.86602497100830078125, -0.5); - float param_35 = 0.25; - float param_36 = 0.0500000007450580596923828125; - float _1720 = sdCappedTorus(param_33, param_34, param_35, param_36); - vec2 param_37 = res; - vec2 param_38 = vec2(_1720, 8.5); - res = opU(param_37, param_38); - vec3 param_39 = pos - vec3(1.0, 0.25, 0.0); - vec3 param_40 = vec3(0.300000011920928955078125, 0.25, 0.100000001490116119384765625); - vec2 param_41 = res; - vec2 param_42 = vec2(sdBox(param_39, param_40), 3.0); - res = opU(param_41, param_42); - vec3 param_43 = pos - vec3(1.0, 0.0, -1.0); - vec3 param_44 = vec3(-0.100000001490116119384765625, 0.100000001490116119384765625, -0.100000001490116119384765625); - vec3 param_45 = vec3(0.20000000298023223876953125, 0.4000000059604644775390625, 0.20000000298023223876953125); - float param_46 = 0.100000001490116119384765625; - vec2 param_47 = res; - vec2 param_48 = vec2(sdCapsule(param_43, param_44, param_45, param_46), 31.8999996185302734375); - res = opU(param_47, param_48); - vec3 param_49 = pos - vec3(1.0, 0.25, -2.0); - vec2 param_50 = vec2(0.1500000059604644775390625, 0.25); - vec2 param_51 = res; - vec2 param_52 = vec2(sdCylinder(param_49, param_50), 8.0); - res = opU(param_51, param_52); - vec3 param_53 = pos - vec3(1.0, 0.20000000298023223876953125, -3.0); - vec2 param_54 = vec2(0.20000000298023223876953125, 0.0500000007450580596923828125); - float _1776 = sdHexPrism(param_53, param_54); - vec2 param_55 = res; - vec2 param_56 = vec2(_1776, 18.3999996185302734375); - res = opU(param_55, param_56); - } - vec3 param_57 = pos - vec3(-1.0, 0.3499999940395355224609375, -1.0); - vec3 param_58 = vec3(0.3499999940395355224609375, 0.3499999940395355224609375, 2.5); - if (sdBox(param_57, param_58) < res.x) - { - vec3 param_59 = pos - vec3(-1.0, -0.60000002384185791015625, -3.0); - float param_60 = 1.0; - float _1801 = sdPyramid(param_59, param_60); - vec2 param_61 = res; - vec2 param_62 = vec2(_1801, 13.56000041961669921875); - res = opU(param_61, param_62); - vec3 param_63 = pos - vec3(-1.0, 0.1500000059604644775390625, -2.0); - float param_64 = 0.3499999940395355224609375; - float _1813 = sdOctahedron(param_63, param_64); - vec2 param_65 = res; - vec2 param_66 = vec2(_1813, 23.5599994659423828125); - res = opU(param_65, param_66); - vec3 param_67 = pos - vec3(-1.0, 0.1500000059604644775390625, -1.0); - vec2 param_68 = vec2(0.300000011920928955078125, 0.0500000007450580596923828125); - float _1826 = sdTriPrism(param_67, param_68); - vec2 param_69 = res; - vec2 param_70 = vec2(_1826, 43.5); - res = opU(param_69, param_70); - vec3 param_71 = pos - vec3(-1.0, 0.25, 0.0); - vec3 param_72 = vec3(0.20000000298023223876953125, 0.25, 0.0500000007450580596923828125); - vec2 param_73 = res; - vec2 param_74 = vec2(sdEllipsoid(param_71, param_72), 43.1699981689453125); - res = opU(param_73, param_74); - vec3 param_75 = (pos - vec3(-1.0, 0.3400000035762786865234375, 1.0)).xzy; - float param_76 = 0.1500000059604644775390625; - float param_77 = 0.25; - float param_78 = 0.039999999105930328369140625; - float param_79 = 0.07999999821186065673828125; - float _1858 = sdRhombus(param_75, param_76, param_77, param_78, param_79); - vec2 param_80 = res; - vec2 param_81 = vec2(_1858, 17.0); - res = opU(param_80, param_81); - } - vec3 param_82 = pos - vec3(2.0, 0.300000011920928955078125, -1.0); - vec3 param_83 = vec3(0.3499999940395355224609375, 0.300000011920928955078125, 2.5); - if (sdBox(param_82, param_83) < res.x) - { - vec3 param_84 = pos - vec3(2.0, 0.20000000298023223876953125, -3.0); - float param_85 = 0.20000000298023223876953125; - float param_86 = 0.0500000007450580596923828125; - float _1882 = sdOctogonPrism(param_84, param_85, param_86); - vec2 param_87 = res; - vec2 param_88 = vec2(_1882, 51.799999237060546875); - res = opU(param_87, param_88); - vec3 param_89 = pos - vec3(2.0, 0.1500000059604644775390625, -2.0); - vec3 param_90 = vec3(0.100000001490116119384765625, -0.100000001490116119384765625, 0.0); - vec3 param_91 = vec3(-0.20000000298023223876953125, 0.3499999940395355224609375, 0.100000001490116119384765625); - float param_92 = 0.07999999821186065673828125; - vec2 param_93 = res; - vec2 param_94 = vec2(sdCylinder(param_89, param_90, param_91, param_92), 31.200000762939453125); - res = opU(param_93, param_94); - vec3 param_95 = pos - vec3(2.0, 0.100000001490116119384765625, -1.0); - vec3 param_96 = vec3(0.100000001490116119384765625, 0.0, 0.0); - vec3 param_97 = vec3(-0.20000000298023223876953125, 0.4000000059604644775390625, 0.100000001490116119384765625); - float param_98 = 0.1500000059604644775390625; - float param_99 = 0.0500000007450580596923828125; - vec2 param_100 = res; - vec2 param_101 = vec2(sdCappedCone(param_95, param_96, param_97, param_98, param_99), 46.09999847412109375); - res = opU(param_100, param_101); - vec3 param_102 = pos - vec3(2.0, 0.1500000059604644775390625, 0.0); - vec3 param_103 = vec3(0.100000001490116119384765625, 0.0, 0.0); - vec3 param_104 = vec3(-0.100000001490116119384765625, 0.3499999940395355224609375, 0.100000001490116119384765625); - float param_105 = 0.1500000059604644775390625; - float param_106 = 0.0500000007450580596923828125; - vec2 param_107 = res; - vec2 param_108 = vec2(sdRoundCone(param_102, param_103, param_104, param_105, param_106), 51.700000762939453125); - res = opU(param_107, param_108); - vec3 param_109 = pos - vec3(2.0, 0.20000000298023223876953125, 1.0); - float param_110 = 0.20000000298023223876953125; - float param_111 = 0.100000001490116119384765625; - float param_112 = 0.300000011920928955078125; - vec2 param_113 = res; - vec2 param_114 = vec2(sdRoundCone(param_109, param_110, param_111, param_112), 37.0); - res = opU(param_113, param_114); - } - return res; - } - - vec2 raycast(vec3 ro, vec3 rd) - { - vec2 res = vec2(-1.0); - float tmin = 1.0; - float tmax = 20.0; - float _2009 = (-ro.y) / rd.y; - if (_2009 > 0.0) - { - tmax = min(tmax, _2009); - res = vec2(_2009, 1.0); - } - vec3 param = ro - vec3(0.0, 0.4000000059604644775390625, -0.5); - vec3 param_1 = rd; - vec3 param_2 = vec3(2.5, 0.4099999964237213134765625, 3.0); - vec2 _2029 = iBox(param, param_1, param_2); - float _2031 = _2029.x; - float _2033 = _2029.y; - bool _2034 = _2031 < _2033; - bool _2040; - if (_2034) - { - _2040 = _2033 > 0.0; - } - else - { - _2040 = _2034; - } - bool _2047; - if (_2040) - { - _2047 = _2031 < tmax; - } - else - { - _2047 = _2040; - } - if (_2047) - { - float _2052 = tmin; - float _2053 = max(_2031, _2052); - tmin = _2053; - tmax = min(_2033, tmax); - float t = _2053; - for (int i = 0; (i < 70) && (t < tmax); i++) - { - vec3 param_3 = ro + (rd * t); - vec2 _2083 = map(param_3); - float _2085 = _2083.x; - if (abs(_2085) < (9.9999997473787516355514526367188e-05 * t)) - { - res = vec2(t, _2083.y); - break; - } - t += _2085; - } - } - return res; - } - - vec3 calcNormal(vec3 pos) - { - vec3 n = vec3(0.0); - for (int i = min(int(fs_params[1].y), 0); i < 4; i++) - { - vec3 _2221 = ((vec3(float(((i + 3) >> 1) & 1), float((i >> 1) & 1), float(i & 1)) * 2.0) - vec3(1.0)) * 0.577300012111663818359375; - vec3 param = pos + (_2221 * 0.0005000000237487256526947021484375); - n += (_2221 * map(param).x); - } - return normalize(n); - } - - float checkersGradBox(vec2 p, vec2 dpdx, vec2 dpdy) - { - vec2 _2309 = (abs(dpdx) + abs(dpdy)) + vec2(0.001000000047497451305389404296875); - vec2 _2313 = _2309 * 0.5; - vec2 _2332 = ((abs(fract((p - _2313) * 0.5) - vec2(0.5)) - abs(fract((p + _2313) * 0.5) - vec2(0.5))) * 2.0) / _2309; - return 0.5 - ((0.5 * _2332.x) * _2332.y); - } - - float calcAO(vec3 pos, vec3 nor) - { - float occ = 0.0; - float sca = 1.0; - for (int i = min(int(fs_params[1].y), 0); i < 5; i++) - { - float _2263 = 0.00999999977648258209228515625 + (float(i) * 0.02999999932944774627685546875); - vec3 param = pos + (nor * _2263); - float _2276 = sca; - float _2278 = occ; - float _2279 = _2278 + ((_2263 - map(param).x) * _2276); - occ = _2279; - sca = _2276 * 0.949999988079071044921875; - if (_2279 > 0.3499999940395355224609375) - { - break; - } - } - return clamp(1.0 - (3.0 * occ), 0.0, 1.0) * (0.5 + (0.5 * nor.y)); - } - - float calcSoftshadow(vec3 ro, vec3 rd, float mint, inout float tmax) - { - float _2114 = (0.800000011920928955078125 - ro.y) / rd.y; - if (_2114 > 0.0) - { - tmax = min(tmax, _2114); - } - float res = 1.0; - float t = mint; - for (int i = min(int(fs_params[1].y), 0); i < 24; i++) - { - vec3 param = ro + (rd * t); - vec2 _2150 = map(param); - float _2151 = _2150.x; - float _2155 = t; - float _2157 = clamp((8.0 * _2151) / _2155, 0.0, 1.0); - float _2158 = res; - float _2166 = min(_2158, (_2157 * _2157) * (3.0 - (2.0 * _2157))); - res = _2166; - float _2171 = _2155 + clamp(_2151, 0.0199999995529651641845703125, 0.20000000298023223876953125); - t = _2171; - if ((_2166 < 0.0040000001899898052215576171875) || (_2171 > tmax)) - { - break; - } - } - return clamp(res, 0.0, 1.0); - } - - vec3 render(vec3 ro, vec3 rd, vec3 rdx, vec3 rdy) - { - vec3 col = vec3(0.699999988079071044921875, 0.699999988079071044921875, 0.89999997615814208984375) - vec3(max(rd.y, 0.0) * 0.300000011920928955078125); - vec3 param = ro; - vec3 param_1 = rd; - vec2 _2357 = raycast(param, param_1); - float _2360 = _2357.x; - float _2363 = _2357.y; - if (_2363 > (-0.5)) - { - vec3 _2373 = ro + (rd * _2360); - bool _2377 = _2363 < 1.5; - vec3 _2378; - if (_2377) - { - _2378 = vec3(0.0, 1.0, 0.0); - } - else - { - vec3 param_2 = _2373; - _2378 = calcNormal(param_2); - } - vec3 _2390 = reflect(rd, _2378); - col = vec3(0.20000000298023223876953125) + (sin(vec3(_2363 * 2.0) + vec3(0.0, 1.0, 2.0)) * 0.20000000298023223876953125); - float ks = 1.0; - if (_2377) - { - vec2 param_3 = _2373.xz * 3.0; - vec2 param_4 = (((rd / vec3(rd.y)) - (rdx / vec3(rdx.y))) * ro.y).xz * 3.0; - vec2 param_5 = (((rd / vec3(rd.y)) - (rdy / vec3(rdy.y))) * ro.y).xz * 3.0; - col = vec3(0.1500000059604644775390625) + (vec3(0.0500000007450580596923828125) * checkersGradBox(param_3, param_4, param_5)); - ks = 0.4000000059604644775390625; - } - vec3 param_6 = _2373; - vec3 param_7 = _2378; - float _2459 = calcAO(param_6, param_7); - vec3 lin = vec3(0.0); - vec3 _2470 = normalize(vec3(-0.56980288028717041015625, 0.455842316150665283203125, -0.683763444423675537109375) - rd); - float dif = clamp(dot(_2378, vec3(-0.56980288028717041015625, 0.455842316150665283203125, -0.683763444423675537109375)), 0.0, 1.0); - vec3 param_8 = _2373; - vec3 param_9 = vec3(-0.56980288028717041015625, 0.455842316150665283203125, -0.683763444423675537109375); - float param_10 = 0.0199999995529651641845703125; - float param_11 = 2.5; - float _2482 = calcSoftshadow(param_8, param_9, param_10, param_11); - float _2483 = dif; - float _2484 = _2483 * _2482; - dif = _2484; - lin = (lin + (((col * 2.2000000476837158203125) * _2484) * vec3(1.2999999523162841796875, 1.0, 0.699999988079071044921875))) + ((vec3(1.2999999523162841796875, 1.0, 0.699999988079071044921875) * (5.0 * ((pow(clamp(dot(_2378, _2470), 0.0, 1.0), 16.0) * _2484) * (0.039999999105930328369140625 + (0.959999978542327880859375 * pow(clamp(1.0 - dot(_2470, vec3(-0.56980288028717041015625, 0.455842316150665283203125, -0.683763444423675537109375)), 0.0, 1.0), 5.0)))))) * ks); - float _2533 = sqrt(clamp(0.5 + (0.5 * _2378.y), 0.0, 1.0)) * _2459; - float spe = (smoothstep(-0.20000000298023223876953125, 0.20000000298023223876953125, _2390.y) * _2533) * (0.039999999105930328369140625 + (0.959999978542327880859375 * pow(clamp(1.0 + dot(_2378, rd), 0.0, 1.0), 5.0))); - vec3 param_12 = _2373; - vec3 param_13 = _2390; - float param_14 = 0.0199999995529651641845703125; - float param_15 = 2.5; - float _2557 = calcSoftshadow(param_12, param_13, param_14, param_15); - float _2558 = spe; - float _2559 = _2558 * _2557; - spe = _2559; - vec3 _2567 = lin; - vec3 _2618 = (((_2567 + (((col * 0.60000002384185791015625) * _2533) * vec3(0.4000000059604644775390625, 0.60000002384185791015625, 1.14999997615814208984375))) + ((vec3(0.4000000059604644775390625, 0.60000002384185791015625, 1.2999999523162841796875) * (2.0 * _2559)) * ks)) + (((col * 0.550000011920928955078125) * ((clamp(dot(_2378, vec3(0.6401844024658203125, 0.0, 0.76822125911712646484375)), 0.0, 1.0) * clamp(1.0 - _2373.y, 0.0, 1.0)) * _2459)) * vec3(0.25))) + ((col * 0.25) * (pow(clamp(1.0 + dot(_2378, rd), 0.0, 1.0), 2.0) * _2459)); - lin = _2618; - col = mix(_2618, vec3(0.699999988079071044921875, 0.699999988079071044921875, 0.89999997615814208984375), vec3(1.0 - exp((((-9.9999997473787516355514526367188e-05) * _2360) * _2360) * _2360))); - } - return clamp(col, vec3(0.0), vec3(1.0)); - } - - vec4 mainImage(vec2 fragCoord) - { - vec2 _2686 = fs_params[0].zw / fs_params[0].xy; - float _2705 = (0.100000001490116119384765625 * (32.0 + (fs_params[1].x * 1.5))) + (7.0 * _2686.x); - vec3 _2721 = vec3(0.5, -0.5, -0.60000002384185791015625) + vec3(4.5 * cos(_2705), 1.2999999523162841796875 + (2.0 * _2686.y), 4.5 * sin(_2705)); - vec3 param = _2721; - vec3 param_1 = vec3(0.5, -0.5, -0.60000002384185791015625); - float param_2 = 0.0; - mat3 _2729 = setCamera(param, param_1, param_2); - vec3 tot = vec3(0.0); - vec2 _2739 = vec2(fs_params[0].y); - vec3 param_3 = _2721; - vec3 param_4 = _2729 * normalize(vec3(((fragCoord * 2.0) - fs_params[0].xy) / _2739, 2.5)); - vec3 param_5 = _2729 * normalize(vec3((((fragCoord + vec2(1.0, 0.0)) * 2.0) - fs_params[0].xy) / _2739, 2.5)); - vec3 param_6 = _2729 * normalize(vec3((((fragCoord + vec2(0.0, 1.0)) * 2.0) - fs_params[0].xy) / _2739, 2.5)); - vec3 _2804 = tot; - vec3 _2805 = _2804 + pow(render(param_3, param_4, param_5, param_6), vec3(0.4544999897480010986328125)); - tot = _2805; - return vec4(_2805, 1.0); - } - - void main() - { - vec2 param = uv * fs_params[0].xy; - frag_color = ((texture(tex, uv) * color) * 9.9999997473787516355514526367188e-06) + mainImage(param); - } - -*/ -static const char fs_source_glsl330[28396] = { - 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x33,0x30,0x0a,0x0a,0x75,0x6e, - 0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x73,0x5f,0x70,0x61, - 0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x3b,0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d, - 0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x74,0x65,0x78,0x3b,0x0a, - 0x0a,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a, - 0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f, - 0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29, - 0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63, - 0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x6d,0x61,0x74,0x33,0x20,0x73,0x65,0x74,0x43, - 0x61,0x6d,0x65,0x72,0x61,0x28,0x76,0x65,0x63,0x33,0x20,0x72,0x6f,0x2c,0x20,0x76, - 0x65,0x63,0x33,0x20,0x74,0x61,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x63,0x72, - 0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x36, - 0x34,0x36,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x74, - 0x61,0x20,0x2d,0x20,0x72,0x6f,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x5f,0x32,0x36,0x35,0x37,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c, - 0x69,0x7a,0x65,0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x5f,0x32,0x36,0x34,0x36,0x2c, - 0x20,0x76,0x65,0x63,0x33,0x28,0x73,0x69,0x6e,0x28,0x63,0x72,0x29,0x2c,0x20,0x63, - 0x6f,0x73,0x28,0x63,0x72,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x74,0x33,0x28, - 0x5f,0x32,0x36,0x35,0x37,0x2c,0x20,0x63,0x72,0x6f,0x73,0x73,0x28,0x5f,0x32,0x36, - 0x35,0x37,0x2c,0x20,0x5f,0x32,0x36,0x34,0x36,0x29,0x2c,0x20,0x5f,0x32,0x36,0x34, - 0x36,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x65,0x63,0x32,0x20,0x69,0x42,0x6f,0x78, - 0x28,0x76,0x65,0x63,0x33,0x20,0x72,0x6f,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72, - 0x64,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72,0x61,0x64,0x29,0x0a,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x39,0x35,0x39,0x20,0x3d,0x20, - 0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x29,0x20,0x2f,0x20,0x72,0x64,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x39,0x36,0x38,0x20,0x3d, - 0x20,0x61,0x62,0x73,0x28,0x5f,0x31,0x39,0x35,0x39,0x29,0x20,0x2a,0x20,0x72,0x61, - 0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x39,0x37, - 0x31,0x20,0x3d,0x20,0x2d,0x28,0x5f,0x31,0x39,0x35,0x39,0x20,0x2a,0x20,0x72,0x6f, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x39,0x37, - 0x33,0x20,0x3d,0x20,0x5f,0x31,0x39,0x37,0x31,0x20,0x2d,0x20,0x5f,0x31,0x39,0x36, - 0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x39,0x37, - 0x38,0x20,0x3d,0x20,0x5f,0x31,0x39,0x37,0x31,0x20,0x2b,0x20,0x5f,0x31,0x39,0x36, - 0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x76,0x65, - 0x63,0x32,0x28,0x6d,0x61,0x78,0x28,0x6d,0x61,0x78,0x28,0x5f,0x31,0x39,0x37,0x33, - 0x2e,0x78,0x2c,0x20,0x5f,0x31,0x39,0x37,0x33,0x2e,0x79,0x29,0x2c,0x20,0x5f,0x31, - 0x39,0x37,0x33,0x2e,0x7a,0x29,0x2c,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x69,0x6e,0x28, - 0x5f,0x31,0x39,0x37,0x38,0x2e,0x78,0x2c,0x20,0x5f,0x31,0x39,0x37,0x38,0x2e,0x79, - 0x29,0x2c,0x20,0x5f,0x31,0x39,0x37,0x38,0x2e,0x7a,0x29,0x29,0x3b,0x0a,0x7d,0x0a, - 0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x53,0x70,0x68,0x65,0x72,0x65,0x28, - 0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x29, - 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6c,0x65, - 0x6e,0x67,0x74,0x68,0x28,0x70,0x29,0x20,0x2d,0x20,0x73,0x3b,0x0a,0x7d,0x0a,0x0a, - 0x76,0x65,0x63,0x32,0x20,0x6f,0x70,0x55,0x28,0x76,0x65,0x63,0x32,0x20,0x64,0x31, - 0x2c,0x20,0x76,0x65,0x63,0x32,0x20,0x64,0x32,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20, - 0x20,0x62,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x35,0x38,0x35,0x20,0x3d,0x20,0x62, - 0x76,0x65,0x63,0x32,0x28,0x64,0x31,0x2e,0x78,0x20,0x3c,0x20,0x64,0x32,0x2e,0x78, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x76,0x65, - 0x63,0x32,0x28,0x5f,0x31,0x35,0x38,0x35,0x2e,0x78,0x20,0x3f,0x20,0x64,0x31,0x2e, - 0x78,0x20,0x3a,0x20,0x64,0x32,0x2e,0x78,0x2c,0x20,0x5f,0x31,0x35,0x38,0x35,0x2e, - 0x79,0x20,0x3f,0x20,0x64,0x31,0x2e,0x79,0x20,0x3a,0x20,0x64,0x32,0x2e,0x79,0x29, - 0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x42,0x6f,0x78, - 0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x62,0x29, - 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x34,0x30, - 0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x29,0x20,0x2d,0x20,0x62,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x61, - 0x78,0x28,0x5f,0x32,0x34,0x30,0x2e,0x78,0x2c,0x20,0x6d,0x61,0x78,0x28,0x5f,0x32, - 0x34,0x30,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,0x30,0x2e,0x7a,0x29,0x29,0x2c,0x20, - 0x30,0x2e,0x30,0x29,0x20,0x2b,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61, - 0x78,0x28,0x5f,0x32,0x34,0x30,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30, - 0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64, - 0x42,0x6f,0x75,0x6e,0x64,0x69,0x6e,0x67,0x42,0x6f,0x78,0x28,0x69,0x6e,0x6f,0x75, - 0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x62, - 0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x65,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20, - 0x20,0x70,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x29,0x20,0x2d,0x20,0x62,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x37,0x31,0x20,0x3d, - 0x20,0x61,0x62,0x73,0x28,0x70,0x20,0x2b,0x20,0x76,0x65,0x63,0x33,0x28,0x65,0x29, - 0x29,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x37,0x35,0x20,0x3d,0x20,0x5f,0x32, - 0x37,0x31,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x32,0x37,0x37,0x20,0x3d,0x20,0x5f,0x32,0x37,0x31,0x2e,0x7a,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x39,0x33,0x20,0x3d,0x20, - 0x5f,0x32,0x37,0x31,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75, - 0x72,0x6e,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x69,0x6e,0x28,0x6c,0x65,0x6e,0x67,0x74, - 0x68,0x28,0x6d,0x61,0x78,0x28,0x76,0x65,0x63,0x33,0x28,0x70,0x2e,0x78,0x2c,0x20, - 0x5f,0x32,0x37,0x35,0x2c,0x20,0x5f,0x32,0x37,0x37,0x29,0x2c,0x20,0x76,0x65,0x63, - 0x33,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x20,0x2b,0x20,0x6d,0x69,0x6e,0x28,0x6d, - 0x61,0x78,0x28,0x70,0x2e,0x78,0x2c,0x20,0x6d,0x61,0x78,0x28,0x5f,0x32,0x37,0x35, - 0x2c,0x20,0x5f,0x32,0x37,0x37,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20, - 0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x76,0x65,0x63,0x33,0x28, - 0x5f,0x32,0x39,0x33,0x2c,0x20,0x70,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x37,0x37,0x29, - 0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x20,0x2b,0x20, - 0x6d,0x69,0x6e,0x28,0x6d,0x61,0x78,0x28,0x5f,0x32,0x39,0x33,0x2c,0x20,0x6d,0x61, - 0x78,0x28,0x70,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x37,0x37,0x29,0x29,0x2c,0x20,0x30, - 0x2e,0x30,0x29,0x29,0x2c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78, - 0x28,0x76,0x65,0x63,0x33,0x28,0x5f,0x32,0x39,0x33,0x2c,0x20,0x5f,0x32,0x37,0x35, - 0x2c,0x20,0x70,0x2e,0x7a,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30, - 0x29,0x29,0x29,0x20,0x2b,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x61,0x78,0x28,0x5f,0x32, - 0x39,0x33,0x2c,0x20,0x6d,0x61,0x78,0x28,0x5f,0x32,0x37,0x35,0x2c,0x20,0x70,0x2e, - 0x7a,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x54,0x6f,0x72,0x75,0x73,0x28,0x76,0x65,0x63, - 0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x20,0x74,0x29,0x0a,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68, - 0x28,0x76,0x65,0x63,0x32,0x28,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78, - 0x7a,0x29,0x20,0x2d,0x20,0x74,0x2e,0x78,0x2c,0x20,0x70,0x2e,0x79,0x29,0x29,0x20, - 0x2d,0x20,0x74,0x2e,0x79,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x73,0x64,0x43,0x6f,0x6e,0x65,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x76, - 0x65,0x63,0x32,0x20,0x63,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x68,0x29,0x0a, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x39,0x36,0x35,0x20, - 0x3d,0x20,0x28,0x76,0x65,0x63,0x32,0x28,0x63,0x2e,0x78,0x2c,0x20,0x2d,0x63,0x2e, - 0x79,0x29,0x20,0x2a,0x20,0x68,0x29,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x63, - 0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x39,0x36,0x39,0x20,0x3d,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78, - 0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x39,0x37, - 0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x39,0x36,0x39,0x2c,0x20,0x70, - 0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x39, - 0x38,0x35,0x20,0x3d,0x20,0x5f,0x39,0x37,0x32,0x20,0x2d,0x20,0x28,0x5f,0x39,0x36, - 0x35,0x20,0x2a,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x5f,0x39, - 0x37,0x32,0x2c,0x20,0x5f,0x39,0x36,0x35,0x29,0x20,0x2f,0x20,0x64,0x6f,0x74,0x28, - 0x5f,0x39,0x36,0x35,0x2c,0x20,0x5f,0x39,0x36,0x35,0x29,0x2c,0x20,0x30,0x2e,0x30, - 0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x39,0x39,0x32,0x20,0x3d,0x20,0x5f,0x39,0x36,0x35,0x2e,0x78, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x39,0x39,0x37,0x20, - 0x3d,0x20,0x5f,0x39,0x37,0x32,0x20,0x2d,0x20,0x28,0x5f,0x39,0x36,0x35,0x20,0x2a, - 0x20,0x76,0x65,0x63,0x32,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x5f,0x39,0x36,0x39, - 0x20,0x2f,0x20,0x5f,0x39,0x39,0x32,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e, - 0x30,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x30,0x30,0x30,0x20,0x3d,0x20,0x5f,0x39,0x36, - 0x35,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x31,0x30,0x30,0x31,0x20,0x3d,0x20,0x73,0x69,0x67,0x6e,0x28,0x5f,0x31,0x30,0x30, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73, - 0x71,0x72,0x74,0x28,0x6d,0x69,0x6e,0x28,0x64,0x6f,0x74,0x28,0x5f,0x39,0x38,0x35, - 0x2c,0x20,0x5f,0x39,0x38,0x35,0x29,0x2c,0x20,0x64,0x6f,0x74,0x28,0x5f,0x39,0x39, - 0x37,0x2c,0x20,0x5f,0x39,0x39,0x37,0x29,0x29,0x29,0x20,0x2a,0x20,0x73,0x69,0x67, - 0x6e,0x28,0x6d,0x61,0x78,0x28,0x5f,0x31,0x30,0x30,0x31,0x20,0x2a,0x20,0x28,0x28, - 0x5f,0x39,0x36,0x39,0x20,0x2a,0x20,0x5f,0x31,0x30,0x30,0x30,0x29,0x20,0x2d,0x20, - 0x28,0x70,0x2e,0x79,0x20,0x2a,0x20,0x5f,0x39,0x39,0x32,0x29,0x29,0x2c,0x20,0x5f, - 0x31,0x30,0x30,0x31,0x20,0x2a,0x20,0x28,0x70,0x2e,0x79,0x20,0x2d,0x20,0x5f,0x31, - 0x30,0x30,0x30,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x64,0x6f,0x74,0x32,0x28,0x76,0x65,0x63,0x32,0x20,0x76,0x29,0x0a,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x74,0x28,0x76, - 0x2c,0x20,0x76,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73, - 0x64,0x43,0x61,0x70,0x70,0x65,0x64,0x43,0x6f,0x6e,0x65,0x28,0x76,0x65,0x63,0x33, - 0x20,0x70,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x68,0x2c,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x72,0x31,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x32,0x29, - 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x30, - 0x34,0x32,0x20,0x3d,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78,0x7a, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x30,0x34, - 0x35,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x30,0x34,0x32,0x2c,0x20, - 0x70,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f, - 0x31,0x30,0x34,0x39,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x72,0x32,0x2c,0x20, - 0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x30, - 0x35,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x72,0x32,0x20,0x2d,0x20,0x72, - 0x31,0x2c,0x20,0x32,0x2e,0x30,0x20,0x2a,0x20,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x30,0x37,0x34,0x20,0x3d,0x20,0x61, - 0x62,0x73,0x28,0x70,0x2e,0x79,0x29,0x20,0x2d,0x20,0x68,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x5f,0x31, - 0x30,0x35,0x36,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31, - 0x30,0x39,0x32,0x20,0x3d,0x20,0x28,0x5f,0x31,0x30,0x34,0x35,0x20,0x2d,0x20,0x5f, - 0x31,0x30,0x34,0x39,0x29,0x20,0x2b,0x20,0x28,0x5f,0x31,0x30,0x35,0x36,0x20,0x2a, - 0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x5f,0x31,0x30,0x34,0x39, - 0x20,0x2d,0x20,0x5f,0x31,0x30,0x34,0x35,0x2c,0x20,0x5f,0x31,0x30,0x35,0x36,0x29, - 0x20,0x2f,0x20,0x64,0x6f,0x74,0x32,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x2c,0x20, - 0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x31,0x30,0x39,0x36,0x20,0x3d,0x20,0x5f,0x31,0x30, - 0x39,0x32,0x2e,0x78,0x20,0x3c,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x31,0x31,0x30,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x69,0x66,0x20,0x28,0x5f,0x31,0x30,0x39,0x36,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x31,0x31,0x30,0x32,0x20,0x3d, - 0x20,0x5f,0x31,0x30,0x37,0x34,0x20,0x3c,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20, - 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x31,0x31,0x30,0x32, - 0x20,0x3d,0x20,0x5f,0x31,0x30,0x39,0x36,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x30,0x34,0x32,0x20,0x2d,0x20, - 0x6d,0x69,0x6e,0x28,0x5f,0x31,0x30,0x34,0x32,0x2c,0x20,0x28,0x70,0x2e,0x79,0x20, - 0x3c,0x20,0x30,0x2e,0x30,0x29,0x20,0x3f,0x20,0x72,0x31,0x20,0x3a,0x20,0x72,0x32, - 0x29,0x2c,0x20,0x5f,0x31,0x30,0x37,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x5f,0x31, - 0x30,0x39,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, - 0x28,0x5f,0x31,0x31,0x30,0x32,0x20,0x3f,0x20,0x28,0x2d,0x31,0x2e,0x30,0x29,0x20, - 0x3a,0x20,0x31,0x2e,0x30,0x29,0x20,0x2a,0x20,0x73,0x71,0x72,0x74,0x28,0x6d,0x69, - 0x6e,0x28,0x64,0x6f,0x74,0x32,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x29,0x2c, - 0x20,0x64,0x6f,0x74,0x32,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x29,0x29,0x29, - 0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x53,0x6f,0x6c, - 0x69,0x64,0x41,0x6e,0x67,0x6c,0x65,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x6f,0x73, - 0x2c,0x20,0x76,0x65,0x63,0x32,0x20,0x63,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x72,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x32,0x33,0x35,0x20,0x3d,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70, - 0x6f,0x73,0x2e,0x78,0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x5f,0x31,0x32,0x33,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31, - 0x32,0x33,0x35,0x2c,0x20,0x70,0x6f,0x73,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x78,0x28,0x6c,0x65,0x6e,0x67, - 0x74,0x68,0x28,0x5f,0x31,0x32,0x33,0x38,0x29,0x20,0x2d,0x20,0x72,0x61,0x2c,0x20, - 0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x5f,0x31,0x32,0x33,0x38,0x20,0x2d,0x20,0x28, - 0x63,0x20,0x2a,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x5f,0x31, - 0x32,0x33,0x38,0x2c,0x20,0x63,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x72,0x61, - 0x29,0x29,0x29,0x20,0x2a,0x20,0x73,0x69,0x67,0x6e,0x28,0x28,0x63,0x2e,0x79,0x20, - 0x2a,0x20,0x5f,0x31,0x32,0x33,0x35,0x29,0x20,0x2d,0x20,0x28,0x63,0x2e,0x78,0x20, - 0x2a,0x20,0x70,0x6f,0x73,0x2e,0x79,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x43,0x61,0x70,0x70,0x65,0x64,0x54,0x6f,0x72, - 0x75,0x73,0x28,0x69,0x6e,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c, - 0x20,0x76,0x65,0x63,0x32,0x20,0x73,0x63,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x72,0x61,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x62,0x29,0x0a,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x70,0x2e,0x78,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x2e, - 0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33, - 0x38,0x39,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28,0x73,0x63,0x2e, - 0x79,0x20,0x2a,0x20,0x70,0x2e,0x78,0x29,0x20,0x3e,0x20,0x28,0x73,0x63,0x2e,0x78, - 0x20,0x2a,0x20,0x70,0x2e,0x79,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x33,0x38,0x39,0x20,0x3d,0x20,0x64,0x6f, - 0x74,0x28,0x70,0x2e,0x78,0x79,0x2c,0x20,0x73,0x63,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x33,0x38,0x39,0x20,0x3d, - 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78,0x79,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, - 0x73,0x71,0x72,0x74,0x28,0x28,0x64,0x6f,0x74,0x28,0x70,0x2c,0x20,0x70,0x29,0x20, - 0x2b,0x20,0x28,0x72,0x61,0x20,0x2a,0x20,0x72,0x61,0x29,0x29,0x20,0x2d,0x20,0x28, - 0x28,0x32,0x2e,0x30,0x20,0x2a,0x20,0x72,0x61,0x29,0x20,0x2a,0x20,0x5f,0x33,0x38, - 0x39,0x29,0x29,0x20,0x2d,0x20,0x72,0x62,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x73,0x64,0x43,0x61,0x70,0x73,0x75,0x6c,0x65,0x28,0x76,0x65,0x63, - 0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x61,0x2c,0x20,0x76,0x65,0x63, - 0x33,0x20,0x62,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x29,0x0a,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x35,0x35,0x37,0x20,0x3d,0x20, - 0x70,0x20,0x2d,0x20,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20, - 0x5f,0x35,0x36,0x31,0x20,0x3d,0x20,0x62,0x20,0x2d,0x20,0x61,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28, - 0x5f,0x35,0x35,0x37,0x20,0x2d,0x20,0x28,0x5f,0x35,0x36,0x31,0x20,0x2a,0x20,0x63, - 0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x5f,0x35,0x35,0x37,0x2c,0x20,0x5f, - 0x35,0x36,0x31,0x29,0x20,0x2f,0x20,0x64,0x6f,0x74,0x28,0x5f,0x35,0x36,0x31,0x2c, - 0x20,0x5f,0x35,0x36,0x31,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30, - 0x29,0x29,0x29,0x20,0x2d,0x20,0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x73,0x64,0x43,0x79,0x6c,0x69,0x6e,0x64,0x65,0x72,0x28,0x76,0x65,0x63, - 0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x38,0x35,0x38,0x20,0x3d,0x20,0x61, - 0x62,0x73,0x28,0x76,0x65,0x63,0x32,0x28,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70, - 0x2e,0x78,0x7a,0x29,0x2c,0x20,0x70,0x2e,0x79,0x29,0x29,0x20,0x2d,0x20,0x68,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x69,0x6e,0x28, - 0x6d,0x61,0x78,0x28,0x5f,0x38,0x35,0x38,0x2e,0x78,0x2c,0x20,0x5f,0x38,0x35,0x38, - 0x2e,0x79,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2b,0x20,0x6c,0x65,0x6e,0x67, - 0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x5f,0x38,0x35,0x38,0x2c,0x20,0x76,0x65,0x63, - 0x32,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x73,0x64,0x48,0x65,0x78,0x50,0x72,0x69,0x73,0x6d,0x28,0x69,0x6e, - 0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x32, - 0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x61,0x62, - 0x73,0x28,0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f, - 0x34,0x33,0x35,0x20,0x3d,0x20,0x70,0x2e,0x78,0x79,0x20,0x2d,0x20,0x28,0x76,0x65, - 0x63,0x32,0x28,0x2d,0x30,0x2e,0x38,0x36,0x36,0x30,0x32,0x35,0x33,0x38,0x38,0x32, - 0x34,0x30,0x38,0x31,0x34,0x32,0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,0x2c,0x20, - 0x30,0x2e,0x35,0x29,0x20,0x2a,0x20,0x28,0x32,0x2e,0x30,0x20,0x2a,0x20,0x6d,0x69, - 0x6e,0x28,0x64,0x6f,0x74,0x28,0x76,0x65,0x63,0x32,0x28,0x2d,0x30,0x2e,0x38,0x36, - 0x36,0x30,0x32,0x35,0x33,0x38,0x38,0x32,0x34,0x30,0x38,0x31,0x34,0x32,0x30,0x38, - 0x39,0x38,0x34,0x33,0x37,0x35,0x2c,0x20,0x30,0x2e,0x35,0x29,0x2c,0x20,0x70,0x2e, - 0x78,0x79,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x70,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x34,0x33,0x35,0x2e,0x78, - 0x2c,0x20,0x5f,0x34,0x33,0x35,0x2e,0x79,0x2c,0x20,0x70,0x2e,0x7a,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x36,0x33,0x20,0x3d, - 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78,0x79,0x20,0x2d,0x20,0x76, - 0x65,0x63,0x32,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x70,0x2e,0x78,0x2c,0x20,0x28, - 0x2d,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x30,0x32,0x30,0x34,0x30,0x38,0x36, - 0x33,0x30,0x33,0x37,0x31,0x30,0x39,0x33,0x37,0x35,0x29,0x20,0x2a,0x20,0x68,0x2e, - 0x78,0x2c,0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x30,0x32,0x30,0x34,0x30, - 0x38,0x36,0x33,0x30,0x33,0x37,0x31,0x30,0x39,0x33,0x37,0x35,0x20,0x2a,0x20,0x68, - 0x2e,0x78,0x29,0x2c,0x20,0x68,0x2e,0x78,0x29,0x29,0x20,0x2a,0x20,0x73,0x69,0x67, - 0x6e,0x28,0x70,0x2e,0x79,0x20,0x2d,0x20,0x68,0x2e,0x78,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x36,0x38,0x20,0x3d,0x20,0x70, - 0x2e,0x7a,0x20,0x2d,0x20,0x68,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65, - 0x74,0x75,0x72,0x6e,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x61,0x78,0x28,0x5f,0x34,0x36, - 0x33,0x2c,0x20,0x5f,0x34,0x36,0x38,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2b, - 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x76,0x65,0x63,0x32, - 0x28,0x5f,0x34,0x36,0x33,0x2c,0x20,0x5f,0x34,0x36,0x38,0x29,0x2c,0x20,0x76,0x65, - 0x63,0x32,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c, - 0x6f,0x61,0x74,0x20,0x73,0x64,0x50,0x79,0x72,0x61,0x6d,0x69,0x64,0x28,0x69,0x6e, - 0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x5f,0x31,0x33,0x35,0x30,0x20,0x3d,0x20,0x68,0x20,0x2a,0x20,0x68,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x33,0x35,0x32,0x20, - 0x3d,0x20,0x5f,0x31,0x33,0x35,0x30,0x20,0x2b,0x20,0x30,0x2e,0x32,0x35,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x33,0x35,0x35,0x20,0x3d, - 0x20,0x61,0x62,0x73,0x28,0x70,0x2e,0x78,0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x70,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x31,0x33,0x35,0x35,0x2e,0x78, - 0x2c,0x20,0x70,0x2e,0x79,0x2c,0x20,0x5f,0x31,0x33,0x35,0x35,0x2e,0x79,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x33,0x36,0x33,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x70,0x2e,0x7a,0x20,0x3e,0x20,0x70, - 0x2e,0x78,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x5f,0x31,0x33,0x36,0x33,0x20,0x3d,0x20,0x70,0x2e,0x7a,0x78,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20, - 0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x31,0x33, - 0x36,0x33,0x20,0x3d,0x20,0x70,0x2e,0x78,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d, - 0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x31, - 0x33,0x36,0x33,0x2e,0x78,0x2c,0x20,0x70,0x2e,0x79,0x2c,0x20,0x5f,0x31,0x33,0x36, - 0x33,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f, - 0x31,0x33,0x37,0x37,0x20,0x3d,0x20,0x70,0x2e,0x78,0x7a,0x20,0x2d,0x20,0x76,0x65, - 0x63,0x32,0x28,0x30,0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d, - 0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x31,0x33,0x37,0x37,0x2e,0x78,0x2c,0x20,0x70, - 0x2e,0x79,0x2c,0x20,0x5f,0x31,0x33,0x37,0x37,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x33,0x39,0x30,0x20,0x3d,0x20, - 0x28,0x68,0x20,0x2a,0x20,0x70,0x2e,0x79,0x29,0x20,0x2d,0x20,0x28,0x30,0x2e,0x35, - 0x20,0x2a,0x20,0x70,0x2e,0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x31,0x33,0x39,0x38,0x20,0x3d,0x20,0x28,0x68,0x20,0x2a,0x20, - 0x70,0x2e,0x78,0x29,0x20,0x2b,0x20,0x28,0x30,0x2e,0x35,0x20,0x2a,0x20,0x70,0x2e, - 0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31, - 0x34,0x30,0x33,0x20,0x3d,0x20,0x2d,0x70,0x2e,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x34,0x31,0x35,0x20,0x3d,0x20,0x63,0x6c, - 0x61,0x6d,0x70,0x28,0x28,0x5f,0x31,0x33,0x39,0x30,0x20,0x2d,0x20,0x28,0x30,0x2e, - 0x35,0x20,0x2a,0x20,0x70,0x2e,0x7a,0x29,0x29,0x20,0x2f,0x20,0x28,0x5f,0x31,0x33, - 0x35,0x30,0x20,0x2b,0x20,0x30,0x2e,0x35,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20, - 0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x34,0x32,0x31,0x20,0x3d,0x20,0x70,0x2e,0x7a,0x20,0x2b,0x20,0x6d,0x61, - 0x78,0x28,0x5f,0x31,0x34,0x30,0x33,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x34,0x34,0x30,0x20,0x3d, - 0x20,0x70,0x2e,0x7a,0x20,0x2b,0x20,0x28,0x30,0x2e,0x35,0x20,0x2a,0x20,0x5f,0x31, - 0x34,0x31,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x34,0x35,0x33,0x20,0x3d,0x20,0x5f,0x31,0x33,0x39,0x30,0x20,0x2d,0x20, - 0x28,0x5f,0x31,0x33,0x35,0x32,0x20,0x2a,0x20,0x5f,0x31,0x34,0x31,0x35,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x34,0x37,0x36, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6d,0x69,0x6e,0x28,0x5f,0x31, - 0x33,0x39,0x30,0x2c,0x20,0x28,0x5f,0x31,0x34,0x30,0x33,0x20,0x2a,0x20,0x5f,0x31, - 0x33,0x35,0x32,0x29,0x20,0x2d,0x20,0x28,0x5f,0x31,0x33,0x39,0x30,0x20,0x2a,0x20, - 0x30,0x2e,0x35,0x29,0x29,0x20,0x3e,0x20,0x30,0x2e,0x30,0x29,0x0a,0x20,0x20,0x20, - 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x31,0x34,0x37,0x36, - 0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20, - 0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x5f,0x31,0x34,0x37,0x36,0x20,0x3d,0x20,0x6d,0x69,0x6e, - 0x28,0x28,0x28,0x5f,0x31,0x33,0x35,0x32,0x20,0x2a,0x20,0x5f,0x31,0x34,0x32,0x31, - 0x29,0x20,0x2a,0x20,0x5f,0x31,0x34,0x32,0x31,0x29,0x20,0x2b,0x20,0x28,0x5f,0x31, - 0x33,0x39,0x30,0x20,0x2a,0x20,0x5f,0x31,0x33,0x39,0x30,0x29,0x2c,0x20,0x28,0x28, - 0x5f,0x31,0x33,0x35,0x32,0x20,0x2a,0x20,0x5f,0x31,0x34,0x34,0x30,0x29,0x20,0x2a, - 0x20,0x5f,0x31,0x34,0x34,0x30,0x29,0x20,0x2b,0x20,0x28,0x5f,0x31,0x34,0x35,0x33, - 0x20,0x2a,0x20,0x5f,0x31,0x34,0x35,0x33,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x71,0x72, - 0x74,0x28,0x28,0x5f,0x31,0x34,0x37,0x36,0x20,0x2b,0x20,0x28,0x5f,0x31,0x33,0x39, - 0x38,0x20,0x2a,0x20,0x5f,0x31,0x33,0x39,0x38,0x29,0x29,0x20,0x2f,0x20,0x5f,0x31, - 0x33,0x35,0x32,0x29,0x20,0x2a,0x20,0x73,0x69,0x67,0x6e,0x28,0x6d,0x61,0x78,0x28, - 0x5f,0x31,0x33,0x39,0x38,0x2c,0x20,0x2d,0x70,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x7d, - 0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x4f,0x63,0x74,0x61,0x68,0x65, - 0x64,0x72,0x6f,0x6e,0x28,0x69,0x6e,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20, - 0x70,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x29,0x0a,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x70,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x32,0x38,0x35,0x20,0x3d,0x20, - 0x28,0x28,0x70,0x2e,0x78,0x20,0x2b,0x20,0x70,0x2e,0x79,0x29,0x20,0x2b,0x20,0x70, - 0x2e,0x7a,0x29,0x20,0x2d,0x20,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x71,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28,0x33,0x2e, - 0x30,0x20,0x2a,0x20,0x70,0x2e,0x78,0x29,0x20,0x3c,0x20,0x5f,0x31,0x32,0x38,0x35, - 0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x71,0x20,0x3d,0x20,0x70,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20, - 0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28,0x33,0x2e,0x30,0x20,0x2a,0x20,0x70, - 0x2e,0x79,0x29,0x20,0x3c,0x20,0x5f,0x31,0x32,0x38,0x35,0x29,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x71,0x20,0x3d,0x20,0x70,0x2e,0x79,0x7a,0x78,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28, - 0x33,0x2e,0x30,0x20,0x2a,0x20,0x70,0x2e,0x7a,0x29,0x20,0x3c,0x20,0x5f,0x31,0x32, - 0x38,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x71,0x20,0x3d,0x20,0x70,0x2e,0x7a,0x78,0x79,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e, - 0x20,0x5f,0x31,0x32,0x38,0x35,0x20,0x2a,0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35, - 0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36, - 0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20, - 0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x33,0x33, - 0x30,0x20,0x3d,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x30,0x2e,0x35,0x20,0x2a,0x20, - 0x28,0x28,0x71,0x2e,0x7a,0x20,0x2d,0x20,0x71,0x2e,0x79,0x29,0x20,0x2b,0x20,0x73, - 0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x73,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x76,0x65, - 0x63,0x33,0x28,0x71,0x2e,0x78,0x2c,0x20,0x28,0x71,0x2e,0x79,0x20,0x2d,0x20,0x73, - 0x29,0x20,0x2b,0x20,0x5f,0x31,0x33,0x33,0x30,0x2c,0x20,0x71,0x2e,0x7a,0x20,0x2d, - 0x20,0x5f,0x31,0x33,0x33,0x30,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x73,0x64,0x54,0x72,0x69,0x50,0x72,0x69,0x73,0x6d,0x28,0x69,0x6e, - 0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x69,0x6e,0x6f,0x75, - 0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20, - 0x68,0x2e,0x78,0x20,0x2a,0x3d,0x20,0x30,0x2e,0x38,0x36,0x36,0x30,0x32,0x35,0x33, - 0x38,0x38,0x32,0x34,0x30,0x38,0x31,0x34,0x32,0x30,0x38,0x39,0x38,0x34,0x33,0x37, - 0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x37,0x36,0x38, - 0x20,0x3d,0x20,0x70,0x2e,0x78,0x79,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x68, - 0x2e,0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x76,0x65,0x63, - 0x33,0x28,0x5f,0x37,0x36,0x38,0x2e,0x78,0x2c,0x20,0x5f,0x37,0x36,0x38,0x2e,0x79, - 0x2c,0x20,0x70,0x2e,0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x70,0x2e,0x78,0x20, - 0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x2e,0x78,0x29,0x20,0x2d,0x20,0x31,0x2e,0x30, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x70,0x2e,0x79,0x20,0x2b,0x3d,0x20,0x30,0x2e,0x35, - 0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37, - 0x32,0x36,0x35,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28, - 0x28,0x70,0x2e,0x78,0x20,0x2b,0x20,0x28,0x31,0x2e,0x37,0x33,0x32,0x30,0x35,0x30, - 0x37,0x37,0x36,0x34,0x38,0x31,0x36,0x32,0x38,0x34,0x31,0x37,0x39,0x36,0x38,0x37, - 0x35,0x20,0x2a,0x20,0x70,0x2e,0x79,0x29,0x29,0x20,0x3e,0x20,0x30,0x2e,0x30,0x29, - 0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x5f,0x38,0x30,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28, - 0x70,0x2e,0x78,0x20,0x2d,0x20,0x28,0x31,0x2e,0x37,0x33,0x32,0x30,0x35,0x30,0x37, - 0x37,0x36,0x34,0x38,0x31,0x36,0x32,0x38,0x34,0x31,0x37,0x39,0x36,0x38,0x37,0x35, - 0x20,0x2a,0x20,0x70,0x2e,0x79,0x29,0x2c,0x20,0x28,0x28,0x2d,0x31,0x2e,0x37,0x33, - 0x32,0x30,0x35,0x30,0x37,0x37,0x36,0x34,0x38,0x31,0x36,0x32,0x38,0x34,0x31,0x37, - 0x39,0x36,0x38,0x37,0x35,0x29,0x20,0x2a,0x20,0x70,0x2e,0x78,0x29,0x20,0x2d,0x20, - 0x70,0x2e,0x79,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x35,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x5f,0x38,0x30,0x36,0x2e,0x78,0x2c,0x20,0x5f,0x38,0x30,0x36,0x2e, - 0x79,0x2c,0x20,0x70,0x2e,0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20, - 0x20,0x20,0x20,0x70,0x2e,0x78,0x20,0x2d,0x3d,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28, - 0x70,0x2e,0x78,0x2c,0x20,0x2d,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x38,0x32,0x38,0x20, - 0x3d,0x20,0x28,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78,0x79,0x29,0x20, - 0x2a,0x20,0x73,0x69,0x67,0x6e,0x28,0x2d,0x70,0x2e,0x79,0x29,0x29,0x20,0x2a,0x20, - 0x68,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x38,0x33,0x35,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x70,0x2e,0x7a,0x29,0x20,0x2d, - 0x20,0x68,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e, - 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x76,0x65,0x63,0x32, - 0x28,0x5f,0x38,0x32,0x38,0x2c,0x20,0x5f,0x38,0x33,0x35,0x29,0x2c,0x20,0x76,0x65, - 0x63,0x32,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x20,0x2b,0x20,0x6d,0x69,0x6e,0x28, - 0x6d,0x61,0x78,0x28,0x5f,0x38,0x32,0x38,0x2c,0x20,0x5f,0x38,0x33,0x35,0x29,0x2c, - 0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x73,0x64,0x45,0x6c,0x6c,0x69,0x70,0x73,0x6f,0x69,0x64,0x28,0x76,0x65,0x63,0x33, - 0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72,0x29,0x0a,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x34,0x30,0x20,0x3d,0x20,0x6c, - 0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x20,0x2f,0x20,0x72,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x5f,0x33,0x34,0x30,0x20,0x2a, - 0x20,0x28,0x5f,0x33,0x34,0x30,0x20,0x2d,0x20,0x31,0x2e,0x30,0x29,0x29,0x20,0x2f, - 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x20,0x2f,0x20,0x28,0x72,0x20,0x2a, - 0x20,0x72,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6e, - 0x64,0x6f,0x74,0x28,0x76,0x65,0x63,0x32,0x20,0x61,0x2c,0x20,0x76,0x65,0x63,0x32, - 0x20,0x62,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e, - 0x20,0x28,0x61,0x2e,0x78,0x20,0x2a,0x20,0x62,0x2e,0x78,0x29,0x20,0x2d,0x20,0x28, - 0x61,0x2e,0x79,0x20,0x2a,0x20,0x62,0x2e,0x79,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x52,0x68,0x6f,0x6d,0x62,0x75,0x73,0x28,0x69, - 0x6e,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x6c,0x61,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6c,0x62,0x2c, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x68,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x72,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x61,0x62, - 0x73,0x28,0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f, - 0x31,0x35,0x30,0x39,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x6c,0x61,0x2c,0x20, - 0x6c,0x62,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x20,0x3d,0x20,0x5f,0x31,0x35,0x30,0x39,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20, - 0x5f,0x31,0x35,0x30,0x39,0x20,0x2d,0x20,0x28,0x70,0x2e,0x78,0x7a,0x20,0x2a,0x20, - 0x32,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x35,0x32,0x34,0x20,0x3d,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x6e,0x64, - 0x6f,0x74,0x28,0x70,0x61,0x72,0x61,0x6d,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x29,0x20,0x2f,0x20,0x64,0x6f,0x74,0x28,0x5f,0x31,0x35,0x30,0x39,0x2c,0x20, - 0x5f,0x31,0x35,0x30,0x39,0x29,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31, - 0x35,0x35,0x38,0x20,0x3d,0x20,0x28,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e, - 0x78,0x7a,0x20,0x2d,0x20,0x28,0x28,0x5f,0x31,0x35,0x30,0x39,0x20,0x2a,0x20,0x30, - 0x2e,0x35,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x31,0x2e,0x30,0x20,0x2d, - 0x20,0x5f,0x31,0x35,0x32,0x34,0x2c,0x20,0x31,0x2e,0x30,0x20,0x2b,0x20,0x5f,0x31, - 0x35,0x32,0x34,0x29,0x29,0x29,0x20,0x2a,0x20,0x73,0x69,0x67,0x6e,0x28,0x28,0x28, - 0x70,0x2e,0x78,0x20,0x2a,0x20,0x6c,0x62,0x29,0x20,0x2b,0x20,0x28,0x70,0x2e,0x7a, - 0x20,0x2a,0x20,0x6c,0x61,0x29,0x29,0x20,0x2d,0x20,0x28,0x6c,0x61,0x20,0x2a,0x20, - 0x6c,0x62,0x29,0x29,0x29,0x20,0x2d,0x20,0x72,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x35,0x36,0x32,0x20,0x3d,0x20,0x70,0x2e, - 0x79,0x20,0x2d,0x20,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72, - 0x6e,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x61,0x78,0x28,0x5f,0x31,0x35,0x35,0x38,0x2c, - 0x20,0x5f,0x31,0x35,0x36,0x32,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2b,0x20, - 0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x76,0x65,0x63,0x32,0x28, - 0x5f,0x31,0x35,0x35,0x38,0x2c,0x20,0x5f,0x31,0x35,0x36,0x32,0x29,0x2c,0x20,0x76, - 0x65,0x63,0x32,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x4f,0x63,0x74,0x6f,0x67,0x6f,0x6e,0x50,0x72, - 0x69,0x73,0x6d,0x28,0x69,0x6e,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x61,0x62, - 0x73,0x28,0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f, - 0x34,0x39,0x36,0x20,0x3d,0x20,0x70,0x2e,0x78,0x79,0x20,0x2d,0x20,0x28,0x76,0x65, - 0x63,0x32,0x28,0x2d,0x30,0x2e,0x39,0x32,0x33,0x38,0x37,0x39,0x35,0x30,0x34,0x32, - 0x30,0x33,0x37,0x39,0x36,0x33,0x38,0x36,0x37,0x31,0x38,0x37,0x35,0x2c,0x20,0x30, - 0x2e,0x33,0x38,0x32,0x36,0x38,0x33,0x34,0x32,0x36,0x31,0x34,0x31,0x37,0x33,0x38, - 0x38,0x39,0x31,0x36,0x30,0x31,0x35,0x36,0x32,0x35,0x29,0x20,0x2a,0x20,0x28,0x32, - 0x2e,0x30,0x20,0x2a,0x20,0x6d,0x69,0x6e,0x28,0x64,0x6f,0x74,0x28,0x76,0x65,0x63, - 0x32,0x28,0x2d,0x30,0x2e,0x39,0x32,0x33,0x38,0x37,0x39,0x35,0x30,0x34,0x32,0x30, - 0x33,0x37,0x39,0x36,0x33,0x38,0x36,0x37,0x31,0x38,0x37,0x35,0x2c,0x20,0x30,0x2e, - 0x33,0x38,0x32,0x36,0x38,0x33,0x34,0x32,0x36,0x31,0x34,0x31,0x37,0x33,0x38,0x38, - 0x39,0x31,0x36,0x30,0x31,0x35,0x36,0x32,0x35,0x29,0x2c,0x20,0x70,0x2e,0x78,0x79, - 0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x70, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x34,0x39,0x36,0x2e,0x78,0x2c,0x20, - 0x5f,0x34,0x39,0x36,0x2e,0x79,0x2c,0x20,0x70,0x2e,0x7a,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x35,0x30,0x39,0x20,0x3d,0x20,0x70,0x2e, - 0x78,0x79,0x20,0x2d,0x20,0x28,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x39,0x32,0x33, - 0x38,0x37,0x39,0x35,0x30,0x34,0x32,0x30,0x33,0x37,0x39,0x36,0x33,0x38,0x36,0x37, - 0x31,0x38,0x37,0x35,0x2c,0x20,0x30,0x2e,0x33,0x38,0x32,0x36,0x38,0x33,0x34,0x32, - 0x36,0x31,0x34,0x31,0x37,0x33,0x38,0x38,0x39,0x31,0x36,0x30,0x31,0x35,0x36,0x32, - 0x35,0x29,0x20,0x2a,0x20,0x28,0x32,0x2e,0x30,0x20,0x2a,0x20,0x6d,0x69,0x6e,0x28, - 0x64,0x6f,0x74,0x28,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x39,0x32,0x33,0x38,0x37, - 0x39,0x35,0x30,0x34,0x32,0x30,0x33,0x37,0x39,0x36,0x33,0x38,0x36,0x37,0x31,0x38, - 0x37,0x35,0x2c,0x20,0x30,0x2e,0x33,0x38,0x32,0x36,0x38,0x33,0x34,0x32,0x36,0x31, - 0x34,0x31,0x37,0x33,0x38,0x38,0x39,0x31,0x36,0x30,0x31,0x35,0x36,0x32,0x35,0x29, - 0x2c,0x20,0x70,0x2e,0x78,0x79,0x29,0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x35, - 0x30,0x39,0x2e,0x78,0x2c,0x20,0x5f,0x35,0x30,0x39,0x2e,0x79,0x2c,0x20,0x70,0x2e, - 0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x35,0x32, - 0x35,0x20,0x3d,0x20,0x70,0x2e,0x78,0x79,0x20,0x2d,0x20,0x76,0x65,0x63,0x32,0x28, - 0x63,0x6c,0x61,0x6d,0x70,0x28,0x70,0x2e,0x78,0x2c,0x20,0x28,0x2d,0x30,0x2e,0x34, - 0x31,0x34,0x32,0x31,0x33,0x35,0x36,0x37,0x39,0x37,0x32,0x31,0x38,0x33,0x32,0x32, - 0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x29,0x20,0x2a,0x20,0x72,0x2c,0x20,0x30, - 0x2e,0x34,0x31,0x34,0x32,0x31,0x33,0x35,0x36,0x37,0x39,0x37,0x32,0x31,0x38,0x33, - 0x32,0x32,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x20,0x2a,0x20,0x72,0x29,0x2c, - 0x20,0x72,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x70,0x20,0x3d,0x20,0x76,0x65,0x63, - 0x33,0x28,0x5f,0x35,0x32,0x35,0x2e,0x78,0x2c,0x20,0x5f,0x35,0x32,0x35,0x2e,0x79, - 0x2c,0x20,0x70,0x2e,0x7a,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x5f,0x35,0x33,0x35,0x20,0x3d,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28, - 0x70,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x73,0x69,0x67,0x6e,0x28,0x70,0x2e,0x79, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,0x33, - 0x39,0x20,0x3d,0x20,0x70,0x2e,0x7a,0x20,0x2d,0x20,0x68,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x69,0x6e,0x28,0x6d,0x61,0x78,0x28, - 0x5f,0x35,0x33,0x35,0x2c,0x20,0x5f,0x35,0x33,0x39,0x29,0x2c,0x20,0x30,0x2e,0x30, - 0x29,0x20,0x2b,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x6d,0x61,0x78,0x28,0x76, - 0x65,0x63,0x32,0x28,0x5f,0x35,0x33,0x35,0x2c,0x20,0x5f,0x35,0x33,0x39,0x29,0x2c, - 0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a, - 0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x43,0x79,0x6c,0x69,0x6e,0x64,0x65, - 0x72,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x61, - 0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x62,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x72,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x38, - 0x37,0x35,0x20,0x3d,0x20,0x70,0x20,0x2d,0x20,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x76,0x65,0x63,0x33,0x20,0x5f,0x38,0x37,0x39,0x20,0x3d,0x20,0x62,0x20,0x2d,0x20, - 0x61,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x38,0x38, - 0x33,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x38,0x37,0x39,0x2c,0x20,0x5f,0x38, - 0x37,0x39,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x38,0x38,0x37,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x38,0x37,0x35,0x2c,0x20, - 0x5f,0x38,0x37,0x39,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x5f,0x39,0x30,0x30,0x20,0x3d,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x28, - 0x5f,0x38,0x37,0x35,0x20,0x2a,0x20,0x5f,0x38,0x38,0x33,0x29,0x20,0x2d,0x20,0x28, - 0x5f,0x38,0x37,0x39,0x20,0x2a,0x20,0x5f,0x38,0x38,0x37,0x29,0x29,0x20,0x2d,0x20, - 0x28,0x72,0x20,0x2a,0x20,0x5f,0x38,0x38,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x39,0x30,0x34,0x20,0x3d,0x20,0x5f,0x38,0x38, - 0x33,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x39,0x30,0x39,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x5f,0x38, - 0x38,0x37,0x20,0x2d,0x20,0x5f,0x39,0x30,0x34,0x29,0x20,0x2d,0x20,0x5f,0x39,0x30, - 0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x39,0x31, - 0x33,0x20,0x3d,0x20,0x5f,0x39,0x30,0x30,0x20,0x2a,0x20,0x5f,0x39,0x30,0x30,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x39,0x31,0x39,0x20, - 0x3d,0x20,0x28,0x5f,0x39,0x30,0x39,0x20,0x2a,0x20,0x5f,0x39,0x30,0x39,0x29,0x20, - 0x2a,0x20,0x5f,0x38,0x38,0x33,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x5f,0x39,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28, - 0x6d,0x61,0x78,0x28,0x5f,0x39,0x30,0x30,0x2c,0x20,0x5f,0x39,0x30,0x39,0x29,0x20, - 0x3c,0x20,0x30,0x2e,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x5f,0x39,0x32,0x35,0x20,0x3d,0x20,0x2d,0x6d,0x69,0x6e, - 0x28,0x5f,0x39,0x31,0x33,0x2c,0x20,0x5f,0x39,0x31,0x39,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20, - 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x39,0x32,0x35,0x20, - 0x3d,0x20,0x28,0x28,0x5f,0x39,0x30,0x30,0x20,0x3e,0x20,0x30,0x2e,0x30,0x29,0x20, - 0x3f,0x20,0x5f,0x39,0x31,0x33,0x20,0x3a,0x20,0x30,0x2e,0x30,0x29,0x20,0x2b,0x20, - 0x28,0x28,0x5f,0x39,0x30,0x39,0x20,0x3e,0x20,0x30,0x2e,0x30,0x29,0x20,0x3f,0x20, - 0x5f,0x39,0x31,0x39,0x20,0x3a,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73, - 0x69,0x67,0x6e,0x28,0x5f,0x39,0x32,0x35,0x29,0x20,0x2a,0x20,0x73,0x71,0x72,0x74, - 0x28,0x61,0x62,0x73,0x28,0x5f,0x39,0x32,0x35,0x29,0x29,0x29,0x20,0x2f,0x20,0x5f, - 0x38,0x38,0x33,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64, - 0x43,0x61,0x70,0x70,0x65,0x64,0x43,0x6f,0x6e,0x65,0x28,0x76,0x65,0x63,0x33,0x20, - 0x70,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x61,0x2c,0x20,0x76,0x65,0x63,0x33,0x20, - 0x62,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x61,0x2c,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x72,0x62,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x31,0x31,0x32,0x30,0x20,0x3d,0x20,0x72,0x62,0x20,0x2d,0x20, - 0x72,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31, - 0x31,0x32,0x38,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x62,0x20,0x2d,0x20,0x61,0x2c, - 0x20,0x62,0x20,0x2d,0x20,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x31,0x31,0x34,0x34,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x70, - 0x20,0x2d,0x20,0x61,0x2c,0x20,0x62,0x20,0x2d,0x20,0x61,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x31,0x34,0x36,0x20,0x3d,0x20, - 0x5f,0x31,0x31,0x34,0x34,0x20,0x2f,0x20,0x5f,0x31,0x31,0x32,0x38,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x31,0x35,0x35,0x20,0x3d, - 0x20,0x73,0x71,0x72,0x74,0x28,0x64,0x6f,0x74,0x28,0x70,0x20,0x2d,0x20,0x61,0x2c, - 0x20,0x70,0x20,0x2d,0x20,0x61,0x29,0x20,0x2d,0x20,0x28,0x28,0x5f,0x31,0x31,0x34, - 0x36,0x20,0x2a,0x20,0x5f,0x31,0x31,0x34,0x36,0x29,0x20,0x2a,0x20,0x5f,0x31,0x31, - 0x32,0x38,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x31,0x36,0x34,0x20,0x3d,0x20,0x6d,0x61,0x78,0x28,0x30,0x2e,0x30,0x2c, - 0x20,0x5f,0x31,0x31,0x35,0x35,0x20,0x2d,0x20,0x28,0x28,0x5f,0x31,0x31,0x34,0x36, - 0x20,0x3c,0x20,0x30,0x2e,0x35,0x29,0x20,0x3f,0x20,0x72,0x61,0x20,0x3a,0x20,0x72, - 0x62,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x31,0x31,0x36,0x39,0x20,0x3d,0x20,0x61,0x62,0x73,0x28,0x5f,0x31,0x31,0x34,0x36, - 0x20,0x2d,0x20,0x30,0x2e,0x35,0x29,0x20,0x2d,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x31,0x38,0x38,0x20,0x3d, - 0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x28,0x28,0x5f,0x31,0x31,0x32,0x30,0x20,0x2a, - 0x20,0x28,0x5f,0x31,0x31,0x35,0x35,0x20,0x2d,0x20,0x72,0x61,0x29,0x29,0x20,0x2b, - 0x20,0x5f,0x31,0x31,0x34,0x34,0x29,0x20,0x2f,0x20,0x28,0x28,0x5f,0x31,0x31,0x32, - 0x30,0x20,0x2a,0x20,0x5f,0x31,0x31,0x32,0x30,0x29,0x20,0x2b,0x20,0x5f,0x31,0x31, - 0x32,0x38,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x31,0x39,0x36,0x20, - 0x3d,0x20,0x28,0x5f,0x31,0x31,0x35,0x35,0x20,0x2d,0x20,0x72,0x61,0x29,0x20,0x2d, - 0x20,0x28,0x5f,0x31,0x31,0x38,0x38,0x20,0x2a,0x20,0x5f,0x31,0x31,0x32,0x30,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x32,0x30, - 0x30,0x20,0x3d,0x20,0x5f,0x31,0x31,0x34,0x36,0x20,0x2d,0x20,0x5f,0x31,0x31,0x38, - 0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x28, - 0x28,0x5f,0x31,0x31,0x39,0x36,0x20,0x3c,0x20,0x30,0x2e,0x30,0x29,0x20,0x26,0x26, - 0x20,0x28,0x5f,0x31,0x31,0x36,0x39,0x20,0x3c,0x20,0x30,0x2e,0x30,0x29,0x29,0x20, - 0x3f,0x20,0x28,0x2d,0x31,0x2e,0x30,0x29,0x20,0x3a,0x20,0x31,0x2e,0x30,0x29,0x20, - 0x2a,0x20,0x73,0x71,0x72,0x74,0x28,0x6d,0x69,0x6e,0x28,0x28,0x5f,0x31,0x31,0x36, - 0x34,0x20,0x2a,0x20,0x5f,0x31,0x31,0x36,0x34,0x29,0x20,0x2b,0x20,0x28,0x28,0x5f, - 0x31,0x31,0x36,0x39,0x20,0x2a,0x20,0x5f,0x31,0x31,0x36,0x39,0x29,0x20,0x2a,0x20, - 0x5f,0x31,0x31,0x32,0x38,0x29,0x2c,0x20,0x28,0x5f,0x31,0x31,0x39,0x36,0x20,0x2a, - 0x20,0x5f,0x31,0x31,0x39,0x36,0x29,0x20,0x2b,0x20,0x28,0x28,0x5f,0x31,0x32,0x30, - 0x30,0x20,0x2a,0x20,0x5f,0x31,0x32,0x30,0x30,0x29,0x20,0x2a,0x20,0x5f,0x31,0x31, - 0x32,0x38,0x29,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x64,0x6f,0x74,0x32,0x28,0x76,0x65,0x63,0x33,0x20,0x76,0x29,0x0a,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x74,0x28,0x76,0x2c, - 0x20,0x76,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64, - 0x52,0x6f,0x75,0x6e,0x64,0x43,0x6f,0x6e,0x65,0x28,0x76,0x65,0x63,0x33,0x20,0x70, - 0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x61,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x62, - 0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x31,0x2c,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x72,0x32,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33, - 0x20,0x5f,0x36,0x34,0x33,0x20,0x3d,0x20,0x62,0x20,0x2d,0x20,0x61,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x34,0x37,0x20,0x3d,0x20, - 0x64,0x6f,0x74,0x28,0x5f,0x36,0x34,0x33,0x2c,0x20,0x5f,0x36,0x34,0x33,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x35,0x31,0x20, - 0x3d,0x20,0x72,0x31,0x20,0x2d,0x20,0x72,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x35,0x37,0x20,0x3d,0x20,0x5f,0x36,0x34,0x37, - 0x20,0x2d,0x20,0x28,0x5f,0x36,0x35,0x31,0x20,0x2a,0x20,0x5f,0x36,0x35,0x31,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x36,0x30, - 0x20,0x3d,0x20,0x31,0x2e,0x30,0x20,0x2f,0x20,0x5f,0x36,0x34,0x37,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x36,0x36,0x34,0x20,0x3d,0x20,0x70, - 0x20,0x2d,0x20,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x36,0x36,0x38,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x36,0x36,0x34,0x2c, - 0x20,0x5f,0x36,0x34,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x5f,0x36,0x37,0x32,0x20,0x3d,0x20,0x5f,0x36,0x36,0x38,0x20,0x2d,0x20, - 0x5f,0x36,0x34,0x37,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x28,0x5f,0x36,0x36,0x34,0x20,0x2a,0x20,0x5f, - 0x36,0x34,0x37,0x29,0x20,0x2d,0x20,0x28,0x5f,0x36,0x34,0x33,0x20,0x2a,0x20,0x5f, - 0x36,0x36,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x36,0x38,0x32,0x20,0x3d,0x20,0x64,0x6f,0x74,0x32,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36, - 0x38,0x38,0x20,0x3d,0x20,0x28,0x5f,0x36,0x36,0x38,0x20,0x2a,0x20,0x5f,0x36,0x36, - 0x38,0x29,0x20,0x2a,0x20,0x5f,0x36,0x34,0x37,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x39,0x34,0x20,0x3d,0x20,0x28,0x5f,0x36,0x37, - 0x32,0x20,0x2a,0x20,0x5f,0x36,0x37,0x32,0x29,0x20,0x2a,0x20,0x5f,0x36,0x34,0x37, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x37,0x30,0x33, - 0x20,0x3d,0x20,0x28,0x28,0x73,0x69,0x67,0x6e,0x28,0x5f,0x36,0x35,0x31,0x29,0x20, - 0x2a,0x20,0x5f,0x36,0x35,0x31,0x29,0x20,0x2a,0x20,0x5f,0x36,0x35,0x31,0x29,0x20, - 0x2a,0x20,0x5f,0x36,0x38,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28, - 0x28,0x28,0x73,0x69,0x67,0x6e,0x28,0x5f,0x36,0x37,0x32,0x29,0x20,0x2a,0x20,0x5f, - 0x36,0x35,0x37,0x29,0x20,0x2a,0x20,0x5f,0x36,0x39,0x34,0x29,0x20,0x3e,0x20,0x5f, - 0x37,0x30,0x33,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x71,0x72,0x74,0x28, - 0x5f,0x36,0x38,0x32,0x20,0x2b,0x20,0x5f,0x36,0x39,0x34,0x29,0x20,0x2a,0x20,0x5f, - 0x36,0x36,0x30,0x29,0x20,0x2d,0x20,0x72,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d, - 0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28,0x28,0x73,0x69,0x67,0x6e,0x28, - 0x5f,0x36,0x36,0x38,0x29,0x20,0x2a,0x20,0x5f,0x36,0x35,0x37,0x29,0x20,0x2a,0x20, - 0x5f,0x36,0x38,0x38,0x29,0x20,0x3c,0x20,0x5f,0x37,0x30,0x33,0x29,0x0a,0x20,0x20, - 0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75, - 0x72,0x6e,0x20,0x28,0x73,0x71,0x72,0x74,0x28,0x5f,0x36,0x38,0x32,0x20,0x2b,0x20, - 0x5f,0x36,0x38,0x38,0x29,0x20,0x2a,0x20,0x5f,0x36,0x36,0x30,0x29,0x20,0x2d,0x20, - 0x72,0x31,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65, - 0x74,0x75,0x72,0x6e,0x20,0x28,0x28,0x73,0x71,0x72,0x74,0x28,0x28,0x5f,0x36,0x38, - 0x32,0x20,0x2a,0x20,0x5f,0x36,0x35,0x37,0x29,0x20,0x2a,0x20,0x5f,0x36,0x36,0x30, - 0x29,0x20,0x2b,0x20,0x28,0x5f,0x36,0x36,0x38,0x20,0x2a,0x20,0x5f,0x36,0x35,0x31, - 0x29,0x29,0x20,0x2a,0x20,0x5f,0x36,0x36,0x30,0x29,0x20,0x2d,0x20,0x72,0x31,0x3b, - 0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x64,0x52,0x6f,0x75,0x6e, - 0x64,0x43,0x6f,0x6e,0x65,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x2c,0x20,0x66,0x6c, - 0x6f,0x61,0x74,0x20,0x72,0x31,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x72,0x32, - 0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x68,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x35,0x38,0x37,0x20,0x3d,0x20,0x76,0x65,0x63, - 0x32,0x28,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x70,0x2e,0x78,0x7a,0x29,0x2c,0x20, - 0x70,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x35,0x39,0x33,0x20,0x3d,0x20,0x28,0x72,0x31,0x20,0x2d,0x20,0x72,0x32,0x29, - 0x20,0x2f,0x20,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x35,0x39,0x39,0x20,0x3d,0x20,0x73,0x71,0x72,0x74,0x28,0x31,0x2e,0x30,0x20, - 0x2d,0x20,0x28,0x5f,0x35,0x39,0x33,0x20,0x2a,0x20,0x5f,0x35,0x39,0x33,0x29,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x30,0x36, - 0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x35,0x38,0x37,0x2c,0x20,0x76,0x65,0x63, - 0x32,0x28,0x2d,0x5f,0x35,0x39,0x33,0x2c,0x20,0x5f,0x35,0x39,0x39,0x29,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x36,0x30,0x36,0x20,0x3c,0x20, - 0x30,0x2e,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68, - 0x28,0x5f,0x35,0x38,0x37,0x29,0x20,0x2d,0x20,0x72,0x31,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x36,0x30,0x36,0x20, - 0x3e,0x20,0x28,0x5f,0x35,0x39,0x39,0x20,0x2a,0x20,0x68,0x29,0x29,0x0a,0x20,0x20, - 0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75, - 0x72,0x6e,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x5f,0x35,0x38,0x37,0x20,0x2d, - 0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x30,0x2c,0x20,0x68,0x29,0x29,0x20,0x2d, - 0x20,0x72,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72, - 0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x74,0x28,0x5f,0x35,0x38,0x37,0x2c,0x20, - 0x76,0x65,0x63,0x32,0x28,0x5f,0x35,0x39,0x39,0x2c,0x20,0x5f,0x35,0x39,0x33,0x29, - 0x29,0x20,0x2d,0x20,0x72,0x31,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x65,0x63,0x32,0x20, - 0x6d,0x61,0x70,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x6f,0x73,0x29,0x0a,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x76, - 0x65,0x63,0x32,0x28,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x2e, - 0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20, - 0x76,0x65,0x63,0x33,0x28,0x2d,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c, - 0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x30,0x2e,0x32,0x35,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x32,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x32, - 0x28,0x73,0x64,0x53,0x70,0x68,0x65,0x72,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x29,0x2c,0x20,0x32,0x36,0x2e,0x38,0x39, - 0x39,0x39,0x39,0x39,0x36,0x31,0x38,0x35,0x33,0x30,0x32,0x37,0x33,0x34,0x33,0x37, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70, - 0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x34,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30, - 0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31, - 0x32,0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x20,0x3d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33, - 0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37,0x35,0x2c,0x20, - 0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32, - 0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x32,0x2e,0x35,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x64,0x42,0x6f,0x78,0x28, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35, - 0x29,0x20,0x3c,0x20,0x72,0x65,0x73,0x2e,0x78,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x36,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c,0x20,0x30,0x2e, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28, - 0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32, - 0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32,0x35, - 0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30, - 0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x38,0x20,0x3d,0x20,0x30,0x2e,0x30,0x32,0x35,0x30,0x30, - 0x30,0x30,0x30,0x30,0x33,0x37,0x32,0x35,0x32,0x39,0x30,0x32,0x39,0x38,0x34,0x36, - 0x31,0x39,0x31,0x34,0x30,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x36,0x32,0x38,0x20,0x3d,0x20, - 0x73,0x64,0x42,0x6f,0x75,0x6e,0x64,0x69,0x6e,0x67,0x42,0x6f,0x78,0x28,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x36,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x20,0x3d, - 0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x20,0x3d,0x20,0x76,0x65, - 0x63,0x32,0x28,0x5f,0x31,0x36,0x32,0x38,0x2c,0x20,0x31,0x36,0x2e,0x38,0x39,0x39, - 0x39,0x39,0x39,0x36,0x31,0x38,0x35,0x33,0x30,0x32,0x37,0x33,0x34,0x33,0x37,0x35, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d, - 0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x2c,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x31,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x20,0x3d, - 0x20,0x28,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30, - 0x2c,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30, - 0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x31,0x2e, - 0x30,0x29,0x29,0x2e,0x78,0x7a,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x32,0x20,0x3d, - 0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x35, - 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34,0x35,0x30,0x35,0x38,0x30,0x35,0x39, - 0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x33,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x34,0x20, - 0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x54,0x6f,0x72,0x75,0x73,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31, - 0x32,0x29,0x2c,0x20,0x32,0x35,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x34,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x31,0x35,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20, - 0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x34,0x34,0x39,0x39, - 0x39,0x39,0x39,0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39,0x32, - 0x31,0x38,0x37,0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x36,0x30,0x30,0x30, - 0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39,0x31,0x30,0x31,0x35, - 0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31, - 0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x37,0x20,0x3d,0x20,0x30,0x2e,0x34,0x34,0x39, - 0x39,0x39,0x39,0x39,0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39, - 0x32,0x31,0x38,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x38,0x20,0x3d,0x20,0x72, - 0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x39,0x20,0x3d,0x20,0x76,0x65,0x63,0x32, - 0x28,0x73,0x64,0x43,0x6f,0x6e,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x35, - 0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x36,0x2c,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x37,0x29,0x2c,0x20,0x35,0x35,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x38,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x39,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x30,0x20,0x3d,0x20,0x70,0x6f,0x73, - 0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32, - 0x35,0x2c,0x20,0x2d,0x32,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x31, - 0x20,0x3d,0x20,0x30,0x2e,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x32,0x20, - 0x3d,0x20,0x30,0x2e,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x33,0x20,0x3d, - 0x20,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31, - 0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x32,0x34,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x32,0x35,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x43,0x61,0x70,0x70, - 0x65,0x64,0x43,0x6f,0x6e,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x30,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x32,0x32,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x33,0x29,0x2c,0x20, - 0x31,0x33,0x2e,0x36,0x37,0x30,0x30,0x30,0x30,0x30,0x37,0x36,0x32,0x39,0x33,0x39, - 0x34,0x35,0x33,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x32,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x35,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x32,0x36,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x2d,0x33,0x2e, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x37,0x20,0x3d,0x20,0x76,0x65,0x63,0x32, - 0x28,0x30,0x2e,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38, - 0x35,0x37,0x39,0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x38,0x30, - 0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35, - 0x30,0x37,0x38,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x38,0x20, - 0x3d,0x20,0x30,0x2e,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30, - 0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x32,0x39,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33, - 0x30,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x53,0x6f,0x6c,0x69,0x64, - 0x41,0x6e,0x67,0x6c,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x36,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x32,0x38,0x29,0x2c,0x20,0x34,0x39,0x2e,0x31,0x33,0x30,0x30,0x30,0x31,0x30,0x36, - 0x38,0x31,0x31,0x35,0x32,0x33,0x34,0x33,0x37,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x32,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x31,0x20,0x3d,0x20,0x70,0x6f, - 0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e, - 0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39, - 0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x33,0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x33,0x34,0x39,0x39, - 0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36, - 0x30,0x39,0x33,0x37,0x35,0x2c,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30, - 0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32, - 0x35,0x2c,0x20,0x32,0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20, - 0x28,0x73,0x64,0x42,0x6f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x31,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x32,0x29,0x20,0x3c,0x20,0x72,0x65,0x73, - 0x2e,0x78,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x33,0x20, - 0x3d,0x20,0x28,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x31,0x2e, - 0x30,0x2c,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32, - 0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x31, - 0x2e,0x30,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x2c, - 0x20,0x2d,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x33,0x34,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x38,0x36,0x36,0x30, - 0x32,0x34,0x39,0x37,0x31,0x30,0x30,0x38,0x33,0x30,0x30,0x37,0x38,0x31,0x32,0x35, - 0x2c,0x20,0x2d,0x30,0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x35,0x20, - 0x3d,0x20,0x30,0x2e,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x36,0x20,0x3d, - 0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34,0x35,0x30, - 0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x31,0x37,0x32,0x30,0x20,0x3d,0x20,0x73,0x64,0x43,0x61,0x70,0x70,0x65,0x64,0x54, - 0x6f,0x72,0x75,0x73,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x33,0x2c,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x33,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33, - 0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x36,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x33,0x37,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x38, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x37,0x32,0x30,0x2c,0x20,0x38, - 0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73, - 0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x37,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33, - 0x39,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x31, - 0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x34,0x30,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x33, - 0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35, - 0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c,0x20,0x30, - 0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31,0x31,0x36, - 0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x34,0x31,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34, - 0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x42,0x6f,0x78,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x33,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34, - 0x30,0x29,0x2c,0x20,0x33,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x34,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x32,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x34,0x33,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76, - 0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x2d,0x31, - 0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x34,0x20,0x3d,0x20,0x76,0x65,0x63, - 0x33,0x28,0x2d,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39, - 0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35, - 0x2c,0x20,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30, - 0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x2c, - 0x20,0x2d,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30, - 0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x34,0x35,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30, - 0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32, - 0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x34, - 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37, - 0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30, - 0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36, - 0x39,0x35,0x33,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x36,0x20, - 0x3d,0x20,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30, - 0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x34,0x37,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x34,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x43,0x61,0x70, - 0x73,0x75,0x6c,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x33,0x2c,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x34,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34, - 0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x36,0x29,0x2c,0x20,0x33,0x31, - 0x2e,0x38,0x39,0x39,0x39,0x39,0x39,0x36,0x31,0x38,0x35,0x33,0x30,0x32,0x37,0x33, - 0x34,0x33,0x37,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72, - 0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34, - 0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x38,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x34,0x39,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33, - 0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c,0x20,0x2d,0x32,0x2e,0x30, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x30,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28, - 0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36, - 0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x31,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x35,0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64, - 0x43,0x79,0x6c,0x69,0x6e,0x64,0x65,0x72,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34, - 0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x30,0x29,0x2c,0x20,0x38,0x2e, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20, - 0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x31,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x33, - 0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x31,0x2e, - 0x30,0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38, - 0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x2c, - 0x20,0x2d,0x33,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x34,0x20,0x3d,0x20, - 0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32, - 0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32, - 0x35,0x2c,0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34, - 0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x5f,0x31,0x37,0x37,0x36,0x20,0x3d,0x20,0x73,0x64,0x48,0x65,0x78,0x50, - 0x72,0x69,0x73,0x6d,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x33,0x2c,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x35,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x35,0x20, - 0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x36,0x20,0x3d,0x20,0x76, - 0x65,0x63,0x32,0x28,0x5f,0x31,0x37,0x37,0x36,0x2c,0x20,0x31,0x38,0x2e,0x33,0x39, - 0x39,0x39,0x39,0x39,0x36,0x31,0x38,0x35,0x33,0x30,0x32,0x37,0x33,0x34,0x33,0x37, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20, - 0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x35,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x36,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x35,0x37,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28, - 0x2d,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39, - 0x34,0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37, - 0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x38,0x20,0x3d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33, - 0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37,0x35,0x2c,0x20, - 0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35,0x33, - 0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37,0x35,0x2c,0x20,0x32,0x2e,0x35, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x64,0x42,0x6f,0x78, - 0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x35,0x38,0x29,0x20,0x3c,0x20,0x72,0x65,0x73,0x2e,0x78,0x29,0x0a,0x20,0x20, - 0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x39,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20, - 0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x31,0x2e,0x30,0x2c,0x20,0x2d,0x30,0x2e, - 0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39, - 0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x2d,0x33,0x2e,0x30,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x36,0x30,0x20,0x3d,0x20,0x31,0x2e,0x30,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x38,0x30, - 0x31,0x20,0x3d,0x20,0x73,0x64,0x50,0x79,0x72,0x61,0x6d,0x69,0x64,0x28,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x35,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x30, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x31,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x36,0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x38, - 0x30,0x31,0x2c,0x20,0x31,0x33,0x2e,0x35,0x36,0x30,0x30,0x30,0x30,0x34,0x31,0x39, - 0x36,0x31,0x36,0x36,0x39,0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x36,0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x33,0x20,0x3d,0x20,0x70,0x6f,0x73, - 0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e, - 0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34, - 0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x2d,0x32,0x2e,0x30,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x34,0x20,0x3d,0x20,0x30,0x2e,0x33,0x34,0x39, - 0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34, - 0x36,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x38,0x31,0x33,0x20,0x3d,0x20,0x73,0x64, - 0x4f,0x63,0x74,0x61,0x68,0x65,0x64,0x72,0x6f,0x6e,0x28,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x36,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x34,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x36,0x35,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x36,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x38,0x31,0x33,0x2c, - 0x20,0x32,0x33,0x2e,0x35,0x35,0x39,0x39,0x39,0x39,0x34,0x36,0x35,0x39,0x34,0x32, - 0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x36,0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x36,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x36,0x37,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76, - 0x65,0x63,0x33,0x28,0x2d,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x31,0x35,0x30,0x30, - 0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33, - 0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x36,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x33,0x30,0x30, - 0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30, - 0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30, - 0x30,0x30,0x37,0x34,0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38, - 0x32,0x38,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x38,0x32,0x36,0x20,0x3d,0x20,0x73,0x64, - 0x54,0x72,0x69,0x50,0x72,0x69,0x73,0x6d,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36, - 0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x38,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x36,0x39,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x30, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x38,0x32,0x36,0x2c,0x20,0x34, - 0x33,0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65, - 0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x36,0x39, - 0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x37,0x31,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28, - 0x2d,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x37,0x32,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30, - 0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32, - 0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32, - 0x35,0x2c,0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34, - 0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x33,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x37,0x34,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64, - 0x45,0x6c,0x6c,0x69,0x70,0x73,0x6f,0x69,0x64,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x37,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x32,0x29,0x2c,0x20,0x34, - 0x33,0x2e,0x31,0x36,0x39,0x39,0x39,0x38,0x31,0x36,0x38,0x39,0x34,0x35,0x33,0x31, - 0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73, - 0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x33,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37, - 0x35,0x20,0x3d,0x20,0x28,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28, - 0x2d,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x33,0x34,0x30,0x30,0x30,0x30,0x30,0x30, - 0x33,0x35,0x37,0x36,0x32,0x37,0x38,0x36,0x38,0x36,0x35,0x32,0x33,0x34,0x33,0x37, - 0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x2e,0x78,0x7a,0x79,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x37,0x36,0x20,0x3d,0x20,0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30,0x30, - 0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36, - 0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x37,0x20,0x3d,0x20,0x30,0x2e,0x32, - 0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x38,0x20,0x3d,0x20,0x30,0x2e,0x30,0x33, - 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x31,0x30,0x35,0x39,0x33,0x30,0x33,0x32,0x38, - 0x33,0x36,0x39,0x31,0x34,0x30,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37, - 0x39,0x20,0x3d,0x20,0x30,0x2e,0x30,0x37,0x39,0x39,0x39,0x39,0x39,0x39,0x38,0x32, - 0x31,0x31,0x38,0x36,0x30,0x36,0x35,0x36,0x37,0x33,0x38,0x32,0x38,0x31,0x32,0x35, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x31,0x38,0x35,0x38,0x20,0x3d,0x20,0x73,0x64,0x52,0x68,0x6f,0x6d,0x62,0x75, - 0x73,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x35,0x2c,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x37,0x36,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x37,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x38,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x37,0x39,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x30,0x20,0x3d,0x20,0x72,0x65,0x73, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x38,0x31,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f, - 0x31,0x38,0x35,0x38,0x2c,0x20,0x31,0x37,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x38,0x30,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38, - 0x31,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x32,0x20,0x3d,0x20,0x70,0x6f, - 0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e, - 0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39, - 0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x2d,0x31,0x2e,0x30,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x38,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x33,0x34,0x39,0x39, - 0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36, - 0x30,0x39,0x33,0x37,0x35,0x2c,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30, - 0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32, - 0x35,0x2c,0x20,0x32,0x2e,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20, - 0x28,0x73,0x64,0x42,0x6f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x32,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x33,0x29,0x20,0x3c,0x20,0x72,0x65,0x73, - 0x2e,0x78,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x34,0x20, - 0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x32,0x2e,0x30, - 0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30, - 0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20, - 0x2d,0x33,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x35,0x20,0x3d,0x20, - 0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33, - 0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x38,0x36,0x20,0x3d,0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30, - 0x30,0x30,0x37,0x34,0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38, - 0x32,0x38,0x31,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x31,0x38,0x38,0x32,0x20,0x3d,0x20,0x73,0x64,0x4f, - 0x63,0x74,0x6f,0x67,0x6f,0x6e,0x50,0x72,0x69,0x73,0x6d,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x38,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x35,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x36,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x37, - 0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x38,0x20,0x3d,0x20, - 0x76,0x65,0x63,0x32,0x28,0x5f,0x31,0x38,0x38,0x32,0x2c,0x20,0x35,0x31,0x2e,0x37, - 0x39,0x39,0x39,0x39,0x39,0x32,0x33,0x37,0x30,0x36,0x30,0x35,0x34,0x36,0x38,0x37, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20, - 0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x37,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x39, - 0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x32,0x2e, - 0x30,0x2c,0x20,0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36, - 0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20, - 0x2d,0x32,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x30,0x20,0x3d,0x20,0x76, - 0x65,0x63,0x33,0x28,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34, - 0x39,0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32, - 0x35,0x2c,0x20,0x2d,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34, - 0x39,0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32, - 0x35,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x31,0x20,0x3d, - 0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30, - 0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33, - 0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39,0x34, - 0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37,0x35, - 0x2c,0x20,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30, - 0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x32,0x20,0x3d,0x20,0x30,0x2e,0x30,0x37,0x39, - 0x39,0x39,0x39,0x39,0x39,0x38,0x32,0x31,0x31,0x38,0x36,0x30,0x36,0x35,0x36,0x37, - 0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x33,0x20,0x3d, - 0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x34,0x20,0x3d,0x20,0x76,0x65, - 0x63,0x32,0x28,0x73,0x64,0x43,0x79,0x6c,0x69,0x6e,0x64,0x65,0x72,0x28,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x38,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x30, - 0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x31,0x2c,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x39,0x32,0x29,0x2c,0x20,0x33,0x31,0x2e,0x32,0x30,0x30,0x30,0x30,0x30, - 0x37,0x36,0x32,0x39,0x33,0x39,0x34,0x35,0x33,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55, - 0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x39,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x35,0x20,0x3d,0x20,0x70,0x6f, - 0x73,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e, - 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31,0x31,0x36,0x31, - 0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x2d,0x31,0x2e, - 0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x33, - 0x28,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31, - 0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20, - 0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x37, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x30,0x2e,0x32,0x30,0x30,0x30,0x30, - 0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39, - 0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x34,0x30,0x30,0x30,0x30,0x30,0x30, - 0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36, - 0x32,0x35,0x2c,0x20,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34, - 0x39,0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x38,0x20,0x3d,0x20,0x30,0x2e,0x31, - 0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37, - 0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x39, - 0x20,0x3d,0x20,0x30,0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34, - 0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32, - 0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x30,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x31,0x30,0x31,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73, - 0x64,0x43,0x61,0x70,0x70,0x65,0x64,0x43,0x6f,0x6e,0x65,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x39,0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x36,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x39,0x38,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x39,0x29,0x2c,0x20,0x34, - 0x36,0x2e,0x30,0x39,0x39,0x39,0x39,0x38,0x34,0x37,0x34,0x31,0x32,0x31,0x30,0x39, - 0x33,0x37,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65, - 0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30, - 0x30,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x31,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x30,0x32,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76,0x65, - 0x63,0x33,0x28,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30, - 0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30, - 0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30, - 0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x31,0x30,0x30,0x30,0x30, - 0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34, - 0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x34,0x20,0x3d,0x20,0x76,0x65,0x63,0x33, - 0x28,0x2d,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30, - 0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x2c, - 0x20,0x30,0x2e,0x33,0x34,0x39,0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35, - 0x33,0x35,0x35,0x32,0x32,0x34,0x36,0x30,0x39,0x33,0x37,0x35,0x2c,0x20,0x30,0x2e, - 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31,0x31,0x36,0x31, - 0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x30,0x35,0x20,0x3d,0x20,0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30, - 0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30, - 0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x36,0x20,0x3d,0x20,0x30, - 0x2e,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x37,0x34,0x35,0x30,0x35,0x38, - 0x30,0x35,0x39,0x36,0x39,0x32,0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x30,0x37,0x20,0x3d,0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x30,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x73,0x64,0x52,0x6f,0x75, - 0x6e,0x64,0x43,0x6f,0x6e,0x65,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x32, - 0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x33,0x2c,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x30,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30, - 0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x36,0x29,0x2c,0x20,0x35, - 0x31,0x2e,0x37,0x30,0x30,0x30,0x30,0x30,0x37,0x36,0x32,0x39,0x33,0x39,0x34,0x35, - 0x33,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72, - 0x65,0x73,0x20,0x3d,0x20,0x6f,0x70,0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31, - 0x30,0x37,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x38,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x30,0x39,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2d,0x20,0x76, - 0x65,0x63,0x33,0x28,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30, - 0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39, - 0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x31,0x31,0x30,0x20,0x3d,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30, - 0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33, - 0x31,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x31,0x20,0x3d,0x20,0x30, - 0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x34,0x39,0x30,0x31,0x31,0x36, - 0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x31,0x32,0x20,0x3d,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30, - 0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31, - 0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x33,0x20,0x3d,0x20,0x72,0x65,0x73, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x34,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28, - 0x73,0x64,0x52,0x6f,0x75,0x6e,0x64,0x43,0x6f,0x6e,0x65,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x30,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x30, - 0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x31,0x2c,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x31,0x32,0x29,0x2c,0x20,0x33,0x37,0x2e,0x30,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x6f,0x70, - 0x55,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x33,0x2c,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x31,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20, - 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65,0x73,0x3b,0x0a,0x7d, - 0x0a,0x0a,0x76,0x65,0x63,0x32,0x20,0x72,0x61,0x79,0x63,0x61,0x73,0x74,0x28,0x76, - 0x65,0x63,0x33,0x20,0x72,0x6f,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72,0x64,0x29, - 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x72,0x65,0x73,0x20, - 0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x2d,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x74,0x6d,0x69,0x6e,0x20,0x3d,0x20,0x31, - 0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x74,0x6d, - 0x61,0x78,0x20,0x3d,0x20,0x32,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x30,0x30,0x39,0x20,0x3d,0x20,0x28,0x2d,0x72, - 0x6f,0x2e,0x79,0x29,0x20,0x2f,0x20,0x72,0x64,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x30,0x30,0x39,0x20,0x3e,0x20,0x30,0x2e,0x30, - 0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x74,0x6d,0x61,0x78,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x28,0x74,0x6d,0x61,0x78,0x2c, - 0x20,0x5f,0x32,0x30,0x30,0x39,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x32,0x30,0x30, - 0x39,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20, - 0x72,0x6f,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30, - 0x2e,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34, - 0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x31,0x20,0x3d,0x20,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x76,0x65,0x63, - 0x33,0x28,0x32,0x2e,0x35,0x2c,0x20,0x30,0x2e,0x34,0x30,0x39,0x39,0x39,0x39,0x39, - 0x39,0x36,0x34,0x32,0x33,0x37,0x32,0x31,0x33,0x31,0x33,0x34,0x37,0x36,0x35,0x36, - 0x32,0x35,0x2c,0x20,0x33,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x32,0x20,0x5f,0x32,0x30,0x32,0x39,0x20,0x3d,0x20,0x69,0x42,0x6f,0x78,0x28, - 0x70,0x61,0x72,0x61,0x6d,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x2c,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c, - 0x6f,0x61,0x74,0x20,0x5f,0x32,0x30,0x33,0x31,0x20,0x3d,0x20,0x5f,0x32,0x30,0x32, - 0x39,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x32,0x30,0x33,0x33,0x20,0x3d,0x20,0x5f,0x32,0x30,0x32,0x39,0x2e,0x79,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x32,0x30,0x33,0x34,0x20,0x3d, - 0x20,0x5f,0x32,0x30,0x33,0x31,0x20,0x3c,0x20,0x5f,0x32,0x30,0x33,0x33,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x32,0x30,0x34,0x30,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x30,0x33,0x34,0x29,0x0a,0x20, - 0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x32,0x30, - 0x34,0x30,0x20,0x3d,0x20,0x5f,0x32,0x30,0x33,0x33,0x20,0x3e,0x20,0x30,0x2e,0x30, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65, - 0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f, - 0x32,0x30,0x34,0x30,0x20,0x3d,0x20,0x5f,0x32,0x30,0x33,0x34,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x32,0x30, - 0x34,0x37,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x30,0x34, - 0x30,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x5f,0x32,0x30,0x34,0x37,0x20,0x3d,0x20,0x5f,0x32,0x30,0x33,0x31,0x20,0x3c, - 0x20,0x74,0x6d,0x61,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20, - 0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x5f,0x32,0x30,0x34,0x37,0x20,0x3d,0x20,0x5f,0x32,0x30,0x34, - 0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20, - 0x28,0x5f,0x32,0x30,0x34,0x37,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x30,0x35, - 0x32,0x20,0x3d,0x20,0x74,0x6d,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x30,0x35,0x33,0x20,0x3d,0x20, - 0x6d,0x61,0x78,0x28,0x5f,0x32,0x30,0x33,0x31,0x2c,0x20,0x5f,0x32,0x30,0x35,0x32, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x6d,0x69,0x6e,0x20, - 0x3d,0x20,0x5f,0x32,0x30,0x35,0x33,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x74,0x6d,0x61,0x78,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x28,0x5f,0x32,0x30,0x33, - 0x33,0x2c,0x20,0x74,0x6d,0x61,0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x74,0x20,0x3d,0x20,0x5f,0x32,0x30,0x35, - 0x33,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28, - 0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x28,0x69,0x20,0x3c,0x20, - 0x37,0x30,0x29,0x20,0x26,0x26,0x20,0x28,0x74,0x20,0x3c,0x20,0x74,0x6d,0x61,0x78, - 0x29,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x72,0x6f,0x20, - 0x2b,0x20,0x28,0x72,0x64,0x20,0x2a,0x20,0x74,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x30, - 0x38,0x33,0x20,0x3d,0x20,0x6d,0x61,0x70,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33, - 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x30,0x38,0x35,0x20,0x3d,0x20,0x5f,0x32,0x30, - 0x38,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x69,0x66,0x20,0x28,0x61,0x62,0x73,0x28,0x5f,0x32,0x30,0x38,0x35,0x29, - 0x20,0x3c,0x20,0x28,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33, - 0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33, - 0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x20,0x2a,0x20,0x74,0x29,0x29,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65, - 0x73,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x74,0x2c,0x20,0x5f,0x32,0x30,0x38, - 0x33,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x20,0x2b,0x3d,0x20,0x5f,0x32,0x30,0x38, - 0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20, - 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65, - 0x73,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x65,0x63,0x33,0x20,0x63,0x61,0x6c,0x63,0x4e, - 0x6f,0x72,0x6d,0x61,0x6c,0x28,0x76,0x65,0x63,0x33,0x20,0x70,0x6f,0x73,0x29,0x0a, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x6e,0x20,0x3d,0x20,0x76, - 0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f, - 0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x28,0x69, - 0x6e,0x74,0x28,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2e, - 0x79,0x29,0x2c,0x20,0x30,0x29,0x3b,0x20,0x69,0x20,0x3c,0x20,0x34,0x3b,0x20,0x69, - 0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x32,0x32,0x31,0x20,0x3d,0x20,0x28, - 0x28,0x76,0x65,0x63,0x33,0x28,0x66,0x6c,0x6f,0x61,0x74,0x28,0x28,0x28,0x69,0x20, - 0x2b,0x20,0x33,0x29,0x20,0x3e,0x3e,0x20,0x31,0x29,0x20,0x26,0x20,0x31,0x29,0x2c, - 0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x28,0x69,0x20,0x3e,0x3e,0x20,0x31,0x29,0x20, - 0x26,0x20,0x31,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x69,0x20,0x26,0x20, - 0x31,0x29,0x29,0x20,0x2a,0x20,0x32,0x2e,0x30,0x29,0x20,0x2d,0x20,0x76,0x65,0x63, - 0x33,0x28,0x31,0x2e,0x30,0x29,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x37,0x37,0x33, - 0x30,0x30,0x30,0x31,0x32,0x31,0x31,0x31,0x36,0x36,0x33,0x38,0x31,0x38,0x33,0x35, - 0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65, - 0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2b, - 0x20,0x28,0x5f,0x32,0x32,0x32,0x31,0x20,0x2a,0x20,0x30,0x2e,0x30,0x30,0x30,0x35, - 0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x33,0x37,0x34,0x38,0x37,0x32,0x35,0x36,0x35, - 0x32,0x36,0x39,0x34,0x37,0x30,0x32,0x31,0x34,0x38,0x34,0x33,0x37,0x35,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x20,0x2b,0x3d,0x20,0x28,0x5f, - 0x32,0x32,0x32,0x31,0x20,0x2a,0x20,0x6d,0x61,0x70,0x28,0x70,0x61,0x72,0x61,0x6d, - 0x29,0x2e,0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20, - 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65, - 0x28,0x6e,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x63,0x68, - 0x65,0x63,0x6b,0x65,0x72,0x73,0x47,0x72,0x61,0x64,0x42,0x6f,0x78,0x28,0x76,0x65, - 0x63,0x32,0x20,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x20,0x64,0x70,0x64,0x78,0x2c, - 0x20,0x76,0x65,0x63,0x32,0x20,0x64,0x70,0x64,0x79,0x29,0x0a,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x30,0x39,0x20,0x3d,0x20,0x28, - 0x61,0x62,0x73,0x28,0x64,0x70,0x64,0x78,0x29,0x20,0x2b,0x20,0x61,0x62,0x73,0x28, - 0x64,0x70,0x64,0x79,0x29,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e, - 0x30,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x34,0x37,0x34,0x39,0x37,0x34, - 0x35,0x31,0x33,0x30,0x35,0x33,0x38,0x39,0x34,0x30,0x34,0x32,0x39,0x36,0x38,0x37, - 0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33, - 0x31,0x33,0x20,0x3d,0x20,0x5f,0x32,0x33,0x30,0x39,0x20,0x2a,0x20,0x30,0x2e,0x35, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x33,0x32, - 0x20,0x3d,0x20,0x28,0x28,0x61,0x62,0x73,0x28,0x66,0x72,0x61,0x63,0x74,0x28,0x28, - 0x70,0x20,0x2d,0x20,0x5f,0x32,0x33,0x31,0x33,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35, - 0x29,0x20,0x2d,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x35,0x29,0x29,0x20,0x2d, - 0x20,0x61,0x62,0x73,0x28,0x66,0x72,0x61,0x63,0x74,0x28,0x28,0x70,0x20,0x2b,0x20, - 0x5f,0x32,0x33,0x31,0x33,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x29,0x20,0x2d,0x20, - 0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x35,0x29,0x29,0x29,0x20,0x2a,0x20,0x32,0x2e, - 0x30,0x29,0x20,0x2f,0x20,0x5f,0x32,0x33,0x30,0x39,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x30,0x2e,0x35,0x20,0x2d,0x20,0x28,0x28,0x30, - 0x2e,0x35,0x20,0x2a,0x20,0x5f,0x32,0x33,0x33,0x32,0x2e,0x78,0x29,0x20,0x2a,0x20, - 0x5f,0x32,0x33,0x33,0x32,0x2e,0x79,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x63,0x61,0x6c,0x63,0x41,0x4f,0x28,0x76,0x65,0x63,0x33,0x20,0x70, - 0x6f,0x73,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x6e,0x6f,0x72,0x29,0x0a,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6f,0x63,0x63,0x20,0x3d,0x20, - 0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73, - 0x63,0x61,0x20,0x3d,0x20,0x31,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f, - 0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x28,0x69, - 0x6e,0x74,0x28,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2e, - 0x79,0x29,0x2c,0x20,0x30,0x29,0x3b,0x20,0x69,0x20,0x3c,0x20,0x35,0x3b,0x20,0x69, - 0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x32,0x36,0x33,0x20,0x3d,0x20, - 0x30,0x2e,0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,0x36,0x34,0x38, - 0x32,0x35,0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,0x32,0x35,0x20, - 0x2b,0x20,0x28,0x66,0x6c,0x6f,0x61,0x74,0x28,0x69,0x29,0x20,0x2a,0x20,0x30,0x2e, - 0x30,0x32,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x33,0x32,0x39,0x34,0x34,0x37,0x37, - 0x34,0x36,0x32,0x37,0x36,0x38,0x35,0x35,0x34,0x36,0x38,0x37,0x35,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x20,0x3d,0x20,0x70,0x6f,0x73,0x20,0x2b,0x20,0x28,0x6e,0x6f,0x72,0x20, - 0x2a,0x20,0x5f,0x32,0x32,0x36,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x32,0x37,0x36,0x20,0x3d,0x20, - 0x73,0x63,0x61,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x32,0x32,0x37,0x38,0x20,0x3d,0x20,0x6f,0x63,0x63,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32, - 0x32,0x37,0x39,0x20,0x3d,0x20,0x5f,0x32,0x32,0x37,0x38,0x20,0x2b,0x20,0x28,0x28, - 0x5f,0x32,0x32,0x36,0x33,0x20,0x2d,0x20,0x6d,0x61,0x70,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x29,0x2e,0x78,0x29,0x20,0x2a,0x20,0x5f,0x32,0x32,0x37,0x36,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6f,0x63,0x63,0x20,0x3d,0x20,0x5f,0x32, - 0x32,0x37,0x39,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x63,0x61, - 0x20,0x3d,0x20,0x5f,0x32,0x32,0x37,0x36,0x20,0x2a,0x20,0x30,0x2e,0x39,0x34,0x39, - 0x39,0x39,0x39,0x39,0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39, - 0x32,0x31,0x38,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69, - 0x66,0x20,0x28,0x5f,0x32,0x32,0x37,0x39,0x20,0x3e,0x20,0x30,0x2e,0x33,0x34,0x39, - 0x39,0x39,0x39,0x39,0x39,0x34,0x30,0x33,0x39,0x35,0x33,0x35,0x35,0x32,0x32,0x34, - 0x36,0x30,0x39,0x33,0x37,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72, - 0x65,0x61,0x6b,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20, - 0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, - 0x63,0x6c,0x61,0x6d,0x70,0x28,0x31,0x2e,0x30,0x20,0x2d,0x20,0x28,0x33,0x2e,0x30, - 0x20,0x2a,0x20,0x6f,0x63,0x63,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e, - 0x30,0x29,0x20,0x2a,0x20,0x28,0x30,0x2e,0x35,0x20,0x2b,0x20,0x28,0x30,0x2e,0x35, - 0x20,0x2a,0x20,0x6e,0x6f,0x72,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x63,0x61,0x6c,0x63,0x53,0x6f,0x66,0x74,0x73,0x68,0x61, - 0x64,0x6f,0x77,0x28,0x76,0x65,0x63,0x33,0x20,0x72,0x6f,0x2c,0x20,0x76,0x65,0x63, - 0x33,0x20,0x72,0x64,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6d,0x69,0x6e,0x74, - 0x2c,0x20,0x69,0x6e,0x6f,0x75,0x74,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x74,0x6d, - 0x61,0x78,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x32,0x31,0x31,0x34,0x20,0x3d,0x20,0x28,0x30,0x2e,0x38,0x30,0x30,0x30,0x30, - 0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38, - 0x31,0x32,0x35,0x20,0x2d,0x20,0x72,0x6f,0x2e,0x79,0x29,0x20,0x2f,0x20,0x72,0x64, - 0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x31,0x31, - 0x34,0x20,0x3e,0x20,0x30,0x2e,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x6d,0x61,0x78,0x20,0x3d,0x20,0x6d,0x69, - 0x6e,0x28,0x74,0x6d,0x61,0x78,0x2c,0x20,0x5f,0x32,0x31,0x31,0x34,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x72,0x65,0x73,0x20,0x3d,0x20,0x31,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x74,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x74,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20, - 0x6d,0x69,0x6e,0x28,0x69,0x6e,0x74,0x28,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d, - 0x73,0x5b,0x31,0x5d,0x2e,0x79,0x29,0x2c,0x20,0x30,0x29,0x3b,0x20,0x69,0x20,0x3c, - 0x20,0x32,0x34,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x20,0x3d,0x20,0x72,0x6f,0x20,0x2b,0x20,0x28,0x72,0x64,0x20,0x2a,0x20, - 0x74,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32, - 0x20,0x5f,0x32,0x31,0x35,0x30,0x20,0x3d,0x20,0x6d,0x61,0x70,0x28,0x70,0x61,0x72, - 0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x32,0x31,0x35,0x31,0x20,0x3d,0x20,0x5f,0x32,0x31,0x35,0x30, - 0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x5f,0x32,0x31,0x35,0x35,0x20,0x3d,0x20,0x74,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x31,0x35,0x37, - 0x20,0x3d,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x28,0x38,0x2e,0x30,0x20,0x2a,0x20, - 0x5f,0x32,0x31,0x35,0x31,0x29,0x20,0x2f,0x20,0x5f,0x32,0x31,0x35,0x35,0x2c,0x20, - 0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x31,0x35,0x38,0x20,0x3d, - 0x20,0x72,0x65,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c, - 0x6f,0x61,0x74,0x20,0x5f,0x32,0x31,0x36,0x36,0x20,0x3d,0x20,0x6d,0x69,0x6e,0x28, - 0x5f,0x32,0x31,0x35,0x38,0x2c,0x20,0x28,0x5f,0x32,0x31,0x35,0x37,0x20,0x2a,0x20, - 0x5f,0x32,0x31,0x35,0x37,0x29,0x20,0x2a,0x20,0x28,0x33,0x2e,0x30,0x20,0x2d,0x20, - 0x28,0x32,0x2e,0x30,0x20,0x2a,0x20,0x5f,0x32,0x31,0x35,0x37,0x29,0x29,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x20,0x3d,0x20,0x5f, - 0x32,0x31,0x36,0x36,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c, - 0x6f,0x61,0x74,0x20,0x5f,0x32,0x31,0x37,0x31,0x20,0x3d,0x20,0x5f,0x32,0x31,0x35, - 0x35,0x20,0x2b,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x5f,0x32,0x31,0x35,0x31,0x2c, - 0x20,0x30,0x2e,0x30,0x31,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x35,0x32,0x39, - 0x36,0x35,0x31,0x36,0x34,0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31,0x32,0x35,0x2c, - 0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32, - 0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x20,0x3d,0x20,0x5f,0x32,0x31,0x37, - 0x31,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x28, - 0x5f,0x32,0x31,0x36,0x36,0x20,0x3c,0x20,0x30,0x2e,0x30,0x30,0x34,0x30,0x30,0x30, - 0x30,0x30,0x30,0x31,0x38,0x39,0x39,0x38,0x39,0x38,0x30,0x35,0x32,0x32,0x31,0x35, - 0x35,0x37,0x36,0x31,0x37,0x31,0x38,0x37,0x35,0x29,0x20,0x7c,0x7c,0x20,0x28,0x5f, - 0x32,0x31,0x37,0x31,0x20,0x3e,0x20,0x74,0x6d,0x61,0x78,0x29,0x29,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x72, - 0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x72,0x65,0x73,0x2c, - 0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76, - 0x65,0x63,0x33,0x20,0x72,0x65,0x6e,0x64,0x65,0x72,0x28,0x76,0x65,0x63,0x33,0x20, - 0x72,0x6f,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72,0x64,0x2c,0x20,0x76,0x65,0x63, - 0x33,0x20,0x72,0x64,0x78,0x2c,0x20,0x76,0x65,0x63,0x33,0x20,0x72,0x64,0x79,0x29, - 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x63,0x6f,0x6c,0x20, - 0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x36,0x39,0x39,0x39,0x39,0x39,0x39, - 0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39,0x32,0x31,0x38,0x37, - 0x35,0x2c,0x20,0x30,0x2e,0x36,0x39,0x39,0x39,0x39,0x39,0x39,0x38,0x38,0x30,0x37, - 0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x2c,0x20,0x30, - 0x2e,0x38,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x36,0x31,0x35,0x38,0x31,0x34,0x32, - 0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,0x29,0x20,0x2d,0x20,0x76,0x65,0x63,0x33, - 0x28,0x6d,0x61,0x78,0x28,0x72,0x64,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20, - 0x2a,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30, - 0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20, - 0x72,0x6f,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72, - 0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x35,0x37,0x20,0x3d,0x20,0x72,0x61,0x79,0x63, - 0x61,0x73,0x74,0x28,0x70,0x61,0x72,0x61,0x6d,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x31,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f, - 0x32,0x33,0x36,0x30,0x20,0x3d,0x20,0x5f,0x32,0x33,0x35,0x37,0x2e,0x78,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x33,0x36,0x33,0x20, - 0x3d,0x20,0x5f,0x32,0x33,0x35,0x37,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69, - 0x66,0x20,0x28,0x5f,0x32,0x33,0x36,0x33,0x20,0x3e,0x20,0x28,0x2d,0x30,0x2e,0x35, - 0x29,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x33,0x37,0x33,0x20,0x3d,0x20,0x72,0x6f, - 0x20,0x2b,0x20,0x28,0x72,0x64,0x20,0x2a,0x20,0x5f,0x32,0x33,0x36,0x30,0x29,0x3b, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x6f,0x6f,0x6c,0x20,0x5f,0x32, - 0x33,0x37,0x37,0x20,0x3d,0x20,0x5f,0x32,0x33,0x36,0x33,0x20,0x3c,0x20,0x31,0x2e, - 0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20, - 0x5f,0x32,0x33,0x37,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69, - 0x66,0x20,0x28,0x5f,0x32,0x33,0x37,0x37,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x5f,0x32,0x33,0x37,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30, - 0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65, - 0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x5f,0x32,0x33,0x37,0x33,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x32,0x33,0x37, - 0x38,0x20,0x3d,0x20,0x63,0x61,0x6c,0x63,0x4e,0x6f,0x72,0x6d,0x61,0x6c,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20, - 0x5f,0x32,0x33,0x39,0x30,0x20,0x3d,0x20,0x72,0x65,0x66,0x6c,0x65,0x63,0x74,0x28, - 0x72,0x64,0x2c,0x20,0x5f,0x32,0x33,0x37,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30, - 0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32, - 0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x29,0x20,0x2b,0x20,0x28, - 0x73,0x69,0x6e,0x28,0x76,0x65,0x63,0x33,0x28,0x5f,0x32,0x33,0x36,0x33,0x20,0x2a, - 0x20,0x32,0x2e,0x30,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30, - 0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x32,0x2e,0x30,0x29,0x29,0x20,0x2a,0x20,0x30, - 0x2e,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32, - 0x32,0x33,0x38,0x37,0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6b,0x73,0x20,0x3d, - 0x20,0x31,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66, - 0x20,0x28,0x5f,0x32,0x33,0x37,0x37,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x5f,0x32, - 0x33,0x37,0x33,0x2e,0x78,0x7a,0x20,0x2a,0x20,0x33,0x2e,0x30,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x34,0x20,0x3d,0x20,0x28,0x28,0x28,0x72,0x64,0x20,0x2f, - 0x20,0x76,0x65,0x63,0x33,0x28,0x72,0x64,0x2e,0x79,0x29,0x29,0x20,0x2d,0x20,0x28, - 0x72,0x64,0x78,0x20,0x2f,0x20,0x76,0x65,0x63,0x33,0x28,0x72,0x64,0x78,0x2e,0x79, - 0x29,0x29,0x29,0x20,0x2a,0x20,0x72,0x6f,0x2e,0x79,0x29,0x2e,0x78,0x7a,0x20,0x2a, - 0x20,0x33,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x20,0x3d, - 0x20,0x28,0x28,0x28,0x72,0x64,0x20,0x2f,0x20,0x76,0x65,0x63,0x33,0x28,0x72,0x64, - 0x2e,0x79,0x29,0x29,0x20,0x2d,0x20,0x28,0x72,0x64,0x79,0x20,0x2f,0x20,0x76,0x65, - 0x63,0x33,0x28,0x72,0x64,0x79,0x2e,0x79,0x29,0x29,0x29,0x20,0x2a,0x20,0x72,0x6f, - 0x2e,0x79,0x29,0x2e,0x78,0x7a,0x20,0x2a,0x20,0x33,0x2e,0x30,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x20,0x3d,0x20, - 0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x35, - 0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35, - 0x29,0x20,0x2b,0x20,0x28,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x35,0x30,0x30, - 0x30,0x30,0x30,0x30,0x30,0x37,0x34,0x35,0x30,0x35,0x38,0x30,0x35,0x39,0x36,0x39, - 0x32,0x33,0x38,0x32,0x38,0x31,0x32,0x35,0x29,0x20,0x2a,0x20,0x63,0x68,0x65,0x63, - 0x6b,0x65,0x72,0x73,0x47,0x72,0x61,0x64,0x42,0x6f,0x78,0x28,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x2c,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x6b,0x73,0x20,0x3d,0x20,0x30,0x2e,0x34,0x30,0x30,0x30, - 0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33, - 0x39,0x30,0x36,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d, - 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x36,0x20,0x3d,0x20,0x5f,0x32,0x33,0x37,0x33,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x37,0x20,0x3d,0x20,0x5f,0x32,0x33,0x37,0x38,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x34,0x35,0x39, - 0x20,0x3d,0x20,0x63,0x61,0x6c,0x63,0x41,0x4f,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x36,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x37,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x6c,0x69,0x6e,0x20,0x3d,0x20, - 0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x34,0x37,0x30,0x20,0x3d,0x20, - 0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,0x65,0x63,0x33,0x28,0x2d, - 0x30,0x2e,0x35,0x36,0x39,0x38,0x30,0x32,0x38,0x38,0x30,0x32,0x38,0x37,0x31,0x37, - 0x30,0x34,0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x34,0x35,0x35, - 0x38,0x34,0x32,0x33,0x31,0x36,0x31,0x35,0x30,0x36,0x36,0x35,0x32,0x38,0x33,0x32, - 0x30,0x33,0x31,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x36,0x38,0x33,0x37,0x36,0x33, - 0x34,0x34,0x34,0x34,0x32,0x33,0x36,0x37,0x35,0x35,0x33,0x37,0x31,0x30,0x39,0x33, - 0x37,0x35,0x29,0x20,0x2d,0x20,0x72,0x64,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x64,0x69,0x66,0x20,0x3d,0x20,0x63, - 0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x5f,0x32,0x33,0x37,0x38,0x2c,0x20, - 0x76,0x65,0x63,0x33,0x28,0x2d,0x30,0x2e,0x35,0x36,0x39,0x38,0x30,0x32,0x38,0x38, - 0x30,0x32,0x38,0x37,0x31,0x37,0x30,0x34,0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c, - 0x20,0x30,0x2e,0x34,0x35,0x35,0x38,0x34,0x32,0x33,0x31,0x36,0x31,0x35,0x30,0x36, - 0x36,0x35,0x32,0x38,0x33,0x32,0x30,0x33,0x31,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e, - 0x36,0x38,0x33,0x37,0x36,0x33,0x34,0x34,0x34,0x34,0x32,0x33,0x36,0x37,0x35,0x35, - 0x33,0x37,0x31,0x30,0x39,0x33,0x37,0x35,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c, - 0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x20,0x3d,0x20,0x5f,0x32, - 0x33,0x37,0x33,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x39,0x20,0x3d,0x20,0x76,0x65,0x63,0x33, - 0x28,0x2d,0x30,0x2e,0x35,0x36,0x39,0x38,0x30,0x32,0x38,0x38,0x30,0x32,0x38,0x37, - 0x31,0x37,0x30,0x34,0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x34, - 0x35,0x35,0x38,0x34,0x32,0x33,0x31,0x36,0x31,0x35,0x30,0x36,0x36,0x35,0x32,0x38, - 0x33,0x32,0x30,0x33,0x31,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x36,0x38,0x33,0x37, - 0x36,0x33,0x34,0x34,0x34,0x34,0x32,0x33,0x36,0x37,0x35,0x35,0x33,0x37,0x31,0x30, - 0x39,0x33,0x37,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66, - 0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x20,0x3d,0x20, - 0x30,0x2e,0x30,0x31,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x35,0x32,0x39,0x36, - 0x35,0x31,0x36,0x34,0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31,0x32,0x35,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x31,0x31,0x20,0x3d,0x20,0x32,0x2e,0x35,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x34,0x38, - 0x32,0x20,0x3d,0x20,0x63,0x61,0x6c,0x63,0x53,0x6f,0x66,0x74,0x73,0x68,0x61,0x64, - 0x6f,0x77,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x38,0x2c,0x20,0x70,0x61,0x72,0x61, - 0x6d,0x5f,0x39,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x30,0x2c,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x31,0x31,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x34,0x38,0x33,0x20,0x3d,0x20, - 0x64,0x69,0x66,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x20,0x5f,0x32,0x34,0x38,0x34,0x20,0x3d,0x20,0x5f,0x32,0x34,0x38,0x33, - 0x20,0x2a,0x20,0x5f,0x32,0x34,0x38,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x64,0x69,0x66,0x20,0x3d,0x20,0x5f,0x32,0x34,0x38,0x34,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x69,0x6e,0x20,0x3d,0x20,0x28,0x6c,0x69, - 0x6e,0x20,0x2b,0x20,0x28,0x28,0x28,0x63,0x6f,0x6c,0x20,0x2a,0x20,0x32,0x2e,0x32, - 0x30,0x30,0x30,0x30,0x30,0x30,0x34,0x37,0x36,0x38,0x33,0x37,0x31,0x35,0x38,0x32, - 0x30,0x33,0x31,0x32,0x35,0x29,0x20,0x2a,0x20,0x5f,0x32,0x34,0x38,0x34,0x29,0x20, - 0x2a,0x20,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x32,0x39,0x39,0x39,0x39,0x39,0x39, - 0x35,0x32,0x33,0x31,0x36,0x32,0x38,0x34,0x31,0x37,0x39,0x36,0x38,0x37,0x35,0x2c, - 0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x36,0x39,0x39,0x39,0x39,0x39,0x39,0x38, - 0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39,0x32,0x31,0x38,0x37,0x35, - 0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x28,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x32, - 0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x32,0x33,0x31,0x36,0x32,0x38,0x34,0x31,0x37, - 0x39,0x36,0x38,0x37,0x35,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x36,0x39, - 0x39,0x39,0x39,0x39,0x39,0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34, - 0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x20,0x2a,0x20,0x28,0x35,0x2e,0x30,0x20,0x2a, - 0x20,0x28,0x28,0x70,0x6f,0x77,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74, - 0x28,0x5f,0x32,0x33,0x37,0x38,0x2c,0x20,0x5f,0x32,0x34,0x37,0x30,0x29,0x2c,0x20, - 0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x2c,0x20,0x31,0x36,0x2e,0x30,0x29, - 0x20,0x2a,0x20,0x5f,0x32,0x34,0x38,0x34,0x29,0x20,0x2a,0x20,0x28,0x30,0x2e,0x30, - 0x33,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x31,0x30,0x35,0x39,0x33,0x30,0x33,0x32, - 0x38,0x33,0x36,0x39,0x31,0x34,0x30,0x36,0x32,0x35,0x20,0x2b,0x20,0x28,0x30,0x2e, - 0x39,0x35,0x39,0x39,0x39,0x39,0x39,0x37,0x38,0x35,0x34,0x32,0x33,0x32,0x37,0x38, - 0x38,0x30,0x38,0x35,0x39,0x33,0x37,0x35,0x20,0x2a,0x20,0x70,0x6f,0x77,0x28,0x63, - 0x6c,0x61,0x6d,0x70,0x28,0x31,0x2e,0x30,0x20,0x2d,0x20,0x64,0x6f,0x74,0x28,0x5f, - 0x32,0x34,0x37,0x30,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x30,0x2e,0x35,0x36, - 0x39,0x38,0x30,0x32,0x38,0x38,0x30,0x32,0x38,0x37,0x31,0x37,0x30,0x34,0x31,0x30, - 0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x34,0x35,0x35,0x38,0x34,0x32,0x33, - 0x31,0x36,0x31,0x35,0x30,0x36,0x36,0x35,0x32,0x38,0x33,0x32,0x30,0x33,0x31,0x32, - 0x35,0x2c,0x20,0x2d,0x30,0x2e,0x36,0x38,0x33,0x37,0x36,0x33,0x34,0x34,0x34,0x34, - 0x32,0x33,0x36,0x37,0x35,0x35,0x33,0x37,0x31,0x30,0x39,0x33,0x37,0x35,0x29,0x29, - 0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x2c,0x20,0x35,0x2e,0x30, - 0x29,0x29,0x29,0x29,0x29,0x29,0x20,0x2a,0x20,0x6b,0x73,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x35,0x33, - 0x33,0x20,0x3d,0x20,0x73,0x71,0x72,0x74,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x30, - 0x2e,0x35,0x20,0x2b,0x20,0x28,0x30,0x2e,0x35,0x20,0x2a,0x20,0x5f,0x32,0x33,0x37, - 0x38,0x2e,0x79,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29, - 0x20,0x2a,0x20,0x5f,0x32,0x34,0x35,0x39,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x70,0x65,0x20,0x3d,0x20,0x28,0x73, - 0x6d,0x6f,0x6f,0x74,0x68,0x73,0x74,0x65,0x70,0x28,0x2d,0x30,0x2e,0x32,0x30,0x30, - 0x30,0x30,0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37, - 0x36,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x32,0x30,0x30,0x30,0x30, - 0x30,0x30,0x30,0x32,0x39,0x38,0x30,0x32,0x33,0x32,0x32,0x33,0x38,0x37,0x36,0x39, - 0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x5f,0x32,0x33,0x39,0x30,0x2e,0x79,0x29,0x20, - 0x2a,0x20,0x5f,0x32,0x35,0x33,0x33,0x29,0x20,0x2a,0x20,0x28,0x30,0x2e,0x30,0x33, - 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x31,0x30,0x35,0x39,0x33,0x30,0x33,0x32,0x38, - 0x33,0x36,0x39,0x31,0x34,0x30,0x36,0x32,0x35,0x20,0x2b,0x20,0x28,0x30,0x2e,0x39, - 0x35,0x39,0x39,0x39,0x39,0x39,0x37,0x38,0x35,0x34,0x32,0x33,0x32,0x37,0x38,0x38, - 0x30,0x38,0x35,0x39,0x33,0x37,0x35,0x20,0x2a,0x20,0x70,0x6f,0x77,0x28,0x63,0x6c, - 0x61,0x6d,0x70,0x28,0x31,0x2e,0x30,0x20,0x2b,0x20,0x64,0x6f,0x74,0x28,0x5f,0x32, - 0x33,0x37,0x38,0x2c,0x20,0x72,0x64,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31, - 0x2e,0x30,0x29,0x2c,0x20,0x35,0x2e,0x30,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x31,0x32,0x20,0x3d,0x20,0x5f,0x32,0x33,0x37,0x33,0x3b,0x0a,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31, - 0x33,0x20,0x3d,0x20,0x5f,0x32,0x33,0x39,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31, - 0x34,0x20,0x3d,0x20,0x30,0x2e,0x30,0x31,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35, - 0x35,0x32,0x39,0x36,0x35,0x31,0x36,0x34,0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31, - 0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x35,0x20,0x3d,0x20,0x32,0x2e,0x35, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x5f,0x32,0x35,0x35,0x37,0x20,0x3d,0x20,0x63,0x61,0x6c,0x63,0x53,0x6f,0x66,0x74, - 0x73,0x68,0x61,0x64,0x6f,0x77,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x32,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x31,0x34,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x35,0x29,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32, - 0x35,0x35,0x38,0x20,0x3d,0x20,0x73,0x70,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x35,0x35,0x39,0x20,0x3d, - 0x20,0x5f,0x32,0x35,0x35,0x38,0x20,0x2a,0x20,0x5f,0x32,0x35,0x35,0x37,0x3b,0x0a, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x70,0x65,0x20,0x3d,0x20,0x5f,0x32, - 0x35,0x35,0x39,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x5f,0x32,0x35,0x36,0x37,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32,0x36,0x31, - 0x38,0x20,0x3d,0x20,0x28,0x28,0x28,0x5f,0x32,0x35,0x36,0x37,0x20,0x2b,0x20,0x28, - 0x28,0x28,0x63,0x6f,0x6c,0x20,0x2a,0x20,0x30,0x2e,0x36,0x30,0x30,0x30,0x30,0x30, - 0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39,0x31,0x30,0x31,0x35,0x36,0x32, - 0x35,0x29,0x20,0x2a,0x20,0x5f,0x32,0x35,0x33,0x33,0x29,0x20,0x2a,0x20,0x76,0x65, - 0x63,0x33,0x28,0x30,0x2e,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36, - 0x30,0x34,0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20, - 0x30,0x2e,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35, - 0x37,0x39,0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x31,0x2e,0x31,0x34,0x39, - 0x39,0x39,0x39,0x39,0x37,0x36,0x31,0x35,0x38,0x31,0x34,0x32,0x30,0x38,0x39,0x38, - 0x34,0x33,0x37,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x28,0x76,0x65,0x63,0x33, - 0x28,0x30,0x2e,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,0x39,0x36,0x30,0x34, - 0x36,0x34,0x34,0x37,0x37,0x35,0x33,0x39,0x30,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e, - 0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39, - 0x31,0x30,0x31,0x35,0x36,0x32,0x35,0x2c,0x20,0x31,0x2e,0x32,0x39,0x39,0x39,0x39, - 0x39,0x39,0x35,0x32,0x33,0x31,0x36,0x32,0x38,0x34,0x31,0x37,0x39,0x36,0x38,0x37, - 0x35,0x29,0x20,0x2a,0x20,0x28,0x32,0x2e,0x30,0x20,0x2a,0x20,0x5f,0x32,0x35,0x35, - 0x39,0x29,0x29,0x20,0x2a,0x20,0x6b,0x73,0x29,0x29,0x20,0x2b,0x20,0x28,0x28,0x28, - 0x63,0x6f,0x6c,0x20,0x2a,0x20,0x30,0x2e,0x35,0x35,0x30,0x30,0x30,0x30,0x30,0x31, - 0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,0x35, - 0x29,0x20,0x2a,0x20,0x28,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28, - 0x5f,0x32,0x33,0x37,0x38,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x36,0x34, - 0x30,0x31,0x38,0x34,0x34,0x30,0x32,0x34,0x36,0x35,0x38,0x32,0x30,0x33,0x31,0x32, - 0x35,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x37,0x36,0x38,0x32,0x32,0x31, - 0x32,0x35,0x39,0x31,0x31,0x37,0x31,0x32,0x36,0x34,0x36,0x34,0x38,0x34,0x33,0x37, - 0x35,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x20,0x2a, - 0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,0x32,0x33, - 0x37,0x33,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29, - 0x20,0x2a,0x20,0x5f,0x32,0x34,0x35,0x39,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63, - 0x33,0x28,0x30,0x2e,0x32,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x28,0x63,0x6f, - 0x6c,0x20,0x2a,0x20,0x30,0x2e,0x32,0x35,0x29,0x20,0x2a,0x20,0x28,0x70,0x6f,0x77, - 0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x31,0x2e,0x30,0x20,0x2b,0x20,0x64,0x6f,0x74, - 0x28,0x5f,0x32,0x33,0x37,0x38,0x2c,0x20,0x72,0x64,0x29,0x2c,0x20,0x30,0x2e,0x30, - 0x2c,0x20,0x31,0x2e,0x30,0x29,0x2c,0x20,0x32,0x2e,0x30,0x29,0x20,0x2a,0x20,0x5f, - 0x32,0x34,0x35,0x39,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x6c,0x69,0x6e,0x20,0x3d,0x20,0x5f,0x32,0x36,0x31,0x38,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x20,0x3d,0x20,0x6d,0x69,0x78,0x28,0x5f, - 0x32,0x36,0x31,0x38,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x36,0x39,0x39, - 0x39,0x39,0x39,0x39,0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39, - 0x32,0x31,0x38,0x37,0x35,0x2c,0x20,0x30,0x2e,0x36,0x39,0x39,0x39,0x39,0x39,0x39, - 0x38,0x38,0x30,0x37,0x39,0x30,0x37,0x31,0x30,0x34,0x34,0x39,0x32,0x31,0x38,0x37, - 0x35,0x2c,0x20,0x30,0x2e,0x38,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x36,0x31,0x35, - 0x38,0x31,0x34,0x32,0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,0x29,0x2c,0x20,0x76, - 0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x20,0x2d,0x20,0x65,0x78,0x70,0x28,0x28,0x28, - 0x28,0x2d,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,0x37,0x38, - 0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,0x36,0x37, - 0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x20,0x2a,0x20,0x5f,0x32,0x33,0x36,0x30, - 0x29,0x20,0x2a,0x20,0x5f,0x32,0x33,0x36,0x30,0x29,0x20,0x2a,0x20,0x5f,0x32,0x33, - 0x36,0x30,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20, - 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x6c,0x61,0x6d,0x70,0x28,0x63,0x6f, - 0x6c,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65, - 0x63,0x33,0x28,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x65,0x63, - 0x34,0x20,0x6d,0x61,0x69,0x6e,0x49,0x6d,0x61,0x67,0x65,0x28,0x76,0x65,0x63,0x32, - 0x20,0x66,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x29,0x0a,0x7b,0x0a,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x36,0x38,0x36,0x20,0x3d,0x20,0x66, - 0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x7a,0x77,0x20,0x2f, - 0x20,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x79, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x32,0x37,0x30, - 0x35,0x20,0x3d,0x20,0x28,0x30,0x2e,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31, - 0x34,0x39,0x30,0x31,0x31,0x36,0x31,0x31,0x39,0x33,0x38,0x34,0x37,0x36,0x35,0x36, - 0x32,0x35,0x20,0x2a,0x20,0x28,0x33,0x32,0x2e,0x30,0x20,0x2b,0x20,0x28,0x66,0x73, - 0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2e,0x78,0x20,0x2a,0x20,0x31, - 0x2e,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x37,0x2e,0x30,0x20,0x2a,0x20,0x5f, - 0x32,0x36,0x38,0x36,0x2e,0x78,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63, - 0x33,0x20,0x5f,0x32,0x37,0x32,0x31,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30, - 0x2e,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x36,0x30,0x30, - 0x30,0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39,0x31,0x30,0x31, - 0x35,0x36,0x32,0x35,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x33,0x28,0x34,0x2e,0x35, - 0x20,0x2a,0x20,0x63,0x6f,0x73,0x28,0x5f,0x32,0x37,0x30,0x35,0x29,0x2c,0x20,0x31, - 0x2e,0x32,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x32,0x33,0x31,0x36,0x32,0x38,0x34, - 0x31,0x37,0x39,0x36,0x38,0x37,0x35,0x20,0x2b,0x20,0x28,0x32,0x2e,0x30,0x20,0x2a, - 0x20,0x5f,0x32,0x36,0x38,0x36,0x2e,0x79,0x29,0x2c,0x20,0x34,0x2e,0x35,0x20,0x2a, - 0x20,0x73,0x69,0x6e,0x28,0x5f,0x32,0x37,0x30,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x5f, - 0x32,0x37,0x32,0x31,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e, - 0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x36,0x30,0x30,0x30, - 0x30,0x30,0x30,0x32,0x33,0x38,0x34,0x31,0x38,0x35,0x37,0x39,0x31,0x30,0x31,0x35, - 0x36,0x32,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x6d,0x61,0x74,0x33,0x20,0x5f,0x32,0x37,0x32,0x39,0x20,0x3d,0x20, - 0x73,0x65,0x74,0x43,0x61,0x6d,0x65,0x72,0x61,0x28,0x70,0x61,0x72,0x61,0x6d,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x74,0x6f,0x74, - 0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x37,0x33,0x39,0x20,0x3d,0x20,0x76, - 0x65,0x63,0x32,0x28,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d, - 0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61, - 0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x5f,0x32,0x37,0x32,0x31,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x20, - 0x3d,0x20,0x5f,0x32,0x37,0x32,0x39,0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c, - 0x69,0x7a,0x65,0x28,0x76,0x65,0x63,0x33,0x28,0x28,0x28,0x66,0x72,0x61,0x67,0x43, - 0x6f,0x6f,0x72,0x64,0x20,0x2a,0x20,0x32,0x2e,0x30,0x29,0x20,0x2d,0x20,0x66,0x73, - 0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x29,0x20,0x2f, - 0x20,0x5f,0x32,0x37,0x33,0x39,0x2c,0x20,0x32,0x2e,0x35,0x29,0x29,0x3b,0x0a,0x20, - 0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x20, - 0x3d,0x20,0x5f,0x32,0x37,0x32,0x39,0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c, - 0x69,0x7a,0x65,0x28,0x76,0x65,0x63,0x33,0x28,0x28,0x28,0x28,0x66,0x72,0x61,0x67, - 0x43,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x31,0x2e,0x30, - 0x2c,0x20,0x30,0x2e,0x30,0x29,0x29,0x20,0x2a,0x20,0x32,0x2e,0x30,0x29,0x20,0x2d, - 0x20,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x79, - 0x29,0x20,0x2f,0x20,0x5f,0x32,0x37,0x33,0x39,0x2c,0x20,0x32,0x2e,0x35,0x29,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x70,0x61,0x72,0x61,0x6d, - 0x5f,0x36,0x20,0x3d,0x20,0x5f,0x32,0x37,0x32,0x39,0x20,0x2a,0x20,0x6e,0x6f,0x72, - 0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,0x65,0x63,0x33,0x28,0x28,0x28,0x28,0x66, - 0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28, - 0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x20,0x2a,0x20,0x32,0x2e,0x30, - 0x29,0x20,0x2d,0x20,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d, - 0x2e,0x78,0x79,0x29,0x20,0x2f,0x20,0x5f,0x32,0x37,0x33,0x39,0x2c,0x20,0x32,0x2e, - 0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x32, - 0x38,0x30,0x34,0x20,0x3d,0x20,0x74,0x6f,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76, - 0x65,0x63,0x33,0x20,0x5f,0x32,0x38,0x30,0x35,0x20,0x3d,0x20,0x5f,0x32,0x38,0x30, - 0x34,0x20,0x2b,0x20,0x70,0x6f,0x77,0x28,0x72,0x65,0x6e,0x64,0x65,0x72,0x28,0x70, - 0x61,0x72,0x61,0x6d,0x5f,0x33,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x2c, - 0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f, - 0x36,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x34,0x35,0x34,0x34,0x39, - 0x39,0x39,0x38,0x39,0x37,0x34,0x38,0x30,0x30,0x31,0x30,0x39,0x38,0x36,0x33,0x32, - 0x38,0x31,0x32,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x6f,0x74,0x20, - 0x3d,0x20,0x5f,0x32,0x38,0x30,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74, - 0x75,0x72,0x6e,0x20,0x76,0x65,0x63,0x34,0x28,0x5f,0x32,0x38,0x30,0x35,0x2c,0x20, - 0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61, - 0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20, - 0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x75,0x76,0x20,0x2a,0x20,0x66,0x73,0x5f, - 0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x3b,0x0a,0x20,0x20, - 0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28, - 0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x75,0x76, - 0x29,0x20,0x2a,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x29,0x20,0x2a,0x20,0x39,0x2e,0x39, - 0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33, - 0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d, - 0x30,0x36,0x29,0x20,0x2b,0x20,0x6d,0x61,0x69,0x6e,0x49,0x6d,0x61,0x67,0x65,0x28, - 0x70,0x61,0x72,0x61,0x6d,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, -}; -#if !defined(SOKOL_GFX_INCLUDED) - #error "Please include sokol_gfx.h before rt_glsl.h" -#endif -static inline const sg_shader_desc* rt_shader_desc(void) { - if (sg_query_backend() == SG_BACKEND_GLCORE33) { - static sg_shader_desc desc; - static bool valid; - if (!valid) { - valid = true; - desc.attrs[0].name = "pos"; - desc.attrs[1].name = "color0"; - desc.attrs[2].name = "texcoord0"; - desc.vs.source = vs_source_glsl330; - desc.vs.entry = "main"; - desc.vs.uniform_blocks[0].size = 64; - desc.vs.uniform_blocks[0].uniforms[0].name = "vs_params"; - desc.vs.uniform_blocks[0].uniforms[0].type = SG_UNIFORMTYPE_FLOAT4; - desc.vs.uniform_blocks[0].uniforms[0].array_count = 4; - desc.fs.source = fs_source_glsl330; - desc.fs.entry = "main"; - desc.fs.uniform_blocks[0].size = 32; - desc.fs.uniform_blocks[0].uniforms[0].name = "fs_params"; - desc.fs.uniform_blocks[0].uniforms[0].type = SG_UNIFORMTYPE_FLOAT4; - desc.fs.uniform_blocks[0].uniforms[0].array_count = 2; - desc.fs.images[0].name = "tex"; - desc.fs.images[0].type = SG_IMAGETYPE_2D; - desc.fs.images[0].sampler_type = SG_SAMPLERTYPE_FLOAT; - desc.label = "rt_shader"; - }; - return &desc; - } - return 0; -} diff --git a/vlib/gg/m4/graphic.v b/vlib/gg/m4/graphic.v new file mode 100644 index 0000000000..cd24cebe8b --- /dev/null +++ b/vlib/gg/m4/graphic.v @@ -0,0 +1,105 @@ +/********************************************************************** +* +* Simply vector/matrix graphic utility +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* TODO: +**********************************************************************/ +module m4 + +import math + +// Translate degrees to radians +[inline] +pub fn rad(deg f32) f32 { + return (math.pi / 180.0) * deg +} + +// Translate radians to degrees +[inline] +pub fn deg(grad f32) f32 { + return (180.0 / math.pi) * grad +} + +// Calculate the perspective matrix +[direct_array_access] +pub fn perspective(fov f32, ar f32, n f32, f f32) Mat4 { + unsafe { + ctan := f32(1.0 / math.tan(fov * (f32(math.pi) / 360.0))) // for the FOV we use 360 instead 180 + return Mat4{ e: [ + ctan / ar, 0, 0, 0, + 0, ctan, 0, 0, + 0, 0, (n + f) / (n - f), -1.0, + 0, 0, (2.0 * n * f) / (n - f), 0, + ]! + } + } +} + +// Calculate the look-at matrix +[direct_array_access] +pub fn look_at(eye Vec4, center Vec4, up Vec4) Mat4 { + unsafe { + f := (center - eye).normalize3() + s := (f % up).normalize3() + u := (s % f) + + return Mat4{ e: [ + /* [0][0] */ s.e[0], + /* [0][1] */ u.e[0], + /* [0][2] */ - f.e[0], + /* [0][3] */ 0, + + /* [1][1] */ s.e[1], + /* [1][1] */ u.e[1], + /* [1][2] */ - f.e[1], + /* [1][3] */ 0, + + /* [2][0] */ s.e[2], + /* [2][1] */ u.e[2], + /* [2][2] */ - f.e[2], + /* [2][3] */ 0, + + /* [3][0] */ - (s * eye), + /* [3][1] */ - (u * eye), + /* [3][2] */ f * eye, + /* [3][3] */ 1, + ]! + } + } +} + +/* +hmm_mat4 proj = HMM_Perspective(60.0f, w/h, 0.01f, 10.0f); + hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 1.5f, 6.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f)); + hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view); + //state.rx += 1.0f; state.ry += 2.0f; + + + hmm_mat4 rxm = HMM_Rotate(rx, HMM_Vec3(1.0f, 0.0f, 0.0f)); + hmm_mat4 rym = HMM_Rotate(ry, HMM_Vec3(0.0f, 1.0f, 0.0f)); + + hmm_mat4 model = HMM_MultiplyMat4(rxm, rym); + hmm_mat4 scale_mx = HMM_Scale(HMM_Vec3(scale, scale, scale)); + model = HMM_MultiplyMat4(model, scale_mx); + hmm_mat4 tmp_res = HMM_MultiplyMat4(view_proj, model); +*/ + +// Get the complete transformation matrix for GLSL demos +pub fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) Mat4 { + proj := perspective(60, w / h, 0.01, 10.0) + view := look_at(Vec4{ e: [f32(0.0), 1.5, 6, 0]! }, Vec4{ e: [f32(0), 0, 0, 0]! }, Vec4{ e: [f32(0), 1.0, 0, 0]! }) + view_proj := view * proj + + rxm := rotate(rad(rx), Vec4{ e: [f32(1), 0, 0, 0]! }) + rym := rotate(rad(ry), Vec4{ e: [f32(0), 1, 0, 0]! }) + + model := rym * rxm + scale_m := scale(Vec4{ e: [in_scale, in_scale, in_scale, 1]! }) + + res := (scale_m * model) * view_proj + return res +} diff --git a/vlib/gg/m4/m4_test.v b/vlib/gg/m4/m4_test.v new file mode 100644 index 0000000000..916b9c986f --- /dev/null +++ b/vlib/gg/m4/m4_test.v @@ -0,0 +1,218 @@ +import gg.m4 + +pub fn test_m4() { + unsafe { + // Test Mat4 + mut a := m4.Mat4{ e: [ + f32(0), 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + ]! + } + mut b := m4.Mat4{} + mut c := m4.Mat4{} + + // equal test + assert a.e == [ + f32(0), 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + ]! + + // copy test + b.copy(a) + assert a.e == b.e + + // test: transpose, scale + assert b.transpose().mul_scalar(2.0).mul_scalar(0.5).transpose().e == a.e + assert b.sum_all() == 120.0 + + // test rows/columns set/get + for i in 0 .. 4 { + b = m4.zero_m4() + b.set_row(i, m4.Vec4{ e: [f32(1.0), 2, 3, 4]! }) + assert b.get_f(0, i) == 1.0 + assert b.get_f(1, i) == 2.0 + assert b.get_f(2, i) == 3.0 + assert b.get_f(3, i) == 4.0 + // println(b) + c = m4.zero_m4() + c.set_col(i, m4.Vec4{ e: [f32(1.0), 2, 3, 4]! }) + assert c.get_f(i, 0) == 1.0 + assert c.get_f(i, 1) == 2.0 + assert c.get_f(i, 2) == 3.0 + assert c.get_f(i, 3) == 4.0 + // println(c) + } + } +} + +fn test_swap_col_row() { + unsafe { + // swap_col / swap_row + b := m4.Mat4{ e: [ + f32(1), 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + ]! + } + b.swap_col(0, 2) + assert b.e == [ + f32(3), 2, 1, 4, + 7, 6, 5, 8, + 11, 10, 9, 12, + 15, 14, 13, 16, + ]! + b = m4.Mat4{ e: [ + f32(1), 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + ]! + } + b.swap_row(0, 2) + assert b.e == [ + f32(9), 10, 11, 12, + 5, 6, 7, 8, + 1, 2, 3, 4, + 13, 14, 15, 16, + ]! + } +} + +fn test_sum_sub() { + unsafe { + // test sum/sub + b := m4.unit_m4() + c := m4.unit_m4() + assert m4.sub(m4.add(b, c), b).e == m4.unit_m4().e + assert (b + c - b).e == m4.unit_m4().e + } +} + +fn test_transpose() { + unsafe { + b := m4.Mat4{ e: [ + f32(0), 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + ]! + } + assert b.transpose().transpose().e == b.e + } +} + +fn test_multiplication() { + unsafe { + b := m4.Mat4{ e: [ + f32(1), 0, 0, 0, + 0, 2, 0, 0, + 0, 0, 3, 0, + 0, 0, 0, 4, + ]! + } + c := m4.Mat4{ e: [ + f32(1), 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + ]! + } + + assert (c * c).e == [ + f32(90),100,110,120, + 202,228,254,280, + 314,356,398,440, + 426,484,542,600, + ]! + + assert m4.mul(c, c).e == [ + f32(90),100,110,120, + 202,228,254,280, + 314,356,398,440, + 426,484,542,600, + ]! + + assert m4.mul(b, c).e == [ + f32(1), 2, 3, 4, + 10, 12, 14, 16, + 27, 30, 33, 36, + 52, 56, 60, 64, + ]! + + assert (b * c).e == [ + f32(1), 2, 3, 4, + 10, 12, 14, 16, + 27, 30, 33, 36, + 52, 56, 60, 64, + ]! + + assert m4.det(b) == 24 + } +} + +fn test_det() { + unsafe { + b := m4.Mat4{ e: [ + f32(5), 6, 6, 8, + 2, 2, 2, 8, + 6, 6, 2, 8, + 2, 3, 6, 7, + ]! + } + assert m4.det(b) == -8 + + c := m4.Mat4{ e: [ + f32(1), 8, 2, 3, + 8, 2, 3, 1, + 2, 3, 3, 2, + 3, 1, 2, 4, + ]! + } + // println("*** INVERSE ****") + // println(m4.mul(b.inverse(),b)) + // println(m4.clean_small(m4.mul(c.inverse(),c))) + // println("****************") + assert m4.mul(b.inverse(), b).e == m4.unit_m4().e + assert m4.mul(c.inverse(), c).is_equal(m4.unit_m4()) + } +} + +fn test_vec4() { + // Test Vec4 + // println("*** Vector4 ****") + mut v := m4.Vec4{[f32(1), 2, 3, 4]!} + assert v * v.inv() == 4 + assert v.mul_scalar(1.0 / v.mod()).mod() == 1 + assert v + m4.Vec4{ e: [f32(5), 6, 7, 8]! } == m4.Vec4{ e: [f32(6), 8, 10, 12]! } + assert v - m4.Vec4{ e: [f32(1), 2, 3, 4]! } == m4.Vec4{ e: [f32(0), 0, 0, 0]! } + assert v.mul_vec4(m4.Vec4{ e: [f32(2), 2, 2, 2]! }) == m4.Vec4{ e: [f32(2), 4, 6, 8]! } + assert v.normalize().mod() == 1 + v = m4.Vec4{[f32(1), 2, 3, 0]!} + assert v.normalize3().mod3() - 1 < m4.precision + assert v.normalize3().mod() - 1 < m4.precision + // x y z + // 1 2 3 ==> -3 6 -3 0 + // 4 5 6 + // println(m4.Vec4{[f32(1),2,3,2]!} % m4.Vec4{[f32(4),5,6,2]!}) + assert m4.Vec4{[f32(1), 2, 3, 0]!} % m4.Vec4{[f32(4), 5, 6, 0]!} == m4.Vec4{[ f32(-3), 6, -3, 0, ]!} + assert m4.Vec4{[f32(1), 2, 3, 13]!} % m4.Vec4{[f32(4), 5, 6, 11]!} == m4.Vec4{[ f32(-3), 6, -3, 0, ]!} + + // Rotation + // println("*** Rotation ****") + rotx := m4.rotate(m4.rad(-90), m4.Vec4{ e: [f32(1.0), 0, 0, 0]! }).clean() + roty := m4.rotate(m4.rad(-90), m4.Vec4{ e: [f32(0), 1.0, 0, 0]! }).clean() + rotz := m4.rotate(m4.rad(-90), m4.Vec4{ e: [f32(0), 0, 1, 0]! }).clean() + // println( rotx ) + // println( roty ) + // println( rotz ) + // println( m4.mul_vec(rotx, m4.Vec4{e:[f32(0),0,1,0]!}).clean()) + assert m4.mul_vec(roty, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), 0.0, 1, 0]! } + assert m4.mul_vec(rotz, m4.Vec4{ e: [f32(1.0), 0.0, 0, 0]! }).clean() == m4.Vec4{ e: [f32(0), -1, 0, 0]! } + assert m4.mul_vec(rotx, m4.Vec4{ e: [f32(0), 0, 1, 0]! }).clean() == m4.Vec4{ e: [f32(0), 1, 0, 0]! } + // println("****************") +} diff --git a/vlib/gg/m4/matrix.v b/vlib/gg/m4/matrix.v new file mode 100644 index 0000000000..376ce3d472 --- /dev/null +++ b/vlib/gg/m4/matrix.v @@ -0,0 +1,624 @@ +/********************************************************************** +* +* Simply vector/matrix utility +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* TODO: +**********************************************************************/ +module m4 + +import math + +pub union Mat4 { +pub mut: + e [16]f32 + f [4][4]f32 +} + +pub const precision = f32(10e-7) + +// default precision for the module + +/********************************************************************* +* +* Utility +* +*********************************************************************/ +fn abs(a f32) f32 { + if a >= f32(0.0) { + return a + } else { + return -a + } +} + +// String representation of the matrix +pub fn (x Mat4) str() string { + unsafe { + return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|\n' + + '|${x.e[4]:-6.3},${x.e[5]:-6.3},${x.e[6]:-6.3},${x.e[7]:-6.3}|\n' + + '|${x.e[8]:-6.3},${x.e[9]:-6.3},${x.e[10]:-6.3},${x.e[11]:-6.3}|\n' + + '|${x.e[12]:-6.3},${x.e[13]:-6.3},${x.e[14]:-6.3},${x.e[15]:-6.3}|\n' + } +} + +// Remove all the raw zeros +[direct_array_access] +pub fn (a Mat4) clean() Mat4 { + unsafe { + x := Mat4{} + for c, value in a.e { + if abs(value) < m4.precision { + x.e[c] = 0 + } else { + x.e[c] = value + } + } + return x + } +} + +// Sum all the elements of the matrix +[direct_array_access] +pub fn (x Mat4) sum_all() f32 { + unsafe { + res := f32(0) + for v in x.e { + res += v + } + return res + } +} + +// Check if two matrix are equal using module precision +[direct_array_access] +pub fn (x Mat4) is_equal(y Mat4) bool { + unsafe { + for c, value in x.e { + if abs(value - y.e[c]) > m4.precision { + return false + } + } + return true + } +} + +//------------------------------------- +// Set/Get values +//------------------------------------- +// Get an element of the matrix using [0..15] indexes, one dimension +pub fn (x Mat4) get_e(elem_index int) f32 { + unsafe { + return x.e[elem_index] + } +} + +// Get an element of the matrix using [0..3][0..3] indexes, two dimension +pub fn (x Mat4) get_f(index_col int, index_row int) f32 { + unsafe { + return x.e[(index_row << 2) + index_col] + } +} + +// Set an element of the matrix using [0..15] indexes, one dimension +pub fn (mut x Mat4) set_e(index int, value f32) { + unsafe { + x.e[index] = value + } +} + +// Set an element of the matrix using [0..3][0..3] indexes, two dimension +pub fn (mut x Mat4) set_f(index_col int, index_row int, value f32) { + unsafe { + x.e[(index_row << 2) + index_col] = value + } +} + +// Copy a matrix elements from another matrix +[direct_array_access] +pub fn (mut x Mat4) copy(y Mat4) { + unsafe { + x.e = [ + y.e[0], y.e[1], y.e[2], y.e[3], + y.e[4], y.e[5], y.e[6], y.e[7], + y.e[8], y.e[9], y.e[10], y.e[11], + y.e[12], y.e[13], y.e[14], y.e[15], + ]! + } +} + +// Set the trace of the matrix using a vec4 +[direct_array_access] +pub fn (mut x Mat4) set_trace(v3 Vec4) { + unsafe { + x.e[0] = v3.e[0] + x.e[5] = v3.e[1] + x.e[10] = v3.e[2] + x.e[15] = v3.e[3] + } +} + +// Get the trace of the matrix +[direct_array_access] +pub fn (x Mat4) get_trace() Vec4 { + unsafe { + return Vec4{ e: [ x.e[0], x.e[5], x.e[10], x.e[15], ]! } + } +} + +// Set all the matrix elements to value +[direct_array_access] +pub fn (mut x Mat4) set_f32(value f32) { + unsafe { + x.e = [ + value, value, value, value, + value, value, value, value, + value, value, value, value, + value, value, value, value, + ]! + } +} + +//------------------------------------- +// Rows/Column access +//------------------------------------- +// Set the row as the input vec4 +[direct_array_access] +pub fn (mut x Mat4) set_row(row int, v3 Vec4) { + unsafe { + x.e[row * 4] = v3.e[0] + x.e[row * 4 + 1] = v3.e[1] + x.e[row * 4 + 2] = v3.e[2] + x.e[row * 4 + 3] = v3.e[3] + } +} + +// Get a row from a matrix +[direct_array_access] +pub fn (x Mat4) get_row(row int) Vec4 { + unsafe { + return Vec4{ + e: [ + x.e[row * 4], + x.e[row * 4 + 1], + x.e[row * 4 + 2], + x.e[row * 4 + 3], + ]! + } + } +} + +// Set the column as the input vec4 +[direct_array_access] +pub fn (mut x Mat4) set_col(col int, v3 Vec4) { + unsafe { + x.e[col] = v3.e[0] + x.e[col + 4] = v3.e[1] + x.e[col + 8] = v3.e[2] + x.e[col + 12] = v3.e[3] + } +} + +// Get a column from a matrix +[direct_array_access] +pub fn (x Mat4) get_col(col int) Vec4 { + unsafe { + return Vec4{ + e: [ + x.e[col], + x.e[col + 4], + x.e[col + 8], + x.e[col + 12], + ]! + } + } +} + +// Swap two columns in the matrix +[direct_array_access] +pub fn (mut x Mat4) swap_col(col1 int, col2 int) { + unsafe { + v0 := x.e[col1] + v1 := x.e[col1 + 4] + v2 := x.e[col1 + 8] + v3 := x.e[col1 + 12] + + x.e[col1] = x.e[col2] + x.e[col1 + 4] = x.e[col2 + 4] + x.e[col1 + 8] = x.e[col2 + 8] + x.e[col1 + 12] = x.e[col2 + 12] + + x.e[col2] = v0 + x.e[col2 + 4] = v1 + x.e[col2 + 8] = v2 + x.e[col2 + 12] = v3 + } +} + +// Swap two rows in the matrix +[direct_array_access] +pub fn (mut x Mat4) swap_row(row1 int, row2 int) { + unsafe { + v0 := x.e[row1 * 4] + v1 := x.e[row1 * 4 + 1] + v2 := x.e[row1 * 4 + 2] + v3 := x.e[row1 * 4 + 3] + + x.e[row1 * 4] = x.e[row2 * 4] + x.e[row1 * 4 + 1] = x.e[row2 * 4 + 1] + x.e[row1 * 4 + 2] = x.e[row2 * 4 + 2] + x.e[row1 * 4 + 3] = x.e[row2 * 4 + 3] + + x.e[row2 * 4] = v0 + x.e[row2 * 4 + 1] = v1 + x.e[row2 * 4 + 2] = v2 + x.e[row2 * 4 + 3] = v3 + } +} + +//------------------------------------- +// Modify data +//------------------------------------- +// Transpose the matrix +[direct_array_access] +pub fn (x Mat4) transpose() Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0], x.e[4], x.e[8], x.e[12], + x.e[1], x.e[5], x.e[9], x.e[13], + x.e[2], x.e[6], x.e[10], x.e[14], + x.e[3], x.e[7], x.e[11], x.e[15], + ]! + } + } +} + +// Multiply the all the elements of the matrix by a scalar +[direct_array_access] +pub fn (x Mat4) mul_scalar(s f32) Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0] * s, x.e[1] * s, x.e[2] * s, x.e[3] * s, + x.e[4] * s, x.e[5] * s, x.e[6] * s, x.e[7] * s, + x.e[8] * s, x.e[9] * s, x.e[10] * s, x.e[11] * s, + x.e[12] * s, x.e[13] * s, x.e[14] * s, x.e[15] * s, + ]! + } + } +} + +/********************************************************************* +* +* Init/set +* +*********************************************************************/ +// Return a zero matrix +[direct_array_access] +pub fn zero_m4() Mat4 { + unsafe { + return Mat4{ e: [ + f32(0), 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ]! + } + } +} + +// Return a unity matrix +[direct_array_access] +pub fn unit_m4() Mat4 { + unsafe { + return Mat4{ e: [ + f32(1), 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ]! + } + } +} + +// Return a matrix initialized with value +[direct_array_access] +pub fn set_m4(value f32) Mat4 { + return Mat4{ e: [ + value, value, value, value, + value, value, value, value, + value, value, value, value, + value, value, value, value, + ]! + } +} + +/********************************************************************* +* +* Math +* +*********************************************************************/ + +// Sum of matrix, operator + +[direct_array_access] +pub fn (a Mat4) + (b Mat4) Mat4 { + unsafe { + return Mat4{ e: [ + a.e[0] + b.e[0], a.e[1] + b.e[1], a.e[2] + b.e[2], a.e[3] + b.e[3], + a.e[4] + b.e[4], a.e[5] + b.e[5], a.e[6] + b.e[6], a.e[7] + b.e[7], + a.e[8] + b.e[8], a.e[9] + b.e[9], a.e[10] + b.e[10], a.e[11] + b.e[11], + a.e[12] + b.e[12], a.e[13] + b.e[13], a.e[14] + b.e[14], a.e[15] + b.e[15], + ]! + } + } +} + +// Subtraction of matrix, operator - +[direct_array_access] +pub fn (a Mat4) - (b Mat4) Mat4 { + unsafe { + return Mat4{ e: [ + a.e[0] - b.e[0], a.e[1] - b.e[1], a.e[2] - b.e[2], a.e[3] - b.e[3], + a.e[4] - b.e[4], a.e[5] - b.e[5], a.e[6] - b.e[6], a.e[7] - b.e[7], + a.e[8] - b.e[8], a.e[9] - b.e[9], a.e[10] - b.e[10], a.e[11] - b.e[11], + a.e[12] - b.e[12], a.e[13] - b.e[13], a.e[14] - b.e[14], a.e[15] - b.e[15], + ]! + } + } +} + +// Multiplication of matrix, operator * +[direct_array_access] +pub fn (a Mat4) * (b Mat4) Mat4 { + unsafe { + return Mat4{ + e: [ + /* [0][0] */ a.f[0][0] * b.f[0][0] + a.f[0][1] * b.f[1][0] + a.f[0][2] * b.f[2][0] + a.f[0][3] * b.f[3][0] + /* [0][1] */, a.f[0][0] * b.f[0][1] + a.f[0][1] * b.f[1][1] + a.f[0][2] * b.f[2][1] + a.f[0][3] * b.f[3][1] + /* [0][2] */, a.f[0][0] * b.f[0][2] + a.f[0][1] * b.f[1][2] + a.f[0][2] * b.f[2][2] + a.f[0][3] * b.f[3][2] + /* [0][3] */, a.f[0][0] * b.f[0][3] + a.f[0][1] * b.f[1][3] + a.f[0][2] * b.f[2][3] + a.f[0][3] * b.f[3][3] + + /* [1][0] */, a.f[1][0] * b.f[0][0] + a.f[1][1] * b.f[1][0] + a.f[1][2] * b.f[2][0] + a.f[1][3] * b.f[3][0] + /* [1][1] */, a.f[1][0] * b.f[0][1] + a.f[1][1] * b.f[1][1] + a.f[1][2] * b.f[2][1] + a.f[1][3] * b.f[3][1] + /* [1][2] */, a.f[1][0] * b.f[0][2] + a.f[1][1] * b.f[1][2] + a.f[1][2] * b.f[2][2] + a.f[1][3] * b.f[3][2] + /* [1][3] */, a.f[1][0] * b.f[0][3] + a.f[1][1] * b.f[1][3] + a.f[1][2] * b.f[2][3] + a.f[1][3] * b.f[3][3] + + /* [2][0] */, a.f[2][0] * b.f[0][0] + a.f[2][1] * b.f[1][0] + a.f[2][2] * b.f[2][0] + a.f[2][3] * b.f[3][0] + /* [2][1] */, a.f[2][0] * b.f[0][1] + a.f[2][1] * b.f[1][1] + a.f[2][2] * b.f[2][1] + a.f[2][3] * b.f[3][1] + /* [2][2] */, a.f[2][0] * b.f[0][2] + a.f[2][1] * b.f[1][2] + a.f[2][2] * b.f[2][2] + a.f[2][3] * b.f[3][2] + /* [2][3] */, a.f[2][0] * b.f[0][3] + a.f[2][1] * b.f[1][3] + a.f[2][2] * b.f[2][3] + a.f[2][3] * b.f[3][3] + + /* [3][0] */, a.f[3][0] * b.f[0][0] + a.f[3][1] * b.f[1][0] + a.f[3][2] * b.f[2][0] + a.f[3][3] * b.f[3][0] + /* [3][1] */, a.f[3][0] * b.f[0][1] + a.f[3][1] * b.f[1][1] + a.f[3][2] * b.f[2][1] + a.f[3][3] * b.f[3][1] + /* [3][2] */, a.f[3][0] * b.f[0][2] + a.f[3][1] * b.f[1][2] + a.f[3][2] * b.f[2][2] + a.f[3][3] * b.f[3][2] + /* [3][3] */, a.f[3][0] * b.f[0][3] + a.f[3][1] * b.f[1][3] + a.f[3][2] * b.f[2][3] + a.f[3][3] * b.f[3][3], + ]! + } + } +} + +// Sum of matrix function +pub fn add(a Mat4, b Mat4) Mat4 { + unsafe { + return a + b + } +} + +// Subtraction of matrix function +pub fn sub(a Mat4, b Mat4) Mat4 { + unsafe { + return a - b + } +} + +// Multiplication of matrix function +pub fn mul(a Mat4, b Mat4) Mat4 { + unsafe { + return a * b + } +} + +// Multiply a Matrix by a vector +[direct_array_access] +pub fn mul_vec(a Mat4, v Vec4) Vec4 { + unsafe { + return Vec4{ e: [ + a.e[0] * v.e[0] + a.e[4] * v.e[1] + a.e[8] * v.e[2] + a.e[12] * v.e[3], + a.e[1] * v.e[0] + a.e[5] * v.e[1] + a.e[9] * v.e[2] + a.e[13] * v.e[3], + a.e[2] * v.e[0] + a.e[6] * v.e[1] + a.e[10] * v.e[2] + a.e[14] * v.e[3], + a.e[3] * v.e[0] + a.e[7] * v.e[1] + a.e[11] * v.e[2] + a.e[15] * v.e[3], + ]! + } + } +} + +// Calculate the determinant of the Matrix +[direct_array_access] +pub fn det(x Mat4) f32 { + unsafe { + mut t := [6]f32{} + x00 := x.f[0][0] + x10 := x.f[1][0] + x20 := x.f[2][0] + x30 := x.f[3][0] + x01 := x.f[0][1] + x11 := x.f[1][1] + x21 := x.f[2][1] + x31 := x.f[3][1] + x02 := x.f[0][2] + x12 := x.f[1][2] + x22 := x.f[2][2] + x32 := x.f[3][2] + x03 := x.f[0][3] + x13 := x.f[1][3] + x23 := x.f[2][3] + x33 := x.f[3][3] + + t[0] = x22 * x33 - x23 * x32 + t[1] = x12 * x33 - x13 * x32 + t[2] = x12 * x23 - x13 * x22 + t[3] = x02 * x33 - x03 * x32 + t[4] = x02 * x23 - x03 * x22 + t[5] = x02 * x13 - x03 * x12 + + return 0.0 + + x00 * (x11 * t[0] - x21 * t[1] + x31 * t[2]) - + x10 * (x01 * t[0] - x21 * t[3] + x31 * t[4]) + + x20 * (x01 * t[1] - x11 * t[3] + x31 * t[5]) - + x30 * (x01 * t[2] - x11 * t[4] + x21 * t[5]) + } +} + +// Calculate the inverse of the Matrix +[direct_array_access] +pub fn (x Mat4) inverse() Mat4 { + unsafe { + mut t := [6]f32{} + mut det := f32(0) + + a := x.f[0][0] + b := x.f[1][0] + c := x.f[2][0] + d := x.f[3][0] + e := x.f[0][1] + f := x.f[1][1] + g := x.f[2][1] + h := x.f[3][1] + i := x.f[0][2] + j := x.f[1][2] + k := x.f[2][2] + l := x.f[3][2] + m := x.f[0][3] + n := x.f[1][3] + o := x.f[2][3] + p := x.f[3][3] + + t[0] = k * p - o * l + t[1] = j * p - n * l + t[2] = j * o - n * k + t[3] = i * p - m * l + t[4] = i * o - m * k + t[5] = i * n - m * j + + mut dest := Mat4{} + dest.f[0][0] = f * t[0] - g * t[1] + h * t[2] + dest.f[0][1] = -(e * t[0] - g * t[3] + h * t[4]) + dest.f[0][2] = e * t[1] - f * t[3] + h * t[5] + dest.f[0][3] = -(e * t[2] - f * t[4] + g * t[5]) + + dest.f[1][0] = -(b * t[0] - c * t[1] + d * t[2]) + dest.f[1][1] = a * t[0] - c * t[3] + d * t[4] + dest.f[1][2] = -(a * t[1] - b * t[3] + d * t[5]) + dest.f[1][3] = a * t[2] - b * t[4] + c * t[5] + + t[0] = g * p - o * h + t[1] = f * p - n * h + t[2] = f * o - n * g + t[3] = e * p - m * h + t[4] = e * o - m * g + t[5] = e * n - m * f + + dest.f[2][0] = b * t[0] - c * t[1] + d * t[2] + dest.f[2][1] = -(a * t[0] - c * t[3] + d * t[4]) + dest.f[2][2] = a * t[1] - b * t[3] + d * t[5] + dest.f[2][3] = -(a * t[2] - b * t[4] + c * t[5]) + + t[0] = g * l - k * h + t[1] = f * l - j * h + t[2] = f * k - j * g + t[3] = e * l - i * h + t[4] = e * k - i * g + t[5] = e * j - i * f + + dest.f[3][0] = -(b * t[0] - c * t[1] + d * t[2]) + dest.f[3][1] = a * t[0] - c * t[3] + d * t[4] + dest.f[3][2] = -(a * t[1] - b * t[3] + d * t[5]) + dest.f[3][3] = a * t[2] - b * t[4] + c * t[5] + + tmp := (a * dest.f[0][0] + b * dest.f[0][1] + c * dest.f[0][2] + d * dest.f[0][3]) + + if tmp != 0 { + det = f32(1.0) / tmp + } + + return dest.mul_scalar(det) + } +} + +/********************************************************************* +* +* Transformations +* +*********************************************************************/ + +// Get a rotation matrix using w as rotation axis vector, the angle is in radians +[direct_array_access] +pub fn rotate(angle f32, w Vec4) Mat4 { + unsafe { + cs := f32(math.cos(angle)) + sn := f32(math.sin(angle)) + cv := f32(1.0) - cs + axis := w.normalize3() + ax := axis.e[0] + ay := axis.e[1] + az := axis.e[2] + + return Mat4{ e: [ + /* [0][0] */ (ax * ax * cv) + cs + /* [0][1] */, (ax * ay * cv) + az * sn + /* [0][2] */, (ax * az * cv) - ay * sn + /* [0][3] */, 0 + + /* [1][0] */, (ay * ax * cv) - az * sn + /* [1][1] */, (ay * ay * cv) + cs + /* [1][2] */, (ay * az * cv) + ax * sn + /* [1][3] */, 0 + + /* [2][0] */, (az * ax * cv) + ay * sn + /* [2][1] */, (az * ay * cv) - ax * sn + /* [2][2] */, (az * az * cv) + cs + /* [2][3] */, 0 + + /* [3][0] */, 0 + /* [3][1] */, 0 + /* [3][2] */, 0 + /* [3][3] */, 1, + ]! + } + } +} + +/********************************************************************* +* +* Graphic +* +*********************************************************************/ +// Get a matrix translated by a vector w +[direct_array_access] +pub fn (x Mat4) translate(w Vec4) Mat4 { + unsafe { + return Mat4{ e: [ + x.e[0], x.e[1], x.e[2], x.e[3] + w.e[0], + x.e[4], x.e[5], x.e[6], x.e[7] + w.e[1], + x.e[8], x.e[9], x.e[10], x.e[11] + w.e[2], + x.e[12], x.e[13], x.e[14], x.e[15], + ]! + } + } +} + +// Get a scale matrix, the scale vector is w, only xyz are evaluated. +[direct_array_access] +pub fn scale(w Vec4) Mat4 { + unsafe { + return Mat4{ e: [ + w.e[0], 0, 0, 0, + 0, w.e[1], 0, 0, + 0, 0, w.e[2], 0, + 0, 0, 0, 1, + ]! + } + } +} diff --git a/vlib/gg/m4/vector.v b/vlib/gg/m4/vector.v new file mode 100644 index 0000000000..99e3feb534 --- /dev/null +++ b/vlib/gg/m4/vector.v @@ -0,0 +1,240 @@ +/********************************************************************** +* +* Simply vector/matrix utility +* +* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Use of this source code is governed by an MIT license +* that can be found in the LICENSE file. +* +* TODO: +**********************************************************************/ +module m4 + +import math + +pub struct Vec4 { +pub mut: + e [4]f32 +} + +/********************************************************************* +* +* Utility +* +*********************************************************************/ +pub fn (x Vec4) str() string { + return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|\n' +} + +// Remove all the raw zeros +[direct_array_access] +pub fn (a Vec4) clean() Vec4 { + unsafe { + x := Vec4{} + for c, value in a.e { + if abs(value) < precision { + x.e[c] = 0 + } else { + x.e[c] = value + } + } + return x + } +} + +// Set all elements to value +[direct_array_access] +pub fn (mut x Vec4) copy(value f32) { + x.e = [ value, value, value, value, ]! +} + +// Scale the vector using a scalar +[direct_array_access] +pub fn (x Vec4) mul_scalar(value f32) Vec4 { + return Vec4{ e: [ x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value, ]! } +} + +// Reciprocal of the vector +[direct_array_access] +pub fn (x Vec4) inv() Vec4 { + return Vec4{ + e: [ + if x.e[0] != 0 { 1.0 / x.e[0] } else { f32(0) }, + if x.e[1] != 0 { 1.0 / x.e[1] } else { f32(0) }, + if x.e[2] != 0 { 1.0 / x.e[2] } else { f32(0) }, + if x.e[3] != 0 { 1.0 / x.e[3] } else { f32(0) }, + ]! + } +} + +// Normalize the vector +[direct_array_access] +pub fn (x Vec4) normalize() Vec4 { + m := x.mod() + if m == 0 { + return zero_v4() + } + return Vec4{ + e: [ + x.e[0] * (1 / m), + x.e[1] * (1 / m), + x.e[2] * (1 / m), + x.e[3] * (1 / m), + ]! + } +} + +// Normalize only xyz, w set to 0 +[direct_array_access] +pub fn (x Vec4) normalize3() Vec4 { + m := x.mod3() + if m == 0 { + return zero_v4() + } + return Vec4{ + e: [ + x.e[0] * (1 / m), + x.e[1] * (1 / m), + x.e[2] * (1 / m), + 0, + ]! + } +} + +// Module of the vector xyzw +[direct_array_access] +pub fn (x Vec4) mod() f32 { + return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2] + x.e[3] * x.e[3])) +} + +// Module for 3d vector xyz, w ignored +[direct_array_access] +pub fn (x Vec4) mod3() f32 { + return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2])) +} + +/********************************************************************* +* +* Math +* +*********************************************************************/ +// Return a zero vector +[direct_array_access] +pub fn zero_v4() Vec4 { + return Vec4{ + e: [ + f32(0), + 0, + 0, + 0, + ]! + } +} + +// Return all one vector +[direct_array_access] +pub fn one_v4() Vec4 { + return Vec4{ + e: [ + f32(1), + 1, + 1, + 1, + ]! + } +} + +// Return a blank vector +[direct_array_access] +pub fn blank_v4() Vec4 { + return Vec4{ + e: [ + f32(0), + 0, + 0, + 1, + ]! + } +} + +// Set all elements to value +[direct_array_access] +pub fn set_v4(value f32) Vec4 { + return Vec4{ + e: [ + value, + value, + value, + value, + ]! + } +} + +// Sum of all the elements +[direct_array_access] +pub fn (x Vec4) sum() f32 { + return x.e[0] + x.e[1] + x.e[2] + x.e[3] +} + +/********************************************************************* +* +* Operators +* +*********************************************************************/ +// Addition +[direct_array_access] +pub fn (a Vec4) + (b Vec4) Vec4 { + return Vec4{ + e: [ + a.e[0] + b.e[0], + a.e[1] + b.e[1], + a.e[2] + b.e[2], + a.e[3] + b.e[3], + ]! + } +} + +// Subtraction +[direct_array_access] +pub fn (a Vec4) - (b Vec4) Vec4 { + return Vec4{ + e: [ + a.e[0] - b.e[0], + a.e[1] - b.e[1], + a.e[2] - b.e[2], + a.e[3] - b.e[3], + ]! + } +} + +// Dot product +[direct_array_access] +pub fn (a Vec4) * (b Vec4) f32 { + return a.e[0] * b.e[0] + a.e[1] * b.e[1] + a.e[2] * b.e[2] + a.e[3] * b.e[3] +} + +// Cross product +[direct_array_access] +pub fn (a Vec4) % (b Vec4) Vec4 { + return Vec4{ + e: [ + (a.e[1] * b.e[2]) - (a.e[2] * b.e[1]), + (a.e[2] * b.e[0]) - (a.e[0] * b.e[2]), + (a.e[0] * b.e[1]) - (a.e[1] * b.e[0]), + 0, + ]! + } +} + +// Components multiplication +[direct_array_access] +pub fn (x Vec4) mul_vec4(y Vec4) Vec4 { + return Vec4{ + e: [ + x.e[0] * y.e[0], + x.e[1] * y.e[1], + x.e[2] * y.e[2], + x.e[3] * y.e[3], + ]! + } +}