diff --git a/Dockerfile b/Dockerfile index cde6bf7..0b48ef9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,18 @@ # Use an official image as a parent image -FROM ubuntu:20.04 +FROM ubuntu:latest # Set the working directory WORKDIR /app # Install necessary libraries and tools -RUN apt-get update && apt-get install -y gcc libcsfml-dev make +RUN apt-get update && apt-get install -y gcc python3 libsfml-dev libcsfml-dev make python3-pip libglib2.0-0 # Copy your source code to the container COPY . . # Compile your C project -RUN make +RUN make re # Set the entry point for your application -CMD ["./bin/engine.out"] +CMD ["./launcher"] +# CMD ["./bin/engine.out", "Projects/New/config.xml"] diff --git a/Engine/AI/.vscode/tasks.json b/Engine/AI/.vscode/tasks.json new file mode 100644 index 0000000..b045707 --- /dev/null +++ b/Engine/AI/.vscode/tasks.json @@ -0,0 +1,29 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc générer le fichier actif", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}", + "-lm" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Tâche générée par le débogueur." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/Engine/AI/gomoku_model.c b/Engine/AI/gomoku_model.c new file mode 100644 index 0000000..7e898c6 --- /dev/null +++ b/Engine/AI/gomoku_model.c @@ -0,0 +1,69 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** gomoku_model +*/ + +#define MH_IMPLEMENTATION +#include "machine_learning.h" + +// 8x8=64 for the input board, 2 for the output coordinates +float gomoku_model[66] = {0}; + +typedef unsigned char uint8_t; + +uint8_t random_between_0_2(void) +{ + return rand() % 3 + '0'; +} + +int main(void) +{ + srand(time(NULL)); + + size_t stride = 8*8+2; + size_t n = ARRAY_SIZE(gomoku_model)/stride; + matrix_t in = { + .rows = n, + .cols = 1, + .stride = stride, + .ptr = gomoku_model + }; + + matrix_t out = { + .rows = n, + .cols = 2, + .stride = stride, + .ptr = (float []){gomoku_model[64], gomoku_model[65]} + }; + + size_t arch[] = {64, 64, 2}; + neural_n_t nn = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_n_t gradient = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_link_randomize(nn, 0, 1); + + size_t epochs = 100*1000; + float rate = 1; + + printf("Training...\n"); + + printf("c = %f\n", neural_link_cost(nn, in, out)); + neural_link_train(nn, gradient, in, out, epochs, rate); + printf("c = %f\n", neural_link_cost(nn, in, out)); + + printf("Done!\n"); + + printf("Saving neural network to xor.nn\n"); + neural_link_save(nn, "xor.nn"); + + neural_link_print_result(nn, (matrix_t) { + .rows = 1, + .cols = 2, + .ptr = (float[]){0, 1} + }, 1); + neural_link_free(nn); + return EXIT_SUCCESS; +} + +// Build: gcc -Wall -Wextra -Werror gomoku_model.c -o gomoku_model -lm diff --git a/Engine/AI/let.nn b/Engine/AI/let.nn new file mode 100644 index 0000000..4ddb83d --- /dev/null +++ b/Engine/AI/let.nn @@ -0,0 +1,135 @@ +2 +64 64 +0.220145 0.590230 0.401051 0.051966 0.565158 0.052271 0.539256 0.318720 0.022997 0.281223 0.795860 0.388512 0.447711 0.506017 0.609447 0.926230 0.779862 0.806888 0.326051 0.418507 0.916804 0.556302 0.902256 0.075599 0.677125 0.033926 0.181633 0.708759 0.463625 0.878365 0.349902 0.683770 0.468596 0.750953 0.735737 0.033754 0.803225 0.274993 0.352474 0.826221 0.556216 0.148333 0.214733 0.003927 0.654351 0.824179 0.930157 0.434213 0.631067 0.256208 0.852719 0.547871 0.812509 0.754976 0.623470 0.489634 0.788901 0.805103 0.198393 0.252526 0.683468 0.548295 0.936297 0.152064 +0.299248 0.672033 0.185818 0.102473 0.947026 0.538291 0.928694 0.503242 0.686625 0.143427 0.507169 0.340975 0.967606 0.437326 0.775188 0.598673 0.693534 0.627907 0.146544 0.506043 0.382883 0.770014 0.995677 0.171784 0.575118 0.194070 0.424311 0.258586 0.742365 0.360607 0.410650 0.041613 0.032640 0.596467 0.144086 0.979666 0.134759 0.072779 0.482908 0.821383 0.216206 0.990077 0.162359 0.183812 0.427403 0.937547 0.782485 0.120936 0.565454 0.929029 0.626979 0.948337 0.699043 0.622656 0.120121 0.274161 0.816726 0.544432 0.532746 0.559091 0.905039 0.943396 0.600704 0.937679 +0.539863 0.744789 0.917345 0.674622 0.817569 0.400253 0.496005 0.033775 0.390330 0.658364 0.217586 0.817733 0.595911 0.000071 0.938669 0.161365 0.929100 0.565649 0.109702 0.628143 0.188305 0.229823 0.902303 0.005031 0.774255 0.435050 0.564122 0.679294 0.378446 0.164826 0.616973 0.918309 0.909615 0.534319 0.592931 0.727184 0.934572 0.088937 0.760958 0.324902 0.747301 0.978545 0.142635 0.343212 0.978616 0.081304 0.504577 0.907715 0.646953 0.614279 0.535858 0.835258 0.844103 0.438161 0.840289 0.618358 0.873211 0.404411 0.297652 0.251657 0.569237 0.914625 0.169966 0.478852 +0.448944 0.762897 0.206036 0.383516 0.851834 0.966994 0.708418 0.599134 0.945539 0.851052 0.942346 0.924154 0.932357 0.446923 0.831869 0.579309 0.061202 0.367728 0.414567 0.905305 0.805889 0.254856 0.523663 0.679100 0.659267 0.821315 0.930757 0.228504 0.735940 0.100723 0.707356 0.184884 0.863620 0.913392 0.568400 0.715454 0.880386 0.276818 0.314588 0.825925 0.127870 0.256934 0.750079 0.060227 0.703858 0.581948 0.639536 0.765060 0.949676 0.054103 0.670365 0.755565 0.308960 0.194028 0.434665 0.968227 0.015342 0.365422 0.196731 0.751282 0.466145 0.904088 0.936166 0.329765 +0.817480 0.504566 0.045219 0.697866 0.781384 0.359807 0.523790 0.909254 0.616741 0.273869 0.969481 0.320599 0.855818 0.609017 0.085659 0.805493 0.663121 0.756024 0.561058 0.972080 0.950051 0.995723 0.940307 0.965394 0.361145 0.137039 0.716676 0.827290 0.041126 0.652842 0.157055 0.858606 0.157409 0.202274 0.556471 0.938793 0.562081 0.080262 0.848047 0.178823 0.354131 0.817528 0.499422 0.209949 0.426545 0.585081 0.015442 0.089666 0.341104 0.576500 0.061746 0.291156 0.572223 0.002054 0.256549 0.933368 0.139092 0.973225 0.760659 0.180218 0.626068 0.917714 0.038824 0.783476 +0.119988 0.595296 0.722269 0.682069 0.675557 0.570317 0.860892 0.029688 0.387845 0.360314 0.239637 0.814390 0.945394 0.255079 0.904056 0.286499 0.831579 0.965803 0.577655 0.403802 0.967856 0.834204 0.337171 0.106948 0.807429 0.097829 0.287167 0.433497 0.015543 0.325991 0.216973 0.135532 0.921286 0.939243 0.817601 0.596844 0.509559 0.678493 0.626532 0.897404 0.038807 0.866169 0.711795 0.984201 0.121248 0.615851 0.270700 0.952827 0.581653 0.848355 0.356629 0.549510 0.682559 0.693800 0.656458 0.489988 0.791629 0.943625 0.923485 0.807173 0.269615 0.140458 0.942704 0.190902 +0.079700 0.760305 0.787745 0.589260 0.438798 0.414277 0.486664 0.477605 0.280446 0.198458 0.461806 0.401694 0.814309 0.732506 0.354521 0.395963 0.580861 0.711150 0.945472 0.263420 0.404950 0.601930 0.753408 0.196579 0.545555 0.676892 0.003752 0.815170 0.817350 0.946456 0.006072 0.897051 0.706761 0.793817 0.486310 0.145559 0.208095 0.972974 0.623164 0.488541 0.171433 0.084971 0.890234 0.985742 0.817477 0.244755 0.381705 0.398338 0.955905 0.327177 0.661757 0.360854 0.929107 0.415165 0.557433 0.474662 0.092057 0.561185 0.289833 0.909408 0.507641 0.295905 0.806458 0.214402 +0.089722 0.292769 0.359961 0.297817 0.265743 0.983125 0.786358 0.437175 0.068096 0.676592 0.422917 0.885573 0.921347 0.804622 0.283910 0.877252 0.131799 0.945668 0.238107 0.060906 0.360833 0.795540 0.535568 0.452890 0.356725 0.825401 0.362297 0.864366 0.121306 0.168756 0.078768 0.211029 0.461524 0.438729 0.508846 0.727267 0.421854 0.295204 0.164443 0.489950 0.971796 0.587360 0.375522 0.893143 0.391982 0.659432 0.770396 0.523781 0.605100 0.008502 0.584687 0.965933 0.804042 0.120255 0.418822 0.160767 0.945656 0.781120 0.025133 0.066963 0.949876 0.103901 0.277991 0.411400 +0.542630 0.786837 0.138667 0.964483 0.082041 0.303110 0.454433 0.053837 0.890470 0.829955 0.946980 0.282452 0.489388 0.717376 0.806232 0.094488 0.725878 0.390919 0.060420 0.529921 0.511174 0.479243 0.690688 0.456830 0.260363 0.715822 0.523793 0.210238 0.819723 0.801784 0.621638 0.362352 0.588621 0.760306 0.326836 0.670662 0.063416 0.781268 0.724499 0.953886 0.611224 0.671480 0.236338 0.100611 0.388856 0.042570 0.195099 0.114734 0.433489 0.255519 0.644655 0.944663 0.734762 0.335343 0.401494 0.995125 0.051165 0.925287 0.205363 0.870888 0.727071 0.827002 0.233240 0.315692 +0.587307 0.560075 0.986355 0.650723 0.341344 0.710854 0.604609 0.952567 0.382334 0.840947 0.053179 0.771190 0.883517 0.248278 0.885924 0.317006 0.503797 0.530579 0.261669 0.238559 0.865923 0.663163 0.233684 0.917088 0.588450 0.439048 0.787975 0.315521 0.266049 0.021215 0.631213 0.853357 0.581290 0.617568 0.504080 0.922634 0.328422 0.108689 0.875201 0.710756 0.949635 0.928380 0.481946 0.833152 0.176657 0.367871 0.150158 0.680454 0.898450 0.411827 0.919013 0.764373 0.074990 0.152697 0.681460 0.663440 0.591745 0.469436 0.978961 0.857794 0.490650 0.610174 0.711151 0.071940 +0.227742 0.215231 0.994574 0.556164 0.323919 0.869775 0.266920 0.273555 0.798155 0.748866 0.106706 0.974812 0.116737 0.256864 0.655266 0.015187 0.668691 0.574279 0.779559 0.743681 0.726976 0.461020 0.407121 0.318721 0.930456 0.386082 0.176516 0.421106 0.996255 0.887667 0.493046 0.223997 0.102898 0.487621 0.780161 0.426817 0.357396 0.047081 0.700372 0.155550 0.795947 0.807078 0.130362 0.912684 0.063942 0.785628 0.927871 0.732634 0.359906 0.707430 0.476315 0.086883 0.168450 0.883436 0.405604 0.098906 0.269518 0.582120 0.520012 0.265773 0.469786 0.013058 0.489770 0.572684 +0.500679 0.269931 0.999501 0.858074 0.317012 0.699872 0.013624 0.112959 0.506951 0.143986 0.025643 0.570893 0.929614 0.953514 0.303527 0.289520 0.660944 0.779842 0.376403 0.829395 0.663278 0.782007 0.928300 0.932796 0.364127 0.448312 0.198569 0.833913 0.461370 0.688339 0.406597 0.962048 0.958270 0.406097 0.820122 0.275282 0.105970 0.833747 0.388242 0.612920 0.977733 0.413885 0.183813 0.907347 0.367399 0.487340 0.196867 0.028344 0.267182 0.573270 0.857738 0.930459 0.355278 0.786039 0.863255 0.719404 0.234350 0.061824 0.553317 0.695720 0.750163 0.959914 0.657768 0.708433 +0.366011 0.477891 0.983716 0.471981 0.311638 0.371958 0.084902 0.289371 0.785843 0.268715 0.196718 0.153242 0.756055 0.393585 0.181586 0.023237 0.966855 0.039325 0.953696 0.322133 0.825363 0.816951 0.041537 0.059714 0.878775 0.594854 0.755434 0.628938 0.554768 0.413202 0.337372 0.920779 0.891093 0.321088 0.392761 0.202731 0.693045 0.477662 0.492102 0.478888 0.746377 0.688820 0.632130 0.502432 0.082405 0.813716 0.525669 0.049260 0.853041 0.479365 0.371393 0.678404 0.296316 0.412930 0.738118 0.175092 0.007785 0.493552 0.804030 0.562553 0.906754 0.141402 0.483332 0.797848 +0.462490 0.876093 0.000579 0.155535 0.353755 0.492681 0.634423 0.100132 0.181500 0.266553 0.602564 0.263905 0.080269 0.128233 0.313166 0.933310 0.607598 0.684559 0.611714 0.903914 0.097489 0.349831 0.079006 0.105274 0.843383 0.883036 0.667827 0.750137 0.024438 0.151159 0.547985 0.486927 0.027252 0.548564 0.642462 0.381007 0.041244 0.276885 0.481138 0.222745 0.543438 0.083703 0.486650 0.623707 0.211935 0.799816 0.557017 0.819533 0.484374 0.168731 0.723447 0.581864 0.518563 0.802453 0.687138 0.361946 0.685488 0.354965 0.112083 0.709926 0.506124 0.660068 0.196853 0.533375 +0.208631 0.839316 0.914382 0.249876 0.116201 0.395520 0.472620 0.659639 0.479223 0.959270 0.283347 0.691158 0.759086 0.840364 0.510692 0.243460 0.009095 0.234139 0.825324 0.527658 0.036592 0.512462 0.889603 0.722080 0.867426 0.001686 0.432006 0.373550 0.661754 0.628860 0.906925 0.870386 0.468175 0.821307 0.120261 0.584376 0.216828 0.592882 0.244016 0.696050 0.552152 0.527363 0.387209 0.311238 0.367727 0.897900 0.554698 0.376822 0.132039 0.380022 0.904479 0.168631 0.892484 0.794083 0.890711 0.759910 0.795769 0.322717 0.133460 0.457523 0.951577 0.040385 0.327909 0.419752 +0.861692 0.448170 0.004128 0.078520 0.041052 0.248144 0.774570 0.593204 0.775507 0.161779 0.904442 0.143233 0.059679 0.459140 0.520055 0.191719 0.839162 0.424535 0.360349 0.731646 0.218617 0.251060 0.491556 0.014386 0.573777 0.625016 0.471910 0.525354 0.665401 0.799819 0.945106 0.527093 0.247989 0.949234 0.605613 0.289041 0.197378 0.380183 0.882246 0.972885 0.541962 0.786688 0.116119 0.601642 0.245828 0.636174 0.793360 0.084991 0.060708 0.153710 0.816637 0.279326 0.404770 0.308193 0.293712 0.978547 0.933209 0.765622 0.503900 0.598610 0.565441 0.449006 0.125703 0.813430 +0.398240 0.731316 0.102471 0.595618 0.111499 0.984717 0.568503 0.653461 0.771405 0.684622 0.255103 0.017233 0.320796 0.048464 0.102224 0.381504 0.202173 0.918860 0.660830 0.606943 0.227053 0.954542 0.585490 0.160262 0.720164 0.089390 0.758871 0.285604 0.538396 0.884574 0.099034 0.936636 0.615890 0.201505 0.532255 0.727389 0.186222 0.100758 0.380850 0.957627 0.785380 0.635953 0.974860 0.106176 0.684417 0.077084 0.487680 0.886590 0.995944 0.148510 0.493533 0.222997 0.103051 0.079023 0.383259 0.823215 0.168413 0.142131 0.108819 0.706809 0.026705 0.207853 0.643446 0.642595 +0.409359 0.175700 0.369983 0.595581 0.276458 0.750833 0.553208 0.061838 0.386786 0.528068 0.168014 0.071203 0.605152 0.655694 0.957793 0.601096 0.804204 0.451326 0.824094 0.907255 0.530348 0.207353 0.730470 0.698762 0.349484 0.839289 0.405571 0.376188 0.047142 0.049016 0.018783 0.456501 0.224717 0.388766 0.052082 0.501175 0.139599 0.605290 0.563013 0.526385 0.133358 0.731027 0.597588 0.738511 0.386721 0.555381 0.339607 0.190925 0.006707 0.163701 0.098180 0.537055 0.371054 0.828650 0.235817 0.720537 0.667939 0.641388 0.096726 0.715082 0.690404 0.115508 0.171582 0.915121 +0.504274 0.223664 0.416295 0.643874 0.828954 0.979308 0.170259 0.962313 0.710336 0.767848 0.700823 0.097057 0.323229 0.040430 0.287982 0.329935 0.204131 0.386163 0.866991 0.575185 0.214813 0.102808 0.295722 0.882752 0.744195 0.392448 0.597834 0.434599 0.507956 0.769416 0.349720 0.012231 0.993080 0.766015 0.656104 0.822035 0.745324 0.826363 0.784347 0.455659 0.594211 0.485171 0.552717 0.917440 0.525601 0.840699 0.247375 0.729732 0.226861 0.114366 0.304916 0.441674 0.217173 0.600638 0.324426 0.961369 0.993086 0.922260 0.395968 0.501042 0.691676 0.745688 0.513272 0.684757 +0.511703 0.169377 0.506791 0.257027 0.995740 0.291139 0.712686 0.589951 0.776309 0.265403 0.507391 0.301910 0.106102 0.754766 0.031642 0.332963 0.869132 0.336558 0.774637 0.086305 0.937196 0.099064 0.047674 0.930282 0.021324 0.443642 0.431323 0.713000 0.189329 0.944596 0.397757 0.701032 0.113972 0.904548 0.958059 0.109712 0.195687 0.670745 0.699663 0.971996 0.936148 0.207054 0.273906 0.042250 0.961820 0.305548 0.375213 0.830952 0.642106 0.149850 0.917257 0.579302 0.248914 0.964931 0.509583 0.270237 0.408573 0.940907 0.983237 0.597902 0.885503 0.380994 0.298935 0.999475 +0.285542 0.256994 0.109187 0.481229 0.927739 0.808850 0.453224 0.863887 0.015904 0.727130 0.906137 0.977724 0.032678 0.281349 0.808676 0.674784 0.431199 0.725933 0.254085 0.680113 0.690864 0.763669 0.950350 0.099437 0.704576 0.933588 0.697339 0.590078 0.314582 0.996273 0.589553 0.600124 0.253267 0.698740 0.081352 0.181006 0.507590 0.534577 0.044893 0.523494 0.261707 0.951030 0.501218 0.294385 0.232379 0.309893 0.969169 0.663579 0.035826 0.223254 0.343691 0.726690 0.986923 0.294042 0.826127 0.691499 0.227629 0.523466 0.281577 0.542211 0.519739 0.871130 0.142335 0.773006 +0.569869 0.223687 0.954012 0.077459 0.758264 0.998905 0.600953 0.019972 0.949935 0.102171 0.314357 0.182315 0.412064 0.283526 0.845893 0.447891 0.506781 0.189585 0.174581 0.493704 0.483626 0.000708 0.185202 0.711256 0.524173 0.466779 0.253467 0.043912 0.337909 0.395802 0.816918 0.907778 0.619489 0.770930 0.985237 0.377754 0.769835 0.586190 0.397725 0.719770 0.688361 0.712083 0.902085 0.100426 0.995609 0.747978 0.548317 0.502390 0.937563 0.722898 0.996093 0.421189 0.723605 0.181296 0.132444 0.247778 0.648075 0.385911 0.291690 0.985984 0.781713 0.108608 0.893762 0.401202 +0.879538 0.878999 0.778956 0.649373 0.465190 0.176681 0.369144 0.153551 0.888763 0.271229 0.253977 0.884372 0.019207 0.802294 0.386762 0.956769 0.525192 0.382855 0.377958 0.248797 0.564151 0.510403 0.496575 0.212226 0.896314 0.788265 0.198210 0.678027 0.896873 0.091972 0.079229 0.776411 0.970971 0.858184 0.425785 0.436161 0.034865 0.794928 0.589712 0.923628 0.066157 0.843690 0.808001 0.085363 0.645984 0.194762 0.042133 0.171175 0.577617 0.420091 0.419972 0.141769 0.930493 0.916547 0.353995 0.826807 0.704812 0.552205 0.504834 0.601685 0.644177 0.584062 0.378097 0.615148 +0.442247 0.803881 0.051309 0.477112 0.598810 0.641022 0.400740 0.664966 0.484711 0.208740 0.750330 0.130695 0.403503 0.792462 0.301870 0.981120 0.212553 0.721842 0.122889 0.143046 0.638389 0.476884 0.969853 0.343201 0.029088 0.474687 0.944887 0.673265 0.058749 0.322984 0.288414 0.500996 0.126865 0.339723 0.978107 0.725675 0.980745 0.378847 0.390641 0.465456 0.587588 0.140971 0.596151 0.991091 0.933433 0.898021 0.972211 0.145986 0.619863 0.095100 0.289032 0.258253 0.571983 0.258886 0.601454 0.601072 0.733573 0.546341 0.274337 0.792322 0.869325 0.562750 0.293318 0.996190 +0.902473 0.271425 0.721864 0.883218 0.650273 0.112505 0.348674 0.237861 0.253476 0.944825 0.228951 0.186909 0.842846 0.201162 0.332895 0.462709 0.296262 0.621927 0.720962 0.868245 0.880813 0.322416 0.469317 0.614385 0.868757 0.743654 0.406707 0.738082 0.306404 0.700025 0.734271 0.208878 0.971451 0.456135 0.092096 0.621724 0.568640 0.440769 0.859584 0.822116 0.385594 0.088535 0.009025 0.228440 0.289698 0.341919 0.691150 0.585959 0.963846 0.412112 0.454204 0.844659 0.734528 0.923521 0.459044 0.603285 0.667175 0.865751 0.341366 0.973579 0.565777 0.075638 0.182457 0.537227 +0.531773 0.274552 0.158951 0.100413 0.715322 0.018535 0.922530 0.100916 0.107071 0.931554 0.329356 0.396768 0.273474 0.020506 0.982728 0.237320 0.432618 0.436932 0.081979 0.167146 0.360453 0.541023 0.770431 0.027628 0.406774 0.111797 0.001208 0.972551 0.187435 0.183664 0.509778 0.719207 0.458217 0.668729 0.819621 0.173538 0.687265 0.742150 0.274454 0.794335 0.673705 0.603811 0.191103 0.947178 0.624317 0.173831 0.184499 0.056935 0.610763 0.266478 0.224081 0.971217 0.807501 0.994511 0.998845 0.214275 0.106308 0.000053 0.186826 0.293743 0.183717 0.696605 0.012950 0.641934 +0.365334 0.832571 0.815473 0.052599 0.574722 0.089927 0.846934 0.248426 0.693738 0.038037 0.195605 0.318054 0.211868 0.380103 0.374989 0.822632 0.646581 0.599070 0.793849 0.454082 0.593581 0.792694 0.668357 0.699889 0.792747 0.855183 0.993632 0.976464 0.551787 0.006582 0.618398 0.917121 0.839153 0.433871 0.969720 0.413875 0.523798 0.816654 0.662301 0.217535 0.854691 0.857906 0.535590 0.066559 0.238009 0.910579 0.889191 0.884590 0.509649 0.683040 0.338671 0.103230 0.475733 0.007028 0.803119 0.268480 0.862211 0.796751 0.244945 0.413998 0.803333 0.863343 0.331120 0.642486 +0.297214 0.300839 0.056361 0.821012 0.117493 0.718662 0.038547 0.972184 0.576568 0.574137 0.038743 0.814577 0.484716 0.927934 0.699167 0.994365 0.610974 0.037838 0.097594 0.086707 0.044867 0.900713 0.355187 0.907077 0.697464 0.600132 0.321076 0.500797 0.463475 0.652195 0.143284 0.760689 0.953035 0.199645 0.581700 0.070528 0.918307 0.620247 0.042712 0.494875 0.194384 0.081455 0.309452 0.679100 0.009389 0.008619 0.673465 0.620362 0.046458 0.771059 0.707069 0.091324 0.671773 0.062257 0.998402 0.369237 0.662389 0.319477 0.870034 0.125863 0.971672 0.013318 0.886552 0.924707 +0.212962 0.468252 0.995234 0.131269 0.088499 0.037946 0.626144 0.282884 0.119401 0.935596 0.961984 0.128789 0.944216 0.635449 0.749152 0.990673 0.406508 0.456221 0.081997 0.078281 0.518478 0.080399 0.447517 0.180867 0.399876 0.317551 0.306730 0.371548 0.330869 0.193282 0.296255 0.543831 0.661534 0.291489 0.675101 0.750033 0.329435 0.301245 0.032916 0.448835 0.236841 0.994900 0.577625 0.181057 0.630349 0.326777 0.171730 0.036857 0.782998 0.253728 0.115137 0.301476 0.334127 0.562655 0.482342 0.734003 0.880206 0.789072 0.105551 0.211075 0.982354 0.401806 0.754906 0.643887 +0.693295 0.430007 0.393920 0.022730 0.731252 0.426836 0.471565 0.968093 0.421736 0.049190 0.149150 0.052085 0.375967 0.320881 0.088942 0.158964 0.574608 0.204079 0.460440 0.908735 0.766734 0.942783 0.642738 0.646940 0.731855 0.748289 0.858015 0.714209 0.150094 0.612922 0.358096 0.843389 0.042929 0.752016 0.866119 0.774181 0.178852 0.337684 0.742274 0.600589 0.386874 0.891425 0.652674 0.762841 0.212306 0.741616 0.921805 0.786914 0.945695 0.382246 0.695649 0.712429 0.325028 0.338387 0.359369 0.056883 0.086675 0.217385 0.771092 0.236770 0.830307 0.129188 0.080159 0.873236 +0.881203 0.946278 0.647416 0.060056 0.283962 0.389691 0.660644 0.670836 0.281116 0.313318 0.433677 0.493421 0.054934 0.355482 0.280335 0.000629 0.737728 0.975984 0.713057 0.062756 0.314371 0.072427 0.119639 0.401046 0.289811 0.890731 0.637816 0.120118 0.019918 0.717975 0.993354 0.901122 0.664253 0.640770 0.961177 0.948214 0.030461 0.621822 0.619051 0.311576 0.935140 0.052727 0.804997 0.990074 0.408210 0.085332 0.990702 0.145937 0.061317 0.703759 0.208693 0.375688 0.776186 0.328332 0.776734 0.065997 0.219063 0.414550 0.186115 0.238981 0.132525 0.179469 0.140103 0.796777 +0.820239 0.101280 0.744992 0.850700 0.723102 0.364042 0.162276 0.658242 0.416770 0.967273 0.648315 0.824979 0.052605 0.639017 0.970916 0.113922 0.342777 0.179609 0.489610 0.118963 0.507941 0.266344 0.184960 0.727004 0.680894 0.371076 0.965985 0.813418 0.550545 0.106087 0.610196 0.370783 0.207367 0.355188 0.221483 0.930469 0.719230 0.383759 0.588711 0.135999 0.351032 0.237026 0.960979 0.403637 0.876043 0.931895 0.517560 0.218819 0.111505 0.007169 0.337782 0.619446 0.273513 0.522742 0.346450 0.954406 0.893818 0.312435 0.767825 0.444362 0.418523 0.378021 0.815146 0.625890 +0.733208 0.036629 0.556359 0.452438 0.420387 0.145070 0.588438 0.771419 0.382095 0.549416 0.175057 0.258138 0.481312 0.692616 0.476957 0.592816 0.699786 0.814739 0.212262 0.973298 0.337481 0.558713 0.927705 0.231299 0.871148 0.695530 0.675661 0.289670 0.073551 0.490807 0.915560 0.806759 0.527435 0.471919 0.259197 0.947823 0.616989 0.847635 0.719242 0.999084 0.397051 0.894299 0.257223 0.878362 0.586915 0.734180 0.471179 0.286701 0.548919 0.683441 0.259999 0.886401 0.242153 0.187704 0.117699 0.113301 0.883234 0.793360 0.402972 0.956785 0.284167 0.318532 0.763544 0.811602 +0.790451 0.022741 0.759425 0.407441 0.870375 0.478667 0.406525 0.267426 0.372966 0.663747 0.145789 0.959881 0.397927 0.616967 0.246582 0.946847 0.300408 0.506581 0.833247 0.542561 0.694285 0.950947 0.655863 0.577519 0.744307 0.058834 0.534304 0.028474 0.377366 0.297848 0.840076 0.167818 0.320589 0.599501 0.575258 0.190964 0.078168 0.981783 0.458391 0.451133 0.645531 0.604179 0.411014 0.043458 0.221146 0.657596 0.990305 0.521554 0.164177 0.823552 0.064116 0.858462 0.774499 0.719978 0.435982 0.518806 0.778813 0.970286 0.547280 0.156179 0.268134 0.387356 0.323997 0.588723 +0.986857 0.899255 0.779687 0.065024 0.881038 0.238078 0.516157 0.526569 0.842257 0.927171 0.570027 0.063403 0.584767 0.560332 0.584957 0.748944 0.383884 0.649073 0.607406 0.158383 0.369051 0.043388 0.677189 0.147864 0.013674 0.224469 0.304043 0.281808 0.611825 0.628039 0.870531 0.598681 0.527295 0.650218 0.663705 0.408333 0.888296 0.179862 0.934902 0.730552 0.107034 0.504930 0.793955 0.691801 0.065262 0.378912 0.440745 0.449147 0.027985 0.048152 0.607530 0.397036 0.091540 0.284719 0.544899 0.105213 0.509188 0.848942 0.387021 0.121012 0.476981 0.257552 0.719694 0.004276 +0.907770 0.383399 0.412609 0.796065 0.563261 0.347512 0.526618 0.670295 0.852441 0.320573 0.362096 0.917703 0.699485 0.802841 0.366850 0.727470 0.850993 0.974380 0.124506 0.942532 0.259099 0.669405 0.047746 0.768286 0.518347 0.434767 0.889299 0.995328 0.692319 0.608993 0.999604 0.600088 0.992391 0.412213 0.396154 0.555652 0.759725 0.922771 0.225947 0.612166 0.243344 0.588043 0.529870 0.942829 0.390885 0.896720 0.670299 0.241878 0.871099 0.794805 0.184410 0.130198 0.464210 0.232156 0.898485 0.982556 0.666923 0.787783 0.977884 0.359242 0.396776 0.977488 0.959330 0.389167 +0.389702 0.355484 0.944820 0.149427 0.278255 0.170767 0.761593 0.521599 0.758810 0.291462 0.464429 0.149695 0.188182 0.134728 0.391573 0.059281 0.929533 0.575983 0.189479 0.393742 0.808139 0.087964 0.376298 0.475061 0.875747 0.354183 0.834303 0.272523 0.331671 0.793633 0.661690 0.721373 0.149117 0.606510 0.870800 0.427372 0.777277 0.632392 0.948971 0.536087 0.923854 0.413400 0.685782 0.112036 0.548128 0.077355 0.171317 0.477660 0.653338 0.360797 0.871402 0.461476 0.448760 0.247701 0.936538 0.324508 0.601884 0.770841 0.597031 0.933555 0.564474 0.258721 0.654928 0.713590 +0.865231 0.525727 0.140962 0.642508 0.158120 0.089933 0.178595 0.081974 0.503333 0.864377 0.194010 0.051461 0.941732 0.365328 0.529121 0.595070 0.726125 0.400523 0.056546 0.174885 0.648224 0.993084 0.499393 0.250107 0.763924 0.096423 0.183662 0.328398 0.355144 0.838590 0.041988 0.220375 0.364318 0.182950 0.862883 0.522437 0.272884 0.041477 0.604411 0.776217 0.905855 0.798422 0.827678 0.847587 0.163749 0.356799 0.442657 0.889874 0.757322 0.499203 0.064759 0.405546 0.492287 0.564152 0.655653 0.256211 0.660575 0.839316 0.584609 0.015719 0.677906 0.626597 0.236094 0.042223 +0.809548 0.098977 0.564660 0.082432 0.140454 0.169072 0.858649 0.046309 0.967493 0.686327 0.893896 0.131243 0.043125 0.336552 0.021117 0.800447 0.835755 0.085876 0.205993 0.328042 0.650028 0.861647 0.584253 0.310603 0.700962 0.168862 0.326322 0.378868 0.795460 0.562416 0.421091 0.605007 0.661393 0.985751 0.687439 0.801847 0.154823 0.546087 0.848156 0.122316 0.232414 0.742051 0.253559 0.275539 0.078604 0.274675 0.075987 0.914359 0.360551 0.281980 0.242401 0.010578 0.143626 0.826654 0.321181 0.844588 0.995517 0.647503 0.223456 0.790976 0.209919 0.644547 0.395983 0.871312 +0.630298 0.083422 0.673159 0.785121 0.629510 0.521315 0.907437 0.861924 0.263366 0.160995 0.137463 0.341970 0.435671 0.213449 0.256329 0.796222 0.495429 0.498730 0.806800 0.639056 0.325384 0.127981 0.483644 0.320901 0.775484 0.707100 0.111877 0.985403 0.351647 0.507860 0.856714 0.981945 0.591283 0.529873 0.767066 0.220792 0.051188 0.674503 0.082716 0.314554 0.835498 0.220179 0.656524 0.271169 0.433628 0.912853 0.067390 0.929057 0.411583 0.874190 0.568113 0.736968 0.002171 0.051757 0.057868 0.777655 0.758857 0.169745 0.763058 0.110504 0.677606 0.619773 0.092450 0.268888 +0.149646 0.859516 0.489681 0.200834 0.534019 0.572397 0.515388 0.369517 0.792576 0.171912 0.640686 0.226204 0.084766 0.708076 0.155261 0.496349 0.582267 0.723375 0.233316 0.584438 0.775132 0.291185 0.362094 0.533989 0.460930 0.125152 0.644493 0.138536 0.744924 0.736943 0.407425 0.894570 0.596458 0.897106 0.095404 0.130477 0.469502 0.610792 0.499994 0.262078 0.782704 0.140680 0.488282 0.867470 0.848757 0.643544 0.363819 0.431024 0.366918 0.597135 0.015462 0.142050 0.888320 0.377556 0.676038 0.349250 0.502707 0.320531 0.487786 0.247632 0.057474 0.895211 0.142202 0.653932 +0.792317 0.237606 0.784409 0.261819 0.848398 0.284404 0.523897 0.631102 0.425084 0.012179 0.498572 0.273841 0.655723 0.862391 0.704864 0.022641 0.459526 0.720326 0.164690 0.347846 0.097882 0.840729 0.697096 0.600589 0.161260 0.184883 0.848221 0.218734 0.080094 0.990423 0.872666 0.872410 0.228030 0.657076 0.134229 0.076428 0.941479 0.658126 0.707530 0.366563 0.670305 0.206102 0.640404 0.326028 0.068493 0.345268 0.348668 0.528019 0.065595 0.513359 0.875865 0.163477 0.354087 0.572961 0.764066 0.515347 0.757843 0.612287 0.734081 0.837937 0.602711 0.606747 0.710347 0.830740 +0.263823 0.844576 0.907168 0.205302 0.502702 0.614698 0.571865 0.173007 0.820800 0.212270 0.499035 0.889293 0.557538 0.847703 0.417312 0.623133 0.361062 0.293177 0.786609 0.715149 0.866137 0.550675 0.230496 0.623981 0.162963 0.964577 0.461918 0.765674 0.571324 0.172265 0.596414 0.835147 0.016841 0.503582 0.040449 0.519543 0.118280 0.612314 0.692551 0.939080 0.824584 0.191586 0.828374 0.382122 0.039289 0.245686 0.005254 0.400351 0.538862 0.791864 0.115500 0.404999 0.342539 0.345996 0.028980 0.505502 0.310573 0.490898 0.271176 0.881897 0.663163 0.867590 0.717043 0.680004 +0.371172 0.757492 0.199547 0.489452 0.369806 0.892098 0.428532 0.194390 0.083684 0.256906 0.576511 0.122973 0.502592 0.581766 0.523324 0.041454 0.373629 0.638824 0.446453 0.716168 0.984820 0.475433 0.221670 0.295393 0.966331 0.492846 0.177289 0.629494 0.360436 0.894333 0.309497 0.731608 0.651825 0.509044 0.221060 0.021631 0.401142 0.649592 0.216021 0.484826 0.906498 0.792532 0.607798 0.409090 0.374298 0.131122 0.450543 0.747927 0.769946 0.896996 0.464096 0.754766 0.372430 0.685766 0.050158 0.338761 0.178612 0.227448 0.968254 0.539047 0.121780 0.277752 0.270655 0.773605 +0.786796 0.491715 0.795236 0.187938 0.141307 0.011257 0.672763 0.047805 0.803790 0.280562 0.456894 0.178088 0.411684 0.907438 0.926015 0.181630 0.804434 0.390110 0.936396 0.176864 0.075876 0.986554 0.515624 0.254488 0.214001 0.483879 0.793535 0.335782 0.761630 0.064191 0.109387 0.548426 0.555905 0.904623 0.736364 0.697212 0.915881 0.409128 0.745017 0.719670 0.689689 0.201911 0.897758 0.101373 0.109348 0.823772 0.283003 0.913782 0.213883 0.219399 0.090646 0.289759 0.205953 0.606271 0.544247 0.419954 0.090149 0.337782 0.755736 0.851780 0.401973 0.865122 0.400206 0.957878 +0.769746 0.136570 0.655090 0.685626 0.545698 0.400106 0.405296 0.235387 0.602017 0.303054 0.336761 0.711366 0.126826 0.619764 0.625148 0.340709 0.839163 0.715794 0.630468 0.045116 0.322065 0.174714 0.465070 0.412214 0.512497 0.220805 0.263994 0.914469 0.085928 0.664200 0.872347 0.855673 0.800770 0.527437 0.541299 0.346468 0.927543 0.946596 0.581855 0.529561 0.249650 0.918616 0.240926 0.376476 0.538380 0.866074 0.717184 0.377543 0.581868 0.347652 0.422659 0.903933 0.522366 0.887728 0.316147 0.034863 0.108533 0.580141 0.949332 0.194461 0.244341 0.821680 0.050134 0.045111 +0.349117 0.591434 0.391579 0.276660 0.538030 0.973434 0.806221 0.787679 0.892050 0.047147 0.164155 0.430430 0.913221 0.881339 0.807972 0.495089 0.228991 0.230631 0.399022 0.751358 0.118359 0.715169 0.786221 0.226893 0.295309 0.735553 0.421354 0.539650 0.557233 0.471488 0.584760 0.906349 0.062922 0.976339 0.183010 0.600952 0.949773 0.989230 0.388631 0.841822 0.036377 0.552786 0.272252 0.949597 0.434125 0.080224 0.444686 0.663116 0.310856 0.843708 0.414474 0.429215 0.558877 0.200695 0.656108 0.854186 0.936248 0.077462 0.393836 0.493481 0.548950 0.978596 0.399830 0.611872 +0.954935 0.582840 0.212824 0.904708 0.572070 0.601454 0.746530 0.608447 0.154240 0.018782 0.558044 0.588365 0.099007 0.002730 0.251481 0.409862 0.846439 0.665955 0.839077 0.405315 0.866650 0.495185 0.259501 0.802898 0.572646 0.653337 0.296378 0.121596 0.631933 0.696208 0.733468 0.586868 0.279048 0.946292 0.491576 0.851118 0.547746 0.238106 0.459565 0.701986 0.256888 0.017609 0.290351 0.355895 0.020339 0.541831 0.765757 0.866778 0.207786 0.604834 0.272093 0.074436 0.100019 0.531594 0.877333 0.672665 0.184931 0.173712 0.794261 0.816864 0.869920 0.527730 0.403731 0.148968 +0.474021 0.895307 0.000086 0.021768 0.133413 0.459651 0.723754 0.390301 0.477260 0.014104 0.746195 0.497599 0.555936 0.511952 0.364377 0.763722 0.116786 0.636470 0.838158 0.216804 0.168064 0.715491 0.889470 0.352995 0.889203 0.683731 0.169858 0.759123 0.211460 0.573590 0.908091 0.685482 0.468897 0.908178 0.707250 0.602309 0.367829 0.431003 0.992610 0.845088 0.445108 0.738805 0.342687 0.001043 0.250757 0.707064 0.764765 0.367543 0.343534 0.602923 0.584348 0.511598 0.318415 0.473817 0.864592 0.207617 0.157548 0.034451 0.966740 0.369008 0.608040 0.874832 0.054490 0.076937 +0.783010 0.761740 0.679247 0.150838 0.192743 0.671857 0.995927 0.637851 0.410662 0.338614 0.638894 0.661420 0.045678 0.403659 0.028963 0.389212 0.006583 0.613310 0.900810 0.324997 0.087128 0.765402 0.532614 0.244675 0.799853 0.499355 0.613684 0.407893 0.374187 0.668174 0.484830 0.157197 0.429914 0.164077 0.308035 0.622657 0.835934 0.303962 0.260508 0.246596 0.642576 0.899402 0.908016 0.688254 0.303062 0.936978 0.077466 0.309644 0.550289 0.978276 0.634641 0.637416 0.743678 0.167256 0.882092 0.543531 0.666611 0.495776 0.951424 0.040797 0.163950 0.436255 0.197994 0.593864 +0.600332 0.506029 0.216522 0.436265 0.809991 0.477030 0.682861 0.452567 0.376432 0.590877 0.140821 0.679494 0.527855 0.218288 0.989138 0.078144 0.196564 0.623779 0.715560 0.940242 0.791034 0.597652 0.483774 0.457645 0.093428 0.435198 0.498443 0.257378 0.871453 0.696437 0.851242 0.471784 0.202465 0.067764 0.908050 0.012456 0.544794 0.590911 0.465023 0.921226 0.181788 0.605844 0.600720 0.709643 0.824132 0.589857 0.787787 0.020696 0.213636 0.503347 0.960939 0.004671 0.100999 0.444712 0.462316 0.194427 0.879910 0.960758 0.451805 0.751363 0.657195 0.303047 0.223147 0.859660 +0.370811 0.131196 0.872117 0.915605 0.722107 0.337140 0.836831 0.903895 0.942984 0.437551 0.613537 0.767117 0.027408 0.401324 0.787813 0.241045 0.904671 0.748751 0.245715 0.005670 0.193463 0.708031 0.200098 0.073373 0.668790 0.651903 0.824736 0.325985 0.954950 0.047883 0.185645 0.325761 0.179079 0.057762 0.241366 0.901186 0.394902 0.078197 0.805081 0.337886 0.515747 0.418618 0.105003 0.543156 0.819942 0.892815 0.784200 0.724613 0.641567 0.029916 0.730284 0.835030 0.737947 0.930381 0.908403 0.406737 0.582284 0.733139 0.732721 0.537234 0.781021 0.918366 0.862995 0.960100 +0.976128 0.104360 0.861286 0.371030 0.182557 0.666367 0.708916 0.698305 0.084985 0.813919 0.241460 0.904927 0.706734 0.025661 0.629540 0.348301 0.055576 0.359824 0.183330 0.793523 0.290205 0.091733 0.200260 0.872489 0.824872 0.932981 0.409723 0.605894 0.851348 0.272717 0.565994 0.827476 0.377077 0.427280 0.198506 0.559634 0.093646 0.907422 0.257939 0.178631 0.721341 0.499399 0.083557 0.428075 0.525060 0.713097 0.776375 0.580636 0.072921 0.959706 0.374160 0.363126 0.051439 0.574420 0.235615 0.876311 0.507401 0.645337 0.482205 0.358749 0.918054 0.048199 0.186225 0.295131 +0.475479 0.384731 0.854766 0.569125 0.292153 0.112705 0.747756 0.013493 0.612104 0.831313 0.441568 0.137164 0.544410 0.217943 0.717801 0.617331 0.177649 0.091961 0.980457 0.229088 0.666380 0.216071 0.105400 0.173781 0.861408 0.587605 0.532530 0.779462 0.635804 0.718755 0.074594 0.111282 0.103486 0.929360 0.680407 0.395638 0.042064 0.428163 0.409132 0.654169 0.259476 0.850700 0.791333 0.803886 0.068643 0.509134 0.421217 0.246293 0.601095 0.401674 0.475381 0.267475 0.617745 0.580781 0.441256 0.479153 0.168386 0.973786 0.258615 0.804189 0.692541 0.333209 0.915471 0.796026 +0.262569 0.595878 0.191665 0.304633 0.024041 0.600797 0.958802 0.283517 0.451496 0.750135 0.087403 0.520140 0.259269 0.508619 0.766432 0.860364 0.910293 0.241813 0.127839 0.528038 0.822594 0.569095 0.007191 0.990980 0.542881 0.265806 0.795169 0.235422 0.599016 0.710641 0.031448 0.861584 0.306519 0.223113 0.166217 0.330560 0.823910 0.125019 0.614077 0.275406 0.875154 0.701479 0.795546 0.134424 0.210099 0.561979 0.994788 0.120392 0.803792 0.122626 0.648430 0.626386 0.691721 0.655621 0.617366 0.234602 0.921427 0.412536 0.470024 0.520443 0.123176 0.501473 0.382027 0.429696 +0.724586 0.548244 0.760256 0.548496 0.673263 0.374333 0.823902 0.548418 0.075812 0.619448 0.682841 0.285911 0.181427 0.677629 0.406303 0.985219 0.800256 0.054733 0.611605 0.491977 0.710354 0.228971 0.726579 0.631782 0.641507 0.196604 0.152225 0.764683 0.698077 0.534252 0.194379 0.422663 0.082496 0.954635 0.971159 0.755760 0.328968 0.795061 0.304178 0.404780 0.414509 0.987019 0.690692 0.595935 0.664648 0.096995 0.581154 0.464904 0.151728 0.192759 0.956881 0.862083 0.421730 0.683460 0.493865 0.063236 0.880064 0.646090 0.827919 0.578141 0.180342 0.022298 0.000804 0.262838 +0.976933 0.971962 0.018598 0.305900 0.767023 0.322776 0.710681 0.181531 0.309795 0.401372 0.777467 0.974443 0.498367 0.358621 0.439347 0.650096 0.551379 0.396228 0.512178 0.973109 0.079688 0.006043 0.036345 0.959752 0.652133 0.864264 0.537893 0.832475 0.886562 0.538696 0.095313 0.863495 0.510658 0.113911 0.169395 0.277681 0.436687 0.880076 0.459213 0.746482 0.281448 0.236679 0.720925 0.779815 0.595300 0.160272 0.429911 0.146679 0.556500 0.942090 0.119788 0.636188 0.948133 0.156133 0.595940 0.600266 0.020397 0.133833 0.432741 0.906960 0.672529 0.528054 0.770454 0.183187 +0.641965 0.939850 0.460868 0.078652 0.819926 0.920081 0.825134 0.101374 0.156760 0.546059 0.881189 0.752060 0.706331 0.311101 0.898740 0.262831 0.253190 0.018528 0.899018 0.201323 0.174661 0.494958 0.801589 0.195058 0.628791 0.234330 0.102018 0.301319 0.762384 0.872472 0.484507 0.404349 0.812322 0.945375 0.483001 0.632248 0.865456 0.308135 0.733622 0.022216 0.854194 0.614811 0.774277 0.560524 0.925912 0.673017 0.823355 0.179102 0.691544 0.722373 0.380425 0.866205 0.217331 0.182014 0.061264 0.846122 0.416345 0.163282 0.147441 0.178728 0.035754 0.631948 0.583078 0.848076 +0.577323 0.066079 0.480323 0.442779 0.374214 0.213945 0.464995 0.228407 0.828756 0.239272 0.788932 0.754668 0.912289 0.612287 0.933770 0.603833 0.334660 0.314195 0.470039 0.551992 0.496210 0.531302 0.398114 0.912554 0.694584 0.545555 0.091283 0.730338 0.177503 0.674360 0.578414 0.754826 0.740439 0.058737 0.197605 0.114653 0.272682 0.662600 0.343060 0.101439 0.901872 0.131992 0.856106 0.814161 0.744279 0.789876 0.417994 0.078939 0.104072 0.888032 0.630930 0.600281 0.419335 0.029044 0.512836 0.113919 0.574599 0.604118 0.844257 0.752102 0.278478 0.422670 0.506928 0.018917 +0.481407 0.704533 0.133570 0.754090 0.367132 0.476630 0.855528 0.269004 0.608621 0.711635 0.083165 0.352900 0.501511 0.501159 0.431839 0.605583 0.389191 0.062769 0.205864 0.808526 0.091813 0.718699 0.922445 0.666411 0.322818 0.766701 0.418513 0.601296 0.189371 0.925441 0.620213 0.670779 0.629973 0.753783 0.424868 0.997106 0.230413 0.280396 0.266110 0.839035 0.992031 0.349275 0.191935 0.493542 0.850434 0.623773 0.099124 0.239626 0.686542 0.304988 0.048152 0.778355 0.023688 0.970596 0.444766 0.346505 0.737297 0.863280 0.947801 0.926669 0.788721 0.568015 0.597447 0.418694 +0.321798 0.022316 0.415800 0.552211 0.302712 0.681910 0.391246 0.294743 0.031186 0.583180 0.788284 0.881620 0.206954 0.887409 0.121246 0.893496 0.192397 0.169397 0.671851 0.216085 0.139993 0.116617 0.562590 0.877291 0.979897 0.510391 0.803960 0.768618 0.078406 0.401407 0.187311 0.400204 0.423723 0.603111 0.952416 0.726435 0.285022 0.343661 0.021177 0.316207 0.926842 0.809462 0.197827 0.133796 0.696871 0.319073 0.027292 0.889268 0.488470 0.699142 0.105352 0.628464 0.815760 0.667942 0.505754 0.795657 0.178334 0.309714 0.564274 0.256740 0.711121 0.751586 0.656944 0.134844 +0.354697 0.609360 0.861278 0.639719 0.953021 0.882456 0.955926 0.879863 0.691917 0.153753 0.013659 0.388788 0.472826 0.040950 0.278055 0.961296 0.740093 0.383408 0.589760 0.555852 0.051350 0.095514 0.351509 0.229684 0.405228 0.915783 0.486424 0.116349 0.667369 0.143369 0.251193 0.022066 0.752729 0.112471 0.661784 0.705750 0.994927 0.617710 0.585613 0.686844 0.771463 0.599272 0.075632 0.244290 0.640222 0.353687 0.205586 0.380315 0.737095 0.795346 0.936167 0.788445 0.890860 0.287676 0.018129 0.296088 0.203459 0.504553 0.412438 0.870828 0.647922 0.663631 0.892894 0.400650 +0.776102 0.554678 0.106400 0.771029 0.172389 0.692013 0.457873 0.943852 0.291285 0.533505 0.188142 0.931507 0.887192 0.393728 0.311821 0.624287 0.189074 0.247989 0.412732 0.079934 0.535665 0.430861 0.376022 0.739124 0.935414 0.788460 0.609952 0.583336 0.452091 0.502846 0.983986 0.228193 0.057525 0.090386 0.999222 0.229914 0.782400 0.457094 0.173766 0.073684 0.990599 0.361907 0.005191 0.877791 0.755635 0.317013 0.502077 0.944709 0.565001 0.914809 0.024643 0.100666 0.345670 0.400665 0.839790 0.281084 0.189125 0.449742 0.864420 0.641215 0.952589 0.848406 0.869408 0.010114 +0.938792 0.868630 0.240027 0.721192 0.325724 0.413793 0.794876 0.316323 0.775700 0.800068 0.194114 0.531335 0.117080 0.696191 0.476044 0.682082 0.611001 0.500687 0.782748 0.956670 0.901352 0.622538 0.237754 0.090476 0.072280 0.102174 0.731692 0.024869 0.950580 0.601100 0.034983 0.889373 0.469729 0.275010 0.610565 0.795453 0.688803 0.405441 0.111776 0.464503 0.205509 0.305890 0.995838 0.322590 0.002082 0.471883 0.004671 0.613082 0.972570 0.787419 0.569753 0.873921 0.409957 0.807507 0.964397 0.482237 0.909681 0.696089 0.507107 0.860262 0.297188 0.542089 0.749635 0.766918 +1 64 +0.817099 0.360200 0.562371 0.505902 0.765641 0.674147 0.970405 0.971150 0.980038 0.966243 0.293740 0.982119 0.438126 0.298411 0.595201 0.410696 0.085830 0.164954 0.284617 0.495787 0.972461 0.249014 0.978024 0.882143 0.945103 0.485131 0.742404 0.242291 0.027220 0.492039 0.009209 0.844320 0.852239 0.571580 0.350222 0.617880 0.245727 0.320627 0.589030 0.225765 0.286870 0.882769 0.207884 0.724996 0.181180 0.803086 0.135692 0.267010 0.968040 0.420309 0.762797 0.940501 0.669323 0.740822 0.822644 0.614426 0.225953 0.565048 0.856717 0.253173 0.057087 0.865927 0.097493 0.909326 +64 2 +0.437507 0.447714 +0.527205 0.683234 +0.768341 0.116235 +0.908999 0.055211 +0.999004 0.116884 +0.780208 0.180184 +0.919969 0.915900 +0.447194 0.888009 +0.336209 0.209991 +0.828510 0.005532 +0.950813 0.651154 +0.619957 0.176766 +0.216202 0.476675 +0.429939 0.273289 +0.342601 0.527432 +0.182614 0.780108 +0.975146 0.709820 +0.463342 0.743487 +0.826054 0.372342 +0.798699 0.825058 +0.489225 0.578907 +0.005242 0.409195 +0.494806 0.452437 +0.297204 0.831015 +0.662428 0.125714 +0.836546 0.613241 +0.776868 0.456504 +0.790007 0.993069 +0.933179 0.219946 +0.266358 0.275780 +0.747378 0.448972 +0.055888 0.722524 +0.158792 0.519230 +0.466011 0.984846 +0.891572 0.264710 +0.809905 0.380797 +0.843617 0.815147 +0.789991 0.338423 +0.267583 0.087195 +0.169438 0.930011 +0.212909 0.005984 +0.543252 0.989777 +0.462488 0.333259 +0.982846 0.395667 +0.553205 0.249203 +0.671447 0.300583 +0.698175 0.727335 +0.023107 0.856967 +0.246565 0.489118 +0.841813 0.138137 +0.753828 0.651718 +0.518934 0.597445 +0.466865 0.308925 +0.935868 0.734448 +0.396120 0.105306 +0.664460 0.609029 +0.111291 0.207712 +0.598806 0.573779 +0.540971 0.581652 +0.969446 0.094177 +0.830855 0.640893 +0.394759 0.529030 +0.368228 0.417866 +0.385998 0.614793 +1 2 +0.906984 0.227811 diff --git a/Engine/AI/let_ai b/Engine/AI/let_ai new file mode 100755 index 0000000..28c309c Binary files /dev/null and b/Engine/AI/let_ai differ diff --git a/Engine/AI/let_ai.c b/Engine/AI/let_ai.c new file mode 100644 index 0000000..fdc0ad5 --- /dev/null +++ b/Engine/AI/let_ai.c @@ -0,0 +1,1099 @@ +/* +** EPITECH PROJECT, 2023 +** B-AIA-500-REN-5-1-gomoku-enzo.monnier +** File description: +** Laplacian Expanded Tree (LET) AI +*/ + +#include // printf +#include // atoi calloc +#include // memcpy + +typedef unsigned char uint8_t; + +#define EMPTY (uint8_t)'0' +#define PLAYER (uint8_t)'1' +#define OPPONENT (uint8_t)'2' + +// bool type and values +#define bool _Bool +#define false 0 +#define true 1 + +#define AT(_board) _board[i * width + j] +#define AT_H(_n) board[i * width + j + _n] +#define AT_V(_n) board[(i + _n) * width + j] +#define AT_D(_n) board[(i + _n) * width + j + _n] +#define AT_A(_n) board[(i + _n) * width + j - _n] + +/** + * @brief Let AI function + * + * @param board board to play on + * @param height height of the board + * @param width width of the board + * @return float* (x, y) coordinates + */ +int *let_ai(uint8_t *board, int height, int width) +{ +#if defined(__STDC__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + register int i = 0; + register int j = 0; + register uint8_t me = 0; + register uint8_t sum = 0; + register uint8_t sum2 = 0; +#else + int i = 0; + int j = 0; + uint8_t me = 0; + uint8_t sum = 0; + uint8_t sum2 = 0; +#endif + +#ifdef DEBUG + FILE * restrict log_file = fopen("let.log", "w+"); + if (log_file == NULL) + return 1; + fprintf(log_file, "[LOG]: Running LET AI\n"); + fprintf(log_file, "[LOG]: height: %d, width: %d\n", height, width); +#endif + + // if ai can win in 1 move do it +#ifdef DEBUG + fprintf(log_file, "[LOG]: 1 (do it)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + + //* horizontal check *// + // if 2 2 2 2 0 + if (j + 4 < width && me == OPPONENT && me == AT_H(1) && me == AT_H(2) && me == AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 4}; + + // or 2 2 0 2 2 + if (j + 4 < width && me == OPPONENT && me == AT_H(1) && EMPTY == AT_H(2) && me == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 2}; + + // or 2 0 2 2 2 + if (j + 4 < width && me == OPPONENT && EMPTY == AT_H(1) && me == AT_H(2) && me == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 1}; + + // or 2 2 2 0 2 + if (j + 4 < width && me == OPPONENT && me == AT_H(1) && me == AT_H(2) && EMPTY == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 3}; + + // or 0 2 2 2 2 + if (j + 4 < width && EMPTY == me && OPPONENT == AT_H(1) && OPPONENT == AT_H(2) && OPPONENT == AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j}; + + //* vertical check *// + // if 2 2 2 2 0 + if (i + 4 < height && me == OPPONENT && me == AT_V(1) && me == AT_V(2) && me == AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 4, j}; + + // or 2 2 0 2 2 + if (i + 4 < height && me == OPPONENT && me == AT_V(1) && EMPTY == AT_V(2) && me == AT_V(3) && me == AT_V(4)) + return (int []){i + 2, j}; + + // or 2 0 2 2 2 + if (i + 4 < height && me == OPPONENT && EMPTY == AT_V(1) && me == AT_V(2) && me == AT_V(3) && me == AT_V(4)) + return (int []){i + 1, j}; + + // or 2 2 2 0 2 + if (i + 4 < height && me == OPPONENT && me == AT_V(1) && me == AT_V(2) && EMPTY == AT_V(3) && me == AT_V(4)) + return (int []){i + 3, j}; + + // or 0 2 2 2 2 + if (i + 4 < height && EMPTY == me && OPPONENT == AT_V(1) && OPPONENT == AT_V(2) && OPPONENT == AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i, j}; + + //* diagonal check *// + // if 2 2 2 2 0 + if (i + 4 < height && j + 4 < width && me == OPPONENT && me == AT_D(1) && me == AT_D(2) && me == AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 4, j + 4}; + + // or 2 2 0 2 2 + if (i + 4 < height && j + 4 < width && me == OPPONENT && me == AT_D(1) && EMPTY == AT_D(2) && me == AT_D(3) && me == AT_D(4)) + return (int []){i + 2, j + 2}; + + // or 2 0 2 2 2 + if (i + 4 < height && j + 4 < width && me == OPPONENT && EMPTY == AT_D(1) && me == AT_D(2) && me == AT_D(3) && me == AT_D(4)) + return (int []){i + 1, j + 1}; + + // or 2 2 2 0 2 + if (i + 4 < height && j + 4 < width && me == OPPONENT && me == AT_D(1) && me == AT_D(2) && EMPTY == AT_D(3) && me == AT_D(4)) + return (int []){i + 3, j + 3}; + + // or 0 2 2 2 2 + if (i + 4 < height && j + 4 < width && EMPTY == me && OPPONENT == AT_D(1) && OPPONENT == AT_D(2) && OPPONENT == AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i, j}; + + //* anti-diagonal check *// + // if 2 2 2 2 0 + if (i + 4 < height && j - 4 >= 0 && me == OPPONENT && me == AT_A(1) && me == AT_A(2) && me == AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 4, j - 4}; + + // or 2 2 0 2 2 + if (i + 4 < height && j - 4 >= 0 && me == OPPONENT && me == AT_A(1) && EMPTY == AT_A(2) && me == AT_A(3) && me == AT_A(4)) + return (int []){i + 2, j - 2}; + + // or 2 0 2 2 2 + if (i + 4 < height && j - 4 >= 0 && me == OPPONENT && EMPTY == AT_A(1) && me == AT_A(2) && me == AT_A(3) && me == AT_A(4)) + return (int []){i + 1, j - 1}; + + // or 2 2 2 0 2 + if (i + 4 < height && j - 4 >= 0 && me == OPPONENT && me == AT_A(1) && me == AT_A(2) && EMPTY == AT_A(3) && me == AT_A(4)) + return (int []){i + 3, j - 3}; + + // or 0 2 2 2 2 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && OPPONENT == AT_A(1) && OPPONENT == AT_A(2) && OPPONENT == AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i, j}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // if ai can loose in 1 move (block) +#ifdef DEBUG + fprintf(log_file, "[LOG]: 1 (block)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + + //* horizontal check *// + // if 1 1 1 1 0 + if (j + 4 < width && me == PLAYER && me == AT_H(1) && me == AT_H(2) && me == AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 4}; + + // or 1 1 0 1 1 + if (j + 4 < width && me == PLAYER && me == AT_H(1) && EMPTY == AT_H(2) && me == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 2}; + + // or 1 0 1 1 1 + if (j + 4 < width && me == PLAYER && EMPTY == AT_H(1) && me == AT_H(2) && me == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 1}; + + // or 1 1 1 0 2 + if (j + 4 < width && me == PLAYER && me == AT_H(1) && me == AT_H(2) && EMPTY == AT_H(3) && me == AT_H(4)) + return (int []){i, j + 3}; + + // or 0 1 1 1 1 + if (j + 4 < width && EMPTY == me && PLAYER == AT_H(1) && PLAYER == AT_H(2) && PLAYER == AT_H(3) && PLAYER == AT_H(4)) + return (int []){i, j}; + + //* vertical check *// + // if 1 1 1 1 0 + if (i + 4 < height && me == PLAYER && me == AT_V(1) && me == AT_V(2) && me == AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 4, j}; + + // or 1 1 0 1 1 + if (i + 4 < height && me == PLAYER && me == AT_V(1) && EMPTY == AT_V(2) && me == AT_V(3) && me == AT_V(4)) + return (int []){i + 2, j}; + + // or 1 0 1 1 1 + if (i + 4 < height && me == PLAYER && EMPTY == AT_V(1) && me == AT_V(2) && me == AT_V(3) && me == AT_V(4)) + return (int []){i + 1, j}; + + // or 1 1 1 0 2 + if (i + 4 < height && me == PLAYER && me == AT_V(1) && me == AT_V(2) && EMPTY == AT_V(3) && me == AT_V(4)) + return (int []){i + 3, j}; + + // or 0 1 1 1 1 + if (i + 4 < height && EMPTY == me && PLAYER == AT_V(1) && PLAYER == AT_V(2) && PLAYER == AT_V(3) && PLAYER == AT_V(4)) + return (int []){i, j}; + + //* diagonal check *// + // if 1 1 1 1 0 + if (i + 4 < height && j + 4 < width && me == PLAYER && me == AT_D(1) && me == AT_D(2) && me == AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 4, j + 4}; + + // or 1 1 0 1 1 + if (i + 4 < height && j + 4 < width && me == PLAYER && me == AT_D(1) && EMPTY == AT_D(2) && me == AT_D(3) && me == AT_D(4)) + return (int []){i + 2, j + 2}; + + // or 1 0 1 1 1 + if (i + 4 < height && j + 4 < width && me == PLAYER && EMPTY == AT_D(1) && me == AT_D(2) && me == AT_D(3) && me == AT_D(4)) + return (int []){i + 1, j + 1}; + + // or 1 1 1 0 2 + if (i + 4 < height && j + 4 < width && me == PLAYER && me == AT_D(1) && me == AT_D(2) && EMPTY == AT_D(3) && me == AT_D(4)) + return (int []){i + 3, j + 3}; + + // or 0 1 1 1 1 + if (i + 4 < height && j + 4 < width && EMPTY == me && PLAYER == AT_D(1) && PLAYER == AT_D(2) && PLAYER == AT_D(3) && PLAYER == AT_D(4)) + return (int []){i, j}; + + //* anti-diagonal check *// + // if 1 1 1 1 0 + if (i + 4 < height && j - 4 >= 0 && me == PLAYER && me == AT_A(1) && me == AT_A(2) && me == AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 4, j - 4}; + + // or 1 1 0 1 1 + if (i + 4 < height && j - 4 >= 0 && me == PLAYER && me == AT_A(1) && EMPTY == AT_A(2) && me == AT_A(3) && me == AT_A(4)) + return (int []){i + 2, j - 2}; + + // or 1 0 1 1 1 + if (i + 4 < height && j - 4 >= 0 && me == PLAYER && EMPTY == AT_A(1) && me == AT_A(2) && me == AT_A(3) && me == AT_A(4)) + return (int []){i + 1, j - 1}; + + // or 1 1 1 0 2 + if (i + 4 < height && j - 4 >= 0 && me == PLAYER && me == AT_A(1) && me == AT_A(2) && EMPTY == AT_A(3) && me == AT_A(4)) + return (int []){i + 3, j - 3}; + + // or 0 1 1 1 1 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && PLAYER == AT_A(1) && PLAYER == AT_A(2) && PLAYER == AT_A(3) && PLAYER == AT_A(4)) + return (int []){i, j}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // if ai can loose in 2*2 moves (block) +#ifdef DEBUG + fprintf(log_file, "[LOG]: 2 (block)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + int tmp_y = i; + int tmp_x = j; + + // board[(i - 2) * width + j + (-2|0|2)] + // board[(i + 2) * width + j + (-2|0|2)] + #define DIAGONAL_LEFT_UP board[(tmp_y - 2) * width + tmp_x - 2] + board[(tmp_y - 1) * width + tmp_x - 1] % 48 + #define VERTICAL_UP board[(tmp_y - 2) * width + tmp_x] + board[(tmp_y - 1) * width + tmp_x] % 48 + #define DIAGONAL_RIGHT_UP board[(tmp_y - 2) * width + tmp_x + 2] + board[(tmp_y - 1) * width + tmp_x + 1] % 48 + #define HORIZONTAL_LEFT board[tmp_y * width + tmp_x - 2] + board[tmp_y * width + tmp_x - 1] % 48 + #define HORIZONTAL_RIGHT board[tmp_y * width + tmp_x + 2] + board[tmp_y * width + tmp_x + 1] % 48 + #define DIAGONAL_LEFT_DOWN board[(tmp_y + 2) * width + tmp_x - 2] + board[(tmp_y + 1) * width + tmp_x - 1] % 48 + #define VERTICAL_DOWN board[(tmp_y + 2) * width + tmp_x] + board[(tmp_y + 1) * width + tmp_x] % 48 + #define DIAGONAL_RIGHT_DOWN board[(tmp_y + 2) * width + tmp_x + 2] + board[(tmp_y + 1) * width + tmp_x + 1] % 48 + + uint8_t lines[8] = {0}; + + //* horizontal check *// + // if 0 1 1 1 0 + if (j + 4 < width && EMPTY == me && PLAYER == AT_H(1) && PLAYER == AT_H(2) && PLAYER == AT_H(3) && EMPTY == AT_H(4)) { + if (i + 2 < height && i - 2 >= 0 && j - 2 >= 0) { + memcpy(lines, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + tmp_x += 4; + + uint8_t lines_h[8]= {0}; + + if (tmp_y + 2 < height && tmp_x + 2 < width && tmp_x - 2 >= 0) { + memcpy(lines_h, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + // compare without the lines[HORIZONTAL_RIGHT] and lines_h[HORIZONTAL_LEFT] + // find max in lines_h + int max = 0; + for (int k = 0; k < 8; ++k) + if (lines_h[k] > max && k != HORIZONTAL_LEFT) + max = lines_h[k]; + + // find max in lines + int max2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] > max2 && k != HORIZONTAL_RIGHT) + max2 = lines[k]; + + if (max > max2) + return (int []){i, j + 4}; + else if (max < max2) + return (int []){i, j}; + + // find how many max in lines_h + int sum = 0; + for (int k = 0; k < 8; ++k) + if (lines_h[k] == max && k != HORIZONTAL_LEFT) + sum++; + + // find how many max in lines + int sum2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] == max2 && k != HORIZONTAL_RIGHT) + sum2++; + + if (sum > sum2) + return (int []){i, j + 4}; + else if (sum < sum2) + return (int []){i, j}; + + // sum all lines_h + sum = 0; + for (int k = 0; k < 8; ++k) + if (k != HORIZONTAL_LEFT) + sum += lines_h[k]; + + // sum all lines + sum2 = 0; + for (int k = 0; k < 8; ++k) + if (k != HORIZONTAL_RIGHT) + sum2 += lines[k]; + + if (sum > sum2) + return (int []){i, j + 4}; + else if (sum < sum2) + return (int []){i, j}; + + return (int []){i, j}; + } + + //* vertical check *// + // if 0 1 1 1 0 + if (i + 4 < height && EMPTY == me && PLAYER == AT_V(1) && PLAYER == AT_V(2) && PLAYER == AT_V(3) && EMPTY == AT_V(4)) { + if (j + 2 < width && j - 2 >= 0 && i - 2 >= 0) { + memcpy(lines, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + tmp_y += 4; + + uint8_t lines_v[8]= {0}; + + if (tmp_x + 2 < width && tmp_x - 2 >= 0 && tmp_y - 2 >= 0) { + memcpy(lines_v, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + // compare without the lines[VERTICAL_DOWN] and lines_v[VERTICAL_UP] + // find max in lines_v + int max = 0; + for (int k = 0; k < 8; ++k) + if (lines_v[k] > max && k != VERTICAL_UP) + max = lines_v[k]; + + // find max in lines + int max2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] > max2 && k != VERTICAL_DOWN) + max2 = lines[k]; + + if (max > max2) + return (int []){i + 4, j}; + else if (max < max2) + return (int []){i, j}; + + // find how many max in lines_v + int sum = 0; + for (int k = 0; k < 8; ++k) + if (lines_v[k] == max && k != VERTICAL_UP) + sum ++; + + // find how many max in lines + int sum2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] == max2 && k != VERTICAL_DOWN) + sum2 ++; + + if (sum > sum2) + return (int []){i + 4, j}; + else if (sum < sum2) + return (int []){i, j}; + + // sum all lines_v + sum = 0; + for (int k = 0; k < 8; ++k) + if (k != VERTICAL_UP) + sum += lines_v[k]; + + // sum all lines + sum2 = 0; + for (int k = 0; k < 8; ++k) + if (k != VERTICAL_DOWN) + sum2 += lines[k]; + + if (sum > sum2) + return (int []){i + 4, j}; + else if (sum < sum2) + return (int []){i, j}; + + return (int []){i, j}; + } + + //* diagonal check *// + // if 0 1 1 1 0 + if (i + 4 < height && EMPTY == me && j + 4 < width && PLAYER == AT_D(1) && PLAYER == AT_D(2) && PLAYER == AT_D(3) && EMPTY == AT_D(4)) { + if (i + 2 < height && j + 2 < width && i - 2 >= 0 && j - 2 >= 0) { + memcpy(lines, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + tmp_y += 4; + tmp_x += 4; + + uint8_t lines_d[8]= {0}; + + if (tmp_y + 2 < height && tmp_x + 2 < width && tmp_y - 2 >= 0 && tmp_x - 2 >= 0) { + memcpy(lines_d, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + // compare without the lines[DIAGONAL_RIGHT_DOWN] and lines_d[DIAGONAL_LEFT_UP] + // find max in lines_d + int max = 0; + for (int k = 0; k < 8; ++k) + if (lines_d[k] > max && k != DIAGONAL_LEFT_UP) + max = lines_d[k]; + + // find max in lines + int max2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] > max2 && k != DIAGONAL_RIGHT_DOWN) + max2 = lines[k]; + + if (max > max2) + return (int []){i + 4, j + 4}; + else if (max < max2) + return (int []){i, j}; + + // find how many max in lines_d + int sum = 0; + for (int k = 0; k < 8; ++k) + if (lines_d[k] == max && k != DIAGONAL_LEFT_UP) + sum ++; + + // find how many max in lines + int sum2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] == max2 && k != DIAGONAL_RIGHT_DOWN) + sum2 ++; + + if (sum > sum2) + return (int []){i + 4, j + 4}; + else if (sum < sum2) + return (int []){i, j}; + + // sum all lines_d + sum = 0; + for (int k = 0; k < 8; ++k) + if (k != DIAGONAL_LEFT_UP) + sum += lines_d[k]; + + // sum all lines + sum2 = 0; + for (int k = 0; k < 8; ++k) + if (k != DIAGONAL_RIGHT_DOWN) + sum2 += lines[k]; + + if (sum > sum2) + return (int []){i + 4, j + 4}; + else if (sum < sum2) + return (int []){i, j}; + + return (int []){i, j}; + } + + //* anti-diagonal check *// + // if 0 1 1 1 0 + if (i + 4 < height && EMPTY == me && j - 4 >= 0 && PLAYER == AT_A(1) && PLAYER == AT_A(2) && PLAYER == AT_A(3) && EMPTY == AT_A(4)) { + if (i + 2 < height && j + 2 < width && i - 2 >= 0 && j - 2 >= 0) { + memcpy(lines, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + } + + tmp_y = i + 4; + tmp_x = j - 4; + + uint8_t lines_a[8]= {0}; + + if (tmp_y + 2 < height && tmp_x + 2 < width && tmp_y - 2 >= 0 && tmp_x - 2 >= 0) { + memcpy(lines_a, (uint8_t [8]){ + DIAGONAL_LEFT_UP, VERTICAL_UP, DIAGONAL_RIGHT_UP, + HORIZONTAL_LEFT, HORIZONTAL_RIGHT, + DIAGONAL_LEFT_DOWN, VERTICAL_DOWN, DIAGONAL_RIGHT_DOWN + }, 8); + }; + + // compare without the lines[DIAGONAL_LEFT_DOWN] and lines_a[DIAGONAL_RIGHT_UP] + // find max in lines_a + int max = 0; + for (int k = 0; k < 8; ++k) + if (lines_a[k] > max && k != DIAGONAL_RIGHT_UP) + max = lines_a[k]; + + // find max in lines + int max2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] > max2 && k != DIAGONAL_LEFT_DOWN) + max2 = lines[k]; + + if (max > max2) + return (int []){i + 4, j - 4}; + else if (max < max2) + return (int []){i, j}; + + // find how many max in lines_a + int sum = 0; + for (int k = 0; k < 8; ++k) + if (lines_a[k] == max && k != DIAGONAL_RIGHT_UP) + sum ++; + + // find how many max in lines + int sum2 = 0; + for (int k = 0; k < 8; ++k) + if (lines[k] == max2 && k != DIAGONAL_LEFT_DOWN) + sum2 ++; + + if (sum > sum2) + return (int []){i + 4, j - 4}; + else if (sum < sum2) + return (int []){i, j}; + + // sum all lines_a + sum = 0; + for (int k = 0; k < 8; ++k) + if (k != DIAGONAL_RIGHT_UP) + sum += lines_a[k]; + + // sum all lines + sum2 = 0; + for (int k = 0; k < 8; ++k) + if (k != DIAGONAL_LEFT_DOWN) + sum2 += lines[k]; + + if (sum > sum2) + return (int []){i + 4, j - 4}; + else if (sum < sum2) + return (int []){i, j}; + + return (int []){i, j}; + } + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + + // if ai can loose in 2 moves (block) by block check +#ifdef DEBUG + fprintf(log_file, "[LOG]: 2 (block) by block check\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + + //* block check *// + // 1 1 + // 1 0 + if (j + 2 < width && i + 2 < height && PLAYER == me && PLAYER == AT_H(1) && PLAYER == AT_V(1) && EMPTY == AT_D(1)) + return (int []){i + 1, j + 1}; + + // 1 1 + // 0 1 + if (j + 2 < width && i + 2 < height && PLAYER == me && PLAYER == AT_H(1) && EMPTY == AT_V(1) && PLAYER == AT_D(1)) + return (int []){i + 1, j}; + + // 1 0 + // 1 1 + if (j + 2 < width && i + 2 < height && PLAYER == me && EMPTY == AT_H(1) && PLAYER == AT_V(1) && PLAYER == AT_D(1)) + return (int []){i, j + 1}; + + // 0 1 + // 1 1 + if (j + 2 < width && i + 2 < height && EMPTY == me && PLAYER == AT_H(1) && PLAYER == AT_V(1) && PLAYER == AT_D(1)) + return (int []){i, j}; + + //* square check *// + // 0 0 0 + // 1 0 1 + // 0 1 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && EMPTY == me && PLAYER == AT_A(1) && PLAYER == AT_D(1) && PLAYER == AT_V(2)) + return (int []){i, j}; + + // 0 1 0 + // 1 0 1 + // 0 0 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && PLAYER == me && PLAYER == AT_A(1) && PLAYER == AT_D(1) && EMPTY == AT_V(2)) + return (int []){i + 2, j}; + + // 0 1 0 + // 0 0 1 + // 0 1 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && PLAYER == me && EMPTY == AT_A(1) && PLAYER == AT_D(1) && PLAYER == AT_V(2)) + return (int []){i + 1, j - 1}; + + // 0 1 0 + // 1 0 0 + // 0 1 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && PLAYER == me && PLAYER == AT_A(1) && EMPTY == AT_D(1) && PLAYER == AT_V(2)) + return (int []){i + 1, j + 1}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // if ai can win in 2 moves do it +#ifdef DEBUG + fprintf(log_file, "[LOG]: 2 (do it)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + + //* horizontal check *// + // if 0 2 2 2 0 + if (j + 4 < width && EMPTY == me && OPPONENT == AT_H(1) && OPPONENT == AT_H(2) && OPPONENT == AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j}; + + // or 0 0 2 2 2 + if (j + 4 < width && EMPTY == me && EMPTY == AT_H(1) && OPPONENT == AT_H(2) && OPPONENT == AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j}; + + // or 2 2 2 0 0 + if (j + 4 < width && me == OPPONENT && me == AT_H(1) && me == AT_H(2) && EMPTY == AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 3}; + + //* vertical check *// + // if 0 2 2 2 0 + if (i + 4 < height && EMPTY == me && OPPONENT == AT_V(1) && OPPONENT == AT_V(2) && OPPONENT == AT_V(3) && EMPTY == AT_V(4)) + return (int []){i, j}; + + // or 0 0 2 2 2 + if (i + 4 < height && EMPTY == me && EMPTY == AT_V(1) && OPPONENT == AT_V(2) && OPPONENT == AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i, j}; + + // or 2 2 2 0 0 + if (i + 4 < height && me == OPPONENT && me == AT_V(1) && me == AT_V(2) && EMPTY == AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 3, j}; + + //* diagonal check *// + // if 0 2 2 2 0 + if (i + 4 < height && j + 4 < width && EMPTY == me && OPPONENT == AT_D(1) && OPPONENT == AT_D(2) && OPPONENT == AT_D(3) && EMPTY == AT_D(4)) + return (int []){i, j}; + + // or 0 0 2 2 2 + if (i + 4 < height && j + 4 < width && EMPTY == me && EMPTY == AT_D(1) && OPPONENT == AT_D(2) && OPPONENT == AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i, j}; + + // or 2 2 2 0 0 + if (i + 4 < height && j + 4 < width && me == OPPONENT && me == AT_D(1) && me == AT_D(2) && EMPTY == AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 3, j + 3}; + + //* anti-diagonal check *// + // if 0 2 2 2 0 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && OPPONENT == AT_A(1) && OPPONENT == AT_A(2) && OPPONENT == AT_A(3) && EMPTY == AT_A(4)) + return (int []){i, j}; + + // or 0 0 2 2 2 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && EMPTY == AT_A(1) && OPPONENT == AT_A(2) && OPPONENT == AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i, j}; + + // or 2 2 2 0 0 + if (i + 4 < height && j - 4 >= 0 && me == OPPONENT && me == AT_A(1) && me == AT_A(2) && EMPTY == AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 3, j - 3}; + + //* block check *// + // 2 2 + // 2 0 + if (j + 2 < width && i + 2 < height && OPPONENT == me && OPPONENT == AT_H(1) && OPPONENT == AT_V(1) && EMPTY == AT_D(1)) + return (int []){i + 1, j + 1}; + + // 2 2 + // 0 2 + if (j + 2 < width && i + 2 < height && OPPONENT == me && OPPONENT == AT_H(1) && EMPTY == AT_V(1) && OPPONENT == AT_D(1)) + return (int []){i + 1, j}; + + // 2 0 + // 2 2 + if (j + 2 < width && i + 2 < height && OPPONENT == me && EMPTY == AT_H(1) && OPPONENT == AT_V(1) && OPPONENT == AT_D(1)) + return (int []){i, j + 1}; + + // 0 2 + // 2 2 + if (j + 2 < width && i + 2 < height && EMPTY == me && OPPONENT == AT_H(1) && OPPONENT == AT_V(1) && OPPONENT == AT_D(1)) + return (int []){i, j}; + + //* square check *// + // 0 0 0 + // 2 0 2 + // 0 2 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && EMPTY == me && OPPONENT == AT_A(1) && OPPONENT == AT_D(1) && OPPONENT == AT_V(2)) + return (int []){i, j}; + + // 0 2 0 + // 2 0 2 + // 0 0 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && OPPONENT == me && OPPONENT == AT_A(1) && OPPONENT == AT_D(1) && EMPTY == AT_V(2)) + return (int []){i + 2, j}; + + // 0 2 0 + // 0 0 2 + // 0 2 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && OPPONENT == me && EMPTY == AT_A(1) && OPPONENT == AT_D(1) && OPPONENT == AT_V(2)) + return (int []){i + 1, j - 1}; + + // 0 2 0 + // 2 0 0 + // 0 2 0 + if (j - 1 >= 0 && j + 1 < width && i + 2 < height && OPPONENT == me && OPPONENT == AT_A(1) && EMPTY == AT_D(1) && OPPONENT == AT_V(2)) + return (int []){i + 1, j + 1}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // if ai can win in 3 moves do it +#ifdef DEBUG + fprintf(log_file, "[LOG]: 3 (do it)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + + //* horizontal check *// + + // if 0 0 0 1 1 + if (j + 4 < width && EMPTY == me && PLAYER != AT_H(1) && PLAYER != AT_H(2) && OPPONENT == AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j}; + // or 0 0 1 1 0 + if (j + 4 < width && EMPTY == me && PLAYER != AT_H(1) && OPPONENT == AT_H(2) && OPPONENT == AT_H(3) && PLAYER != AT_H(4)) + return (int []){i, j}; + // or 0 1 1 0 0 + if (j + 4 < width && EMPTY == me && OPPONENT == AT_H(1) && OPPONENT == AT_H(2) && PLAYER != AT_H(3) && PLAYER != AT_H(4)) + return (int []){i, j}; + // or 1 1 0 0 0 + if (j + 4 < width && OPPONENT == me && OPPONENT == AT_H(1) && PLAYER != AT_H(2) && PLAYER != AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 4}; + // or 0 1 0 1 0 + if (j + 4 < width && EMPTY == me && OPPONENT == AT_H(1) && PLAYER != AT_H(2) && OPPONENT == AT_H(3) && PLAYER != AT_H(4)) + return (int []){i, j}; + // or 0 0 1 0 1 + if (j + 4 < width && EMPTY == me && PLAYER != AT_H(1) && OPPONENT == AT_H(2) && PLAYER != AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j}; + // or 1 0 1 0 0 + if (j + 4 < width && OPPONENT == me && PLAYER != AT_H(1) && OPPONENT == AT_H(2) && PLAYER != AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 4}; + // or 1 0 0 0 1 + if (j + 4 < width && OPPONENT == me && PLAYER != AT_H(1) && PLAYER != AT_H(2) && EMPTY == AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j + 3}; + // or 0 1 0 0 1 + if (j + 4 < width && EMPTY == me && OPPONENT == AT_H(1) && PLAYER != AT_H(2) && PLAYER != AT_H(3) && OPPONENT == AT_H(4)) + return (int []){i, j}; + // or 1 0 0 1 0 + if (j + 4 < width && OPPONENT == me && PLAYER != AT_H(1) && PLAYER != AT_H(2) && OPPONENT == AT_H(3) && EMPTY == AT_H(4)) + return (int []){i, j + 4}; + + //* vertical check *// + + // if 0 0 0 1 1 + if (i + 4 < height && EMPTY == me && PLAYER != AT_V(1) && PLAYER != AT_V(2) && OPPONENT == AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i, j}; + // or 0 0 1 1 0 + if (i + 4 < height && EMPTY == me && PLAYER != AT_V(1) && OPPONENT == AT_V(2) && OPPONENT == AT_V(3) && PLAYER != AT_V(4)) + return (int []){i, j}; + // or 0 1 1 0 0 + if (i + 4 < height && EMPTY == me && OPPONENT == AT_V(1) && OPPONENT == AT_V(2) && PLAYER != AT_V(3) && PLAYER != AT_V(4)) + return (int []){i, j}; + // or 1 1 0 0 0 + if (i + 4 < height && OPPONENT == me && OPPONENT == AT_V(1) && PLAYER != AT_V(2) && PLAYER != AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 4, j}; + // or 0 1 0 1 0 + if (i + 4 < height && EMPTY == me && OPPONENT == AT_V(1) && PLAYER != AT_V(2) && OPPONENT == AT_V(3) && PLAYER != AT_V(4)) + return (int []){i, j}; + // or 0 0 1 0 1 + if (i + 4 < height && EMPTY == me && PLAYER != AT_V(1) && OPPONENT == AT_V(2) && PLAYER != AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i, j}; + // or 1 0 1 0 0 + if (i + 4 < height && OPPONENT == me && PLAYER != AT_V(1) && OPPONENT == AT_V(2) && PLAYER != AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 4, j}; + // or 1 0 0 0 1 + if (i + 4 < height && OPPONENT == me && PLAYER != AT_V(1) && PLAYER != AT_V(2) && EMPTY == AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i + 3, j}; + // or 0 1 0 0 1 + if (i + 4 < height && EMPTY == me && OPPONENT == AT_V(1) && PLAYER != AT_V(2) && PLAYER != AT_V(3) && OPPONENT == AT_V(4)) + return (int []){i, j}; + // or 1 0 0 1 0 + if (i + 4 < height && OPPONENT == me && PLAYER != AT_V(1) && PLAYER != AT_V(2) && OPPONENT == AT_V(3) && EMPTY == AT_V(4)) + return (int []){i + 4, j}; + + //* diagonal check *// + + // if 0 0 0 1 1 + if (i + 4 < height && j + 4 < width && EMPTY == me && PLAYER != AT_D(1) && PLAYER != AT_D(2) && OPPONENT == AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i, j}; + // or 0 0 1 1 0 + if (i + 4 < height && j + 4 < width && EMPTY == me && PLAYER != AT_D(1) && OPPONENT == AT_D(2) && OPPONENT == AT_D(3) && PLAYER != AT_D(4)) + return (int []){i, j}; + // or 0 1 1 0 0 + if (i + 4 < height && j + 4 < width && EMPTY == me && OPPONENT == AT_D(1) && OPPONENT == AT_D(2) && PLAYER != AT_D(3) && PLAYER != AT_D(4)) + return (int []){i, j}; + // or 1 1 0 0 0 + if (i + 4 < height && j + 4 < width && OPPONENT == me && OPPONENT == AT_D(1) && PLAYER != AT_D(2) && PLAYER != AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 4, j + 4}; + // or 0 1 0 1 0 + if (i + 4 < height && j + 4 < width && EMPTY == me && OPPONENT == AT_D(1) && PLAYER != AT_D(2) && OPPONENT == AT_D(3) && PLAYER != AT_D(4)) + return (int []){i, j}; + // or 0 0 1 0 1 + if (i + 4 < height && j + 4 < width && EMPTY == me && PLAYER != AT_D(1) && OPPONENT == AT_D(2) && PLAYER != AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i, j}; + // or 1 0 1 0 0 + if (i + 4 < height && j + 4 < width && OPPONENT == me && PLAYER != AT_D(1) && OPPONENT == AT_D(2) && PLAYER != AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 4, j + 4}; + // or 1 0 0 0 1 + if (i + 4 < height && j + 4 < width && OPPONENT == me && PLAYER != AT_D(1) && PLAYER != AT_D(2) && EMPTY == AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i + 3, j + 3}; + // or 0 1 0 0 1 + if (i + 4 < height && j + 4 < width && EMPTY == me && OPPONENT == AT_D(1) && PLAYER != AT_D(2) && PLAYER != AT_D(3) && OPPONENT == AT_D(4)) + return (int []){i, j}; + // or 1 0 0 1 0 + if (i + 4 < height && j + 4 < width && OPPONENT == me && PLAYER != AT_D(1) && PLAYER != AT_D(2) && OPPONENT == AT_D(3) && EMPTY == AT_D(4)) + return (int []){i + 4, j + 4}; + + //* anti-diagonal check *// + + // if 0 0 0 1 1 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && PLAYER != AT_A(1) && PLAYER != AT_A(2) && OPPONENT == AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i, j}; + // or 0 0 1 1 0 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && PLAYER != AT_A(1) && OPPONENT == AT_A(2) && OPPONENT == AT_A(3) && PLAYER != AT_A(4)) + return (int []){i, j}; + // or 0 1 1 0 0 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && OPPONENT == AT_A(1) && OPPONENT == AT_A(2) && PLAYER != AT_A(3) && PLAYER != AT_A(4)) + return (int []){i, j}; + // or 1 1 0 0 0 + if (i + 4 < height && j - 4 >= 0 && OPPONENT == me && OPPONENT == AT_A(1) && PLAYER != AT_A(2) && PLAYER != AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 4, j - 4}; + // or 0 1 0 1 0 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && OPPONENT == AT_A(1) && PLAYER != AT_A(2) && OPPONENT == AT_A(3) && PLAYER != AT_A(4)) + return (int []){i, j}; + // or 0 0 1 0 1 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && PLAYER != AT_A(1) && OPPONENT == AT_A(2) && PLAYER != AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i, j}; + // or 1 0 1 0 0 + if (i + 4 < height && j - 4 >= 0 && OPPONENT == me && PLAYER != AT_A(1) && OPPONENT == AT_A(2) && PLAYER != AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 4, j - 4}; + // or 1 0 0 0 1 + if (i + 4 < height && j - 4 >= 0 && OPPONENT == me && PLAYER != AT_A(1) && PLAYER != AT_A(2) && EMPTY == AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i + 3, j - 3}; + // or 0 1 0 0 1 + if (i + 4 < height && j - 4 >= 0 && EMPTY == me && OPPONENT == AT_A(1) && PLAYER != AT_A(2) && PLAYER != AT_A(3) && OPPONENT == AT_A(4)) + return (int []){i, j}; + // or 1 0 0 1 0 + if (i + 4 < height && j - 4 >= 0 && OPPONENT == me && PLAYER != AT_A(1) && PLAYER != AT_A(2) && OPPONENT == AT_A(3) && EMPTY == AT_A(4)) + return (int []){i + 4, j - 4}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // if ai can win in 4 moves (block) +#ifdef DEBUG + fprintf(log_file, "[LOG]: 4 (block)\n[\n"); +#endif + for (i = 0; i < height; ++i) { + #ifdef DEBUG + fprintf(log_file, " [ "); + #endif + for (j = 0; j < width; ++j) { + me = AT(board); + if (j + 4 < width && me == PLAYER && EMPTY == AT_H(1)) + return (int []){i, j + 1}; + if (me + 4 < height && me == PLAYER && EMPTY == AT_V(1)) + return (int []){i + 1, j}; + if (i + 4 < height && j + 4 < width && me == PLAYER && EMPTY == AT_D(1)) + return (int []){i + 1, j + 1}; + if (i + 4 < height && j - 4 >= 0 && me == PLAYER && EMPTY == AT_A(1)) + return (int []){i + 1, j - 1}; + +#ifdef DEBUG + fprintf(log_file, "%c ", me); + } + fprintf(log_file, "]\n"); + } + fprintf(log_file, "]\n"); +#else + } + } // end of for loops +#endif + + // play in the first empty case between 4 and max-4 +#ifdef DEBUG + fprintf(log_file, "[LOG]: 4 (first empty case between 4 and max-4)\n[\n"); +#endif + for (i = 4; i < height-4; ++i) + for (j = 4; j < width-4; ++j) { + if (AT(board) == EMPTY) + return (int []){i, j}; + } + + // play in the first empty case + for (i = 0; i < height; ++i) + for (j = 0; j < width; ++j) { + if (AT(board) == EMPTY) + return (int []){i, j}; + } + +#ifdef DEBUG + fprintf(log_file, "[ERROR]: (-1, -1)\n"); + fclose(log_file); +#endif + printf("-1,-1\n"); + return (int []){-1, -1}; +} + +#define MH_IMPLEMENTATION +#include "machine_learning.h" + +// 8x8=64 for the input board, 2 for the output coordinates +float gomoku_model[66] = {0}; + +uint8_t random_between_0_2(void) +{ + return rand() % 3 + '0'; +} + +int main(void) +{ + srand(time(NULL)); + + size_t stride = 8*8; + size_t n = ARRAY_SIZE(gomoku_model)/stride; + + uint8_t board[64] = {0}; + + for (size_t i = 0; i < n; ++i) { + for (size_t j = 0; j < stride; ++j) { + board[j] = random_between_0_2(); + } + } + + for (size_t i = 0; i < n; ++i) { + for (size_t j = 0; j < stride; ++j) { + gomoku_model[j] = (float)((board[j]-'0')/'2'); + } + } + + matrix_t in = { + .rows = n, + .cols = 8*8, + .stride = stride, + .ptr = gomoku_model + }; + + int *ok = let_ai(board, 8, 8); + gomoku_model[64] = (float)((ok[0]-'0')/'2'); + gomoku_model[65] = (float)((ok[1]-'0')/'2'); + + matrix_t out = { + .rows = n, + .cols = 2, + .stride = stride, + .ptr = gomoku_model + 64 + }; + + size_t arch[] = {64, 64, 2}; + neural_n_t nn = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_n_t gradient = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_link_randomize(nn, 0, 1); + + size_t epochs = 100*1000; + float rate = 1; + + printf("Training...\n"); + + NEURAL_LINK_PRINT(nn); + printf("c = %f\n", neural_link_cost(nn, in, out)); + neural_link_train(nn, gradient, in, out, epochs, rate); + printf("c = %f\n", neural_link_cost(nn, in, out)); + NEURAL_LINK_PRINT(nn); + + printf("Done!\n"); + + printf("Saving neural network to let.nn\n"); + neural_link_save(nn, "let.nn"); + + neural_link_print_result(nn, (matrix_t) { + .rows = n, + .cols = 8, + .ptr = gomoku_model + }, 2); + neural_link_free(nn); + return EXIT_SUCCESS; +} diff --git a/Engine/AI/machine_learning.h b/Engine/AI/machine_learning.h new file mode 100644 index 0000000..1ef4ea5 --- /dev/null +++ b/Engine/AI/machine_learning.h @@ -0,0 +1,456 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** machine_learning +*/ + +#ifndef MACHINE_LEARNING_H_ + #define MACHINE_LEARNING_H_ + #include + #include + #include + #include + +#ifndef MH_MALLOC + #include + #define MH_CALLOC calloc +#endif /* !MH_MALLOC */ + +#define ERROR(str) fprintf(stderr, "[%s:%d]: %s\n", __FILE__, __LINE__, str) +#define RAISE(str) ERROR(str), exit(EXIT_FAILURE) +#define ARRAY_SIZE(arr) (sizeof arr / sizeof *arr) + + +typedef struct { + size_t rows; + size_t cols; + size_t stride; + float *ptr; +} matrix_t; + +typedef matrix_t mat_t; + +#define MAT_AT(_m_, _i_, _j_) _m_.ptr[_i_ * _m_.stride + _j_] +#define JOIN_IN_OUT(in, out) ((mat_t[2]){in, out}) + +extern matrix_t matrix_create(size_t rows, size_t cols); +static void matrix_dot(matrix_t dest, matrix_t a, matrix_t b); +static void matrix_sum(matrix_t dest, matrix_t a); +static void matrix_sigma(matrix_t dest); +extern void matrix_fill(matrix_t m, float value); +extern void matrix_randomize(matrix_t m, float min, float max); +extern matrix_t matrix_row(matrix_t m, size_t row); +extern void matrix_copy(matrix_t dest, matrix_t src); +extern void matrix_print(matrix_t m, const char name[], size_t indent); +#define MAT_PRINT(m, i) matrix_print(m, #m, i) +extern void matrix_free(matrix_t m); + +typedef struct { + size_t count; + matrix_t *ws; + matrix_t *bs; + matrix_t *as; +} neural_n_t; + +typedef neural_n_t nn_t; + +#define NEURAL_LINK_INPUT(nn) nn.as[0] +#define NEURAL_LINK_OUTPUT(nn) nn.as[nn.count] + +extern neural_n_t neural_link_create(size_t *arch, size_t arch_count); +extern void neural_link_randomize(neural_n_t nn, float min, float max); +extern void neural_link_reset(nn_t nn); +extern void neural_link_forward(neural_n_t nn); +extern float neural_link_cost(neural_n_t nn, mat_t in, mat_t out); +extern void neural_link_finite_diff(nn_t nn, nn_t g, float eps, mat_t inout[2]); +extern void neural_link_back_prop(nn_t nn, nn_t g, mat_t in, mat_t out); +extern void neural_link_learn(nn_t nn, nn_t g, float rate); +// neural_link_train(nn_t nn, mat_t in, mat_t out, size_t epochs, float rate, float momentum, float weight_decay, float eps); +extern void neural_link_train(nn_t nn, nn_t g, mat_t in, mat_t out, size_t epochs, float rate); +extern void neural_link_print_result(nn_t nn, matrix_t in, size_t nb_output); +extern matrix_t neural_link_return_result(nn_t nn, matrix_t in, size_t nb_output); +extern void neural_link_print(neural_n_t nn, const char name[]); +#define NEURAL_LINK_PRINT(nn) neural_link_print(nn, #nn) +extern void neural_link_save(neural_n_t nn, const char filename[]); +extern neural_n_t neural_link_create_fromfile(const char filename[]); +extern void neural_link_free(neural_n_t nn); + +static float random_float(void); +static float sigmoid(float x); + +#endif /* !MACHINE_LEARNING_H_ */ + +#ifdef MH_IMPLEMENTATION + +static float random_float(void) +{ + return (float) rand() / (float) RAND_MAX; +} + +static float sigmoid(float x) +{ + return 1.f / (1.f + expf(-x)); +} + +matrix_t matrix_create(size_t rows, size_t cols) +{ + matrix_t m = {rows, cols, cols, NULL}; + + if ((m.ptr = MH_CALLOC(rows * cols, sizeof *m.ptr)) == NULL) + RAISE("matrix_create: malloc failed"); + return m; +} + +static void matrix_dot(matrix_t dest, matrix_t a, matrix_t b) +{ + if (a.cols != b.rows || dest.rows != a.rows || dest.cols != b.cols) + RAISE("matrix_dot: matrixes must have the same size"); + + for (size_t i = 0; i < dest.rows; ++i) { + for (size_t j = 0; j < dest.cols; ++j) { + float sum = 0; + for (size_t k = 0; k < a.cols; ++k) + sum += MAT_AT(a, i, k) * MAT_AT(b, k, j); + MAT_AT(dest, i, j) = sum; + } } +} + +static void matrix_sum(matrix_t dest, matrix_t a) +{ + if (a.rows != dest.rows || a.cols != dest.cols) + RAISE("matrix_sum: matrixes must have the same size"); + + for (size_t i = 0; i < a.rows; ++i) + for (size_t j = 0; j < a.cols; ++j) + MAT_AT(dest, i, j) += MAT_AT(a, i, j); +} + +static void matrix_sigma(matrix_t dest) +{ + for (size_t i = 0; i < dest.rows; ++i) + for (size_t j = 0; j < dest.cols; ++j) + MAT_AT(dest, i, j) = sigmoid(MAT_AT(dest, i, j)); +} + +void matrix_fill(matrix_t m, float value) +{ + for (size_t i = 0; i < m.rows; ++i) + for (size_t j = 0; j < m.cols; ++j) + MAT_AT(m, i, j) = value; +} + +void matrix_randomize(matrix_t m, float min, float max) +{ + for (size_t i = 0; i < m.rows; ++i) + for (size_t j = 0; j < m.cols; ++j) + MAT_AT(m, i, j) = random_float() * (max - min) + min; +} + +matrix_t matrix_row(matrix_t m, size_t row) +{ + return (matrix_t) { 1, m.cols, m.stride, &MAT_AT(m, row, 0) }; +} + +void matrix_copy(matrix_t dest, matrix_t src) +{ + if (dest.rows != src.rows || dest.cols != src.cols) + RAISE("matrix_copy: matrixes must have the same size"); + + for (size_t i = 0; i < dest.rows; ++i) + for (size_t j = 0; j < dest.cols; ++j) + MAT_AT(dest, i, j) = MAT_AT(src, i, j); +} + +void matrix_print(matrix_t m, const char name[], size_t indent) +{ + printf("%*s%s = [\n", (int)indent, "", name); + for (size_t i = 0; i < m.rows; ++i) { + printf("%*s ", (int)indent, ""); + for (size_t j = 0; j < m.cols; ++j) + printf(" %f", MAT_AT(m, i, j)); + printf("\n"); + } + printf("%*s]\n", (int)indent, ""); +} + +void matrix_free(matrix_t m) +{ + if (m.ptr != NULL) + free(m.ptr); +} + +neural_n_t neural_link_create(size_t *arch, size_t arch_count) +{ + if (arch_count < 1) + RAISE("neural_link_create: arch_count must be >= 2"); + + neural_n_t nn; + nn.count = arch_count - 1; + if ((nn.ws = MH_CALLOC(nn.count, sizeof *nn.ws)) == NULL) + RAISE("neural_link_create: malloc failed"); + if ((nn.bs = MH_CALLOC(nn.count, sizeof *nn.bs)) == NULL) + RAISE("neural_link_create: malloc failed"); + if ((nn.as = MH_CALLOC(nn.count + 1, sizeof *nn.as)) == NULL) + RAISE("neural_link_create: malloc failed"); + + + nn.as[0] = matrix_create(1, arch[0]); + + for (size_t i = 1; i < arch_count; ++i) { + nn.ws[i - 1] = matrix_create(nn.as[i - 1].cols, arch[i]); + nn.bs[i - 1] = matrix_create(1, arch[i]); + nn.as[i] = matrix_create(1, arch[i]); + } + return nn; +} + +void neural_link_randomize(neural_n_t nn, float min, float max) +{ + for (size_t i = 0; i < nn.count; ++i) { + matrix_randomize(nn.ws[i], min, max); + matrix_randomize(nn.bs[i], min, max); + } +} + +void neural_link_forward(neural_n_t nn) +{ + for (size_t i = 0; i < nn.count; ++i) { + matrix_dot(nn.as[i + 1], nn.as[i], nn.ws[i]); + matrix_sum(nn.as[i + 1], nn.bs[i]); + matrix_sigma(nn.as[i + 1]); + } +} + +float neural_link_cost(neural_n_t nn, mat_t in, mat_t out) +{ + if (in.rows != out.rows || out.cols != NEURAL_LINK_OUTPUT(nn).cols) + RAISE("neural_link_cost: in and out must have the same size"); + + float sum = 0; + for (size_t i = 0; i < in.rows; ++i) { + mat_t x = matrix_row(in, i); + mat_t y = matrix_row(out, i); + + matrix_copy(NEURAL_LINK_INPUT(nn), x); + neural_link_forward(nn); + for (size_t j = 0; j < out.cols; ++j) { + float diff = MAT_AT(NEURAL_LINK_OUTPUT(nn), 0, j) - MAT_AT(y, 0, j); + sum += diff * diff; + } + } + return sum / in.rows; +} + +void neural_link_reset(nn_t nn) +{ + for (size_t i = 0; i < nn.count; ++i) { + matrix_fill(nn.ws[i], 0); + matrix_fill(nn.bs[i], 0); + matrix_fill(nn.as[i], 0); + } + matrix_fill(nn.as[nn.count], 0); +} + +void neural_link_back_prop(nn_t nn, nn_t g, mat_t in, mat_t out) +{ + if (in.rows != out.rows || NEURAL_LINK_OUTPUT(nn).cols != out.cols) + RAISE("neural_link_back_prop: in and out must have the same size"); + + size_t n = in.rows; + + neural_link_reset(g); + + for (size_t i = 0; i < in.rows; ++i) { + matrix_copy(NEURAL_LINK_INPUT(nn), matrix_row(in, i)); + neural_link_forward(nn); + for (size_t j = 0; j <= nn.count; j++) + matrix_fill(g.as[j], 0); + for (size_t j = 0; j < out.cols; ++j) + MAT_AT(NEURAL_LINK_OUTPUT(g), 0, j) = MAT_AT(NEURAL_LINK_OUTPUT(nn), 0, j) - MAT_AT(out, i, j); + for (size_t l = nn.count; l > 0; --l) { + for (size_t j = 0; j < nn.as[l].cols; ++j) { + float a = MAT_AT(nn.as[l], 0, j); + float da = MAT_AT(g.as[l], 0, j); + MAT_AT(g.bs[l-1], 0, j) += 2*da*a*(1 - a); + for (size_t k = 0; k < nn.as[l-1].cols; ++k) { + float pa = MAT_AT(nn.as[l-1], 0, k); + float w = MAT_AT(nn.ws[l-1], k, j); + MAT_AT(g.ws[l-1], k, j) += 2*da*a*(1-a)*pa; + MAT_AT(g.as[l-1], 0, k) += 2*da*a*(1-a)*w; + } + } } + } + for (size_t i = 0; i < g.count; ++i) { + for (size_t j = 0; j < g.ws[i].rows; ++j) + for (size_t k = 0; k < g.ws[i].cols; ++k) + MAT_AT(g.ws[i], j, k) /= n; + for (size_t j = 0; j < g.bs[i].rows; ++j) + for (size_t k = 0; k < g.bs[i].cols; ++k) + MAT_AT(g.bs[i], j, k) /= n; + } +} + +void neural_link_finite_diff(nn_t nn, nn_t g, float eps, mat_t inout[2]) +{ + float saved; + mat_t in = inout[0]; + mat_t out = inout[1]; + float c = neural_link_cost(nn, in, out); + + for (size_t i = 0; i < nn.count; ++i) { + for (size_t j = 0; j < nn.ws[i].rows; ++j) { + for (size_t k = 0; k < nn.ws[i].cols; ++k) { + saved = MAT_AT(nn.ws[i], j, k); + MAT_AT(nn.ws[i], j, k) += eps; + MAT_AT(g.ws[i], j, k) = (neural_link_cost(nn, in, out) - c)/eps; + MAT_AT(nn.ws[i], j, k) = saved; + } + } + for (size_t j = 0; j < nn.bs[i].rows; ++j) { + for (size_t k = 0; k < nn.bs[i].cols; ++k) { + saved = MAT_AT(nn.bs[i], j, k); + MAT_AT(nn.bs[i], j, k) += eps; + MAT_AT(g.bs[i], j, k) = (neural_link_cost(nn, in, out) - c)/eps; + MAT_AT(nn.bs[i], j, k) = saved; + } + } } +} + +void neural_link_learn(nn_t nn, nn_t g, float rate) +{ + for (size_t i = 0; i < nn.count; ++i) { + for (size_t j = 0; j < nn.ws[i].rows; ++j) { + for (size_t k = 0; k < nn.ws[i].cols; ++k) + MAT_AT(nn.ws[i], j, k) -= MAT_AT(g.ws[i], j, k) * rate; + } + for (size_t j = 0; j < nn.bs[i].rows; ++j) { + for (size_t k = 0; k < nn.bs[i].cols; ++k) { + MAT_AT(nn.bs[i], j, k) -= MAT_AT(g.bs[i], j, k) * rate; + } + } } +} + +void neural_link_train(nn_t nn, nn_t g, mat_t in, mat_t out, size_t epochs, float rate) +{ + for (size_t i = 0; i < epochs; ++i) { + neural_link_back_prop(nn, g, in, out); + neural_link_learn(nn, g, rate); + } +} + +void neural_link_print_result(nn_t nn, matrix_t in, size_t nb_output) +{ + for (size_t i = 0; i < in.rows; ++i) { + for (size_t j = 0; j < in.cols; ++j) { + MAT_AT(NEURAL_LINK_INPUT(nn), 0, j) = MAT_AT(in, i, j); + } + neural_link_forward(nn); + for (size_t j = 0; j < nb_output; ++j) { + printf("%f ", MAT_AT(NEURAL_LINK_OUTPUT(nn), 0, j)); + } + printf("\n"); + } +} + +matrix_t neural_link_return_result(nn_t nn, matrix_t in, size_t nb_output) +{ + matrix_t out = matrix_create(in.rows, nb_output); + for (size_t i = 0; i < in.rows; ++i) { + for (size_t j = 0; j < in.cols; ++j) { + MAT_AT(NEURAL_LINK_INPUT(nn), 0, j) = MAT_AT(in, i, j); + } + neural_link_forward(nn); + for (size_t j = 0; j < nb_output; ++j) { + MAT_AT(out, i, j) = MAT_AT(NEURAL_LINK_OUTPUT(nn), 0, j); + } + } + return out; +} + +void neural_link_print(neural_n_t nn, const char name[]) +{ + char buf[32]; + printf("%s = [\n", name); + for (size_t i = 0; i < nn.count; ++i) { + snprintf(buf, sizeof(buf), "w%zu", i); + matrix_print(nn.ws[i], buf, 4); + snprintf(buf, sizeof(buf), "b%zu", i); + matrix_print(nn.bs[i], buf, 4); + } + printf("]\n"); +} + +void neural_link_save(neural_n_t nn, const char filename[]) +{ + FILE *fp = fopen(filename, "w"); + if (fp == NULL) + RAISE("neural_link_save: fopen failed"); + + fprintf(fp, "%zu\n", nn.count); + for (size_t i = 0; i < nn.count; ++i) { + fprintf(fp, "%zu %zu\n", nn.ws[i].rows, nn.ws[i].cols); + for (size_t j = 0; j < nn.ws[i].rows; ++j) { + for (size_t k = 0; k < nn.ws[i].cols; ++k) + fprintf(fp, "%f ", MAT_AT(nn.ws[i], j, k)); + fprintf(fp, "\n"); + } + fprintf(fp, "%zu %zu\n", nn.bs[i].rows, nn.bs[i].cols); + for (size_t j = 0; j < nn.bs[i].rows; ++j) { + for (size_t k = 0; k < nn.bs[i].cols; ++k) + fprintf(fp, "%f ", MAT_AT(nn.bs[i], j, k)); + fprintf(fp, "\n"); + } + } + fclose(fp); +} + +neural_n_t neural_link_create_fromfile(const char filename[]) +{ + FILE *fp = fopen(filename, "r"); + if (fp == NULL) + RAISE("neural_link_create_fromfile: fopen failed"); + + size_t count; + fscanf(fp, "%zu", &count); + + neural_n_t nn; + nn.count = count; + if ((nn.ws = MH_CALLOC(nn.count, sizeof *nn.ws)) == NULL) + RAISE("neural_link_create_fromfile: malloc failed"); + if ((nn.bs = MH_CALLOC(nn.count, sizeof *nn.bs)) == NULL) + RAISE("neural_link_create_fromfile: malloc failed"); + if ((nn.as = MH_CALLOC(nn.count + 1, sizeof *nn.as)) == NULL) + RAISE("neural_link_create_fromfile: malloc failed"); + + for (size_t i = 0; i < nn.count; ++i) { + size_t rows, cols; + fscanf(fp, "%zu %zu", &rows, &cols); + nn.ws[i] = matrix_create(rows, cols); + for (size_t j = 0; j < rows; ++j) + for (size_t k = 0; k < cols; ++k) + fscanf(fp, "%f", &MAT_AT(nn.ws[i], j, k)); + fscanf(fp, "%zu %zu", &rows, &cols); + nn.bs[i] = matrix_create(rows, cols); + for (size_t j = 0; j < rows; ++j) + for (size_t k = 0; k < cols; ++k) + fscanf(fp, "%f", &MAT_AT(nn.bs[i], j, k)); + } + fclose(fp); + return nn; +} + +void neural_link_free(neural_n_t nn) +{ + for (size_t i = 0; i < nn.count; ++i) { + matrix_free(nn.ws[i]); + matrix_free(nn.bs[i]); + matrix_free(nn.as[i]); + } + matrix_free(nn.as[nn.count]); + free(nn.ws); + free(nn.bs); + free(nn.as); +} + +#endif /* !MH_IMPLEMENTATION */ diff --git a/Engine/AI/xor.nn b/Engine/AI/xor.nn new file mode 100644 index 0000000..6184d1c --- /dev/null +++ b/Engine/AI/xor.nn @@ -0,0 +1,11 @@ +2 +2 2 +3.413696 4.764245 +3.413400 4.764508 +1 2 +-2.986807 -4.366150 +2 1 +4.606448 +9.886581 +1 1 +-4.796438 diff --git a/Engine/AI/xor_model b/Engine/AI/xor_model new file mode 100755 index 0000000..0ec7635 Binary files /dev/null and b/Engine/AI/xor_model differ diff --git a/Engine/AI/xor_model.c b/Engine/AI/xor_model.c new file mode 100644 index 0000000..c7076c6 --- /dev/null +++ b/Engine/AI/xor_model.c @@ -0,0 +1,66 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** xor_model +*/ + +#define MH_IMPLEMENTATION +#include "machine_learning.h" + +float xor_model[] = { + 0, 0, 0, + 0, 2, 2, + 2, 0, 2, + 2, 2, 0, +}; + +int main(void) +{ + srand(time(NULL)); + + size_t stride = 3; + size_t n = ARRAY_SIZE(xor_model)/stride; + matrix_t in = { + .rows = n, + .cols = 2, + .stride = stride, + .ptr = xor_model + }; + + matrix_t out = { + .rows = n, + .cols = 1, + .stride = stride, + .ptr = &xor_model[2] + }; + + size_t arch[] = {2, 2, 1}; + neural_n_t nn = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_n_t gradient = neural_link_create(arch, ARRAY_SIZE(arch)); + neural_link_randomize(nn, 0, 1); + + size_t epochs = 20*1000; + float rate = 1-1e-2; + + printf("Training...\n"); + + printf("c = %f\n", neural_link_cost(nn, in, out)); + neural_link_train(nn, gradient, in, out, epochs, rate); + printf("c = %f\n", neural_link_cost(nn, in, out)); + + printf("Done!\n"); + + printf("Saving neural network to xor.nn\n"); + neural_link_save(nn, "xor.nn"); + + neural_link_print_result(nn, (matrix_t) { + .rows = 1, + .cols = 2, + .ptr = (float[]){0, 2} + }, 1); + neural_link_free(nn); + return EXIT_SUCCESS; +} + +// Build: gcc -Wall -Wextra -Werror xor_model.c -o xor_model -lm diff --git a/Engine/Camera/Webcam/Filters/gray_scale.c b/Engine/Camera/Webcam/Filters/gray_scale.c new file mode 100644 index 0000000..d3c15c4 --- /dev/null +++ b/Engine/Camera/Webcam/Filters/gray_scale.c @@ -0,0 +1,60 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-21 +** File description: +** gray_scale +*/ + +#include "webcam_filters.h" + +void filterGrayscale(imgRawImage_t *lpInput, imgRawImage_t **lpOutput) +{ + if (lpOutput == NULL) + (*lpOutput) = lpInput; + else { + (*lpOutput) = malloc(sizeof(imgRawImage_t)); + (*lpOutput)->width = lpInput->width; + (*lpOutput)->height = lpInput->height; + (*lpOutput)->numComponents = lpInput->numComponents; + (*lpOutput)->lpData = malloc(sizeof(unsigned char) * lpInput->width*lpInput->height*3); + } + + for (unsigned long int i = 0; i < lpInput->width * lpInput->height; i++) { + /* Do a grayscale transformation */ + unsigned char luma = (unsigned char)( + 0.299f * (float)lpInput->lpData[i * 3 + 0] + + 0.587f * (float)lpInput->lpData[i * 3 + 1] + + 0.114f * (float)lpInput->lpData[i * 3 + 2] + ); + (*lpOutput)->lpData[i * 3 + 0] = luma; + (*lpOutput)->lpData[i * 3 + 1] = luma; + (*lpOutput)->lpData[i * 3 + 2] = luma; + } +} + +void filterSepia(imgRawImage_t *lpInput, imgRawImage_t **lpOutput) +{ + if (lpOutput == NULL) + (*lpOutput) = lpInput; + else { + (*lpOutput) = malloc(sizeof(imgRawImage_t)); + (*lpOutput)->width = lpInput->width; + (*lpOutput)->height = lpInput->height; + (*lpOutput)->numComponents = lpInput->numComponents; + (*lpOutput)->lpData = malloc(sizeof(unsigned char) * lpInput->width*lpInput->height*3); + } + + for (unsigned long int i = 0; i < lpInput->width * lpInput->height; i++) { + /* Do a sepia transformation */ + unsigned char luma = (unsigned char)( + 0.299f * (float)lpInput->lpData[i * 3 + 0] + + 0.587f * (float)lpInput->lpData[i * 3 + 1] + + 0.114f * (float)lpInput->lpData[i * 3 + 2] + ); + (*lpOutput)->lpData[i * 3 + 0] = luma; + (*lpOutput)->lpData[i * 3 + 1] = luma * 0.9; + (*lpOutput)->lpData[i * 3 + 2] = luma * 0.8; + } +} diff --git a/Engine/Camera/Webcam/Filters/webcam_filters.h b/Engine/Camera/Webcam/Filters/webcam_filters.h new file mode 100644 index 0000000..babdc25 --- /dev/null +++ b/Engine/Camera/Webcam/Filters/webcam_filters.h @@ -0,0 +1,26 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** webcam_filters +*/ + +#ifndef WEBCAM_FILTERS_H_ + #define WEBCAM_FILTERS_H_ + +//////////////////////////////////////////////////////////// +// Include necessary headers for the webcam module +//////////////////////////////////////////////////////////// +#include "webcam.h" + +/** + * @brief Apply a grayscale filter to the image passed as parameter + * + * @param lpInput {imgRawImage_t *} - The image to apply the filter to + * @param lpOutput {imgRawImage_t **} - The image to store the result in + */ +extern void filterGrayscale(imgRawImage_t *lpInput, imgRawImage_t **lpOutput); + +extern void filterSepia(imgRawImage_t *lpInput, imgRawImage_t **lpOutput); + +#endif /* !WEBCAM_FILTERS_H_ */ diff --git a/Engine/Camera/Webcam/VisualOdometry/webcame_visual_odometry.h b/Engine/Camera/Webcam/VisualOdometry/webcame_visual_odometry.h new file mode 100644 index 0000000..d8688eb --- /dev/null +++ b/Engine/Camera/Webcam/VisualOdometry/webcame_visual_odometry.h @@ -0,0 +1,36 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** webcame_monocular_visual_odometry +*/ + +#ifndef WEBCAME_MONOCULAR_VISUAL_ODOMETRY_H_ + #define WEBCAME_MONOCULAR_VISUAL_ODOMETRY_H_ + +#include "engine_math.h" +#include "webcam.h" + +/** + * @brief The camera entity + * + * @param pos {vector3f} - The camera position + * @param rot {vector3f} - The camera rotation + */ +typedef struct { + vector3f pos; + vector3f rot; +} camera_entity_t; + +///////////////////////////////////////////// +// Monocular Visual Odometry +///////////////////////////////////////////// + +void extractFeatures(imgRawImage_t* image, vector2f *features) { + // Implement feature extraction here + UNUSED_PARAMETER(image); + UNUSED_PARAMETER(features); + PASS; +} + +#endif /* !WEBCAME_MONOCULAR_VISUAL_ODOMETRY_H_ */ diff --git a/Engine/Camera/Webcam/webcam.c b/Engine/Camera/Webcam/webcam.c new file mode 100644 index 0000000..f5817e0 --- /dev/null +++ b/Engine/Camera/Webcam/webcam.c @@ -0,0 +1,437 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** webcam +*/ + +#include "webcam.h" + +//////////////////////////////////////////////////////////// +// Utility functions +//////////////////////////////////////////////////////////// +/** + * @brief Wrapper around ioctl that repeats the calls in case + * they are interrupted by a signal (i.e. restarts) until + * they succeed or fail. +*/ +static inline int xioctl(int fh, int request, void *arg) +{ + int r; + do { + r = ioctl(fh, request, arg); + } while((r == -1) && (errno == EINTR)); + return r; +} + +//////////////////////////////////////////////////////////// +// Device functions +//////////////////////////////////////////////////////////// +static inline enum cameraError deviceOpen(int *lpDeviceOut, const char *deviceName) +{ + struct stat st; + int hHandle; + + if (lpDeviceOut == NULL) + return cameraE_InvalidParam; + (*lpDeviceOut) = -1; + + if (deviceName == NULL) + deviceName = (const char *)"/dev/video0"; + + if (stat(deviceName, &st) == -1) + return cameraE_UnknownDevice; + + if (!S_ISCHR(st.st_mode)) + return cameraE_UnknownDevice; + + if ((hHandle = open(deviceName, O_RDWR|O_NONBLOCK, 0)) < 0) { + switch(errno) { + case EACCES: return cameraE_PermissionDenied; + case EPERM: return cameraE_PermissionDenied; + default: return cameraE_Failed; + } + } + + (*lpDeviceOut) = hHandle; + return cameraE_Ok; +} + +static inline enum cameraError deviceClose(int hHandle) +{ + if (hHandle < 0) + return cameraE_InvalidParam; + + close(hHandle); + return cameraE_Ok; +} + +//////////////////////////////////////////////////////////// +// Capabilities functions +//////////////////////////////////////////////////////////// +static inline enum cameraError query_capabilities(int hHandle) +{ + struct v4l2_capability cap = {0}; + + if (xioctl(hHandle, VIDIOC_QUERYCAP, &cap) == -1) { + printf("[%s:%u]: Failed to query capabilities\n", __FILE__, __LINE__); + deviceClose(hHandle); + return cameraE_Failed; + } + + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { + printf("[%s:%u]: Device does not support video capture\n", __FILE__, __LINE__); + deviceClose(hHandle); + return cameraE_Failed; + } +} + +static void set_cropping(int hHandle) +{ + struct v4l2_cropcap cropcap = {0}; + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(hHandle, VIDIOC_CROPCAP, &cropcap) != -1) { + struct v4l2_crop crop = {0}; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; + + if (xioctl(hHandle, VIDIOC_S_CROP, &crop) == -1) + printf("[%s:%u]: Failed to set cropping rectangle\n", __FILE__, __LINE__); + return: + } + printf("[%s:%u]: Failed to query cropping capabilities, continuing anyways\n", __FILE__, __LINE__); +} + +static void negotiate_format(int hHandle, unsigned *width, unsigned *height) +{ + unsigned defaultWidth = 640; + unsigned defaultHeight = 480; + struct v4l2_format fmt = {0}; + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = defaultWidth; + fmt.fmt.pix.height = defaultHeight; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (xioctl(hHandle, VIDIOC_S_FMT, &fmt) == -1) + printf("[%s:%u]: Format negotiation (S_FMT) failed!\n", __FILE__, __LINE__); + + /* Now one should query the real size ... */ + (*width) = fmt.fmt.pix.width; + (*height) = fmt.fmt.pix.height; +} + +//////////////////////////////////////////////////////////// +// Webcam functions +//////////////////////////////////////////////////////////// +static inline enum cameraError setup_buffers(int hHandle, unsigned *bufferCount) +{ + struct v4l2_requestbuffers rqBuffers = {0}; + + rqBuffers.count = (*bufferCount); + rqBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rqBuffers.memory = V4L2_MEMORY_MMAP; + + if (xioctl(hHandle, VIDIOC_REQBUFS, &rqBuffers) == -1) { + printf("[%s:%u]: Requesting buffers failed!\n", __FILE__, __LINE__); + deviceClose(hHandle); + return cameraE_Failed; + } + + (*bufferCount) = rqBuffers.count; + return cameraE_Ok; +} + +static inline enum cameraError map_buffers(int hHandle, unsigned bufferCount, imageBuffer_t **lpBuffers) +{ + if (((*lpBuffers) = calloc(bufferCount, sizeof(imageBuffer_t))) == NULL) { + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(hHandle); + return cameraE_Failed; + } + + for (unsigned iBuf = 0; iBuf < bufferCount; iBuf++) { + struct v4l2_buffer vBuffer = {0}; + + vBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vBuffer.memory = V4L2_MEMORY_MMAP; + vBuffer.index = iBuf; + + if (xioctl(hHandle, VIDIOC_QUERYBUF, &vBuffer) == -1) { + printf("[%s:%u]: Failed to query buffer %d\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return cameraE_Failed; + } + + (*lpBuffers)[iBuf].lpBase = mmap(NULL, vBuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, hHandle, vBuffer.m.offset); + (*lpBuffers)[iBuf].sLen = vBuffer.length; + + if ((*lpBuffers)[iBuf].lpBase == MAP_FAILED) { + printf("[%s:%u]: Failed to map buffer %d\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return cameraE_Failed; + } + } + return cameraE_Ok; +} + +static inline enum cameraError queue_buffers(int hHandle, unsigned bufferCount) +{ + for (unsigned iBuf = 0; iBuf < bufferCount; iBuf++) { + struct v4l2_buffer buf = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = iBuf; + + if (xioctl(hHandle, VIDIOC_QBUF, &buf) == -1) { + printf("[%s:%u]: Queueing buffer %d failed ...\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return cameraE_Failed; + } + } + return cameraE_Ok; +} + +//////////////////////////////////////////////////////////// +// Webcam API +//////////////////////////////////////////////////////////// +webcam_t *webcam_create(const char *device, unsigned width, unsigned height) +{ + webcam_t *webcam = malloc(sizeof(webcam_t)); + unsigned bufferCount = 2; + + if (webcam == NULL) { + printf("[%s:%u]: Failed to allocate memory for webcam\n", __FILE__, __LINE__); + return (NULL); + } + + /* Try to open the camera */ + if (deviceOpen(&(webcam->hHandle), device) != cameraE_Ok) { + printf("[%s:%u]: Failed to open device: %s\n", __FILE__, __LINE__, device); + return (NULL); + } + + /* Query capabilities */ + if (query_capabilities(webcam->hHandle) != cameraE_Ok) { + printf("[%s:%u]: Failed to query capabilities\n", __FILE__, __LINE__); + return (NULL); + } + + /* Set cropping */ + set_cropping(webcam->hHandle); + + /* Negotiate format */ + negotiate_format(webcam->hHandle, &width, &height); + + /* Setup buffers */ + if (setup_buffers(webcam->hHandle, &bufferCount) != cameraE_Ok) { + printf("[%s:%u]: Failed to setup buffers\n", __FILE__, __LINE__); + return (NULL); + } + + /* Map buffers */ + if (map_buffers(webcam->hHandle, bufferCount, &(webcam->lpBuffers)) != cameraE_Ok) { + printf("[%s:%u]: Failed to map buffers\n", __FILE__, __LINE__); + return (NULL); + } + + /* Queue buffers */ + if (queue_buffers(webcam->hHandle, bufferCount) != cameraE_Ok) { + printf("[%s:%u]: Failed to queue buffers\n", __FILE__, __LINE__); + return (NULL); + } + + /* Store the webcam data */ + webcam->width = width; + webcam->height = height; + webcam->bufferCount = bufferCount; + return webcam; +} + +enum cameraError webcam_start(webcam_t *webcam) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(webcam->hHandle, VIDIOC_STREAMON, &type) == -1) { + printf("[%s:%u]: Stream on failed\n", __FILE__, __LINE__); + deviceClose(webcame->hHandle); + return cameraE_Failed; + } + return cameraE_Ok; +} + +enum cameraError webcam_capture(webcam_t *webcam) +{ + do { + struct v4l2_buffer buf = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (xioctl(webcam->hHandle, VIDIOC_DQBUF, &buf) == -1) { + if (errno == EAGAIN) { continue; } + + printf("[%s:%u]: DQBUF failed\n", __FILE__, __LINE__); + deviceClose(webcam->hHandle); + return cameraE_Failed; + } + + if (webcame->lpRawImg != NULL) { + free(webcam->lpRawImg->lpData); + free(webcam->lpRawImg); + webcam->lpRawImg = NULL; + } + + if ((webcam->lpRawImg = malloc(sizeof(struct imgRawImage))) == NULL) { + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(webcam->hHandle); + return cameraE_Failed; + } + + if ((webcam->lpRawImg->lpData = malloc(sizeof(unsigned char) * webcam->width * webcam->height * 3)) == NULL) { + free(webcam->lpRawImg); + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(webcam->hHandle); + return cameraE_Failed; + } + + webcam->lpRawImg->numComponents = 3; + webcam->lpRawImg->width = webcam->width; + webcam->lpRawImg->height = webcam->height; + + for (unsigned long int row = 0; row < webcam->height; row++) { + for (unsigned long int col = 0; col < webcam->width; col++) { + unsigned char y0, y1, y; + unsigned char u0, v0; + + signed int c,d,e; + unsigned char r,g,b; + signed int rtmp,gtmp, btmp; + + y0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *(webcam->width)) >> 1) * 4 + 0]; + u0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *(webcam->width)) >> 1) * 4 + 1]; + y1 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *(webcam->width)) >> 1) * 4 + 2]; + v0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *(webcam->width)) >> 1) * 4 + 3]; + + if ((col + row *(webcam->width)) % 2 == 0) { y = y0; } + else { y = y1; } + + c = ((signed int)y) - 16; + d = ((signed int)u0) - 128; + e = ((signed int)v0) - 128; + + rtmp = ((298 *c + 409 *e + 128) >> 8); + gtmp = ((298 *c - 100 *d - 208 *e + 128) >> 8); + btmp = ((298 *c + 516 *d + 128) >> 8); + + if (rtmp < 0) { r = 0; } + else if (rtmp > 255) { r = 255; } + else { r = (unsigned char)rtmp; } + + if (gtmp < 0) { g = 0; } + else if (gtmp > 255) { g = 255; } + else { g = (unsigned char)gtmp; } + + if (btmp < 0) { b = 0; } + else if (btmp > 255) { b = 255; } + else { b = (unsigned char)btmp; } + + webcam->lpRawImg->lpData[(col + row * webcam->width) * 3 + 0] = r; + webcam->lpRawImg->lpData[(col + row * webcam->width) * 3 + 1] = g; + webcam->lpRawImg->lpData[(col + row * webcam->width) * 3 + 2] = b; + } + } + + return cameraE_Ok; + } while (true); +} + +enum cameraError webcam_save(webcam_t *webcam, const char *filename, unsigned quality) +{ + struct jpeg_compress_struct info; + struct jpeg_error_mgr err; + + unsigned char *lpRowBuffer[1]; + + FILE *fHandle; + + if ((fHandle = fopen(filename, "wb")) == NULL) + return cameraE_Failed; + + info.err = jpeg_std_error(&err); + jpeg_create_compress(&info); + + jpeg_stdio_dest(&info, fHandle); + + info.image_width = webcame->lpRawImg->width; + info.image_height = webcame->lpRawImg->height; + info.input_components = 3; + info.in_color_space = JCS_RGB; + + jpeg_set_defaults(&info); + jpeg_set_quality(&info, 100, TRUE); + + jpeg_start_compress(&info, TRUE); + + /* Write every scanline ... */ + while(info.next_scanline < info.image_height) { + lpRowBuffer[0] = &(webcame->lpRawImg->lpData[info.next_scanline * (webcame->lpRawImg->width * 3)]); + jpeg_write_scanlines(&info, lpRowBuffer, 1); + } + + jpeg_finish_compress(&info); + fclose(fHandle); + + jpeg_destroy_compress(&info); + return cameraE_Ok; +} + +enum cameraError webcam_stop(webcam_t *webcam) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(webcam->hHandle, VIDIOC_STREAMOFF, &type) == -1) { + printf("[%s:%u]: Stream off failed\n", __FILE__, __LINE__); + deviceClose(webcam->hHandle); + return cameraE_Failed; + } + return cameraE_Ok; +} + +enum cameraError webcam_destroy(webcam_t *webcam) +{ + /* Release buffers ... */ + for (unsigned iBuf = 0; iBuf < webcam->bufferCount; iBuf++) + munmap(lpBuffers[iBuf].lpBase, lpBuffers[iBuf].sLen); + + struct v4l2_requestbuffers rqBuffers = {0}; + + rqBuffers.count = 0; + rqBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rqBuffers.memory = V4L2_MEMORY_MMAP; + + if (xioctl(webcam->hHandle, VIDIOC_REQBUFS, &rqBuffers) == -1) { + printf("[%s:%u]: Releasing buffers failed!\n", __FILE__, __LINE__); + deviceClose(webcam->hHandle); + return cameraE_Failed; + } + + /* Free buffers */ + free(webcam->lpBuffers); + + /* Free raw image */ + if (webcame->lpRawImg != NULL) { + free(webcam->lpRawImg->lpData); + free(webcam->lpRawImg); + webcam->lpRawImg = NULL; + } + + /* Close camera at the end */ + deviceClose(webcam->hHandle); + return cameraE_Ok; +} diff --git a/Engine/Camera/Webcam/webcam.h b/Engine/Camera/Webcam/webcam.h new file mode 100644 index 0000000..a8e6a43 --- /dev/null +++ b/Engine/Camera/Webcam/webcam.h @@ -0,0 +1,130 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-21 +** File description: +** webcam +*/ + +#ifndef WEBCAM_H_ + #define WEBCAM_H_ + +//////////////////////////////////////////////////////////// +// Include necessary headers for the vector module +//////////////////////////////////////////////////////////// +#ifdef __cplusplus + extern "C" { +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +typedef enum cameraError { + cameraE_Ok, + + cameraE_Failed, + + cameraE_InvalidParam, + cameraE_UnknownDevice, + cameraE_PermissionDenied, +} cameraError_t; + +typedef struct { + void * lpBase; + size_t sLen; +} imageBuffer_t; + +typedef struct { + unsigned int numComponents; + unsigned long int width, height; + unsigned char *lpData; +} imgRawImage_t; + +/** + * @brief The webcam frame buffer + * + * @param hHandle {int} - The webcam handle id + * @param width {int} - The webcam width + * @param height {int} - The webcam height + * @param bufferCount {int} - The webcam buffer count (default: 2) + * @param lpBuffers {imageBuffer_t *} - The webcam image buffer + * @param lpRawImg {imgRawImage_t *} - The webcam raw image buffer + * @return {webcam_t *} - The webcam module + */ +typedef struct { + int hHandle; + unsigned width; + unsigned height; + unsigned bufferCount; + imageBuffer_t *lpBuffers; + imgRawImage_t *lpRawImg; +} webcam_t; + +/** + * @brief The webcam image buffer + * + * @param device {const char *} - The webcam device path (default: /dev/video0) + * @param width {unsigned} - The webcam width (default: 640) + * @param height {unsigned} - The webcam height (default: 480) + * @return {webcam_t *} - The webcam module + */ +extern webcam_t *webcam_create(const char *device, unsigned width, unsigned height); + +/** + * @brief Start the webcam module + * + * @param webcam {webcam_t *} - The webcam module + * @return {enum cameraError} - The webcam error code + */ +extern enum cameraError webcam_start(webcam_t *webcam); + +/** + * @brief Capture the webcam image + * + * @param webcam {webcam_t *} - The webcam module + * @return {enum cameraError} - The webcam error code + */ +extern enum cameraError webcam_capture(webcam_t *webcam); + +/** + * @brief Save the webcam image + * + * @param webcam {webcam_t *} - The webcam module + * @param filename {const char *} - The webcam image filename + * @param quality {unsigned} - The webcam image quality (default: 100) + */ +extern enum cameraError webcam_save(webcam_t *webcam, const char *filename, unsigned quality); + +/** + * @brief Stop the webcam module + * + * @param webcam {webcam_t *} - The webcam module + */ +extern void webcam_stop(webcam_t *webcam); + +/** + * @brief Destroy the webcam module + * + * @param webcam {webcam_t *} - The webcam module + */ +extern void webcam_destroy(webcam_t *webcam); + +#ifdef __cplusplus + } +#endif + +#endif /* !WEBCAM_H_ */ diff --git a/Engine/Camera/camera.c b/Engine/Camera/camera.c new file mode 100644 index 0000000..182582b --- /dev/null +++ b/Engine/Camera/camera.c @@ -0,0 +1,133 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-20 +** File description: +** camera +*/ + +#include "camera.h" +#include + +/* +float fFovDegrees, float fAspectRatio, float fNear, float fFar +projection(90.0f, (float) WIN_Y / (float) WIN_X, 0.1f, 1000.0f); + +VrLeftEyeProjection(120.0f, float(win_y/2) / float(win_x), 0.1f, 1000.0f); +VrRightEyeProjection(120.0f, float(win_y/2) / float(win_x), 0.1f, 1000.0f); +projection(120.0f, float(win_y) / float(win_x), 0.1f, 1000.0f); +*/ + +camera_t *camera_create(vector4f pos, vector4f dir, vector2f screen_size) +{ + camera_t *camera = malloc(sizeof(camera_t)); + + if (!camera) + return (NULL); + camera->position = pos; + camera->direction = dir; + camera->velocity = VECTOR4F_DEFAULT; + camera->acceleration = VECTOR4F_DEFAULT; + camera->faw = VECTOR3F_DEFAULT; + camera->fov_degrees = 90.f; + camera->aspect_ratio = screen_size.width / screen_size.height; // TODO: width / height + camera->near = 0.1f; + camera->far = 1000.0f; + camera->ipd = 0.06f; + camera->distortion = 1.f; + camera->screen_size = screen_size; + camera->is_drunk = false; + camera->is_vr = false; + camera->radius = 2.f; + camera->speed = 5.f; + camera->sensitivity = 0.1f; + + camera->view = matrix4_f_identity(); + matrix4_f_set_projection ( + &camera->projection, camera->fov_degrees, + camera->aspect_ratio, camera->near, camera->far + ); + + camera->final_meshs = NULL; + camera->state = IDLE; + + return camera; +} + +void camera_set_position(camera_t *camera, vector4f pos) { + camera->position = pos; +} + +void camera_set_direction(camera_t *camera, vector4f dir) { + camera->direction = dir; +} + +void camera_set_fov(camera_t *camera, float fov) { + camera->fov_degrees = fov; +} + +void camera_set_drunk(camera_t *camera, bool is_drunk) { + camera->is_drunk = is_drunk; +} + +void camera_set_vr(camera_t *camera, bool is_vr) { + camera->is_vr = is_vr; + + if (is_vr) { + camera->aspect_ratio = (camera->screen_size.width / 2) / camera->screen_size.height; // TODO: width / height + matrix4_f_set_left_eye_projection ( + &camera->projection_left, + camera->fov_degrees, + camera->aspect_ratio, + camera->near, camera->far, + camera->ipd, camera->distortion + ); + matrix4_f_set_right_eye_projection ( + &camera->projection_right, + camera->fov_degrees, + camera->aspect_ratio, + camera->near, camera->far, + camera->ipd, camera->distortion + ); + return; + } + + camera->aspect_ratio = camera->screen_size.width / camera->screen_size.height; // TODO: width / height + matrix4_f_set_projection ( + &camera->projection, + camera->fov_degrees, + camera->aspect_ratio, + camera->near, camera->far + ); +} + +void camera_update(camera_t *camera, float deltatime) +{ + matrix4f rotate; + matrix4f rotateY; + matrix4f rotateX; + vector4f dir = {{0, 0, 1, 1}}; + vector4f up = {{0, 1, 0, 1}}; + + if (camera->is_drunk) { + matrix4_f_set_rotate_x(&rotateX, deltatime); + matrix4_f_set_rotate_y(&rotateY, deltatime); + rotate = matrix4_f_mul(rotateY, rotateX); + } else { + matrix4_f_set_rotate_x(&rotateX, camera->faw.x); + matrix4_f_set_rotate_y(&rotateY, camera->faw.y); + rotate = matrix4_f_mul(rotateX, rotateY); + } + + camera->direction = matrix4_f_mul_vector4_f(rotate, dir); + dir = vector4_f_add(camera->position, camera->direction); + matrix4_f_set_view(&camera->view, camera->position, dir, up); + matrix4_f_print(camera->view); + exit(0); +} + +void camera_destroy(camera_t *camera) +{ + free(camera); +} diff --git a/Engine/Camera/camera.h b/Engine/Camera/camera.h new file mode 100644 index 0000000..81fb6ff --- /dev/null +++ b/Engine/Camera/camera.h @@ -0,0 +1,93 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-19 +** File description: +** camera +*/ + +#ifndef CAMERA_H_ + #define CAMERA_H_ + +#include "engine_math.h" +#include "engine_renderer.h" +#include "laplace_link.h" + +typedef enum player_state_e { + IDLE, + JUMP, +} player_state; + +typedef struct { + vector4f position; // position of the camera + vector4f velocity; // velocity of the camera + vector4f acceleration; // acceleration of the camera + vector4f direction; // forward vector + vector3f faw; // forward and right vector + float radius; // radius of the camera + float speed; // speed of the camera + float sensitivity; // sensitivity of the camera + float fov_degrees; // field of view + float aspect_ratio; // width / height + float near; // clipping planes + float far; // clipping planes + float ipd; // interpupillary distance + float distortion; // lens distortion + matrix4f view; // view matrix + matrix4f projection; // projection matrix + matrix4f projection_left; // projection matrix for left eye in VR + matrix4f projection_right; // projection matrix for right eye in VR + vector2f screen_size; // screen size + bool is_drunk; + bool is_vr; + link_t *final_meshs; + player_state state; +} camera_t; + +/* +float fFovDegrees, float fAspectRatio, float fNear, float fFar +projection(90.0f, (float) WIN_Y / (float) WIN_X, 0.1f, 1000.0f); + +VrLeftEyeProjection(120.0f, float(win_y/2) / float(win_x), 0.1f, 1000.0f); +VrRightEyeProjection(120.0f, float(win_y/2) / float(win_x), 0.1f, 1000.0f); +projection(120.0f, float(win_y) / float(win_x), 0.1f, 1000.0f); +*/ + +/** + * @brief Create the camera module + * + * @param pos {vector4f} - The position of the camera in the world + * @param dir {vector4f} - The direction of the camera + * @param screen_size {vector2f} - The size of the screen + * @return {camera_t *} - The camera module + */ +extern camera_t *camera_create(vector4f pos, vector4f dir, vector2f screen_size); + +extern void camera_set_position(camera_t *camera, vector4f pos); + +extern void camera_set_direction(camera_t *camera, vector4f dir); + +extern void camera_set_fov(camera_t *camera, float fov); + +extern void camera_set_drunk(camera_t *camera, bool is_drunk); + +extern void camera_set_vr(camera_t *camera, bool is_vr); + +extern void camera_move(camera_t *camera, engine_renderer_t *renderer, float deltatime); + +/** + * @brief Update the camera module + * + * @param camera {camera_t *} - The camera module + */ +extern void camera_update(camera_t *camera, float deltaTime); + +/** + * @brief Destroy the camera module + * + * @param camera {camera_t *} - The camera module + */ +extern void camera_destroy(camera_t *camera); + +#endif /* !CAMERA_H_ */ diff --git a/Engine/Config/RunMode/Runtime/monitor_folder.h b/Engine/Config/RunMode/Runtime/monitor_folder.h new file mode 100644 index 0000000..5b57170 --- /dev/null +++ b/Engine/Config/RunMode/Runtime/monitor_folder.h @@ -0,0 +1,182 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-11-30 +** File description: +** monitor_folder +*/ + +#ifndef MONITOR_FOLDER_H_ + #define MONITOR_FOLDER_H_ + +#include +#include +#include + +#include + +#include + +#include +#include + +/** + * @brief Create a monitor folder object and return the file descriptor + * + * @param folderPath The path of the folder to monitor + * @return int The file descriptor of the monitor folder + */ +extern int monitor_folder_create(const char folderPath[]); + +/** + * @brief Check if the folder has been modified + * + * @param inotifyFd The file descriptor of the monitor folder + * @return int 1 if the folder has been modified, 0 if not, -1 if the folder has been deleted + */ +extern int monitorFolder_check_update(int inotifyFd); + +/** + * @brief Destroy the monitor folder object + * + * @param inotifyFd The file descriptor of the monitor folder + */ +extern void monitor_folder_destroy(int inotifyFd); + +#endif /* !MONITOR_FOLDER_H_ */ + +#ifdef MONITOR_FOLDER_IMPLEMENTATION + +struct ThreadData { + int inotifyFd; +}; + +void *monitorFolder(void *data) { + struct ThreadData *threadData = (struct ThreadData *)data; + int inotifyFd = threadData->inotifyFd; + + char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); + ssize_t bytesRead; + + while (1) { + bytesRead = read(inotifyFd, buffer, sizeof(buffer)); + if (bytesRead == -1) { + perror("read"); + exit(EXIT_FAILURE); + } + + struct inotify_event *event = (struct inotify_event *)buffer; + + if (event->mask & IN_MODIFY) { + printf("File modified: %s\n", event->name); + } else if (event->mask & IN_CREATE) { + printf("File created: %s\n", event->name); + } else if (event->mask & IN_DELETE) { + printf("File deleted: %s\n", event->name); + } + } + + return NULL; +} + +int main() { + const char *folderPath = "/path/to/your/folder"; + int inotifyFd = inotify_init(); + + if (inotifyFd == -1) { + perror("inotify_init"); + exit(EXIT_FAILURE); + } + + int watchDescriptor = inotify_add_watch(inotifyFd, folderPath, IN_MODIFY | IN_CREATE | IN_DELETE); + + if (watchDescriptor == -1) { + perror("inotify_add_watch"); + exit(EXIT_FAILURE); + } + + + // Main thread can do other work or sleep + while (1) { + sleep(1); + printf("Main thread doing other work...\n"); + } + + close(inotifyFd); + + return 0; +} + + +void monitor_folder_create(const char title[]) +{ + int inotifyFd = inotify_init(); + + if (inotifyFd == -1) { + perror(strerror(errno)); + return inotifyFd; + } + + // Get the config file + char folderPath[256] = {0}; + sprintf(folderPath, "./Projects/%s/src", title); + + if (inotify_add_watch(inotifyFd, folderPath, IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF) == -1) { + perror(strerror(errno)); + return (-1); + } + struct ThreadData threadData = {inotifyFd}; + pthread_t thread; + + if (pthread_create(&thread, NULL, monitorFolder, (void *)&threadData) != 0) { + perror("pthread_create"); + exit(EXIT_FAILURE); + } + return inotifyFd; +} + +void monitor_folder_check_update(int inotifyFd) +{ + + char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); + sigset_t set; + + sigemptyset(&set); + if (sigaddset(&set, SIGINT) == -1) { + perror(strerror(errno)); + pthread_exit((void *)1); + } + + loop: + if (inotifyFd == -1) { + perror("inotifyFd is not valid"); + return (-1); + } + + ssize_t bytesRead = read(inotifyFd, buffer, sizeof(buffer)); + if (bytesRead == -1) { + perror(strerror(errno)); + return (bytesRead); + } + + struct inotify_event* event = (struct inotify_event*)buffer; + + if (event->mask & (IN_MODIFY | IN_CREATE | IN_DELETE)) { + printf("The file %s has been modified\n", event->name); + } else if (event->mask & IN_DELETE_SELF) { + monitor_folder_destroy(inotifyFd); + return (-1); + } + goto loop; +} + +void monitor_folder_destroy(int inotifyFd) +{ + if (inotifyFd != -1) { + close(inotifyFd); + pthread_exit(NULL); + } +} + +#endif /* !MONITOR_FOLDER_IMPLEMENTATION */ diff --git a/Engine/Config/RunMode/Runtime/ok.c b/Engine/Config/RunMode/Runtime/ok.c new file mode 100644 index 0000000..863d37c --- /dev/null +++ b/Engine/Config/RunMode/Runtime/ok.c @@ -0,0 +1,77 @@ +#include +#include +#include + +#include + +#include + +#include +#include + +typedef struct { + int dll_fd; + int folder_fd; + pthread_t thread; +} monitor_folder_t; + +monitor_folder_t monitor_folder_create(const char folderPath[], int *dll_fd) +{ + monitor_folder_t monitor_folder = { + .dll_fd = dll_fd, + .folder_fd = 0, + .thread = 0 + }; + if ((monitor_folder.dll_fd = inotify_init()) == -1) { + perror(strerror(errno)); + return -1; + } + + if (inotify_add_watch(monitor_folder.inotifyFd, folderPath, IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF) == -1) { + perror(strerror(errno)); + return -1; + } + + if (pthread_create(&(monitor_folder.thread), NULL, monitor_folder_check_update, (void *)&monitor_folder) != 0) { + perror("pthread_create"); + exit(EXIT_FAILURE); + } + + return monitor_folder; +} + +void monitor_folder_check_update(void *monitor_folder) +{ + char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); + monitor_folder_t *monitor_folder = (monitor_folder_t *)monitor_folder; + sigset_t set; + + sigemptyset(&set); + if (sigaddset(&set, SIGUSR1) == -1) { + perror(strerror(errno)); + } + + loop: + if (read(monitor_folder->inotifyFd, buffer, sizeof(buffer)) == -1) { + perror(strerror(errno)); + } + + struct inotify_event* event = (struct inotify_event*)buffer; + + if (event->mask & (IN_MODIFY | IN_CREATE | IN_DELETE)) { + printf("The file %s has been modified\n", event->name); + } else if (event->mask & IN_DELETE_SELF) { + monitor_folder_destroy(inotifyFd); + return (-1); + } + + goto loop; +} + +void monitor_folder_destroy(int inotifyFd) +{ + if (inotifyFd != -1) { + close(inotifyFd); + pthread_exit(NULL); + } +} diff --git a/Engine/Config/config.h b/Engine/Config/config.h index 4ac3758..39d46eb 100644 --- a/Engine/Config/config.h +++ b/Engine/Config/config.h @@ -20,4 +20,46 @@ #include "OperatingSystem/distribution.h" #include "Version/version.h" +#ifdef DEBUG + #define API_MODE __attribute__((optimize(0))) +#else + #define API_MODE inline +#endif + +#define ENGINE_API __attribute__((visibility("default"))) API_MODE + +//////////////////////////////////////////////////////////// +// Define the Engine's API here +//////////////////////////////////////////////////////////// +#define NEED_COMMA , +#define UNUSED_PARAMETER(param) (void) param NEED_COMMA // The parameter is unused +#define UNUSED_VARIABLE(var) (void) var NEED_COMMA // The variable is unused +#define ATTRIBUTE(attr) __attribute__((attr)) // The function has an attribute +#define NEEDED __attribute__((used)) // The function is needed by the program +#define UNUSED __attribute__((unused)) // The function is not used by the program +#define ALWAYS_INLINE __attribute__((always_inline)) // The function is always inlined +#define NEVER_INLINE __attribute__((noinline)) // The function is never inlined +#define NORETURN __attribute__((noreturn)) // The function never returns +#define PURE __attribute__((pure)) // The function depends only on its arguments +#define CONST __attribute__((const)) // The function depends only on its arguments and global variables +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) // The function's result is not used +#define NON_NULL __attribute__((nonnull)) // The function's arguments are not null +#define FORMAT(str, first) __attribute__((format(printf, str, first))) // The function's arguments are printf-like +#define MALLOC __attribute__((malloc)) // The function returns a pointer to a newly allocated memory +#define HOT __attribute__((hot)) // The function is likely to be executed +#define COLD __attribute__((cold)) // The function is unlikely to be executed +#define ALIAS(name) __attribute__((alias(name))) // The function is an alias of another function +#define ALIGNED(size) __attribute__((aligned(size))) // The function's memory is aligned +#define TRANSPARENT_UNION __attribute__((transparent_union)) // The function's union is transparent +#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function)) // The function is not instrumented +#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) // The function is not sanitized +#define PASS (void) NEED_COMMA // The function does nothing +#define auto __auto_type // The variable's type is automatically deduced +#define restrict __restrict__ // The variable is restricted +#define thread_local _Thread_local // The variable is thread-local +#define likely(x) __builtin_expect(!!(x), 1) // The condition is likely to be true +#define unlikely(x) __builtin_expect(!!(x), 0) // The condition is unlikely to be true +#define unreachable() __builtin_unreachable() // The function is unreachable +#define unreachable_if(x) if (unlikely(x)) unreachable() // The function is unreachable if the condition is true + #endif /* !CONFIG_H_ */ diff --git a/Engine/Engine/Clock/clock.c b/Engine/Engine/Clock/clock.c index 633e523..439368c 100644 --- a/Engine/Engine/Clock/clock.c +++ b/Engine/Engine/Clock/clock.c @@ -69,22 +69,33 @@ void clock_restart(engine_clock_t *clock) float clock_get_f_delta_time(engine_clock_t *clock) { #if GRAPHICS_LIBRARY == CSFML - float delta_time = sfTime_asSeconds(sfClock_getElapsedTime(clock->clock)); - return sfClock_restart(clock->clock), delta_time; + return sfTime_asSeconds(sfClock_getElapsedTime(clock->clock)); #elif GRAPHICS_LIBRARY == SFML && defined(__cplusplus) - float delta_time = clock->clock->getElapsedTime().asSeconds(); - return clock->clock->restart().asSeconds(), delta_time; + return clock->clock->getElapsedTime().asSeconds(); #elif GRAPHICS_LIBRARY == SDL - float delta_time = SDL_GetElapsedTime(clock->clock); - return SDL_RestartClock(clock->clock), delta_time; + return SDL_GetElapsedTime(clock->clock); #elif GRAPHICS_LIBRARY == OPENGL - float delta_time = GL_GetElapsedTime(clock->clock); - return GL_RestartClock(clock->clock), delta_time; + return GL_GetElapsedTime(clock->clock); #elif GRAPHICS_LIBRARY == VULKAN - float delta_time = VK_GetElapsedTime(clock->clock); - return VK_RestartClock(clock->clock), delta_time; + return VK_GetElapsedTime(clock->clock); #elif GRAPHICS_LIBRARY == DIRECTX - float delta_time = DX_GetElapsedTime(clock->clock); - return DX_RestartClock(clock->clock), delta_time; + return DX_GetElapsedTime(clock->clock); + #endif +} + +float clock_get_fps(engine_clock_t *clock) +{ + #if GRAPHICS_LIBRARY == CSFML + return 1 / sfTime_asSeconds(sfClock_getElapsedTime(clock->clock)); + #elif GRAPHICS_LIBRARY == SFML && defined(__cplusplus) + return 1 / clock->clock->getElapsedTime().asSeconds(); + #elif GRAPHICS_LIBRARY == SDL + return 1 / SDL_GetElapsedTime(clock->clock); + #elif GRAPHICS_LIBRARY == OPENGL + return 1 / GL_GetElapsedTime(clock->clock); + #elif GRAPHICS_LIBRARY == VULKAN + return 1 / VK_GetElapsedTime(clock->clock); + #elif GRAPHICS_LIBRARY == DIRECTX + return 1 / DX_GetElapsedTime(clock->clock); #endif } diff --git a/Engine/Engine/Clock/engine_clock.h b/Engine/Engine/Clock/engine_clock.h index 5e4657d..357922c 100644 --- a/Engine/Engine/Clock/engine_clock.h +++ b/Engine/Engine/Clock/engine_clock.h @@ -63,14 +63,40 @@ extern engine_clock_t *clock_create(void); */ extern void clock_destroy(engine_clock_t *clock); +/** + * @brief Restart a clock module to 0 + * + * @param clock {engine_clock_t *} - The clock module + */ +extern void clock_restart(engine_clock_t *clock); + /** * @brief Get the delta time of a clock module * * @param clock {engine_clock_t *} - The clock module - * @return {float} - The delta time + * @return {float} - The delta time in seconds */ extern float clock_get_f_delta_time(engine_clock_t *clock); +extern float clock_get_fps(engine_clock_t *clock); + +// typedef struct { +// float speed = 0.f; +// float acceleration = 1.f; +// sfVector3f pos = (sfVector3f){0.f, 0.f, 0.f}; +// } player_t; + +// void clock_Update(clock_t *clock, player_t *player) +// { +// float delta_time = clock_get_delta_time(clock); + +// player->speed += player->acceleration * delta_time * 0.5f; +// player->pos.y += player->pos.y * player->speed * delta_time; +// player->speed += player->acceleration * delta_time * 0.5f; + +// sfClock_restart(clock->clock); +// } + #ifdef __cplusplus } #endif diff --git a/Engine/Engine/Event/Keyboard/event_keyboard.h b/Engine/Engine/Event/Keyboard/event_keyboard.h index fa94d65..67bbb90 100644 --- a/Engine/Engine/Event/Keyboard/event_keyboard.h +++ b/Engine/Engine/Event/Keyboard/event_keyboard.h @@ -15,56 +15,141 @@ //////////////////////////////////////////////////////////// #include "config.h" -enum key_state { - KEY_PRESSED, - KEY_RELEASED, - KEY_STATE_SIZE -}; +typedef enum key_state { + KEY_PRESSED = 0, +#define KEY_PRESSED (enum key_state)KEY_PRESSED + KEY_RELEASED = 1, +#define KEY_RELEASED (enum key_state)KEY_RELEASED + KEY_STATE_SIZE = 2 +} key_state_t; enum key_code { - KEY_UNKNOWN, - KEY_SPACE, + KEY_UNKNOWN = -1, + KEY_SPACE = 0, +#define KEY_SPACE (enum key_code)KEY_SPACE + // KEY_APOSTROPHE, + // KEY_COMMA, + // KEY_MINUS, + // KEY_PERIOD, + // KEY_SLASH, KEY_0, +#define KEY_0 (enum key_code)KEY_0 KEY_1, +#define KEY_1 (enum key_code)KEY_1 KEY_2, +#define KEY_2 (enum key_code)KEY_2 KEY_3, +#define KEY_3 (enum key_code)KEY_3 KEY_4, +#define KEY_4 (enum key_code)KEY_4 KEY_5, +#define KEY_5 (enum key_code)KEY_5 KEY_6, +#define KEY_6 (enum key_code)KEY_6 KEY_7, +#define KEY_7 (enum key_code)KEY_7 KEY_8, +#define KEY_8 (enum key_code)KEY_8 KEY_9, - KEY_ESCAPE, +#define KEY_9 (enum key_code)KEY_9 + // KEY_SEMICOLON, + // KEY_EQUAL, KEY_A, +#define KEY_A (enum key_code)KEY_A KEY_B, +#define KEY_B (enum key_code)KEY_B KEY_C, +#define KEY_C (enum key_code)KEY_C KEY_D, +#define KEY_D (enum key_code)KEY_D KEY_E, +#define KEY_E (enum key_code)KEY_E KEY_F, +#define KEY_F (enum key_code)KEY_F KEY_G, +#define KEY_G (enum key_code)KEY_G KEY_H, +#define KEY_H (enum key_code)KEY_H KEY_I, +#define KEY_I (enum key_code)KEY_I KEY_J, +#define KEY_J (enum key_code)KEY_J KEY_K, +#define KEY_K (enum key_code)KEY_K KEY_L, +#define KEY_L (enum key_code)KEY_L KEY_M, +#define KEY_M (enum key_code)KEY_M KEY_N, +#define KEY_N (enum key_code)KEY_N KEY_O, +#define KEY_O (enum key_code)KEY_O KEY_P, +#define KEY_P (enum key_code)KEY_P KEY_Q, +#define KEY_Q (enum key_code)KEY_Q KEY_R, +#define KEY_R (enum key_code)KEY_R KEY_S, +#define KEY_S (enum key_code)KEY_S KEY_T, +#define KEY_T (enum key_code)KEY_T KEY_U, +#define KEY_U (enum key_code)KEY_U KEY_V, +#define KEY_V (enum key_code)KEY_V KEY_W, +#define KEY_W (enum key_code)KEY_W KEY_X, +#define KEY_X (enum key_code)KEY_X KEY_Y, +#define KEY_Y (enum key_code)KEY_Y KEY_Z, +#define KEY_Z (enum key_code)KEY_Z + // KEY_LEFT_BRACKET, + // KEY_BACKSLASH, + // KEY_RIGHT_BRACKET, + // KEY_GRAVE_ACCENT, + // KEY_WORLD_1, + // KEY_WORLD_2, + KEY_ESCAPE, +#define KEY_ESCAPE (enum key_code)KEY_ESCAPE + // KEY_ENTER, + // KEY_TAB, + // KEY_BACKSPACE, + // KEY_INSERT, + // KEY_DELETE, KEY_RIGHT, +#define KEY_RIGHT (enum key_code)KEY_RIGHT KEY_LEFT, +#define KEY_LEFT (enum key_code)KEY_LEFT KEY_DOWN, +#define KEY_DOWN (enum key_code)KEY_DOWN KEY_UP, +#define KEY_UP (enum key_code)KEY_UP + // KEY_PAGE_UP, + // KEY_PAGE_DOWN, + // KEY_HOME, + // KEY_END, + // KEY_CAPS_LOCK, + // SCROLL_LOCK, + // KEY_NUM_LOCK, + // KEY_PRINT_SCREEN, + // KEY_PAUSE, + // KEY_F1, + // KEY_F2, + // KEY_F3, + // KEY_F4, + // KEY_F5, + // KEY_F6, + // KEY_F7, + // KEY_F8, + // KEY_F9, + // KEY_F10, + // KEY_F11, + // KEY_F12, + KEY_CTRL, +#define KEY_CTRL (enum key_code)KEY_CTRL KEY_CODE_SIZE }; diff --git a/Engine/Engine/Event/Keyboard/keyboard.c b/Engine/Engine/Event/Keyboard/keyboard.c index df6bff6..51c4267 100644 --- a/Engine/Engine/Event/Keyboard/keyboard.c +++ b/Engine/Engine/Event/Keyboard/keyboard.c @@ -26,8 +26,10 @@ static enum key_code keyboard_code_csfml_to_engine(KEYBOARD_EVENT graphics_event return (KEY_A + graphics_event.key.code - sfKeyA); if (graphics_event.key.code == sfKeyEscape) return (KEY_ESCAPE); - if (graphics_event.key.code >= sfKeyRight && graphics_event.key.code <= sfKeyUp) - return (KEY_RIGHT + graphics_event.key.code - sfKeyRight); + if (graphics_event.key.code >= sfKeyLeft && graphics_event.key.code <= sfKeyDown) + return (KEY_RIGHT + graphics_event.key.code - sfKeyLeft); + if (graphics_event.key.code == sfKeyLControl) + return (KEY_CTRL); return (KEY_UNKNOWN); } @@ -48,8 +50,10 @@ static enum key_code keyboard_code_sfml_to_engine(KEYBOARD_EVENT graphics_event) return (KEY_A + graphics_event.key.code - sf::Keyboard::A); if (graphics_event.key.code == sf::Keyboard::Escape) return (KEY_ESCAPE); - if (graphics_event.key.code >= sf::Keyboard::Right && graphics_event.key.code <= sf::Keyboard::Up) - return (KEY_RIGHT + graphics_event.key.code - sf::Keyboard::Right); + if (graphics_event.key.code >= sf::Keyboard::Left && graphics_event.key.code <= sf::Keyboard::Down) + return (KEY_RIGHT + graphics_event.key.code - sf::Keyboard::Left); + if (graphics_event.key.code == sf::Keyboard::LControl) + return (KEY_CTRL); return (KEY_UNKNOWN); } @@ -77,18 +81,71 @@ static enum key_code keyboard_code_sdl_to_engine(KEYBOARD_EVENT graphics_event) #endif +char *key_to_string(int key) { + switch (key) { + case KEY_SPACE: return "KEY_SPACE"; + case KEY_0: return "KEY_0"; + case KEY_1: return "KEY_1"; + case KEY_2: return "KEY_2"; + case KEY_3: return "KEY_3"; + case KEY_4: return "KEY_4"; + case KEY_5: return "KEY_5"; + case KEY_6: return "KEY_6"; + case KEY_7: return "KEY_7"; + case KEY_8: return "KEY_8"; + case KEY_9: return "KEY_9"; + case KEY_A: return "KEY_A"; + case KEY_B: return "KEY_B"; + case KEY_C: return "KEY_C"; + case KEY_D: return "KEY_D"; + case KEY_E: return "KEY_E"; + case KEY_F: return "KEY_F"; + case KEY_G: return "KEY_G"; + case KEY_H: return "KEY_H"; + case KEY_I: return "KEY_I"; + case KEY_J: return "KEY_J"; + case KEY_K: return "KEY_K"; + case KEY_L: return "KEY_L"; + case KEY_M: return "KEY_M"; + case KEY_N: return "KEY_N"; + case KEY_O: return "KEY_O"; + case KEY_P: return "KEY_P"; + case KEY_Q: return "KEY_Q"; + case KEY_R: return "KEY_R"; + case KEY_S: return "KEY_S"; + case KEY_T: return "KEY_T"; + case KEY_U: return "KEY_U"; + case KEY_V: return "KEY_V"; + case KEY_W: return "KEY_W"; + case KEY_X: return "KEY_X"; + case KEY_Y: return "KEY_Y"; + case KEY_Z: return "KEY_Z"; + case KEY_ESCAPE: return "KEY_ESCAPE"; + case KEY_RIGHT: return "KEY_RIGHT"; + case KEY_LEFT: return "KEY_LEFT"; + case KEY_DOWN: return "KEY_DOWN"; + case KEY_UP: return "KEY_UP"; + default: return "KEY_UNKNOWN"; + } +} + void keyboard_graphics_to_engine(engine_event_t *event) { if (event->graphics_event.KEYBOARD_GET_TYPE == KEYBOARD_TYPE_PRESSED) { - unsigned i = GRAPHICS_CODE_TO_ENGINE_CODE(event->graphics_event) * KEY_STATE_SIZE + KEY_PRESSED; - if (i - KEY_PRESSED == KEY_UNKNOWN) + int i = GRAPHICS_CODE_TO_ENGINE_CODE(event->graphics_event); + if (i == KEY_UNKNOWN) return; - event->event_callback[i].event_callback(); + i = i * KEY_STATE_SIZE + KEY_PRESSED; + if (event->event_callback[i].event_callback != NULL) + event->event_callback[i].event_callback(); + return; } if (event->graphics_event.KEYBOARD_GET_TYPE == KEYBOARD_TYPE_RELEASED) { - unsigned i = GRAPHICS_CODE_TO_ENGINE_CODE(event->graphics_event) * KEY_STATE_SIZE + KEY_RELEASED; - if (i - KEY_RELEASED == KEY_UNKNOWN) + int i = GRAPHICS_CODE_TO_ENGINE_CODE(event->graphics_event); + if (i == KEY_UNKNOWN) return; - event->event_callback[i].event_callback(); + i = i * KEY_STATE_SIZE + KEY_RELEASED; + if (event->event_callback[i].event_callback != NULL) + event->event_callback[i].event_callback(); } } diff --git a/Engine/Engine/Event/Mouse/event_mouse.h b/Engine/Engine/Event/Mouse/event_mouse.h new file mode 100644 index 0000000..2564840 --- /dev/null +++ b/Engine/Engine/Event/Mouse/event_mouse.h @@ -0,0 +1,49 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-11-10 +** File description: +** event_mouse +*/ + +#ifndef EVENT_MOUSE_H_ + #define EVENT_MOUSE_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "config.h" +#include "engine_math.h" + +#define MOUSE_SIZE 2 + +typedef enum +{ + sfMouseLeft, ///< The left mouse button + sfMouseRight, ///< The right mouse button + sfMouseMiddle, ///< The middle (wheel) mouse button + sfMouseXButton1, ///< The first extra mouse button + sfMouseXButton2, ///< The second extra mouse button + + sfMouseButtonCount ///< Keep last -- the total number of mouse buttons +} sfMouseButton; + +typedef enum +{ + sfMouseVerticalWheel, ///< The vertical mouse wheel + sfMouseHorizontalWheel ///< The horizontal mouse wheel +} sfMouseWheel; + +typedef struct { + enum mouse_code mouse_code; + enum mouse_state mouse_state; +} event_mouse_t; + +sfBool sfMouse_isButtonPressed(sfMouseButton button); + +sfVector2i sfMouse_getPosition(const sfWindow* relativeTo); + +void sfMouse_setPosition(sfVector2i position, const sfWindow* relativeTo); + +#endif /* !EVENT_MOUSE_H_ */ diff --git a/Engine/Engine/Event/engine_event.h b/Engine/Engine/Event/engine_event.h index e98dd57..882c0b7 100644 --- a/Engine/Engine/Event/engine_event.h +++ b/Engine/Engine/Event/engine_event.h @@ -15,6 +15,8 @@ #include "config.h" #include "engine_renderer.h" #include "event_keyboard.h" +// #include "event_mouse.h" +// #include "event_joystick.h" //////////////////////////////////////////////////////////// // Include the necessary headers for the event module @@ -39,6 +41,9 @@ typedef struct { #define EVENT_CALLBACKS_COUNT KEYBOARD_SIZE // + MOUSE_SIZE // + JOYSTICK_SIZE +// TODO: Add mouse and joystick events +// TODO: Add static asserts to check if the size of the event_callback_t union is equal to the sum of the sizes of the event_callback_t structs + typedef struct engine_event_s { event_callback_t event_callback[EVENT_CALLBACKS_COUNT]; #if GRAPHICS_LIBRARY == CSFML diff --git a/Engine/Engine/Event/event.c b/Engine/Engine/Event/event.c index cd8870a..c1f437b 100644 --- a/Engine/Engine/Event/event.c +++ b/Engine/Engine/Event/event.c @@ -11,19 +11,15 @@ engine_event_t *event_create(void) { - engine_event_t *event = calloc(1, sizeof(engine_event_t)); - - if (event == NULL) - return (NULL); - return (event); + return calloc(1, sizeof(engine_event_t)); } void event_add_keyboard_callback(engine_event_t *event, event_keyboard_t keyboard, void (*event_callback)(void)) { if (keyboard.key_code <= KEY_UNKNOWN || keyboard.key_code >= KEY_CODE_SIZE) return; - unsigned i = keyboard.key_code - 1 * KEY_STATE_SIZE + keyboard.key_state; - event->event_callback[i].event.keyboard = keyboard; + unsigned i = keyboard.key_code * KEY_STATE_SIZE + keyboard.key_state; + memcpy(&event->event_callback[i].event.keyboard, &keyboard, sizeof(event_keyboard_t)); event->event_callback[i].event_callback = event_callback; } @@ -31,7 +27,7 @@ void event_remove_keyboard_callback(engine_event_t *event, event_keyboard_t keyb { if (keyboard.key_code <= KEY_UNKNOWN || keyboard.key_code >= KEY_CODE_SIZE) return; - unsigned i = keyboard.key_code - 1 * KEY_STATE_SIZE + keyboard.key_state; + unsigned i = keyboard.key_code * KEY_STATE_SIZE * keyboard.key_state; event->event_callback[i].event.keyboard.key_code = 0; event->event_callback[i].event_callback = NULL; } @@ -61,6 +57,8 @@ void event_update(engine_event_t *event, engine_renderer_t *renderer) return; } keyboard_graphics_to_engine(event); + // mouse_graphics_to_engine(event); + // joystick_graphics_to_engine(event); } } diff --git a/Engine/Engine/Math/Geometry/math_geometry.h b/Engine/Engine/Math/Geometry/math_geometry.h index c8ee08c..9574260 100644 --- a/Engine/Engine/Math/Geometry/math_geometry.h +++ b/Engine/Engine/Math/Geometry/math_geometry.h @@ -25,6 +25,9 @@ #ifdef __cplusplus #include #include + + using namespace std; + extern "C" { #else #include #include @@ -35,12 +38,11 @@ * * @param vertices Triangle vertices (x, y, z, w) * @param textures Texture coordinates of the triangle (x, y, z) - * @param dp Distance from camera + * @param dp Dot product of the triangle */ typedef struct triangle_s { vector4f vertices[3]; vector3f textures[3]; - // texture usemtl; float dp; } triangle_t; @@ -53,6 +55,8 @@ typedef struct triangle_s { */ extern triangle_t *geometry_triangle_create(vector4f vertices[3], vector3f textures[3]/*, texture usemtl*/); +extern void geometry_triangle_print(triangle_t triangle); + /** * @brief Destroy a triangle * @@ -60,4 +64,41 @@ extern triangle_t *geometry_triangle_create(vector4f vertices[3], vector3f textu */ extern void geometry_triangle_destroy(triangle_t *triangle); + +extern bool geometry_triangle_contains_point(triangle_t *triangle, vector3f point); + +extern bool geometry_triangle_contains_triangle(triangle_t *triangle, triangle_t *other); + +extern bool geometry_triangle_overlaps(triangle_t *triangle, triangle_t *other); + +extern bool geometry_triangle_compare(void *tri1, void *tri2); + +// extern vector3f geometry_triangle_average(triangle_t *triangle); + +// extern bool geometry_triangle_cmp_triangles(void *triangle1, void *triangle2); + +// extern bool geometry_triangle_vector_inside(vector3f vector, triangle_t *triangle); + +// extern int geometry_triangle_clip_against_plane(vector3f plane_p, vector3f plane_n, triangle_t *in_tri, triangle_t (*out_tri)[2]); + + +typedef struct rectangle_s { + vector3f pos; + vector3f size; +} rectangle_t; + +extern rectangle_t *geometry_rectangle_create(vector3f position, vector3f size); + +extern void geometry_rectangle_destroy(rectangle_t *rectangle); + +extern bool geometry_rectangle_contains_point(rectangle_t *rectangle, vector3f point); + +extern bool geometry_rectangle_contains_rectangle(rectangle_t *rectangle, rectangle_t *other); + +extern bool geometry_rectangle_overlaps(rectangle_t *rectangle, rectangle_t *other); + +#ifdef __cplusplus + } +#endif + #endif /* !MATH_GEOMETRY_H_ */ diff --git a/Engine/Engine/Math/Geometry/rectangle.c b/Engine/Engine/Math/Geometry/rectangle.c new file mode 100644 index 0000000..88cacba --- /dev/null +++ b/Engine/Engine/Math/Geometry/rectangle.c @@ -0,0 +1,71 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-12 +** File description: +** rectangle +*/ + +#include "math_geometry.h" + +rectangle_t *geometry_rectangle_create(vector3f position, vector3f size) +{ + rectangle_t *rectangle = malloc(sizeof(rectangle_t)); + + if (rectangle == NULL) + return (NULL); + + rectangle->pos = position; + rectangle->size = size; + return rectangle; +} +void geometry_rectangle_destroy(rectangle_t *rectangle) +{ + free(rectangle); +} + +bool geometry_rectangle_contains_point(rectangle_t *r, vector3f p) { + return !( + p.x < r->pos.x + || p.y < r->pos.y + || p.z < r->pos.z + || p.x > r->pos.x + r->size.x + || p.y > r->pos.y + r->size.y + || p.z > r->pos.z + r->size.z + ); +} + +bool geometry_rectangle_contains_rectangle(rectangle_t *r, rectangle_t *o) +{ + return ( + o->pos.x >= r->pos.x + && o->pos.y >= r->pos.y + && o->pos.z >= r->pos.z + && o->pos.x + o->size.x <= r->pos.x + r->size.x + && o->pos.y + o->size.y <= r->pos.y + r->size.y + && o->pos.z + o->size.z <= r->pos.z + r->size.z + ); +} + +bool geometry_rectangle_overlaps(rectangle_t *r, rectangle_t *o) +{ + return ( + r->pos.x < o->pos.x + o->size.x + && r->pos.x + r->size.x > o->pos.x + && r->pos.y < o->pos.y + o->size.y + && r->pos.y + r->size.y > o->pos.y + && r->pos.z < o->pos.z + o->size.z + && r->pos.z + r->size.z > o->pos.z + ); +} + +// vector3f geometry_rectangle_average(rectangle_t *rectangle); + +// bool geometry_rectangle_cmp_rectangles(void *rectangle1, void *rectangle2); + +// bool geometry_rectangle_vector_inside(vector3f vector, rectangle_t *rectangle); + +// int geometry_rectangle_clip_against_plane(vector3f plane_p, vector3f plane_n, rectangle_t *in_tri, rectangle_t (*out_tri)[2]); + +// void geometry_rectangle_print(rectangle_t *rectangle); diff --git a/Engine/Engine/Math/Geometry/triangle.c b/Engine/Engine/Math/Geometry/triangle.c index 2227f9e..bd5d588 100644 --- a/Engine/Engine/Math/Geometry/triangle.c +++ b/Engine/Engine/Math/Geometry/triangle.c @@ -13,15 +13,84 @@ triangle_t *geometry_triangle_create(vector4f vertices[3], vector3f textures[3]/ { triangle_t *triangle = malloc(sizeof(triangle_t)); - triangle->vertices[0] = vertices[0]; - triangle->vertices[1] = vertices[1]; - triangle->vertices[2] = vertices[2]; - triangle->textures[0] = textures[0]; - triangle->textures[1] = textures[1]; - triangle->textures[2] = textures[2]; + if (triangle == NULL) + return (NULL); + + memcpy(triangle->vertices, vertices, 3 * sizeof vertices[0]); + memcpy(triangle->textures, textures, 3 * sizeof textures[0]); + // triangle->usemtl = usemtl; return triangle; } + +void geometry_triangle_print(triangle_t triangle) +{ + printf("[triangle_t]:\n"); + for (unsigned i = 0; i < 3; i++) { + printf("Sommet %d: ", i); + vector4_f_print(triangle.vertices[i]); + } +} + void geometry_triangle_destroy(triangle_t *triangle) { free(triangle); } + +// vector3f geometry_triangle_average(triangle_t *triangle); + +// bool geometry_triangle_cmp_triangles(void *triangle1, void *triangle2); + +// bool geometry_triangle_vector_inside(vector3f vector, triangle_t *triangle); + +// int geometry_triangle_clip_against_plane(vector3f plane_p, vector3f plane_n, triangle_t *in_tri, triangle_t (*out_tri)[2]); + +bool geometry_triangle_contains_point(triangle_t *triangle, vector3f point) +{ + vector3f v0 = vector4f_to_vector3f(triangle->vertices[0]); + vector3f v1 = vector4f_to_vector3f(triangle->vertices[1]); + vector3f v2 = vector4f_to_vector3f(triangle->vertices[2]); + + vector3f u = vector3_f_sub(v1, v0); + vector3f v = vector3_f_sub(v2, v0); + vector3f w = vector3_f_sub(point, v0); + + vector3f vCrossW = vector3_f_cross_product(v, w); + vector3f vCrossU = vector3_f_cross_product(v, u); + + if (vector3_f_dot_product(vCrossW, vCrossU) < 0) + return (false); + + vector3f uCrossW = vector3_f_cross_product(u, w); + vector3f uCrossV = vector3_f_cross_product(u, v); + + if (vector3_f_dot_product(uCrossW, uCrossV) < 0) + return (false); + + float denom = vector3_f_length(uCrossV); + float r = vector3_f_length(vCrossW) / denom; + float t = vector3_f_length(uCrossW) / denom; + + return (r <= 1 && t <= 1 && r + t <= 1); +} + +bool geometry_triangle_contains_triangle(triangle_t *triangle, triangle_t *other) +{ + return (geometry_triangle_contains_point(triangle, vector4f_to_vector3f(other->vertices[0])) && + geometry_triangle_contains_point(triangle, vector4f_to_vector3f(other->vertices[1])) && + geometry_triangle_contains_point(triangle, vector4f_to_vector3f(other->vertices[2]))); +} + +bool geometry_triangle_overlaps(triangle_t *triangle, triangle_t *other) +{ + return (geometry_triangle_contains_triangle(triangle, other) || geometry_triangle_contains_triangle(other, triangle)); +} + +bool geometry_triangle_compare(void *triangle1, void *triangle2) +{ + triangle_t *t1 = (triangle_t *)triangle1; + triangle_t *t2 = (triangle_t *)triangle2; + + float z1 = (t1->vertices[0].z + t1->vertices[1].z + t1->vertices[2].z) / 3.0f; + float z2 = (t2->vertices[0].z + t2->vertices[1].z + t2->vertices[2].z) / 3.0f; + return z1 > z2; +} diff --git a/Engine/Engine/Math/Matrix/math_matrix.h b/Engine/Engine/Math/Matrix/math_matrix.h index 905614c..5e7b1c6 100644 --- a/Engine/Engine/Math/Matrix/math_matrix.h +++ b/Engine/Engine/Math/Matrix/math_matrix.h @@ -20,17 +20,19 @@ //////////////////////////////////////////////////////////// #ifdef __cplusplus #include + #include using namespace std; extern "C" { #else #include + #include #endif //////////////////////////////////////////////////////////// // Define the default matrix4 of floats //////////////////////////////////////////////////////////// -#define MATRIX4F_DEFAULT (matrix4f){{{0}}} +#define MATRIX4F_DEFAULT (matrix4f){{{0}}}// NEED_COMMA /** * @brief A 4x4 matrix of floats @@ -38,9 +40,11 @@ * @param m {float[4][4]} - The matrix */ typedef struct { - float m[4][4]; + float m[4][4]; // TODO: Change to float[16] } matrix4f; +extern matrix4f matrix4_f_identity(); + /** * @brief Multiply two matrix4 of floats * @@ -83,6 +87,28 @@ extern matrix4f matrix4_f_quick_inverse(matrix4f m); */ extern void matrix4_f_print(matrix4f m); +//////////////////////////////////////////////////////////// +// Matrix Library +//////////////////////////////////////////////////////////// + +void matrix4_f_set_rotate_x(matrix4f *matrix, float angle); + +void matrix4_f_set_rotate_y(matrix4f *matrix, float angle); + +void matrix4_f_set_rotate_z(matrix4f *matrix, float angle); + +void matrix4_f_set_translate(matrix4f *matrix, float x, float y, float z); + +void matrix4_f_set_scale(matrix4f *matrix, float x, float y, float z); + +void matrix4_f_set_left_eye_projection(matrix4f *matrix, float fov_degrees, float aspect_ratio, float near, float far, float ipd, float distortion); + +void matrix4_f_set_right_eye_projection(matrix4f *matrix, float fov_degrees, float aspect_ratio, float near, float far, float ipd, float distortion); + +void matrix4_f_set_projection(matrix4f *matrix, float fov_degrees, float aspect_ratio, float near, float far); + +void matrix4_f_set_view(matrix4f *matrix, vector4f pos, vector4f dir, vector4f up); + #ifdef __cplusplus } #endif diff --git a/Engine/Engine/Math/Matrix/matrix.c b/Engine/Engine/Math/Matrix/matrix.c index f0fa962..f410ff3 100644 --- a/Engine/Engine/Math/Matrix/matrix.c +++ b/Engine/Engine/Math/Matrix/matrix.c @@ -8,7 +8,18 @@ */ #include "math_matrix.h" -#include + +matrix4f matrix4_f_identity() +{ + matrix4f m = MATRIX4F_DEFAULT; + + m.m[0][0] = 1.0f; + m.m[1][1] = 1.0f; + m.m[2][2] = 1.0f; + m.m[3][3] = 1.0f; + + return m; +} matrix4f matrix4_f_mul(matrix4f m, matrix4f n) { @@ -24,32 +35,39 @@ matrix4f matrix4_f_mul(matrix4f m, matrix4f n) vector4f matrix4_f_mul_vector4_f(matrix4f m, vector4f v) { - vector4f o = VECTOR4F_DEFAULT; - - o.x = v.x * m.m[0][0] + v.y * m.m[1][0] + v.z * m.m[2][0] + v.w * m.m[3][0]; - o.y = v.x * m.m[0][1] + v.y * m.m[1][1] + v.z * m.m[2][1] + v.w * m.m[3][1]; - o.z = v.x * m.m[0][2] + v.y * m.m[1][2] + v.z * m.m[2][2] + v.w * m.m[3][2]; - o.w = v.x * m.m[0][3] + v.y * m.m[1][3] + v.z * m.m[2][3] + v.w * m.m[3][3]; + vector4f o; + float *parts[4] = { &o.x, &o.y, &o.z, &o.w }; + for (int i = 0; i < 4; i++) + *(parts[i]) = ( + v.x * m.m[0][i] + + v.y * m.m[1][i] + + v.z * m.m[2][i] + + v.w * m.m[3][i] + ); return o; } vector3f matrix4_f_mul_vector3_f(matrix4f m, vector3f v) { - vector3f o = VECTOR3F_DEFAULT; - - o.x = v.x * m.m[0][0] + v.y * m.m[1][0] + v.z * m.m[2][0]; - o.y = v.x * m.m[0][1] + v.y * m.m[1][1] + v.z * m.m[2][1]; - o.z = v.x * m.m[0][2] + v.y * m.m[1][2] + v.z * m.m[2][2]; + vector3f o; + float *parts[3] = { &o.x, &o.y, &o.z }; + for (int i = 0; i < 3; i++) + *(parts[i]) = ( + v.x * m.m[0][i] + + v.y * m.m[1][i] + + v.z * m.m[2][i] + + m.m[3][i] + ); return o; } matrix4f matrix4_f_quick_inverse(matrix4f m) { - matrix4f o = MATRIX4F_DEFAULT; + matrix4f o = matrix4_f_identity(); - memcpy(o.m, m.m, sizeof(float) * 16); + memcpy(o.m, m.m, sizeof m.m); o.m[3][0] = -(m.m[3][0] * o.m[0][0] + m.m[3][1] * o.m[1][0] + m.m[3][2] * o.m[2][0]); o.m[3][1] = -(m.m[3][0] * o.m[0][1] + m.m[3][1] * o.m[1][1] + m.m[3][2] * o.m[2][1]); @@ -68,3 +86,177 @@ void matrix4_f_print(matrix4f m) printf("\t%f %f %f %f\n", m.m[2][0], m.m[2][1], m.m[2][2], m.m[2][3]); printf("\t%f %f %f %f\n", m.m[3][0], m.m[3][1], m.m[3][2], m.m[3][3]); } + + +////////////////////////////////////////////////////////// +// Matrix Library +////////////////////////////////////////////////////////// + +void matrix4_f_set_rotate_x(matrix4f *matrix, float angle) +{ + float rot_matrix[4][4] = { + { 1, 0, 0, 0 }, + { 0, cosf(angle), -sinf(angle), 0 }, + { 0, sinf(angle), cosf(angle), 0 }, + { 0, 0, 0, 1 } + }; + + memcpy(matrix->m, rot_matrix, sizeof rot_matrix); +} + +void matrix4_f_set_rotate_y(matrix4f *matrix, float angle) +{ + float rot_matrix[4][4] = { + { cosf(angle), 0, sinf(angle), 0 }, + { 0, 1, 0, 0 }, + { -sinf(angle), 0, cosf(angle), 0 }, + { 0, 0, 0, 1 } + }; + + memcpy(matrix->m, rot_matrix, sizeof rot_matrix); +} + +void matrix4_f_set_rotate_z(matrix4f *matrix, float angle) +{ + float rot_matrix[4][4] = { + { cosf(angle), -sinf(angle), 0, 0 }, + { sinf(angle), cosf(angle), 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }; + + memcpy(matrix->m, rot_matrix, sizeof rot_matrix); +} + +void matrix4_f_set_translate(matrix4f *matrix, float x, float y, float z) +{ + float tran_matrix[4][4] = { + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { x, y, z, 1 } + }; + + memcpy(matrix->m, tran_matrix, sizeof tran_matrix); +} + +void matrix4_f_set_scale(matrix4f *matrix, float x, float y, float z) +{ + float sca_matrix[4][4] = { + { x, 0, 0, 0 }, + { 0, y, 0, 0 }, + { 0, 0, z, 0 }, + { 0, 0, 0, 1 } + }; + + memcpy(matrix->m, sca_matrix, sizeof sca_matrix); +} + +void matrix4_f_set_left_eye_projection ( + matrix4f *matrix, + float fov_degrees, + float aspect_ratio, + float near, float far, + float ipd, float distortion +) { + float fov_rad = 1.0f / tanf(fov_degrees * 0.5f / 180.0f * M_PI); + + // Compute the parameters for the left eye frustum + float left = -aspect_ratio * fov_rad - ipd * 0.5f; + float right = aspect_ratio * fov_rad - ipd * 0.5f; + float top = fov_rad; + float bottom = -fov_rad; + + // Apply distortion correction + float distortion_factor = 1.0f / distortion; + + left *= distortion_factor; + right *= distortion_factor; + top *= distortion_factor; + bottom *= distortion_factor; + + float proj_matrix[4][4] = { + { (2.0f * near) / (right - left), 0, (right + left) / (right - left), 0 }, + { 0, (2.0f * near) / (top - bottom), (top + bottom) / (top - bottom), 0 }, + { 0, 0, -(far + near) / (far - near), (-2.0f * far * near) / (far - near) }, + { 0, 0, -1, 0 } + }; + + memcpy(matrix->m, proj_matrix, sizeof proj_matrix); +} + +void matrix4_f_set_right_eye_projection ( + matrix4f *matrix, + float fov_degrees, + float aspect_ratio, + float near, float far, + float ipd, float distortion +) { + float fov_rad = 1.0f / tanf(fov_degrees * 0.5f / 180.0f * M_PI); + + // Compute the parameters for the right eye frustum + float left = -aspect_ratio * fov_rad + ipd * 0.5f; + float right = aspect_ratio * fov_rad + ipd * 0.5f; + float top = fov_rad; + float bottom = -fov_rad; + + // Apply distortion correction + float distortion_factor = 1.0f / distortion; + + left *= distortion_factor; + right *= distortion_factor; + top *= distortion_factor; + bottom *= distortion_factor; + + float proj_matrix[4][4] = { + { (2.0f * near) / (right - left), 0, (right + left) / (right - left), 0 }, + { 0, (2.0f * near) / (top - bottom), (top + bottom) / (top - bottom), 0 }, + { 0, 0, -(far + near) / (far - near), (-2.0f * far * near) / (far - near) }, + { 0, 0, -1, 0 } + }; + + memcpy(matrix->m, proj_matrix, sizeof proj_matrix); +} + +void matrix4_f_set_projection ( + matrix4f *matrix, + float fov_degrees, + float aspect_ratio, + float near, float far +) { + float fov_rad = 1.0f / tanf(fov_degrees * 0.5f / 180.0f * M_PI); + + float proj_matrix[4][4] = { + { aspect_ratio * fov_rad, 0, 0, 0 }, + { 0, fov_rad, 0, 0 }, + { 0, 0, far / (far - near), 1 }, + { 0, 0, (-far * near) / (far - near), 0 } + }; + + memcpy(matrix->m, proj_matrix, sizeof proj_matrix); +} + +void matrix4_f_set_view(matrix4f *matrix, vector4f pos, vector4f dir, vector4f up) +{ + // Calculate new forward direction + vector4f new_forward = vector4_f_sub(dir, pos); + new_forward = vector4_f_normalise(new_forward); + + // Calculate new Up direction + vector4f new_up = vector4_f_sub(up, vector4_f_mul(new_forward, vector4_f_dot_product(up, new_forward))); + new_up = vector4_f_normalise(new_up); + + // New Right direction is easy, its just cross product + vector4f new_right = vector4_f_cross_product(new_up, new_forward); + + // Construct Dimensioning and Translation Matrix + matrix4f view_matrix = (matrix4f) { + .m = { + { new_right.x, new_right.y, new_right.z, 0 }, + { new_up.x, new_up.y, new_up.z, 0 }, + { new_forward.x, new_forward.y, new_forward.z, 0 }, + { pos.x, pos.y, pos.z, 1 } + }}; + + *matrix = matrix4_f_quick_inverse(view_matrix); +} diff --git a/Engine/Engine/Math/Point/math_point.h b/Engine/Engine/Math/Point/math_point.h index 5a86b73..f5d12ff 100644 --- a/Engine/Engine/Math/Point/math_point.h +++ b/Engine/Engine/Math/Point/math_point.h @@ -18,7 +18,16 @@ //////////////////////////////////////////////////////////// // Include necessary headers for the point module //////////////////////////////////////////////////////////// -#include +#ifdef __cplusplus + #include + #include + + using namespace std; + extern "C" { +#else + #include + #include +#endif //////////////////////////////////////////////////////////// // Define the default point of floats @@ -79,4 +88,8 @@ extern point_f point_f_div(point_f v, float w); */ extern void point_f_print(point_f v); +#ifdef __cplusplus + } +#endif + #endif /* !MATH_POINT_H_ */ diff --git a/Engine/Engine/Math/Point/point.c b/Engine/Engine/Math/Point/point.c index ebbeba0..e94951f 100644 --- a/Engine/Engine/Math/Point/point.c +++ b/Engine/Engine/Math/Point/point.c @@ -8,7 +8,6 @@ */ #include "math_point.h" -#include point_f point_f_add(point_f p, point_f w) { return (point_f){p.x + w.x, p.y + w.y}; diff --git a/Engine/Engine/Math/Vector/math_vector.h b/Engine/Engine/Math/Vector/math_vector.h index a77ef65..b4c2726 100644 --- a/Engine/Engine/Math/Vector/math_vector.h +++ b/Engine/Engine/Math/Vector/math_vector.h @@ -18,13 +18,22 @@ //////////////////////////////////////////////////////////// // Include necessary headers for the vector module //////////////////////////////////////////////////////////// -#include +#ifdef __cplusplus + #include + #include + + using namespace std; + extern "C" { +#else + #include + #include +#endif //////////////////////////////////////////////////////////// // Define the default vector4 of floats //////////////////////////////////////////////////////////// -#define VECTOR4F_DEFAULT (vector4f){0, 0, 0, 0} -#define VECTOR4F_INIT(x, y, z, w) (vector4f){x, y, z, w} +#define VECTOR4F_DEFAULT (vector4f){{0, 0, 0, 0}} +#define VECTOR4F_INIT(x, y, z, w) (vector4f){{x, y, z, w}} /** * @brief Structure containing a 4D vector of floats @@ -34,8 +43,11 @@ * @param z {float} - The z component of the vector * @param w {float} - The w component of the vector */ -typedef struct { - float x, y, z, w; +typedef union vector4f_u { + struct { float x, y, z, w; }; + struct { float r, g, b, a; }; + struct { float width, height, depth, time; }; + float raw[4]; } vector4f; /** @@ -74,6 +86,9 @@ extern vector4f vector4_f_mul(vector4f v, float w); */ extern vector4f vector4_f_div(vector4f v, float w); +extern vector4f vector4_f_mul_vector4_f(vector4f v, vector4f w); + +extern vector4f vector4_f_div_vector4_f(vector4f v, vector4f w); /** * @brief Normalise a vector4 of floats (make its length equal to 1) @@ -109,6 +124,15 @@ extern float vector4_f_dot_product(vector4f v, vector4f w); */ extern float vector4_f_length(vector4f v); +/** + * @brief Compute the linear interpolation of two vector4 of floats with a float + * + * @param v {vector4f} - The first vector4 of floats + * @param w {vector4f} - The second vector4 of floats + * @param t {float} - The float to interpolate + * @return {vector4f} - The result of the linear interpolation + */ +extern vector4f vector4_f_lerp(vector4f v, vector4f w, float t); /** * @brief Compute the intersection of a plane and a line @@ -133,6 +157,8 @@ extern vector4f vector4_f_intersect_plane(vector4f plane_p, vector4f plane_n, ve */ extern vector4f vector4_f_intersect_line(vector4f plane_p, vector4f plane_n, vector4f line_start, vector4f line_end, float *t); +extern float vector4_f_calcul_dist(vector4f p, vector4f plane_p, vector4f plane_n); + /** * @brief Print a vector4 of floats in the console @@ -144,8 +170,8 @@ extern void vector4_f_print(vector4f v); //////////////////////////////////////////////////////////// // Define the default vector3 of floats //////////////////////////////////////////////////////////// -#define VECTOR3F_DEFAULT (vector3f){0, 0, 0} -#define VECTOR3F_INIT(x, y, z) (vector3f){x, y, z} +#define VECTOR3F_DEFAULT (vector3f){{0, 0, 0}}// NEED_COMMA +#define VECTOR3F_INIT(x, y, z) (vector3f){{x, y, z}}// NEED_COMMA /** * @brief Structure containing a 3D vector of floats @@ -154,8 +180,11 @@ extern void vector4_f_print(vector4f v); * @param y {float} - The y component of the vector * @param z {float} - The z component of the vector */ -typedef struct { - float x, y, z; +typedef union vector3f_u { + struct { float x, y, z; }; + struct { float r, g, b; }; + struct { float width, height, depth; }; + float raw[3]; } vector3f; /** @@ -261,4 +290,22 @@ extern vector3f vector3_f_intersect_line(vector3f plane_p, vector3f plane_n, vec */ extern void vector3_f_print(vector3f v); +//////////////////////////////////////////////////////////// +// Define the default vector2 of floats +//////////////////////////////////////////////////////////// + +typedef union vecto2f_u { + struct { float x, y; }; + struct { float u, v; }; + struct { float width, height; }; + float raw[2]; +} vector2f; + +extern vector3f vector4f_to_vector3f(vector4f v); +extern vector4f vector3f_to_vector4f(vector3f v); + +#ifdef __cplusplus + } +#endif + #endif /* !MATH_VECTOR_H_ */ diff --git a/Engine/Engine/Math/Vector/vector3.c b/Engine/Engine/Math/Vector/vector3.c index e6a4618..5ea5c1a 100644 --- a/Engine/Engine/Math/Vector/vector3.c +++ b/Engine/Engine/Math/Vector/vector3.c @@ -8,35 +8,34 @@ */ #include "math_vector.h" -#include vector3f vector3_f_add(vector3f v, vector3f w) { - return (vector3f){v.x + w.x, v.y + w.y, v.z + w.z}; + return (vector3f){{v.x + w.x, v.y + w.y, v.z + w.z}}; } vector3f vector3_f_sub(vector3f v, vector3f w) { - return (vector3f){v.x - w.x, v.y - w.y, v.z - w.z}; + return (vector3f){{v.x - w.x, v.y - w.y, v.z - w.z}}; } vector3f vector3_f_mul(vector3f v, float w) { - return (vector3f){v.x * w, v.y * w, v.z * w}; + return (vector3f){{v.x * w, v.y * w, v.z * w}}; } vector3f vector3_f_div(vector3f v, float w) { - return (vector3f){v.x / w, v.y / w, v.z / w}; + return (vector3f){{v.x / w, v.y / w, v.z / w}}; } vector3f vector3_f_normalise(vector3f v) { float length = vector3_f_length(v); - return (vector3f){v.x / length, v.y / length, v.z / length}; + return (vector3f){{v.x / length, v.y / length, v.z / length}}; } vector3f vector3_f_cross_product(vector3f a, vector3f b) { - return (vector3f){ + return (vector3f){{ a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x - }; + }}; } float vector3_f_dot_product(vector3f v, vector3f w) { @@ -74,3 +73,11 @@ vector3f vector3_f_intersect_line(vector3f plane_p, vector3f plane_n, vector3f l void vector3_f_print(vector3f v) { printf("[vector3f]: (%f, %f, %f)\n", v.x, v.y, v.z); } + +vector3f vector4f_to_vector3f(vector4f v) { + return (vector3f){{v.x, v.y, v.z}}; + +} +vector4f vector3f_to_vector4f(vector3f v) { + return (vector4f){{v.x, v.y, v.z, 1}}; +} diff --git a/Engine/Engine/Math/Vector/vector4.c b/Engine/Engine/Math/Vector/vector4.c index c4cd769..14402ef 100644 --- a/Engine/Engine/Math/Vector/vector4.c +++ b/Engine/Engine/Math/Vector/vector4.c @@ -8,36 +8,43 @@ */ #include "math_vector.h" -#include vector4f vector4_f_add(vector4f v, vector4f w) { - return (vector4f){v.x + w.x, v.y + w.y, v.z + w.z, v.w + w.w}; + return (vector4f){{v.x + w.x, v.y + w.y, v.z + w.z, v.w + w.w}}; } vector4f vector4_f_sub(vector4f v, vector4f w) { - return (vector4f){v.x - w.x, v.y - w.y, v.z - w.z, v.w - w.w}; + return (vector4f){{v.x - w.x, v.y - w.y, v.z - w.z, v.w - w.w}}; } vector4f vector4_f_mul(vector4f v, float w) { - return (vector4f){v.x * w, v.y * w, v.z * w, v.w * w}; + return (vector4f){{v.x * w, v.y * w, v.z * w, v.w * w}}; } vector4f vector4_f_div(vector4f v, float w) { - return (vector4f){v.x / w, v.y / w, v.z / w, v.w / w}; + return (vector4f){{v.x / w, v.y / w, v.z / w, v.w / w}}; +} + +vector4f vector4_f_mul_vector4_f(vector4f v, vector4f w) { + return (vector4f){{v.x * w.x, v.y * w.y, v.z * w.z, v.w * w.w}}; +} + +vector4f vector4_f_div_vector4_f(vector4f v, vector4f w) { + return (vector4f){{v.x / w.x, v.y / w.y, v.z / w.z, v.w / w.w}}; } vector4f vector4_f_normalise(vector4f v) { float length = vector4_f_length(v); - return (vector4f){v.x / length, v.y / length, v.z / length, v.w / length}; + return (vector4f){{v.x / length, v.y / length, v.z / length, v.w / length}}; } vector4f vector4_f_cross_product(vector4f a, vector4f b) { - return (vector4f){ + return (vector4f){{ a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x, 0 - }; + }}; } float vector4_f_dot_product(vector4f v, vector4f w) { @@ -48,6 +55,15 @@ float vector4_f_length(vector4f v) { return sqrtf(vector4_f_dot_product(v, v)); } +vector4f vector4_f_lerp(vector4f v, vector4f w, float t) { + return (vector4f){{ + v.x + t * (w.x - v.x), + v.y + t * (w.y - v.y), + v.z + t * (w.z - v.z), + v.w + t * (w.w - v.w) + }}; +} + vector4f vector4_f_intersect_plane(vector4f plane_p, vector4f plane_n, vector4f line_start, vector4f line_end) { plane_n = vector4_f_normalise(plane_n); @@ -72,6 +88,11 @@ vector4f vector4_f_intersect_line(vector4f plane_p, vector4f plane_n, vector4f l return vector4_f_add(line_start, line_to_intersect); } +float vector4_f_calcul_dist(vector4f p, vector4f plane_p, vector4f plane_n) +{ + return (plane_n.x * p.x + plane_n.y * p.y + plane_n.z * p.z - vector4_f_dot_product(plane_n, plane_p)); +} + void vector4_f_print(vector4f v) { printf("[vector4f]: (%f, %f, %f, %f)\n", v.x, v.y, v.z, v.w); } diff --git a/Engine/Engine/Math/engine_math.h b/Engine/Engine/Math/engine_math.h index 594ca21..96f7dfd 100644 --- a/Engine/Engine/Math/engine_math.h +++ b/Engine/Engine/Math/engine_math.h @@ -21,5 +21,7 @@ #include "math_vector.h" #include "math_matrix.h" #include "math_geometry.h" +// #include "Quaternion/quaternion.h" +// #include "Transform/transform.h" #endif /* !MATH_H_ */ diff --git a/Engine/Engine/Math/math.md b/Engine/Engine/Math/math.md new file mode 100644 index 0000000..bf58c7f --- /dev/null +++ b/Engine/Engine/Math/math.md @@ -0,0 +1,34 @@ +**The Cauchy-Schwarz Inequality** + +```math +\left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) +``` + + +q = Q′ ∼ + + + + + +fx s cx +0 fy cy +0 0 1 + + + + + +︸ ︷︷ ︸ +K +R [I| − t] +︸ ︷︷ ︸ +C +Q (1.2) +where: +q – 2D point on image plane, +Q′ – 2D point on image plane expressed in homogeneous coordinates (3-vector), +Q – 3D point corresponding to q, expressed in homogeneous coordinates (4-vector), +∼ – equality between homogeneous points, +K – 3x3 camera intrinsic parameters matrix, +C – 3x4 camera matrix, diff --git a/Engine/Engine/Pipelines/00.txt b/Engine/Engine/Pipelines/00.txt new file mode 100644 index 0000000..cf2ce71 --- /dev/null +++ b/Engine/Engine/Pipelines/00.txt @@ -0,0 +1,409 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** graphics_pipeline +*/ + +#ifndef GRAPHICS_PIPELINE_H_ +#define GRAPHICS_PIPELINE_H_ + +//////////////////////////////////////////////////////////// +// Include the other headers of the engine module +//////////////////////////////////////////////////////////// +#include "camera.h" +#include "mesh.h" + + +// graphics_lighting +// graphics_projection_transformation (World to Projection) +// graphics_z_buffering (optional) +// graphics_rasterization +// graphics_rasterization_by_pixel (optional) +// graphics_texture_mapping (optional) +// graphics_fragment_shader (optional) +// graphics_depth_buffering (optional) +// graphics_alpha_blending (optional) + +// graphics_clip_against_plane (Clipping) +int graphics_clip_against_plane(camera_t *camera, vector4f plane_p, triangle_t *triangle, triangle_t *clipped) +{ + vector4f plane_n = vector4_f_normalise(plane_p); + int nb_vertices_in_front_of_plane = 0; + int nb_vertices_behind_plane = 0; + float distance_to_plane = 0.0f; + float distance1 = 0.0f; + float distance2 = 0.0f; + vector4f intersection_point = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_vertex = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_color = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_normal = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_uv = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_tangent = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_bitangent = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + vector4f new_barycentric = VECTOR4F_INIT(0.0f, 0.0f, 0.0f, 0.0f); + + distance1 = vector4_f_dot_product(plane_n, triangle->vertices[0]) - vector4_f_dot_product(plane_n, plane_p); + distance2 = vector4_f_dot_product(plane_n, triangle->vertices[1]) - vector4_f_dot_product(plane_n, plane_p); + if (distance1 >= 0.0f) + nb_vertices_in_front_of_plane++; + else + nb_vertices_behind_plane++; + if (distance2 >= 0.0f) + nb_vertices_in_front_of_plane++; + else + nb_vertices_behind_plane++; + if (nb_vertices_in_front_of_plane == 3) { + clipped->vertices[0] = triangle->vertices[0]; + clipped->vertices[1] = triangle->vertices[1]; + clipped->vertices[2] = triangle->vertices[2]; + clipped->color[0] = triangle->color[0]; + clipped->color[1] = triangle->color[1]; + clipped->color[2] = triangle->color[2]; + clipped->normal[0] = triangle->normal[0]; + clipped->normal[1] = triangle->normal[1]; + clipped->normal[2] = triangle->normal[2]; + clipped->uv[0] = triangle->uv[0]; + clipped->uv[1] = triangle->uv[1]; + clipped->uv[2] = triangle->uv[2]; + clipped->tangent[0] = triangle->tangent[0]; + clipped->tangent[1] = triangle->tangent[1]; + clipped->tangent[2] = triangle->tangent[2]; + clipped->bitangent[0] = triangle->bitangent[0]; + clipped->bitangent[1] = triangle->bitangent[1]; + clipped->bitangent[2] = triangle->bitangent[2]; + clipped->barycentric[0] = triangle->barycentric[0]; + clipped->barycentric[1] = triangle->barycentric[1]; + clipped->barycentric[2] = triangle->barycentric[2]; + return (1); + } + if (nb_vertices_behind_plane == 3) + return (0); + if (nb_vertices_in_front_of_plane == 1 && nb_vertices_behind_plane == 2) { + clipped->vertices[0] = triangle->vertices[0]; + clipped->vertices[1] = triangle->vertices[1]; + clipped->vertices[2] = triangle->vertices[2]; + clipped->color[0] = triangle->color[0]; + clipped->color[1] = triangle->color[1]; + clipped->color[2] = triangle->color[2]; + clipped->normal[0] = triangle->normal[0]; + clipped->normal[1] = triangle->normal[1]; + clipped->normal[2] = triangle->normal[2]; + clipped->uv[0] = triangle->uv[0]; + clipped->uv[1] = triangle->uv[1]; + clipped->uv[2] = triangle->uv[2]; + clipped->tangent[0] = triangle->tangent[0]; + clipped->tangent[1] = triangle->tangent[1]; + clipped->tangent[2] = triangle->tangent[2]; + clipped->bitangent[0] = triangle->bitangent[0]; + clipped->bitangent[1] = triangle->bitangent[1]; + clipped->bitangent[2] = triangle->bitangent[2]; + clipped->barycentric[0] = triangle->barycentric[0]; + clipped->barycentric[1] = triangle->barycentric[1]; + clipped->barycentric[2] = triangle->barycentric[2]; + distance_to_plane = distance1 / (distance1 - distance2); + new_vertex = vector4_f_lerp(triangle->vertices[0], triangle->vertices[1], distance_to_plane); + new_color = vector4_f_lerp(triangle->color[0], triangle->color[1], distance_to_plane); + new_normal = vector4_f_lerp(triangle->normal[0], triangle->normal[1], distance_to_plane); + new_uv = vector4_f_lerp(triangle->uv[0], triangle->uv[1], distance_to_plane); + new_tangent = vector4_f_lerp(triangle->tangent[0], triangle->tangent[1], distance_to_plane); + new_bitangent = vector4_f_lerp(triangle->bitangent[0], triangle->bitangent[1], distance_to_plane); + new_barycentric = vector4_f_lerp(triangle->barycentric[0], triangle->barycentric[1], distance_to_plane); + clipped->vertices[1] = new_vertex; + clipped->color[1] = new_color; + clipped->normal[1] = new_normal; + clipped->uv[1] = new_uv; + clipped->tangent[1] = new_tangent; + clipped->bitangent[1] = new_bitangent; + clipped->barycentric[1] = new_barycentric; + return (1); + } + if (nb_vertices_in_front_of_plane == 2 && nb_vertices_behind_plane == 1) { + clipped->vertices[0] = triangle->vertices[0]; + clipped->vertices[1] = triangle->vertices[1]; + clipped->vertices[2] = triangle->vertices[2]; + clipped->color[0] = triangle->color[0]; + clipped->color[1] = triangle->color[1]; + clipped->color[2] = triangle->color[2]; + clipped->normal[0] = triangle->normal[0]; + clipped->normal[1] = triangle->normal[1]; + clipped->normal[2] = triangle->normal[2]; + clipped->uv[0] = triangle->uv[0]; + clipped->uv[1] = triangle->uv[1]; + clipped->uv[2] = triangle->uv[2]; + clipped->tangent[0] = triangle->tangent[0]; + clipped->tangent[1] = triangle->tangent[1]; + clipped->tangent[2] = triangle->tangent[2]; + clipped->bitangent[0] = triangle->bitangent[0]; + clipped->bitangent[1] = triangle->bitangent[1]; + clipped->bitangent[2] = triangle->bitangent[2]; + clipped->barycentric[0] = triangle->barycentric[0]; + clipped->barycentric[1] = triangle->barycentric[1]; + clipped->barycentric[2] = triangle->barycentric[2]; + distance_to_plane = distance1 / (distance1 - distance2); + new_vertex = vector4_f_lerp(triangle->vertices[0], triangle->vertices[1], distance_to_plane); + new_color = vector4_f_lerp(triangle->color[0], triangle->color[1], distance_to_plane); + new_normal = vector4_f_lerp(triangle->normal[0], triangle->normal[1], distance_to_plane); + new_uv = vector4_f_lerp(triangle->uv[0], triangle->uv[1], distance_to_plane); + new_tangent = vector4_f_lerp(triangle->tangent[0], triangle->tangent[1], distance_to_plane); + new_bitangent = vector4_f_lerp(triangle->bitangent[0], triangle->bitangent[1], distance_to_plane); + new_barycentric = vector4_f_lerp(triangle->barycentric[0], triangle->barycentric[1], distance_to_plane); + clipped->vertices[0] = new_vertex; + clipped->color[0] = new_color; + clipped->normal[0] = new_normal; + clipped->uv[0] = new_uv; + clipped->tangent[0] = new_tangent; + clipped->bitangent[0] = new_bitangent; + clipped->barycentric[0] = new_barycentric; + distance_to_plane = distance1 / (distance1 - distance2); + new_vertex = vector4_f_lerp(triangle->vertices[0], triangle->vertices[2], distance_to_plane); + new_color = vector4_f_lerp(triangle->color[0], triangle->color[2], distance_to_plane); + new_normal = vector4_f_lerp(triangle->normal[0], triangle->normal[2], distance_to_plane); + new_uv = vector4_f_lerp(triangle->uv[0], triangle->uv[2], distance_to_plane); + new_tangent = vector4_f_lerp(triangle->tangent[0], triangle->tangent[2], distance_to_plane); + new_bitangent = vector4_f_lerp(triangle->bitangent[0], triangle->bitangent[2], distance_to_plane); + new_barycentric = vector4_f_lerp(triangle->barycentric[0], triangle->barycentric[2], distance_to_plane); + clipped->vertices[2] = new_vertex; + clipped->color[2] = new_color; + clipped->normal[2] = new_normal; + clipped->uv[2] = new_uv; + clipped->tangent[2] = new_tangent; + clipped->bitangent[2] = new_bitangent; + clipped->barycentric[2] = new_barycentric; + return (1); + } + if (nb_vertices_in_front_of_plane == 1 && nb_vertices_behind_plane == 1) { + clipped->vertices[0] = triangle->vertices[0]; + clipped->vertices[1] = triangle->vertices[1]; + clipped->vertices[2] = triangle->vertices[2]; + clipped->color[0] = triangle->color[0]; + clipped->color[1] = triangle->color[1]; + clipped->color[2] = triangle->color[2]; + clipped->normal[0] = triangle->normal[0]; + clipped->normal[1] = triangle->normal[1]; + clipped->normal[2] = triangle->normal[2]; + clipped->uv[0] = triangle->uv[0]; + clipped->uv[1] = triangle->uv[1]; + clipped->uv[2] = triangle->uv[2]; + clipped->tangent[0] = triangle->tangent[0]; + clipped->tangent[1] = triangle->tangent[1]; + clipped->tangent[2] = triangle->tangent[2]; + clipped->bitangent[0] = triangle->bitangent[0]; + clipped->bitangent[1] = triangle->bitangent[1]; + clipped->bitangent[2] = triangle->bitangent[2]; + clipped->barycentric[0] = triangle->barycentric[0]; + clipped->barycentric[1] = triangle->barycentric[1]; + clipped->barycentric[2] = triangle->barycentric[2]; + distance_to_plane = distance1 / (distance1 - distance2); + new_vertex = vector4_f_lerp(triangle->vertices[0], triangle->vertices[1], distance_to_plane); + new_color = vector4_f_lerp(triangle->color[0], triangle->color[1], distance_to_plane); + new_normal = vector4_f_lerp(triangle->normal[0], triangle->normal[1], distance_to_plane); + new_uv = vector4_f_lerp(triangle->uv[0], triangle->uv[1], distance_to_plane); + new_tangent = vector4_f_lerp(triangle->tangent[0], triangle->tangent[1], distance_to_plane); + new_bitangent = vector4_f_lerp(triangle->bitangent[0], triangle->bitangent[1], distance_to_plane); + new_barycentric = vector4_f_lerp(triangle->barycentric[0], triangle->barycentric[1], distance_to_plane); + clipped->vertices[1] = new_vertex; + clipped->color[1] = new_color; + clipped->normal[1] = new_normal; + clipped->uv[1] = new_uv; + clipped->tangent[1] = new_tangent; + clipped->bitangent[1] = new_bitangent; + clipped->barycentric[1] = new_barycentric; + distance_to_plane = distance1 / (distance1 - distance2); + new_vertex = vector4_f_lerp(triangle->vertices[0], triangle->vertices[2], distance_to_plane); + new_color = vector4_f_lerp(triangle->color[0], triangle->color[2], distance_to_plane); + new_normal = vector4_f_lerp(triangle->normal[0], triangle->normal[2], distance_to_plane); + new_uv = vector4_f_lerp(triangle->uv[0], triangle->uv[2], distance_to_plane); + new_tangent = vector4_f_lerp(triangle->tangent[0], triangle->tangent[2], distance_to_plane); + new_bitangent = vector4_f_lerp(triangle->bitangent[0], triangle->bitangent[2], distance_to_plane); + new_barycentric = vector4_f_lerp(triangle->barycentric[0], triangle->barycentric[2], distance_to_plane); + clipped->vertices[2] = new_vertex; + clipped->color[2] = new_color; + clipped->normal[2] = new_normal; + clipped->uv[2] = new_uv; + clipped->tangent[2] = new_tangent; + clipped->bitangent[2] = new_bitangent; + clipped->barycentric[2] = new_barycentric; + return (2); + } + return (0); +} + + +// graphics_clipping +void graphics_clipping(camera_t *camera, triangle_t *transformed) +{ + triangle_t clipped[2]; + int nb_triangles = 0; + nb_triangles = graphics_clip_against_plane(camera, VECTOR4F_INIT(0.0f, 0.0f, 0.1f, 0.0f), transformed, &clipped[0]); + for (int i = 0; i < nb_triangles; i++) { + nb_triangles = graphics_clip_against_plane(camera, VECTOR4F_INIT(0.0f, 0.0f, 1.0f, 0.0f), &clipped[i], &clipped[(i + 1) % 2]); + } + if (nb_triangles > 0) { + for (int i = 0; i < nb_triangles; i++) { + graphics_rasterization(camera, clipped[i]); + } + } +} + + +// graphics_viewport_transformation (World to View) +void graphics_viewport_transformation(camera_t *camera, triangle_t *transformed, vector4f normal) +{ + triangle_t viewed; + + viewed.vertices[0] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[0]); + viewed.vertices[1] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[1]); + viewed.vertices[2] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[2]); + + viewed.vertices[0] = vector4_f_div(viewed.vertices[0], viewed.vertices[0].w); + viewed.vertices[1] = vector4_f_div(viewed.vertices[1], viewed.vertices[1].w); + viewed.vertices[2] = vector4_f_div(viewed.vertices[2], viewed.vertices[2].w); + + viewed.vertices[0].x *= -1.0f; + viewed.vertices[1].x *= -1.0f; + viewed.vertices[2].x *= -1.0f; + viewed.vertices[0].y *= -1.0f; + viewed.vertices[1].y *= -1.0f; + viewed.vertices[2].y *= -1.0f; + + viewed.vertices[0].x += 1.0f; + viewed.vertices[1].x += 1.0f; + viewed.vertices[2].x += 1.0f; + viewed.vertices[0].y += 1.0f; + viewed.vertices[1].y += 1.0f; + viewed.vertices[2].y += 1.0f; + + viewed.vertices[0].x *= 0.5f * (float) camera->width; + viewed.vertices[1].x *= 0.5f * (float) camera->width; + viewed.vertices[2].x *= 0.5f * (float) camera->width; + viewed.vertices[0].y *= 0.5f * (float) camera->height; + viewed.vertices[1].y *= 0.5f * (float) camera->height; + viewed.vertices[2].y *= 0.5f * (float) camera->height; + + graphics_clipping(camera, &viewed); +} + + +// graphics_backface_culling +void graphics_backface_culling(camera_t *camera, mesh_t *mesh) +{ + triangle_t transformed; + link_t *actual = mesh; + triangle_t *triangle = NULL; + + if (!actual) + return; + do { + triangle = (triangle_t *) actual->obj; + + transformed.vertices[0] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[0]); + transformed.vertices[1] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[1]); + transformed.vertices[2] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[2]); + + vector4f line1 = vector4_f_sub(transformed.vertices[1], transformed.vertices[0]); + vector4f line2 = vector4_f_sub(transformed.vertices[2], transformed.vertices[0]); + vector4f normal = vector4_f_normalise(vector4_f_cross_product(line1, line2)); + vector4f camera_ray = vector4_f_sub(transformed.vertices[0], camera->position); + + if (vector4_f_dot_product(normal, camera_ray) < 0.0f) + graphics_viewport_transformation(camera, transformed, normal); + + actual = actual->next; + } while (mesh && actual != mesh); +} + + +// graphics_tesselation (optional) + + +// graphics_world_transformation (Model to World) +void graphics_world_transformation(camera_t *camera, mesh_t *mesh, float delta_time UNUSED) +{ + if (!mesh) + return; + // if (mesh->animation) { + // mesh->animation->current_time += delta_time; + // if (mesh->animation->current_time >= mesh->animation->duration) + // mesh->animation->current_time = 0; + // mesh->animation->current_frame = (int) (mesh->animation->current_time + // * mesh->animation->fps); + // mesh->animation->current_frame %= mesh->animation->nb_frames; + // mesh->animation->current_frame *= mesh->animation->nb_bones; + // for (int i = 0; i < mesh->animation->nb_bones; i++) { + // mesh->bones[i].transform = mesh->animation->frames[ + // mesh->animation->current_frame + i]; + // } + // } + // if (mesh->skeleton) { + // for (int i = 0; i < mesh->skeleton->nb_bones; i++) { + // mesh->bones[i].transform = mesh->skeleton->bones[i].transform; + // } + // } + // if (mesh->animation || mesh->skeleton) { + // for (int i = 0; i < mesh->nb_vertices; i++) { + // mesh->vertices[i].position = vector4_f_mul_matrix4_f( + // mesh->vertices[i].original_position, mesh->bones[ + // mesh->vertices[i].bone_id].transform); + // } + // } + + // Model to World (M2W) + matrix4f rotate[4][4]; + matrix4f rotate_y[4][4]; + matrix4f rotate_x[4][4]; + matrix4f rotate_z[4][4]; + matrix4f translate[4][4]; + matrix4f scale[4][4]; + + // Rotation matrices : around the z-axis - around the y-axis - around the x-axis + matrix4_f_set_rotate_x(&rotate_x, angle.x); + matrix4_f_set_rotate_y(&rotate_y, angle.y); + matrix4_f_set_rotate_z(&rotate_z, angle.z); + rotate = matrix4_f_mul(rotate_x, rotate_y); + rotate = matrix4_f_mul(rotate, rotate_z); + // Translation matrix + matrix4_f_set_translate(&translate, pos.x, pos.y, pos.z); + mesh->transform = matrix4_f_mul(rotate, translate); + // Scaling matrix + matrix4_f_set_scale(&scale, scale.x, scale.y, scale.z); + mesh->transform= matrix4_f_mul(mesh->transform, scale); + + graphics_backface_culling(camera, mesh); +} + + +// graphics_animation (optional) + + +void grapycal_pipeline_apply(engine_renderer_t *renderer, camera_t *camera, link_t *meshs, float delta_time) +{ + triangle_t triTransformed, triViewed; + link_t *actual = meshs; + mesh_t *mesh = NULL; + + if (!actual) + return; + do { + mesh = (mesh_t *) actual->obj; + // graphics_animation (optional) + graphics_world_transformation(camera, mesh, delta_time); // M2W (Model to World) + // graphics_tesselation (optional) + + // graphics_backface_culling + // graphics_viewport_transformation (World to View) + // graphics_clipping + // graphics_lighting + // graphics_projection_transformation (World to Projection) + // graphics_z_buffering (optional) + // graphics_rasterization + // graphics_rasterization_by_pixel (optional) + // graphics_texture_mapping (optional) + // graphics_fragment_shader (optional) + // graphics_depth_buffering (optional) + // graphics_alpha_blending (optional) + actual = actual->next; + } while (meshs && actual != meshs); +} + +#endif /* !GRAPHICS_PIPELINE_H_ */ diff --git a/Engine/Engine/Pipelines/graphics_pipeline.c b/Engine/Engine/Pipelines/graphics_pipeline.c new file mode 100644 index 0000000..4a048dd --- /dev/null +++ b/Engine/Engine/Pipelines/graphics_pipeline.c @@ -0,0 +1,582 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** graphics_pipeline +*/ + +#include "graphics_pipeline.h" +#include + +static sfVertexArray *create_triangle(triangle_t *node) +{ + sfVertexArray *vertex_array = sfVertexArray_create(); + sfVertex vertex1, vertex2, vertex3; + + int lighting = (int)(node->dp * 255); + + // if (node->usemtl == WATER || node->usemtl == BUBBLE) { + // sfColor color = (sfColor){lighting, lighting, lighting, 255/1.5}; + // vertex1 = (sfVertex){*(sfVector2f*)&(node->vertices[0]), color, *(sfVector2f*)&(node->texture[0])}; + // vertex2 = (sfVertex){*(sfVector2f*)&(node->vertices[1]), color, *(sfVector2f*)&(node->texture[1])}; + // vertex3 = (sfVertex){*(sfVector2f*)&(node->vertices[2]), color, *(sfVector2f*)&(node->texture[2])}; + // } else if (node->usemtl != NONE) { + sfColor color = (sfColor){lighting, lighting, lighting, 255}; + // sfVector2u texSize = sfTexture_getSize(engine.textures[node->usemtl]->texture); + vertex1 = (sfVertex){*(sfVector2f*)&(node->vertices[0]), color, (sfVector2f){0,0}};//, (sfVector2f){node->texture[0].x * texSize.x, node->texture[0].y * texSize.y}}; + vertex2 = (sfVertex){*(sfVector2f*)&(node->vertices[1]), color, (sfVector2f){0,0}};//, (sfVector2f){node->texture[1].x * texSize.x, node->texture[1].y * texSize.y}}; + vertex3 = (sfVertex){*(sfVector2f*)&(node->vertices[2]), color, (sfVector2f){0,0}};//, (sfVector2f){node->texture[2].x * texSize.x, node->texture[2].y * texSize.y}}; + // } else { + // int r = RAND(0, 255); + // int g = RAND(0, 255); + // int b = RAND(0, 255); + // sfColor color = (sfColor){r, g, b, 255}; + // vertex1 = (sfVertex){*(sfVector2f*)&(node->vertices[0]), .color = color}; + // vertex2 = (sfVertex){*(sfVector2f*)&(node->vertices[1]), .color = color}; + // vertex3 = (sfVertex){*(sfVector2f*)&(node->vertices[2]), .color = color}; + // } + + sfVertexArray_append(vertex_array, vertex1); + sfVertexArray_append(vertex_array, vertex2); + sfVertexArray_append(vertex_array, vertex3); + sfVertexArray_setPrimitiveType(vertex_array, sfTriangleFan); + return vertex_array; +} + +static void draw_triangle(engine_renderer_t *renderer, triangle_t *node) +{ + sfVertexArray *vertex_array = NULL; + + if ((vertex_array = create_triangle(node))) { + sfRenderWindow_drawVertexArray(renderer->window->window, vertex_array, NULL); + sfVertexArray_destroy(vertex_array); + } +} + +// void graphics_texture_mapping(camera_t *camera, triangle_t projected) +// { +// int x1 = projected.vertices[0].x; +// int y1 = projected.vertices[0].y; + +// int x2 = projected.vertices[1].x; +// int y2 = projected.vertices[1].y; + +// int x3 = projected.vertices[2].x; +// int y3 = projected.vertices[2].y; + +// float u1 = projected.textures[0].x; +// float v1 = projected.textures[0].y; +// float w1 = projected.textures[0].z; + +// float u2 = projected.textures[1].x; +// float v2 = projected.textures[1].y; +// float w2 = projected.textures[1].z; + +// float u3 = projected.textures[2].x; +// float v3 = projected.textures[2].y; +// float w3 = projected.textures[2].z; + +// if (y2 < y1) { +// SWAP(y1, y2); +// SWAP(x1, x2); +// SWAP(u1, u2); +// SWAP(v1, v2); +// SWAP(w1, w2); +// } + +// if (y3 < y1) { +// SWAP(y1, y3); +// SWAP(x1, x3); +// SWAP(u1, u3); +// SWAP(v1, v3); +// SWAP(w1, w3); +// } + +// if (y3 < y2) { +// SWAP(y2, y3); +// SWAP(x2, x3); +// SWAP(u2, u3); +// SWAP(v2, v3); +// SWAP(w2, w3); +// } + +// int dy1 = y2 - y1; +// int dx1 = x2 - x1; +// float dv1 = v2 - v1; +// float du1 = u2 - u1; +// float dw1 = w2 - w1; + +// int dy2 = y3 - y1; +// int dx2 = x3 - x1; +// float dv2 = v3 - v1; +// float du2 = u3 - u1; + +// float tex_u, tex_v, tex_w; + +// float dax_step = 0, dbx_step = 0; +// float du1_step = 0, dv1_step = 0; +// float du2_step = 0, dv2_step = 0; +// float dw1_step = 0, dw2_step = 0; + +// if (dy1) dax_step = dx1 / (float)abs(dy1); +// if (dy2) dbx_step = dx2 / (float)abs(dy2); + +// if (dy1) du1_step = du1 / (float)abs(dy1); +// if (dy1) dv1_step = dv1 / (float)abs(dy1); +// if (dy1) dw1_step = dw1 / (float)abs(dy1); + +// if (dy2) du2_step = du2 / (float)abs(dy2); +// if (dy2) dv2_step = dv2 / (float)abs(dy2); + +// if (dy1) { +// for (int i = y1; i <= y2; i++) { +// int ax = x1 + (float)(i - y1) * dax_step; +// int bx = x1 + (float)(i - y1) * dbx_step; + +// float tex_su = u1 + (float)(i - y1) * du1_step; +// float tex_sv = v1 + (float)(i - y1) * dv1_step; +// float tex_sw = w1 + (float)(i - y1) * dw1_step; + +// float tex_eu = u1 + (float)(i - y1) * du2_step; +// float tex_ev = v1 + (float)(i - y1) * dv2_step; +// float tex_ew = w1 + (float)(i - y1) * dw2_step; + +// if (ax > bx) { +// SWAP(ax, bx); +// SWAP(tex_su, tex_eu); +// SWAP(tex_sv, tex_ev); +// SWAP(tex_sw, tex_ew); +// } + +// tex_u = tex_su; +// tex_v = tex_sv; +// tex_w = tex_sw; + +// float tstep = 1.0f / ((float)(bx - ax)); +// float t = 0.0f; + +// for (int j = ax; j < bx; j++) { +// tex_u = (1.0f - t) * tex_su + t * tex_eu; +// tex_v = (1.0f - t) * tex_sv + t * tex_ev; +// tex_w = (1.0f - t) * tex_sw + t * tex_ew; + +// t += tstep; + +// int tx = (int)(tex_u / tex_w); +// int ty = (int)(tex_v / tex_w); + +// sfColor color = sfImage_getPixel(camera->texture, tx, ty); +// sfVector2f pos = {j, i}; +// sfVertex vertex = {pos, color, {0, 0}}; +// sfVertexArray_append(camera->vertex_array, vertex); +// // sfRenderWindow_drawVertexArray(WINDOW, camera->vertex_array, NULL); +// } +// } +// } +// } + +void graphics_rasterization(engine_renderer_t *renderer, camera_t *camera) +{ + while (camera->final_meshs) { + triangle_t *tri = (triangle_t *) camera->final_meshs->obj; + draw_triangle(renderer, tri); + free((triangle_t *) camera->final_meshs->obj); + lp_link_remove(&(camera->final_meshs), camera->final_meshs, NULL); + } +} + + +void graphics_z_buffering(camera_t *camera) +{ + lp_link_sort(&camera->final_meshs, &geometry_triangle_compare); +} + + +void graphics_projection_transformation(camera_t *camera, triangle_t *clipped) +{ + triangle_t *projected = calloc(1, sizeof(triangle_t)); + float win_x = (float) camera->screen_size.width; + float win_y = (float) camera->screen_size.height; + + if (!projected) + return; + + if (camera->is_vr) { + // vector4f offset_view = VECTOR4F_INIT(0.5, 1, 0, 0); + + projected->vertices[0] = matrix4_f_mul_vector4_f(camera->projection_left, clipped->vertices[0]); + projected->vertices[1] = matrix4_f_mul_vector4_f(camera->projection_left, clipped->vertices[1]); + projected->vertices[2] = matrix4_f_mul_vector4_f(camera->projection_left, clipped->vertices[2]); + + projected->textures[0].x = clipped->textures[0].x / clipped->vertices[0].w; + projected->textures[0].y = clipped->textures[0].y / clipped->vertices[0].w; + projected->textures[1].x = clipped->textures[1].x / clipped->vertices[1].w; + projected->textures[1].y = clipped->textures[1].y / clipped->vertices[1].w; + projected->textures[2].x = clipped->textures[2].x / clipped->vertices[2].w; + projected->textures[2].y = clipped->textures[2].y / clipped->vertices[2].w; + + projected->textures[0].z = 1.0f / clipped->vertices[0].w; + projected->textures[1].z = 1.0f / clipped->vertices[1].w; + projected->textures[2].z = 1.0f / clipped->vertices[2].w; + + projected->vertices[0] = vector4_f_div(projected->vertices[0], projected->vertices[0].w); + projected->vertices[1] = vector4_f_div(projected->vertices[1], projected->vertices[1].w); + projected->vertices[2] = vector4_f_div(projected->vertices[2], projected->vertices[2].w); + + projected->vertices[0] = vector4_f_add(projected->vertices[0], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + projected->vertices[1] = vector4_f_add(projected->vertices[1], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + projected->vertices[2] = vector4_f_add(projected->vertices[2], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + + projected->vertices[0] = vector4_f_mul_vector4_f(projected->vertices[0], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + projected->vertices[1] = vector4_f_mul_vector4_f(projected->vertices[1], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + projected->vertices[2] = vector4_f_mul_vector4_f(projected->vertices[2], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + + projected->vertices[0].z = clipped->vertices[0].z; + projected->vertices[1].z = clipped->vertices[1].z; + projected->vertices[2].z = clipped->vertices[2].z; + + projected->dp = clipped->dp; + + lp_link_append(&(camera->final_meshs), lp_link_create(projected)); + + + triangle_t *projected2 = calloc(1, sizeof(triangle_t)); + if (!projected2) + return; + // vector4f offset_view2 = VECTOR4F_INIT(1.5, 1, 0, 0); + + projected2->vertices[0] = matrix4_f_mul_vector4_f(camera->projection_right, clipped->vertices[0]); + projected2->vertices[1] = matrix4_f_mul_vector4_f(camera->projection_right, clipped->vertices[1]); + projected2->vertices[2] = matrix4_f_mul_vector4_f(camera->projection_right, clipped->vertices[2]); + + projected2->textures[0].x = clipped->textures[0].x / clipped->vertices[0].w; + projected2->textures[0].y = clipped->textures[0].y / clipped->vertices[0].w; + projected2->textures[1].x = clipped->textures[1].x / clipped->vertices[1].w; + projected2->textures[1].y = clipped->textures[1].y / clipped->vertices[1].w; + projected2->textures[2].x = clipped->textures[2].x / clipped->vertices[2].w; + projected2->textures[2].y = clipped->textures[2].y / clipped->vertices[2].w; + + projected2->textures[0].z = 1.0f / clipped->vertices[0].w; + projected2->textures[1].z = 1.0f / clipped->vertices[1].w; + projected2->textures[2].z = 1.0f / clipped->vertices[2].w; + + projected2->vertices[0] = vector4_f_div(projected2->vertices[0], projected2->vertices[0].w); + projected2->vertices[1] = vector4_f_div(projected2->vertices[1], projected2->vertices[1].w); + projected2->vertices[2] = vector4_f_div(projected2->vertices[2], projected2->vertices[2].w); + + projected2->vertices[0] = vector4_f_add(projected2->vertices[0], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + projected2->vertices[1] = vector4_f_add(projected2->vertices[1], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + projected2->vertices[2] = vector4_f_add(projected2->vertices[2], VECTOR4F_INIT(1.f, 1.f, 0.f, 0.f)); + + projected2->vertices[0] = vector4_f_mul_vector4_f(projected2->vertices[0], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + projected2->vertices[1] = vector4_f_mul_vector4_f(projected2->vertices[1], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + projected2->vertices[2] = vector4_f_mul_vector4_f(projected2->vertices[2], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.f, 1.f)); + + projected2->vertices[0].z = clipped->vertices[0].z; + projected2->vertices[1].z = clipped->vertices[1].z; + projected2->vertices[2].z = clipped->vertices[2].z; + + projected2->dp = clipped->dp; + + lp_link_append(&(camera->final_meshs), lp_link_create(projected2)); + return; + } + + projected->vertices[0] = matrix4_f_mul_vector4_f(camera->projection, clipped->vertices[0]); + projected->vertices[1] = matrix4_f_mul_vector4_f(camera->projection, clipped->vertices[1]); + projected->vertices[2] = matrix4_f_mul_vector4_f(camera->projection, clipped->vertices[2]); + + projected->textures[0].x = clipped->textures[0].x / clipped->vertices[0].w; + projected->textures[0].y = clipped->textures[0].y / clipped->vertices[0].w; + projected->textures[1].x = clipped->textures[1].x / clipped->vertices[1].w; + projected->textures[1].y = clipped->textures[1].y / clipped->vertices[1].w; + projected->textures[2].x = clipped->textures[2].x / clipped->vertices[2].w; + projected->textures[2].y = clipped->textures[2].y / clipped->vertices[2].w; + + projected->textures[0].z = 1.0f / clipped->vertices[0].w; + projected->textures[1].z = 1.0f / clipped->vertices[1].w; + projected->textures[2].z = 1.0f / clipped->vertices[2].w; + + projected->vertices[0] = vector4_f_div(projected->vertices[0], projected->vertices[0].w); + projected->vertices[1] = vector4_f_div(projected->vertices[1], projected->vertices[1].w); + projected->vertices[2] = vector4_f_div(projected->vertices[2], projected->vertices[2].w); + + projected->vertices[0] = vector4_f_mul_vector4_f(projected->vertices[0], VECTOR4F_INIT(-1.0f, -1.0f, 1.0f, 1.0f)); + projected->vertices[1] = vector4_f_mul_vector4_f(projected->vertices[1], VECTOR4F_INIT(-1.0f, -1.0f, 1.0f, 1.0f)); + projected->vertices[2] = vector4_f_mul_vector4_f(projected->vertices[2], VECTOR4F_INIT(-1.0f, -1.0f, 1.0f, 1.0f)); + + projected->vertices[0] = vector4_f_add(projected->vertices[0], VECTOR4F_INIT(1.0f, 1.0f, 0.0f, 0.0f)); + projected->vertices[1] = vector4_f_add(projected->vertices[1], VECTOR4F_INIT(1.0f, 1.0f, 0.0f, 0.0f)); + projected->vertices[2] = vector4_f_add(projected->vertices[2], VECTOR4F_INIT(1.0f, 1.0f, 0.0f, 0.0f)); + + projected->vertices[0] = vector4_f_mul_vector4_f(projected->vertices[0], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.0f, 1.0f)); + projected->vertices[1] = vector4_f_mul_vector4_f(projected->vertices[1], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.0f, 1.0f)); + projected->vertices[2] = vector4_f_mul_vector4_f(projected->vertices[2], VECTOR4F_INIT(0.5f * win_x, 0.5f * win_y, 1.0f, 1.0f)); + + projected->vertices[0].z = clipped->vertices[0].z; + projected->vertices[1].z = clipped->vertices[1].z; + projected->vertices[2].z = clipped->vertices[2].z; + + projected->dp = clipped->dp; + + lp_link_append(&(camera->final_meshs), lp_link_create(projected)); +} + + +int graphics_clip_against_plane(vector4f front, vector4f back, triangle_t *intri, triangle_t (*outtri)[2]) +{ + back = vector4_f_normalise(back); + + float d0 = vector4_f_calcul_dist(intri->vertices[0], front, back); + float d1 = vector4_f_calcul_dist(intri->vertices[1], front, back); + float d2 = vector4_f_calcul_dist(intri->vertices[2], front, back); + + vector4f inside_point[3]; int nInsidePointCount = 0; + vector4f outside_point[3]; int nOutsidePointCount = 0; + vector3f inside_texture[3]; int nInsideTextureCount = 0; + vector3f outside_texture[3]; int nOutsideTextureCount = 0; + + if (d0 >= 0) { + inside_point[nInsidePointCount++] = intri->vertices[0]; + inside_texture[nInsideTextureCount++] = intri->textures[0]; + } + else { + outside_point[nOutsidePointCount++] = intri->vertices[0]; + outside_texture[nOutsideTextureCount++] = intri->textures[0]; + } + + if (d1 >= 0) { + inside_point[nInsidePointCount++] = intri->vertices[1]; + inside_texture[nInsideTextureCount++] = intri->textures[1]; + } + else { + outside_point[nOutsidePointCount++] = intri->vertices[1]; + outside_texture[nOutsideTextureCount++] = intri->textures[1]; + } + + if (d2 >= 0) { + inside_point[nInsidePointCount++] = intri->vertices[2]; + inside_texture[nInsideTextureCount++] = intri->textures[2]; + } + else { + outside_point[nOutsidePointCount++] = intri->vertices[2]; + outside_texture[nOutsideTextureCount++] = intri->textures[2]; + } + + + if (!nInsidePointCount) { + return (0); + } + if (nInsidePointCount == 3) { + memcpy(outtri[0], intri, sizeof(*intri)); + return (1); + } + if (nInsidePointCount == 1 && nOutsidePointCount == 2) { + (*outtri)[0].dp = intri->dp; + // (*outtri)[0].usemtl = intri->usemtl; + (*outtri)[0].vertices[0] = inside_point[0]; + (*outtri)[0].textures[0] = inside_texture[0]; + + float t; + (*outtri)[0].vertices[1] = vector4_f_intersect_line(front, back, inside_point[0], outside_point[0], &t); + (*outtri)[0].textures[1].x = t * (outside_texture[0].x - inside_texture[0].x) + inside_texture[0].x; + (*outtri)[0].textures[1].y = t * (outside_texture[0].y - inside_texture[0].y) + inside_texture[0].y; + (*outtri)[0].textures[1].z = t * (outside_texture[0].z - inside_texture[0].z) + inside_texture[0].z; + + (*outtri)[0].vertices[2] = vector4_f_intersect_line(front, back, inside_point[0], outside_point[1], &t); + (*outtri)[0].textures[2].x = t * (outside_texture[1].x - inside_texture[0].x) + inside_texture[0].x; + (*outtri)[0].textures[2].y = t * (outside_texture[1].y - inside_texture[0].y) + inside_texture[0].y; + (*outtri)[0].textures[2].z = t * (outside_texture[1].z - inside_texture[0].z) + inside_texture[0].z; + return (1); + } + if (nInsidePointCount == 2 && nOutsidePointCount == 1) { + float t; + + (*outtri)[0].dp = intri->dp; + // (*outtri)[0].usemtl = intri->usemtl; + (*outtri)[0].vertices[0] = inside_point[0]; (*outtri)[0].textures[0] = inside_texture[0]; + (*outtri)[0].vertices[1] = inside_point[1]; (*outtri)[0].textures[1] = inside_texture[1]; + + (*outtri)[0].vertices[2] = vector4_f_intersect_line(front, back, inside_point[0], outside_point[0], &t); + (*outtri)[0].textures[2].x = t * (outside_texture[0].x - inside_texture[0].x) + inside_texture[0].x; + (*outtri)[0].textures[2].y = t * (outside_texture[0].y - inside_texture[0].y) + inside_texture[0].y; + (*outtri)[0].textures[2].z = t * (outside_texture[0].z - inside_texture[0].y) + inside_texture[0].z; + + (*outtri)[1].dp = intri->dp; + // (*outtri)[1].usemtl = intri->usemtl; + (*outtri)[1].vertices[0] = inside_point[1]; (*outtri)[1].textures[0] = inside_texture[1]; + (*outtri)[1].vertices[1] = (*outtri)[0].vertices[2]; (*outtri)[1].textures[1] = (*outtri)[0].textures[2]; + + (*outtri)[1].vertices[2] = vector4_f_intersect_line(front, back, inside_point[1], outside_point[0], &t); + (*outtri)[1].textures[2].x = t * (outside_texture[0].x -inside_texture[1].x) + inside_texture[1].x; + (*outtri)[1].textures[2].y = t * (outside_texture[0].y -inside_texture[1].y) + inside_texture[1].y; + (*outtri)[1].textures[2].z = t * (outside_texture[0].z - inside_texture[1].y) + inside_texture[1].z; + return (2); + } + return (-1); +} + + +void graphics_clipping(camera_t *camera, triangle_t *viewed) +{ + int nb_triangles = 0; + triangle_t clipped[2]; + + if ((nb_triangles = graphics_clip_against_plane ( + (vector4f){{0.0f, 0.0f, 0.1f, 1.f}}, + (vector4f){{0.0f, 0.0f, 1.0f, 1.f}}, + viewed, &clipped + )) == -1) return; + + for (unsigned i = 0; i < (unsigned) nb_triangles; i++) + graphics_projection_transformation(camera, &clipped[i]); +} + + +void graphics_lighting(camera_t *camera, triangle_t *viewed, vector4f normal) +{ + static float angle = 0.0f; + static sfClock *clock = NULL; + + if (!clock) + clock = sfClock_create(); + + const float rotation_speed = 0.1f * sfTime_asSeconds(sfClock_getElapsedTime(clock)); + + // Rotate the light direction around the Y-axis + float cos_angle = cos(angle); + float sin_angle = sin(angle); + vector4f light_dir = VECTOR4F_INIT(cos_angle, 1.0f, -sin_angle, 1.0f); + + light_dir = vector4_f_normalise(light_dir); + viewed->dp = vector4_f_dot_product(normal, light_dir); + + if (viewed->dp < 0.0f) + viewed->dp = 0.0f; + + graphics_clipping(camera, viewed); + + angle += rotation_speed; + + if (angle > 2.0f * M_PI) + angle -= 2.0f * M_PI; + + sfClock_restart(clock); +} + + +void graphics_viewport_transformation(camera_t *camera, triangle_t transformed, vector4f normal) +{ + triangle_t viewed; + + viewed.vertices[0] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[0]); + viewed.vertices[1] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[1]); + viewed.vertices[2] = matrix4_f_mul_vector4_f(camera->view, transformed.vertices[2]); + + viewed.textures[0] = transformed.textures[0]; + viewed.textures[1] = transformed.textures[1]; + viewed.textures[2] = transformed.textures[2]; + + graphics_lighting(camera, &viewed, normal); +} + + +void graphics_backface_culling(camera_t *camera, mesh_t *mesh) +{ + triangle_t transformed; + link_t *actual = mesh->lTriangle; + triangle_t *triangle = NULL; + + if (!actual) + return; + do { + triangle = (triangle_t *) actual->obj; + + transformed.vertices[0] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[0]); + transformed.vertices[1] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[1]); + transformed.vertices[2] = matrix4_f_mul_vector4_f(mesh->transform, triangle->vertices[2]); + + #ifdef DEBUG + geometry_triangle_print(transformed); + #endif + + vector4f line1 = vector4_f_sub(transformed.vertices[1], transformed.vertices[0]); + vector4f line2 = vector4_f_sub(transformed.vertices[2], transformed.vertices[0]); + vector4f normal = vector4_f_normalise(vector4_f_cross_product(line1, line2)); + vector4f camera_ray = vector4_f_sub(transformed.vertices[0], camera->position); + + if (vector4_f_dot_product(normal, camera_ray) < 0.0f) { + + transformed.textures[0] = triangle->textures[0]; + transformed.textures[1] = triangle->textures[1]; + transformed.textures[2] = triangle->textures[2]; + + graphics_viewport_transformation(camera, transformed, normal); + } + + actual = actual->next; + } while (mesh->lTriangle && actual != mesh->lTriangle); +} + + +// graphics_tesselation (optional) + + +void graphics_world_transformation(camera_t *camera, mesh_t *mesh, float delta_time UNUSED) +{ + if (!mesh) + return; + + // Model to World (M2W) + matrix4f rotate; + matrix4f rotate_y; + matrix4f rotate_x; + matrix4f rotate_z; + matrix4f translate; + matrix4f scale; + + // Rotation matrices : around the z-axis - around the y-axis - around the x-axis + matrix4_f_set_rotate_x(&rotate_x, mesh->rotation.x); + matrix4_f_set_rotate_y(&rotate_y, mesh->rotation.y); + matrix4_f_set_rotate_z(&rotate_z, mesh->rotation.z); + rotate = matrix4_f_mul(rotate_x, rotate_y); + rotate = matrix4_f_mul(rotate, rotate_z); + + #ifdef DEBUG + matrix4_f_print(rotate); + #endif + + // Translation matrix + matrix4_f_set_translate(&translate, mesh->position.x, mesh->position.y, mesh->position.z); + mesh->transform = matrix4_f_mul(rotate, translate); + + // Scaling matrix + matrix4_f_set_scale(&scale, mesh->scale.x, mesh->scale.y, mesh->scale.z); + mesh->transform = matrix4_f_mul(mesh->transform, scale); + + graphics_backface_culling(camera, mesh); +} + + +// graphics_animation (optional) + + +void grapycal_pipeline_apply ( + engine_renderer_t *renderer UNUSED, + camera_t *camera, + link_t *meshs, + float delta_time +) { + link_t *actual = meshs; + mesh_t *mesh = NULL; + + if (!actual) + return; + do { + mesh = (mesh_t *) actual->obj; + graphics_world_transformation(camera, mesh, delta_time); // M2W (Model to World) + actual = actual->next; + } while (meshs && actual != meshs); + + graphics_z_buffering(camera); +} diff --git a/Engine/Engine/Pipelines/graphics_pipeline.h b/Engine/Engine/Pipelines/graphics_pipeline.h new file mode 100644 index 0000000..a45aa49 --- /dev/null +++ b/Engine/Engine/Pipelines/graphics_pipeline.h @@ -0,0 +1,71 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** graphics_pipeline +*/ + +#ifndef GRAPHICS_PIPELINE_H_ +#define GRAPHICS_PIPELINE_H_ + +//////////////////////////////////////////////////////////// +// Include the other headers of the engine module +//////////////////////////////////////////////////////////// +#include "camera.h" +#include "engine_renderer.h" +#include "mesh.h" + +#define SWAP(a, b) { typeof(a) tmp = a; a = b; b = tmp; } + +// graphics_rasterization_by_pixel (optional) +// graphics_texture_mapping (optional) +// graphics_fragment_shader (optional) +// graphics_depth_buffering (optional) +// graphics_alpha_blending (optional) + + +// graphics_rasterization +void graphics_rasterization(engine_renderer_t *renderer, camera_t *camera); + + +// graphics_z_buffering (optional) +void graphics_z_buffering(camera_t *camera); + + +// graphics_projection_transformation (World to Projection) +extern void graphics_projection_transformation(camera_t *camera, triangle_t *clipped); + + +// graphics_clip_against_plane (Clipping) +extern int graphics_clip_against_plane(vector4f front, vector4f back, triangle_t *intri, triangle_t (*outtri)[2]); + + +// graphics_clipping +extern void graphics_clipping(camera_t *camera, triangle_t *viewed); + + +// graphics_lighting +extern void graphics_lighting(camera_t *camera, triangle_t *viewed, vector4f normal); + + +// graphics_viewport_transformation (World to View) +extern void graphics_viewport_transformation(camera_t *camera, triangle_t transformed, vector4f normal); + + +// graphics_backface_culling +extern void graphics_backface_culling(camera_t *camera, mesh_t *mesh); + + +// graphics_tesselation (optional) + + +// graphics_world_transformation (Model to World) +extern void graphics_world_transformation(camera_t *camera, mesh_t *mesh, float delta_time UNUSED); + + +// graphics_animation (optional) + + +extern void grapycal_pipeline_apply(engine_renderer_t *renderer, camera_t *camera, link_t *meshs, float delta_time); + +#endif /* !GRAPHICS_PIPELINE_H_ */ diff --git a/Engine/Engine/Renderer/Window/render_window.h b/Engine/Engine/Renderer/Window/render_window.h index f11955f..35300e7 100644 --- a/Engine/Engine/Renderer/Window/render_window.h +++ b/Engine/Engine/Renderer/Window/render_window.h @@ -133,4 +133,14 @@ extern void window_set_size(render_window_t *window, point_f size); */ extern void window_set_title(render_window_t *window, const char *title); +// /** +// * @brief Set the icon of the window +// * +// * @param window {render_window_t *} - The window module +// * @param width {unsigned int} - The width of the icon +// * @param height {unsigned int} - The height of the icon +// * @param pixels {const sfUint8 *} - The pixels of the icon +// */ +// extern void window_set_icon(render_window_t *window, unsigned int width, unsigned int height, const sfUint8 *pixels; + #endif /* !RENDER_WINDOW_H_ */ diff --git a/Engine/Engine/Renderer/Window/window.c b/Engine/Engine/Renderer/Window/window.c index 3dfcac6..ee9774c 100644 --- a/Engine/Engine/Renderer/Window/window.c +++ b/Engine/Engine/Renderer/Window/window.c @@ -75,6 +75,7 @@ bool window_is_open(render_window_t *window) #elif GRAPHICS_LIBRARY == SDL return true; #elif GRAPHICS_LIBRARY == OPENGL + return true; #endif } @@ -123,6 +124,7 @@ point_f window_get_size(render_window_t *window) SDL_GetWindowSize(window->window, &w, &h); return (point_f){w, h}; #elif GRAPHICS_LIBRARY == OPENGL + return (point_f){0, 0}; #endif } @@ -139,6 +141,7 @@ point_f window_get_position(render_window_t *window) SDL_GetWindowPosition(window->window, &x, &y); return (point_f){x, y}; #elif GRAPHICS_LIBRARY == OPENGL + return (point_f){0, 0}; #endif } diff --git a/Engine/Engine/Renderer/renderer.c b/Engine/Engine/Renderer/renderer.c index 7ffe908..7571f8f 100644 --- a/Engine/Engine/Renderer/renderer.c +++ b/Engine/Engine/Renderer/renderer.c @@ -18,6 +18,7 @@ engine_renderer_t *renderer_init(const char *title, unsigned width, unsigned hei if ((renderer->window = window_create(title, width, height)) == NULL) return (NULL); renderer->vr_mode = vr_mode; + sfRenderWindow_setFramerateLimit(renderer->window->window, 60); return renderer; } diff --git a/Engine/Engine/engine.c b/Engine/Engine/engine.c index 8040d3c..c0eeb3d 100644 --- a/Engine/Engine/engine.c +++ b/Engine/Engine/engine.c @@ -9,9 +9,138 @@ #include "engine.h" +#include +#include +#include +#include +#include +#include + +static char **load_file(char *filename, char *filepath) +{ + struct stat st; + char *file = lp_lib_strcat(filename, filepath); + char *buf = NULL; + int fd = lp_lib_open_file(file, O_RDONLY); + + if (fd == -1) + return (NULL); + stat(file, &st); + if (!(buf = malloc(sizeof(char) * (st.st_size + 1)))) + return (NULL); + if (read(fd, buf, st.st_size) == -1) + return (NULL); + buf[st.st_size] = '\0'; + char **file_content = lp_lib_stwa(buf, "\n"); + free(buf); + free(file); + close(fd); + return file_content; +} + +static engine_game_asset_t engine_game_asset_create(void) +{ + engine_game_asset_t game_asset = {0}; + + char **file_content = load_file("Artisans_Hub.obj", "./Projects/New/Assets/Meshs/mesh_map/OBJ/"); + lp_link_append(&(game_asset.meshs), lp_link_create(parser_obj_create_mesh(file_content))); + lp_lib_two_free(file_content); + return game_asset; +} + +static engine_game_data_t *engine_game_data_create(const char *title, const char *start) +{ + engine_game_data_t *game_data = calloc(1, sizeof(engine_game_data_t)); + if (game_data == NULL) + return (NULL); + // Get directory based on the project name + char project_name[256] = {0}; + sprintf(project_name, "./Projects/%s/Assets/Meshs", title); + + // Get all the scenes in the project + DIR *dir = opendir(project_name); + if (dir == NULL) + return (NULL); + struct dirent *ent; + + // Create the scene map + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') + continue; + printf ("[%s]\n", ent->d_name); + // snprintf(project_name, 256, "./Projects/%s/%s", title, ent->d_name); + // lp_map_append(&(game_data->scenegraph), lp_map_create(strdup(ent->d_name), scene_create(project_name))); + // char scene_name[256] = {0}; + // sprintf(scene_name, "%s/%s", project_name, ent->d_name); + // map_t *scene = parser_xml_load_file(scene_name); + // if (scene == NULL) + // return (NULL); + // map_t *scene_name_map = lp_map_get_at_key(scene, "name", &lp_map_cmp_str); + // if (scene_name_map == NULL) + // return (NULL); + // char *scene_name_str = (char*)scene_name_map->obj; + } + + closedir(dir); + // Get the start scene + game_data->current_scene = strdup(start); + + game_data->camera = camera_create((vector4f){{0, 0, 0, 0}}, (vector4f){{0, 0, 0, 0}}, (vector2f){{1920, 1080}}); + game_data->game_assets = engine_game_asset_create(); + return game_data; +} + +static engine_config_t *engine_config_create(const char *title) +{ + engine_config_t *engine_config = calloc(1, sizeof(engine_config_t)); + if (engine_config == NULL) + return (NULL); + // Get the config file + char project_name[256] = {0}; + sprintf(project_name, "./Projects/%s/config.xml", title); + + // Parse the config file + map_t *config = parser_xml_load_file(project_name); + if (config == NULL) + return (NULL); + + // Get the Info section + map_t *info = lp_map_get_at_key(config, "Info", &lp_map_cmp_str); + if (info == NULL) + return (NULL); + engine_config->info = (engine_info_t) { + .name = (char*)((map_t*)lp_map_get_at_key(info->obj, "name", &lp_map_cmp_str))->obj, + .graphics = (char*)((map_t*)lp_map_get_at_key(info->obj, "graphycal", &lp_map_cmp_str))->obj, + .version = (char*)((map_t*)lp_map_get_at_key(info->obj, "version", &lp_map_cmp_str))->obj, + }; + + // Get the Game section + map_t *game = lp_map_get_at_key(config, "Game", &lp_map_cmp_str); + if (game == NULL) + return (NULL); + engine_config->game = (engine_game_t) { + .width = (char*)((map_t*)lp_map_get_at_key(game->obj, "width", &lp_map_cmp_str))->obj, + .height = (char*)((map_t*)lp_map_get_at_key(game->obj, "height", &lp_map_cmp_str))->obj, + .fps = (char*)((map_t*)lp_map_get_at_key(game->obj, "fps", &lp_map_cmp_str))->obj, + .fullscreen = (char*)((map_t*)lp_map_get_at_key(game->obj, "fullscreen", &lp_map_cmp_str))->obj, + .vsync = (char*)((map_t*)lp_map_get_at_key(game->obj, "vsync", &lp_map_cmp_str))->obj, + .antialiasing = (char*)((map_t*)lp_map_get_at_key(game->obj, "antialiasing", &lp_map_cmp_str))->obj, + .debug = (char*)((map_t*)lp_map_get_at_key(game->obj, "debug", &lp_map_cmp_str))->obj, + }; + + // Get the Scenegraph section + map_t *scenegraph = lp_map_get_at_key(config, "SceneGraph", &lp_map_cmp_str); + if (scenegraph == NULL) + return (NULL); + engine_config->scenegraph = (engine_scenegraph_t) { + .start = (char*)((map_t*)lp_map_get_at_key(scenegraph->obj, "start", &lp_map_cmp_str))->obj, + }; + return engine_config; +} + engine_t *engine_init(const char *title, unsigned width, unsigned height, bool vr) { - engine_t *engine = malloc(sizeof(engine_t)); + engine_t *engine = calloc(1, sizeof(engine_t)); if (engine == NULL) return (NULL); @@ -21,6 +150,10 @@ engine_t *engine_init(const char *title, unsigned width, unsigned height, bool v return (NULL); if ((engine->event = event_create()) == NULL) return (NULL); + if ((engine->config = engine_config_create(title)) == NULL) + return (NULL); + if ((engine->game_data = engine_game_data_create(title, engine->config->scenegraph.start)) == NULL) + return (NULL); return engine; } @@ -37,19 +170,53 @@ void engine_event(engine_t *engine) void engine_update(engine_t *engine) { float deltatime = clock_get_f_delta_time(engine->clock); - (void) deltatime; + + camera_move(engine->game_data->camera, engine->renderer, deltatime); + camera_update(engine->game_data->camera, deltatime); + + grapycal_pipeline_apply ( + engine->renderer, + engine->game_data->camera, + engine->game_data->game_assets.meshs, + deltatime + ); } void engine_render(engine_t *engine) { renderer_clear(engine->renderer); + #ifdef DEBUG + printf("FPS: %f\n", clock_get_fps(engine->clock)); + #endif + graphics_rasterization(engine->renderer, engine->game_data->camera); renderer_display(engine->renderer); } +// void game_assets_destroy(engine_game_asset_t game_assets) +// { +// lp_link_t *tmp = game_assets.meshs; +// while (tmp != NULL) { +// parser_obj_destroy_mesh(tmp->obj); +// tmp = tmp->next; +// } +// } + +// void game_data_destroy(engine_game_data_t *game_data) +// { +// // lp_map_destroy(game_data->scenegraph); +// camera_destroy(game_data->camera); +// game_assets_destroy(game_data->game_assets); +// free(game_data->current_scene); +// free(game_data); +// } + void engine_destroy(engine_t *engine) { clock_destroy(engine->clock); renderer_destroy(engine->renderer); event_destroy(engine->event); + // game_data_destroy(engine->game_data); + // config_destroy(engine->config); + // free(engine->project_name); free(engine); } diff --git a/Engine/Engine/engine.h b/Engine/Engine/engine.h index 86e0f33..1d66012 100644 --- a/Engine/Engine/engine.h +++ b/Engine/Engine/engine.h @@ -22,6 +22,53 @@ #include "engine_renderer.h" #include "engine_event.h" #include "engine_math.h" +#include "camera.h" +#include "graphics_pipeline.h" + +#include "parser_xml.h" +#include "parser_obj.h" +#include "laplace_lib.h" +#include "laplace_link.h" + +typedef struct { + char *name; + char *graphics; + char *version; +} engine_info_t; + +typedef struct { + char *width; + char *height; + char *fps; + char *fullscreen; + char *vsync; + char *antialiasing; + char *debug; +} engine_game_t; + +typedef struct { + char *start; +} engine_scenegraph_t; + +typedef struct { + engine_info_t info; + engine_game_t game; + engine_scenegraph_t scenegraph; +} engine_config_t; + +typedef struct { + map_t *images; + link_t *meshs; + map_t *musics; + map_t *sounds; +} engine_game_asset_t; + +typedef struct { + engine_game_asset_t game_assets; + map_t *scenegraph; + char *current_scene; + camera_t *camera; +} engine_game_data_t; /** * @brief Structure containing the engine module @@ -29,12 +76,15 @@ * @param clock {engine_clock_t *} - The clock module * @param renderer {engine_renderer_t *} - The renderer module * @param event {event_t *} - The event module + * @param config {map_t *} - The config module * @return {engine_t *} - The engine module */ -typedef struct { +typedef struct engine_s { engine_clock_t *clock; engine_renderer_t *renderer; engine_event_t *event; + engine_config_t *config; + engine_game_data_t *game_data; } engine_t; /** diff --git a/Engine/EntityCoponentSystem/ecs.c b/Engine/EntityCoponentSystem/ecs.c new file mode 100644 index 0000000..c8f7afc --- /dev/null +++ b/Engine/EntityCoponentSystem/ecs.c @@ -0,0 +1,167 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** ecs +*/ + +#include +#include +#include +#include + +#include "ecs.h" + +#define INITIAL_CAPACITY 32 + +typedef struct { + uint32_t type_count; + uint32_t cap; + size_t size; + size_t *data_size_array; + size_t *data_offset_array; + void *data; +} ComponentStore; + +typedef struct { + uint32_t *mask_array; + uint32_t *flag_array; + uint32_t count; + uint32_t cap; +} EntityStore; + +typedef struct { + ComponentStore component_store; + EntityStore entity_store; + QueryResult query_result; + ArrayStack *entity_pool; +} State; + +static State state = {0}; + +void +ecs_init(uint32_t n, ...) +{ + uint32_t i; + va_list ap; + size_t sizes[32]; + size_t offsets[32]; + size_t size = 0; + + va_start(ap, n); + for (i = 0; i < n; ++i) { + sizes[i] = va_arg(ap, size_t); + offsets[i] = size; + size += sizes[i]; + } + va_end(ap); + + state.entity_pool = as_create(sizeof(uint32_t)); + + state.component_store.type_count = n; + state.component_store.cap = INITIAL_CAPACITY; + state.component_store.data = malloc(INITIAL_CAPACITY * size); + state.component_store.data_size_array = malloc(n * sizeof(size_t)); + state.component_store.data_offset_array = malloc(n * sizeof(size_t)); + state.component_store.size = size; + memcpy(state.component_store.data_size_array, sizes, n * sizeof(size_t)); + memcpy(state.component_store.data_offset_array, offsets, n * sizeof(size_t)); + + state.entity_store.count = 0; + state.entity_store.cap = INITIAL_CAPACITY; + state.entity_store.mask_array = malloc(INITIAL_CAPACITY * sizeof(uint32_t)); + state.entity_store.flag_array = malloc(INITIAL_CAPACITY * sizeof(uint32_t)); +} + +Entity +ecs_create() +{ + Entity entity; + uint32_t id; + if (state.entity_pool->count > 0) { + id = *(uint32_t*)as_pop(state.entity_pool); + } else { + id = state.entity_store.count++; + if (state.entity_store.cap == id) { + uint32_t *new_flag_array = realloc(state.entity_store.flag_array, state.entity_store.cap * 2 * sizeof(uint32_t)); + uint32_t *new_mask_array = realloc(state.entity_store.mask_array, state.entity_store.cap * 2 * sizeof(uint32_t)); + void *new_data = realloc(state.component_store.data, state.component_store.cap * 2 * state.component_store.size); + uint32_t *new_query_result_list = realloc(state.query_result.list, state.entity_store.cap * 2 * sizeof(uint32_t)); + if (NULL == new_flag_array || NULL == new_mask_array || NULL == new_data || NULL == new_query_result_list) { + printf("Realloc fail %s:%d\n", __FILE__, __LINE__); + exit(1); + } else { + state.entity_store.flag_array = new_flag_array; + state.entity_store.mask_array = new_mask_array; + state.query_result.list = new_query_result_list; + state.entity_store.cap *= 2; + + state.component_store.data = new_data; + state.component_store.cap *= 2; + } + } + } + + state.entity_store.mask_array[id] = 0; + state.entity_store.flag_array[id] = ENTITY_FLAG_ALIVE; + entity.id = id; + return entity; +} + +void * +ecs_get(uint32_t entity_id, uint32_t component_id) +{ + return (uint8_t*)state.component_store.data + (entity_id * state.component_store.size + state.component_store.data_offset_array[component_id]); +} + +void +ecs_add(uint32_t entity_id, uint32_t component_id, void *data) { + size_t size = state.component_store.data_size_array[component_id]; + void *ptr = ecs_get(entity_id, component_id); + state.entity_store.mask_array[entity_id] |= (1 << component_id); + memcpy(ptr, data, size); +} + +void +ecs_remove(uint32_t entity_id, uint32_t component_id) +{ + state.entity_store.mask_array[entity_id] &= ~(1 << component_id); +} + +uint32_t +ecs_has(uint32_t entity_id, uint32_t component_id) +{ + return 0 != (state.entity_store.mask_array[entity_id] & (1 << component_id)); +} + +void +ecs_kill(uint32_t entity_id) +{ + if (0 != (state.entity_store.flag_array[entity_id] & ENTITY_FLAG_ALIVE)) { + state.entity_store.flag_array[entity_id] &= ~ENTITY_FLAG_ALIVE; + state.entity_store.mask_array[entity_id] = 0; + as_push(state.entity_pool, &entity_id); + } +} + +QueryResult * +ecs_query(uint32_t n, ...) +{ + va_list ap; + uint32_t i, mask = 0; + + state.query_result.count = 0; + + va_start(ap, n); + for (i = 0; i < n; ++i) { + mask |= (1 << va_arg(ap, uint32_t)); + } + va_end(ap); + + for (i = 0; i < state.entity_store.count; ++i) { + if (0 != (state.entity_store.flag_array[i] & ENTITY_FLAG_ALIVE) && mask == (state.entity_store.mask_array[i] & mask)) { + state.query_result.list[state.query_result.count++] = i; + } + } + return &state.query_result; +} diff --git a/Engine/EntityCoponentSystem/ecs.h b/Engine/EntityCoponentSystem/ecs.h new file mode 100644 index 0000000..ae45290 --- /dev/null +++ b/Engine/EntityCoponentSystem/ecs.h @@ -0,0 +1,109 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** ecs +*/ + +#ifndef ECS_H_ +#define ECS_H_ + +#define ENTITY_FLAG_ALIVE 1 + +typedef struct { + uint32_t id; +} Entity; + +typedef struct { + uint32_t count; + uint32_t cap; + uint32_t *list; +} QueryResult; + +#define prototype_dynamic_array(type) \ + typedef struct type##_dynamic_container{ \ + type *Data; \ + int Size; \ + void (*append)(struct type##_dynamic_container *this, type value); \ + } type##_dynamic_container; \ + +#define definition_dynamic_container(type) \ + prototype_dynamic_array(type) \ + void type##_dynamic_container_append(type##_dynamic_container *this, type value){ \ + this->Data = realloc(this->Data, (this->Size + 1) * sizeof(type)); \ + this->Data[this->Size++] = value; \ + } \ + type##_dynamic_container *type##_dynamic_container_new(){ \ + type##_dynamic_container *this = malloc(sizeof(type##_dynamic_container)); \ + this->Data = malloc(sizeof(type)); \ + this->Size = 0; \ + this->append = type##_dynamic_container_append; \ + return this; \ + } \ + +#define createDynamic_container(type) type##_dynamic_container_new() +#define dynamic_container(type) type##_dynamic_container + +definition_dynamic_container(int) +definition_dynamic_container(char) + +void main(int ac, char **av) +{ + dynamic_container(int) *my_int_container = createDynamic_container(int); + my_int_container->append(my_int_container, 5); + + printf("%d\n", my_int_container->Data[0]); + + dynamic_container(char) *my_char_container = createDynamic_container(char); + for (char i = 'a'; i <= 'z'; i++) + my_char_container->append(my_char_container, i); + for (int i = 0; i < my_char_container->Size; i++) + printf("%c\n", my_char_container->Data[i]); +} + + +/** + * Initialise the ECS module with the component sizes. + * + * Must pass in the size of each component type in the order you want + * to store them. The maximum number of component types is 32, though + * this could be extended by adding another bitmask and a bit switch. + */ +void ecs_init(uint32_t component_count, ...); + +/** + * Create an entity. Returns a handle which contains the id. + */ +Entity ecs_create(); + +/** + * Get component data from an entity. + */ +void *ecs_get(uint32_t entity_id, uint32_t component_id); + +/** + * Add a component with data to an entity. + */ +void ecs_add(uint32_t entity_id, uint32_t component_id, void *data); + +/** + * Remove a component from an entity. + */ +void ecs_remove(uint32_t entity_id, uint32_t component_id); + +/** + * Returns true if entity has component. + */ +uint32_t ecs_has(uint32_t entity_id, uint32_t component_id); + +/** + * Kill an entity. + */ +void ecs_kill(uint32_t entity_id); + +/** + * Find all entities which have components with IDs. + */ +QueryResult *ecs_query(uint32_t component_count, ...); + +#endif /* !ECS_H_ */ diff --git a/Engine/EntityCoponentSystem/registry.h b/Engine/EntityCoponentSystem/registry.h new file mode 100644 index 0000000..13ac7a5 --- /dev/null +++ b/Engine/EntityCoponentSystem/registry.h @@ -0,0 +1,116 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** registry +*/ + +#ifndef REGISTRY_H_ +#define REGISTRY_H_ + +#include + +//* Utils *// +typedef union { + struct { + float x; + float y; + float z; + }; + struct { + float r; + float g; + float b; + }; + struct { + float u; + float v; + float w; + }; + struct { + float pitch; + float yaw; + float roll; + }; + struct { + float h; + float s; + float v; + }; + struct { + float i; + float j; + float k; + }; + struct { + float width; + float height; + float depth; + } + float position[3]; +} Vector3; + + +//////////////////////////////////////////////////////////// +//* Entity *// +//////////////////////////////////////////////////////////// +typedef struct { + uint32_t id; +} Entity; + + +//////////////////////////////////////////////////////////// +//* Components *// +//////////////////////////////////////////////////////////// +typedef struct { + Vector3 position; + Vector3 rotation; + float scale; +} Tranform; + +typedef struct { + Vector3 color; +} Color; + +typedef struct { + Vector3 velocity; + Vector3 acceleration; +} Movement; + +typedef struct { + float radius; +} SphereCollider; + +typedef struct { + float width; + float height; +} BoxCollider; + + +//////////////////////////////////////////////////////////// +//* Registry *// +//////////////////////////////////////////////////////////// +typedef struct { + uint32_t signature; + uint32_t size; + void *components; +} ComponentArray; + +typedef struct { + uint32_t signature; + uint32_t size; + void *entities; +} EntityArray; + +typedef struct { + uint32_t signature; + uint32_t size; + void *systems; +} SystemArray; + +typedef enum + + +void registry_init(void); + +#endif /* !REGISTRY_H_ */ diff --git a/Engine/Injector/injector.h b/Engine/Injector/injector.h new file mode 100644 index 0000000..7ca0cbf --- /dev/null +++ b/Engine/Injector/injector.h @@ -0,0 +1,125 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-11-27 +** File description: +** injector +*/ + +#ifndef INJECTOR_H_ + #define INJECTOR_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "engine.h" + +extern const char injector_plugin[]; + +typedef void (*injector_init_t)(engine_t *); +extern injector_init_t injector_init; + +typedef void (*injector_update_t)(engine_t *); +extern injector_update_t injector_update; + +typedef void (*injector_clean_t)(engine_t *); +extern injector_clean_t injector_clean; + +/** + * @brief Create a lib object from a file name + * + * @return void* The lib object + */ +void *injector_create_lib(void); + +/** + * @brief Reload a lib object + * + * @param lib_handle The lib object to reload + */ +void *injector_reload_lib(void *lib_handle); + +/** + * @brief Destroy a lib object + * + * @param lib_handle The lib object to destroy + */ +void injector_destroy_lib(void *lib_handle); + +#endif /* !INJECTOR_H_ */ + +#ifdef INJECTOR_IMPLEMENTATION + +#ifdef ENGINE_SYSTEM_WINDOWS +#include +const char injector_plugin[] = "./libinjector.dll"; +#else +#include +const char injector_plugin[] = "./libinjector.so"; +#endif + +injector_init_t injector_init = NULL; +injector_update_t injector_update = NULL; +injector_clean_t injector_clean = NULL; + +void *injector_create_lib(void) +{ + #ifdef ENGINE_SYSTEM_WINDOWS + HMODULE libplug_handle = LoadLibrary(injector_plugin); + if (libplug_handle == NULL) { + fprintf(stderr, "[ERROR]: LoadLibrary(%s): %lu\n", injector_plugin, GetLastError()); + return (NULL); + } + if ((*(void **)(&injector_init) = GetProcAddress(libplug_handle, "_injector_init")) == NULL) { + fprintf(stderr, "[ERROR]: GetProcAddress(%s): %lu\n", injector_plugin, GetLastError()); + return (NULL); + } + if ((*(void **)(&injector_update) = GetProcAddress(libplug_handle, "_injector_update")) == NULL) { + fprintf(stderr, "[ERROR]: GetProcAddress(%s): %lu\n", injector_plugin, GetLastError()); + return (NULL); + } + if ((*(void **)(&injector_clean) = GetProcAddress(libplug_handle, "_injector_clean")) == NULL) { + fprintf(stderr, "[ERROR]: GetProcAddress(%s): %lu\n", injector_plugin, GetLastError()); + return (NULL); + } + #else + //* Load plugin *// + void *libplug_handle = dlopen("/home/laplace/2ème/HUB/Engine-3D/libinjector.so", RTLD_NOW); + if (libplug_handle == NULL) { + fprintf(stderr, "[ERROR]: dlopen(%s): %s\n", injector_plugin, dlerror()); + return (NULL); + } + if ((*(void **)(&injector_init) = dlsym(libplug_handle, "_injector_init")) == NULL) { + fprintf(stderr, "[ERROR]: dlsym(%s): %s\n", injector_plugin, dlerror()); + return (NULL); + } + if ((*(void **)(&injector_update) = dlsym(libplug_handle, "_injector_update")) == NULL) { + fprintf(stderr, "[ERROR]: dlsym(%s): %s\n", injector_plugin, dlerror()); + return (NULL); + } + if ((*(void **)(&injector_clean) = dlsym(libplug_handle, "_injector_clean")) == NULL) { + fprintf(stderr, "[ERROR]: dlsym(%s): %s\n", injector_plugin, dlerror()); + return (NULL); + } + #endif + return libplug_handle; +} + +void *injector_reload_lib(void *lib_handle) +{ + if (lib_handle != NULL) + injector_destroy_lib(lib_handle); + return injector_create_lib(); +} + +void injector_destroy_lib(void *lib_handle) +{ + #ifdef ENGINE_SYSTEM_WINDOWS + FreeLibrary(lib_handle); + #else + dlclose(lib_handle); + #endif +} + +#endif diff --git a/Engine/Mesh/Mouvement/mouvement.h b/Engine/Mesh/Mouvement/mouvement.h new file mode 100644 index 0000000..34f1bf7 --- /dev/null +++ b/Engine/Mesh/Mouvement/mouvement.h @@ -0,0 +1,14 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-12 +** File description: +** mouvement +*/ + +#ifndef MOUVEMENT_H_ +#define MOUVEMENT_H_ + + +#endif /* !MOUVEMENT_H_ */ diff --git a/Engine/Mesh/mesh.h b/Engine/Mesh/mesh.h new file mode 100644 index 0000000..4452267 --- /dev/null +++ b/Engine/Mesh/mesh.h @@ -0,0 +1,49 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-12 +** File description: +** mesh +*/ + +#ifndef MESH_H_ + #define MESH_H_ + +#include "engine_math.h" +#include "laplace_link.h" + +// typedef enum mesh_flags_e { +// TRANSPARENT = 1, // 0b001 +// MOVABLE = 2, // 0b010 +// WATER = 4, // 0b100 +// MESH_SIGNATURE = 0xb00b // 0xdeadbeef +// } mesh_flags; + +/** + * @brief A generic mesh structure + * + * @param lTriangle {link_t *} - A linked list of triangles + * @param nb_triangles {unsigned} - The number of triangles in the mesh + * @param usemtl {texture} - The texture of the mesh (usemtl) + * @param signature {unsigned} - The signature of the mesh + * @param position {vector4f} - The position of the mesh + * @param rotation {vector4f} - The rotation of the mesh + * @param scale {vector4f} - The scale of the mesh + * @param transform {matrix4f} - The transformation matrix of the mesh + * @param alpha {int} - The alpha value of the mesh (0 to 255) + * @return {mesh_t *} - The mesh created + */ +typedef struct { + link_t *lTriangle; + unsigned nb_triangles; + // texture usemtl; + unsigned signature; + vector4f position; + vector4f rotation; + vector4f scale; + matrix4f transform; + int alpha; +} mesh_t; + +#endif /* !MESH_H_ */ diff --git a/Engine/Parser/MTL/parser_mtl.c b/Engine/Parser/MTL/parser_mtl.c new file mode 100644 index 0000000..583c76d --- /dev/null +++ b/Engine/Parser/MTL/parser_mtl.c @@ -0,0 +1,77 @@ +/* +** EPITECH PROJECT, 2023 +** Engine-3D +** File description: +** parser_mtl +*/ + +#include "parser_mtl.h" + +inline mtl_t parser_mtl_create_from_file(char *buffer[]) +{ + mtl_t mtl = {0}; + bool new = true; + + for (; *buffer; buffer++) { + for (unsigned i = 0; mtl_keys[i].key; i++) { + if (!strncmp(*buffer , mtl_keys[i].key, strlen(mtl_keys[i].key))) { + char tmp[256]; + switch (i) { + case 0: + sscanf(*buffer, mtl_keys[i].format, &tmp); + if ((new = !new)) return mtl; + mtl.newmtl = strdup(tmp); + break; + case 1: sscanf(*buffer, mtl_keys[i].format, &mtl.ka.x, &mtl.ka.y, &mtl.ka.z); break; + case 2: sscanf(*buffer, mtl_keys[i].format, &mtl.kd.x, &mtl.kd.y, &mtl.kd.z); break; + case 3: sscanf(*buffer, mtl_keys[i].format, &mtl.ks.x, &mtl.ks.y, &mtl.ks.z); break; + case 4: sscanf(*buffer, mtl_keys[i].format, &mtl.ke.x, &mtl.ke.y, &mtl.ke.z); break; + case 5: sscanf(*buffer, mtl_keys[i].format, &mtl.ni); break; + case 6: sscanf(*buffer, mtl_keys[i].format, &mtl.ns); break; + case 7: sscanf(*buffer, mtl_keys[i].format, &mtl.d); break; + case 8: sscanf(*buffer, mtl_keys[i].format, &mtl.illum); break; + case 9: sscanf(*buffer, mtl_keys[i].format, &tmp); mtl.map_kd = strdup(tmp); break; + case 10: sscanf(*buffer, mtl_keys[i].format, &tmp); mtl.map_ks = strdup(tmp); break; + case 11: sscanf(*buffer, mtl_keys[i].format, &tmp); mtl.map_ka = strdup(tmp); break; + default: printf("Unknown key: %s\n", mtl_keys[i].key); break; + } + break; + } + } + } + return mtl; +} + +inline void parser_mtl_destroy(mtl_t mtl) +{ + free(mtl.newmtl); + if (mtl.map_kd) free(mtl.map_kd); + if (mtl.map_ks) free(mtl.map_ks); + if (mtl.map_ka) free(mtl.map_ka); +} + +inline void parser_mtl_print(mtl_t mtl) +{ + printf("[mtl_t]:\n"); + printf("\tnewmtl %s\n", mtl.newmtl); + printf("\tKa %f %f %f\n", mtl.ka.x, mtl.ka.y, mtl.ka.z); + printf("\tKd %f %f %f\n", mtl.kd.x, mtl.kd.y, mtl.kd.z); + printf("\tKs %f %f %f\n", mtl.ks.x, mtl.ks.y, mtl.ks.z); + printf("\tKe %f %f %f\n", mtl.ke.x, mtl.ke.y, mtl.ke.z); + printf("\tNi %f\nNs %f\nd %f\n", mtl.ni, mtl.ns, mtl.d); + printf("\tillum %d\n", mtl.illum); + if (mtl.map_kd) printf("\tmap_kd %s\n", mtl.map_kd); + if (mtl.map_ks) printf("\tmap_ks %s\n", mtl.map_ks); + if (mtl.map_ka) printf("\tmap_ka %s\n", mtl.map_ka); +} + +void ENGINE_DEPRECATED parser_obj_loop_in_the_file(char *buffer[]) +{ + for (; *buffer; buffer++) { + if (!strncmp(*buffer, "newmtl", 6)) { + mtl_t mtl = parser_mtl_create_from_file(buffer); + parser_mtl_print(mtl); + parser_mtl_destroy(mtl); + } + } +} diff --git a/Engine/Parser/MTL/parser_mtl.h b/Engine/Parser/MTL/parser_mtl.h new file mode 100644 index 0000000..9548feb --- /dev/null +++ b/Engine/Parser/MTL/parser_mtl.h @@ -0,0 +1,125 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** parser_mtl +*/ + +#ifndef PARSER_MTL_H_ + #define PARSER_MTL_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "config.h" + +//////////////////////////////////////////////////////////// +// Include the other headers of the parser module +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Include the headers of the external libraries +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Include necessary headers for the parser_mtl module +//////////////////////////////////////////////////////////// +#include "engine_math.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include +#include + +#ifdef ENGINE_SYSTEM_WINDOWS + #define strdup _strdup +#endif + +/** + * @brief Structure containing material information (mtl) + * + * @param newmtl {char *} - Material name + * @param ka {vector3f} - Ambient color + * @param kd {vector3f} - Diffuse color + * @param ks {vector3f} - Specular color + * @param ke {vector3f} - Emissive color + * @param ni {float} - Optical density + * @param ns {float} - Specular exponent + * @param d {float} - Transparency + * @param illum {float} - Lighting parameters + * @param map_kd {char *} - Texture used for diffuse color + * @param map_ks {char *} - Texture used for specular color + * @param map_ka {char *} - Texture used for ambient color + */ +typedef struct { + char *newmtl; + vector3f ka; + vector3f kd; + vector3f ks; + vector3f ke; + float ni; + float ns; + float d; + int illum; + char *map_kd; + char *map_ks; + char *map_ka; +} mtl_t; + +/** + * @brief Structure containing the keys and their format + * + * @param key {char *} - Key name + * @param format {char *} - Format of the key + */ +const struct mtl_keys_t { + char *key; + char *format; +} mtl_keys[] = { + {"newmtl", "newmtl %s"}, + {"Ka", "Ka %f %f %f"}, + {"Kd", "Kd %f %f %f"}, + {"Ks", "Ks %f %f %f"}, + {"Ke", "Ke %f %f %f"}, + {"Ni", "Ni %f"}, + {"Ns", "Ns %f"}, + {"d", "d %f"}, + {"illum", "illum %d"}, + {"map_Kd", "map_Kd %s"}, + {"map_Ks", "map_Ks %s"}, + {"map_Ka", "map_Ka %s"}, + {NULL, NULL} +}; + +/** + * @brief Create a mtl object from a file + * + * @param buffer {char **} - File buffer containing the mtl + * @return mtl_t {mtl_t} - mtl object + */ +extern inline mtl_t parser_mtl_create_from_file(char *buffer[]); + +/** + * @brief Destroy a mtl object + * + * @param mtl {mtl_t} - mtl object + */ +extern inline void parser_mtl_destroy(mtl_t mtl); + +/** + * @brief Print a mtl object + * + * @param mtl {mtl_t} - mtl object + */ +extern inline void parser_mtl_print(mtl_t mtl); + +#ifdef __cplusplus + } +#endif + +#endif /* !PARSER_MTL_H_ */ diff --git a/Engine/Parser/OBJ/parser_obj.c b/Engine/Parser/OBJ/parser_obj.c new file mode 100644 index 0000000..6887ed5 --- /dev/null +++ b/Engine/Parser/OBJ/parser_obj.c @@ -0,0 +1,97 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** parser_obj +*/ + +#include "parser_obj.h" + +mesh_t *parser_obj_create_mesh(char **buf) +{ + mesh_t *mesh = malloc(sizeof(mesh_t)); + triangle_t *tri, *tri2 = NULL; + char **info = NULL; + size_t nb_chr = 0; + unsigned nb_v = 0, nb_vt = 0; + + if (!mesh || !buf) + return (NULL); + + // mesh->signature = MESH_SIGNATURE; + mesh->position = VECTOR4F_INIT(0, 0, 0, 1.f); + mesh->rotation = VECTOR4F_INIT(0, 0, 0, 1.f); + mesh->scale = VECTOR4F_INIT(1.f, 1.f, 1.f, 1.f); + mesh->transform = matrix4_f_identity(); + mesh->alpha = 255; + + /* count nbr of vectors */ + for (register unsigned i = 0; buf[i]; i++) { + if (buf[i][0] == 'v' && buf[i][1] == ' ') + nb_v++; + else if (buf[i][0] == 'v' && buf[i][1] == 't') + nb_vt++; + } + + /* add vectors in list */ + vector4f list_v[nb_v]; + vector3f list_vt[nb_vt]; + + for (register unsigned i = 0, v = 0, t = 0; buf[i]; i++) { + if (!(info = lp_lib_stwa(buf[i], " \t"))); + else if (info[0][0] == 'v' && info[0][1] == '\0') { + list_v[v] = (vector4f){{atof(info[1]), atof(info[2]), atof(info[3]), 1.f}}; + v++; + } else if (info[0][0] == 'v' && info[0][1] == 't') { + list_vt[t] = (vector3f){{atof(info[1]), atof(info[2]), 1.f}}; + t++; + } + lp_lib_two_free(info); + } + + /* create triangles */ + mesh->lTriangle = NULL; + mesh->nb_triangles = 0; + // char *mtllib = NULL; + // unsigned tex = 0; + + for (register unsigned i = 0; buf[i]; i++) { + if (!(info = lp_lib_stwa(buf[i], " \t/"))); + else if (**info == 'f' && (nb_chr = lp_lib_count_char(buf[i], '/')) != 0) { + tri = malloc(sizeof(triangle_t)); + tri->vertices[0] = list_v[atoi(info[1]) - 1]; + tri->vertices[1] = list_v[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?4:3]) - 1]; + tri->vertices[2] = list_v[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?7:5]) - 1]; + tri->textures[0] = list_vt[atoi(info[2]) - 1]; + tri->textures[1] = list_vt[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?5:4]) - 1]; + tri->textures[2] = list_vt[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?8:6]) - 1]; + // tri->usemtl = tex; + lp_link_append(&(mesh->lTriangle), lp_link_create(tri)); + mesh->nb_triangles++; + if (info[(nb_chr % 3 == 0 && nb_chr != 3)?10:7]) { + tri2 = malloc(sizeof(triangle_t)); + tri2->vertices[0] = list_v[atoi(info[1]) - 1]; + tri2->vertices[1] = list_v[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?7:5]) - 1]; + tri2->vertices[2] = list_v[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?10:7]) - 1]; + tri2->textures[0] = list_vt[atoi(info[2]) - 1]; + tri2->textures[1] = list_vt[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?8:6]) - 1]; + tri2->textures[2] = list_vt[atoi(info[(nb_chr % 3 == 0 && nb_chr != 3)?11:8]) - 1]; + // tri2->usemtl = tex; + lp_link_append(&(mesh->lTriangle), lp_link_create(tri2)); + mesh->nb_triangles++; + } + } + // else if (!strcmp(info[0], "usemtl")) + // tex = search_in_file(info[1], mtllib); + // else if (!strcmp(info[0], "mtllib")) { + // if (mtllib) + // free(mtllib); + // mtllib = strdup(buf[i] + 7); + // } + lp_lib_two_free(info); + } + // free(mtllib); + return mesh; +} diff --git a/Engine/Parser/OBJ/parser_obj.h b/Engine/Parser/OBJ/parser_obj.h new file mode 100644 index 0000000..a087aa6 --- /dev/null +++ b/Engine/Parser/OBJ/parser_obj.h @@ -0,0 +1,27 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** parser_obj +*/ + +#ifndef PARSER_OBJ_H_ + #define PARSER_OBJ_H_ + +//////////////////////////////////////////////////////////// +// Include necessary headers for the parser_obj module +//////////////////////////////////////////////////////////// +#include "mesh.h" +#include "laplace_lib.h" + +/** + * @brief Create a mesh object from a .obj file content + * + * @param buf {char **} - The content of the .obj file + * @return {mesh_t *} - The mesh created + */ +extern mesh_t *parser_obj_create_mesh(char **buf); + +#endif /* !PARSER_OBJ_H_ */ diff --git a/Engine/Parser/XML/parser_xml.c b/Engine/Parser/XML/parser_xml.c new file mode 100644 index 0000000..73e3da0 --- /dev/null +++ b/Engine/Parser/XML/parser_xml.c @@ -0,0 +1,122 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-22 +** File description: +** parser_xml +*/ + +#include "parser_xml.h" + +map_t *parser_xml_load_file(char *pathname) +{ + if (pathname == NULL) + return (NULL); + + char *line = NULL; + size_t len = 0; + ssize_t read; + map_t *attributes = NULL; + char *balise_name = NULL; + + FILE *fp = fopen(pathname, "r"); + + if (fp != NULL) { + bool isComented = false; + bool isMultiline = false; + + while ((read = getline(&line, &len, fp)) != -1) { + /* Skip commented lines */ + if (strstr(line, "")) + continue; + if (strstr(line, "")) + isComented = false; + if (isComented) + continue; + + if (strstr(line, "s>\n") && !isMultiline) + isMultiline = true; + if ((balise_name = strdup(strtok(line, " \t"))) == NULL) + continue; + + char *data_name = NULL; + char *data_value = NULL; + map_t *tokens = NULL; + + #ifdef DEBUG + printf("<%s", balise_name); + #endif + // TODO: manage multiple identical balise_name (ex: ) + while ((data_name = strtok(NULL, " \t=\"\r\n")) != NULL + && (data_value = strtok(NULL, " \t\"<>\r\n")) != NULL) { + #ifdef DEBUG + printf(" %s=\"%s\"", data_name, data_value); + #endif + lp_map_append(&(tokens), lp_map_create(strdup(data_name), strdup(data_value))); + } + if (isMultiline) { + #ifdef DEBUG + printf("/>\n"); + #endif + char *tmp_balise_name = NULL; + while ((read = getline(&line, &len, fp)) != -1) { + if (strstr(line, "")) + isComented = false; + if (isComented) + continue; + if ((tmp_balise_name = strdup(strtok(line, " \t"))) == NULL) + continue; + map_t *tmp_tokens = NULL; + #ifdef DEBUG + printf("\t<%s", balise_name); + #endif + while ((data_name = strtok(NULL, " \t=\"\r\n")) != NULL + && (data_value = strtok(NULL, " \t\"<>\r\n")) != NULL) { + #ifdef DEBUG + printf(" %s=\"%s\"", data_name, data_value); + #endif + lp_map_append(&(tmp_tokens), lp_map_create(strdup(data_name), strdup(data_value))); + } + if (tmp_tokens == NULL) { + #ifdef DEBUG + printf("/>\n"); + #endif + free(tmp_balise_name); + tmp_balise_name = NULL; + continue; + } + #ifdef DEBUG + printf("/>\n"); + #endif + lp_map_append(&(tokens), lp_map_create(tmp_balise_name, tmp_tokens)); + } + isMultiline = false; + } + if (tokens == NULL) { + #ifdef DEBUG + printf(">\n"); + #endif + free(balise_name); + balise_name = NULL; + continue; + } + #ifdef DEBUG + printf("/>\n"); + #endif + lp_map_append(&(attributes), lp_map_create(balise_name, tokens)); + } + fclose(fp); + + if (line) + free(line); + return attributes; + } + return printf("[%s:%u] : Unable to open file\n", __FILE__, __LINE__), (NULL); +} diff --git a/Engine/Parser/XML/parser_xml.h b/Engine/Parser/XML/parser_xml.h new file mode 100644 index 0000000..6feb64c --- /dev/null +++ b/Engine/Parser/XML/parser_xml.h @@ -0,0 +1,81 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-14 +** File description: +** parser_xml +*/ + +#ifndef PARSER_XML_H_ + #define PARSER_XML_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "config.h" + +//////////////////////////////////////////////////////////// +// Include necessary headers for the parser_xml module +//////////////////////////////////////////////////////////// +#include "laplace_map.h" + +#ifdef ENGINE_SYSTEM_WINDOWS + #define strdup _strdup +#endif + +/** + * @brief Load the xml file and store all attributes in a map (see _attributes) + * + * @param pathname the path to the xml file, ex: "GUI/ressources/scene.xml" + */ +extern map_t *parser_xml_load_file(char *pathname); + +// void parser_xml_clear(map_t *map) +// { +// if (!map) +// return; +// lp_map_remove(&(map), map, &lp_map_clean_r); +// } + +/** + * @brief Get the Attribute object from the xml file (one attribute of a tile) + * + * @param pathname ex: "GUI/ressources/scene.xml" + * @param className ex: "Panels" + * @param tileName ex: "Panel" + * @param key ex: "position" + * @return char * ex: "0, 0" + */ +// char *parser_xml_getAttribute(char * pathname, char * className, char * tileName, char * key); + +/** + * @brief Get the Attributes object from the xml file (all attributes of a tile) + * + * @param pathname ex: "GUI/ressources/scene.xml" + * @param tileName ex: "Panel" + * @return std::vector ex: ["0, 0", "0, 0"] + */ +// link_t *parser_xml_getAttributes(char * pathname, char * tileName); + +/** + * @brief Get the Tiles object from the xml file (all tiles of a class) + * + * @param pathname ex: "GUI/ressources/scene.xml" + * @param type ex: "Panel" + * @return std::vector> ex: [{"position": "0, 0"}, {"position": "0, 0"}] + */ +// link_t *> parser_xml_getTiles(char * pathname, char * type); + +/* Path: GUI/ressources/scene.xml + + + +*/ +// map_t>> _attributes; + +#endif /* !PARSER_XML_H_ */ diff --git a/Engine/Parser/parser.h b/Engine/Parser/parser.h new file mode 100644 index 0000000..a0b57aa --- /dev/null +++ b/Engine/Parser/parser.h @@ -0,0 +1,27 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** parser +*/ + +#ifndef PARSER_H_ + #define PARSER_H_ + +//////////////////////////////////////////////////////////// +// Include the other headers of the parser module +//////////////////////////////////////////////////////////// +// #include "ANIM/anim.h" +// #include "JSON/json.h" +#include "MTL/parser_mtl.h" +#include "OBJ/parser_obj.h" +#include "XML/parser_xml.h" + +//////////////////////////////////////////////////////////// +// Include necessary headers for the parser module +//////////////////////////////////////////////////////////// +#include "../Engine/Math/math.h" + +#endif /* !PARSER_H_ */ diff --git a/Engine/Scene/Layers/layers.h b/Engine/Scene/Layers/layers.h new file mode 100644 index 0000000..b540f77 --- /dev/null +++ b/Engine/Scene/Layers/layers.h @@ -0,0 +1,28 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-26 +** File description: +** layers +*/ + +#ifndef LAYERS_H_ + #define LAYERS_H_ + +//////////////////////////////////////////////////////////// +// Include the other headers of the layers module +//////////////////////////////////////////////////////////// + +typedef struct scene_layer_s { + void (*on_attach)(); + void (*on_detach)(); + void (*on_update)(); + void (*on_event)(); + void (*on_render)(); + void (*on_gui_render)(); +} scene_layer_t; + +scene_layer_t *layer_create(); + +#endif /* !LAYERS_H_ */ diff --git a/Engine/Scene/WorldMapper/scene_world_mapper.h b/Engine/Scene/WorldMapper/scene_world_mapper.h new file mode 100644 index 0000000..e9c068c --- /dev/null +++ b/Engine/Scene/WorldMapper/scene_world_mapper.h @@ -0,0 +1,37 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-26 +** File description: +** scene_world_mapper +*/ + +#ifndef SCENE_WORLD_MAPPER_H_ + #define SCENE_WORLD_MAPPER_H_ + +/////////////////////////////////////////////////////////// +// Include the other headers of the world_mapper module +/////////////////////////////////////////////////////////// +// #include "Scene/R-Tree/r_tree.h" + +typedef struct { + unsigned x; + unsigned y; +} chunck_pos_t; + +typedef struct { + chunck_pos_t pos; + void *data; + // r_tree_t *tree; +} chunck_t; + + +typedef struct world_mapper_s { + chunck_t **map; + unsigned width; + unsigned height; + unsigned chunck_size; +} world_mapper_t; + +#endif /* !SCENE_WORLD_MAPPER_H_ */ diff --git a/Engine/Scene/scene.h b/Engine/Scene/scene.h new file mode 100644 index 0000000..6d92f9e --- /dev/null +++ b/Engine/Scene/scene.h @@ -0,0 +1,48 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-11-13 +** File description: +** scene +*/ + +#ifndef SCENE_H_ + #define SCENE_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Include the other headers of the engine module +//////////////////////////////////////////////////////////// + +#include "laplace_link.h" + +/** + * @brief Structure containing the scene module + * + * @return {scene_t *} - The scene module + */ +typedef struct { + link_t *entities; + // world_mapper_t *world_mapper; +} scene_t; + +/** + * @brief Initialize the renderer module + * + * @param dirpath {const char *} - The directory path of the scene + * @return {scene_t *} - The renderer module + */ +extern scene_t *scene_create(const char *dirpath); + +/** + * @brief Destroy the renderer module + * + * @param renderer {scene_t *} - The renderer module + */ +extern void scene_destroy(scene_t *renderer); + +#endif /* !SCENE_H_ */ diff --git a/Engine/ThirdParty/fast-corner-detectors b/Engine/ThirdParty/fast-corner-detectors new file mode 160000 index 0000000..e08f3b5 --- /dev/null +++ b/Engine/ThirdParty/fast-corner-detectors @@ -0,0 +1 @@ +Subproject commit e08f3b5c3845523baf4847b5898804d2e20ec411 diff --git a/Engine/ThirdParty/miniaudio b/Engine/ThirdParty/miniaudio new file mode 160000 index 0000000..b19cc09 --- /dev/null +++ b/Engine/ThirdParty/miniaudio @@ -0,0 +1 @@ +Subproject commit b19cc09fd06b80f370ca4385d260df7e31925b50 diff --git a/Engine/core.c b/Engine/core.c index adf5a31..1c1d276 100644 --- a/Engine/core.c +++ b/Engine/core.c @@ -8,39 +8,81 @@ */ #include "engine.h" -#include +#include "parser_xml.h" + +#define INJECTOR_IMPLEMENTATION +#include "injector.h" + +// #define MONITOR_FOLDER_IMPLEMENTATION +// #include "monitor_folder.h" #ifdef ENGINE_SYSTEM_WINDOWS #include int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { +#elif defined(ENGINE_SYSTEM_MACOS) +int main(int ac, const char *av[], const char *envp[], const char *apple[]) { #else -int main(int ac, const char *av[]) { +int main(int ac, const char *av[], const char *envp[] UNUSED) { #endif // Initialize the game engine and its components. if (ac != 2) { printf("Usage: ./engine.out [config.xml]\n"); return EXIT_FAILURE; } + printf("Loading config file: %s\n", av[1]); printf("Engine version: %s\n", ENGINE_VERSION_STRING); - engine_t *engine = engine_init(av[1], 600, 600, true); // using the xml_parser to load the config file + + engine_t *engine = engine_init(av[1], 1920, 1080, true); // using the xml_parser to load the config file if (engine == NULL) return EXIT_FAILURE; + // Set up any necessary resources, such as the game window and assets. + + #ifdef INJECTOR_IMPLEMENTATION + void *injector_handle = injector_create_lib(); + // int runtime_fd = monitor_folder_create(av[1]); + // add init injector here + injector_init(engine); + #endif + // Game loop while (engine_is_running(engine)) { // Handle events (e.g., user input, window events). engine_event(engine); // Update the game world, physics, AI, etc. - // add update injector here engine_update(engine); + #ifdef INJECTOR_IMPLEMENTATION + // switch (monitor_folder_check_update(runtime_fd)) { + // case 1: + // injector_handle = injector_reload_lib(injector_handle); + // break; + // case -1: + // monitor_folder_destroy(runtime_fd); + // runtime_fd = -1; + // break; + // default: + // break; + // } + // add update injector here + injector_update(engine); + #endif + // Render the game. engine_render(engine); + + clock_restart(engine->clock); } + #ifdef INJECTOR_IMPLEMENTATION + // add destroy injector here + injector_clean(engine); + injector_destroy_lib(injector_handle); + #endif + // Clean up resources and perform any necessary shutdown tasks. engine_destroy(engine); diff --git a/Images/Logo_2-200x200.png b/Images/Logo_2-200x200.png new file mode 100644 index 0000000..73bc3f4 Binary files /dev/null and b/Images/Logo_2-200x200.png differ diff --git a/Images/Logo_2.png b/Images/Logo_2.png new file mode 100644 index 0000000..1bf7b67 Binary files /dev/null and b/Images/Logo_2.png differ diff --git a/Images/Logo_Halloween.png b/Images/Logo_Halloween.png new file mode 100644 index 0000000..1b381ca Binary files /dev/null and b/Images/Logo_Halloween.png differ diff --git a/Launcher/Makefile b/Launcher/Makefile index 7921a7f..771f2cd 100644 --- a/Launcher/Makefile +++ b/Launcher/Makefile @@ -20,8 +20,8 @@ install: @$(ECHO) $(BOLD) $(GREEN)"\n► INSTALL Launcher 📦 !\n"$(DEFAULT) @$(PYTHON) -m pip install --upgrade pip -q @$(PIP) install PyQt5 -q - @$(PIP) freeze | grep -v moddb > ./requirements.txt 2> /dev/null - @$(PIP) install -r ./requirements.txt -q + # @$(PIP) freeze | grep -v moddb > ./requirements.txt 2> /dev/null + # @$(PIP) install -r ./requirements.txt -q @$(ECHO) $(BOLD) $(GREEN)✓$(LIGHT_BLUE)" INSTALL Launcher 📦"$(DEFAULT) lint: diff --git a/Launcher/src/SceneManager.py b/Launcher/src/SceneManager.py index 0dc9b81..85f4ca9 100644 --- a/Launcher/src/SceneManager.py +++ b/Launcher/src/SceneManager.py @@ -23,6 +23,7 @@ def __init__(self, fullscreen: bool=False): self.project_graphycal = '' self.project_name = '' self.project_version = '' + self.vr_mode = False self.InitUI() if self.fullscreen: self.setWindowState(Qt.WindowFullScreen) @@ -53,6 +54,7 @@ def HomePage(self)-> Widgets: layout.addWidget(Widgets.CreateLabel([0, 0], 'Welcome to Engine-3D Launcher')) layout.addWidget(Widgets.CreateButton([0, 0], [0, 0], 'Create a new project', self.ShowCreateProject)) + layout.addWidget(Widgets.CreateButton([0, 0], [0, 0], 'Delete a project', self.ShowFileDialog)) # TODO: Add delete project layout.addWidget(Widgets.CreateButton([0, 0], [0, 0], 'Open a project (config.xml)', self.ShowFileDialog)) self.xml_text = QTextEdit(self) self.xml_text.setReadOnly(True) @@ -72,6 +74,7 @@ def CreateProjectPage(self)-> Widgets: layout.addWidget(Widgets.CreateLineEdit([0, 0], [0, 0], self.ChangeProjectName)) layout.addWidget(Widgets.CreateLabel([0, 0], 'Graphycal API:')) layout.addWidget(Widgets.CreateComboBox([0, 0], [0, 0], ['sdl2', 'CSFML', 'SFML', 'OpenGL', 'Vulkan'], self.ChangeProjectGraphycal)) + layout.addWidget(Widgets.CreateCheckBox([0, 0], [0, 0], 'VR mode', self.ChangeProjectVRMode)) layout.addWidget(Widgets.CreateLabel([0, 0], 'Engine-3D version:')) layout.addWidget(Widgets.CreateComboBox([0, 0], [0, 0], ['0.2.0', '0.1.0'], self.ChangeProjectVersion)) layout.addWidget(Widgets.CreateButton([0, 0], [0, 0], 'Create', self.CreateProject)) @@ -126,15 +129,45 @@ def CreateProject(self): __XML_TEMPLATE__ = f"""\ - - - + + + + """ - filename = f'Projects/{self.project_name}/config.xml' - os.makedirs(os.path.dirname(filename), exist_ok=True) - with open(filename, "w", encoding='utf-8') as file: + __DTD_TEMPLATE__ = """\ + + + + + + + + + + + + + + + + + + + + + + + +""" + + config_name = f'Projects/{self.project_name}/config.xml' + os.makedirs(os.path.dirname(config_name), exist_ok=True) + with open(config_name, "w", encoding='utf-8') as file: file.write(__XML_TEMPLATE__) + config_template = f'Projects/{self.project_name}/config_template.xml' + with open(config_template, "w", encoding='utf-8') as file: + file.write(__DTD_TEMPLATE__) self.project_graphycal = '' self.project_name = '' @@ -193,6 +226,8 @@ def ChangeProjectName(self, name): self.project_name = name def ChangeProjectGraphycal(self, graphycal): self.project_graphycal = graphycal + def ChangeProjectVRMode(self, vr_mode): + self.vr_mode = True if vr_mode == 2 else False def ChangeProjectVersion(self, version): self.project_version = version diff --git a/Launcher/src/__pycache__/ParseArgument.cpython-310.pyc b/Launcher/src/__pycache__/ParseArgument.cpython-310.pyc new file mode 100644 index 0000000..11af8a9 Binary files /dev/null and b/Launcher/src/__pycache__/ParseArgument.cpython-310.pyc differ diff --git a/Launcher/src/__pycache__/SceneManager.cpython-310.pyc b/Launcher/src/__pycache__/SceneManager.cpython-310.pyc new file mode 100644 index 0000000..2586a94 Binary files /dev/null and b/Launcher/src/__pycache__/SceneManager.cpython-310.pyc differ diff --git a/Launcher/src/__pycache__/Widgets.cpython-310.pyc b/Launcher/src/__pycache__/Widgets.cpython-310.pyc new file mode 100644 index 0000000..6b6ef17 Binary files /dev/null and b/Launcher/src/__pycache__/Widgets.cpython-310.pyc differ diff --git a/Libs/LaplaceLib/include/laplace_lib.h b/Libs/LaplaceLib/include/laplace_lib.h index 05b5879..0c638bb 100644 --- a/Libs/LaplaceLib/include/laplace_lib.h +++ b/Libs/LaplaceLib/include/laplace_lib.h @@ -15,7 +15,7 @@ #ifndef LAPLACE_LIB_H_ #define LAPLACE_LIB_H_ - #define auto_clean __attribute__((cleanup(laplace_lib_free))) + #define auto_clean __attribute__((cleanup(lp_lib_free))) //////////////////////////////////////////////////////////// // Include the appropriate header based on the platform used @@ -44,14 +44,14 @@ * @param list {char *} - List of char * @return {int} - Index of the char in the list, -1 if not found */ -extern inline int laplace_lib_char_in_list(char c, char *list); +extern int lp_lib_char_in_list(char c, char *list); /** * @brief Check if the system is little endian * * @return {int} - 1 if little endian, 0 if big endian */ -extern inline int laplace_lib_check_endianness(void); +extern int lp_lib_check_endianness(void); /** * @brief Count the number of char in a string @@ -60,7 +60,7 @@ extern inline int laplace_lib_check_endianness(void); * @param c {char} - Char to count * @return {unsigned} - Number of char in the string */ -extern inline unsigned laplace_lib_count_char(char const *str, char c); +extern unsigned lp_lib_count_char(char const *str, char c); /** * @brief Get the number in a string @@ -68,7 +68,7 @@ extern inline unsigned laplace_lib_count_char(char const *str, char c); * @param str {const char *} - String to get the number from * @return {unsigned} - Number in the string */ -extern inline unsigned laplace_lib_getnbr(char const *str); +extern unsigned lp_lib_getnbr(char const *str); /** * @brief Check if a string is a number @@ -77,15 +77,15 @@ extern inline unsigned laplace_lib_getnbr(char const *str); * @return {true} - if the string is a number * @return {false} - if the string is not a number */ -extern inline bool laplace_lib_is_number(const char *str); +extern bool lp_lib_is_number(const char *str); /** * @brief free a 2d array of string * * @param tab {char **} - the array of string */ -extern inline void laplace_lib_two_free(char **tab); -inline void laplace_lib_free(char **to_free); +extern void lp_lib_two_free(char **tab); +void lp_lib_free(char **to_free); /** * @brief Get the length of a 2d array of string @@ -93,14 +93,14 @@ inline void laplace_lib_free(char **to_free); * @param tab {const char **} - he array of string * @return {unsigned} - the length of the array */ -extern inline unsigned laplace_lib_two_len(const char *tab[]); +extern unsigned lp_lib_two_len(const char *tab[]); /** * @brief Print a 2d array of string * * @param tab {const char **} - the array of string */ -extern inline void laplace_lib_two_print(const char *tab[]); +extern void lp_lib_two_print(const char *tab[]); /** * @brief Open a file and check if it exists @@ -109,7 +109,7 @@ extern inline void laplace_lib_two_print(const char *tab[]); * @param oflag {unsigned} - Open flag (O_RDONLY, O_WRONLY, O_RDWR) * @return {int} - File descriptor */ -extern inline int laplace_lib_open_file(char const *filepath, unsigned oflag); +extern int lp_lib_open_file(char const *filepath, unsigned oflag); /** * @brief Replace a char in a string by another char @@ -118,7 +118,7 @@ extern inline int laplace_lib_open_file(char const *filepath, unsigned oflag); * @param orig {char} - char to replace * @param rep {char} - char to replace with */ -extern inline void laplace_lib_replace_char(char *str, char orig, char rep); +extern void lp_lib_replace_char(char *str, char orig, char rep); /** * @brief Concatenate two strings @@ -127,7 +127,7 @@ extern inline void laplace_lib_replace_char(char *str, char orig, char rep); * @param src {char const *} - String to concatenate * @return {char *} - Concatenated string */ -extern inline char *laplace_lib_strcat(char const *dest, char const *src); +extern char *lp_lib_strcat(char const *dest, char const *src); /** * @brief Create a string array from a string @@ -136,7 +136,7 @@ extern inline char *laplace_lib_strcat(char const *dest, char const *src); * @param delim {const char *} - Delimiter * @return {char **} - String array */ -extern char **laplace_lib_stwa(char *str, const char *delim); +extern char **lp_lib_stwa(char *str, const char *delim); #ifdef __cplusplus } // extern "C" diff --git a/Libs/LaplaceLib/lib_char_in_list.c b/Libs/LaplaceLib/lib_char_in_list.c index e1e3146..5059d0f 100644 --- a/Libs/LaplaceLib/lib_char_in_list.c +++ b/Libs/LaplaceLib/lib_char_in_list.c @@ -7,7 +7,7 @@ ** lib_char_in_list */ -inline int laplace_lib_char_in_list(char c, char *list) +int lp_lib_char_in_list(char c, char *list) { if (!list) return (-1); diff --git a/Libs/LaplaceLib/lib_check_endian.c b/Libs/LaplaceLib/lib_check_endian.c index 9b2b4a3..8122a94 100644 --- a/Libs/LaplaceLib/lib_check_endian.c +++ b/Libs/LaplaceLib/lib_check_endian.c @@ -7,7 +7,7 @@ ** lib_check_endian */ -inline int laplace_lib_check_endianness(void) +int lp_lib_check_endianness(void) { unsigned x = 1; char *c = (char*) &x; diff --git a/Libs/LaplaceLib/lib_count_char.c b/Libs/LaplaceLib/lib_count_char.c index d238f42..b8793dd 100644 --- a/Libs/LaplaceLib/lib_count_char.c +++ b/Libs/LaplaceLib/lib_count_char.c @@ -7,7 +7,7 @@ ** lib_count_char */ -inline unsigned laplace_lib_count_char(char const *str, char c) +unsigned lp_lib_count_char(char const *str, char c) { unsigned nb = 0; diff --git a/Libs/LaplaceLib/lib_getnbr.c b/Libs/LaplaceLib/lib_getnbr.c index 48a6558..a2c713d 100644 --- a/Libs/LaplaceLib/lib_getnbr.c +++ b/Libs/LaplaceLib/lib_getnbr.c @@ -13,7 +13,7 @@ #include #endif -inline unsigned laplace_lib_getnbr(char const *str) +unsigned lp_lib_getnbr(char const *str) { unsigned exp = 0; diff --git a/Libs/LaplaceLib/lib_is_number.c b/Libs/LaplaceLib/lib_is_number.c index 087f4ad..7a523d4 100644 --- a/Libs/LaplaceLib/lib_is_number.c +++ b/Libs/LaplaceLib/lib_is_number.c @@ -13,7 +13,7 @@ #include #endif -inline _Bool laplace_lib_is_number(const char *str) +_Bool lp_lib_is_number(const char *str) { if (!str || !*str) return ((_Bool)+0u); diff --git a/Libs/LaplaceLib/lib_openfile.c b/Libs/LaplaceLib/lib_openfile.c index ecb66c8..dbdb1d5 100644 --- a/Libs/LaplaceLib/lib_openfile.c +++ b/Libs/LaplaceLib/lib_openfile.c @@ -25,7 +25,7 @@ #endif #endif -inline int laplace_lib_open_file(char const *filepath, unsigned oflag) +int lp_lib_open_file(char const *filepath, unsigned oflag) { int fd = open(filepath, oflag); diff --git a/Libs/LaplaceLib/lib_replace_char.c b/Libs/LaplaceLib/lib_replace_char.c index b4a50a5..9951db2 100644 --- a/Libs/LaplaceLib/lib_replace_char.c +++ b/Libs/LaplaceLib/lib_replace_char.c @@ -13,7 +13,7 @@ #include #endif -inline void laplace_lib_replace_char(char *str, char orig, char rep) +void lp_lib_replace_char(char *str, char orig, char rep) { char *ix = str; diff --git a/Libs/LaplaceLib/lib_strcat.c b/Libs/LaplaceLib/lib_strcat.c index e071518..f91c789 100644 --- a/Libs/LaplaceLib/lib_strcat.c +++ b/Libs/LaplaceLib/lib_strcat.c @@ -15,7 +15,7 @@ #include #endif -inline char *laplace_lib_strcat(char const *dest, char const *src) +char *lp_lib_strcat(char const *dest, char const *src) { char *tmp = malloc(sizeof(char) * (strlen(dest) + strlen(src) + 1)); unsigned i = 0; diff --git a/Libs/LaplaceLib/lib_stwa.c b/Libs/LaplaceLib/lib_stwa.c index ae8d637..d8739cc 100644 --- a/Libs/LaplaceLib/lib_stwa.c +++ b/Libs/LaplaceLib/lib_stwa.c @@ -19,7 +19,7 @@ #define strdup(__s) _strdup(__s) #endif -static unsigned laplace_lib_count_words(char *str, const char *delim) +static unsigned lp_lib_count_words(char *str, const char *delim) { char *str_dup = NULL; unsigned count = 0; @@ -34,9 +34,9 @@ static unsigned laplace_lib_count_words(char *str, const char *delim) return count; } -char **laplace_lib_stwa(char *str, const char *delim) +char **lp_lib_stwa(char *str, const char *delim) { - unsigned len = laplace_lib_count_words(str, delim); + unsigned len = lp_lib_count_words(str, delim); char **words = malloc(sizeof(char *) * (len + 1)); char *str_dup = NULL; diff --git a/Libs/LaplaceLib/lib_two_free.c b/Libs/LaplaceLib/lib_two_free.c index 1238edd..14143ac 100644 --- a/Libs/LaplaceLib/lib_two_free.c +++ b/Libs/LaplaceLib/lib_two_free.c @@ -13,9 +13,9 @@ #include #endif -inline void laplace_lib_free(char **to_free) { free(*to_free); } +void lp_lib_free(char **to_free) { free(*to_free); } -inline void laplace_lib_two_free(char **tab) +void lp_lib_two_free(char **tab) { if (!tab) return; diff --git a/Libs/LaplaceLib/lib_two_len.c b/Libs/LaplaceLib/lib_two_len.c index 3b75f31..316f09c 100644 --- a/Libs/LaplaceLib/lib_two_len.c +++ b/Libs/LaplaceLib/lib_two_len.c @@ -7,7 +7,7 @@ ** lib_two_len */ -inline unsigned laplace_lib_two_len(const char *tab[]) +unsigned lp_lib_two_len(const char *tab[]) { unsigned i = 0; diff --git a/Libs/LaplaceLib/lib_two_print.c b/Libs/LaplaceLib/lib_two_print.c index 9cd7177..e8af1de 100644 --- a/Libs/LaplaceLib/lib_two_print.c +++ b/Libs/LaplaceLib/lib_two_print.c @@ -13,7 +13,7 @@ #include #endif -inline void laplace_lib_two_print(const char *tab[]) +void lp_lib_two_print(const char *tab[]) { if (!tab) return; diff --git a/Libs/LaplaceLink/include/laplace_link.h b/Libs/LaplaceLink/include/laplace_link.h index 5726734..0d1bb5d 100644 --- a/Libs/LaplaceLink/include/laplace_link.h +++ b/Libs/LaplaceLink/include/laplace_link.h @@ -54,43 +54,43 @@ typedef struct link_s { } link_t; //* It creates a link with the object passed in parameter. -extern link_t *laplace_link_create(void *_new); +extern link_t *lp_link_create(void *_new); //* It adds a link to the list. -extern void laplace_link_append(link_t **list, link_t *link); +extern void lp_link_append(link_t **list, link_t *link); //* It adds a link to the beginning of the list. -extern void laplace_link_appstart(link_t **list, link_t *link); +extern void lp_link_appstart(link_t **list, link_t *link); //* It apply a function on each link of the list. -extern void laplace_link_do(link_t *list, void (*func)(void *)); +extern void lp_link_do(link_t *list, void (*func)(void *)); //* It duplicates the list. -extern link_t *laplace_link_dup(link_t *list, unsigned __size); +extern link_t *lp_link_dup(link_t *list, unsigned __size); //* It checks if the link is null. -extern bool laplace_link_is_null(link_t *link); +extern bool lp_link_is_null(link_t *link); //* It returns the size of the link. -extern unsigned laplace_link_len(link_t *link); +extern unsigned lp_link_len(link_t *link); //* It prints the list. -extern void laplace_link_print(link_t *list, void (*print)(void *)); +extern void lp_link_print(link_t *list, void (*print)(void *)); //* It removes a link from the list. -extern void laplace_link_remove(link_t **list, link_t *link, void (*free_data)(void *)); +extern void lp_link_remove(link_t **list, link_t *link, void (*free_data)(void *)); //* It sorts the list following the function passed in parameter. -extern void laplace_link_sort(link_t **list, bool (*cmp)(void *, void *)); +extern void lp_link_sort(link_t **list, bool (*cmp)(void *, void *)); //* It swaps the left and right link. -extern void laplace_link_swap(link_t **start, link_t *left, link_t *right); +extern void lp_link_swap(link_t **start, link_t *left, link_t *right); //* It returns the link at the index passed in parameter. -extern link_t *laplace_link_get_at_index(link_t *list, unsigned index); +extern link_t *lp_link_get_at_index(link_t *list, unsigned index); //* It returns the link with the object passed in parameter. -extern link_t *laplace_link_get_at_obj(link_t *list, void *obj); +extern link_t *lp_link_get_at_obj(link_t *list, void *obj); #ifdef __cplusplus } // extern "C" diff --git a/Libs/LaplaceLink/link_append.c b/Libs/LaplaceLink/link_append.c index adce63c..6b84eb2 100644 --- a/Libs/LaplaceLink/link_append.c +++ b/Libs/LaplaceLink/link_append.c @@ -9,21 +9,20 @@ #include "laplace_link.h" -void laplace_link_append(link_t **list, link_t *link) -{ - link_t *start = NULL; +void lp_link_append(link_t **list, link_t *link) { + link_t *start = NULL; - if (!link) - return; - if (!list || !*list) { - link->next = link; - link->prev = link; - *list = link; - return; - } - start = *(list); - link->prev = start->prev; - (start->prev)->next = link; - start->prev = link; - link->next = *list; + if (!link) + return; + if (!list || !*list) { + link->next = link; + link->prev = link; + *list = link; + return; + } + start = *(list); + link->prev = start->prev; + (start->prev)->next = link; + start->prev = link; + link->next = *list; } diff --git a/Libs/LaplaceLink/link_appstart.c b/Libs/LaplaceLink/link_appstart.c index 3b9e5de..168c228 100644 --- a/Libs/LaplaceLink/link_appstart.c +++ b/Libs/LaplaceLink/link_appstart.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -void laplace_link_appstart(link_t **list, link_t *link) +void lp_link_appstart(link_t **list, link_t *link) { link_t *start = *list; link_t *end = (*list)->prev; diff --git a/Libs/LaplaceLink/link_create.c b/Libs/LaplaceLink/link_create.c index 8b02645..ff220fd 100644 --- a/Libs/LaplaceLink/link_create.c +++ b/Libs/LaplaceLink/link_create.c @@ -9,14 +9,14 @@ #include "laplace_link.h" -link_t *laplace_link_create(void *new) +link_t *lp_link_create(void *_new) { link_t *link = malloc(sizeof(link_t)); - if (!link || !new) + if (!link || !_new) return (NULL); - if (new) - link->obj = new; + if (_new) + link->obj = _new; link->next = link; link->prev = link; return link; diff --git a/Libs/LaplaceLink/link_do.c b/Libs/LaplaceLink/link_do.c index e205302..2c2061e 100644 --- a/Libs/LaplaceLink/link_do.c +++ b/Libs/LaplaceLink/link_do.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -void laplace_link_do(link_t *list, void (*func)(void *)) +void lp_link_do(link_t *list, void (*func)(void *)) { link_t *actual = list; diff --git a/Libs/LaplaceLink/link_dup.c b/Libs/LaplaceLink/link_dup.c index 4835277..0969d61 100644 --- a/Libs/LaplaceLink/link_dup.c +++ b/Libs/LaplaceLink/link_dup.c @@ -15,7 +15,7 @@ #include #endif -link_t *laplace_link_dup(link_t *list, unsigned __size) +link_t *lp_link_dup(link_t *list, unsigned __size) { link_t *new = NULL; link_t *actual = list; @@ -26,7 +26,7 @@ link_t *laplace_link_dup(link_t *list, unsigned __size) do { tmp = malloc(__size); memcpy(tmp, actual->obj, __size); - laplace_link_append(&new, laplace_link_create(tmp)); + lp_link_append(&new, lp_link_create(tmp)); actual = actual->next; } while (list && actual != list); return new; diff --git a/Libs/LaplaceLink/link_get_at_index.c b/Libs/LaplaceLink/link_get_at_index.c index 9071b01..3f0377e 100644 --- a/Libs/LaplaceLink/link_get_at_index.c +++ b/Libs/LaplaceLink/link_get_at_index.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -link_t *laplace_link_get_at_index(link_t *link, unsigned index) +link_t *lp_link_get_at_index(link_t *link, unsigned index) { link_t *actual = link; diff --git a/Libs/LaplaceLink/link_get_at_obj.c b/Libs/LaplaceLink/link_get_at_obj.c index 368aabe..f8a0361 100644 --- a/Libs/LaplaceLink/link_get_at_obj.c +++ b/Libs/LaplaceLink/link_get_at_obj.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -link_t *laplace_link_get_at_obj(link_t *link, void *obj) +link_t *lp_link_get_at_obj(link_t *link, void *obj) { link_t *actual = link; diff --git a/Libs/LaplaceLink/link_is_null.c b/Libs/LaplaceLink/link_is_null.c index 11d2e0d..03d2470 100644 --- a/Libs/LaplaceLink/link_is_null.c +++ b/Libs/LaplaceLink/link_is_null.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -bool laplace_link_is_null(link_t *link) +bool lp_link_is_null(link_t *link) { return !link; } diff --git a/Libs/LaplaceLink/link_len.c b/Libs/LaplaceLink/link_len.c index dc3eefc..dc945c5 100644 --- a/Libs/LaplaceLink/link_len.c +++ b/Libs/LaplaceLink/link_len.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -unsigned laplace_link_len(link_t *link) +unsigned lp_link_len(link_t *link) { link_t *actual = link; unsigned count = 0; diff --git a/Libs/LaplaceLink/link_print.c b/Libs/LaplaceLink/link_print.c index 7662150..1ab3619 100644 --- a/Libs/LaplaceLink/link_print.c +++ b/Libs/LaplaceLink/link_print.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -void laplace_link_print(link_t *list, void (*print)(void *)) +void lp_link_print(link_t *list, void (*print)(void *)) { link_t *actual = list; diff --git a/Libs/LaplaceLink/link_remove.c b/Libs/LaplaceLink/link_remove.c index 8333f31..6e0ee3c 100644 --- a/Libs/LaplaceLink/link_remove.c +++ b/Libs/LaplaceLink/link_remove.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -void laplace_link_remove(link_t **list, link_t *link, void (*free_data)(void *)) +void lp_link_remove(link_t **list, link_t *link, void (*free_data)(void *)) { if (!list || !*(list) || !link) return; diff --git a/Libs/LaplaceLink/link_sort.c b/Libs/LaplaceLink/link_sort.c index 25c7684..0f65890 100644 --- a/Libs/LaplaceLink/link_sort.c +++ b/Libs/LaplaceLink/link_sort.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -static void laplace_link_split(link_t *head, link_t **left, link_t **right) +static void lp_link_split(link_t *head, link_t **left, link_t **right) { link_t *slow_ptr = head; link_t *fast_ptr = head->next; @@ -27,7 +27,7 @@ static void laplace_link_split(link_t *head, link_t **left, link_t **right) slow_ptr->next = NULL; } -static link_t *laplace_link_merge(link_t *left, link_t *right, bool (*cmp)(void *, void *)) +static link_t *lp_link_merge(link_t *left, link_t *right, bool (*cmp)(void *, void *)) { link_t *result = NULL; @@ -38,15 +38,15 @@ static link_t *laplace_link_merge(link_t *left, link_t *right, bool (*cmp)(void if (cmp((void *)left->obj, (void *)right->obj)) { result = left; - result->next = laplace_link_merge(left->next, right, cmp); + result->next = lp_link_merge(left->next, right, cmp); } else { result = right; - result->next = laplace_link_merge(left, right->next, cmp); + result->next = lp_link_merge(left, right->next, cmp); } return result; } -static void laplace_link_merge_sort(link_t **list, bool (*cmp)(void *, void *)) +static void lp_link_merge_sort(link_t **list, bool (*cmp)(void *, void *)) { link_t *left = NULL; link_t *right = NULL; @@ -54,20 +54,20 @@ static void laplace_link_merge_sort(link_t **list, bool (*cmp)(void *, void *)) if (*list == NULL || (*list)->next == NULL) return; - laplace_link_split(*list, &left, &right); + lp_link_split(*list, &left, &right); - laplace_link_merge_sort(&left, cmp); - laplace_link_merge_sort(&right, cmp); + lp_link_merge_sort(&left, cmp); + lp_link_merge_sort(&right, cmp); - *list = laplace_link_merge(left, right, cmp); + *list = lp_link_merge(left, right, cmp); } -void laplace_link_sort(link_t **list, bool (*cmp)(void *, void *)) +void lp_link_sort(link_t **list, bool (*cmp)(void *, void *)) { if (*list == NULL || (*list)->next == NULL) return; (*list)->prev->next = NULL; - laplace_link_merge_sort(list, cmp); + lp_link_merge_sort(list, cmp); link_t *actual = (*list); link_t *prev = NULL; diff --git a/Libs/LaplaceLink/link_swap.c b/Libs/LaplaceLink/link_swap.c index 4633ca8..b200e59 100644 --- a/Libs/LaplaceLink/link_swap.c +++ b/Libs/LaplaceLink/link_swap.c @@ -9,7 +9,7 @@ #include "laplace_link.h" -void laplace_link_swap(link_t **start, link_t *left, link_t *right) +void lp_link_swap(link_t **start, link_t *left, link_t *right) { link_t *prev_left = left->prev; link_t *next_right = right->next; diff --git a/Libs/LaplaceMap/include/laplace_map.h b/Libs/LaplaceMap/include/laplace_map.h index f3d10a9..232fccc 100644 --- a/Libs/LaplaceMap/include/laplace_map.h +++ b/Libs/LaplaceMap/include/laplace_map.h @@ -26,20 +26,14 @@ // Include necessary headers for the map library //////////////////////////////////////////////////////////// #ifdef __cplusplus - #include - #include - #include - #include - - using namespace std; extern "C" { -#else - #include - #include - #include - #include #endif +#include +#include +#include +#include + /** * @brief The map structure that contains the key, the object and the link to the next element. * @@ -54,79 +48,79 @@ typedef struct map_s { } map_t; //* It creates a map with the key and the object passed in parameter. -extern map_t *laplace_map_create(void *key, void *obj); +extern map_t *lp_map_create(void *key, void *obj); //* It adds a map to the list. -extern void laplace_map_append(map_t **list, map_t *map); +extern void lp_map_append(map_t **list, map_t *map); //* It adds a map to the beginning of the list. -extern void laplace_map_appstart(map_t **list, map_t *map); +extern void lp_map_appstart(map_t **list, map_t *map); //* It checks if the map is null. -extern bool laplace_map_is_null(map_t *map); +extern bool lp_map_is_null(map_t *map); //* It returns the size of the map. -extern unsigned laplace_map_len(map_t *map); +extern unsigned lp_map_len(map_t *map); //* It prints the list. -extern void laplace_map_print(map_t *list, void (*print)(map_t *)); +extern void lp_map_print(map_t *list, void (*print)(map_t *)); //* It removes a map from the list. -extern void laplace_map_remove(map_t **list, map_t *map, void (*clean_data)(map_t *map)); +extern void lp_map_remove(map_t **list, map_t *map, void (*clean_data)(map_t *map)); //////////////////////////////////////////////////////////// // clean data functions //////////////////////////////////////////////////////////// //* Free an int. -extern void laplace_map_clean_ptr_int(map_t *map); +extern void lp_map_clean_ptr_int(map_t *map); //* Free a float. -extern void laplace_map_clean_ptr_float(map_t *map); +extern void lp_map_clean_ptr_float(map_t *map); //* Free a double. -extern void laplace_map_clean_ptr_double(map_t *map); +extern void lp_map_clean_ptr_double(map_t *map); //* Free a char. -extern void laplace_map_clean_ptr_char(map_t *map); +extern void lp_map_clean_ptr_char(map_t *map); //* Free a string. -extern void laplace_map_clean_ptr_str(map_t *map); +extern void lp_map_clean_ptr_str(map_t *map); //* Free a pointer. -extern void laplace_map_clean_ptr(map_t *map); +extern void lp_map_clean_ptr(map_t *map); //* Free a map_t ... map_t. -extern void laplace_map_clean_r(map_t *map); +extern void lp_map_clean_r(map_t *map); //* It returns the map with the key passed in parameter. -extern map_t *laplace_map_get_at_key(map_t *list, void *key, bool (*cmp)(void *key, void *key2)); +extern map_t *lp_map_get_at_key(map_t *list, void *key, bool (*cmp)(void *key, void *key2)); //////////////////////////////////////////////////////////// // comparison functions //////////////////////////////////////////////////////////// //* Compare two int and return true if they are equal. -extern bool laplace_map_cmp_int(void *a, void *b); +extern bool lp_map_cmp_int(void *a, void *b); //* Compare two float and return true if they are equal. -extern bool laplace_map_cmp_float(void *a, void *b); +extern bool lp_map_cmp_float(void *a, void *b); //* Compare two double and return true if they are equal. -extern bool laplace_map_cmp_double(void *a, void *b); +extern bool lp_map_cmp_double(void *a, void *b); //* Compare two char and return true if they are equal. -extern bool laplace_map_cmp_char(void *a, void *b); +extern bool lp_map_cmp_char(void *a, void *b); //* Compare two string and return true if they are equal. -extern bool laplace_map_cmp_str(void *a, void *b); +extern bool lp_map_cmp_str(void *a, void *b); //* Compare two pointer and return true if they are equal. -extern bool laplace_map_cmp_ptr(void *a, void *b); +extern bool lp_map_cmp_ptr(void *a, void *b); //* Compare two bool and return true if they are equal. -extern bool laplace_map_cmp_bool(void *a, void *b); +extern bool lp_map_cmp_bool(void *a, void *b); #ifdef __cplusplus } // extern "C" diff --git a/Libs/LaplaceMap/map_append.c b/Libs/LaplaceMap/map_append.c index d97fefd..efe6561 100644 --- a/Libs/LaplaceMap/map_append.c +++ b/Libs/LaplaceMap/map_append.c @@ -9,9 +9,9 @@ #include "laplace_map.h" -void laplace_map_append(map_t **list, map_t *map) +void lp_map_append(map_t **list, map_t *map) { - if (!*list && (*list = map)) + if (*list == NULL && (*list = map)) return; map_t *tmp = *list; diff --git a/Libs/LaplaceMap/map_appstart.c b/Libs/LaplaceMap/map_appstart.c index da01dea..faff8a0 100644 --- a/Libs/LaplaceMap/map_appstart.c +++ b/Libs/LaplaceMap/map_appstart.c @@ -9,7 +9,7 @@ #include "laplace_map.h" -void laplace_map_appstart(map_t **list, map_t *map) +void lp_map_appstart(map_t **list, map_t *map) { if (!*list && (*list = map)) return; diff --git a/Libs/LaplaceMap/map_clean_data.c b/Libs/LaplaceMap/map_clean_data.c index 580a842..483cfe5 100644 --- a/Libs/LaplaceMap/map_clean_data.c +++ b/Libs/LaplaceMap/map_clean_data.c @@ -9,43 +9,43 @@ #include "laplace_map.h" -void laplace_map_clean_ptr_int(map_t *map) { +void lp_map_clean_ptr_int(map_t *map) { free((int *)map->key); free((int *)map->obj); } -void laplace_map_clean_ptr_float(map_t *map) { +void lp_map_clean_ptr_float(map_t *map) { free((float *)map->key); free((float *)map->obj); } -void laplace_map_clean_ptr_double(map_t *map) { +void lp_map_clean_ptr_double(map_t *map) { free((double *)map->key); free((double *)map->obj); } -void laplace_map_clean_ptr_char(map_t *map) { +void lp_map_clean_ptr_char(map_t *map) { free((char *)map->key); free((char *)map->obj); } -void laplace_map_clean_ptr_str(map_t *map) { +void lp_map_clean_ptr_str(map_t *map) { free((char *)map->key); free((char *)map->obj); } -void laplace_map_clean_ptr(map_t *map) { +void lp_map_clean_ptr(map_t *map) { free((void *)map->key); free((void *)map->obj); } -void laplace_map_clean_r(map_t *map) +void lp_map_clean_r(map_t *map) { - if (!map->next) { + if (!map->next) { // TODO: Fix this free((char *)map->key); free((char *)map->obj); return; } free((char *)map->key); - laplace_map_remove(&(map), map, &laplace_map_clean_r); + lp_map_remove(&(map), map, &lp_map_clean_r); } diff --git a/Libs/LaplaceMap/map_compare.c b/Libs/LaplaceMap/map_compare.c index daaae7f..3251445 100644 --- a/Libs/LaplaceMap/map_compare.c +++ b/Libs/LaplaceMap/map_compare.c @@ -9,30 +9,30 @@ #include "laplace_map.h" -bool laplace_map_cmp_int(void *a, void *b) { +bool lp_map_cmp_int(void *a, void *b) { return *(int *)a == *(int *)b; } -bool laplace_map_cmp_float(void *a, void *b) { +bool lp_map_cmp_float(void *a, void *b) { return *(float *)a == *(float *)b; } -bool laplace_map_cmp_double(void *a, void *b) { +bool lp_map_cmp_double(void *a, void *b) { return *(double *)a == *(double *)b; } -bool laplace_map_cmp_char(void *a, void *b) { +bool lp_map_cmp_char(void *a, void *b) { return *(char *)a == *(char *)b; } -bool laplace_map_cmp_str(void *a, void *b) { +bool lp_map_cmp_str(void *a, void *b) { return strcmp((char *)a, (char *)b) == 0; } -bool laplace_map_cmp_ptr(void *a, void *b) { +bool lp_map_cmp_ptr(void *a, void *b) { return a == b; } -bool laplace_map_cmp_bool(void *a, void *b) { +bool lp_map_cmp_bool(void *a, void *b) { return *(bool *)a == *(bool *)b; } diff --git a/Libs/LaplaceMap/map_create.c b/Libs/LaplaceMap/map_create.c index daa4c8b..49eab0f 100644 --- a/Libs/LaplaceMap/map_create.c +++ b/Libs/LaplaceMap/map_create.c @@ -9,12 +9,12 @@ #include "laplace_map.h" -map_t *laplace_map_create(void *key, void *obj) +map_t *lp_map_create(void *key, void *obj) { + if (key == NULL || obj == NULL) return (NULL); map_t *map = malloc(sizeof(map_t)); - if (!map) - return (NULL); + if (map == NULL) return (NULL); map->key = key; map->obj = obj; diff --git a/Libs/LaplaceMap/map_get_at_key.c b/Libs/LaplaceMap/map_get_at_key.c index 7484b76..32b6aec 100644 --- a/Libs/LaplaceMap/map_get_at_key.c +++ b/Libs/LaplaceMap/map_get_at_key.c @@ -9,9 +9,36 @@ #include "laplace_map.h" -map_t *laplace_map_get_at_key(map_t *list, void *key, bool (*cmp)(void *, void *)) +map_t *lp_map_get_at_key(map_t *list, void *key, bool (*cmp)(void *, void *)) { - while (list && cmp(list->key, key)) + while (list && !cmp(list->key, key)) list = list->next; return list; } + +/** + * @brief equivalent to lp_map_get_at_key but with multiple keys + * + * @example To get the Info section name of the config file: + * char *keys[] = {"Info", "name", NULL}; + * map_t *info = lp_map_get_at_key(config, &lp_map_cmp_str, keys); + * + * @param list The list to search in + * @param cmp The function to compare the keys + * @param keys The keys to search + * @return { map_t * } - The map at the key + * + * @note The keys must be terminated by a NULL pointer + * @note The keys must be in the same order as the map + */ +map_t *lp_map_get_by_path(map_t *list, bool (*cmp)(void *, void *), char *keys[]) +{ + for (unsigned int i = 0; keys[i]; i++) { + while (list && !cmp(list->key, keys[i])) + list = list->next; + if (list == NULL) + return (NULL); + list = (map_t *)list->obj; + } + return list; +} diff --git a/Libs/LaplaceMap/map_is_null.c b/Libs/LaplaceMap/map_is_null.c index 51745f7..ad0fa40 100644 --- a/Libs/LaplaceMap/map_is_null.c +++ b/Libs/LaplaceMap/map_is_null.c @@ -9,7 +9,7 @@ #include "laplace_map.h" -bool laplace_map_is_null(map_t *map) +bool lp_map_is_null(map_t *map) { return !map; } diff --git a/Libs/LaplaceMap/map_len.c b/Libs/LaplaceMap/map_len.c index 75712b3..66e5fc3 100644 --- a/Libs/LaplaceMap/map_len.c +++ b/Libs/LaplaceMap/map_len.c @@ -9,7 +9,7 @@ #include "laplace_map.h" -unsigned laplace_map_len(map_t *map) +unsigned lp_map_len(map_t *map) { unsigned len = 0; diff --git a/Libs/LaplaceMap/map_print.c b/Libs/LaplaceMap/map_print.c index 7cbda3d..0e72406 100644 --- a/Libs/LaplaceMap/map_print.c +++ b/Libs/LaplaceMap/map_print.c @@ -9,7 +9,7 @@ #include "laplace_map.h" -void laplace_map_print(map_t *list, void (*print)(map_t *)) +void lp_map_print(map_t *list, void (*print)(map_t *)) { printf("[map_t]:\n"); while (list) { diff --git a/Libs/LaplaceMap/map_remove.c b/Libs/LaplaceMap/map_remove.c index e679c08..ebfc2f5 100644 --- a/Libs/LaplaceMap/map_remove.c +++ b/Libs/LaplaceMap/map_remove.c @@ -9,7 +9,7 @@ #include "laplace_map.h" -void laplace_map_remove(map_t **list, map_t *map, void (*clean_data)(map_t *map)) +void lp_map_remove(map_t **list, map_t *map, void (*clean_data)(map_t *map)) { if (!*list) return; diff --git a/Libs/LaplaceString/include/laplace_string.h b/Libs/LaplaceString/include/laplace_string.h new file mode 100644 index 0000000..ebf949d --- /dev/null +++ b/Libs/LaplaceString/include/laplace_string.h @@ -0,0 +1,178 @@ +/************************************************************************** + * Laplace String Library v1.0.0 + * + * Laplace String Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace String Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_STRING_H_ + #define LAPLACE_STRING_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "laplace_string_config.h" +#include "laplace_string_version.h" + +//////////////////////////////////////////////////////////// +// Include necessary headers for the string library +//////////////////////////////////////////////////////////// +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include +#include +#include + +/** + * @brief The string structure that contains the string and its length. + * + * @param str The string. + * @param len The length of the string. + */ +typedef struct string_s { + char *str; + unsigned len; +} string_t; + +//* It creates a string from a char *. +extern string_t *lp_string_create(char *str) { + string_t *string = malloc(sizeof(string_t)); + if (string == NULL) { + printf("[Laplace@String]: Error while allocating memory for string.\n"); + return (NULL); + } + if (str == NULL) { + string->str = NULL; + string->len = 0; + return string; + } + string->str = str; + string->len = strlen(str); + return string; +} + +//* It adds a char to the string. +extern void lp_string_char_append(string_t *string, char c) +{ + if (string == NULL) { + printf("[Laplace@String]: Error while appending char to string.\n"); + return; + } + string->str = realloc(string->str, string->len + 2); + if (string->str == NULL) { + printf("[Laplace@String]: Error while appending char to string.\n"); + return; + } + string->str[string->len] = c; + string->str[string->len + 1] = '\0'; + string->len++; +} + +//* It adds a char to the beginning of the string. +extern void lp_string_char_appstart(string_t *string, char c) +{ + if (string == NULL) { + printf("[Laplace@String]: Error while appending char to string.\n"); + return; + } + string->str = realloc(string->str, string->len + 2); + if (string->str == NULL) { + printf("[Laplace@String]: Error while appending char to string.\n"); + return; + } + for (unsigned i = string->len; i > 0; i--) + string->str[i] = string->str[i - 1]; + string->str[0] = c; + string->str[string->len + 1] = '\0'; + string->len++; +} + +//* It adds a string to the string. +extern void lp_string_concat(string_t *string1, string_t *string2) +{ + if (string1 == NULL || string2 == NULL) { + printf("[Laplace@String]: Error while concatenating strings.\n"); + return; + } + string1->str = realloc(string1->str, string1->len + string2->len + 1); + if (string1->str == NULL) { + printf("[Laplace@String]: Error while concatenating strings.\n"); + return; + } + strcat(string1->str, string2->str); + string1->len += string2->len; +} + +//* It erases a part of the string. +extern void lp_string_erase(string_t *string, unsigned start, unsigned end) +{ + if (string == NULL) { + printf("[Laplace@String]: Error while erasing string.\n"); + return; + } + if (start > string->len || end > string->len) { + printf("[Laplace@String]: Error while erasing string.\n"); + return; + } + if (start > end) { + printf("[Laplace@String]: Error while erasing string.\n"); + return; + } + unsigned len = end - start; + for (unsigned i = start; i < string->len - len; i++) + string->str[i] = string->str[i + len]; + string->str = realloc(string->str, string->len - len + 1); + if (string->str == NULL) { + printf("[Laplace@String]: Error while erasing string.\n"); + return; + } // + string->str[string->len - len] = '\0'; + string->len -= len; +} + +//* It checks if the string is null. +extern bool lp_string_is_null(string_t *string) +{ + return (string == NULL); +} + +//* It returns the size of the string. +extern unsigned lp_string_len(string_t *string) +{ + if (string == NULL) { + printf("[Laplace@String]: Error while getting string length.\n"); + return (0); + } + return (string->len); +} + +//* It prints the string. +extern void lp_string_print(string_t *list) +{ + if (list == NULL) { + printf("[Laplace@String]: Error while printing string.\n"); + return; + } + #if defined(LAPLACE_STRING_SYSTEM_WINDOWS) + printf("%s\r\n", list->str); + #else + printf("%s\n", list->str); + #endif +} + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif/* !LAPLACE_STRING_H_ */ diff --git a/Libs/LaplaceString/include/laplace_string_config.h b/Libs/LaplaceString/include/laplace_string_config.h new file mode 100644 index 0000000..7c78ef6 --- /dev/null +++ b/Libs/LaplaceString/include/laplace_string_config.h @@ -0,0 +1,132 @@ +/************************************************************************** + * Laplace String Library v1.0.0 + * + * Laplace String Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace String Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_STRING_CONFIG_H_ + #define LAPLACE_STRING_CONFIG_H_ + +//////////////////////////////////////////////////////////// +// Check if we need to mark functions as extern "C" +//////////////////////////////////////////////////////////// +#ifdef __cplusplus + #define LAPLACE_STRING_EXTERN_C extern "C" +#else + #define LAPLACE_STRING_EXTERN_C extern +#endif + + +//////////////////////////////////////////////////////////// +// Identify the operating system +//////////////////////////////////////////////////////////// +#if defined(_WIN32) || defined(__WIN32__) + + // Windows + #define LAPLACE_STRING_SYSTEM_WINDOWS + +#elif defined(linux) || defined(__linux) + + // Linux + #define LAPLACE_STRING_SYSTEM_LINUX + +#elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh) + + // MacOS + #define LAPLACE_STRING_SYSTEM_MACOS + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + + // FreeBSD + #define LAPLACE_STRING_SYSTEM_FREEBSD + +#else + + // Unsupported system + #error [Laplace@String@config]: This operating system is not supported by LAPLACE STRING library. + +#endif + + +//////////////////////////////////////////////////////////// +// Define helpers to create portable import / export macros for each module +//////////////////////////////////////////////////////////// +#if defined(LAPLACE_STRING_SYSTEM_WINDOWS) + + // Windows compilers need specific (and different) keywords for export and import + #define LAPLACE_STRING_API_EXPORT extern "C" __declspec(dllexport) + #define LAPLACE_STRING_API_IMPORT LAPLACE_STRING_EXTERN_C __declspec(dllimport) + + // For Visual C++ compilers, we also need to turn off this annoying C4251 warning + #ifdef _MSC_VER + + #pragma warning(disable : 4251) + + #endif + +#else // Linux, FreeBSD, Mac OS X + + #if __GNUC__ >= 4 + + // GCC 4 has special keywords for showing/hidding symbols, + // the same keyword is used for both importing and exporting + #define LAPLACE_STRING_API_EXPORT extern "C" __attribute__ ((__visibility__ ("default"))) + #define LAPLACE_STRING_API_IMPORT LAPLACE_STRING_EXTERN_C __attribute__ ((__visibility__ ("default"))) + + #else + + // GCC < 4 has no mechanism to explicitely hide symbols, everything's exported + #define LAPLACE_STRING_API_EXPORT extern "C" + #define LAPLACE_STRING_API_IMPORT LAPLACE_STRING_EXTERN_C + + #endif + +#endif + +//////////////////////////////////////////////////////////// +// Cross-platform warning for deprecated functions and classes +// +// @example: +// struct LAPLACE_STRING_DEPRECATED MyStruct +// { +// ... +// }; +// +// LAPLACE_STRING_DEPRECATED void global_func(); +//////////////////////////////////////////////////////////// +#if defined(LAPLACE_STRING_NO_DEPRECATED_WARNINGS) + + // User explicitly requests to disable deprecation warnings + #define LAPLACE_STRING_DEPRECATED + +#elif defined(_MSC_VER) + + // Microsoft C++ compiler + // Note: On newer MSVC versions, using deprecated functions causes a compiler error. In order to + // trigger a warning instead of an error, the compiler flag /sdl- (instead of /sdl) must be specified. + #define LAPLACE_STRING_DEPRECATED __declspec(deprecated) + +#elif defined(__GNUC__) + + // g++ and Clang + #define LAPLACE_STRING_DEPRECATED __attribute__ ((deprecated)) + +#else + + // Other compilers are not supported, leave class or function as-is. + // With a bit of luck, the #pragma directive works, otherwise users get a warning (no error!) for unrecognized #pragma. + #pragma message("LAPLACE_STRING_DEPRECATED is not supported for your compiler, please contact the LAPLACE_STRING team") + #define LAPLACE_STRING_DEPRECATED + +#endif + +#endif /* !LAPLACE_STRING_CONFIG_H_ */ diff --git a/Libs/LaplaceString/include/laplace_string_version.h b/Libs/LaplaceString/include/laplace_string_version.h new file mode 100644 index 0000000..7847e42 --- /dev/null +++ b/Libs/LaplaceString/include/laplace_string_version.h @@ -0,0 +1,31 @@ +/************************************************************************** + * Laplace String Library v1.0.0 + * + * Laplace String Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace String Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_STRING_VERSION_H_ + #define LAPLACE_STRING_VERSION_H_ + +//////////////////////////////////////////////////////////// +// Define the LAPLACE_STRING version +//////////////////////////////////////////////////////////// +#define LAPLACE_STRING_VERSION_MAJOR 1 +#define LAPLACE_STRING_VERSION_MINOR 0 +#define LAPLACE_STRING_VERSION_PATCH 0 + +//////////////////////////////////////////////////////////// +// Define the LAPLACE_STRING version string +//////////////////////////////////////////////////////////// +#define LAPLACE_STRING_VERSION_STRING "1.0.0" + +#endif /* !LAPLACE_STRING_VERSION_H_ */ diff --git a/Libs/LaplaceString/string_char_append.c b/Libs/LaplaceString/string_char_append.c new file mode 100644 index 0000000..e69de29 diff --git a/Libs/LaplaceVector/include/laplace_vector.h b/Libs/LaplaceVector/include/laplace_vector.h new file mode 100644 index 0000000..6b86b2c --- /dev/null +++ b/Libs/LaplaceVector/include/laplace_vector.h @@ -0,0 +1,132 @@ +/************************************************************************** + * Laplace Vector Library v1.0.0 + * + * Laplace Vector Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace Vector Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_VECTOR_H_ + #define LAPLACE_VECTOR_H_ + +//////////////////////////////////////////////////////////// +// Include the appropriate header based on the platform used +//////////////////////////////////////////////////////////// +#include "laplace_vector_config.h" +#include "laplace_vector_version.h" + +//////////////////////////////////////////////////////////// +// Include necessary headers for the vector library +//////////////////////////////////////////////////////////// +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include + +#ifndef LV_CALLOC + + #if defined(LAPLACE_VECTOR_SYSTEM_WINDOWS) + #include + #define LV_CALLOC calloc + #else + #include + #define LV_CALLOC calloc + #endif +#endif /* !LV_CALLOC */ + +/** + * @brief The vector structure that contains the vector and its length. + * + */ +typedef struct vector_s { + size_t len; + unsigned sizeof_data; + void *data; +} vector_t; + +/** + * @brief It creates a vector with a specific size of data. + * + * std::vector first; // empty vector of ints + */ +extern vector_t lp_vector_create(unsigned sizeof_data) +{ + vector_t vector; + vector.len = 0; + vector.sizeof_data = sizeof_data; + vector.data = NULL; + return vector; +} + +/** + * @brief It creates a vector with a specific length of data filled with data. + * + * @param sizeof_data The size of the data. + * @param len The length of the vector. + * @param data The data to put in the vector. + * + * std::vector second (4,100); // four ints with value 100 + */ +extern vector_t lp_vector_create_with_length(unsigned sizeof_data, size_t len, void *data) +{ + vector_t vector; + vector.len = len; + vector.sizeof_data = sizeof_data; + vector.data = LV_CALLOC(len, sizeof_data); + for (size_t i = 0; i < len; i++) { + vector.data += i * sizeof_data; + vector.data = data; + } + return vector; +} + +/** + * @brief It creates a vector with from a begin to an end of another vector. + * + * std::vector third (second.begin(),second.end()); // iterating through second + */ +extern vector_t lp_vector_create_with_begin_end(vector_t vector, size_t begin, size_t end) +{ + vector_t new_vector; + new_vector.len = end - begin; + new_vector.sizeof_data = vector.sizeof_data; + new_vector.data = LV_CALLOC(new_vector.len, vector.sizeof_data); + for (size_t i = 0; i < new_vector.len; i++) { + new_vector.data += i * vector.sizeof_data; + new_vector.data = vector.data + (begin + i) * vector.sizeof_data; + } + return new_vector; +} + +/** + * @brief It creates a vector from another vector. + * + * std::vector fourth (third); // a copy of third + */ +extern vector_t lp_vector_create_with_vector(vector_t vector) +{ + vector_t new_vector; + new_vector.len = vector.len; + new_vector.sizeof_data = vector.sizeof_data; + new_vector.data = LV_CALLOC(new_vector.len, vector.sizeof_data); + for (size_t i = 0; i < new_vector.len; i++) { + new_vector.data += i * vector.sizeof_data; + new_vector.data = vector.data + i * vector.sizeof_data; + } + return new_vector; +} + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif/* !LAPLACE_VECTOR_H_ */ diff --git a/Libs/LaplaceVector/include/laplace_vector_config.h b/Libs/LaplaceVector/include/laplace_vector_config.h new file mode 100644 index 0000000..226731f --- /dev/null +++ b/Libs/LaplaceVector/include/laplace_vector_config.h @@ -0,0 +1,132 @@ +/************************************************************************** + * Laplace Vector Library v1.0.0 + * + * Laplace Vector Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace Vector Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_VECTOR_CONFIG_H_ + #define LAPLACE_VECTOR_CONFIG_H_ + +//////////////////////////////////////////////////////////// +// Check if we need to mark functions as extern "C" +//////////////////////////////////////////////////////////// +#ifdef __cplusplus + #define LAPLACE_VECTOR_EXTERN_C extern "C" +#else + #define LAPLACE_VECTOR_EXTERN_C extern +#endif + + +//////////////////////////////////////////////////////////// +// Identify the operating system +//////////////////////////////////////////////////////////// +#if defined(_WIN32) || defined(__WIN32__) + + // Windows + #define LAPLACE_VECTOR_SYSTEM_WINDOWS + +#elif defined(linux) || defined(__linux) + + // Linux + #define LAPLACE_VECTOR_SYSTEM_LINUX + +#elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh) + + // MacOS + #define LAPLACE_VECTOR_SYSTEM_MACOS + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + + // FreeBSD + #define LAPLACE_VECTOR_SYSTEM_FREEBSD + +#else + + // Unsupported system + #error [Laplace@Vector@config]: This operating system is not supported by LAPLACE VECTOR library. + +#endif + + +//////////////////////////////////////////////////////////// +// Define helpers to create portable import / export macros for each module +//////////////////////////////////////////////////////////// +#if defined(LAPLACE_VECTOR_SYSTEM_WINDOWS) + + // Windows compilers need specific (and different) keywords for export and import + #define LAPLACE_VECTOR_API_EXPORT extern "C" __declspec(dllexport) + #define LAPLACE_VECTOR_API_IMPORT LAPLACE_VECTOR_EXTERN_C __declspec(dllimport) + + // For Visual C++ compilers, we also need to turn off this annoying C4251 warning + #ifdef _MSC_VER + + #pragma warning(disable : 4251) + + #endif + +#else // Linux, FreeBSD, Mac OS X + + #if __GNUC__ >= 4 + + // GCC 4 has special keywords for showing/hidding symbols, + // the same keyword is used for both importing and exporting + #define LAPLACE_VECTOR_API_EXPORT extern "C" __attribute__ ((__visibility__ ("default"))) + #define LAPLACE_VECTOR_API_IMPORT LAPLACE_VECTOR_EXTERN_C __attribute__ ((__visibility__ ("default"))) + + #else + + // GCC < 4 has no mechanism to explicitely hide symbols, everything's exported + #define LAPLACE_VECTOR_API_EXPORT extern "C" + #define LAPLACE_VECTOR_API_IMPORT LAPLACE_VECTOR_EXTERN_C + + #endif + +#endif + +//////////////////////////////////////////////////////////// +// Cross-platform warning for deprecated functions and classes +// +// @example: +// struct LAPLACE_VECTOR_DEPRECATED MyStruct +// { +// ... +// }; +// +// LAPLACE_VECTOR_DEPRECATED void global_func(); +//////////////////////////////////////////////////////////// +#if defined(LAPLACE_VECTOR_NO_DEPRECATED_WARNINGS) + + // User explicitly requests to disable deprecation warnings + #define LAPLACE_VECTOR_DEPRECATED + +#elif defined(_MSC_VER) + + // Microsoft C++ compiler + // Note: On newer MSVC versions, using deprecated functions causes a compiler error. In order to + // trigger a warning instead of an error, the compiler flag /sdl- (instead of /sdl) must be specified. + #define LAPLACE_VECTOR_DEPRECATED __declspec(deprecated) + +#elif defined(__GNUC__) + + // g++ and Clang + #define LAPLACE_VECTOR_DEPRECATED __attribute__ ((deprecated)) + +#else + + // Other compilers are not supported, leave class or function as-is. + // With a bit of luck, the #pragma directive works, otherwise users get a warning (no error!) for unrecognized #pragma. + #pragma message("LAPLACE_VECTOR_DEPRECATED is not supported for your compiler, please contact the LAPLACE_VECTOR team") + #define LAPLACE_VECTOR_DEPRECATED + +#endif + +#endif /* !LAPLACE_VECTOR_CONFIG_H_ */ diff --git a/Libs/LaplaceVector/include/laplace_vector_version.h b/Libs/LaplaceVector/include/laplace_vector_version.h new file mode 100644 index 0000000..afa89b0 --- /dev/null +++ b/Libs/LaplaceVector/include/laplace_vector_version.h @@ -0,0 +1,37 @@ +/************************************************************************** + * Laplace Vector Library v1.0.0 + * + * Laplace Vector Library is a library that contains a lot of useful + * functions for C programming. It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Laplace Vector Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-10-14 + **************************************************************************/ + +#ifndef LAPLACE_VECTOR_VERSION_H_ + #define LAPLACE_VECTOR_VERSION_H_ + +//////////////////////////////////////////////////////////// +// Define the LAPLACE_VECTOR version +//////////////////////////////////////////////////////////// +#define LAPLACE_VECTOR_VERSION_MAJOR 1 +#define LAPLACE_VECTOR_VERSION_MINOR 0 +#define LAPLACE_VECTOR_VERSION_PATCH 0 + +//////////////////////////////////////////////////////////// +// Define the LAPLACE_VECTOR version string +//////////////////////////////////////////////////////////// +#define STRINGIFY(x) STRINGIFY_(x) +#define STRINGIFY_(x) #x + +#define LAPLACE_VECTOR_VERSION_VECTOR \ + STRINGIFY(LAPLACE_VECTOR_VERSION_MAJOR) "." \ + STRINGIFY(LAPLACE_VECTOR_VERSION_MINOR) "." \ + STRINGIFY(LAPLACE_VECTOR_VERSION_PATCH) + +#endif /* !LAPLACE_VECTOR_VERSION_H_ */ diff --git a/Libs/Makefile b/Libs/Makefile index 59aeece..05d1646 100644 --- a/Libs/Makefile +++ b/Libs/Makefile @@ -58,6 +58,7 @@ CFLAGS = -Wall -Wpedantic $(INCLUDE_LLIB) $(INCLUDE_LLINK) $(INCLUDE_LMAP) $(INC LDFLAGS = -L. -lLaplaceLib -lLaplaceLink -lLaplaceMap -lLaplaceError FASTFLAGS = -Ofast -march=native -mtune=native -fomit-frame-pointer \ -fopenmp -fprefetch-loop-arrays -pipe +# FASTFLAGS = -g3 -ggdb all: $(NAME_LLIB) $(NAME_LLINK) $(NAME_LMAP) $(NAME_LERROR) diff --git a/Libs/README.md b/Libs/README.md index 5846c18..6512b6f 100644 --- a/Libs/README.md +++ b/Libs/README.md @@ -37,10 +37,10 @@ Status: complete ✅ **Laplace Lib Library v1.0.0** is a comprehensive C library that offers a wide range of functions for various common programming tasks. Designed for ease of use and seamless integration into diverse projects, this library is a valuable resource for C developers. It is developed and maintained by MasterLaplace. Key features of Laplace Lib Library include: -- **String Manipulation**: Functions like `laplace_lib_count_char` to count occurrences of a character in a string, `laplace_lib_getnbr` for extracting numbers from strings, and `laplace_lib_is_number` to check if a string is numeric. -- **File Handling**: The library provides `laplace_lib_open_file` to open files with customizable access flags. -- **String Operations**: Functions such as `laplace_lib_replace_char` for replacing characters in strings and `laplace_lib_strcat` for string concatenation. -- **Array Management**: It offers the ability to free 2D arrays of strings using `laplace_lib_two_free`, along with functions for obtaining the length of 2D arrays and printing them. +- **String Manipulation**: Functions like `lp_lib_count_char` to count occurrences of a character in a string, `lp_lib_getnbr` for extracting numbers from strings, and `lp_lib_is_number` to check if a string is numeric. +- **File Handling**: The library provides `lp_lib_open_file` to open files with customizable access flags. +- **String Operations**: Functions such as `lp_lib_replace_char` for replacing characters in strings and `lp_lib_strcat` for string concatenation. +- **Array Management**: It offers the ability to free 2D arrays of strings using `lp_lib_two_free`, along with functions for obtaining the length of 2D arrays and printing them. - **Cross-Platform Compatibility**: The library includes appropriate header files based on the platform in use. The Laplace Lib Library is distributed under the MIT License, making it accessible for various applications. It is version **1.0.0**, and this documentation was last updated on **October 13, 2023**. @@ -54,7 +54,7 @@ The Laplace Lib Library is distributed under the MIT License, making it accessib Key features of Laplace Link Library include: - **Linked List Structure**: The library defines the `link_t` struct to represent individual links in the linked list. -- **Link Operations**: Functions like `laplace_link_create` to create links with objects, `laplace_link_append` for adding links to the list, and `laplace_link_remove` for removing links from the list. +- **Link Operations**: Functions like `lp_link_create` to create links with objects, `lp_link_append` for adding links to the list, and `lp_link_remove` for removing links from the list. - **List Operations**: Functions for duplicating lists, checking if a link is null, determining the size of the list, and obtaining links by index or by the object they contain. - **Sorting and Swapping**: It provides functions for sorting the list based on custom comparison functions and for swapping links within the list. - **Cross-Platform Compatibility**: The library includes appropriate header files based on the platform in use. @@ -70,7 +70,7 @@ The Laplace Link Library is distributed under the MIT License, making it accessi Key features of Laplace Map Library include: - **Hash Map Structure**: The library defines the `map_t` struct to represent individual key-value pairs in the hash map. -- **Map Operations**: Functions like `laplace_map_create` to create maps with objects, `laplace_map_append` for adding pairs to the map, and `laplace_map_remove` for removing pairs from the map. +- **Map Operations**: Functions like `lp_map_create` to create maps with objects, `lp_map_append` for adding pairs to the map, and `lp_map_remove` for removing pairs from the map. - **List Operations**: Functions for checking if a pair is null, determining the size of the map, and obtaining pairs by the key they contain. - **Cross-Platform Compatibility**: The library includes appropriate header files based on the platform in use. diff --git a/Libs/tests/test_lib/lib_char_in_list_test.c b/Libs/tests/test_lib/lib_char_in_list_test.c index ce61913..4b1d8bf 100644 --- a/Libs/tests/test_lib/lib_char_in_list_test.c +++ b/Libs/tests/test_lib/lib_char_in_list_test.c @@ -9,36 +9,36 @@ #include -int laplace_lib_char_in_list(char c, char *list); +int lp_lib_char_in_list(char c, char *list); -Test(laplace_lib_char_in_list_01, should_return_true) +Test(lp_lib_char_in_list_01, should_return_true) { char a = 'H'; char *list = "Hello"; - cr_assert_neq(laplace_lib_char_in_list(a, list), (-1)); + cr_assert_neq(lp_lib_char_in_list(a, list), (-1)); } -Test(laplace_lib_char_in_list_02, should_return_false) +Test(lp_lib_char_in_list_02, should_return_false) { char a = 'H'; char *list = "World"; - cr_assert_eq(laplace_lib_char_in_list(a, list), (-1)); + cr_assert_eq(lp_lib_char_in_list(a, list), (-1)); } -Test(laplace_lib_char_in_list_03, should_return_false) +Test(lp_lib_char_in_list_03, should_return_false) { char a = 'H'; char *list = ""; - cr_assert_eq(laplace_lib_char_in_list(a, list), (-1)); + cr_assert_eq(lp_lib_char_in_list(a, list), (-1)); } -Test(laplace_lib_char_in_list_04, should_return_false) +Test(lp_lib_char_in_list_04, should_return_false) { char a = 'H'; char *list = NULL; - cr_assert_eq(laplace_lib_char_in_list(a, list), (-1)); + cr_assert_eq(lp_lib_char_in_list(a, list), (-1)); } diff --git a/Libs/tests/test_lib/lib_check_endian_test.c b/Libs/tests/test_lib/lib_check_endian_test.c index 3b5a68d..7a8c292 100644 --- a/Libs/tests/test_lib/lib_check_endian_test.c +++ b/Libs/tests/test_lib/lib_check_endian_test.c @@ -9,14 +9,14 @@ #include -int laplace_lib_check_endianness(void); +int lp_lib_check_endianness(void); Test(check_endian_01, should_return_true) { - cr_assert_eq(laplace_lib_check_endianness(), 1); + cr_assert_eq(lp_lib_check_endianness(), 1); } Test(check_endian_02, should_return_false) { - cr_assert_neq(laplace_lib_check_endianness(), 0); + cr_assert_neq(lp_lib_check_endianness(), 0); } diff --git a/Libs/tests/test_lib/lib_count_char_test.c b/Libs/tests/test_lib/lib_count_char_test.c index 544f543..634f9ea 100644 --- a/Libs/tests/test_lib/lib_count_char_test.c +++ b/Libs/tests/test_lib/lib_count_char_test.c @@ -15,76 +15,76 @@ #include #endif -unsigned laplace_lib_count_char(char const *str, char c); +unsigned lp_lib_count_char(char const *str, char c); -Test(laplace_lib_count_char_01, should_return_true) +Test(lp_lib_count_char_01, should_return_true) { char *str = "Hello World"; char c = 'o'; - cr_assert_eq(laplace_lib_count_char(str, c), 2); + cr_assert_eq(lp_lib_count_char(str, c), 2); } -Test(laplace_lib_count_char_02, should_return_false) +Test(lp_lib_count_char_02, should_return_false) { char *str = "Hello World"; char c = 'a'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_03, should_return_false) +Test(lp_lib_count_char_03, should_return_false) { char *str = "Hello World"; char c = ' '; - cr_assert_eq(laplace_lib_count_char(str, c), 1); + cr_assert_eq(lp_lib_count_char(str, c), 1); } -Test(laplace_lib_count_char_04, should_return_false) +Test(lp_lib_count_char_04, should_return_false) { char *str = "Hello World"; char c = '\0'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_05, should_return_false) +Test(lp_lib_count_char_05, should_return_false) { char *str = "Hello World"; char c = '\n'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_06, should_return_false) +Test(lp_lib_count_char_06, should_return_false) { char *str = "Hello World"; char c = '\t'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_07, should_return_false) +Test(lp_lib_count_char_07, should_return_false) { char *str = ""; char c = 'H'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_08, should_return_false) +Test(lp_lib_count_char_08, should_return_false) { char *str = NULL; char c = 'H'; - cr_assert_eq(laplace_lib_count_char(str, c), 0); + cr_assert_eq(lp_lib_count_char(str, c), 0); } -Test(laplace_lib_count_char_09, should_return_false) +Test(lp_lib_count_char_09, should_return_false) { char *str = "Hello World"; char c = 'l'; - cr_assert_eq(laplace_lib_count_char(str, c), 3); + cr_assert_eq(lp_lib_count_char(str, c), 3); } diff --git a/Libs/tests/test_lib/lib_getnbr_test.c b/Libs/tests/test_lib/lib_getnbr_test.c index 4dbbc54..c73a997 100644 --- a/Libs/tests/test_lib/lib_getnbr_test.c +++ b/Libs/tests/test_lib/lib_getnbr_test.c @@ -9,74 +9,74 @@ #include -unsigned laplace_lib_getnbr(char const *str); +unsigned lp_lib_getnbr(char const *str); -Test(laplace_lib_getnbr_01, should_return_true) +Test(lp_lib_getnbr_01, should_return_true) { char *str = "Hello World"; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } -Test(laplace_lib_getnbr_02, should_return_false) +Test(lp_lib_getnbr_02, should_return_false) { char *str = "Hello 150"; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } -Test(laplace_lib_getnbr_03, should_return_false) +Test(lp_lib_getnbr_03, should_return_false) { char *str = "Hello -150"; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } -Test(laplace_lib_getnbr_04, should_return_false) +Test(lp_lib_getnbr_04, should_return_false) { char *str = "150 World"; - cr_assert_eq(laplace_lib_getnbr(str), 150); + cr_assert_eq(lp_lib_getnbr(str), 150); } -Test(laplace_lib_getnbr_05, should_return_false) +Test(lp_lib_getnbr_05, should_return_false) { char *str = "-150 World"; - cr_assert_eq(laplace_lib_getnbr(str), (-150)); + cr_assert_eq(lp_lib_getnbr(str), (-150)); } -Test(laplace_lib_getnbr_06, should_return_false) +Test(lp_lib_getnbr_06, should_return_false) { char *str = "Hello 150 World"; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } -Test(laplace_lib_getnbr_07, should_return_false) +Test(lp_lib_getnbr_07, should_return_false) { char *str = "-150"; - cr_assert_eq(laplace_lib_getnbr(str), (-150)); + cr_assert_eq(lp_lib_getnbr(str), (-150)); } -Test(laplace_lib_getnbr_08, should_return_false) +Test(lp_lib_getnbr_08, should_return_false) { char *str = "150"; - cr_assert_eq(laplace_lib_getnbr(str), 150); + cr_assert_eq(lp_lib_getnbr(str), 150); } -Test(laplace_lib_getnbr_09, should_return_false) +Test(lp_lib_getnbr_09, should_return_false) { char *str = NULL; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } -Test(laplace_lib_getnbr_10, should_return_false) +Test(lp_lib_getnbr_10, should_return_false) { char *str = ""; - cr_assert_eq(laplace_lib_getnbr(str), 0); + cr_assert_eq(lp_lib_getnbr(str), 0); } diff --git a/Libs/tests/test_lib/lib_is_number_test.c b/Libs/tests/test_lib/lib_is_number_test.c index 2860bc8..12cb952 100644 --- a/Libs/tests/test_lib/lib_is_number_test.c +++ b/Libs/tests/test_lib/lib_is_number_test.c @@ -15,81 +15,81 @@ #include #endif -bool laplace_lib_is_number(char const *str); +bool lp_lib_is_number(char const *str); -Test(laplace_lib_is_number_01, should_return_false) +Test(lp_lib_is_number_01, should_return_false) { char *str = "Hello World"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_02, should_return_false) +Test(lp_lib_is_number_02, should_return_false) { char *str = "Hello 150"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_03, should_return_false) +Test(lp_lib_is_number_03, should_return_false) { char *str = "Hello -150"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_04, should_return_false) +Test(lp_lib_is_number_04, should_return_false) { char *str = "150 World"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_05, should_return_false) +Test(lp_lib_is_number_05, should_return_false) { char *str = "-150 World"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_06, should_return_false) +Test(lp_lib_is_number_06, should_return_false) { char *str = "Hello 150 World"; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_07, should_return_true) +Test(lp_lib_is_number_07, should_return_true) { char *str = "-150"; - cr_assert_eq(laplace_lib_is_number(str), true); + cr_assert_eq(lp_lib_is_number(str), true); } -Test(laplace_lib_is_number_08, should_return_true) +Test(lp_lib_is_number_08, should_return_true) { char *str = "150"; - cr_assert_eq(laplace_lib_is_number(str), true); + cr_assert_eq(lp_lib_is_number(str), true); } -Test(laplace_lib_is_number_09, should_return_true) +Test(lp_lib_is_number_09, should_return_true) { char *str = "0"; - cr_assert_eq(laplace_lib_is_number(str), true); + cr_assert_eq(lp_lib_is_number(str), true); } -Test(laplace_lib_is_number_10, should_return_false) +Test(lp_lib_is_number_10, should_return_false) { char *str = NULL; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } -Test(laplace_lib_is_number_11, should_return_false) +Test(lp_lib_is_number_11, should_return_false) { char *str = ""; - cr_assert_eq(laplace_lib_is_number(str), false); + cr_assert_eq(lp_lib_is_number(str), false); } diff --git a/Libs/tests/test_lib/lib_openfile_test.c b/Libs/tests/test_lib/lib_openfile_test.c index 7c04bef..b9037e5 100644 --- a/Libs/tests/test_lib/lib_openfile_test.c +++ b/Libs/tests/test_lib/lib_openfile_test.c @@ -18,11 +18,11 @@ #include #endif -int laplace_lib_open_file(char const *filepath, unsigned oflag); +int lp_lib_open_file(char const *filepath, unsigned oflag); -Test(laplace_lib_open_file_01, laplace_lib_open_file_test) +Test(lp_lib_open_file_01, lp_lib_open_file_test) { - int fd = laplace_lib_open_file("tests/test_my/.file.txt", O_RDONLY); + int fd = lp_lib_open_file("tests/test_my/.file.txt", O_RDONLY); cr_assert_neq(fd, -1); close(fd); diff --git a/Libs/tests/test_lib/lib_replace_char_test.c b/Libs/tests/test_lib/lib_replace_char_test.c index 8a37706..8b900b4 100644 --- a/Libs/tests/test_lib/lib_replace_char_test.c +++ b/Libs/tests/test_lib/lib_replace_char_test.c @@ -15,108 +15,108 @@ #include #endif -void laplace_lib_replace_char(char *str, char orig, char rep); +void lp_lib_replace_char(char *str, char orig, char rep); -Test(laplace_lib_replace_char_01, should_return_true) +Test(lp_lib_replace_char_01, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'o', 'a'); + lp_lib_replace_char(str, 'o', 'a'); cr_assert_str_eq(str, "Hella Warld"); } -Test(laplace_lib_replace_char_02, should_return_true) +Test(lp_lib_replace_char_02, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'l', 'a'); + lp_lib_replace_char(str, 'l', 'a'); cr_assert_str_eq(str, "Heaao Worad"); } -Test(laplace_lib_replace_char_03, should_return_true) +Test(lp_lib_replace_char_03, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'H', 'a'); + lp_lib_replace_char(str, 'H', 'a'); cr_assert_str_eq(str, "aello World"); } -Test(laplace_lib_replace_char_04, should_return_true) +Test(lp_lib_replace_char_04, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'W', 'a'); + lp_lib_replace_char(str, 'W', 'a'); cr_assert_str_eq(str, "Hello aorld"); } -Test(laplace_lib_replace_char_05, should_return_true) +Test(lp_lib_replace_char_05, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'd', 'a'); + lp_lib_replace_char(str, 'd', 'a'); cr_assert_str_eq(str, "Hello Worla"); } -Test(laplace_lib_replace_char_06, should_return_true) +Test(lp_lib_replace_char_06, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, ' ', 'a'); + lp_lib_replace_char(str, ' ', 'a'); cr_assert_str_eq(str, "HelloaWorld"); } -Test(laplace_lib_replace_char_07, should_return_true) +Test(lp_lib_replace_char_07, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'H', ' '); + lp_lib_replace_char(str, 'H', ' '); cr_assert_str_eq(str, " ello World"); } -Test(laplace_lib_replace_char_08, should_return_true) +Test(lp_lib_replace_char_08, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'W', ' '); + lp_lib_replace_char(str, 'W', ' '); cr_assert_str_eq(str, "Hello orld"); } -Test(laplace_lib_replace_char_09, should_return_true) +Test(lp_lib_replace_char_09, should_return_true) { char *str = NULL; - laplace_lib_replace_char(str, 'W', ' '); + lp_lib_replace_char(str, 'W', ' '); cr_assert_eq(str, NULL); } -Test(laplace_lib_replace_char_10, should_return_true) +Test(lp_lib_replace_char_10, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, 'W', '\0'); + lp_lib_replace_char(str, 'W', '\0'); cr_assert_str_eq(str, "Hello "); } -Test(laplace_lib_replace_char_11, should_return_true) +Test(lp_lib_replace_char_11, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, '\0', ' '); + lp_lib_replace_char(str, '\0', ' '); cr_assert_str_eq(str, "Hello World"); } -Test(laplace_lib_replace_char_12, should_return_true) +Test(lp_lib_replace_char_12, should_return_true) { char str[] = "Hello World"; - laplace_lib_replace_char(str, '\0', '\0'); + lp_lib_replace_char(str, '\0', '\0'); cr_assert_str_eq(str, "Hello World"); } -Test(laplace_lib_replace_char_13, should_return_true) +Test(lp_lib_replace_char_13, should_return_true) { char str[] = ""; - laplace_lib_replace_char(str, 'W', ' '); + lp_lib_replace_char(str, 'W', ' '); cr_assert_str_eq(str, ""); } diff --git a/Libs/tests/test_lib/lib_strcat_test.c b/Libs/tests/test_lib/lib_strcat_test.c index 06ab22a..bf2755e 100644 --- a/Libs/tests/test_lib/lib_strcat_test.c +++ b/Libs/tests/test_lib/lib_strcat_test.c @@ -17,59 +17,59 @@ #include #endif -char *laplace_lib_strcat(char const *dest, char const *src); +char *lp_lib_strcat(char const *dest, char const *src); -Test(laplace_lib_strcat_01, should_return_concatenated_string) +Test(lp_lib_strcat_01, should_return_concatenated_string) { char *dest = "Hello"; char *src = "World"; char *expected = "WorldHello"; - char *actual = laplace_lib_strcat(dest, src); + char *actual = lp_lib_strcat(dest, src); cr_assert_str_eq(actual, expected); free(actual); } -Test(laplace_lib_strcat_02, should_return_concatenated_string) +Test(lp_lib_strcat_02, should_return_concatenated_string) { char *dest = "Hello"; char *src = " World"; char *expected = "Hello World"; - char *actual = laplace_lib_strcat(dest, src); + char *actual = lp_lib_strcat(dest, src); cr_assert_str_neq(actual, expected); free(actual); } -Test(laplace_lib_strcat_03, should_return_concatenated_string) +Test(lp_lib_strcat_03, should_return_concatenated_string) { char *dest = " World"; char *src = "Hello"; char *expected = "Hello World"; - char *actual = laplace_lib_strcat(dest, src); + char *actual = lp_lib_strcat(dest, src); cr_assert_str_eq(actual, expected); free(actual); } -Test(laplace_lib_strcat_04, should_return_concatenated_string) +Test(lp_lib_strcat_04, should_return_concatenated_string) { char *dest = "Hello"; char *src = ""; char *expected = "Hello"; - char *actual = laplace_lib_strcat(dest, src); + char *actual = lp_lib_strcat(dest, src); cr_assert_str_eq(actual, expected); free(actual); } -Test(laplace_lib_strcat_05, should_return_concatenated_string) +Test(lp_lib_strcat_05, should_return_concatenated_string) { char *dest = ""; char *src = "Hello"; char *expected = "Hello"; - char *actual = laplace_lib_strcat(dest, src); + char *actual = lp_lib_strcat(dest, src); cr_assert_str_eq(actual, expected); free(actual); } diff --git a/Libs/tests/test_lib/lib_stwa_test.c b/Libs/tests/test_lib/lib_stwa_test.c index 4471d32..fb7253d 100644 --- a/Libs/tests/test_lib/lib_stwa_test.c +++ b/Libs/tests/test_lib/lib_stwa_test.c @@ -17,9 +17,9 @@ #include #endif -char **laplace_lib_stwa(char *str, const char *delim); +char **lp_lib_stwa(char *str, const char *delim); -Test(laplace_lib_stwa_01, should_return_array_of_strings) +Test(lp_lib_stwa_01, should_return_array_of_strings) { char *str = "Hello World"; char *delim = " "; @@ -28,7 +28,7 @@ Test(laplace_lib_stwa_01, should_return_array_of_strings) expected[1] = "World"; expected[2] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_str_eq(actual[1], expected[1]); cr_assert_eq(actual[2], expected[2]); @@ -37,7 +37,7 @@ Test(laplace_lib_stwa_01, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_02, should_return_array_of_strings) +Test(lp_lib_stwa_02, should_return_array_of_strings) { char *str = "Hello \tWorld"; char *delim = " \t"; @@ -46,7 +46,7 @@ Test(laplace_lib_stwa_02, should_return_array_of_strings) expected[1] = "World"; expected[2] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_str_eq(actual[1], expected[1]); cr_assert_eq(actual[2], expected[2]); @@ -55,7 +55,7 @@ Test(laplace_lib_stwa_02, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_03, should_return_array_of_strings) +Test(lp_lib_stwa_03, should_return_array_of_strings) { char *str = "Hello World"; char *delim = " \t"; @@ -64,7 +64,7 @@ Test(laplace_lib_stwa_03, should_return_array_of_strings) expected[1] = "World"; expected[2] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_str_eq(actual[1], expected[1]); cr_assert_eq(actual[2], expected[2]); @@ -73,7 +73,7 @@ Test(laplace_lib_stwa_03, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_04, should_return_array_of_strings) +Test(lp_lib_stwa_04, should_return_array_of_strings) { char *str = "\tHello\t World "; char *delim = " \t"; @@ -82,7 +82,7 @@ Test(laplace_lib_stwa_04, should_return_array_of_strings) expected[1] = "World"; expected[2] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_str_eq(actual[1], expected[1]); cr_assert_eq(actual[2], expected[2]); @@ -91,7 +91,7 @@ Test(laplace_lib_stwa_04, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_05, should_return_array_of_strings) +Test(lp_lib_stwa_05, should_return_array_of_strings) { char *str = "HelloWorld"; char *delim = " \t"; @@ -99,7 +99,7 @@ Test(laplace_lib_stwa_05, should_return_array_of_strings) expected[0] = "HelloWorld"; expected[1] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_eq(actual[1], expected[1]); for (unsigned i = 0; actual[i]; i++) { free(actual[i]); } @@ -107,7 +107,7 @@ Test(laplace_lib_stwa_05, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_06, should_return_array_of_strings) +Test(lp_lib_stwa_06, should_return_array_of_strings) { char *str = "HelloWorld"; char *delim = ""; @@ -115,7 +115,7 @@ Test(laplace_lib_stwa_06, should_return_array_of_strings) expected[0] = "HelloWorld"; expected[1] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_eq(actual[1], expected[1]); for (unsigned i = 0; actual[i]; i++) { free(actual[i]); } @@ -123,17 +123,17 @@ Test(laplace_lib_stwa_06, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_07, should_return_array_of_strings) +Test(lp_lib_stwa_07, should_return_array_of_strings) { char *str = "HelloWorld"; char *delim = "HelloWorld"; char **expected = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_eq(actual, expected); } -Test(laplace_lib_stwa_08, should_return_array_of_strings) +Test(lp_lib_stwa_08, should_return_array_of_strings) { char *str = "HelloWorld"; char *delim = "Hello"; @@ -143,7 +143,7 @@ Test(laplace_lib_stwa_08, should_return_array_of_strings) expected[2] = "d"; expected[3] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_str_eq(actual[1], expected[1]); cr_assert_str_eq(actual[2], expected[2]); @@ -153,7 +153,7 @@ Test(laplace_lib_stwa_08, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_09, should_return_array_of_strings) +Test(lp_lib_stwa_09, should_return_array_of_strings) { char *str = "HelloWorld"; char *delim = "World"; @@ -161,7 +161,7 @@ Test(laplace_lib_stwa_09, should_return_array_of_strings) expected[0] = "He"; expected[1] = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_str_eq(actual[0], expected[0]); cr_assert_eq(actual[1], expected[1]); for (unsigned i = 0; actual[i]; i++) { free(actual[i]); } @@ -169,22 +169,22 @@ Test(laplace_lib_stwa_09, should_return_array_of_strings) free(expected); } -Test(laplace_lib_stwa_10, should_return_array_of_strings) +Test(lp_lib_stwa_10, should_return_array_of_strings) { char *str = ""; char *delim = "Hello"; char **expected = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_eq(actual, expected); } -Test(laplace_lib_stwa_11, should_return_array_of_strings) +Test(lp_lib_stwa_11, should_return_array_of_strings) { char *str = NULL; char *delim = ""; char **expected = NULL; - char **actual = laplace_lib_stwa(str, delim); + char **actual = lp_lib_stwa(str, delim); cr_assert_eq(actual, expected); } diff --git a/Libs/tests/test_lib/lib_two_free_test.c b/Libs/tests/test_lib/lib_two_free_test.c index 9f1bdd0..3262809 100644 --- a/Libs/tests/test_lib/lib_two_free_test.c +++ b/Libs/tests/test_lib/lib_two_free_test.c @@ -15,9 +15,9 @@ #include #endif -void laplace_lib_two_free(char **tab); +void lp_lib_two_free(char **tab); -Test(laplace_lib_two_free_01, should_free_tab) +Test(lp_lib_two_free_01, should_free_tab) { char **tab = malloc(sizeof(char *) << 1); @@ -27,26 +27,26 @@ Test(laplace_lib_two_free_01, should_free_tab) tab[0][1] = '\0'; tab[1][0] = 'b'; tab[1][1] = '\0'; - laplace_lib_two_free(tab); + lp_lib_two_free(tab); cr_assert_not_null(tab[0]); cr_assert_not_null(tab[1]); } -Test(laplace_lib_two_free_02, should_free_tab) +Test(lp_lib_two_free_02, should_free_tab) { char **tab = NULL; - laplace_lib_two_free(tab); + lp_lib_two_free(tab); cr_assert_eq(tab, NULL); } -Test(laplace_lib_two_free_03, should_free_tab) +Test(lp_lib_two_free_03, should_free_tab) { char **tab = malloc(sizeof(char *) << 1); tab[0] = NULL; tab[1] = NULL; - laplace_lib_two_free(tab); + lp_lib_two_free(tab); cr_assert_not_null(tab[0]); cr_assert_not_null(tab[1]); } diff --git a/Libs/tests/test_lib/lib_two_len_test.c b/Libs/tests/test_lib/lib_two_len_test.c index fdf4462..97d168c 100644 --- a/Libs/tests/test_lib/lib_two_len_test.c +++ b/Libs/tests/test_lib/lib_two_len_test.c @@ -9,39 +9,39 @@ #include -unsigned laplace_lib_two_len(const char *tab[]); +unsigned lp_lib_two_len(const char *tab[]); -Test(laplace_lib_two_len_01, should_return_true) +Test(lp_lib_two_len_01, should_return_true) { const char *tab[] = {"Hello", "World", NULL}; - cr_assert_eq(laplace_lib_two_len(tab), 2); + cr_assert_eq(lp_lib_two_len(tab), 2); } -Test(laplace_lib_two_len_02, should_return_false) +Test(lp_lib_two_len_02, should_return_false) { const char *tab[] = {"Hello", "World", "!", NULL}; - cr_assert_eq(laplace_lib_two_len(tab), 3); + cr_assert_eq(lp_lib_two_len(tab), 3); } -Test(laplace_lib_two_len_03, should_return_false) +Test(lp_lib_two_len_03, should_return_false) { const char *tab[] = {"Hello", NULL}; - cr_assert_eq(laplace_lib_two_len(tab), 1); + cr_assert_eq(lp_lib_two_len(tab), 1); } -Test(laplace_lib_two_len_04, should_return_false) +Test(lp_lib_two_len_04, should_return_false) { const char *tab[] = {NULL}; - cr_assert_eq(laplace_lib_two_len(tab), 0); + cr_assert_eq(lp_lib_two_len(tab), 0); } -Test(laplace_lib_two_len_05, should_return_false) +Test(lp_lib_two_len_05, should_return_false) { const char *tab[] = {"Hello", "World", "!", "!", NULL}; - cr_assert_eq(laplace_lib_two_len(tab), 4); + cr_assert_eq(lp_lib_two_len(tab), 4); } diff --git a/Libs/tests/test_lib/lib_two_print_test.c b/Libs/tests/test_lib/lib_two_print_test.c index 01c81aa..7b1cd94 100644 --- a/Libs/tests/test_lib/lib_two_print_test.c +++ b/Libs/tests/test_lib/lib_two_print_test.c @@ -9,20 +9,20 @@ #include -void laplace_lib_two_print(const char *tab[]); +void lp_lib_two_print(const char *tab[]); -Test(laplace_lib_two_print_01, should_print_tab) +Test(lp_lib_two_print_01, should_print_tab) { const char *tab[] = {"Hello", "World", NULL}; - laplace_lib_two_print(tab); + lp_lib_two_print(tab); cr_assert_eq(0, 0); } -Test(laplace_lib_two_print_02, should_not_crash) +Test(lp_lib_two_print_02, should_not_crash) { const char *tab[] = {NULL}; - laplace_lib_two_print(tab); + lp_lib_two_print(tab); cr_assert_eq(0, 0); } diff --git a/Libs/tests/test_link/link_example_test.c b/Libs/tests/test_link/link_example_test.c index bb53076..95d1313 100644 --- a/Libs/tests/test_link/link_example_test.c +++ b/Libs/tests/test_link/link_example_test.c @@ -33,7 +33,7 @@ void init_wave() wave->wave_direction = 0; // Add the wave to the list - laplace_link_append(&(wave_list), laplace_link_create(wave)); + lp_link_append(&(wave_list), lp_link_create(wave)); } } @@ -54,14 +54,14 @@ void delete_wave() wave_t *wave = (wave_t *)actual->obj; if (wave->wave_length == 0) { - laplace_link_remove(&(wave_list), actual, &free_wave); + lp_link_remove(&(wave_list), actual, &free_wave); break; } // If you want to delete the last element of the list, you do this: - laplace_link_remove(&(wave_list), wave_list->prev, &free_wave); + lp_link_remove(&(wave_list), wave_list->prev, &free_wave); // If you want to delete the first element of the list, you do this: - laplace_link_remove(&(wave_list), wave_list, &free_wave); + lp_link_remove(&(wave_list), wave_list, &free_wave); actual = actual->next; } while (wave_list && actual != wave_list); @@ -73,7 +73,7 @@ void delete_all_wave() if (!wave_list) return; while (wave_list) { - laplace_link_remove(&(wave_list), wave_list, &free_wave); + lp_link_remove(&(wave_list), wave_list, &free_wave); } } diff --git a/Libs/tests/test_map/map_example_test.c b/Libs/tests/test_map/map_example_test.c index 29c09a7..984a36c 100644 --- a/Libs/tests/test_map/map_example_test.c +++ b/Libs/tests/test_map/map_example_test.c @@ -36,7 +36,7 @@ void init_wave() *key = (int)i; // Add the wave as obj in the map list with the key - laplace_map_append(&(wave_list), laplace_map_create(key, wave)); + lp_map_append(&(wave_list), lp_map_create(key, wave)); } } @@ -57,7 +57,7 @@ void delete_all_wave() if (!wave_list) return; while (wave_list) { - laplace_map_remove(&(wave_list), wave_list, &free_wave); + lp_map_remove(&(wave_list), wave_list, &free_wave); } } diff --git a/Makefile b/Makefile index a4b5046..8abdcc6 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,12 @@ DEFAULT_GRAPHICAL_LIB := csfml SRC_DIR = Engine/ ENGINE_DIR = Engine/Engine/ +PARSER_DIR = Engine/Parser/ BIN = bin/ -SRC = $(ENGINE_DIR)engine.c \ +#$(shell find $(SRC_DIR) -name '*.c' | grep -v "core.c") +SRC = $(SRC_DIR)Camera/camera.c \ + $(ENGINE_DIR)engine.c \ $(ENGINE_DIR)Renderer/renderer.c \ $(ENGINE_DIR)Renderer/Window/window.c \ $(ENGINE_DIR)Event/event.c \ @@ -32,6 +35,13 @@ SRC = $(ENGINE_DIR)engine.c \ $(ENGINE_DIR)Math/Vector/vector4.c \ $(ENGINE_DIR)Math/Vector/vector3.c \ $(ENGINE_DIR)Math/Point/point.c \ + $(ENGINE_DIR)Math/Matrix/matrix.c \ + $(ENGINE_DIR)Math/Geometry/triangle.c \ + $(ENGINE_DIR)Pipelines/graphics_pipeline.c \ + $(ENGINE_DIR)Clock/clock.c \ + $(PARSER_DIR)MTL/parser_mtl.c \ + $(PARSER_DIR)OBJ/parser_obj.c \ + $(PARSER_DIR)XML/parser_xml.c \ MAIN = $(SRC_DIR)core.c @@ -41,9 +51,12 @@ OBJ = $(MAIN:.c=.o) $(SRC:.c=.o) INCLUDES = -iquote ./Libs/LaplaceLib/include -iquote ./Libs/LaplaceLink/include \ -iquote ./Libs/LaplaceMap/include -iquote ./Libs/LaplaceError/include -INCLUDES += -iquote ./Engine/Config +INCLUDES += -iquote ./Engine/Camera -INCLUDES += -iquote ./Engine/Engine -iquote ./Engine/Engine/Renderer +INCLUDES += -iquote ./Engine/Config -iquote ./Engine/Config/RunMode/Runtime + +INCLUDES += -iquote ./Engine/Engine -iquote ./Engine/Engine/Renderer \ + -iquote ./Engine/Engine/Renderer/Window INCLUDES += -iquote ./Engine/Engine/Event -iquote ./Engine/Engine/Event/Keyboard @@ -53,12 +66,24 @@ INCLUDES += -iquote ./Engine/Engine/Math \ INCLUDES += -iquote ./Engine/Engine/Clock +INCLUDES += -iquote ./Engine/Engine/Pipelines + +INCLUDES += -iquote ./Engine/Parser/MTL -iquote ./Engine/Parser/OBJ \ + -iquote ./Engine/Parser/XML + +INCLUDES += -iquote ./Engine/Injector + +INCLUDES += -iquote ./Engine/Mesh + + LIB_NAME = -L ./Libs -l LaplaceLib -l LaplaceLink -l LaplaceMap OPTI = -Ofast -march=native -mtune=native -flto -fuse-linker-plugin \ -pipe -fomit-frame-pointer -fopenmp -fprefetch-loop-arrays \ -fno-stack-protector -fno-ident -fno-asynchronous-unwind-tables +# OPTI = -g3 -ggdb + IGNORE = -fno-strict-aliasing -Wno-strict-aliasing CSFML = -l csfml-graphics \ @@ -81,18 +106,18 @@ VULKAN = -l glfw -l vulkan -l X11 -l dl -l pthread -l Xrandr \ LDFLAGS := ifeq ($(GRAPHICAL_LIB), csfml) - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(CSFML) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(CSFML) -lm -lpthread else ifeq ($(GRAPHICAL_LIB), sfml) - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(SFML) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(SFML) -lm -lpthread else ifeq ($(GRAPHICAL_LIB), sdl2) - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(SDL2) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(SDL2) -lm -lpthread else ifeq ($(GRAPHICAL_LIB), opengl) - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(OPENGL) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(OPENGL) -lm -lpthread else ifeq ($(GRAPHICAL_LIB), vulkan) - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(VULKAN) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(VULKAN) -lm -lpthread else # If no graphical lib is specified, use the default one - LDFLAGS := $(INCLUDES) $(LIB_NAME) $(CSFML) -lm + LDFLAGS := $(INCLUDES) $(LIB_NAME) $(CSFML) -lm -lpthread GRAPHICAL_LIB := $(DEFAULT_GRAPHICAL_LIB) endif @@ -108,6 +133,7 @@ D_FLAGS := -D GRAPHICS_LIBRARY=$(GRAPHICAL_LIB) \ endif CFLAGS = $(FLAGS) $(LDFLAGS) $(OPTI) $(IGNORE) $(D_FLAGS) +# CFLAGS = $(FLAGS) $(LDFLAGS) $(IGNORE) $(D_FLAGS) ifeq ($(OS), linux) CC := gcc @@ -138,8 +164,12 @@ endif SRC_COUNT := $(words $(SRC)) NB = 0 +INJECTOR := +$(PROJECT_NAME): INJECTOR = -L. -linjector $(PROJECT_NAME): @$(ECHO) $(BOLD) $(LIGHT_BLUE) "Selected project: $(PROJECT_NAME) 🎮 !" $(DEFAULT) + @gcc -fPIC -shared Projects/$(PROJECT_NAME)/src/__injector__.c $(SRC) $(LDFLAGS) -o libinjector.so $(INCLUDES) -g3 + @export LD_LIBRARY_PATH="." $(GRAPHICAL_LIB): @$(ECHO) $(BOLD) $(LIGHT_BLUE) "Selected graphical library: $(GRAPHICAL_LIB) 🎮 !" $(DEFAULT) @@ -148,7 +178,7 @@ $(VERSION_ENGINE): @$(ECHO) $(BOLD) $(LIGHT_BLUE) "Selected version: $(VERSION_ENGINE) 🎮 !" $(DEFAULT) $(NAME): $(OBJ) - @$(CC) -o $(NAME) $(OBJ) $(CFLAGS) \ + @-LD_LIBRARY_PATH="." $(CC) -o $(NAME) $(OBJ) $(CFLAGS) $(INJECTOR) \ && $(ECHO) $(BOLD) $(GREEN)"\n► BUILD SUCCESS ⛽ !"$(DEFAULT) \ || ($(ECHO) $(BOLD) $(RED)"\n► BUILD FAILED ⛽"$(DEFAULT) && exit 1) @@ -188,6 +218,7 @@ fclean: clean @$(RM) $(NAME) @$(RM) $(SHARE_NAME) @$(RM) $(TEST_NAME) + @$(RM) libinjector.so @$(MAKE) -C ./Libs fclean $(NO_PRINT) @$(MAKE) -C ./Launcher fclean $(NO_PRINT) @$(RM) *.gcda @@ -199,7 +230,7 @@ re: fclean all launcher ## DEBUG MODE -debug: OPTI = -Og -pipe +debug: OPTI = -O0 -pipe debug: CFLAGS = $(FLAGS) $(LDFLAGS) $(OPTI) $(IGNORE) -g3 -ggdb -DDEBUG debug: fclean lib_debug $(NAME) @-$(ECHO) $(BOLD) $(GREEN)"\n► DEBUG MODE 🔧 !"$(DEFAULT) diff --git a/Projects/New/Assets/Meshs/mesh_map/MTL/Artisans_Hub.mtl b/Projects/New/Assets/Meshs/mesh_map/MTL/Artisans_Hub.mtl new file mode 100644 index 0000000..7b926a5 --- /dev/null +++ b/Projects/New/Assets/Meshs/mesh_map/MTL/Artisans_Hub.mtl @@ -0,0 +1,12 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl Material.001 +Ns 92.156863 +Ka 0.000000 0.000000 0.000000 +Kd 0.512000 0.512000 0.512000 +Ks 0.250000 0.250000 0.250000 +Ni 1.000000 +d 1.000000 +illum 0 +map_Kd High.png diff --git a/Projects/New/Assets/Meshs/mesh_map/MTL/High.png b/Projects/New/Assets/Meshs/mesh_map/MTL/High.png new file mode 100644 index 0000000..0b5897e Binary files /dev/null and b/Projects/New/Assets/Meshs/mesh_map/MTL/High.png differ diff --git a/Projects/New/Assets/Meshs/mesh_map/MTL/Low.png b/Projects/New/Assets/Meshs/mesh_map/MTL/Low.png new file mode 100644 index 0000000..531bdab Binary files /dev/null and b/Projects/New/Assets/Meshs/mesh_map/MTL/Low.png differ diff --git a/Projects/New/Assets/Meshs/mesh_map/OBJ/Artisans_Hub.obj b/Projects/New/Assets/Meshs/mesh_map/OBJ/Artisans_Hub.obj new file mode 100644 index 0000000..b05882e --- /dev/null +++ b/Projects/New/Assets/Meshs/mesh_map/OBJ/Artisans_Hub.obj @@ -0,0 +1,10448 @@ +# Blender v2.73 (sub 0) OBJ File: '' +# www.blender.org +mtllib Artisans_Hub.mtl +o tex_3 +v -39.394119 -14.657062 177.590027 +v -39.394119 -14.657062 183.990036 +v -32.994122 -14.657063 183.990036 +v -32.994122 -14.657063 177.590027 +v -39.394119 -14.657061 171.190033 +v -32.994122 -14.657062 171.190033 +v -39.394119 -14.657062 164.790039 +v -32.994122 -14.657062 164.790039 +v -39.394119 -14.657061 158.390030 +v -32.994122 -14.657062 158.390030 +v -39.394119 -14.657061 151.990036 +v -32.994122 -14.657062 151.990036 +v -39.394119 -14.657061 145.590027 +v -32.994122 -14.657062 145.590027 +v -26.594118 -14.657063 183.990036 +v -26.594118 -14.657063 177.590027 +v -26.594118 -14.657063 158.390030 +v -26.594118 -14.657063 151.990036 +v 102.255882 -5.857064 -69.409988 +v 99.355888 -5.857062 -68.859985 +v 100.655884 -5.857063 -62.409981 +v 98.505882 -5.857061 -75.009987 +v 88.355888 -5.857062 -57.009983 +v 83.955887 -5.857060 -61.559982 +v 83.955887 -4.257060 -61.559982 +v 88.355888 -4.257062 -57.009983 +v 94.155884 -5.857062 -54.509983 +v 94.155884 -4.257062 -54.509983 +v 100.355888 -5.857063 -53.009983 +v 99.355888 -5.857064 -55.959984 +v 108.105888 -5.857063 -59.759983 +v 107.805885 -5.857066 -65.609985 +v 98.055885 -5.857063 -62.409981 +v 92.405884 -5.857060 -66.159988 +v 106.755882 -5.857063 -52.709984 +v 99.505882 3.092937 -56.409985 +v 98.205887 3.292937 -62.409985 +v 99.705887 8.942939 -56.709991 +v 98.455887 9.192939 -62.409988 +v 100.505882 13.292938 -56.959980 +v 99.205887 13.542939 -62.409977 +v 100.755882 2.942937 -62.409985 +v 101.005882 8.742940 -62.409988 +v 101.755882 12.992940 -62.409977 +v 99.505882 3.092938 -68.409988 +v 99.705887 8.942940 -68.109993 +v 100.505882 13.292940 -67.859993 +v 107.955887 14.142935 -61.059978 +v 106.805885 14.142936 -52.859978 +v 106.355888 17.342937 -56.959984 +v 106.655884 17.992935 -62.409981 +v -61.194115 17.992968 -118.409996 +v -69.294121 19.292967 -118.659996 +v -73.894119 19.942972 -112.259995 +v -65.794121 18.592970 -112.009995 +v -81.994118 21.242973 -112.510002 +v -67.444115 18.292969 -102.909996 +v -55.744118 4.042962 -94.309990 +v -55.944118 5.142964 -92.259987 +v -58.544117 5.142964 -92.259987 +v -58.544117 4.042963 -94.309990 +v -67.194115 13.142967 -96.859993 +v -64.544121 13.692967 -103.359993 +v -69.994118 16.942965 -96.209991 +v -62.994118 8.792968 -96.859993 +v -60.444118 8.842967 -103.159996 +v -61.094112 13.842967 -110.909996 +v -57.244118 8.842967 -110.209991 +v -57.394115 5.392965 -103.059990 +v -54.594116 5.392966 -109.859985 +v -57.594116 12.192966 -116.459991 +v -54.144115 9.092967 -115.609993 +v -51.044117 5.392966 -115.509987 +v -47.044117 5.342966 -121.059990 +v -50.244118 9.792967 -121.059998 +v -48.494118 1.342966 -114.209984 +v -44.594116 1.342963 -119.159988 +v -123.794121 1.242961 47.990017 +v -124.294121 0.442962 49.740017 +v -119.394119 -1.157040 47.790016 +v -114.494118 -2.757041 47.090015 +v -114.394119 -0.457039 43.540016 +v -119.244118 1.142962 43.890015 +v -119.194115 2.192963 39.990017 +v -114.344116 0.592961 39.990017 +v -114.394119 -0.457039 36.440014 +v -119.244118 1.142962 36.090015 +v -114.494118 -2.757037 32.890015 +v -119.394119 -1.157036 32.190014 +v -122.694115 3.392964 38.390011 +v -122.544121 3.742963 39.990013 +v -123.794121 1.242964 31.990015 +v -111.694115 -6.457039 44.140018 +v -108.344116 -0.257039 44.590015 +v -107.344116 0.042959 47.990017 +v -110.994118 -5.907040 47.440018 +v -126.044121 -1.307037 37.040016 +v -126.194115 -6.557036 30.840012 +v -119.894119 -6.957036 32.140018 +v -119.844116 -2.807038 37.390015 +v -126.044121 -1.307037 42.940014 +v -119.844116 -2.807038 42.590015 +v -126.194115 -6.557038 48.940018 +v -119.894119 -6.207038 47.840019 +v -129.994125 -1.407038 41.190014 +v -129.994125 -1.407035 38.790016 +v -131.544113 -1.907035 38.940014 +v -131.294113 -3.507037 35.490021 +v -107.344116 0.042962 31.990015 +v -108.344116 -0.257040 35.390015 +v -106.994118 -1.807042 39.990017 +v -124.294121 0.442963 30.240015 +v -134.294113 -2.057035 38.940014 +v -134.294113 -2.057037 41.040016 +v -130.894119 -1.207038 41.190014 +v -130.894119 -1.207035 38.790016 +v -131.644119 -3.007038 40.840015 +v -134.244125 -3.157037 40.840015 +v -114.544121 -3.957038 39.990021 +v -114.244118 -3.907039 43.790020 +v 57.505890 12.942933 71.040009 +v 64.255882 12.892932 72.090012 +v 65.955887 15.192932 64.140007 +v 59.405888 15.492933 64.340012 +v 50.755890 12.942933 71.640007 +v 52.555889 15.992934 64.540009 +v 43.905888 13.442935 70.790009 +v 45.255890 16.942932 64.740005 +v 37.105888 13.292936 70.390007 +v 37.555889 18.142933 64.890007 +v 30.305885 11.392936 70.190010 +v 29.705889 19.142935 64.640007 +v 59.655888 16.392933 56.940022 +v 52.355888 17.792934 57.440018 +v 44.855888 19.192936 57.740021 +v 62.905880 -14.657070 83.040024 +v 65.405884 -14.657069 89.590027 +v 66.655884 -11.457070 88.590027 +v 63.805885 -11.657070 80.790024 +v 36.855881 -14.657066 87.140022 +v 43.805882 -14.657067 87.990021 +v 43.555882 -14.657067 81.740021 +v 36.855881 -14.657066 80.740021 +v 30.155886 7.592936 73.040009 +v 23.505886 13.392938 70.840012 +v 23.505886 7.492938 74.190010 +v 30.355885 2.592938 75.540016 +v 23.655884 1.342939 75.790016 +v 30.305883 -6.007063 77.390015 +v 23.505884 -5.107064 78.190018 +v 37.105885 7.492935 73.440010 +v 37.105885 1.792936 75.290016 +v 37.105885 -5.407063 77.490013 +v 36.705883 -11.357067 79.740021 +v 30.005882 -11.257066 79.140022 +v 30.005882 -14.657065 80.840027 +v 44.055885 7.492934 73.290009 +v 43.905884 1.192936 76.340019 +v 43.905884 -5.007068 77.840019 +v 43.505886 -12.057069 79.640022 +v 50.755886 7.742934 74.990005 +v 50.755886 1.242932 77.640015 +v 50.655884 -4.907068 78.890015 +v 50.305885 -11.857068 80.340027 +v 50.455879 -14.657067 82.290024 +v 57.455883 8.292932 75.340012 +v 57.505886 1.192930 76.990013 +v 57.105885 -4.407069 78.840019 +v 56.955879 -12.957070 80.090027 +v 57.655880 -14.657068 82.690025 +v 64.255882 6.992931 75.690010 +v 64.255882 1.242930 78.040016 +v 64.155884 -4.907069 79.340019 +v 71.555885 -5.057071 79.240013 +v 71.055885 1.192928 77.390015 +v 100.655884 -14.657081 153.090027 +v 99.955887 -14.657084 155.690033 +v 102.705887 -14.657081 160.290039 +v 105.955887 -14.657083 159.290039 +v 102.605888 -14.657083 165.190033 +v 105.205887 -14.657085 167.040039 +v 97.605888 -14.657081 165.990036 +v 95.755882 -14.657083 169.340027 +v 93.005882 -14.657081 162.690033 +v 89.955887 -14.657081 164.040039 +v 93.205887 -14.657082 157.240036 +v 90.855888 -14.657082 155.640030 +v 107.805885 -14.657083 158.390030 +v 109.055885 -14.657083 165.640030 +v 95.005882 -14.657082 171.190033 +v 103.055885 -14.657083 171.390030 +v 87.355888 -14.657080 158.390030 +v 93.605888 -14.657081 152.190033 +v 100.555885 -10.707083 163.440018 +v 98.455887 -6.357081 160.990021 +v 97.805885 -10.707083 163.790024 +v 95.805885 -11.207083 162.190018 +v 96.505882 -10.707081 159.490021 +v 99.255882 -10.707082 158.690018 +v 101.255882 -10.707081 160.690018 +v 75.805885 -14.657078 183.990036 +v 75.805885 -14.657083 190.390015 +v 82.205887 -14.657084 190.390015 +v 82.205887 -14.657080 183.990036 +v 75.805885 -14.657079 164.790039 +v 75.805885 -14.657079 171.190033 +v 82.205887 -14.657080 171.190033 +v 82.205887 -14.657080 164.790039 +v 75.805885 -14.657078 158.390030 +v 82.205887 -14.657078 158.390030 +v 75.805885 -14.657078 151.990036 +v 82.205887 -14.657079 151.990036 +v 75.805885 -14.657078 145.590027 +v 82.205887 -14.657079 145.590027 +v 88.605888 -14.657085 190.390015 +v 88.605888 -14.657082 183.990036 +v 82.205887 -14.657080 177.590027 +v 88.605888 -14.657081 177.590027 +v 88.605888 -14.657081 171.190033 +v 88.605888 -14.657081 151.990036 +v 88.605888 -14.657080 145.590027 +v 95.005882 -14.657082 183.990036 +v 95.005882 -14.657082 177.590027 +v 95.005882 -14.657081 145.590027 +v 101.405884 -14.657083 183.990036 +v 101.405884 -14.657083 177.590027 +v 101.405884 -14.657082 145.590027 +v 95.005882 -14.657081 139.190033 +v 101.405884 -14.657082 139.190033 +v 107.805885 -14.657084 183.990036 +v 107.805885 -14.657084 177.590027 +v 107.805885 -14.657084 171.190033 +v 107.805885 -14.657083 151.990036 +v 107.805885 -14.657083 145.590027 +v 107.805885 -14.657083 139.190033 +v 114.205887 -14.657084 183.990036 +v 114.205887 -14.657084 177.590027 +v 114.205887 -14.657084 171.190033 +v 114.205887 -14.657084 164.790039 +v 114.205887 -14.657084 158.390030 +v 114.205887 -14.657084 151.990036 +v 114.205887 -14.657084 145.590027 +v 120.605888 -14.657085 183.990036 +v 120.605888 -14.657085 177.590027 +v 120.605888 -14.657085 171.190033 +v 120.605888 -14.657085 164.790039 +v 120.605888 -14.657084 158.390030 +v 120.605888 -14.657084 151.990036 +v 120.605888 -14.657084 145.590027 +v -206.494125 35.742989 -63.909973 +v -209.794113 48.042980 -57.759983 +v -203.644119 35.692989 -58.809975 +v -191.944122 29.592979 -46.959988 +v -190.994125 37.842983 -44.459980 +v -188.844116 29.542980 -48.509987 +v 184.605881 -14.657095 183.990036 +v 184.605881 -14.657100 190.390015 +v 191.005890 -14.657101 190.390015 +v 191.005890 -14.657096 183.990036 +v 184.605881 -14.657096 177.590027 +v 191.005890 -14.657096 177.590027 +v 184.605881 -14.657095 171.190033 +v 191.005890 -14.657096 171.190033 +v 184.605881 -14.657095 164.790039 +v 191.005890 -14.657097 164.790039 +v 184.605881 -14.657095 158.390030 +v 191.005890 -14.657096 158.390030 +v 184.605881 -14.657094 151.990036 +v 191.005890 -14.657095 151.990036 +v 184.605881 -14.657094 145.590027 +v 191.005890 -14.657095 145.590027 +v 70.805885 -10.007068 72.190025 +v 70.805885 -8.357068 66.040024 +v 71.555885 -2.207069 67.690018 +v 71.555885 -3.857070 73.840019 +v 72.705887 0.992931 68.540016 +v 72.705887 -0.657069 74.690018 +v 77.205887 2.542931 68.940018 +v 77.205887 0.892930 75.140015 +v 81.655884 -0.657071 74.690018 +v 81.655884 0.992930 68.540016 +v 77.205887 -10.007070 72.190025 +v 77.205887 -8.357069 66.040024 +v 83.605888 -10.007071 72.190025 +v 83.605888 -8.357069 66.040024 +v 82.855888 -3.857071 73.840019 +v 82.855888 -2.207071 67.690018 +v 70.805885 -6.707067 59.840019 +v 71.555885 -0.507069 61.490017 +v 72.755882 2.642932 62.340015 +v 77.205887 4.192931 62.790012 +v 82.855888 -0.507070 61.490017 +v 81.705887 2.642930 62.340015 +v 77.205887 -6.707067 59.840019 +v 83.605888 -6.707071 59.840019 +v 71.555885 1.142932 55.290016 +v 72.755882 4.292932 56.190010 +v 77.205887 5.892932 56.590012 +v 81.705887 4.292931 56.190010 +v 82.855888 1.142930 55.290016 +v -144.694122 13.542976 -55.609978 +v -147.344116 13.542974 -54.109978 +v -147.144119 13.542974 -60.059978 +v -144.594116 13.542974 -58.409977 +v -147.094116 3.942975 -62.209991 +v -142.744125 3.942975 -59.359989 +v -141.944122 10.342974 -59.759995 +v -147.094116 10.342977 -63.109993 +v -147.094116 -1.907026 -62.209988 +v -142.744125 -1.907025 -59.359985 +v -151.594116 3.942977 -59.759991 +v -151.744125 3.942976 -54.659988 +v -151.744125 -1.907025 -54.659985 +v -151.594116 -1.907023 -59.759987 +v -142.894119 3.942974 -54.559990 +v -142.894119 -1.907026 -54.559986 +v -152.144119 3.942977 -59.409988 +v -152.244125 3.942975 -55.009991 +v -142.094116 10.342973 -54.109993 +v -147.394119 3.942976 -51.959991 +v -147.394119 10.342976 -51.059994 +v -71.394119 16.492966 -83.759995 +v -76.144119 19.892965 -83.959991 +v -76.994118 19.242970 -77.709991 +v -72.294121 15.042965 -77.509995 +v -76.294121 18.292965 -71.459991 +v -71.594116 14.692964 -71.259995 +v -75.094116 17.642969 -65.209991 +v -70.344116 14.192964 -65.059998 +v -55.744118 4.042962 -88.459984 +v -55.944118 5.142965 -90.509987 +v -55.794117 6.242965 -90.309990 +v -55.594116 4.642963 -86.909988 +v -67.544121 10.442963 -65.709991 +v -68.794121 10.392962 -71.909996 +v -63.344116 7.442964 -65.709991 +v -64.544121 7.842964 -71.909996 +v -69.444115 11.292964 -78.159996 +v -65.294121 8.542963 -78.159996 +v -61.344116 5.292964 -71.909988 +v -62.044117 5.192965 -78.159988 +v -57.444118 1.342963 -71.909988 +v -58.144115 1.342964 -78.159988 +v -68.544121 13.142963 -84.409996 +v -64.394119 8.842964 -84.409996 +v -61.144115 5.392965 -84.409988 +v -57.244118 1.342964 -85.709984 +v -68.844116 12.792968 -90.759995 +v -71.644119 16.692968 -90.109993 +v -64.644119 9.092968 -90.759995 +v -61.394115 7.692965 -90.759995 +v -147.094116 -2.457026 -62.859985 +v -142.144119 -2.457025 -59.859985 +v -141.894119 -8.857027 -59.959984 +v -147.094116 -8.857024 -63.159981 +v -142.194122 3.942975 -59.809990 +v -147.094116 3.942974 -62.809990 +v -147.144119 15.092974 -60.759979 +v -150.394119 15.092976 -59.009979 +v -147.244125 23.192976 -57.059982 +v -143.994125 15.092976 -58.859978 +v -144.094116 15.092973 -55.159977 +v 0.855887 22.142958 -157.610001 +v 0.855887 22.142962 -164.410004 +v 0.805888 24.692961 -164.460007 +v 0.805888 24.692957 -157.610001 +v 0.855887 22.142962 -150.809998 +v 0.805887 23.692961 -150.710007 +v -3.044114 17.242960 -157.760010 +v -2.794112 24.692959 -157.610001 +v -2.794112 24.692963 -164.460007 +v -3.044114 17.242964 -164.309998 +v -3.044114 17.242964 -151.210007 +v -2.794113 23.692963 -150.710007 +v -127.894119 9.942962 66.140007 +v -132.544113 13.492961 68.740005 +v -126.194115 14.042959 68.590012 +v -121.544121 10.492961 65.990005 +v -119.744118 15.392958 68.390007 +v -115.094116 11.842960 65.740005 +v -113.294121 16.542957 68.440010 +v -108.644119 12.992958 65.790009 +v -107.044121 16.692957 69.640007 +v -102.894119 13.492958 67.290009 +v -88.544121 13.442956 72.890007 +v -93.994118 16.642960 75.540009 +v -87.644119 16.292952 77.140007 +v -82.194115 13.192952 74.490005 +v -84.094116 9.442953 67.990005 +v -78.194115 9.392953 70.340012 +v -77.494118 16.092951 80.040009 +v -73.094116 14.242951 75.840012 +v -72.344116 10.742952 70.890007 +v -99.794121 16.842957 72.590012 +v -94.394119 13.242955 69.940010 +v 24.005892 51.942959 -158.409958 +v 25.105892 51.942955 -161.009964 +v 21.405893 58.492958 -161.009964 +v 21.405891 51.942959 -157.359955 +v 18.805891 51.942959 -158.409958 +v 17.705893 51.942955 -161.009964 +v 18.805891 51.942955 -163.609955 +v 21.405891 51.942955 -164.709961 +v 24.005892 51.942955 -163.609955 +v 27.055891 47.192963 -155.359955 +v 21.405891 47.192966 -153.009964 +v 15.755891 47.192963 -155.359955 +v 11.405891 50.442963 -161.009964 +v 10.205891 47.192963 -158.959961 +v 12.605890 47.192963 -158.959961 +v 12.605890 47.192959 -163.109955 +v 10.205891 47.192959 -163.109955 +v 55.405884 -5.057061 15.390018 +v 63.105885 -4.357064 17.640017 +v 60.805885 -3.807063 11.240013 +v 56.605885 -4.457063 11.190014 +v 59.455883 -3.007061 7.990016 +v 53.905884 -3.007061 6.090014 +v 49.655884 -5.057061 15.390018 +v 50.205883 -4.957062 11.190014 +v -145.894119 2.492979 -116.709984 +v -148.594116 5.042982 -119.009987 +v -152.644119 5.992980 -115.159988 +v -152.144119 2.442978 -113.209984 +v -148.494125 7.842979 -126.259995 +v -151.244125 10.392981 -130.709991 +v -157.594116 10.742984 -127.459991 +v -152.944122 8.142982 -122.559998 +v -163.194122 10.742983 -123.559998 +v -156.644119 8.992981 -118.459991 +v -168.094116 11.292982 -119.059998 +v -158.694122 9.892981 -112.909996 +v -153.944122 6.842981 -109.809998 +v -149.244125 2.442978 -106.859985 +v -149.244125 -3.957021 -106.859985 +v -151.194122 -3.957021 -112.509987 +v -148.744125 -10.357020 -106.509979 +v -151.194122 -10.357021 -112.509979 +v -142.994125 -10.357019 -109.609978 +v -136.594116 -10.357022 -112.409981 +v -139.344116 -10.357023 -118.309982 +v -144.844116 -10.357020 -115.909981 +v -139.344116 2.542978 -118.309990 +v -145.894119 -3.907021 -116.759987 +v -139.344116 -3.857022 -118.309990 +v -140.644119 5.792979 -122.659988 +v -136.694122 6.292979 -122.459984 +v -135.194122 9.942980 -126.909996 +v -141.844116 9.142982 -126.609993 +v -133.844116 13.342979 -130.459991 +v -142.544113 11.742979 -130.559982 +v -131.144119 -10.357023 -119.159981 +v -133.344116 -10.357024 -112.759979 +v -123.094116 -10.357023 -118.109978 +v -125.994118 -10.357026 -112.309982 +v -119.194115 -10.357024 -109.359978 +v -115.594116 -10.357023 -114.709976 +v -115.594116 -3.857025 -114.709984 +v -123.094116 -3.857025 -118.109985 +v -131.144119 -3.857024 -119.159988 +v -123.094116 2.542975 -118.109985 +v -131.144119 2.542976 -119.159988 +v -126.094116 11.042979 -127.109993 +v -124.394119 13.542977 -130.410004 +v -127.994118 7.792977 -123.409996 +v 105.355888 6.692930 -9.709986 +v 103.955887 7.692933 -5.059985 +v 108.255882 13.292933 -5.159984 +v 110.055885 13.192930 -8.359985 +v 105.855888 8.292932 -13.109986 +v 104.105888 3.392931 -7.709987 +v 104.405884 3.392932 -8.509984 +v 104.005882 -3.007069 -7.709983 +v 102.305885 -3.007068 -7.759984 +v 102.605888 3.392932 -8.509984 +v 102.755882 6.692930 -9.709986 +v 102.955887 8.292933 -13.109986 +v 103.105888 7.192933 -13.309985 +v 105.705887 7.192933 -13.309985 +v 102.305885 8.942931 -12.959984 +v 102.905884 6.092934 -11.259986 +v 102.805885 3.392934 -10.209984 +v 31.005882 -14.657077 222.390015 +v 31.005882 -14.657078 228.790009 +v 37.405880 -14.657079 228.790009 +v 37.405880 -14.657078 222.390015 +v 31.005882 -14.657077 215.990005 +v 37.405880 -14.657079 215.990005 +v 31.005882 -14.657078 209.590012 +v 37.405880 -14.657078 209.590012 +v 31.005882 -14.657077 203.190002 +v 37.405880 -14.657078 203.190002 +v 31.005882 -14.657076 196.790009 +v 37.405880 -14.657077 196.790009 +v 31.005882 -14.657076 190.390015 +v 37.405880 -14.657077 190.390015 +v 43.805882 -14.657081 228.790009 +v 43.805882 -14.657080 222.390015 +v 43.805882 -14.657079 215.990005 +v 43.805882 -14.657079 209.590012 +v 43.805882 -14.657079 203.190002 +v 43.805882 -14.657079 196.790009 +v 43.805882 -14.657078 190.390015 +v 50.205879 -14.657081 228.790009 +v 50.205879 -14.657080 222.390015 +v 50.205879 -14.657080 215.990005 +v 50.205879 -14.657080 209.590012 +v 50.205879 -14.657080 203.190002 +v 50.205879 -14.657080 196.790009 +v 50.205879 -14.657079 190.390015 +v 56.605881 -14.657082 228.790009 +v 56.605881 -14.657081 222.390015 +v 56.605881 -14.657082 215.990005 +v 56.605881 -14.657081 209.590012 +v 56.605881 -14.657082 203.190002 +v 56.605881 -14.657081 196.790009 +v 56.605881 -14.657080 190.390015 +v 63.005882 -14.657083 228.790009 +v 63.005882 -14.657082 222.390015 +v 63.005882 -14.657082 215.990005 +v 63.005882 -14.657082 209.590012 +v 63.005882 -14.657082 203.190002 +v 63.005882 -14.657082 196.790009 +v 69.405884 -14.657084 228.790009 +v 69.405884 -14.657083 222.390015 +v 69.405884 -14.657083 215.990005 +v 69.405884 -14.657083 209.590012 +v 69.405884 -14.657083 203.190002 +v 69.405884 -14.657083 196.790009 +v 75.805885 -14.657084 209.590012 +v 75.805885 -14.657084 203.190002 +v 75.805885 -14.657084 196.790009 +v 45.405884 -3.957053 -87.659988 +v 38.755886 -4.357051 -86.059990 +v 43.805885 -4.507051 -84.809990 +v 51.705883 -3.657052 -89.859985 +v 50.205883 -4.407052 -84.809990 +v 43.805885 -3.407051 -97.609985 +v 37.405884 -3.957050 -97.609985 +v 37.505886 -4.357051 -92.359985 +v 43.655884 -3.957052 -93.809990 +v 50.205883 -3.057051 -97.609985 +v 49.705883 -3.407050 -95.909988 +v 55.555885 -3.557052 -97.909988 +v 64.555885 -4.057056 -95.059990 +v 58.255886 -3.857053 -92.109985 +v 63.005886 -5.057054 -91.209984 +v 70.655884 -4.307055 -99.459984 +v 69.405884 -4.707055 -91.209984 +v 74.655884 -4.857056 -99.559990 +v 75.455887 -4.707055 -104.509987 +v 79.805885 -5.007055 -110.759987 +v 83.355888 -5.057057 -105.459984 +v 56.605885 -3.057052 -104.009987 +v 61.155884 -3.807054 -100.509987 +v 65.805885 -4.307053 -103.609985 +v 50.205883 -5.057053 -71.859985 +v 43.805885 -5.057052 -72.009987 +v 45.805885 -5.057054 -70.009987 +v 56.605885 -5.057053 -84.809990 +v 43.805885 -3.057050 -104.009987 +v 37.405884 -3.707049 -104.009987 +v 43.805885 -4.957052 -78.409988 +v 50.205883 -4.957053 -78.409988 +v 78.905884 -5.057057 -100.909988 +v 75.955887 -5.057054 -95.309990 +v 63.005886 -3.957052 -110.409988 +v 69.405884 -4.507054 -110.409988 +v 69.405884 -4.707053 -116.809990 +v 62.205883 -4.257052 -116.809990 +v 50.205883 -2.607051 -104.009987 +v 56.605885 -5.057054 -78.409988 +v 56.605885 -3.407052 -110.409988 +v 50.205883 -3.057050 -110.409988 +v 56.605885 -5.057054 -72.009987 +v 63.005886 -4.707054 -84.809990 +v 63.005886 -5.007055 -78.409988 +v 69.405884 -4.857055 -84.809990 +v 69.405884 -5.007056 -78.409988 +v 74.805885 -5.057057 -87.259987 +v 75.105888 -5.057057 -79.309990 +v 69.405884 -5.057056 -72.009987 +v 76.205887 -5.057061 -71.459984 +v 56.605885 -3.957051 -116.809990 +v 37.405884 -4.807051 -78.409988 +v 76.205887 -4.257060 -71.459984 +v 75.105888 -4.257057 -79.309990 +v 78.455887 -4.257058 -72.409988 +v 77.455887 -4.257058 -79.459984 +v 77.455887 -5.857058 -79.459984 +v 78.455887 -5.857058 -72.409988 +v 74.805885 -4.257057 -87.259987 +v 77.205887 -4.257057 -86.659988 +v 77.205887 -5.857057 -86.659988 +v 78.905884 -4.257058 -100.909988 +v 83.355888 -4.257057 -105.459984 +v 76.205887 -3.007063 -4.659986 +v 79.305885 -3.007065 -7.759984 +v 76.555885 -3.007065 -9.359987 +v 73.055885 -2.657064 -7.759984 +v 60.255886 -3.007061 -26.859983 +v 57.105885 -3.007059 -23.709984 +v 60.255886 -2.657061 -20.559984 +v 61.855885 -3.007060 -24.059984 +v 55.555885 -3.007061 3.390016 +v 60.105885 -3.007062 5.890017 +v 60.255886 -3.007063 -1.509984 +v 73.155884 -3.007061 -34.209988 +v 66.355888 -3.007058 -34.759987 +v 66.655884 -3.007059 -28.559984 +v 73.055885 -3.007063 -26.859983 +v 66.655884 -2.657062 -20.559984 +v 60.255886 -2.657062 -14.159984 +v 66.655884 -2.657063 -14.159984 +v 73.055885 -2.657063 -20.559984 +v 73.055885 -2.657064 -14.159984 +v 60.255886 -2.657062 -7.759984 +v 66.655884 -2.657063 -7.759984 +v 90.005882 -5.057072 53.640018 +v 90.005882 -5.057071 47.240021 +v 83.605888 -5.057070 47.240021 +v 83.605888 -5.057071 53.640018 +v 83.605888 -5.057069 40.840019 +v 77.205887 -5.057069 40.840019 +v 77.205887 -5.057069 47.240021 +v 83.605888 -5.057070 34.440018 +v 77.205887 -5.057069 34.440018 +v 70.805885 -5.057068 40.840019 +v 70.805885 -5.057069 47.240021 +v 70.805885 -5.057068 34.440018 +v 88.455887 1.342929 34.440014 +v 88.455887 1.342929 40.840015 +v 83.605888 6.142931 40.840012 +v 83.605888 6.142931 34.440010 +v 88.455887 1.342931 29.640015 +v 70.805885 1.342933 29.640015 +v 77.205887 1.342932 29.640015 +v 77.205887 6.142931 34.440010 +v 70.805885 6.142932 34.440010 +v 70.805885 -5.057067 28.040016 +v 77.205887 -5.057068 28.040016 +v 77.205887 7.442931 40.840012 +v 66.005882 1.342934 29.590015 +v 65.955887 1.342934 52.090015 +v 66.005882 1.342932 46.540016 +v 70.805885 6.142932 47.240013 +v 88.455887 1.342931 52.090015 +v 82.855888 1.342931 52.040016 +v 83.605888 6.142931 47.240013 +v 88.455887 1.342929 47.240017 +v 66.005882 1.342933 35.190014 +v 81.705887 4.642931 48.740013 +v 71.555885 1.342933 52.040016 +v 72.755882 4.642932 48.740013 +v 71.555885 1.342931 53.640015 +v 72.755882 4.642933 53.640011 +v 83.605888 1.342931 29.640015 +v 83.605888 -5.057069 28.040016 +v 90.005882 -5.057070 28.040016 +v 75.805885 -4.207060 -40.009983 +v 67.655884 -4.057058 -40.009983 +v 66.455887 -3.007060 -37.909985 +v 73.805885 -3.007060 -36.309986 +v 88.605888 -3.907063 -33.609982 +v 79.355888 -3.007060 -34.459988 +v 83.605888 -3.007063 -31.159985 +v 63.005886 -4.207057 -40.009983 +v 63.005886 -4.907057 -46.409981 +v 56.605885 -4.507057 -46.409981 +v 56.605885 -3.907060 -40.009983 +v 69.405884 -4.607059 -46.409981 +v 75.805885 -4.757060 -46.409981 +v 82.205887 -4.257061 -40.009983 +v 82.205887 -5.407060 -46.409981 +v 46.805885 -2.657055 -62.209988 +v 50.205883 -2.657055 -60.809986 +v 50.205883 -2.657053 -65.609985 +v 45.405884 -2.657053 -65.609985 +v 53.605885 -2.657056 -62.209988 +v 55.005886 -2.657054 -65.609985 +v 56.605885 -5.057056 -59.209984 +v 56.455883 -5.057055 -65.609985 +v 54.605885 -5.057056 -61.209984 +v 50.205883 -5.057056 -59.359982 +v 50.205883 -5.107054 -52.809982 +v 56.605885 -5.157056 -52.809982 +v 50.205883 -4.407055 -46.409981 +v 63.005886 -5.057056 -59.209984 +v 63.005886 -5.057055 -65.609985 +v 63.005886 -5.257056 -52.809982 +v 69.405884 -5.107059 -59.209984 +v 69.405884 -5.057056 -65.609985 +v 69.405884 -4.607059 -52.809982 +v 75.805885 -5.057057 -59.209984 +v 75.805885 -5.057057 -65.609985 +v 75.805885 -4.707060 -52.809982 +v 82.205887 -5.507061 -52.809982 +v 53.905884 -3.007056 -34.459988 +v 53.905884 2.592944 -34.459988 +v 59.455883 3.392942 -36.909988 +v 59.455883 -3.007058 -36.309986 +v 79.355888 2.592940 -34.459988 +v 83.605888 3.392937 -31.159988 +v 77.705887 2.592938 -31.709988 +v 81.355888 3.392939 -28.859987 +v 66.455887 2.592940 -37.909985 +v 73.855888 3.392939 -36.909988 +v 45.655884 -5.057062 30.540016 +v 47.055885 -5.057061 32.640018 +v 46.555885 1.342939 33.140015 +v 44.955883 1.342938 30.790014 +v 38.055885 -5.057062 41.590019 +v 33.905884 -5.057062 35.390018 +v 34.605885 1.342938 35.090015 +v 38.605885 1.342937 41.090015 +v 32.405884 -5.057062 28.040016 +v 33.155884 1.342938 28.040014 +v 35.655884 4.642938 34.640011 +v 39.405884 4.642937 40.240013 +v 34.355885 4.642938 28.040012 +v 33.155884 1.342939 21.640015 +v 34.355885 4.642941 21.640013 +v 39.805885 -5.057060 32.940018 +v 42.555885 -5.057062 37.090019 +v 38.805885 -5.057063 28.040016 +v 48.855885 1.342936 34.690014 +v 51.605885 1.342935 35.190014 +v 51.605885 4.642937 36.390011 +v 48.405884 4.642937 35.790012 +v 45.705883 4.642936 33.990013 +v 43.905884 4.642939 31.240013 +v 178.205887 -14.657098 215.990005 +v 178.205887 -14.657099 222.390015 +v 184.605881 -14.657101 222.390015 +v 184.605881 -14.657100 215.990005 +v 178.205887 -14.657099 209.590012 +v 184.605881 -14.657100 209.590012 +v 184.605881 -14.657100 228.790009 +v 191.005890 -14.657102 228.790009 +v 191.005890 -14.657102 222.390015 +v 191.005890 -14.657101 215.990005 +v 191.005890 -14.657101 209.590012 +v 184.605881 -14.657100 203.190002 +v 191.005890 -14.657101 203.190002 +v 184.605881 -14.657100 196.790009 +v 191.005890 -14.657101 196.790009 +v 29.605890 34.392960 -161.010010 +v 32.605888 37.592960 -158.960007 +v 30.205891 37.592960 -158.960007 +v 33.805889 37.592960 -161.010010 +v 30.205891 37.592960 -163.110001 +v 29.455891 37.592960 -161.010010 +v 32.605888 37.592960 -163.110001 +v 12.605889 37.592964 -158.960007 +v 13.355889 37.592964 -161.010010 +v 13.455891 42.642963 -161.010025 +v 12.405890 42.642963 -159.310013 +v 12.605889 37.592960 -163.110001 +v 12.405890 42.642960 -162.710022 +v 10.205890 37.592960 -163.110001 +v 10.455891 42.642963 -162.710022 +v 27.205891 34.392963 -155.210007 +v 29.405890 40.642960 -161.010025 +v 27.055889 40.642963 -155.360016 +v 21.405890 34.392967 -152.809998 +v 21.405890 40.642967 -153.010025 +v 21.405890 40.642956 -169.010025 +v 21.405890 34.392956 -169.210007 +v 15.605888 34.392960 -166.809998 +v 15.755890 40.642960 -166.660019 +v 27.055889 40.642956 -166.660019 +v 27.205891 34.392956 -166.809998 +v 27.905888 27.992956 -167.510010 +v 21.405888 27.992964 -170.210007 +v 30.405890 42.642960 -159.310013 +v 30.205893 47.192959 -158.959961 +v 29.405891 47.192959 -161.009964 +v 29.355890 42.642960 -161.010025 +v 30.205893 47.192959 -163.109955 +v 30.405890 42.642960 -162.710022 +v 32.605892 47.192959 -163.109955 +v 32.355892 42.642960 -162.710022 +v 33.805893 47.192959 -161.009964 +v 33.355892 42.642960 -161.010025 +v 32.355892 42.642960 -159.310013 +v -117.794121 -16.657030 -98.509979 +v -122.594116 -16.657028 -97.609978 +v -122.594116 -16.657024 -91.209976 +v -116.194115 -16.657026 -91.209976 +v -123.094116 -16.657022 -101.509979 +v -122.594116 -17.157028 -84.809982 +v -128.994125 -18.157028 -84.809982 +v -128.994125 -18.457024 -78.409981 +v -122.594116 -17.657024 -78.409981 +v -128.594116 -16.657024 -103.909981 +v -128.994125 -17.457027 -97.609978 +v -110.794121 -16.657024 -88.709976 +v -113.944115 -16.657028 -93.909981 +v -128.994125 -17.707024 -91.209976 +v -116.194115 -16.807030 -84.809982 +v -98.894119 -10.257028 -97.309982 +v -104.144119 -10.257029 -93.859978 +v -101.394119 -10.257028 -87.009979 +v -95.744118 -10.257031 -89.759979 +v -103.194115 -10.257027 -104.259979 +v -107.994118 -10.257028 -100.109978 +v -108.594116 -10.357026 -110.509979 +v -112.844116 -10.357027 -105.709976 +v -106.994118 -10.257030 -84.309982 +v -109.244118 -10.257030 -90.259979 +v -112.594116 -10.357028 -95.709976 +v -116.644119 -10.357026 -100.559982 +v -98.894119 -3.857029 -97.309990 +v -95.744118 -3.857029 -89.759987 +v -95.744118 2.542971 -89.759987 +v -98.894119 2.542971 -97.309990 +v -103.194115 -3.857028 -104.259987 +v -103.194115 2.542972 -104.259987 +v -108.594116 -3.857027 -110.509987 +v -108.594116 2.542974 -110.509987 +v -90.294121 10.442969 -91.959991 +v -93.694115 9.542971 -100.059998 +v -86.994118 16.492971 -102.759995 +v -91.794121 15.392971 -110.709991 +v -98.244118 9.242970 -107.459991 +v -97.794121 13.992972 -117.759995 +v -103.944115 9.192975 -114.159996 +v -90.944115 20.742971 -119.910004 +v -99.094116 20.292976 -124.910004 +v -105.644119 14.542974 -122.559998 +v -111.394119 8.992973 -118.659996 +v -115.594116 2.542976 -114.709984 +v -111.394119 16.342976 -128.910004 +v -113.994118 11.342978 -126.409996 +v -119.394119 8.092977 -122.309998 +v -122.144119 -10.357024 -103.659981 +v 10.805883 -4.857056 4.490013 +v 9.955883 -5.507054 8.440014 +v 18.055883 -5.207056 5.340014 +v 11.805883 -3.807055 -1.609987 +v 4.455884 -3.407054 -1.609987 +v 4.105883 -4.957055 4.590014 +v 18.255884 -3.857056 -1.859987 +v 24.355885 -3.707057 -1.659987 +v 24.605885 -4.907057 5.090014 +v 30.305883 -2.707057 -7.009984 +v 24.605885 -2.807057 -8.009984 +v 30.705885 -3.707057 -0.209987 +v 32.305885 -4.307058 6.590014 +v 38.155884 -2.957057 -11.859987 +v 36.555885 -2.857058 -6.659986 +v 43.555885 -3.007060 -7.959983 +v -4.694117 -5.857053 6.140014 +v 2.755883 -5.857052 8.940014 +v 18.205885 -5.257058 11.190014 +v 24.605885 -5.257059 11.190014 +v 16.455885 -5.207057 18.290018 +v 22.205885 -5.057056 15.390018 +v 33.255886 -2.357056 -24.959984 +v 30.755884 -1.707054 -28.959984 +v 31.005884 -1.857057 -20.809984 +v 34.005886 -2.657057 -19.409985 +v 26.655884 -1.457055 -33.259987 +v 24.605885 -0.557056 -27.209986 +v 32.305885 -2.707057 -13.859983 +v 38.205883 -4.007060 4.440017 +v 34.205883 -4.807059 12.340014 +v 40.455883 -4.857060 11.340014 +v 37.005886 -3.557059 -0.759987 +v 40.155884 -3.507057 -18.909985 +v 24.605885 -1.957056 -14.409985 +v 24.605885 -1.007056 -20.809986 +v 5.405884 -0.157054 -8.009986 +v 11.805884 -1.207055 -8.009985 +v 11.805884 1.842945 -14.409986 +v 5.405884 2.492946 -14.409986 +v 11.805884 2.542946 -20.809988 +v 18.205885 1.392945 -20.809986 +v 18.205885 1.292945 -27.209986 +v 11.805884 1.842946 -27.209988 +v 18.205885 0.042945 -14.409986 +v 18.205885 -2.007056 -8.009985 +v -56.244114 17.692970 -124.309998 +v -50.794113 16.942966 -129.660004 +v -61.244114 18.492970 -127.709991 +v -35.244118 -5.057035 -127.609985 +v -35.244118 1.342965 -127.609985 +v -39.694118 1.342964 -123.159988 +v -39.694118 -5.057036 -123.159988 +v -53.344112 13.442966 -122.059998 +v -48.044113 14.042968 -126.909996 +v -42.644112 14.992967 -133.010010 +v -44.694115 18.592970 -135.160004 +v -44.994118 10.142963 -125.609993 +v -40.494118 10.842964 -131.159988 +v -41.894115 5.442966 -125.309990 +v -37.994118 5.892964 -129.459991 +v -34.544113 18.092966 -137.710007 +v -37.144112 19.592964 -140.760010 +v -33.494114 12.992964 -135.559982 +v -32.244118 7.842965 -133.759995 +v -31.494116 1.342965 -132.959991 +v -39.394115 -5.057037 -116.809990 +v -32.994118 -5.057038 -116.809990 +v -31.844116 -5.057037 -123.209984 +v -26.594116 -5.007039 -116.809990 +v -26.844116 -5.057035 -125.409988 +v -44.594116 -5.057035 -119.159988 +v -18.644117 0.192961 -136.909988 +v -19.094116 4.292961 -137.759995 +v -25.144117 2.542963 -134.959991 +v -24.744116 -2.207037 -134.109985 +v -25.894117 2.542963 -136.259995 +v -19.844116 4.292964 -139.059982 +v -21.194115 14.192962 -142.010010 +v -21.244112 19.092960 -144.360001 +v -28.944115 18.292963 -141.910004 +v -28.044115 13.492965 -139.659988 +v -20.694115 8.342963 -140.209991 +v -26.094114 7.692963 -137.309982 +v -23.394114 21.592966 -148.309998 +v -31.094112 20.742962 -145.809998 +v 5.405881 -14.657068 177.590027 +v 5.405881 -14.657068 183.990036 +v 11.805882 -14.657070 183.990036 +v 11.805882 -14.657069 177.590027 +v 5.405881 -14.657068 171.190033 +v 11.805882 -14.657069 171.190033 +v 5.405881 -14.657066 164.790039 +v 11.805882 -14.657068 164.790039 +v 5.405881 -14.657067 158.390030 +v 11.805882 -14.657069 158.390030 +v 5.405881 -14.657068 151.990036 +v 11.805882 -14.657068 151.990036 +v 5.405881 -14.657067 145.590027 +v 11.805882 -14.657068 145.590027 +v 18.205883 -14.657070 183.990036 +v 18.205883 -14.657070 177.590027 +v 18.205883 -14.657071 171.190033 +v 18.205883 -14.657070 164.790039 +v 18.205883 -14.657069 158.390030 +v 18.205883 -14.657069 151.990036 +v 18.205883 -14.657070 145.590027 +v 24.605883 -14.657070 164.790039 +v 24.605883 -14.657070 158.390030 +v 24.605883 -14.657070 151.990036 +v -7.394119 -14.657064 139.190033 +v -7.394119 -14.657065 145.590027 +v -0.994118 -14.657067 145.590027 +v -0.994118 -14.657066 139.190033 +v -0.994118 -14.657066 164.790039 +v -0.994118 -14.657067 171.190033 +v -7.394119 -14.657067 177.590027 +v -7.394119 -14.657066 183.990036 +v -0.994118 -14.657067 183.990036 +v -0.994118 -14.657067 177.590027 +v -7.394119 -14.657066 171.190033 +v -7.394119 -14.657065 164.790039 +v -0.994118 -14.657066 158.390030 +v -0.994118 -14.657066 151.990036 +v -13.794118 -14.657065 177.590027 +v -13.794118 -14.657065 183.990036 +v -7.394119 -14.657065 158.390030 +v -13.794118 -14.657065 171.190033 +v -13.794118 -14.657064 164.790039 +v -7.394119 -14.657065 151.990036 +v -13.794118 -14.657064 158.390030 +v 5.405881 -14.657068 139.190033 +v -13.794118 -14.657064 151.990036 +v -13.794118 -14.657064 145.590027 +v -26.594118 -14.657063 164.790039 +v -26.594118 -14.657064 171.190033 +v -20.194118 -14.657064 171.190033 +v -20.194118 -14.657063 164.790039 +v -20.194118 -14.657064 183.990036 +v -20.194118 -14.657068 190.390015 +v -13.794118 -14.657069 190.390015 +v -20.194118 -14.657064 177.590027 +v -20.194118 -14.657063 158.390030 +v -20.194118 -14.657063 151.990036 +v -20.194118 -14.657063 145.590027 +v 166.955887 1.192914 85.140015 +v 172.005890 1.192915 80.840019 +v 172.005890 7.492914 78.290009 +v 166.955887 7.492916 82.540009 +v 166.955887 -4.907085 86.190018 +v 172.055893 -4.907084 81.890015 +v 160.955887 7.492915 85.390007 +v 166.955887 12.892913 79.140007 +v 160.955887 12.692916 81.940010 +v 160.955887 1.142917 87.940018 +v 160.955887 -4.907084 88.990013 +v 154.355881 7.542917 86.340012 +v 154.405884 10.942918 82.790009 +v 154.405884 1.192918 88.790016 +v 154.405884 -4.907085 89.840019 +v 147.905884 7.542917 84.840012 +v 148.055893 10.242917 80.340012 +v 148.055893 1.392918 86.290016 +v 148.055893 -4.907081 87.390015 +v 141.755890 7.592918 85.440010 +v 141.855881 12.092919 81.490005 +v 141.855881 3.392919 87.440018 +v 141.855881 -4.857080 88.490013 +v 135.255890 7.542919 85.840012 +v 135.255890 12.942920 82.440010 +v 135.255890 2.292921 88.390015 +v 172.005890 12.942914 74.840012 +v 43.005882 -14.657073 140.590027 +v 38.405880 -14.657071 140.340027 +v 37.405880 -14.657072 145.590027 +v 43.805882 -14.657072 145.590027 +v 31.005882 -14.657072 177.590027 +v 31.005882 -14.657073 183.990036 +v 37.405880 -14.657073 183.990036 +v 37.405880 -14.657073 177.590027 +v 31.005882 -14.657072 171.190033 +v 37.405880 -14.657073 171.190033 +v 31.005882 -14.657071 164.790039 +v 37.405880 -14.657072 164.790039 +v 31.005882 -14.657071 158.390030 +v 37.405880 -14.657072 158.390030 +v 31.005882 -14.657072 151.990036 +v 37.405880 -14.657072 151.990036 +v 31.005882 -14.657071 145.590027 +v 31.005882 -14.657071 139.190033 +v 43.805882 -14.657074 183.990036 +v 43.805882 -14.657074 177.590027 +v 43.805882 -14.657074 171.190033 +v 43.805882 -14.657073 164.790039 +v 43.805882 -14.657074 158.390030 +v 43.805882 -14.657073 151.990036 +v 50.205879 -14.657075 183.990036 +v 50.205879 -14.657074 177.590027 +v 50.205879 -14.657075 171.190033 +v 50.205879 -14.657074 164.790039 +v 50.205879 -14.657074 158.390030 +v 50.205879 -14.657074 151.990036 +v 50.205879 -14.657074 145.590027 +v 50.205879 -14.657074 139.190033 +v 56.605881 -14.657076 183.990036 +v 56.605881 -14.657076 177.590027 +v 56.605881 -14.657076 171.190033 +v 56.605881 -14.657076 164.790039 +v 56.605881 -14.657075 158.390030 +v 56.605881 -14.657075 151.990036 +v 56.605881 -14.657075 145.590027 +v 56.605881 -14.657075 139.190033 +v 63.005882 -14.657077 183.990036 +v 63.005882 -14.657077 177.590027 +v 63.005882 -14.657078 171.190033 +v 63.005882 -14.657076 164.790039 +v 63.005882 -14.657076 158.390030 +v 63.005882 -14.657075 151.990036 +v 63.005882 -14.657077 145.590027 +v 63.005882 -14.657076 139.190033 +v 69.405884 -14.657078 183.990036 +v 69.405884 -14.657078 177.590027 +v 69.405884 -14.657078 171.190033 +v 69.405884 -14.657077 164.790039 +v 69.405884 -14.657077 158.390030 +v 69.405884 -14.657077 151.990036 +v 69.405884 -14.657077 145.590027 +v 69.405884 -14.657077 139.190033 +v 133.405884 -14.657087 183.990036 +v 133.405884 -14.657091 190.390015 +v 139.805893 -14.657092 190.390015 +v 139.805893 -14.657088 183.990036 +v 133.405884 -14.657086 177.590027 +v 139.805893 -14.657088 177.590027 +v 133.405884 -14.657087 171.190033 +v 139.805893 -14.657088 171.190033 +v 133.405884 -14.657088 164.790039 +v 139.805893 -14.657088 164.790039 +v 133.405884 -14.657086 158.390030 +v 139.805893 -14.657087 158.390030 +v 133.405884 -14.657086 151.990036 +v 139.805893 -14.657087 151.990036 +v 133.405884 -14.657086 145.590027 +v 139.805893 -14.657086 145.590027 +v 146.205887 -14.657094 190.390015 +v 146.205887 -14.657089 183.990036 +v 146.205887 -14.657089 177.590027 +v 146.205887 -14.657089 171.190033 +v 146.205887 -14.657089 164.790039 +v 146.205887 -14.657088 158.390030 +v 146.205887 -14.657087 151.990036 +v 146.205887 -14.657088 145.590027 +v 152.605881 -14.657094 190.390015 +v 152.605881 -14.657089 183.990036 +v 152.605881 -14.657090 177.590027 +v 152.605881 -14.657090 171.190033 +v 152.605881 -14.657089 164.790039 +v 152.605881 -14.657088 158.390030 +v 152.605881 -14.657089 151.990036 +v 152.605881 -14.657089 145.590027 +v 159.005890 -14.657091 183.990036 +v 159.005890 -14.657091 177.590027 +v 159.005890 -14.657092 171.190033 +v 159.005890 -14.657091 164.790039 +v 159.005890 -14.657090 158.390030 +v 159.005890 -14.657090 151.990036 +v 159.005890 -14.657091 145.590027 +v 165.405884 -14.657092 183.990036 +v 165.405884 -14.657091 177.590027 +v 165.405884 -14.657092 171.190033 +v 165.405884 -14.657092 164.790039 +v 165.405884 -14.657091 158.390030 +v 165.405884 -14.657091 151.990036 +v 165.405884 -14.657091 145.590027 +v 165.405884 -14.657097 190.390015 +v 171.805893 -14.657098 190.390015 +v 171.805893 -14.657092 183.990036 +v 171.805893 -14.657093 177.590027 +v 171.805893 -14.657093 171.190033 +v 171.805893 -14.657093 164.790039 +v 171.805893 -14.657092 158.390030 +v 171.805893 -14.657093 151.990036 +v 171.805893 -14.657092 145.590027 +v 122.455887 3.142938 -83.859985 +v 122.455887 3.442937 -84.059990 +v 122.455887 1.142937 -84.259987 +v 122.455887 1.192937 -84.009987 +v 122.455887 4.142936 -81.609985 +v 122.455887 4.492936 -81.609985 +v 122.455887 3.142936 -79.359985 +v 122.455887 3.442936 -79.159988 +v 122.455887 1.142936 -78.959984 +v 122.455887 1.142936 -79.209984 +v 121.005882 4.042937 -78.709984 +v 120.905884 1.342937 -77.659988 +v 120.855888 1.342937 -85.559990 +v 120.955887 4.042937 -84.509987 +v 122.455887 -5.057063 -84.809990 +v 120.355888 -5.057063 -85.309990 +v 121.155884 5.142936 -82.459984 +v 120.305885 -5.057064 -88.009987 +v 120.655884 1.342936 -87.259987 +v 123.805885 1.342935 -87.259987 +v 123.805885 -5.107065 -88.009987 +v 120.805885 4.642937 -86.109985 +v 123.805885 4.642936 -86.109985 +v 121.005882 6.242936 -82.659988 +v 0.655888 30.142962 -150.460007 +v 0.855889 36.592957 -150.860001 +v 2.755889 36.592957 -147.610001 +v 2.305888 30.142963 -147.610001 +v 0.855889 36.592960 -144.360001 +v 0.655888 30.142958 -144.760010 +v -2.844111 36.592960 -144.360001 +v -2.644112 30.142958 -144.760010 +v -0.994110 44.542957 -174.410019 +v 0.855889 36.592972 -177.660004 +v -2.844111 36.592972 -177.660004 +v -2.844111 36.592957 -150.860001 +v -4.744111 36.592957 -147.610001 +v -0.994110 44.542957 -147.610016 +v -134.444122 -5.807039 51.540020 +v -130.094116 -5.207039 51.290020 +v -135.694122 -4.157038 53.040020 +v -130.194122 -3.807036 51.040020 +v -114.844116 -6.607037 32.840019 +v -110.994118 -5.907037 32.540020 +v -113.394119 -5.857040 34.340019 +v -114.244118 -3.907039 36.190018 +v -132.344116 -4.707036 42.240021 +v -132.344116 -4.957036 41.940018 +v -132.294113 -4.007037 39.790020 +v -132.294113 -3.757035 39.740021 +v -132.344116 -5.107036 37.640018 +v -132.344116 -4.857036 37.340019 +v -145.044113 24.642967 22.990017 +v -146.394119 24.842968 24.140017 +v -142.544113 29.592968 26.640020 +v -145.844116 24.992970 26.190018 +v -144.194122 24.892969 26.340017 +v -143.694122 24.692968 24.340017 +v -69.794121 18.942963 -33.109982 +v -69.744118 18.342964 -29.959980 +v -61.494114 18.942963 -29.809982 +v -61.594112 20.142960 -36.109982 +v -71.844116 18.092960 -22.509979 +v -61.444115 18.092958 -23.459980 +v -73.644119 15.242962 -47.659977 +v -65.444115 17.792961 -48.159981 +v -68.144119 16.092964 -53.859978 +v 107.905884 7.792939 -84.809998 +v 111.105888 7.792938 -84.809998 +v 111.055885 7.792939 -91.209991 +v 107.855888 7.792940 -91.259995 +v 107.955887 7.792939 -78.409996 +v 111.155884 7.792938 -78.409996 +v 107.955887 7.792939 -71.959991 +v 111.155884 7.792938 -72.009995 +v 111.155884 8.142936 -78.409996 +v 111.155884 8.142936 -72.009995 +v 107.955887 7.742939 -72.009995 +v 107.905884 7.742939 -78.409996 +v 111.105888 8.142936 -84.809998 +v 107.905884 7.742939 -84.809998 +v 111.055885 8.142940 -91.209991 +v 107.855888 7.742940 -91.209991 +v 117.405884 7.742938 -78.409996 +v 117.405884 7.742937 -72.009995 +v 123.805885 7.742937 -78.409996 +v 123.805885 7.742936 -72.009995 +v 117.405884 7.742938 -84.809998 +v 123.805885 7.742937 -84.809998 +v 117.405884 7.742938 -91.209991 +v 123.805885 7.742937 -91.209991 +v 123.805885 1.342937 -91.209984 +v 123.805885 1.342937 -84.809990 +v 123.805885 -5.057063 -91.209984 +v 123.805885 -5.057063 -84.809990 +v 123.805885 1.342936 -78.409988 +v 123.805885 -5.057064 -78.409988 +v 123.805885 -5.057064 -72.009987 +v 123.805885 1.342936 -72.009987 +v 117.405884 -5.057063 -72.009987 +v 117.405884 -5.057063 -78.409988 +v 111.105888 -5.057062 -78.409988 +v 111.155884 -5.057062 -72.009987 +v 117.405884 -5.057062 -84.809990 +v 111.105888 -5.057061 -84.809990 +v 117.405884 -5.057062 -91.209984 +v 111.055885 -5.057061 -91.209984 +v 117.405884 1.342938 -91.209984 +v 111.055885 1.342939 -91.209984 +v 120.355888 -5.107064 -75.209984 +v 123.805885 -5.057065 -75.209984 +v 123.805885 1.342934 -75.959984 +v 120.705887 1.342934 -75.959984 +v 120.855888 4.642935 -77.109985 +v 123.805885 4.642934 -77.159988 +v 121.155884 5.142936 -80.759987 +v 123.805885 5.142936 -80.759987 +v 123.805885 6.242936 -80.559990 +v 120.355888 6.942936 -80.409996 +v -144.444122 14.542964 50.590023 +v -142.294113 10.692966 48.090008 +v -139.194122 9.992964 51.640011 +v -142.294113 14.092965 53.590023 +v -143.494125 17.542965 47.740021 +v -140.894119 14.442963 44.590023 +v -140.744125 18.892967 48.990021 +v -136.844116 16.092962 45.940022 +v -135.844116 13.242962 50.340023 +v -130.844116 9.592965 49.640011 +v -132.494125 12.542966 43.490025 +v -140.044113 16.792969 52.590023 +v -137.394119 7.942961 52.240013 +v 5.405881 -14.657072 196.790009 +v 5.405881 -14.657074 203.190002 +v 11.805882 -14.657074 203.190002 +v 11.805882 -14.657073 196.790009 +v 5.405881 -14.657072 190.390015 +v 11.805882 -14.657073 190.390015 +v 11.805882 -14.657073 222.390015 +v 11.805882 -14.657075 228.790009 +v 18.205883 -14.657075 228.790009 +v 18.205883 -14.657075 222.390015 +v 11.805882 -14.657074 215.990005 +v 18.205883 -14.657075 215.990005 +v 11.805882 -14.657074 209.590012 +v 18.205883 -14.657075 209.590012 +v 18.205883 -14.657075 203.190002 +v 18.205883 -14.657074 196.790009 +v 18.205883 -14.657075 190.390015 +v 24.605883 -14.657076 222.390015 +v 24.605883 -14.657076 215.990005 +v -0.994118 -14.657072 222.390015 +v -0.994118 -14.657071 228.790009 +v 5.405881 -14.657073 228.790009 +v 5.405881 -14.657073 222.390015 +v -0.994118 -14.657071 215.990005 +v 5.405881 -14.657073 215.990005 +v -0.994118 -14.657072 209.590012 +v 5.405881 -14.657073 209.590012 +v -0.994118 -14.657072 203.190002 +v -13.794118 -14.657070 222.390015 +v -13.794118 -14.657070 228.790009 +v -7.394119 -14.657071 228.790009 +v -7.394119 -14.657071 222.390015 +v -13.794118 -14.657070 215.990005 +v -7.394119 -14.657071 215.990005 +v -7.394119 -14.657071 209.590012 +v -13.794118 -14.657069 209.590012 +v -13.794118 -14.657070 203.190002 +v -7.394119 -14.657071 203.190002 +v -13.794118 -14.657070 196.790009 +v -7.394119 -14.657070 196.790009 +v -0.994118 -14.657071 196.790009 +v -26.594118 -14.657067 196.790009 +v -26.594118 -14.657067 203.190002 +v -20.194118 -14.657069 203.190002 +v -20.194118 -14.657068 196.790009 +v -20.194118 -14.657068 222.390015 +v -20.194118 -14.657069 228.790009 +v -20.194118 -14.657069 215.990005 +v -20.194118 -14.657069 209.590012 +v 45.855888 17.242956 -178.010010 +v 41.755890 17.242956 -178.010010 +v 42.005890 23.692955 -177.559998 +v 45.605888 23.692955 -177.559998 +v 45.455887 30.142956 -177.309998 +v 42.155888 30.142956 -177.309998 +v 47.105888 30.142958 -174.410004 +v 47.405888 23.692957 -174.410004 +v 45.455887 30.142960 -171.559998 +v 45.605888 23.692959 -171.309998 +v 41.955887 36.592964 -177.660004 +v 45.655888 36.592964 -177.660004 +v -149.794113 13.542975 -58.659977 +v -149.894119 13.542977 -55.659977 +v -152.544113 10.342974 -54.209995 +v -152.394119 10.342976 -60.209995 +v -164.094116 4.692978 -60.659988 +v -164.444122 3.042978 -60.609985 +v -168.894119 2.442979 -60.809986 +v -168.894119 4.542978 -60.909988 +v -159.844116 4.342978 -65.459984 +v -163.544113 4.542975 -65.459984 +v -159.294113 4.542977 -60.659988 +v -159.044113 2.442977 -60.609985 +v -159.594116 3.542979 -65.459984 +v -163.794113 3.742979 -65.459984 +v 111.155884 22.442938 -67.560005 +v 111.155884 23.742935 -62.409985 +v 116.155884 23.842939 -65.109970 +v 116.555885 22.992937 -70.959999 +v 111.155884 19.992937 -71.809998 +v 116.405884 21.692940 -77.860001 +v 123.955894 26.592937 -79.459969 +v 131.405884 29.492937 -80.909973 +v 131.355881 29.792940 -88.059975 +v 123.905891 26.892935 -86.609970 +v 116.355888 21.792936 -85.010002 +v 131.805893 28.792934 -95.059975 +v 124.355896 26.192936 -93.659973 +v 116.755882 24.142939 -93.309975 +v 131.455887 28.392941 -101.109970 +v 124.005890 26.392942 -99.709969 +v 116.255882 24.892935 -99.359970 +v 131.905884 27.492937 -106.809975 +v 124.455894 26.142939 -105.409973 +v 116.705887 24.692940 -105.059975 +v 128.155884 25.692942 -112.209969 +v 124.505890 25.542942 -111.509972 +v 116.905884 22.742937 -109.860001 +v 121.105888 24.192940 -117.959969 +v 113.505882 22.192942 -116.360001 +v 124.155891 26.242935 -72.559975 +v 131.605881 29.192932 -74.009972 +v 107.655884 21.892941 -121.560005 +v 108.555885 17.592941 -115.209991 +v 103.955887 17.892941 -120.859993 +v 111.155884 22.442940 -105.010002 +v 111.105888 23.742945 -99.859970 +v 111.155884 20.042938 -109.259995 +v 104.405884 3.192934 -16.809988 +v 104.405884 3.142934 -16.459988 +v 104.405884 5.392935 -16.259989 +v 104.405884 5.642934 -16.559990 +v 105.105888 6.692933 -18.659983 +v 105.855888 8.292934 -15.259987 +v 110.105888 13.192931 -19.859985 +v 86.955887 2.592935 -26.909988 +v 84.205887 2.592937 -25.259987 +v 90.305885 3.392936 -22.009987 +v 91.655884 3.392936 -24.909988 +v 96.505882 2.592933 -20.809988 +v 96.755882 2.592935 -23.959988 +v 91.505882 -3.007065 -24.859983 +v 96.755882 -3.007065 -23.959984 +v 103.855888 3.392934 -24.009987 +v 104.105888 3.392932 -20.659988 +v 105.705887 7.542935 -22.059982 +v 104.055885 2.292936 -28.009987 +v 106.355888 7.342932 -27.659983 +v 104.055885 -4.107064 -28.009983 +v 104.055885 -3.007066 -23.809984 +v 86.955887 -3.007065 -26.909985 +v 104.405884 3.392932 -19.809988 +v 104.005882 -3.007068 -20.609983 +v 101.405884 -5.557062 -40.009983 +v 101.405884 -4.657067 -33.609982 +v 103.905884 -4.107064 -34.409981 +v 104.505882 -5.057065 -40.759983 +v 101.405884 -5.307062 -46.409981 +v 104.955887 -5.057064 -47.159981 +v 101.405884 -4.207067 -27.209984 +v 95.005882 -4.207066 -27.209984 +v 95.005882 -4.657066 -33.609982 +v 95.005882 -4.807062 -40.009983 +v 103.905884 2.292936 -34.409985 +v 104.505882 1.342937 -40.759987 +v 104.955887 1.342937 -47.159985 +v 106.805885 7.192936 -34.209991 +v 106.605888 7.192935 -40.859989 +v 109.555885 13.092935 -35.059978 +v 108.605888 13.092935 -41.559978 +v 104.955887 7.742936 -47.159988 +v 104.955887 14.142935 -47.159977 +v 102.905884 6.092934 -17.059982 +v 102.805885 3.392934 -18.109987 +v 99.955887 -5.057064 -51.059982 +v 106.205887 -5.057065 -50.709984 +v 106.805885 1.342937 -52.859985 +v 106.805885 7.742936 -52.859989 +v 102.305885 -3.007068 -20.559984 +v 102.605888 3.392933 -19.809988 +v 102.755882 6.692933 -18.659983 +v 102.955887 8.292936 -15.259987 +v 103.105888 7.192933 -15.009986 +v 102.305885 -3.007066 -17.859983 +v 106.305885 -5.057065 -50.709984 +v 106.905884 -5.057063 -52.709984 +v 100.355888 -4.257064 -53.009983 +v 99.955887 -4.257065 -51.059982 +v 93.755882 -4.257062 -52.559982 +v 93.755882 -5.057060 -52.559982 +v 89.355888 18.592945 -127.859993 +v 92.805885 20.942944 -131.010010 +v 86.355888 23.492945 -134.059998 +v 82.705887 21.092945 -130.860001 +v 87.405884 14.392946 -127.009995 +v 81.005882 14.842946 -130.110001 +v 85.805885 7.892948 -124.859993 +v 79.705887 8.092948 -128.209991 +v 79.755882 24.992950 -139.010010 +v 76.305885 21.142952 -135.410004 +v 76.305885 14.842948 -135.460007 +v 75.155884 8.342949 -133.859985 +v 95.205887 17.242949 -123.859993 +v 99.405884 19.842945 -126.209991 +v -127.994118 -8.557037 39.990021 +v -120.894119 -8.357038 39.990021 +v -120.894119 -6.457036 32.090019 +v -127.994118 -6.557036 30.990011 +v -116.794121 -5.607039 47.140018 +v -116.244118 -7.507038 43.840019 +v -120.894119 -5.707038 47.890018 +v -116.794121 -6.057036 32.890018 +v -116.244118 -7.507039 36.140018 +v -122.594116 -10.157037 30.390013 +v -122.594116 -9.907036 23.990013 +v -128.994125 -10.057034 23.990013 +v -128.994125 -10.307035 30.390013 +v -116.894119 -8.957042 56.440018 +v -116.194115 -9.707038 49.590019 +v -122.594116 -10.107037 49.590019 +v -123.294121 -10.057040 57.190018 +v 27.905888 27.992956 -154.510010 +v 30.255888 22.192957 -152.210007 +v 33.905888 22.192959 -161.010010 +v 30.605888 27.992960 -161.010010 +v 21.405888 27.992958 -151.809998 +v 21.405888 22.192959 -148.510010 +v 8.905888 22.192963 -161.010010 +v 12.205888 27.992962 -161.010010 +v 14.905888 27.992958 -167.510010 +v 12.555888 22.192965 -169.860001 +v 42.805885 4.592942 -20.609987 +v 44.455883 3.392943 -17.459988 +v 47.555885 4.592942 -19.109987 +v 47.205883 3.392940 -21.059988 +v 44.155884 3.392943 -22.009987 +v 46.605885 -3.007059 -20.709984 +v 46.855885 -3.007059 -19.359983 +v 44.605885 5.342943 -18.059990 +v 47.455883 5.342942 -20.359989 +v 45.205883 7.442941 -19.859982 +v 45.205883 4.592942 -19.859987 +v 43.655884 5.342942 -21.559990 +v 46.355885 2.592941 -26.909988 +v 49.105885 2.592942 -25.259987 +v -120.294121 2.042960 60.190014 +v -122.994118 6.842958 63.440010 +v -116.644119 7.392961 63.290012 +v -113.944115 2.592959 60.040016 +v -110.194115 8.742958 63.090012 +v -107.494118 3.942957 59.840012 +v -103.744118 9.892957 63.140011 +v -101.044121 5.092958 59.840012 +v -97.694115 10.242957 64.490005 +v -94.744118 5.242956 61.090012 +v -78.794121 1.342954 62.440014 +v -84.644119 1.342954 59.540016 +v -87.344116 5.792953 63.140011 +v -81.294121 5.492957 65.640015 +v -72.444115 1.342952 64.090019 +v -74.944115 5.292952 67.240013 +v -91.044121 10.342957 66.240005 +v -72.444115 -5.057045 64.090019 +v -78.794121 -5.057045 62.440018 +v -84.644119 -5.057044 59.540020 +v -64.544121 -5.057049 66.440018 +v -64.544121 1.342951 66.440018 +v -66.344116 6.342953 69.490013 +v -64.944115 10.742952 72.890007 +v -58.094116 10.742949 75.540009 +v -59.394115 6.342953 71.440018 +v -58.394115 1.342951 68.440018 +v 113.205894 38.042942 -12.259985 +v 113.255890 38.042938 -15.909985 +v 110.055893 48.042942 -14.109982 +v 77.405884 -11.657074 92.390022 +v 72.605888 -11.657074 92.390022 +v 72.605888 -11.707074 97.240021 +v 77.405884 -11.707074 97.240021 +v 82.205887 -11.707074 97.240021 +v 82.205887 -11.657074 92.390022 +v 72.605888 -11.857070 102.040024 +v 77.405884 -11.857072 102.040024 +v 82.205887 -11.857073 102.040024 +v 72.605888 -11.907072 106.840027 +v 77.405884 -11.907074 106.840027 +v 82.205887 -11.907074 106.840027 +v 72.605888 -11.857073 111.640022 +v 77.405884 -11.857074 111.640022 +v 82.205887 -11.857074 111.640022 +v 72.605888 -11.707075 116.440025 +v 77.405884 -11.707075 116.440025 +v 82.205887 -11.707076 116.440025 +v 72.605888 -11.457076 121.240021 +v 77.405884 -11.457077 121.240021 +v 82.205887 -11.457077 121.240021 +v 72.605888 -12.907074 97.540024 +v 72.605888 -12.657074 92.790024 +v 72.605888 -13.057072 102.240021 +v 72.605888 -13.107072 106.990021 +v 72.605888 -13.057074 111.740021 +v 72.605888 -12.907075 116.490021 +v 72.605888 -12.657076 121.240021 +v 77.405884 -12.657077 121.240021 +v 82.205887 -12.657077 121.240021 +v 77.405884 -12.907076 97.540024 +v 77.405884 -12.657074 92.790024 +v 82.205887 -12.657074 92.790024 +v 82.205887 -12.907076 97.540024 +v 77.405884 -13.057072 102.240021 +v 77.405884 -12.907075 116.490021 +v 82.205887 -12.907076 116.490021 +v 33.605881 -14.657066 107.190025 +v 30.855883 -14.657068 109.290024 +v 31.005882 -14.657066 113.590027 +v 45.155880 -14.657071 135.890030 +v 42.605881 -14.657072 132.390030 +v 41.855881 -14.657071 134.090027 +v 43.205879 -14.657070 136.440033 +v 37.455879 -14.657071 132.690033 +v 39.155880 -14.657071 134.090027 +v 36.205879 -14.657069 137.140030 +v 38.405880 -14.657069 136.540039 +v 43.805882 -14.657072 126.390022 +v 37.405880 -14.657071 126.390022 +v 31.005882 -14.657070 132.790039 +v 50.205879 -14.657073 132.790039 +v 31.005882 -14.657065 100.790024 +v 28.355883 -14.657064 101.990021 +v 30.405882 -14.657067 105.140022 +v 26.705883 -14.657068 129.340027 +v 29.355883 -14.657071 131.790039 +v 29.355883 -14.657070 126.940025 +v 23.305882 -14.657069 134.190033 +v 26.105883 -14.657066 137.240036 +v 25.305882 -14.657067 123.590027 +v 23.305882 -14.657065 125.840027 +v 31.005882 -14.657066 119.990021 +v 24.605883 -14.657065 119.990021 +v 31.005882 -14.657070 126.390022 +v 39.955883 -11.707069 135.040024 +v 41.555885 -12.107070 135.390015 +v 38.955883 -11.707069 136.340012 +v 39.905884 -10.357070 135.840012 +v 42.255882 -12.807070 136.340012 +v 41.305885 -12.407069 137.490021 +v 41.855881 -14.657073 138.790039 +v 39.805885 -11.707073 137.740021 +v 39.355881 -14.657073 138.490036 +v 70.955887 -10.957074 97.240021 +v 71.705887 -10.857073 97.990021 +v 72.405884 -10.857074 97.240021 +v 71.705887 -10.957070 96.490021 +v 72.005882 -14.657073 98.240021 +v 72.655884 -14.657074 97.590027 +v 71.355888 -14.657074 97.590027 +v 72.005882 -14.657074 96.940025 +v 70.955887 -10.957074 116.390022 +v 71.705887 -10.957074 117.140022 +v 72.405884 -10.857076 116.390022 +v 71.705887 -10.857076 115.640022 +v 72.005882 -14.657075 115.390022 +v 72.655884 -14.657075 116.040024 +v 71.355888 -14.657075 116.040024 +v 72.005882 -14.657074 116.690025 +v 37.405880 -14.657067 119.990021 +v 37.405880 -14.657067 113.590027 +v 37.405880 -14.657067 107.190025 +v 37.405880 -14.657065 100.790024 +v 31.005882 -14.657065 94.390022 +v 37.405880 -14.657066 94.390022 +v 43.805882 -14.657068 119.990021 +v 43.805882 -14.657068 113.590027 +v 43.805882 -14.657068 107.190025 +v 43.805882 -14.657067 100.790024 +v 43.805882 -14.657068 94.390022 +v 50.205879 -14.657073 126.390022 +v 50.205879 -14.657069 119.990021 +v 50.205879 -14.657069 113.590027 +v 50.205879 -14.657069 107.190025 +v 50.205879 -14.657068 100.790024 +v 50.205879 -14.657068 94.390022 +v 56.605881 -14.657074 132.790039 +v 56.605881 -14.657074 126.390022 +v 56.605881 -14.657070 119.990021 +v 56.605881 -14.657070 113.590027 +v 56.605881 -14.657069 107.190025 +v 56.605881 -14.657069 100.790024 +v 56.605881 -14.657069 94.390022 +v 50.205879 -14.657068 87.990021 +v 56.855881 -14.657068 88.840027 +v 63.005882 -14.657075 132.790039 +v 63.005882 -14.657075 126.390022 +v 63.005882 -14.657071 119.990021 +v 63.005882 -14.657071 113.590027 +v 63.005882 -14.657071 107.190025 +v 63.005882 -14.657071 99.840027 +v 64.105888 -14.657070 94.240021 +v 69.405884 -14.657076 132.790039 +v 69.405884 -14.657076 126.390022 +v 69.405884 -14.657072 119.990021 +v 69.405884 -14.657072 113.590027 +v 69.405884 -14.657072 107.190025 +v 69.505882 -14.657072 98.990021 +v 45.855888 17.242952 -157.760010 +v 45.855888 17.242956 -164.309998 +v 45.605888 24.692955 -164.460007 +v 45.605888 24.692951 -157.610001 +v 45.855888 17.242956 -151.210007 +v 45.605888 23.692955 -150.710007 +v 41.955887 22.142956 -164.410004 +v 41.955887 22.142952 -157.610001 +v 42.005890 24.692951 -157.610001 +v 42.005890 24.692955 -164.460007 +v 41.955887 22.142956 -150.809998 +v 42.005890 23.692955 -150.710007 +v 18.205885 4.042950 -52.809990 +v 24.605885 4.042949 -52.809990 +v 24.605885 4.042950 -59.209991 +v 18.205885 4.042951 -59.209991 +v 24.605885 2.942948 -48.709988 +v 28.755884 2.942949 -52.809986 +v 28.755884 2.942949 -59.209988 +v 29.155884 3.742948 -52.609989 +v 29.155884 3.742949 -59.409988 +v 30.055883 3.742948 -52.259991 +v 30.055883 3.742949 -59.759991 +v 24.755884 3.742948 -48.309990 +v 25.155884 3.742949 -47.459991 +v 18.205885 2.942949 -48.709988 +v 18.055883 3.742949 -48.309990 +v 17.655884 3.742950 -47.459991 +v 12.755885 3.742952 -52.259991 +v 13.655885 3.742952 -52.609989 +v 12.755885 3.742952 -59.759991 +v 13.655885 3.742952 -59.409988 +v 16.955885 4.092949 -63.859989 +v 18.055883 4.092949 -63.709991 +v 14.055884 2.942950 -52.809986 +v 14.055884 2.942950 -59.209988 +v 18.205885 3.542949 -63.309990 +v 24.555883 1.342948 -48.759987 +v 28.705885 1.342949 -52.809986 +v 28.705885 1.342950 -59.209988 +v 14.105884 1.342952 -59.209988 +v 14.105884 1.342951 -52.809986 +v 107.905884 -5.057061 -78.409988 +v 107.905884 -5.057061 -84.809990 +v 101.505882 -5.057060 -84.809990 +v 101.505882 -5.057060 -78.409988 +v 107.855888 -5.057060 -91.209984 +v 101.455887 -5.057059 -91.209984 +v -184.044113 13.642980 -53.609978 +v -183.194122 19.242979 -47.709984 +v -182.644119 12.592979 -47.909977 +v -182.444122 10.342980 -52.409992 +v -183.744125 15.242981 -57.009979 +v -211.894119 10.292985 -38.359993 +v -212.044113 22.592983 -45.109982 +v -220.944122 22.592989 -53.759983 +v -225.544113 10.292987 -51.609993 +v -190.644119 21.042978 -38.209984 +v -195.294113 17.192980 -34.459984 +v -191.394119 10.092979 -33.959991 +v -197.694122 21.042984 -42.009983 +v -198.794113 17.242981 -37.109982 +v -208.344116 10.092982 -28.559984 +v -203.044113 17.192982 -32.659981 +v -201.694122 17.242981 -35.709984 +v -198.594116 24.092981 -32.959988 +v -200.094116 12.592981 -41.259979 +v -196.594116 17.192982 -31.359987 +v -193.994125 10.092980 -28.559984 +v -200.494125 17.192984 -30.459988 +v -201.394119 10.092978 -26.009983 +v -190.294113 29.592976 -40.409985 +v -194.244125 29.592983 -43.159985 +v -186.494125 29.592979 -46.009987 +v -187.194122 29.592981 -41.959988 +v -185.394119 21.042976 -39.859982 +v -187.394119 19.892981 -61.409981 +v -188.344116 22.292978 -51.409981 +v 51.605885 -5.057065 47.240021 +v 44.255886 -5.057065 45.740021 +v 44.555885 1.342938 45.090015 +v 51.605885 1.342934 46.540016 +v 107.955887 -5.057061 -72.009987 +v 108.005882 -5.057065 -65.609985 +v 108.005882 1.342938 -65.609985 +v 107.955887 1.342938 -72.009987 +v 178.205887 -14.657088 119.990021 +v 178.205887 -14.657092 126.390022 +v 184.605881 -14.657093 126.390022 +v 184.605881 -14.657089 119.990021 +v 184.605881 -14.657094 132.790039 +v 184.605881 -14.657094 139.190033 +v 191.005890 -14.657095 139.190033 +v 191.005890 -14.657095 132.790039 +v 191.005890 -14.657094 126.390022 +v 191.005890 -14.657090 119.990021 +v 184.605881 -14.657089 113.590027 +v 191.005890 -14.657090 113.590027 +v 184.605881 -14.657089 107.190025 +v 191.005890 -14.657091 107.190025 +v 184.605881 -14.657089 100.790024 +v 191.005890 -14.657090 100.790024 +v 184.605881 -14.657089 94.390022 +v 191.005890 -14.657089 94.390022 +v -136.344116 3.692966 11.040017 +v -129.744125 4.392966 11.340016 +v -135.294113 7.842966 10.440014 +v -141.894119 7.142970 10.140015 +v -130.544113 -0.007033 13.940015 +v -123.894119 0.742966 14.190015 +v -133.594116 -10.357035 17.390013 +v -124.194115 -10.107037 15.190013 +v -124.194115 -3.707033 15.190013 +v -133.594116 -3.957035 17.390017 +v 115.055893 32.392937 -16.959982 +v 114.405891 26.192928 -16.559986 +v 110.105896 26.192936 -19.109985 +v 110.105896 32.392937 -19.859982 +v -26.594116 -5.057039 -104.009987 +v -22.794117 -4.207041 -99.059990 +v -18.944117 -4.207042 -98.859985 +v -20.194117 -4.657040 -104.009987 +v 24.105886 6.642954 -108.659988 +v 25.205887 8.892955 -108.659996 +v 25.105886 8.892951 -102.259995 +v 24.055885 6.492954 -102.259987 +v 25.105886 8.542951 -95.859993 +v 24.055883 6.142954 -95.859985 +v 18.855886 7.592954 -114.809998 +v 18.055885 8.392955 -115.059998 +v 18.555885 8.892956 -108.659996 +v 18.955887 8.092957 -108.659996 +v 18.605886 8.892952 -102.259995 +v 19.005886 8.092952 -102.259995 +v 18.605886 8.542952 -95.859993 +v 19.005886 7.742955 -95.859993 +v 16.955887 8.392955 -115.059998 +v 17.605886 8.892956 -108.659996 +v 17.705887 8.892952 -102.259995 +v 17.705887 8.542952 -95.859993 +v 18.555885 7.842954 -89.459991 +v 17.605886 7.842955 -89.459991 +v 24.605886 7.592954 -114.809998 +v 23.855886 8.092956 -108.659996 +v 24.255886 8.892955 -108.659996 +v 24.755886 8.392955 -115.059998 +v 23.805885 8.092952 -102.259995 +v 24.205887 8.892951 -102.259995 +v 23.805885 7.742954 -95.859993 +v 24.205887 8.542951 -95.859993 +v 18.755886 6.492955 -102.259987 +v 18.705887 6.642954 -108.659988 +v 18.755884 6.142955 -95.859985 +v 18.255886 6.392956 -114.459984 +v 18.705885 5.442954 -89.459984 +v 25.855886 8.392955 -115.059998 +v -0.994117 -3.807044 -91.209984 +v 5.405883 -3.457045 -91.209984 +v 5.405883 -4.057044 -97.609985 +v -0.994117 -3.957044 -97.609985 +v -19.844116 -4.557040 -110.409988 +v -13.794117 -4.107041 -110.409988 +v -13.794117 -4.257041 -116.809990 +v -19.594116 -4.607040 -116.809990 +v -13.794117 -4.507042 -97.609985 +v -7.394117 -4.207043 -97.609985 +v -7.394117 -3.907042 -104.009987 +v -13.794117 -4.257042 -104.009987 +v -26.594116 -4.957039 -110.409988 +v -0.994117 -3.607043 -104.009987 +v 18.205885 -3.757047 -91.209984 +v 25.005884 -4.207048 -90.559990 +v 24.605885 -4.807047 -97.609985 +v 18.205885 -4.607047 -97.609985 +v -179.994125 3.942981 -64.409988 +v -178.894119 4.942980 -68.209984 +v -181.844116 13.692983 -67.959991 +v -182.144119 10.342981 -63.709995 +v -212.294113 23.042984 -86.860001 +v -209.194122 32.092991 -87.409973 +v -210.844116 22.992990 -89.910004 +v -212.644119 10.192987 -87.709991 +v -210.294113 10.192987 -93.159996 +v -207.544113 22.992990 -89.410004 +v -204.394119 10.192987 -92.059998 +v 75.805885 -14.657084 215.990005 +v 75.805885 -14.657084 222.390015 +v 82.205887 -14.657085 222.390015 +v 82.205887 -14.657084 215.990005 +v 82.205887 -14.657085 228.790009 +v 88.605888 -14.657086 228.790009 +v 88.605888 -14.657085 222.390015 +v 88.605888 -14.657085 215.990005 +v 82.205887 -14.657084 209.590012 +v 88.605888 -14.657085 209.590012 +v 82.205887 -14.657084 203.190002 +v 88.605888 -14.657085 203.190002 +v 82.205887 -14.657084 196.790009 +v 88.605888 -14.657085 196.790009 +v 95.005882 -14.657087 228.790009 +v 95.005882 -14.657086 222.390015 +v 95.005882 -14.657087 215.990005 +v 95.005882 -14.657086 209.590012 +v 95.005882 -14.657086 203.190002 +v 95.005882 -14.657087 196.790009 +v 101.405884 -14.657089 228.790009 +v 101.405884 -14.657087 222.390015 +v 101.405884 -14.657087 215.990005 +v 101.405884 -14.657087 209.590012 +v 101.405884 -14.657087 203.190002 +v 101.405884 -14.657087 196.790009 +v 95.005882 -14.657085 190.390015 +v 101.405884 -14.657085 190.390015 +v 107.805885 -14.657089 228.790009 +v 107.805885 -14.657088 222.390015 +v 107.805885 -14.657088 215.990005 +v 107.805885 -14.657088 209.590012 +v 107.805885 -14.657089 203.190002 +v 107.805885 -14.657088 196.790009 +v 114.205887 -14.657090 228.790009 +v 114.205887 -14.657090 222.390015 +v 114.205887 -14.657089 215.990005 +v 114.205887 -14.657089 209.590012 +v 114.205887 -14.657089 203.190002 +v 114.205887 -14.657089 196.790009 +v 120.605888 -14.657091 228.790009 +v 120.605888 -14.657091 222.390015 +v 120.605888 -14.657090 215.990005 +v 120.605888 -14.657091 209.590012 +v 120.605888 -14.657090 203.190002 +v 120.605888 -14.657089 196.790009 +v 127.005882 -14.657093 228.790009 +v 127.005882 -14.657092 222.390015 +v -181.194122 12.392978 -34.959980 +v -183.294113 12.592979 -39.959980 +v -184.644119 13.542980 -33.409977 +v -179.094116 11.642977 -29.209984 +v -184.344116 15.042979 -26.809986 +v -182.344116 3.942980 -54.859989 +v -182.144119 3.942980 -61.259991 +v -182.144119 4.342981 -60.909988 +v -182.344116 4.342980 -55.259991 +v -182.144119 10.192979 -60.709995 +v -182.144119 10.142980 -60.409992 +v -182.144119 12.142980 -60.259979 +v -182.144119 12.442979 -60.509979 +v -182.244125 13.142982 -58.059978 +v -182.244125 13.492981 -58.059978 +v -182.344116 12.142982 -55.909977 +v -182.344116 12.442982 -55.609978 +v -182.344116 10.142982 -55.759995 +v -182.344116 10.192978 -55.409992 +v -176.694122 6.542977 -36.359989 +v -174.494125 6.242977 -30.659983 +v -170.194122 -1.057024 -30.659986 +v -171.444122 -0.907023 -36.709988 +v -180.294113 3.942980 -54.309990 +v -180.044113 3.942980 -61.709991 +v -180.794113 10.342979 -54.059994 +v -180.644119 10.342980 -52.359993 +v -180.344116 3.942977 -51.609989 +v -180.694122 13.092979 -60.909977 +v -180.494125 13.642982 -62.509979 +v -180.794113 15.242980 -59.109978 +v -180.944122 14.142980 -58.909977 +v -180.344116 10.342981 -63.659992 +v -180.594116 10.342982 -61.959995 +v -184.244125 10.342980 -52.459995 +v -184.544113 3.942978 -51.709991 +v -180.994125 14.142982 -57.159977 +v -180.894119 13.092978 -55.109978 +v -180.144119 15.942979 -59.209980 +v -180.194122 15.942981 -56.809978 +v -180.944122 14.142982 -57.159977 +v -83.894119 -9.157036 -52.559982 +v -89.994118 -10.357035 -52.559978 +v -89.994118 -3.957034 -53.259983 +v -85.094116 -2.907035 -53.409985 +v -89.994118 -0.657034 -54.459988 +v -85.744118 0.342966 -54.659985 +v -89.994118 0.942964 -57.859985 +v -85.894119 1.842967 -59.159985 +v -85.444115 0.192964 -63.609985 +v -84.794121 -3.057034 -64.709984 +v -82.044121 -2.457036 -65.109985 +v -82.194115 0.892964 -64.009987 +v -83.494118 -9.357035 -65.309982 +v -89.994118 -3.957036 -64.609985 +v -89.994118 -10.357034 -65.309982 +v -81.244118 -8.807035 -65.809982 +v -83.694115 -9.257035 -58.909981 +v -78.844116 -8.407037 -59.909981 +v -89.994118 -10.357033 -62.609978 +v -89.994118 -10.357036 -55.259979 +v -89.994118 -3.957035 -62.859982 +v 9.105885 4.492957 -129.559982 +v 12.305885 6.192955 -126.409988 +v 8.805885 5.342957 -129.159988 +v 10.305885 4.542956 -129.609985 +v 9.655885 5.342957 -129.559982 +v -0.994117 -3.307043 -110.409988 +v 5.405883 -3.607044 -110.409988 +v 5.205884 -3.857043 -116.809990 +v -0.994117 -3.607042 -116.809990 +v 4.555883 -4.307043 -123.209984 +v -1.494117 -4.157042 -123.209984 +v 5.405883 -3.907044 -104.009987 +v 11.805883 -4.257045 -104.009987 +v 11.805883 -4.107045 -110.409988 +v 3.605883 -5.057043 -130.709991 +v -2.444117 -5.057041 -129.509995 +v -7.394117 -3.607042 -110.409988 +v -7.394117 -3.907042 -116.809990 +v 3.805884 1.342957 -130.159988 +v -2.244116 0.942959 -129.059982 +v 4.155884 4.242958 -129.259995 +v -1.944116 3.442959 -128.359985 +v -8.044116 -0.057039 -127.509987 +v -7.794116 2.042961 -126.959984 +v -13.594116 -1.657041 -125.409988 +v -13.394116 0.142959 -125.109985 +v -18.794117 -5.057039 -123.009987 +v -13.694118 -5.057037 -125.659988 +v -18.744116 -3.257039 -122.909988 +v -18.644117 -2.207039 -122.759987 +v 15.005885 4.542956 -129.609985 +v 13.805885 5.392954 -126.809990 +v 21.405884 5.392953 -126.809990 +v 16.405884 6.192955 -123.159988 +v 21.405884 6.192954 -123.159988 +v 15.755885 6.992956 -123.109993 +v 17.355886 7.692955 -118.909996 +v 17.905886 6.892958 -118.959991 +v 13.155885 6.192955 -126.759987 +v -16.044117 0.192960 -131.009995 +v -21.694117 -2.207038 -128.409988 +v -9.994117 2.042962 -133.059982 +v -3.694116 3.442960 -134.609985 +v 3.255885 4.242958 -135.609985 +v 9.455885 4.542957 -136.009995 +v 14.905885 6.992956 -122.759995 +v 16.505886 7.692955 -118.559998 +v 15.455885 5.242956 -122.859985 +v 17.055883 5.842956 -118.659988 +v -153.994125 -21.657022 -53.459991 +v -151.744125 -13.657026 -54.659992 +v -147.394119 -13.657026 -51.959995 +v -147.444122 -21.657028 -49.409988 +v -139.094116 -15.157027 -58.909992 +v -139.044113 -14.707028 -60.059994 +v -139.144119 -13.557027 -57.609993 +v -139.244125 -14.357026 -57.459995 +v -138.994125 -17.357029 -59.659988 +v -138.944122 -17.357029 -60.909988 +v -138.644119 -21.657028 -59.459991 +v -138.594116 -21.657028 -61.409988 +v -142.744125 -7.757025 -59.359982 +v -147.094116 -7.757026 -62.209984 +v -147.094116 -13.657024 -62.209995 +v -142.744125 -13.657027 -59.359993 +v -140.544113 -21.657026 -59.509991 +v -140.694122 -21.657024 -54.259991 +v -138.744125 -21.657024 -54.209991 +v -142.744125 -21.657026 -59.359989 +v -142.894119 -21.657024 -54.559990 +v -140.544113 -21.657028 -60.509991 +v -140.744125 -21.657024 -53.309990 +v -147.394119 -21.657030 -51.959991 +v -151.744125 -21.657022 -54.659988 +v -151.594116 -21.657026 -59.759991 +v -153.744125 -21.657026 -61.109989 +v -147.094116 -21.657028 -62.209991 +v -147.044113 -21.657022 -64.709969 +v -138.694122 -14.607025 -56.259995 +v -138.744125 -13.107025 -56.009995 +v -141.244125 -13.557024 -56.159992 +v -141.144119 -14.357025 -56.309994 +v -151.594116 -7.757024 -59.759983 +v -151.744125 -7.757025 -54.659981 +v -151.594116 -13.657024 -59.759995 +v -147.394119 -7.757024 -51.959984 +v -142.894119 -7.757026 -54.559982 +v -142.894119 -13.657028 -54.559994 +v -141.144119 -14.357026 -57.509995 +v -138.694122 -14.607026 -57.409992 +v -141.144119 -15.157027 -59.009995 +v -140.544113 -17.357029 -59.709991 +v -140.194122 -17.607029 -60.659988 +v -139.144119 -17.357025 -54.059990 +v -140.694122 -17.357025 -54.109989 +v -141.244125 -15.157028 -54.859993 +v -139.194122 -15.157028 -54.809994 +v -139.294113 -14.357025 -56.259995 +v -139.194122 -13.557024 -56.109993 +v -139.244125 -14.707028 -53.659992 +v -139.194122 -17.357025 -52.809990 +v -138.694122 -13.107026 -57.709995 +v 24.355885 3.992948 -69.359985 +v 24.605885 3.542948 -63.309990 +v 24.755884 4.092948 -63.709991 +v 24.505884 4.892952 -69.559990 +v 25.855885 4.092947 -63.859989 +v 25.505884 4.942948 -69.709984 +v 5.005883 -1.807047 -82.759987 +v -0.994117 -2.657045 -78.409988 +v 0.755884 -1.607048 -76.459984 +v 9.305884 -1.257046 -78.059990 +v 6.305884 -1.057047 -73.359985 +v 11.805884 -1.257047 -72.009987 +v 14.005884 -1.257049 -81.159988 +v 18.205885 -1.457048 -78.409988 +v 19.555883 -2.357046 -83.059990 +v 4.555883 -2.507049 -62.509987 +v -1.644117 -4.057047 -61.909981 +v 0.555883 -4.857048 -54.809982 +v 6.305883 -3.357050 -57.159985 +v 4.855884 -1.657048 -68.009987 +v -1.394117 -2.207048 -69.259987 +v 11.305884 -2.657047 -86.759987 +v 17.955885 -3.657047 -89.159988 +v 24.105885 5.442954 -89.459984 +v 25.205887 7.842953 -89.459991 +v 25.155886 7.042950 -83.059998 +v 24.055883 4.642950 -83.059990 +v 25.355885 6.192949 -76.659988 +v 24.205885 3.792949 -76.659988 +v 24.305883 2.442948 -69.659988 +v 18.955885 6.242951 -83.059990 +v 18.555885 7.042952 -83.059998 +v 18.405884 6.192950 -76.659988 +v 18.805883 5.392950 -76.659988 +v 17.655886 7.042952 -83.059998 +v 17.455885 6.192950 -76.659988 +v 18.305883 4.892952 -69.559990 +v 17.305883 4.942949 -69.709984 +v 23.855886 7.042953 -89.459991 +v 23.855885 6.242949 -83.059990 +v 24.255886 7.042950 -83.059998 +v 24.255886 7.842953 -89.459991 +v 24.005884 5.392950 -76.659988 +v 24.405884 6.192950 -76.659988 +v 18.605885 3.792950 -76.659988 +v 18.755884 4.642951 -83.059990 +v 18.955887 7.042954 -89.459991 +v 18.455885 3.992949 -69.359985 +v -16.994116 2.192957 -86.759987 +v -13.944117 2.192957 -85.859985 +v -15.444117 2.192958 -92.059990 +v -17.744116 2.192959 -89.859985 +v -0.994117 -3.407044 -84.809990 +v -7.394117 -3.857046 -60.809982 +v -7.394117 -3.707045 -67.209984 +v 24.605885 -2.657049 -78.409988 +v 25.305883 -3.357048 -84.209984 +v 18.205885 -0.707048 -72.009987 +v -13.794117 -4.257044 -72.009987 +v -7.394117 -3.657045 -73.609985 +v -7.394117 -3.857044 -78.409988 +v -13.794117 -4.857043 -78.409988 +v -13.794117 -4.107048 -65.609985 +v 24.605885 -2.157049 -72.009987 +v 127.005882 -14.657084 132.790039 +v 127.005882 -14.657085 139.190033 +v 133.405884 -14.657085 139.190033 +v 133.405884 -14.657087 132.790039 +v 127.005882 -14.657081 113.590027 +v 127.005882 -14.657082 119.990021 +v 133.405884 -14.657082 119.990021 +v 133.405884 -14.657081 113.590027 +v 133.405884 -14.657085 126.390022 +v 139.805893 -14.657088 132.790039 +v 139.805893 -14.657086 126.390022 +v 139.805893 -14.657082 119.990021 +v 139.805893 -14.657083 113.590027 +v 133.405884 -14.657082 107.190025 +v 139.805893 -14.657083 107.190025 +v 134.855881 -14.657083 98.940025 +v 141.605881 -14.657084 98.590027 +v 171.805893 -14.657086 94.390022 +v 171.605881 -14.657089 91.340027 +v 166.555893 -14.657085 95.640022 +v 146.205887 -14.657088 132.790039 +v 146.205887 -14.657087 126.390022 +v 146.205887 -14.657084 119.990021 +v 146.205887 -14.657084 113.590027 +v 146.205887 -14.657084 107.190025 +v 147.905884 -14.657084 98.140022 +v 152.605881 -14.657088 132.790039 +v 152.605881 -14.657088 126.390022 +v 152.605881 -14.657084 119.990021 +v 152.605881 -14.657084 113.590027 +v 152.605881 -14.657084 107.190025 +v 154.005890 -14.657085 99.440025 +v 159.005890 -14.657090 132.790039 +v 159.005890 -14.657089 126.390022 +v 159.005890 -14.657085 119.990021 +v 159.005890 -14.657085 113.590027 +v 159.005890 -14.657085 107.190025 +v 160.555893 -14.657087 98.490021 +v 165.405884 -14.657091 132.790039 +v 165.405884 -14.657090 126.390022 +v 165.405884 -14.657086 119.990021 +v 165.405884 -14.657086 113.590027 +v 165.405884 -14.657086 107.190025 +v 165.405884 -14.657087 100.790024 +v 171.805893 -14.657092 132.790039 +v 171.805893 -14.657091 126.390022 +v 171.805893 -14.657087 119.990021 +v 171.805893 -14.657087 113.590027 +v 171.805893 -14.657087 107.190025 +v 171.805893 -14.657087 100.790024 +v 178.205887 -14.657088 113.590027 +v 178.205887 -14.657088 107.190025 +v 178.205887 -14.657088 100.790024 +v 141.605881 -14.657084 92.190025 +v 134.855881 -14.657084 92.540024 +v 147.905884 -14.657084 91.740021 +v 154.005890 -14.657084 93.040024 +v 160.555893 -14.657086 92.090027 +v 166.555893 -14.657086 89.240021 +v 171.605881 -14.657088 84.940025 +v 166.555893 -11.607085 87.890022 +v 160.555893 -11.607083 90.690025 +v 153.955887 -11.657085 91.640022 +v 147.505890 -11.607080 90.140022 +v 141.355881 -11.507084 90.740021 +v 134.855881 -10.507082 91.140022 +v -7.694116 -0.107052 12.390015 +v -13.444117 0.692947 10.790015 +v -15.544116 0.692950 14.190015 +v -13.344116 1.242947 16.690016 +v -7.694116 1.042945 22.790014 +v -2.644116 -0.107054 18.540014 +v -5.194116 0.242945 15.490015 +v -8.994117 -2.857052 11.890017 +v -11.794117 -5.857053 10.840014 +v -8.544116 -1.357053 12.090015 +v -17.494114 9.142948 10.740018 +v -15.494116 7.442950 7.490016 +v -19.344114 7.442951 7.390015 +v -13.744116 7.442947 10.790015 +v -15.344116 0.692950 7.240014 +v -14.444118 -5.857052 5.840014 +v -13.794117 -3.857051 -8.009988 +v -7.394117 -2.707052 -8.009984 +v -7.394116 -1.157052 -14.409985 +v -13.794116 -2.507051 -14.409985 +v -14.494118 -5.057051 -1.609986 +v -8.094117 -4.307052 -1.609987 +v -9.944118 -5.357049 3.840014 +v -0.994116 -1.557053 -8.009985 +v -0.994116 1.342947 -14.409986 +v -1.944117 -3.557053 -1.609987 +v -14.444116 7.992947 17.640018 +v -10.044115 7.192946 23.340019 +v -12.944115 11.092949 25.390017 +v -8.994115 11.092947 31.390017 +v -3.744115 8.542945 27.940018 +v -3.394116 0.692944 27.940016 +v -4.144116 -0.107055 9.440015 +v -4.294116 -1.357051 8.540016 +v -138.844116 -16.157028 -33.259995 +v -144.644119 -16.157028 -34.859993 +v -144.494125 -12.207027 -34.259995 +v -139.294113 -12.207027 -32.809994 +v -26.794117 -3.307042 -52.509987 +v -29.194117 -3.307043 -54.609985 +v -30.944117 -3.257043 -53.409985 +v -28.144117 -3.257044 -56.509987 +v -25.444117 -3.257044 -48.459988 +v -26.594116 -3.407043 -46.409981 +v -24.644117 -3.307045 -50.559986 +v -24.444117 -3.307045 -50.359985 +v -24.844116 2.942955 -50.709988 +v -24.994116 2.942954 -50.909985 +v -25.144117 4.892955 -51.009991 +v -24.994116 5.242955 -50.859989 +v -26.794117 5.892958 -52.509991 +v -26.794117 6.242957 -52.509991 +v -24.944117 3.142956 -48.659985 +v -25.644117 5.842956 -49.459991 +v -23.644117 5.842956 -51.659988 +v -22.794117 3.142954 -51.059986 +v -22.644117 -3.257046 -51.609985 +v -28.644117 5.242956 -54.109989 +v -27.944117 5.842956 -55.559990 +v -26.544115 6.942955 -54.059990 +v -27.044115 6.942955 -50.909988 +v -28.344114 6.942957 -52.109989 +v -25.294115 6.942955 -52.909988 +v -20.644117 -3.257046 -49.759987 +v -21.394117 3.142954 -50.059986 +v -23.794117 3.142956 -47.359985 +v -23.444117 -3.307044 -46.659985 +v -22.394115 6.392954 -50.709991 +v -24.594114 6.392955 -48.259991 +v -25.044115 8.042956 -52.859989 +v -26.994114 8.042957 -50.709991 +v -24.494114 8.692955 -53.259991 +v -28.544115 8.042957 -52.109989 +v -26.294115 8.692955 -54.859989 +v -29.044115 6.392956 -56.709991 +v -26.644115 8.042955 -54.259991 +v 73.655884 -3.007065 11.340014 +v 73.805885 -3.007063 7.990016 +v 66.455887 -3.007065 9.590014 +v 66.705887 -3.257064 11.240013 +v 66.655884 3.392937 0.240017 +v 66.655884 3.392936 -2.959985 +v 61.855885 2.592940 -4.259984 +v 60.255886 2.592937 -1.509987 +v 73.055885 2.592936 -1.509987 +v 71.455887 2.592938 -4.259984 +v 73.055885 -3.007065 -1.509984 +v 71.455887 -3.007062 -4.259984 +v 66.655884 -3.007063 0.240016 +v 73.855888 3.392936 8.590017 +v 66.455887 2.592935 9.590013 +v 79.355888 -3.007065 6.090014 +v 79.355888 2.592935 6.090014 +v 72.905884 3.392936 5.540013 +v 66.355888 2.592937 6.390017 +v 77.705887 2.592937 3.390013 +v 66.355888 -3.007063 6.390017 +v 73.155884 -3.007064 5.890017 +v 81.055885 3.392935 -14.159983 +v 77.855888 3.392936 -14.159983 +v 76.555885 2.592935 -9.359987 +v 79.305885 2.592935 -7.759984 +v 10.155886 14.542938 67.490005 +v 16.855886 14.892940 69.890007 +v 14.705887 18.842941 62.340019 +v 7.505887 17.792942 60.940018 +v 3.105886 13.142941 65.290009 +v 0.355886 16.892944 60.340023 +v -4.544115 12.942944 65.640007 +v -6.794114 16.342945 60.790024 +v -1.744118 -14.657060 75.190025 +v -2.044118 -11.207061 73.840027 +v -8.394118 -11.607059 75.140022 +v -8.394118 -14.657058 76.940025 +v -18.494114 6.742943 72.040016 +v -11.794115 6.742945 69.590019 +v -12.944115 13.692942 67.790009 +v -19.644115 15.192945 70.190010 +v -3.494115 7.492942 68.840012 +v -2.694116 1.192940 71.190018 +v -10.644116 0.592941 71.440018 +v -9.494118 -5.507058 73.290016 +v -2.344117 -5.007060 72.190018 +v -13.994119 -14.657057 84.840027 +v -7.044119 -14.657058 83.590027 +v -15.094118 -14.657060 79.340027 +v -0.994118 -14.657061 81.590027 +v -13.794118 -14.657058 87.990021 +v -7.394119 -14.657060 87.990021 +v 4.005881 -14.657061 81.990021 +v 4.005881 -14.657061 75.590027 +v 9.855882 -14.657063 85.490021 +v 9.755882 -14.657061 77.590027 +v 3.855884 1.242939 71.190018 +v 3.555885 7.492942 68.690010 +v 4.005883 -5.057061 72.290016 +v 3.805882 -11.207062 73.890022 +v 10.155885 7.442942 70.940010 +v 10.155884 1.192939 73.440018 +v 10.155883 -5.007060 74.540016 +v 9.755882 -11.207061 76.140022 +v 16.855886 7.442938 73.290009 +v 16.855885 1.242940 75.790016 +v 16.855885 -5.057060 76.990013 +v 16.455883 -11.207061 78.540024 +v 16.455883 -14.657063 80.090027 +v 102.255882 -5.857061 -93.809990 +v 99.355888 -5.857061 -93.409988 +v 98.505882 -5.857062 -88.209984 +v 100.655884 -5.857060 -99.859985 +v 96.855888 -5.057057 -115.309990 +v 94.755882 -5.057057 -110.959984 +v 101.005882 -5.057059 -112.009987 +v 80.955887 -5.857057 -99.159988 +v 80.955887 -4.257057 -99.159988 +v 78.055885 -4.257057 -93.509987 +v 78.005882 -5.857057 -93.509987 +v 96.805885 -5.857058 -109.209984 +v 96.805885 -4.257058 -109.209984 +v 90.855888 -4.257056 -107.009987 +v 90.855888 -5.857056 -107.009987 +v 94.755882 -4.257058 -110.959984 +v 88.755882 -4.257056 -108.759987 +v 99.505882 3.092940 -93.909988 +v 98.205887 3.292940 -99.859985 +v 98.055885 -5.857060 -99.859985 +v 99.705887 8.942939 -94.209991 +v 98.455887 9.192940 -99.859993 +v 100.505882 13.292940 -94.459991 +v 99.205887 13.542941 -99.859993 +v 99.355888 -5.857060 -106.309990 +v 99.505882 3.092941 -105.859985 +v 99.705887 8.942941 -105.559998 +v 100.505882 13.292942 -105.309998 +v 100.755882 2.942940 -99.859985 +v 101.005882 8.742940 -99.859993 +v 101.755882 12.992940 -99.859993 +v 90.405884 -5.857057 -95.659988 +v 85.405884 -5.857056 -103.709984 +v -113.944115 -12.057031 -59.209995 +v -113.944115 -12.057032 -54.209995 +v -108.644119 -10.807033 -53.809978 +v -108.644119 -10.807032 -59.209980 +v -113.944115 -12.057030 -64.209976 +v -108.644119 -10.807031 -64.559982 +v -103.594116 -10.257032 -52.909977 +v -102.594116 -10.257032 -59.209980 +v -102.894119 -10.257031 -65.559982 +v -108.644119 -16.757029 -53.809994 +v -105.394119 -16.657028 -53.209995 +v -113.944115 -16.807028 -54.209995 +v -108.644119 -16.757027 -64.559982 +v -104.744118 -16.657028 -65.259979 +v -113.944115 -16.807034 -64.209976 +v -109.794121 -16.657032 -46.409992 +v -107.644119 -16.657034 -47.559994 +v -106.844116 -16.657026 -77.209976 +v -109.794121 -16.657028 -78.409981 +v -109.794121 -16.657030 -71.009979 +v -105.744118 -16.657032 -71.259979 +v -108.644119 -16.657030 -83.059982 +v -91.344116 -10.257030 -73.959976 +v -97.594116 -10.257033 -72.809982 +v -96.644119 -10.257033 -66.609978 +v -90.494118 -10.357032 -68.959976 +v -93.094116 -10.257030 -82.009979 +v -99.094116 -10.257030 -80.009979 +v -96.244118 -10.257032 -58.159977 +v -97.644119 -10.257032 -50.909977 +v -103.944115 -10.257031 -71.909981 +v -105.094116 -10.257031 -78.159981 +v -91.394119 -3.857035 -49.659981 +v -94.244118 -3.857034 -41.959984 +v -94.244118 2.542966 -41.959988 +v -91.394119 2.542965 -49.659985 +v -91.394119 -10.257036 -49.659977 +v -94.194115 -10.257035 -42.159977 +v -91.344116 -3.857032 -73.959984 +v -90.344116 -3.957034 -68.509987 +v -90.344116 2.542967 -67.809990 +v -91.344116 2.542968 -73.959984 +v -85.694115 7.792965 -49.059990 +v -78.644119 9.892962 -48.459991 +v -79.644119 13.592966 -57.209980 +v -84.044121 7.992968 -57.659988 +v -89.944115 2.542968 -59.159985 +v -79.794121 13.942965 -65.459991 +v -84.244118 8.092965 -66.459991 +v -80.744118 14.242965 -72.359993 +v -85.644119 8.142967 -75.109993 +v 14.705887 21.842939 56.390018 +v 22.055887 22.792938 57.090019 +v 22.105888 23.392942 50.340019 +v 14.705888 22.342943 50.440018 +v 7.355887 20.292940 55.790020 +v 7.205887 20.542944 50.640018 +v 0.005887 18.842939 55.540020 +v -0.394113 18.992947 50.690018 +v -7.444113 17.892942 55.690018 +v -8.094113 17.992949 50.590019 +v 29.505888 23.092941 50.490021 +v 29.405888 21.192938 43.390018 +v 22.155888 21.342937 43.640018 +v 14.705887 20.242941 44.490021 +v 7.055887 18.642942 45.490021 +v -0.794114 17.292944 45.890018 +v -8.794113 16.642944 45.540024 +v -15.794113 17.292948 50.390018 +v -16.744114 16.342945 44.590023 +v 36.605888 20.092936 43.540020 +v 36.305889 16.942940 36.440018 +v 29.255886 17.292940 36.290020 +v 22.205887 16.542942 36.940022 +v 14.705886 15.642940 38.540024 +v 8.655886 14.792942 39.940022 +v 1.555886 13.992944 40.990025 +v -6.444114 14.192945 41.040024 +v 92.855888 -14.657073 90.590027 +v 96.255882 -14.657074 90.640022 +v 96.255882 -14.657073 84.240021 +v 90.655884 -14.657073 84.190025 +v 122.505882 7.542922 82.190010 +v 128.805893 7.492920 84.140007 +v 128.805893 12.942920 80.740005 +v 122.505882 13.142923 78.940010 +v 122.605888 1.192920 83.840019 +v 128.805893 1.092921 86.640015 +v 121.755882 -14.657077 89.840027 +v 128.355881 -14.657084 90.940025 +v 128.355881 -11.057078 89.490021 +v 122.105888 -11.607080 87.540024 +v 116.155884 7.592923 80.090012 +v 116.055885 14.992924 77.840012 +v 115.905884 1.142924 81.640015 +v 116.055885 -6.257079 83.940018 +v 122.255882 -5.007079 86.190018 +v 115.705887 -11.507080 85.590027 +v 115.605888 -14.657080 87.340027 +v 109.555885 8.692923 79.990005 +v 109.455887 16.042921 77.290009 +v 109.355888 1.142925 81.140015 +v 109.555885 -5.657078 83.690018 +v 109.155884 -10.657080 84.940025 +v 103.055885 8.042923 79.040009 +v 103.055885 16.192928 75.640007 +v 103.105888 1.192926 80.940018 +v 103.105888 -4.857075 82.740013 +v 102.505882 -11.107075 83.840027 +v 96.705887 6.942928 76.940010 +v 96.655884 14.042926 74.090012 +v 96.655884 1.192926 79.940018 +v 96.705887 -4.957075 81.040016 +v 96.105888 -11.657074 82.690025 +v 102.655884 -14.657077 85.840027 +v 90.055885 7.292928 76.490005 +v 90.055885 12.842926 73.340012 +v 90.255882 1.192926 78.240013 +v 90.155884 -4.907073 80.990013 +v 83.455887 7.492929 76.740005 +v 83.455887 12.942926 73.340012 +v -128.944122 -18.557024 -52.859989 +v -128.944122 -18.557030 -46.509991 +v -125.444115 -16.957031 -50.709991 +v -125.444115 -16.957026 -52.959991 +v -128.944122 -18.557028 -59.209991 +v -125.444115 -16.957029 -59.209991 +v -128.944122 -18.557024 -65.559982 +v -125.444115 -16.957024 -65.259979 +v -119.694115 -14.357031 -53.409992 +v -125.444115 -18.407032 -50.709991 +v -119.694115 -17.357027 -53.409988 +v -160.994125 -21.307024 -33.609989 +v -156.144119 -20.857025 -32.509991 +v -162.644119 -21.657026 -36.859989 +v -160.994125 -20.257029 -27.209990 +v -154.594116 -19.657030 -27.209990 +v -150.544113 -7.507027 -42.409981 +v -154.894119 -7.507024 -45.559982 +v -154.794113 -3.757024 -46.659981 +v -149.544113 -3.757026 -42.909981 +v -151.044113 -7.507027 -37.059982 +v -150.144119 -3.757027 -36.459984 +v -149.944122 -15.657028 -42.709995 +v -154.844116 -15.657025 -46.159992 +v -150.544113 -15.657028 -36.709995 +v -122.094116 4.892962 39.990013 +v -123.694115 4.942960 39.990013 +v -124.494118 6.342964 32.140011 +v -122.394119 5.192962 34.540012 +v -123.494118 7.642962 29.040018 +v -123.994118 9.292965 28.540016 +v -123.144119 7.142962 33.990013 +v -122.594116 7.242964 38.790012 +v -132.494125 12.542966 36.490025 +v -130.994125 12.992964 39.990025 +v -125.744118 10.292963 39.990009 +v -128.144119 10.192963 34.090008 +v -123.494118 7.642963 50.940010 +v -122.394119 5.192961 45.440010 +v -123.144119 7.142961 45.990013 +v -123.994118 9.292961 51.440010 +v -122.594116 7.242963 41.190010 +v -146.594116 9.092965 45.890011 +v -139.694122 12.692966 43.290024 +v -140.094116 13.442965 39.990025 +v -147.894119 9.892965 39.990013 +v -141.744125 9.592966 48.140011 +v -124.244118 7.292961 41.190010 +v -125.244118 8.192962 45.990013 +v -125.094116 7.692963 50.940010 +v -124.494118 6.342962 47.840012 +v -128.144119 10.192962 45.890007 +v -207.444122 12.592987 -75.559998 +v -207.094116 22.992987 -82.860001 +v -210.444122 23.042986 -83.360001 +v -209.144119 12.592987 -81.059998 +v -192.994125 35.342983 -74.559982 +v -195.644119 47.592983 -75.609985 +v -194.894119 35.442982 -70.609978 +v 5.405884 1.692947 -27.209963 +v -0.994116 0.142948 -27.209961 +v -1.494116 1.642948 -20.809961 +v 5.405884 3.142947 -20.809963 +v -26.594116 -3.357044 -59.209961 +v -28.144117 -3.257044 -56.509960 +v -26.794117 -3.307042 -52.509960 +v -23.444117 -3.307044 -46.659962 +v -25.444117 -3.257044 -48.459961 +v -26.594116 -3.407043 -46.409958 +v -20.194117 -3.507044 -46.409958 +v -20.644117 -3.257046 -49.759960 +v -20.194117 -3.357044 -52.809963 +v -22.644117 -3.257046 -51.609962 +v -13.794117 -4.107048 -65.609962 +v -20.194117 -3.757043 -65.609962 +v -20.194117 -3.557045 -59.209957 +v -13.794117 -4.007044 -59.209957 +v -13.794117 -3.857045 -52.809959 +v -20.194117 -3.857047 -40.009956 +v -26.594116 -3.907046 -40.009956 +v -26.594116 -4.457048 -27.209959 +v -26.594116 -4.007048 -33.609959 +v -32.994118 -4.007047 -33.609959 +v -32.994118 -5.057047 -27.209959 +v -32.994118 -4.007044 -40.009956 +v -0.994117 -2.857051 -40.009960 +v 5.405883 -2.857051 -40.009960 +v 4.955884 -4.657049 -48.409958 +v -0.994117 -4.007047 -46.959957 +v -0.994116 -1.657050 -33.609962 +v 5.405884 -0.757051 -33.609962 +v -13.894116 -2.357049 -26.709959 +v -7.494116 -1.007051 -26.709961 +v -7.394117 -2.457051 -33.609962 +v -13.794117 -3.657048 -33.609959 +v -20.194117 -3.257049 -33.609962 +v -13.794117 -3.957049 -40.009956 +v -7.394117 -3.457049 -40.009956 +v -13.794117 -3.857045 -46.409958 +v -7.394117 -3.857046 -46.409958 +v -7.394117 -3.707046 -53.859959 +v -7.394116 -0.207051 -20.809961 +v -7.394117 -3.857046 -60.809959 +v -1.694117 -4.657047 -53.959957 +v -26.594116 -4.707048 -14.409962 +v -20.194117 -3.907050 -14.409963 +v -20.194117 -3.557049 -20.809959 +v -26.594116 -4.657047 -20.809959 +v -13.794116 -2.507051 -14.409960 +v -7.394116 -1.157052 -14.409960 +v -13.794116 -1.707050 -20.809959 +v -20.194117 -3.257046 -27.209959 +v -0.994116 1.342947 -14.409962 +v -1.644117 -4.057047 -61.909958 +v 11.805884 1.842946 -27.209963 +v 11.805884 -0.857053 -33.609962 +v -20.194117 -4.457049 -8.009962 +v -13.794117 -3.857051 -8.009963 +v -7.394117 -3.707045 -67.209961 +v -46.594116 -5.057045 3.740014 +v -51.894115 -5.057045 0.340014 +v -55.694118 -5.057045 5.340014 +v -50.344116 -5.057046 8.590014 +v -45.794117 -4.707047 -1.609987 +v -40.594116 -5.057046 1.340014 +v -39.394115 -4.707047 -1.609987 +v -48.794117 -5.057044 -5.209986 +v -28.044117 -5.057046 3.990014 +v -34.044117 -5.057047 1.440014 +v -34.044117 1.342953 1.440014 +v -28.044117 1.342950 3.990014 +v -31.194115 14.242949 29.340015 +v -26.994114 14.242949 35.890022 +v -22.544115 15.792947 32.890022 +v -28.194115 14.392948 26.540014 +v -63.544117 5.842956 8.090016 +v -58.944118 5.392959 3.990016 +v -65.044121 8.842959 2.840015 +v -48.794117 1.342956 -5.209986 +v -51.894115 1.342955 0.340014 +v -46.544117 -5.057044 -11.109982 +v -46.544117 1.342956 -11.109986 +v -44.844116 -5.057043 -17.159985 +v -44.844116 1.342957 -17.159986 +v -55.694118 1.342955 5.340014 +v -55.744118 5.392956 0.340016 +v -60.144115 8.842957 -0.609986 +v -52.694118 5.392957 -5.209984 +v -56.144115 8.842957 -5.359985 +v -50.444118 5.392957 -11.109984 +v -53.644115 9.142957 -11.059982 +v -48.694118 5.292957 -17.209990 +v -51.944118 10.642957 -17.159985 +v -59.944118 1.342954 9.790014 +v -21.144115 7.442948 10.540015 +v -21.644115 10.192947 15.140017 +v -19.394115 7.442949 13.790015 +v -32.994118 -4.957047 -1.609987 +v -24.644115 6.592953 9.990015 +v -27.844114 9.442951 12.290016 +v -15.694116 7.442949 13.890015 +v -17.294115 11.142949 19.390017 +v -39.394115 -4.657047 -8.009987 +v -32.994118 -4.507048 -8.009987 +v -32.994118 -4.757047 -14.409986 +v -39.394115 -4.657047 -14.409986 +v -26.594116 -4.707048 -14.409986 +v -26.594116 -4.657047 -20.809984 +v -32.994118 -4.957047 -20.809984 +v -39.394115 -5.007045 -19.459984 +v -26.594116 -5.057049 -8.009987 +v -20.194117 -4.457049 -8.009987 +v -20.194117 -3.907050 -14.409986 +v -26.594116 -4.657049 -1.609987 +v -20.194117 -5.007051 -1.609986 +v -25.594116 -5.057048 8.140018 +v -24.694117 1.342952 8.990014 +v -51.994118 -5.057045 14.740014 +v -51.994118 1.342956 14.740014 +v -50.344116 1.342956 8.590014 +v -46.594116 1.342953 3.740014 +v -40.594116 1.342954 1.340014 +v -46.394115 1.342953 25.690016 +v -41.594116 1.342951 30.040014 +v -39.494118 6.342949 28.490019 +v -44.294117 6.342952 24.240019 +v -39.994118 10.692952 24.890017 +v -35.794113 14.242951 24.690016 +v -38.594112 14.242950 21.040014 +v -43.994118 10.692951 20.890017 +v -47.944118 6.342954 19.990019 +v -50.744118 1.342954 20.890015 +v -40.794117 12.242952 17.890015 +v -46.144115 10.742952 16.890017 +v -48.444118 6.342954 14.840015 +v -45.144115 10.742953 12.140017 +v -47.044117 6.342955 9.790015 +v -40.694118 11.592953 10.640016 +v -44.094116 7.592953 6.040014 +v -32.694115 12.792953 13.840014 +v -36.744118 11.592954 8.740016 +v -40.194118 7.592956 4.040014 +v -32.994118 10.792952 6.340017 +v -35.094116 6.342955 3.690015 +v -30.544117 4.442952 7.140016 +v -27.994114 14.442947 26.740015 +v -34.294113 13.692949 20.490015 +v -28.094114 13.292950 17.640015 +v -22.494114 12.892948 22.790014 +v -17.444115 14.342949 30.190016 +v -68.794121 5.842956 10.690016 +v -72.294121 10.592959 6.990016 +v -80.494118 9.692961 8.640017 +v -76.044121 5.142958 12.440016 +v -65.194115 1.342957 13.690014 +v 1.055886 17.242962 -178.010010 +v 0.805887 23.692961 -177.559998 +v 2.605887 23.692963 -174.410004 +v 3.155886 17.242964 -174.410004 +v -3.044114 17.242964 -178.010010 +v -2.794113 23.692963 -177.559998 +v 0.805887 23.692965 -171.309998 +v 1.055886 17.242966 -170.860001 +v 0.655888 30.142962 -177.309998 +v 2.305888 30.142963 -174.410004 +v -2.644112 30.142963 -177.309998 +v -2.794113 23.692966 -171.309998 +v 0.655888 30.142965 -171.559998 +v -2.644112 30.142965 -171.559998 +v -4.294112 30.142965 -174.410004 +v -2.844111 36.592960 -171.210007 +v -4.744111 36.592957 -174.410004 +v 0.855889 36.592960 -171.210007 +v 2.755889 36.592957 -174.410004 +v 77.405884 -13.057074 111.740021 +v 77.405884 -13.107072 106.990021 +v 82.205887 -13.107074 106.990021 +v 82.205887 -13.057075 111.740021 +v 119.405884 -14.657080 119.140022 +v 118.505882 -14.657083 121.040024 +v 119.605888 -14.657081 122.940025 +v 121.105888 -14.657081 123.090027 +v 118.505882 -14.657081 124.840027 +v 119.205887 -14.657084 126.240021 +v 116.455887 -14.657081 124.640022 +v 114.805885 -14.657084 126.140022 +v 115.505882 -14.657081 122.940025 +v 113.805885 -14.657081 123.240021 +v 116.305885 -14.657083 121.040024 +v 115.305885 -14.657080 119.340027 +v 112.305885 -14.657082 127.290024 +v 114.405884 -14.657081 129.640030 +v 116.205887 -14.657082 129.490036 +v 112.305885 -14.657084 131.990036 +v 113.405884 -14.657083 133.690033 +v 109.755882 -14.657079 131.690033 +v 108.605888 -14.657082 133.240036 +v 107.805885 -14.657080 129.640030 +v 105.655884 -14.657080 129.240036 +v 109.555885 -14.657082 127.290024 +v 108.805885 -14.657079 125.390022 +v 107.805885 -14.657077 119.990021 +v 120.605888 -14.657082 130.440033 +v 101.405884 -14.657081 126.390022 +v 101.405884 -14.657081 132.790039 +v 109.405884 -10.557080 129.540024 +v 111.755882 -7.107081 129.190018 +v 110.355888 -10.557081 128.240021 +v 111.855888 -11.107081 128.090012 +v 112.655884 -10.557080 129.540024 +v 111.855888 -10.557079 130.940018 +v 110.205887 -10.557079 130.940018 +v 116.955887 -13.107081 121.790024 +v 118.155884 -13.207083 121.690025 +v 118.855888 -12.907081 122.840027 +v 118.155884 -12.907081 123.990021 +v 116.155884 -13.107081 122.840027 +v 116.805885 -13.107080 123.990021 +v 83.855888 -10.957076 116.390022 +v 83.105888 -10.857076 115.640022 +v 82.355888 -10.857076 116.390022 +v 83.105888 -10.957076 117.140022 +v 82.755882 -14.657077 115.390022 +v 82.105888 -14.657076 116.040024 +v 83.405884 -14.657077 116.040024 +v 82.755882 -14.657076 116.690025 +v 83.855888 -10.957076 97.240021 +v 83.105888 -10.957071 96.490021 +v 82.355888 -10.857075 97.240021 +v 83.105888 -10.857075 97.990021 +v 82.755882 -14.657076 98.240021 +v 82.105888 -14.657076 97.590027 +v 83.405884 -14.657076 97.590027 +v 82.755882 -14.657076 96.940025 +v 75.805885 -14.657077 126.390022 +v 75.805885 -14.657077 132.790039 +v 82.205887 -14.657078 132.790039 +v 82.205887 -14.657078 126.390022 +v 76.555885 -14.657074 107.190025 +v 75.805885 -14.657073 113.590027 +v 82.205887 -14.657073 113.590027 +v 83.705887 -14.657074 107.190025 +v 82.205887 -14.657079 139.190033 +v 88.605888 -14.657080 139.190033 +v 88.605888 -14.657079 132.790039 +v 88.605888 -14.657079 126.390022 +v 82.205887 -14.657074 119.990021 +v 88.605888 -14.657075 119.990021 +v 88.605888 -14.657075 113.590027 +v 88.605888 -14.657075 107.190025 +v 85.455887 -14.657076 99.190025 +v 88.605888 -14.657076 99.840027 +v 89.905884 -14.657074 94.890022 +v 95.005882 -14.657080 132.790039 +v 95.005882 -14.657080 126.390022 +v 95.005882 -14.657076 119.990021 +v 95.005882 -14.657077 113.590027 +v 95.005882 -14.657076 107.190025 +v 95.005882 -14.657076 99.840027 +v 95.005882 -14.657075 94.390022 +v 101.405884 -14.657077 119.990021 +v 101.405884 -14.657077 113.590027 +v 101.405884 -14.657078 107.190025 +v 102.005882 -14.657077 99.740021 +v 102.655884 -14.657078 92.240021 +v 107.805885 -14.657078 113.590027 +v 107.805885 -14.657078 107.190025 +v 108.155884 -14.657078 99.740021 +v 109.155884 -14.657078 93.140022 +v 114.205887 -14.657080 113.590027 +v 114.205887 -14.657079 107.190025 +v 114.655884 -14.657079 100.090027 +v 115.605888 -14.657078 93.740021 +v 114.205887 -14.657084 139.190033 +v 120.605888 -14.657084 139.190033 +v 120.605888 -14.657080 113.590027 +v 120.605888 -14.657080 107.190025 +v 120.505882 -14.657079 100.440025 +v 121.755882 -14.657078 96.240021 +v 127.005882 -14.657080 107.190025 +v 127.005882 -14.657079 100.790024 +v 128.355881 -14.657083 97.340027 +v -145.194122 1.442965 28.340015 +v -148.994125 7.592969 27.190020 +v -149.094116 3.742969 34.090012 +v -147.594116 6.692970 21.090019 +v -151.894119 8.742967 20.990017 +v -147.394119 6.892969 12.990015 +v -152.394119 12.292971 11.290016 +v -143.744125 7.942964 61.190010 +v -149.094116 11.442963 61.490009 +v -142.094116 12.942965 67.040009 +v -137.094116 9.442963 65.240005 +v 45.655888 36.592953 -171.210007 +v 47.555889 36.592949 -174.410004 +v 43.805893 44.542950 -174.410019 +v 41.955887 36.592953 -171.210007 +v 40.055889 36.592953 -174.410004 +v -142.294113 10.692966 31.890017 +v -139.194122 9.992966 28.340017 +v -137.394119 7.942968 27.740019 +v -141.744125 9.592968 31.840017 +v -144.444122 14.542967 29.390015 +v -142.294113 14.092965 26.390015 +v -140.894119 14.442966 35.390022 +v -139.694122 12.692966 36.690022 +v -143.494125 17.542965 32.240021 +v -146.094116 20.292971 28.290018 +v -146.944122 18.992970 25.340019 +v -136.844116 16.092964 34.040024 +v -140.744125 18.892963 30.990019 +v -143.594116 20.792971 27.990019 +v -135.844116 13.242966 29.640015 +v -140.044113 16.792969 27.390013 +v -142.894119 19.792969 24.840019 +v -142.544113 29.592960 53.340015 +v -146.394119 24.842962 55.840015 +v -145.044113 24.642963 56.990017 +v -145.844116 24.992962 53.790016 +v -144.194122 24.892962 53.640015 +v -143.594116 20.792969 51.990021 +v -143.694122 24.692963 55.640015 +v -142.894119 19.792963 55.140018 +v 114.355888 19.542933 -11.609985 +v 114.405891 26.192932 -11.559984 +v 110.055893 26.192934 -9.109984 +v 110.055885 19.542934 -9.159986 +v 105.105888 13.192933 -11.259986 +v 105.755882 19.542933 -11.659986 +v 105.805885 19.542931 -16.609982 +v 105.105888 13.192932 -17.009985 +v -39.394119 -14.657066 222.390015 +v -39.394119 -14.657066 228.790009 +v -32.994122 -14.657067 228.790009 +v -32.994122 -14.657067 222.390015 +v -39.394119 -14.657065 215.990005 +v -32.994122 -14.657067 215.990005 +v -39.394119 -14.657066 209.590012 +v -32.994122 -14.657067 209.590012 +v -39.394119 -14.657066 203.190002 +v -32.994122 -14.657067 203.190002 +v -39.394119 -14.657065 196.790009 +v -32.994122 -14.657065 196.790009 +v -26.594118 -14.657068 215.990005 +v -26.594118 -14.657068 209.590012 +v -122.594116 -17.307034 -40.009991 +v -128.944122 -18.757034 -40.009991 +v -128.944122 -18.307030 -33.609989 +v -122.594116 -17.507030 -33.609989 +v -116.194115 -16.657036 -40.009995 +v -115.844116 -16.657030 -31.309984 +v -122.594116 -17.307034 -27.209984 +v -119.394119 -16.657034 -26.409985 +v -124.244118 -16.657032 -21.859983 +v -112.544121 -16.657034 -36.459995 +v -110.044121 -16.657030 -41.959995 +v -110.944115 -10.257036 -13.909987 +v -115.094116 -10.257034 -18.759987 +v -120.744118 -10.257034 -14.009988 +v -117.244118 -10.257036 -8.609987 +v -105.794121 -10.257036 -20.209988 +v -110.544121 -10.257034 -24.509987 +v -101.144119 -10.257033 -27.009987 +v -106.444115 -10.257034 -30.659988 +v -97.394119 -10.257034 -34.459980 +v -103.144119 -10.257035 -37.259979 +v -128.944122 -10.257030 -16.459988 +v -127.094116 -10.257031 -10.259988 +v -123.394119 -10.257033 -19.959988 +v -118.294121 -10.257033 -24.759987 +v -114.544121 -10.257033 -29.909988 +v -111.094116 -10.257032 -35.259979 +v -108.444115 -10.257032 -41.109978 +v -100.294121 -10.257031 -44.059978 +v -105.944115 -10.257032 -46.959980 +v -117.194115 -3.857035 -8.659986 +v -124.244118 -3.857032 -4.509984 +v -124.244118 2.542968 -4.509984 +v -117.194115 2.542965 -8.659987 +v -110.894119 -3.857036 -13.909986 +v -110.894119 2.542964 -13.909987 +v -105.744118 -3.857036 -20.309984 +v -105.744118 2.542964 -20.309988 +v -101.144119 -3.857037 -27.059984 +v -101.144119 2.542964 -27.059988 +v -97.394119 -3.857037 -34.359982 +v -97.394119 2.542964 -34.359985 +v -113.144119 8.342966 -5.259984 +v -107.394119 12.892962 -1.809985 +v -100.444115 12.992962 -7.859985 +v -106.444115 8.442965 -10.859986 +v -94.644119 12.242965 -15.059984 +v -100.944115 8.342965 -17.659983 +v -89.494118 10.642963 -22.759983 +v -96.044121 7.692964 -24.909983 +v -85.344116 11.342961 -31.109983 +v -92.094116 7.292963 -32.759991 +v -81.844116 10.942964 -39.709995 +v -88.744118 7.842965 -40.809990 +v -52.194118 -5.057048 36.790020 +v -52.194118 -5.057048 30.390017 +v -58.594116 -5.707046 30.390018 +v -58.594116 -5.757047 36.790020 +v -52.194118 -5.057047 23.990017 +v -58.594116 -6.157046 23.990011 +v -50.744118 -5.057045 20.890017 +v -58.594116 -5.057046 17.590017 +v -52.194118 -5.057050 62.390018 +v -52.094116 -5.057049 69.690018 +v -45.794117 -5.057052 68.790016 +v -45.794117 -5.057051 62.390018 +v -45.794117 -5.057050 55.990021 +v -52.194118 -5.907049 55.990021 +v -45.794117 -5.057050 49.590019 +v -52.194118 -5.057049 49.590019 +v -45.794117 -5.057049 43.190018 +v -52.194118 -5.057048 43.190018 +v -45.794117 -5.057049 36.790020 +v -45.794117 -5.057049 30.390017 +v -46.394115 -5.057047 25.690018 +v -36.694118 -5.057053 60.240021 +v -39.394115 -5.057051 55.990021 +v -39.394115 -5.057051 49.590019 +v -39.394115 -5.057050 43.190018 +v -39.394115 -5.057050 36.790020 +v -35.244118 -5.057052 53.990021 +v -34.794117 -5.057052 47.540020 +v -35.744118 -5.057052 41.190018 +v 108.155884 18.092928 -4.859983 +v 108.255882 24.342928 -5.159983 +v 111.455887 24.342930 -1.609983 +v 111.205887 18.092930 -1.559984 +v 105.455887 18.092934 3.690016 +v 105.355888 24.342934 3.990017 +v 102.155884 24.342932 0.440017 +v 102.455887 18.092932 0.390016 +v 108.405891 25.792933 1.190016 +v 109.155891 25.792931 -1.109984 +v 106.805893 26.692930 -0.609984 +v 106.105896 25.792933 1.690016 +v 104.455894 25.792933 -0.059984 +v 105.205894 25.792931 -2.359984 +v 107.555893 25.792931 -2.859984 +v 110.055885 24.342932 2.940017 +v 103.605888 24.342930 -4.109983 +v 114.355888 19.542929 -16.559982 +v 119.155884 23.392929 -16.809984 +v 118.205887 22.392933 -22.409985 +v 112.205887 17.192934 -21.309988 +v 117.305885 21.842930 -26.909983 +v 112.205887 17.442930 -27.909988 +v 102.605888 7.742942 -110.109993 +v 106.205887 7.742941 -104.159996 +v 105.605888 14.142941 -104.159996 +v 103.755882 14.142942 -109.659996 +v 106.355888 14.142940 -99.309998 +v 107.855888 14.142940 -91.209991 +v 106.355888 17.342939 -94.459991 +v 106.655884 17.992945 -99.859993 +v 106.355888 17.342939 -105.309998 +v 106.455887 -5.057059 -104.259987 +v 102.905884 -5.057058 -110.209984 +v 102.805885 -5.857059 -110.259987 +v 106.355888 -5.857060 -104.359985 +v -155.744125 -21.657028 -52.459991 +v -160.994125 -21.307020 -52.809990 +v -161.894119 -21.657022 -44.809990 +v -154.644119 -21.657026 -48.109989 +v -148.444122 -20.757025 -43.409988 +v -147.494125 -21.657026 -47.409988 +v -160.244125 4.342976 -49.459991 +v -159.494125 4.542977 -54.209991 +v -164.294113 4.692978 -54.459991 +v -163.994125 4.542976 -49.609989 +v -165.694122 -14.457024 -38.609993 +v -166.944122 -15.257022 -45.959995 +v -171.344116 -8.457026 -43.609982 +v -169.044113 -8.507026 -37.759983 +v -164.494125 -14.057022 -32.409992 +v -166.194122 -8.507025 -31.709988 +v -160.744125 -12.357026 -24.159986 +v -162.394119 -7.557026 -24.459990 +v -161.294113 -3.757026 -37.509983 +v -159.594116 -0.907026 -38.259987 +v -159.194122 -0.907025 -42.859985 +v -160.694122 -3.757025 -43.959984 +v -154.994125 -0.907026 -44.759987 +v -151.244125 -0.907026 -42.109985 +v -160.294113 -15.657026 -43.659992 +v -160.844116 -15.657027 -37.709995 +v -160.294113 -7.507026 -37.959984 +v -159.794113 -7.507025 -43.309982 +v -164.494125 -21.007025 -32.409988 +v -160.744125 -19.457026 -24.159990 +v -165.694122 -21.807026 -38.609989 +v -166.944122 -21.657022 -45.959991 +v 59.755890 13.092936 27.790014 +v 53.255890 14.942937 30.290014 +v 51.705887 15.792937 36.190022 +v 60.555889 16.192934 34.690022 +v 77.055885 7.242934 24.590019 +v 71.455887 7.742935 25.040018 +v 75.205887 12.942932 27.190016 +v 80.805885 12.692933 25.190016 +v 79.455887 1.342934 21.440016 +v 74.755882 1.342933 23.640015 +v 81.955887 7.692932 22.540018 +v 85.155884 13.742932 22.340015 +v 43.305885 4.642939 18.690014 +v 44.455883 1.342939 18.540014 +v 42.755886 1.342940 18.740015 +v 41.705883 4.042940 18.840014 +v 41.705883 4.042940 21.640013 +v 42.755886 1.342937 21.640015 +v -125.444115 -18.407026 -67.659981 +v -125.444115 -16.957026 -67.659981 +v -119.694115 -14.357029 -64.959976 +v -119.694115 -17.357027 -64.959976 +v -128.944122 -18.557028 -71.909981 +v -148.194122 -19.757025 -84.809982 +v -154.594116 -19.957024 -84.809982 +v -152.544113 -19.857025 -83.859978 +v -146.194122 -19.507023 -79.209976 +v -141.794113 -19.357027 -84.809982 +v -141.794113 -20.157022 -78.409981 +v -135.394119 -18.807026 -84.809982 +v -135.394119 -19.957022 -78.409981 +v -141.794113 -20.957026 -72.009972 +v -135.394119 -20.007029 -72.009979 +v -153.144119 -18.057022 -96.509979 +v -159.544113 -19.707020 -92.359978 +v -154.594116 -19.307020 -91.209976 +v -148.194122 -18.607021 -91.209976 +v -141.794113 -18.357023 -91.209976 +v -135.394119 -18.357023 -91.209976 +v -161.394119 -20.207024 -87.209976 +v -147.844116 -5.157022 -78.559990 +v -149.294113 -2.807022 -77.909988 +v -149.894119 -2.807023 -73.359985 +v -148.594116 -5.157023 -72.409988 +v -147.994125 -13.507025 -78.459976 +v -152.794113 -13.507022 -82.109978 +v -152.844116 -8.357022 -81.459976 +v -148.594116 -8.357025 -78.209976 +v -148.744125 -13.507025 -72.509979 +v -149.244125 -8.357026 -72.909981 +v -32.994118 -3.207040 -78.409988 +v -25.044117 -4.207042 -80.809990 +v -26.844116 -4.207040 -84.209984 +v -32.994118 -3.757040 -84.809990 +v -31.994116 -4.207042 -88.609985 +v -32.894115 -4.207040 -92.209984 +v -28.444117 -4.207042 -87.559990 +v -24.744116 -4.207042 -87.459984 +v -25.794117 -4.207039 -90.109985 +v -20.894117 -4.207043 -87.259987 +v -23.144117 -4.207041 -92.409988 +v -13.794117 -4.207043 -85.259987 +v -17.444117 -4.207043 -86.309990 +v -19.144117 -4.207041 -83.859985 +v -7.394117 -4.207043 -84.809990 +v -11.044117 -4.207045 -87.909988 +v -24.894117 -4.207039 -95.859985 +v -26.694117 -4.207041 -93.709984 +v -32.994118 -4.657038 -104.009987 +v -32.994118 -5.057038 -110.409988 +v -39.394115 -5.057037 -110.409988 +v -39.394115 -4.657037 -104.009987 +v -45.794117 -5.057036 -110.409988 +v -45.794117 -4.657036 -104.009987 +v -48.494118 -5.057036 -114.209984 +v -51.844116 -5.057034 -108.809990 +v -53.794117 -5.057035 -102.809990 +v -45.794117 -3.657038 -72.009987 +v -45.794117 -3.607038 -78.409988 +v -52.194118 -4.457037 -78.409988 +v -52.194118 -4.307038 -72.009987 +v -39.394115 -3.207039 -72.009987 +v -39.394115 -3.207039 -78.409988 +v -32.994118 -3.207040 -72.009987 +v -26.594116 -3.207041 -72.009987 +v -20.194117 -3.157042 -72.009987 +v -21.194117 -4.207042 -80.609985 +v -45.794117 -4.507038 -84.809990 +v -52.194118 -4.507037 -84.809990 +v -39.394115 -3.757039 -84.809990 +v -45.794117 -4.557037 -91.209984 +v -52.194118 -4.557036 -91.209984 +v -39.394115 -4.007038 -91.209984 +v -45.794117 -4.607037 -97.609985 +v -52.194118 -4.607036 -97.609985 +v -39.394115 -4.607038 -97.609985 +v -51.844116 1.342966 -108.809990 +v -53.794117 1.342966 -102.809990 +v -21.494116 -0.207043 -81.209984 +v -19.794117 -0.207041 -83.909988 +v -26.194117 -0.207040 -84.209984 +v -24.694117 -0.207043 -81.359985 +v -24.444117 -0.207042 -86.909988 +v -21.244116 -0.207042 -86.759987 +v -31.644117 -1.807038 -88.959984 +v -28.594116 -1.807042 -88.059990 +v -30.094116 -1.807041 -94.259987 +v -32.394115 -1.807040 -92.059990 +v -27.044117 -1.807041 -93.359985 +v -26.244116 -1.807040 -90.259987 +v -30.244116 -4.207042 -94.759987 +v -19.594116 3.792958 -92.759987 +v -17.844116 3.792958 -95.459984 +v -24.244116 3.792958 -95.809990 +v -22.794117 3.792958 -92.959984 +v 127.005882 -14.657091 196.790009 +v 127.005882 -14.657091 203.190002 +v 133.405884 -14.657092 203.190002 +v 133.405884 -14.657092 196.790009 +v 133.405884 -14.657093 222.390015 +v 133.405884 -14.657093 228.790009 +v 139.805893 -14.657094 228.790009 +v 139.805893 -14.657095 222.390015 +v 133.405884 -14.657093 215.990005 +v 139.805893 -14.657093 215.990005 +v 133.405884 -14.657092 209.590012 +v 139.805893 -14.657093 209.590012 +v 139.805893 -14.657093 203.190002 +v 139.805893 -14.657093 196.790009 +v 146.205887 -14.657095 228.790009 +v 146.205887 -14.657095 222.390015 +v 146.205887 -14.657094 215.990005 +v 146.205887 -14.657094 209.590012 +v 146.205887 -14.657093 203.190002 +v 146.205887 -14.657094 196.790009 +v 152.605881 -14.657097 228.790009 +v 152.605881 -14.657096 222.390015 +v 152.605881 -14.657095 215.990005 +v 152.605881 -14.657095 209.590012 +v 152.605881 -14.657095 203.190002 +v 152.605881 -14.657095 196.790009 +v 159.005890 -14.657097 228.790009 +v 159.005890 -14.657097 222.390015 +v 159.005890 -14.657096 215.990005 +v 159.005890 -14.657096 209.590012 +v 159.005890 -14.657096 203.190002 +v 159.005890 -14.657095 196.790009 +v 165.405884 -14.657098 228.790009 +v 165.405884 -14.657098 222.390015 +v 165.405884 -14.657097 215.990005 +v 165.405884 -14.657097 209.590012 +v 165.405884 -14.657096 203.190002 +v 165.405884 -14.657097 196.790009 +v 171.805893 -14.657099 228.790009 +v 171.805893 -14.657099 222.390015 +v 171.805893 -14.657098 215.990005 +v 171.805893 -14.657097 209.590012 +v 171.805893 -14.657098 203.190002 +v 171.805893 -14.657098 196.790009 +v 178.205887 -14.657099 203.190002 +v 178.205887 -14.657098 196.790009 +v -159.894119 -20.157021 -80.959976 +v -163.144119 -20.557020 -82.009972 +v -166.194122 -21.007017 -76.409973 +v -156.844116 1.942980 -97.859985 +v -163.694122 0.192980 -93.009987 +v -161.744125 -6.607020 -92.559990 +v -155.094116 -4.757020 -97.309990 +v -168.894119 -21.257021 -70.409973 +v -160.894119 -21.007025 -73.059975 +v -170.594116 -21.657026 -64.259972 +v -167.394119 -21.207018 -65.609970 +v -171.494125 6.742981 -87.759987 +v -179.094116 11.242981 -89.559998 +v -179.294113 11.842983 -79.709991 +v -174.444122 6.092981 -79.209984 +v -163.144119 -14.257021 -82.009979 +v -161.394119 -13.407020 -87.209976 +v -164.394119 -6.557020 -85.959984 +v -166.944122 -7.557020 -79.659981 +v -183.944122 12.592983 -75.159996 +v -177.344116 6.292981 -74.009987 +v -166.194122 -15.257021 -76.409981 +v -170.794113 -8.457020 -74.759979 +v -168.894119 -15.257021 -70.409981 +v -173.294113 -8.457020 -69.109978 +v -154.294113 -5.157022 -69.959984 +v -154.144119 -2.807022 -71.559990 +v -157.794113 -2.807023 -74.359985 +v -159.244125 -5.157022 -73.709984 +v -157.194122 -2.807021 -78.909988 +v -158.494125 -5.157021 -79.859985 +v -152.944122 -2.807023 -80.709984 +v -152.744125 -5.157023 -82.259987 +v -158.294113 -13.507020 -79.759979 +v -159.044113 -13.507020 -73.809982 +v -158.494125 -8.357021 -74.059982 +v -157.844116 -8.357020 -79.409981 +v -154.544113 -20.907022 -68.209969 +v -154.294113 -13.507023 -70.209976 +v -170.594116 -15.257021 -64.259979 +v 76.405884 -1.607070 81.090019 +v 78.005882 -1.607071 81.090019 +v 78.405884 0.542929 81.090019 +v 76.005882 0.542930 81.090019 +v 76.355888 -1.257072 77.640015 +v 78.055885 -1.257073 77.640015 +v 80.105888 -2.357071 80.440018 +v 81.655884 -1.757072 80.640015 +v 78.255882 -0.157071 80.440018 +v 78.055885 -1.257071 80.290016 +v 81.155884 -5.057072 80.590019 +v 82.855888 -5.057073 80.790016 +v 74.305885 -2.357070 80.440018 +v 76.355888 -1.257071 80.290016 +v 76.105888 -0.157071 80.440018 +v 72.705887 -1.757070 80.640015 +v 80.105888 -2.357073 77.640015 +v 81.155884 -5.057073 77.640015 +v 74.305885 -2.357072 77.640015 +v -109.794121 -8.757038 36.790020 +v -109.794121 -8.857038 43.190018 +v -103.394119 -8.207039 43.190018 +v -103.394119 -8.007039 36.790020 +v -96.994118 -7.007042 43.190018 +v -96.994118 -7.007042 36.790020 +v -96.994118 -7.007041 30.390011 +v -103.394119 -7.457040 30.390011 +v -96.994118 -6.857041 23.990011 +v -103.394119 -7.007040 23.990011 +v -90.594116 -7.007043 49.590019 +v -90.594116 -7.007043 43.190018 +v -96.994118 -7.007042 49.590019 +v -90.594116 -7.007043 36.790020 +v -90.594116 -7.007042 30.390011 +v -90.594116 -6.507042 23.990011 +v -84.194115 -5.807044 55.990021 +v -84.194115 -7.007044 49.590019 +v -91.394119 -5.707046 57.340019 +v -84.194115 -7.007044 43.190018 +v -84.194115 -7.007044 36.790020 +v -84.194115 -7.007043 30.390011 +v -84.194115 -6.207042 23.990011 +v -77.794121 -5.557045 55.990021 +v -77.794121 -7.007045 49.590019 +v -77.794121 -7.007045 43.190018 +v -77.794121 -7.007044 36.790020 +v -77.794121 -7.007044 30.390011 +v -77.794121 -6.107044 23.990011 +v -71.394119 -5.407046 55.990021 +v -71.394119 -6.457046 49.590019 +v -71.394119 -6.407045 43.190018 +v -71.394119 -6.507045 36.790020 +v -71.394119 -6.457045 30.390011 +v -71.394119 -5.957044 23.990011 +v -64.994118 -5.357047 55.990021 +v -64.994118 -6.507047 49.590019 +v -64.994118 -6.307046 43.190018 +v -64.994118 -6.407046 36.790020 +v -64.994118 -6.557045 30.390011 +v -64.994118 -6.107045 23.990011 +v -64.994118 -5.057045 17.590017 +v -71.044121 -5.057043 15.040014 +v -58.594116 -5.307048 55.990021 +v -58.594116 -5.907048 49.590019 +v -58.594116 -5.657047 43.190018 +v -67.794121 -7.157037 -83.259979 +v -69.194115 -7.507035 -81.409981 +v -70.144119 -1.157036 -81.559990 +v -68.694115 -1.057033 -83.209984 +v -65.744118 -6.707034 -84.609985 +v -66.894119 -0.357034 -84.709984 +v -63.594116 -6.007035 -85.009987 +v -64.694115 0.342965 -85.409988 +v -71.444115 2.042964 -81.409988 +v -69.744118 2.292966 -83.709984 +v -67.794121 2.942965 -85.509987 +v -65.244118 3.642965 -86.459984 +v -73.094116 3.992965 -86.609985 +v -75.694115 3.542967 -83.309990 +v -69.844116 4.642968 -89.459984 +v -65.544121 5.442966 -90.859985 +v -79.844116 1.792968 -84.809990 +v -76.294121 2.492968 -89.809990 +v -71.494118 3.142965 -93.659988 +v -65.244118 4.042967 -95.409988 +v -58.544117 4.642966 -95.859985 +v -58.544117 6.242964 -92.459984 +v -80.844116 -1.557032 -85.259987 +v -76.944115 -0.757032 -90.909988 +v -71.594116 -0.107035 -95.009987 +v -64.694115 0.842967 -96.759987 +v -58.544117 1.342965 -97.059990 +v -81.244118 -8.007031 -85.559982 +v -77.144119 -7.357033 -92.009979 +v -71.044121 -6.407032 -96.209984 +v -63.594116 -5.407034 -97.759987 +v -63.594116 -5.707035 -91.409988 +v -58.544117 -5.057037 -87.709984 +v -58.544117 -5.057037 -95.059990 +v -68.394119 -6.557033 -90.409988 +v -72.494118 -7.257036 -87.659981 +v -58.544117 1.342963 -95.309990 +v -58.544117 -5.057035 -97.759987 +v -70.344116 -7.007035 -58.159981 +v -76.494118 -8.007036 -54.009983 +v -77.844116 -1.757036 -54.659985 +v -71.894119 -0.807035 -58.559986 +v -66.194115 -6.807035 -64.259979 +v -67.394119 -0.457039 -64.309990 +v -65.444115 -6.807035 -71.859978 +v -66.544121 -0.457035 -71.859985 +v -73.244118 2.342965 -59.309986 +v -68.794121 2.742965 -64.609985 +v -67.894119 2.792965 -71.709984 +v -72.994118 4.092965 -66.359985 +v -76.594116 3.492964 -62.459991 +v -72.394119 4.142964 -70.809990 +v -79.444115 1.442966 -65.709984 +v -76.794121 2.242964 -69.059990 +v -77.894119 2.142966 -73.259987 +v -74.194115 3.792964 -75.759987 +v -80.244118 1.742967 -79.109985 +v -75.944115 3.492966 -80.109985 +v -79.744118 -1.907034 -66.609985 +v -77.744118 -1.157036 -68.809990 +v -78.694115 -1.157034 -72.409988 +v -81.294121 -1.557033 -78.759987 +v -79.244118 -8.307036 -67.209976 +v -77.894119 -7.557034 -69.409981 +v -78.994118 -7.557034 -71.659981 +v -81.794121 -7.957033 -78.409981 +v -71.694115 -7.157038 -70.559982 +v -73.644119 -7.457035 -75.159981 +v -72.044121 -7.207035 -66.809982 +v -74.794121 -7.657036 -62.659981 +v -75.544121 -7.807034 -79.759979 +v -44.994114 13.442947 82.440010 +v -50.044113 13.092946 84.990005 +v -57.894112 14.242949 80.040009 +v -49.744114 14.242947 79.590012 +v -37.444115 14.242948 77.790009 +v -53.744118 6.742947 90.490013 +v -47.644115 6.742946 90.040016 +v -55.844112 13.092947 85.340012 +v -42.344116 6.742947 87.340019 +v -37.044117 6.742947 82.690018 +v -30.944115 6.742945 78.840019 +v -31.244114 14.242948 72.840012 +v -29.794117 0.592945 80.690018 +v -35.894115 0.592945 84.540016 +v -24.694115 6.742945 75.440018 +v -25.594114 15.092945 71.540009 +v -23.544117 0.592943 77.240013 +v -28.644117 -5.507055 82.490013 +v -22.394117 -5.507057 79.090019 +v -21.294119 -11.607059 80.940025 +v -27.494118 -11.607055 84.340027 +v -16.194117 -5.507056 75.740013 +v -17.344116 0.592944 73.890015 +v -15.044118 -11.607057 77.540024 +v -40.144115 -5.057054 65.690018 +v -45.644115 -5.057051 68.740013 +v -45.644115 1.342949 68.740013 +v -40.144115 1.342947 65.690018 +v -50.944118 10.742949 76.590012 +v -43.194118 10.792948 75.840012 +v -52.694118 6.342948 72.440018 +v -45.444118 6.342947 71.790016 +v -52.094116 1.342951 69.690018 +v -36.244118 10.742949 72.490005 +v -38.694118 6.342948 68.740013 +v -30.994114 10.742948 65.690010 +v -34.194118 6.342948 62.390011 +v -36.694118 1.342947 60.240017 +v -28.544115 10.692947 57.940006 +v -32.444118 6.342948 55.590012 +v -35.244118 1.342947 53.990017 +v -24.294115 14.242946 57.540024 +v -24.044115 14.242946 50.290024 +v -28.294115 10.692945 50.690006 +v -32.044117 6.342948 48.590012 +v -34.794117 1.342947 47.540016 +v -24.494114 14.242949 43.190022 +v -28.694115 10.692949 43.540009 +v -33.044117 6.342948 41.490013 +v -35.744118 1.342948 41.190014 +v -31.244114 10.692949 36.290009 +v -35.244118 6.342948 34.490013 +v -37.744118 1.342949 35.140015 +v -93.444115 -0.507035 -58.109985 +v -93.444115 1.642965 -57.709988 +v -93.444115 1.642968 -60.109985 +v -93.444115 -0.507032 -59.709988 +v 38.005886 4.792940 18.240013 +v 37.605885 6.942940 18.240019 +v 40.005886 6.942940 18.240019 +v 39.605885 4.792940 18.240013 +v 37.955883 5.142941 21.640011 +v 39.655884 5.142941 21.640011 +v 35.905884 4.042941 18.840014 +v 34.355885 4.642941 18.690014 +v 37.755886 6.242940 18.890018 +v 37.955883 5.142941 19.040010 +v 34.855885 1.342941 18.740015 +v 33.155884 1.342941 18.540014 +v 35.905884 4.042941 21.640013 +v 42.005886 7.742939 20.340019 +v 35.605885 7.742940 20.340019 +v 35.755886 12.342942 20.340015 +v 41.855885 12.342941 20.340015 +v 43.305885 4.642939 20.340014 +v 39.855885 6.242939 20.340019 +v 48.355885 7.742939 20.340019 +v 21.405888 25.542953 -145.010010 +v 27.805887 25.242954 -145.010010 +v 27.805887 25.242960 -148.110001 +v 21.405888 25.542959 -148.110001 +v 15.005888 25.242956 -145.010010 +v 15.005888 25.242962 -148.110001 +v 66.855888 16.092930 56.140022 +v 74.055885 14.792933 55.190022 +v 75.555885 15.392932 46.540024 +v 67.805885 16.592934 48.190022 +v 77.055885 16.992935 37.890018 +v 68.755882 16.592936 40.240025 +v 59.955887 17.042936 49.490021 +v 60.255890 16.742933 42.090023 +v 52.105888 18.342937 50.390018 +v 51.905888 17.692934 43.290020 +v 44.455887 19.792938 50.690018 +v 44.055889 18.692934 43.690018 +v 15.005888 22.142962 -173.910004 +v 21.405888 22.142962 -173.910004 +v 21.405888 25.542961 -173.910004 +v 15.005888 25.242962 -173.910004 +v 8.605887 22.142963 -172.710007 +v 8.605887 24.692963 -172.710007 +v 34.205887 24.692957 -175.809998 +v 34.205887 24.692959 -172.710007 +v 42.005890 23.692959 -171.309998 +v 40.205887 23.692957 -174.410004 +v 27.805887 25.242958 -177.010010 +v 27.805887 25.242960 -173.910004 +v 21.405888 25.542959 -177.010010 +v 15.005888 25.242960 -177.010010 +v 8.605887 24.692961 -175.809998 +v 27.805887 22.142960 -173.910004 +v 34.205887 22.142960 -172.710007 +v 41.955887 22.142960 -171.210007 +v 2.655885 8.542946 31.890017 +v 4.655885 10.192944 33.040009 +v 4.955885 8.542943 28.190018 +v 6.305883 -5.857058 28.240011 +v 11.255883 -5.057055 26.640017 +v 11.655883 -5.707057 20.290018 +v 3.605883 -5.857056 23.240011 +v -2.044117 -5.857055 23.040010 +v -2.444117 -2.857053 19.940018 +v -2.494117 -1.357053 19.440016 +v -1.294116 0.692945 24.490015 +v 0.605885 10.542943 28.040016 +v 2.905885 8.542945 24.340017 +v -1.444115 8.542947 24.240017 +v 2.755884 0.692945 24.640015 +v 4.655884 0.692943 28.190016 +v 2.205884 -2.357056 16.090017 +v 1.755884 -1.357056 15.940016 +v 13.905883 -4.107050 -48.759983 +v 18.805883 -3.907052 -44.959984 +v 11.805883 -3.557050 -52.809982 +v 9.505883 -4.057049 -52.909981 +v 21.655884 -2.407053 -36.509987 +v 15.605884 -3.057052 -39.509987 +v 18.205885 -0.957053 -33.609985 +v 24.605885 -3.907051 -46.409981 +v 24.455885 -3.507052 -42.159981 +v 10.155883 -4.007051 -43.609982 +v 4.955884 -4.657049 -48.409981 +v 5.405883 -2.857051 -40.009987 +v 11.805884 -3.007053 -40.009987 +v 31.005884 -3.857051 -46.409981 +v 31.005884 -3.857051 -52.809982 +v 31.005884 -3.407050 -65.609985 +v 24.605885 -2.157050 -65.609985 +v 31.005884 -3.557051 -59.209984 +v 5.405884 -0.757051 -33.609985 +v 11.805884 -0.857053 -33.609985 +v 30.405884 -2.707055 -38.309986 +v 37.405884 -4.757053 -52.809982 +v 37.405884 -5.057055 -59.209984 +v 37.405884 -4.057054 -46.409981 +v 37.405884 -3.807057 -40.009983 +v 35.455883 -2.407057 -33.209988 +v 43.805885 -4.707054 -46.409981 +v 43.805885 -5.107053 -52.809982 +v 43.805885 -3.557058 -40.009983 +v 33.155884 5.342953 -129.559982 +v 34.005886 5.342953 -129.159988 +v 32.505886 4.542953 -129.609985 +v 18.205885 -4.557045 -110.409988 +v 18.205885 -4.557046 -104.009987 +v 24.605885 -4.607047 -104.009987 +v 24.605885 -4.857047 -110.409988 +v 18.205885 -4.657045 -116.809990 +v 24.605885 -4.907046 -116.809990 +v 31.005884 -4.507048 -110.409988 +v 31.005884 -4.707047 -116.809990 +v 18.205885 -4.807045 -123.209984 +v 24.605885 -5.007046 -123.209984 +v 25.305883 -5.057044 -131.409988 +v 17.505884 -5.057044 -131.409988 +v 31.905884 -4.857047 -123.309990 +v 26.405884 6.192954 -123.159988 +v 24.905886 6.892957 -118.959991 +v 25.455887 7.692954 -118.909996 +v 27.055885 6.992954 -123.109993 +v 29.005884 5.392952 -126.809990 +v 29.655884 6.192955 -126.759987 +v 27.805883 4.542954 -129.609985 +v 24.805883 5.292954 -122.859985 +v 27.355885 5.242954 -122.859985 +v 25.755884 5.842956 -118.659988 +v 24.455885 4.592957 -126.509987 +v 29.955885 4.592956 -126.509987 +v 25.205885 1.342954 -130.709991 +v 32.855885 1.342953 -130.709991 +v 18.005884 5.292955 -122.859985 +v 18.355885 4.592957 -126.509987 +v 17.605885 1.342955 -130.709991 +v 12.855885 4.592957 -126.509987 +v 9.955884 1.342956 -130.709991 +v 21.405886 10.942959 -145.009995 +v 27.605886 10.942957 -145.009995 +v 27.405886 17.342953 -145.010010 +v 21.405886 17.342953 -145.010010 +v 27.905886 6.992954 -122.759995 +v 26.305885 7.692954 -118.559998 +v 30.505884 6.192955 -126.409988 +v 9.755883 -5.057043 -131.409988 +v -149.344116 -17.557032 -16.909985 +v -142.744125 -17.207031 -14.859987 +v -141.144119 -18.057028 -21.359991 +v -148.194122 -18.357027 -20.809992 +v -135.394119 -17.657028 -20.809992 +v -135.894119 -16.657034 -16.109983 +v -146.144119 6.592968 3.740015 +v -152.544113 6.042972 2.640015 +v -150.844116 9.092971 6.690015 +v -144.594116 10.092970 7.690014 +v -157.144119 8.092971 5.740016 +v -147.194122 2.242969 -0.459987 +v -153.544113 1.892973 -3.709986 +v -137.394119 7.742970 3.740014 +v -140.044113 2.542969 -0.259987 +v -147.194122 -4.157031 -0.459987 +v -153.544113 -4.507030 -3.709987 +v -139.994125 -3.857032 -0.259987 +v -131.944122 -3.857033 -1.659987 +v -131.944122 2.542967 -1.659987 +v -133.894119 11.092969 7.490016 +v -132.044113 12.892965 9.540014 +v -120.844116 14.542967 8.740014 +v -123.894119 11.442966 6.140016 +v -128.794113 8.092969 2.240014 +v -115.294121 11.942966 2.940016 +v -120.644119 8.092966 -0.809986 +v -144.144119 10.342968 9.740017 +v 42.805885 4.592941 -7.759984 +v 47.555885 4.592940 -9.209985 +v 44.455883 3.392943 -10.909983 +v 47.205883 3.392940 -7.309988 +v 44.155884 3.392941 -6.359983 +v 46.605885 -3.007060 -7.659986 +v 46.855885 -3.007060 -9.009988 +v 45.205883 7.442940 -8.509986 +v 47.455883 5.342940 -8.009985 +v 44.605885 5.342943 -10.309984 +v 45.205883 4.592940 -8.509985 +v 43.655884 5.342941 -6.809984 +v 46.355885 -3.007061 -1.459984 +v 46.355885 2.592940 -1.459987 +v 44.505886 -3.007059 -7.009984 +v 49.705883 3.392941 2.790015 +v 51.955883 3.392940 0.540017 +v 49.105885 2.592938 -3.109987 +v 49.105885 -3.007061 -3.109984 +v 53.955883 -3.007061 -7.759984 +v 53.955883 2.592939 -7.759984 +v 52.255886 3.392939 -14.159983 +v 52.255886 -3.007061 -14.159986 +v 46.855885 -3.007060 -14.159986 +v 1.055886 17.242958 -144.010010 +v 1.555885 10.842958 -143.159988 +v 4.155885 10.842959 -147.609985 +v 3.155886 17.242964 -147.610001 +v -3.044114 17.242960 -144.010010 +v -3.544115 10.842960 -143.159988 +v -5.144114 17.242966 -147.610001 +v -6.144115 10.842961 -147.609985 +v 2.255885 4.542960 -142.009995 +v 5.455884 4.542959 -147.609985 +v 15.205886 10.942959 -145.009995 +v 15.405887 17.342955 -145.010010 +v 8.605886 17.342955 -146.210007 +v 8.605886 10.942959 -146.209991 +v 15.005885 4.542959 -145.009995 +v 8.605885 4.542959 -146.209991 +v -4.344114 17.242958 -146.260010 +v -7.894114 15.842962 -145.760010 +v -6.644115 9.492959 -143.059982 +v -4.594112 23.692965 -147.610001 +v -7.944113 21.042957 -145.809998 +v -10.094112 23.542963 -149.760010 +v -167.394119 -21.207022 -59.209991 +v -171.144119 -21.657022 -57.909988 +v -169.544113 -21.657026 -51.809990 +v -167.394119 -21.207018 -52.809990 +v -160.994125 -21.307026 -64.059975 +v -160.994125 -21.307024 -60.909988 +v -155.494125 -21.657026 -62.159988 +v -169.544113 -15.257021 -51.809994 +v -171.144119 -15.257020 -57.909992 +v -173.944122 -8.457020 -55.809982 +v -173.044113 -8.457025 -49.609982 +v 103.655884 18.292940 -94.459991 +v 106.505882 19.242941 -94.459991 +v 106.355888 20.542944 -99.860001 +v 103.005882 19.342943 -99.859993 +v 103.655884 18.292942 -105.309998 +v 106.505882 19.242941 -105.309998 +v 101.755882 16.442942 -105.309998 +v 104.255882 17.242945 -99.859993 +v 102.905884 15.992940 -99.859993 +v 101.755882 16.442940 -94.459991 +v 108.005882 20.092937 -108.359993 +v 108.005882 22.042940 -105.209999 +v 107.955887 23.092943 -99.860001 +v 108.005882 22.042938 -94.560005 +v 108.005882 20.092939 -91.359993 +v 111.155884 22.442938 -94.709999 +v 111.155884 23.742945 -99.859970 +v 111.155884 20.042940 -90.459991 +v 54.855888 14.142938 24.340015 +v 57.155888 14.142939 20.340015 +v 55.005890 18.792936 20.340019 +v 53.755890 18.792936 22.440020 +v 56.755886 7.742937 20.340019 +v 54.655884 7.742937 16.690020 +v 54.855888 14.142937 16.340015 +v 50.455883 7.742937 16.690020 +v 50.255890 14.142939 16.340015 +v 52.555889 25.542936 20.340015 +v 51.305889 18.792938 22.440020 +v 53.755890 18.792934 18.240019 +v 57.155884 1.342938 20.340015 +v 54.855885 1.342936 16.340015 +v 50.255886 1.342937 16.340015 +v 51.305889 18.792934 18.240019 +v 47.955887 14.142940 20.340015 +v 50.105888 18.792936 20.340019 +v 56.355885 -5.057064 23.690018 +v 58.305885 -5.057063 20.340017 +v 54.855885 1.342937 24.340015 +v 54.655884 7.742937 23.990019 +v 69.105888 -5.057066 23.890017 +v 63.655884 -5.057065 23.590017 +v 63.655884 1.342935 23.590015 +v 69.105888 1.342934 23.890015 +v 22.755884 1.342942 24.340015 +v 22.955887 7.742942 23.990019 +v 20.855886 7.742943 20.340019 +v 20.455885 1.342944 20.340015 +v 22.755886 14.142942 24.340015 +v 20.455887 14.142944 20.340015 +v 27.355886 14.142941 24.340015 +v 26.305885 18.792942 22.440020 +v 23.855886 18.792942 22.440020 +v 22.605886 18.792940 20.340019 +v 22.755886 14.142941 16.340015 +v 22.955887 7.742941 16.690020 +v 27.355886 14.142941 16.340015 +v 27.155886 7.742941 16.690020 +v 25.055887 25.542940 20.340015 +v 23.855886 18.792940 18.240019 +v 22.755884 1.342941 16.340015 +v 27.355885 1.342940 16.340015 +v 29.255886 7.742943 20.340019 +v 29.655884 1.342942 20.340015 +v 26.305885 18.792938 18.240019 +v 27.955885 -5.057057 15.390018 +v 30.805883 -5.057058 20.340017 +v 27.505886 18.792940 20.340019 +v -45.244122 -14.657056 97.740021 +v -44.994118 -11.607053 95.940025 +v -51.894115 -11.607056 96.740021 +v -52.394119 -14.657055 98.440025 +v -38.944122 -14.657055 94.640022 +v -38.944118 -11.607056 92.890022 +v -33.594120 -14.657054 89.990021 +v -33.594116 -11.607056 88.190025 +v -52.494118 -5.507051 94.640015 +v -45.894115 -5.507053 93.990013 +v -46.744118 0.592946 91.990013 +v -53.094116 0.592948 92.590019 +v -40.094116 -5.507056 91.040016 +v -41.244118 0.592944 89.190018 +v -34.744118 -5.507055 86.340019 +v -39.394119 -14.657055 100.790024 +v -36.544121 -14.657057 98.540024 +v -32.994122 -14.657056 94.390022 +v -39.394119 -14.657060 126.390022 +v -39.394119 -14.657060 132.790039 +v -32.994122 -14.657061 132.790039 +v -32.994122 -14.657061 126.390022 +v -39.394119 -14.657056 119.990021 +v -32.994122 -14.657058 119.990021 +v -39.394119 -14.657055 113.590027 +v -32.994122 -14.657057 113.590027 +v -39.394119 -14.657055 107.190025 +v -32.994122 -14.657057 107.190025 +v -32.994122 -14.657056 100.790024 +v 104.055885 -3.007067 -4.509984 +v 103.855888 3.392933 -4.309988 +v 96.755882 2.592934 -4.359983 +v 96.755882 -3.007066 -4.359983 +v 91.655884 3.392932 -3.409986 +v 91.505882 -3.007066 -3.459985 +v 86.955887 2.592933 -1.459987 +v 90.305885 3.392934 -6.359983 +v 84.205887 2.592933 -3.109987 +v 86.955887 -3.007067 -1.459984 +v 99.355888 -3.457067 2.190017 +v 83.605888 -3.007066 2.790015 +v 94.605888 -5.057068 7.890014 +v 94.605888 1.342934 7.890014 +v 100.455887 2.942933 1.690014 +v 100.955887 12.292933 8.740016 +v 94.305885 12.942933 12.840014 +v 98.355888 18.542934 14.640016 +v 104.955887 17.542931 10.490016 +v 97.105888 6.992934 8.540015 +v 90.655884 7.342933 12.840015 +v 88.155884 1.342933 12.040014 +v 93.405884 20.092928 19.240019 +v 97.605888 21.292931 21.690020 +v 102.505882 21.592934 16.840019 +v 102.155884 6.442933 2.190015 +v 89.555885 13.742932 17.340015 +v 86.055885 8.342935 17.440020 +v 84.455887 19.942934 26.790018 +v 90.355888 21.142933 24.790018 +v 88.605888 20.792933 23.690020 +v 109.055885 22.242931 12.640018 +v -100.944115 17.342962 0.190017 +v -93.744118 20.392963 3.640015 +v -88.494118 17.592960 0.040017 +v -93.644119 16.442966 -6.009983 +v -86.344116 16.242960 -3.909982 +v -79.044121 16.042959 -1.809982 +v -79.994118 16.292963 -9.359983 +v -72.294121 14.142959 -5.209985 +v -73.144119 16.842957 -16.809988 +v -63.994114 15.642958 -12.159983 +v -92.394119 12.392961 12.240016 +v -85.794121 12.092959 11.090016 +v -89.244118 17.192959 8.790017 +v -96.344116 16.892962 9.890017 +v -110.494118 -1.707036 15.590015 +v -103.544121 -0.157040 16.190016 +v -109.594116 4.092963 14.990017 +v -116.844116 2.042965 14.390014 +v -96.744118 1.192960 17.590015 +v -102.644119 5.642960 16.390011 +v -90.044121 1.342960 19.140015 +v -95.294121 6.542960 17.890018 +v -100.044121 11.542960 15.040016 +v -105.144119 16.442963 12.640017 +v -88.044121 7.092961 15.690015 +v -83.194115 1.142958 17.590015 +v -96.744118 -5.207040 17.590019 +v -90.044121 -5.057040 19.140017 +v -83.144119 -5.057041 19.290016 +v -77.094116 -5.057043 17.090017 +v -77.094116 1.342957 17.090015 +v -75.594116 14.392957 3.290015 +v -68.594116 13.342958 0.640015 +v -84.344116 13.392962 5.890016 +v -81.994118 5.892960 15.190016 +v -99.544121 20.342958 6.740016 +v 111.155884 22.442936 -57.259983 +v 111.155884 19.992941 -53.009983 +v 114.605888 21.292938 -52.909981 +v 115.805885 23.442934 -59.259983 +v 115.155884 19.242935 -46.109982 +v 111.155884 18.142941 -52.859982 +v 120.305885 24.092937 -53.859985 +v 126.705894 27.442932 -61.459988 +v 121.455894 26.092932 -60.459988 +v 111.155884 18.242939 -41.709984 +v 116.755882 19.642931 -39.459984 +v 107.505882 18.692936 -47.059982 +v 101.755882 16.442938 -56.959980 +v 103.655884 18.292938 -56.959984 +v 103.005882 19.342934 -62.409981 +v 100.555885 16.942936 -62.409981 +v 102.905884 15.992940 -62.409977 +v 104.255882 17.242935 -62.409981 +v 101.755882 16.442940 -67.859993 +v 103.655884 18.292940 -67.859993 +v 108.005882 20.092936 -70.909996 +v 106.505882 19.242939 -67.859993 +v 108.005882 22.042938 -67.760002 +v 106.355888 20.542934 -62.409981 +v 107.955887 23.092934 -62.409981 +v -73.144119 16.692963 -59.260002 +v -68.144119 16.092964 -53.860004 +v -68.444115 14.292962 -59.060001 +v -70.344116 14.192964 -65.060020 +v -75.094116 17.642969 -65.210022 +v -33.894115 -3.407043 -52.810005 +v -26.794117 -3.307042 -52.510010 +v -30.944117 -3.257043 -53.410011 +v -32.944118 -3.257043 -55.210011 +v -33.944118 -3.407043 -59.210007 +v -30.144117 -3.357041 -58.360012 +v -26.594116 -3.357044 -59.210011 +v -28.144117 -3.257044 -56.510010 +v -39.394115 -5.007045 -19.460009 +v -39.394115 -5.057045 -25.860008 +v -45.194118 -5.057043 -23.460009 +v -44.844116 -5.057043 -17.160007 +v -13.794117 -4.257044 -72.010010 +v -20.194117 -3.157042 -72.010010 +v -20.194117 -3.757043 -65.610008 +v -13.794117 -4.107048 -65.610008 +v -44.644115 -4.257041 -46.410007 +v -45.794117 -4.207040 -52.810005 +v -51.894115 -5.057039 -53.860008 +v -49.194118 -5.057041 -48.160007 +v -39.394115 -4.007042 -46.410007 +v -39.394115 -3.757042 -52.810005 +v -32.994118 -3.607042 -46.410007 +v -26.594116 -3.407043 -46.410007 +v -45.794117 -4.107040 -59.210007 +v -54.294117 -5.057038 -59.710007 +v -39.394115 -3.707042 -59.210007 +v -39.394115 -4.007045 -32.260006 +v -39.394115 -4.257045 -38.660007 +v -45.344116 -5.057042 -36.110008 +v -45.294117 -5.057043 -29.810009 +v -45.794117 -4.007041 -65.610008 +v -52.194118 -4.307042 -65.610008 +v -39.394115 -3.757040 -65.610008 +v -32.994118 -3.507041 -65.610008 +v -26.594116 -3.507042 -65.610008 +v -20.194117 -3.557045 -59.210007 +v -45.794117 -3.657038 -72.010010 +v -52.194118 -4.307038 -72.010010 +v -39.394115 -3.207039 -72.010010 +v -32.994118 -3.207040 -72.010010 +v -26.594116 -3.207041 -72.010010 +v -32.994118 -5.057047 -27.210009 +v -32.994118 -4.007047 -33.610008 +v -32.994118 -4.007044 -40.010006 +v -26.594116 -3.907046 -40.010006 +v -57.444118 -5.057037 -71.910011 +v -56.244118 -5.057041 -65.710014 +v -47.194118 -5.057041 -42.160007 +v -45.194118 1.342957 -23.460011 +v -44.844116 1.342957 -17.160009 +v -45.294117 1.342957 -29.810011 +v -45.344116 1.342958 -36.110012 +v -47.194118 1.342959 -42.160011 +v -49.194118 1.342960 -48.160011 +v -51.894115 1.342961 -53.860012 +v -54.294117 1.342962 -59.710011 +v -56.244118 1.342963 -65.710014 +v -57.444118 1.342963 -71.910011 +v -53.644115 9.142957 -11.060007 +v -51.944118 10.642957 -17.160007 +v -56.144112 14.892958 -17.210011 +v -58.294113 12.842957 -11.410010 +v -56.394112 15.642958 -23.460012 +v -61.444115 18.092958 -23.460005 +v -61.294113 17.542955 -17.310013 +v -52.294117 11.242956 -23.460009 +v -48.694118 5.292957 -17.210014 +v -49.044117 5.292958 -23.460014 +v -56.444115 16.742964 -29.810013 +v -61.494114 18.942963 -29.810007 +v -52.394115 12.142958 -29.810011 +v -49.144115 5.442958 -29.810015 +v -56.544113 17.992960 -36.110008 +v -61.594112 20.142960 -36.110008 +v -52.444115 13.492958 -36.110004 +v -49.244118 6.542958 -36.110016 +v -58.394112 16.342962 -42.160004 +v -63.444115 19.042965 -42.160007 +v -54.294117 12.242959 -42.160004 +v -51.044117 6.842957 -42.160015 +v -60.544113 13.742960 -48.160004 +v -65.444115 17.792961 -48.160007 +v -56.294117 9.592960 -48.160015 +v -53.094116 5.792959 -48.160015 +v -63.194118 12.392961 -53.860004 +v -59.044117 8.592960 -53.860016 +v -55.794117 5.192961 -53.860016 +v -65.594116 11.142962 -59.710018 +v -61.394115 7.592963 -59.710014 +v -58.194118 4.192963 -59.710014 +v -67.544121 10.442963 -65.710022 +v -63.344116 7.442964 -65.710022 +v -60.094116 4.342959 -65.710014 +v -61.344116 5.292964 -71.910011 +v -64.544121 7.842964 -71.910019 +v -28.444117 4.892957 -54.010014 +v -26.794117 5.892958 -52.510014 +v -26.794117 6.242957 -52.510014 +v -28.644117 5.242956 -54.110016 +v -29.194117 -3.307043 -54.610012 +v -28.944117 -3.307043 -54.460011 +v -28.594116 2.892957 -54.110012 +v -28.794117 2.942957 -54.260010 +v -28.644117 3.142956 -56.310009 +v -27.944117 5.842956 -55.560013 +v -29.944117 5.842956 -53.310013 +v -30.794117 3.142958 -53.960011 +v -32.994118 -4.957047 -20.810009 +v -26.594116 -4.657047 -20.810009 +v -26.594116 -4.457048 -27.210009 +v -28.344114 6.942957 -52.110016 +v -32.194118 3.142957 -54.960011 +v -29.794117 3.142956 -57.610012 +v -29.044115 6.392956 -56.710014 +v -31.244114 6.392958 -54.260014 +v -26.644115 8.042955 -54.260014 +v -28.544115 8.042957 -52.110016 +v -27.044115 6.942955 -50.910015 +v -26.994114 8.042957 -50.710014 +v -142.294113 -2.457026 -54.059986 +v -147.394119 -2.457027 -51.309986 +v -147.394119 -8.857024 -51.009983 +v -142.094116 -8.857027 -53.909981 +v -139.444122 -7.857030 -32.709984 +v -139.844116 -5.607030 -32.309982 +v -138.694122 -5.607028 -27.859982 +v -138.144119 -7.857032 -27.659990 +v -141.994125 -5.607029 -24.609982 +v -141.844116 -7.857029 -24.009989 +v -146.394119 -5.607028 -25.809982 +v -144.294113 -5.607030 -33.509983 +v -147.594116 -5.607028 -30.309982 +v -148.294113 -12.207029 -30.509985 +v -146.944122 -12.207030 -25.259985 +v -146.844116 -7.857028 -25.409990 +v -148.144119 -7.857028 -30.459990 +v -141.794113 -12.207030 -23.859985 +v -141.844116 -7.857029 -24.059990 +v 69.655884 -5.057054 -125.409988 +v 74.155884 -5.057053 -122.159988 +v 78.605888 -5.057053 -127.559990 +v 73.155884 -5.057053 -130.759995 +v 37.405884 -4.307048 -116.809990 +v 43.805885 -3.957049 -116.809990 +v 43.805885 -4.557049 -123.209984 +v 37.955883 -4.707048 -123.209984 +v 45.255886 -5.057049 -129.509995 +v 39.205883 -5.057045 -130.709991 +v 84.605888 -5.057056 -124.209984 +v 84.605888 1.342945 -124.209984 +v 78.605888 1.342948 -127.559990 +v 45.055885 0.942952 -129.059982 +v 39.005886 1.342952 -130.159988 +v 44.755886 3.442952 -128.359985 +v 38.655884 4.242953 -129.259995 +v 50.855885 -0.057048 -127.509987 +v 50.605885 2.042952 -126.959984 +v 56.405884 -1.657052 -125.409988 +v 56.205883 0.142948 -125.109985 +v 61.605885 -5.057051 -123.009987 +v 61.555885 -3.257051 -122.909988 +v 56.505886 -5.057048 -125.659988 +v 61.455883 -2.207051 -122.759987 +v 50.655888 15.942953 -144.610001 +v 57.105888 14.092954 -143.809998 +v 57.805889 21.492950 -145.059998 +v 51.655888 22.542950 -145.760010 +v 49.455883 9.492952 -143.059982 +v 56.405884 8.792951 -142.709991 +v 56.205883 6.492951 -141.359985 +v 64.205887 21.792950 -142.410004 +v 67.505890 26.842953 -146.860001 +v 58.805889 26.442947 -146.309998 +v 63.405888 14.542951 -141.059998 +v 62.005886 8.442951 -139.709991 +v 62.655884 4.292952 -139.059982 +v 46.355885 10.842952 -143.159988 +v 47.155888 17.242950 -146.260010 +v 70.805885 21.392950 -139.610001 +v 73.955894 26.192947 -142.660004 +v 69.855888 14.242950 -138.410004 +v 69.005882 8.242948 -137.059982 +v 68.705887 2.542948 -136.259995 +v 52.255890 25.392956 -146.610001 +v 67.955887 2.542949 -134.959991 +v 61.905884 4.292948 -137.759995 +v 55.405884 6.492952 -140.059982 +v 48.655884 9.492952 -141.759995 +v 42.005890 23.692951 -144.510010 +v 40.205887 23.692957 -147.610001 +v 39.655888 17.242958 -147.610001 +v 41.755890 17.242952 -144.010010 +v 45.605888 23.692951 -144.510010 +v 45.855888 17.242952 -144.010010 +v 38.655884 10.842955 -147.609985 +v 41.255886 10.842953 -143.159988 +v 47.955887 17.242958 -147.610001 +v 48.955883 10.842953 -147.609985 +v 40.555885 4.542954 -142.009995 +v 37.355885 4.542954 -147.609985 +v 47.055885 4.542953 -142.009995 +v 34.205887 24.692951 -146.210007 +v 34.205887 17.342951 -146.210007 +v 34.205883 10.942954 -146.209991 +v 48.255886 3.442953 -140.859985 +v 61.455883 0.192949 -136.909988 +v 67.555885 -2.207051 -134.109985 +v 55.005886 2.042953 -139.159988 +v 64.505882 -2.207051 -128.409988 +v 58.855885 0.192949 -131.009995 +v 52.805885 2.042953 -133.059982 +v 46.505886 3.442952 -134.609985 +v 39.555885 4.242953 -135.609985 +v 40.505890 30.142958 -147.610001 +v 42.155888 30.142952 -144.760010 +v 41.955887 36.592953 -144.360001 +v 40.055889 36.592953 -147.610001 +v 45.455887 30.142952 -144.760010 +v 45.655888 36.592953 -144.360001 +v 19.205883 -14.657065 110.890022 +v 18.205883 -14.657064 113.590027 +v 21.455883 -14.657065 112.140022 +v 15.705882 -14.657063 107.190025 +v 18.405882 -14.657067 108.390022 +v 18.205883 -14.657063 100.790024 +v 22.105883 -14.657065 105.140022 +v 13.755882 -14.657066 134.540039 +v 19.755882 -14.657069 138.140030 +v 18.455883 -14.657069 134.190033 +v 16.055882 -14.657066 130.040039 +v 13.105882 -14.657066 128.940033 +v 17.105883 -14.657067 121.990021 +v 18.305882 -14.657065 124.390022 +v 11.805882 -14.657066 132.790039 +v 11.805882 -14.657068 139.190033 +v 11.805882 -14.657067 126.390022 +v 18.205883 -14.657064 119.990021 +v 11.805882 -14.657063 119.990021 +v 28.405882 -11.707067 105.290024 +v 26.205883 -8.307066 104.990021 +v 27.155882 -11.707066 106.890022 +v 25.305882 -12.107065 107.090027 +v 27.705883 -14.657065 107.890022 +v 24.755882 -14.657064 108.140022 +v 24.255882 -11.707067 105.290024 +v 25.255882 -11.707067 103.490021 +v 27.355883 -11.707067 103.490021 +v 24.255882 -12.707067 111.340027 +v 24.855883 -11.057067 110.090027 +v 23.955883 -12.957067 110.140022 +v 25.055882 -12.707067 109.290024 +v 25.405882 -12.707067 112.040024 +v 26.505882 -12.707067 109.440025 +v 26.505882 -12.707067 111.190025 +v 27.555882 -14.657066 111.740021 +v 21.155882 -11.207067 110.790024 +v 19.905882 -11.207067 110.090027 +v 21.055882 -6.857065 109.340027 +v 19.155882 -11.657067 108.640022 +v 20.755882 -11.207065 107.940025 +v 22.105883 -11.207067 108.490021 +v 22.305882 -11.207067 109.940025 +v 18.555882 -7.607066 129.890015 +v 21.005884 -4.257067 129.440018 +v 19.655882 -7.607068 127.990021 +v 17.605883 -11.107066 129.840012 +v 19.405882 -11.107068 126.740021 +v 21.455883 -7.557067 128.740021 +v 22.655882 -11.107068 127.540024 +v 22.605883 -7.557067 129.890015 +v 24.705883 -11.107067 129.840012 +v 21.905882 -7.607069 131.840012 +v 22.955883 -11.107069 132.940018 +v 19.655882 -7.607066 131.840012 +v 19.405882 -11.107068 132.940018 +v 5.405881 -14.657066 126.390022 +v 5.405881 -14.657066 132.790039 +v 5.405881 -14.657063 119.990021 +v 5.405881 -14.657063 113.590027 +v 11.805882 -14.657063 113.590027 +v 5.405881 -14.657062 107.190025 +v 11.805882 -14.657063 107.190025 +v 5.405881 -14.657062 100.790024 +v 11.805882 -14.657063 100.790024 +v 5.405881 -14.657062 94.390022 +v 11.805882 -14.657062 94.390022 +v -20.194118 -14.657058 119.990021 +v -20.194118 -14.657063 126.390022 +v -13.794118 -14.657064 126.390022 +v -13.794118 -14.657061 119.990021 +v -20.194118 -14.657059 113.590027 +v -13.794118 -14.657060 113.590027 +v -20.194118 -14.657058 107.190025 +v -13.794118 -14.657059 107.190025 +v -7.394119 -14.657061 107.190025 +v -7.394119 -14.657062 113.590027 +v -0.994118 -14.657062 113.590027 +v -0.994118 -14.657061 107.190025 +v -7.394119 -14.657060 100.790024 +v -0.994118 -14.657061 100.790024 +v -7.394119 -14.657060 94.390022 +v -0.994118 -14.657061 94.390022 +v 18.205883 -14.657063 94.390022 +v -20.194118 -14.657058 100.790024 +v -13.794118 -14.657060 100.790024 +v -20.194118 -14.657059 94.390022 +v -13.794118 -14.657059 94.390022 +v -0.994118 -14.657065 126.390022 +v -0.994118 -14.657066 132.790039 +v -20.194118 -14.657063 132.790039 +v -13.794118 -14.657063 132.790039 +v -0.994118 -14.657061 87.990021 +v 5.405881 -14.657062 87.990021 +v -7.394119 -14.657065 126.390022 +v -7.394119 -14.657065 132.790039 +v -7.394119 -14.657061 119.990021 +v -0.994118 -14.657063 119.990021 +v -26.594118 -14.657059 113.590027 +v -26.594118 -14.657058 119.990021 +v -26.594118 -14.657057 94.390022 +v -26.594118 -14.657057 100.790024 +v -149.344116 -10.357026 -14.809987 +v -155.194122 -10.357028 -18.509987 +v -156.944122 -10.357029 -13.309987 +v -151.344116 -10.357028 -9.909987 +v -159.744125 -10.357029 -7.409988 +v -153.544113 -10.357028 -3.709988 +v -170.694122 9.992974 -11.609983 +v -174.144119 11.092976 -18.609983 +v -179.994125 15.592978 -15.609982 +v -178.744125 15.042978 -9.059982 +v -168.894119 8.092976 -3.509986 +v -174.944122 13.242973 -1.059985 +v -168.444122 6.142975 -19.709982 +v -166.394119 5.042973 -12.059984 +v -161.044113 -4.657027 -18.709984 +v -159.644119 -5.257027 -13.209987 +v -170.194122 12.792974 4.790016 +v -163.644119 8.592973 0.590014 +v 97.205887 -5.857060 -81.609985 +v 87.705887 -5.857060 -83.259987 +v 88.455887 -5.857058 -77.859985 +v -39.394119 -14.657066 190.390015 +v -32.994122 -14.657066 190.390015 +v -39.394119 -14.657060 139.190033 +v -32.994122 -14.657061 139.190033 +v -26.594118 -14.657067 190.390015 +v -26.594118 -14.657063 145.590027 +v -26.594118 -14.657062 139.190033 +v 87.555885 -5.057061 -55.209984 +v 88.605888 -5.407061 -52.809982 +v 82.855888 -5.057058 -59.359982 +v 108.005882 7.742938 -66.059998 +v 107.955887 7.742938 -60.009991 +v 108.005882 14.142935 -67.109993 +v 107.955887 1.342937 -59.609985 +v 87.555885 -4.257061 -55.209984 +v 82.855888 -4.257061 -59.359982 +v 102.255882 -5.057063 -69.409988 +v 98.505882 -5.057061 -75.009987 +v 108.105888 -5.057066 -59.759983 +v 90.155884 -5.857059 -72.609985 +v 108.005882 20.092939 -53.909981 +v 106.505882 19.242939 -56.959984 +v 107.955887 17.342939 -53.709984 +v 111.155884 20.042940 -53.009983 +v 106.355888 17.342939 -67.859993 +v -76.494118 21.492970 -103.510002 +v -74.744118 21.642965 -96.360001 +v -59.744118 5.892966 -96.859985 +v -57.244118 1.342965 -97.059990 +v -55.144115 -5.057037 -87.709984 +v -55.144115 -5.057038 -95.059990 +v -58.544117 6.242966 -90.309990 +v -55.144115 6.942965 -90.159996 +v -55.144115 6.942964 -92.609993 +v -55.144115 4.792963 -92.209984 +v -55.144115 4.792964 -90.559990 +v -58.544117 5.142965 -90.509987 +v -55.594116 4.642966 -95.859985 +v -55.794117 6.242964 -92.459984 +v -55.644115 1.342963 -95.309990 +v -55.444118 1.342965 -97.059990 +v -55.144115 -5.057035 -97.759987 +v -57.244118 -5.057035 -97.759987 +v -130.194122 -3.807037 28.940018 +v -131.344116 0.292963 27.790014 +v -135.394119 -4.607034 26.640017 +v -138.394119 0.142968 26.990015 +v -122.694115 3.392961 41.590012 +v -110.144119 -6.107042 39.990021 +v -111.694115 -6.457040 35.840019 +v -131.294113 -3.507036 44.490021 +v -131.544113 -1.907038 41.040016 +v -114.844116 -6.607040 47.140018 +v -131.394119 -4.107036 37.090019 +v -131.644119 -3.007036 39.140015 +v -131.394119 -4.107037 42.890018 +v -134.244125 -3.157035 39.140015 +v -131.344116 0.292962 52.190014 +v -138.944122 0.442962 52.440014 +v 71.055885 12.942932 72.440010 +v 72.555885 13.792931 63.790024 +v 22.055887 19.442942 63.790020 +v 37.255890 20.942936 57.790020 +v 29.605888 22.392939 57.540020 +v 71.155884 -14.657072 93.790024 +v 72.005882 -11.457073 92.340027 +v 23.255882 -14.657063 88.490021 +v 30.005882 -14.657065 87.240021 +v 23.255882 -14.657063 81.490021 +v 60.705879 -14.657069 89.540024 +v 71.605888 -11.407072 86.940025 +v 70.805885 -11.457071 81.090027 +v 73.505882 -11.457072 81.090027 +v 71.055885 7.492931 75.890007 +v 76.855888 7.492930 76.740005 +v 76.855888 12.942927 73.340012 +v 72.705887 -1.757072 77.640015 +v 71.555885 -5.057071 80.790016 +v 23.255882 -11.207065 79.990021 +v 75.805885 -14.657080 177.590027 +v 75.805885 -14.657078 139.190033 +v 107.805885 -14.657087 190.390015 +v 114.205887 -14.657088 190.390015 +v 120.605888 -14.657089 190.390015 +v 127.005882 -14.657090 190.390015 +v 127.005882 -14.657086 183.990036 +v 127.005882 -14.657086 177.590027 +v 127.005882 -14.657086 171.190033 +v 127.005882 -14.657086 164.790039 +v 127.005882 -14.657085 158.390030 +v 127.005882 -14.657085 151.990036 +v 127.005882 -14.657085 145.590027 +v -211.194122 35.842983 -52.809975 +v -214.494125 35.892979 -56.009975 +v -213.244125 35.792992 -60.609974 +v -206.644119 35.792980 -54.159973 +v -200.094116 26.092983 -69.159973 +v -193.944122 22.692982 -59.359982 +v -201.444122 22.642982 -47.059982 +v -193.644119 21.542980 -48.909981 +v 178.205887 -14.657094 183.990036 +v 178.205887 -14.657099 190.390015 +v 178.205887 -14.657094 177.590027 +v 178.205887 -14.657094 171.190033 +v 178.205887 -14.657094 164.790039 +v 178.205887 -14.657095 158.390030 +v 178.205887 -14.657093 151.990036 +v 178.205887 -14.657094 145.590027 +v 178.205887 -14.657092 139.190033 +v 70.805885 -11.457069 77.640022 +v 71.555885 -5.057072 77.640015 +v 83.605888 -11.457072 77.640022 +v 82.855888 -5.057073 77.640015 +v 81.655884 -1.757073 77.640015 +v 70.805885 -5.057068 53.640018 +v 77.205887 -5.057070 53.640018 +v 73.505882 -11.457070 77.640022 +v 77.205887 -11.457070 77.640022 +v 80.905884 -11.457072 77.640022 +v 76.105888 -0.157072 77.640015 +v 78.255882 -0.157073 77.640015 +v -147.394119 -1.907027 -51.959988 +v -154.494125 3.942976 -60.759991 +v -154.694122 3.942976 -53.809990 +v -153.044113 9.192976 -59.909988 +v -152.094116 3.942976 -60.709991 +v -153.044113 8.792975 -58.959991 +v -153.094116 8.792974 -55.509991 +v -153.194122 9.592976 -57.259991 +v -76.394119 20.992970 -90.260002 +v -58.544117 4.642965 -86.909988 +v -58.544117 1.342963 -87.459984 +v -58.544117 1.342964 -85.709984 +v -58.544117 4.042962 -88.459984 +v -55.644115 1.342962 -87.459984 +v -55.444118 1.342963 -85.709984 +v -57.244118 -5.057036 -85.009987 +v -55.144115 -5.057036 -85.009987 +v -58.144115 -5.057036 -78.159988 +v -57.444118 -5.057037 -71.909988 +v -142.344116 3.942974 -54.059990 +v -152.394119 -8.857026 -60.259983 +v -152.194122 -2.457024 -60.109985 +v -141.294113 -14.707028 -60.109993 +v -147.044113 -15.057025 -64.209976 +v -141.044113 10.342974 -60.459995 +v -141.244125 10.342974 -53.409992 +v -147.044113 10.342976 -64.109993 +v -150.494125 15.092974 -55.309978 +v -153.244125 10.342976 -60.759995 +v -5.144114 17.242966 -174.410004 +v -3.044114 17.242968 -170.860001 +v -4.594112 23.692965 -174.410004 +v 0.855887 22.142965 -171.210007 +v -138.444122 4.942966 59.540012 +v -131.844116 6.292963 63.440010 +v -65.694115 14.242951 77.840012 +v 13.405890 47.192963 -161.009964 +v 15.755891 47.192959 -166.659958 +v 21.405891 47.192955 -169.009964 +v 27.055891 47.192955 -166.659958 +v 32.605892 47.192959 -158.959961 +v 31.405891 54.692955 -161.009964 +v 9.005891 47.192963 -161.009964 +v 58.005886 -5.057064 23.940018 +v 69.355888 -4.357065 17.690018 +v 50.205883 -4.007062 4.790017 +v 49.705883 -3.007061 2.790015 +v -144.544113 4.742980 -122.859985 +v -172.294113 11.842982 -113.959991 +v -160.944122 10.642980 -107.809998 +v -155.294113 7.592980 -104.859993 +v -150.894119 2.442980 -102.909988 +v -148.844116 -3.957020 -101.709984 +v -147.244125 -10.357023 -101.209976 +v -141.344116 -16.657021 -102.509979 +v -141.194122 -10.357022 -104.609978 +v -147.394119 -16.657026 -99.109978 +v -134.594116 -16.657022 -104.209976 +v -134.244125 -10.357024 -106.459976 +v -127.994118 -10.357024 -106.209976 +v 96.505882 -3.007067 -7.559988 +v 96.505882 2.592933 -7.559987 +v 90.455887 -3.007066 -6.309988 +v 104.405884 -3.007067 -10.959988 +v 102.305885 -3.007066 -10.459988 +v 104.405884 3.192933 -11.509984 +v 104.405884 5.642933 -11.759985 +v 104.405884 6.542932 -14.159985 +v 105.705887 7.192931 -15.009986 +v 102.305885 8.942935 -15.359982 +v 24.605883 -14.657077 228.790009 +v 24.605883 -14.657076 209.590012 +v 24.605883 -14.657077 203.190002 +v 24.605883 -14.657076 196.790009 +v 24.605883 -14.657076 190.390015 +v 63.005882 -14.657081 190.390015 +v 69.405884 -14.657082 190.390015 +v 75.805885 -14.657084 228.790009 +v 70.105888 -4.707053 -108.009987 +v 43.805885 -5.057055 -59.209984 +v 45.805885 -5.057054 -61.209984 +v 43.955883 -5.057055 -65.609985 +v 54.605885 -5.057054 -70.009987 +v 46.805885 -2.657055 -69.009987 +v 50.205883 -2.657056 -70.409988 +v 53.605885 -2.657056 -69.009987 +v 37.405884 -4.807051 -72.009987 +v 31.005884 -3.857049 -78.409988 +v 32.105885 -4.007050 -84.909988 +v 37.405884 -4.857051 -65.609985 +v 31.005884 -3.607050 -72.009987 +v 88.755882 -5.057056 -108.759987 +v 88.605888 -5.057056 -110.409988 +v 66.205887 -5.057050 -120.009987 +v 88.605888 -5.057056 -116.809990 +v 81.705887 -5.007056 -118.209984 +v 51.005886 -5.057048 -127.809990 +v 50.205883 -4.457050 -123.209984 +v 50.205883 -3.707050 -116.809990 +v 63.005886 -5.057055 -72.009987 +v 78.705887 -4.257061 -65.309990 +v 80.705887 -4.257059 -66.909988 +v 80.705887 -5.857059 -66.909988 +v 75.955887 -4.257054 -95.309990 +v 85.405884 -4.257056 -103.709984 +v 104.405884 -3.007066 -17.359983 +v 104.405884 -2.607067 -11.359983 +v 104.405884 -2.607066 -16.959984 +v 96.505882 -3.007067 -14.159986 +v 96.505882 -3.007067 -20.809984 +v 86.455887 -3.007066 -14.159986 +v 86.455887 -3.007066 -9.009988 +v 90.455887 -3.007066 -14.159986 +v 86.455887 -3.007065 -19.359983 +v 90.455887 -3.007063 -22.059984 +v 76.205887 -3.007061 -23.709984 +v 71.455887 -3.007061 -24.059984 +v 79.305885 -3.007064 -20.559984 +v 76.555885 -3.007063 -18.959984 +v 53.955883 -3.007060 -20.559984 +v 56.755886 -3.007060 -18.959984 +v 77.705887 -3.007062 3.390016 +v 81.055885 -3.007065 -14.159986 +v 84.205887 -3.007066 -3.109984 +v 81.355888 -3.007065 0.540016 +v 51.955883 -3.007060 0.540016 +v 57.105885 -3.007060 -4.659986 +v 60.105885 -3.007061 -34.209988 +v 55.555885 -3.007059 -31.709984 +v 51.955883 -3.007057 -28.859983 +v 49.105885 -3.007058 -25.259983 +v 84.205887 -3.007064 -25.259983 +v 77.705887 -3.007062 -31.709984 +v 81.355888 -3.007061 -28.859983 +v 55.455883 -3.007061 -14.159986 +v 77.855888 -3.007064 -14.159986 +v 56.755886 -3.007061 -9.359987 +v 66.655884 -3.007061 -25.359983 +v 61.855885 -3.007060 -4.259984 +v 66.655884 -3.007064 -2.959985 +v 90.005882 -5.057071 40.840019 +v 90.005882 -5.057071 34.440018 +v 64.405884 -5.057066 47.240021 +v 64.405884 -5.057067 53.640018 +v 64.405884 -5.057065 40.840019 +v 64.405884 -5.057067 34.440018 +v 64.405884 -5.057066 28.040016 +v 81.705887 4.642932 53.640011 +v 77.205887 6.242931 53.640011 +v 82.855888 1.342929 53.640015 +v 70.805885 6.142932 40.840012 +v 77.205887 6.142931 47.240013 +v 69.355888 4.642935 45.340012 +v 69.355888 4.642934 36.390011 +v 88.605888 -4.507061 -40.009983 +v 88.605888 -4.757061 -46.409981 +v 43.805885 -2.907055 -27.209984 +v 46.355885 -3.007059 -26.909985 +v 49.705883 -3.007058 -31.159985 +v 43.805885 -2.607058 -33.609985 +v 95.805885 -5.257062 -45.459984 +v 50.205883 -3.707059 -40.009983 +v 78.705887 -5.057057 -65.309990 +v 49.705883 3.392942 -31.159988 +v 51.955883 3.392943 -28.859987 +v 55.555885 2.592941 -31.709988 +v 60.405884 3.392941 -33.859989 +v 72.905884 3.392937 -33.859989 +v 66.355888 2.592942 -34.759987 +v 60.255886 2.592939 -26.859987 +v 66.655884 3.392941 -28.559988 +v 73.055885 2.592937 -26.859987 +v 35.105885 -5.057058 21.640017 +v 32.405884 -5.057058 21.640017 +v 45.205883 -5.057060 21.640017 +v 42.505886 -5.057060 21.640017 +v 45.205883 -5.057064 28.040016 +v 49.155884 -5.057065 33.990021 +v 51.605885 -5.057065 34.490021 +v 44.455883 1.342937 28.040014 +v 45.005886 4.642938 43.990013 +v 37.755886 6.242940 21.640018 +v 39.855885 6.242940 21.640018 +v 38.805885 6.242938 28.040018 +v 44.455883 1.342937 21.640015 +v 43.305885 4.642937 28.040012 +v 43.305885 4.642941 21.640013 +v 34.855885 1.342938 21.640015 +v 46.705883 -5.057065 39.890018 +v 42.555885 6.242938 37.090012 +v 46.705883 6.242935 39.890011 +v 39.805885 6.242940 32.940010 +v 51.605885 6.242935 40.840012 +v 178.205887 -14.657100 228.790009 +v 13.205889 34.392963 -161.010010 +v 10.205890 37.592964 -158.960007 +v 9.005890 37.592964 -161.010010 +v 9.455891 42.642963 -161.010025 +v 10.455891 42.642963 -159.310013 +v 15.755890 40.642963 -155.360016 +v 13.405890 40.642963 -161.010025 +v 15.605888 34.392963 -155.210007 +v 14.905888 27.992958 -154.510010 +v -116.194115 -16.957026 -78.409981 +v -135.394119 -17.457026 -97.609978 +v -141.794113 -17.307026 -97.609978 +v -121.594116 -17.507029 -71.009979 +v -115.494118 -16.907030 -71.009979 +v -148.194122 -17.257025 -97.609978 +v -93.094116 -3.857033 -82.009987 +v -93.094116 2.542967 -82.009987 +v -87.494118 10.592967 -83.659996 +v -79.644119 15.642968 -81.009995 +v -83.494118 16.342968 -94.159996 +v 43.805885 -4.007061 -1.609987 +v 43.805885 -4.307060 4.790017 +v 31.005884 -4.907059 11.190014 +v 44.705883 -3.007057 -10.059987 +v 44.705883 -3.007059 -14.159986 +v 44.705883 -3.007058 -18.309984 +v 43.555885 -3.007059 -20.359983 +v 39.355885 -3.007057 -26.209984 +v 44.505886 -3.007056 -21.359983 +v 11.755883 -5.907055 13.890018 +v 4.055883 -5.857056 16.790010 +v 5.405884 3.142947 -20.809988 +v 5.405884 1.692947 -27.209988 +v 1.205884 -2.357055 10.190016 +v -4.394117 -2.357052 8.090015 +v 115.055893 32.392925 -11.209981 +v 110.055893 38.042927 -10.459986 +v 110.055893 32.392925 -8.359981 +v 106.905891 38.042942 -12.309984 +v 105.105896 32.392925 -11.259981 +v 106.905891 38.042938 -15.909985 +v 105.105896 32.392937 -17.009981 +v 110.105896 38.042938 -17.759983 +v -30.344116 -5.057035 -130.759995 +v -23.394117 -5.057037 -120.009987 +v -12.194117 2.042963 -139.159988 +v -12.594115 6.492962 -140.059982 +v -13.394115 6.492962 -141.359985 +v -14.494115 14.542964 -144.510010 +v -14.594113 19.542959 -144.760010 +v -13.644115 8.492961 -142.759995 +v -16.744112 22.042965 -148.710007 +v 18.205883 -14.657069 139.190033 +v 24.605883 -14.657071 183.990036 +v 24.605883 -14.657072 177.590027 +v 24.605883 -14.657071 171.190033 +v 24.605883 -14.657070 145.590027 +v 24.605883 -14.657069 139.190033 +v -7.394119 -14.657070 190.390015 +v -0.994118 -14.657071 190.390015 +v -13.794118 -14.657063 139.190033 +v -20.194118 -14.657063 139.190033 +v 171.605881 -11.607085 83.590027 +v 135.255890 -4.907082 89.490013 +v 128.755890 -4.957079 87.790016 +v 184.605881 -14.657088 81.590027 +v 184.605881 -14.657088 87.990021 +v 191.005890 -14.657089 87.990021 +v 191.005890 -14.657089 81.590027 +v 139.805893 -14.657087 139.190033 +v 146.205887 -14.657089 139.190033 +v 152.605881 -14.657089 139.190033 +v 159.005890 -14.657094 190.390015 +v 159.005890 -14.657091 139.190033 +v 165.405884 -14.657091 139.190033 +v 171.805893 -14.657092 139.190033 +v 107.855888 -5.107061 -91.259987 +v 107.905884 -5.107061 -84.809990 +v 107.905884 1.342939 -84.809990 +v 107.855888 1.342940 -91.259987 +v 107.905884 -5.107061 -78.409988 +v 107.955887 1.342939 -78.409988 +v 107.955887 -5.107062 -71.959984 +v 107.955887 1.342939 -71.959984 +v 122.455887 -4.657063 -84.509987 +v 122.455887 -5.057064 -78.409988 +v 122.455887 -4.657063 -78.709984 +v 120.355888 -5.057063 -77.909988 +v 123.805885 6.242934 -82.709984 +v 120.355888 6.942935 -82.809998 +v 121.005882 6.242938 -80.559990 +v -2.644112 30.142963 -150.460007 +v 2.605887 23.692963 -147.610001 +v 0.805887 23.692957 -144.510010 +v -2.794113 23.692957 -144.510010 +v -4.294112 30.142965 -147.610001 +v -133.394119 -10.207035 30.290012 +v -134.394119 -4.757037 28.440018 +v -130.094116 -5.157037 28.690020 +v -131.094116 -7.557038 46.390018 +v -130.944122 -6.807038 45.640018 +v -127.994118 -6.557037 48.990021 +v -131.094116 -7.557034 33.590019 +v -130.944122 -6.807038 34.340019 +v -131.094116 -7.557037 36.290020 +v -131.144119 -6.807037 36.040020 +v -131.094116 -7.557036 43.690018 +v -131.144119 -6.807036 43.940018 +v -133.394119 -10.207035 49.690022 +v -113.394119 -5.857042 45.640018 +v -113.194115 -5.907039 42.090019 +v -113.194115 -5.907038 37.890018 +v -132.394119 -7.157036 37.190018 +v -132.444122 -7.507036 37.190018 +v -132.444122 -7.557037 42.540020 +v -132.394119 -7.007037 42.490021 +v -132.394119 -7.007037 42.190018 +v -132.694122 -7.007036 37.490021 +v -144.944122 18.692966 23.240019 +v -61.294113 17.542955 -17.309988 +v -68.894119 16.392958 -40.609978 +v -63.444115 19.042965 -42.159981 +v 107.905884 7.792939 -78.409996 +v 107.855888 1.342940 -91.209984 +v 111.155884 1.342938 -72.009987 +v 117.405884 1.342937 -72.009987 +v 123.805885 5.142935 -82.459984 +v -144.944122 18.692963 56.740021 +v -146.944122 18.992964 54.640018 +v -146.094116 20.292969 51.690018 +v -26.594118 -14.657068 222.390015 +v -26.594118 -14.657067 228.790009 +v 39.655888 17.242958 -174.410004 +v 47.955887 17.242958 -174.410004 +v 41.755890 17.242960 -170.860001 +v 40.505890 30.142958 -174.410004 +v 42.155888 30.142960 -171.559998 +v -153.194122 9.192975 -54.559990 +v -153.344116 10.342976 -57.259995 +v 111.155884 17.342939 -90.259995 +v 111.155884 16.942936 -84.159996 +v 111.155884 16.942940 -78.109993 +v 111.155884 17.342936 -72.009995 +v 123.805893 27.242937 -66.759972 +v 131.305893 28.242935 -68.159973 +v 104.405884 3.142933 -11.859983 +v 104.405884 5.392933 -12.059984 +v 104.405884 6.242933 -14.159985 +v 109.705887 13.242934 -28.459986 +v 93.405884 14.292945 -122.759995 +v 92.155884 7.642944 -121.159996 +v 90.605888 1.342946 -120.759987 +v 74.305885 1.342949 -132.959991 +v -113.144119 -9.457039 39.990021 +v -113.144119 -9.157040 33.940018 +v -113.794121 -5.957040 35.640018 +v -113.794121 -5.707040 39.990021 +v -113.794121 -5.507037 33.140018 +v -113.794121 -5.507041 46.840019 +v -115.594116 -5.407040 46.740021 +v -113.794121 -5.957038 44.340019 +v -115.594116 -5.407036 33.240021 +v -121.744118 -9.607038 32.690018 +v -113.144119 -9.157041 46.040020 +v -121.744118 -9.607038 47.290020 +v -109.794121 -8.607038 30.390013 +v -116.194115 -9.757037 30.390013 +v -109.794121 -8.757037 49.590019 +v -110.544121 -8.407043 56.290020 +v -136.094116 -10.557034 22.790012 +v -130.544113 -10.307035 55.490025 +v -104.094116 -7.007042 56.040020 +v -103.394119 -7.707041 49.590019 +v -116.194115 -9.507036 23.990013 +v -117.544121 -9.407038 15.440013 +v 12.555888 22.192959 -152.210007 +v 21.405888 22.192961 -173.510010 +v 30.255888 22.192961 -169.860001 +v 76.555885 2.592937 -18.959988 +v 79.305885 2.592936 -20.559988 +v 71.455887 2.592939 -24.059988 +v 66.655884 3.392939 -25.359987 +v 61.855885 2.592941 -24.059988 +v 53.955883 2.592940 -20.559988 +v 56.755886 2.592940 -18.959988 +v -130.544113 -4.107037 56.140018 +v -123.294121 -2.407038 57.190014 +v -116.894119 -1.907039 56.440014 +v -110.544121 -1.357040 56.290016 +v -104.094116 -0.007041 56.040016 +v -97.644119 -5.907042 56.090019 +v -97.644119 1.142958 56.090015 +v -91.394119 1.342957 57.340015 +v -134.844116 0.192964 58.040016 +v -128.594116 1.492961 60.690014 +v -58.394115 -5.057049 68.440018 +v 82.205887 -13.057073 102.240021 +v 24.605883 -14.657067 116.340027 +v 25.705883 -14.657065 113.340027 +v 23.555882 -14.657065 112.140022 +v 24.605883 -14.657065 98.440025 +v 25.155882 -14.657064 101.640022 +v 24.605883 -14.657064 94.390022 +v 75.805885 -14.657073 119.990021 +v 77.205887 -14.657073 100.190025 +v 77.205887 -14.657074 93.790024 +v 77.205887 -11.457074 92.340027 +v 83.255882 -14.657074 93.790024 +v 82.405884 -11.457074 92.340027 +v 45.855888 17.242960 -170.860001 +v 19.505884 -2.807053 -51.709988 +v 23.305883 -2.807053 -51.709988 +v 18.255884 1.342949 -48.759987 +v 17.055883 -2.807050 -54.109985 +v 23.305883 -2.807050 -60.309986 +v 24.555883 1.342948 -63.259987 +v 25.755884 -2.807050 -57.909985 +v 19.505884 -2.807050 -60.309986 +v 17.055883 -2.807050 -57.909985 +v 18.255884 1.342949 -63.259987 +v 25.755884 -2.807051 -54.109985 +v 101.555885 -5.057060 -72.009987 +v 97.205887 -5.057060 -81.609985 +v 98.505882 -5.057061 -88.209984 +v 102.255882 -5.057061 -93.809990 +v 107.855888 -5.057060 -97.609985 +v -179.544113 4.542978 -48.109989 +v -178.194122 6.492978 -42.509991 +v -180.744125 13.642980 -53.559978 +v -180.844116 15.242981 -56.959980 +v -183.594116 14.142980 -58.959980 +v -183.694122 15.242980 -59.159977 +v -183.644119 14.142982 -57.259979 +v -183.794113 13.642982 -62.559978 +v -214.244125 22.642988 -66.310005 +v -218.994125 10.292987 -68.709991 +v -193.544113 27.492985 -68.059975 +v 58.005886 -5.057065 40.840019 +v 58.005886 -5.057065 47.240021 +v 58.005886 -5.057065 34.490021 +v 51.605885 -5.057065 40.840019 +v 58.005886 4.642936 45.340012 +v 51.605885 4.642937 45.340012 +v 58.005886 6.242935 40.840012 +v 58.005886 1.342933 46.540016 +v 58.005886 4.642936 36.390011 +v 58.005886 1.342934 35.190014 +v 64.405884 4.642935 36.390011 +v 64.405884 6.242933 40.840012 +v 64.405884 1.342933 35.190014 +v 64.405884 4.642935 45.340012 +v 64.405884 1.342932 46.540016 +v 107.905884 12.942936 -78.409996 +v 107.905884 12.942936 -84.809998 +v 107.955887 14.142936 -72.009995 +v 107.605888 7.742940 -98.409996 +v 107.705887 1.342940 -97.609985 +v 107.955887 17.342939 -91.209991 +v 107.955887 17.342936 -71.109993 +v 107.955887 15.642938 -78.409996 +v 107.905884 15.642937 -84.809998 +v 178.205887 -14.657093 132.790039 +v 178.205887 -14.657087 94.390022 +v 178.205887 -14.657087 87.990021 +v -136.094116 -4.157035 22.790016 +v -138.094116 -0.257035 16.340015 +v -139.094116 -0.457035 22.240015 +v -142.594116 3.442969 14.190017 +v -117.544121 -3.007038 15.440013 +v -128.194122 9.142965 10.590018 +v -122.694115 5.692964 11.490016 +v -120.944115 12.192965 9.740016 +v -141.294113 -10.257030 -6.509988 +v -145.244125 -10.357031 -6.859988 +v -147.094116 -10.357031 -0.459988 +v -139.844116 -10.257031 -0.259988 +v -142.694122 -10.357030 -12.709988 +v -132.344116 -10.257033 -1.559988 +v -133.994125 -10.257032 -7.709988 +v -124.394119 -10.257032 -4.459988 +v -135.594116 -10.257032 -13.909987 +v 77.555885 1.192927 77.190018 +v 83.955887 1.192927 77.740013 +v 73.255882 -5.057072 77.640015 +v 105.755890 26.192932 -11.609984 +v 105.755890 26.192930 -16.609985 +v -17.194117 -4.207040 -95.409988 +v -15.594117 -4.207043 -92.659988 +v -11.944118 -4.207043 -91.559990 +v -32.994118 -4.607039 -97.609985 +v 24.555885 6.392955 -114.459984 +v 11.805883 -4.307045 -97.609985 +v 31.005884 -4.457048 -97.609985 +v 31.005884 -4.407048 -104.009987 +v -12.394116 2.192958 -91.159988 +v -19.294117 3.792959 -98.309990 +v -19.294117 -4.207042 -92.209984 +v -13.794117 -4.557040 -123.209984 +v 31.255884 -4.457049 -91.209984 +v -7.394117 -4.307041 -123.209984 +v -8.194118 -5.057040 -127.809990 +v 11.805883 -3.357046 -91.209984 +v -7.394117 -4.257043 -91.209984 +v 45.205883 -5.057061 18.240017 +v 45.205883 -5.057061 20.340017 +v 46.805885 -5.057061 20.340017 +v 43.805885 -5.407061 11.190014 +v 42.505886 -5.057061 18.240017 +v 32.405884 -5.057059 18.240017 +v 32.405884 -5.057058 20.340017 +v 35.105885 -5.057060 18.240017 +v -173.144119 -0.607020 -73.809990 +v -169.394119 -0.207019 -78.709984 +v -175.294113 -1.657021 -68.259987 +v -176.044113 -2.457020 -60.759987 +v -204.344116 24.042990 -76.359970 +v -204.794113 21.092983 -85.810005 +v -201.744125 22.842983 -83.910004 +v -200.894119 10.192986 -85.459991 +v -199.194122 35.542984 -71.259979 +v -201.594116 35.592983 -75.809982 +v -200.144119 35.542980 -80.509979 +v -195.444122 35.392979 -79.109978 +v -194.394119 24.042984 -81.659973 +v -189.294113 12.592985 -85.209991 +v -190.944122 26.592979 -74.109970 +v -184.194122 3.942981 -64.509987 +v -183.944122 10.342981 -63.759995 +v 127.005882 -14.657091 215.990005 +v 127.005882 -14.657091 209.590012 +v -176.344116 10.942976 -23.809984 +v -181.394119 16.892979 -21.609987 +v -173.894119 3.942979 -54.309990 +v -176.244125 -1.707021 -48.209988 +v -176.194122 -2.457021 -54.959988 +v -173.994125 -0.557022 -42.509987 +v -171.294113 5.742975 -24.559990 +v -166.894119 -0.557025 -24.759985 +v -164.894119 0.142974 -19.059986 +v -173.694122 3.942979 -61.309990 +v -169.094116 4.542978 -54.459991 +v -173.894119 -0.257021 -54.459988 +v -173.694122 -0.257021 -61.159985 +v -78.844116 1.442964 -55.709988 +v -89.994118 -0.657035 -63.409985 +v -89.994118 0.942967 -60.009987 +v -80.794121 2.742966 -59.859985 +v -89.994118 -1.257034 -61.859985 +v -89.994118 -0.157033 -59.809986 +v -89.994118 -0.157036 -58.059986 +v -89.994118 -1.257035 -56.009987 +v -89.994118 -3.957034 -55.009983 +v 11.155883 -4.557044 -123.209984 +v 11.805883 -4.257045 -116.809990 +v 21.405886 6.892957 -118.959991 +v 21.405884 4.542955 -129.609985 +v 15.005885 4.542958 -142.409988 +v 8.605885 4.542959 -142.409988 +v 15.005885 4.542956 -136.009995 +v 21.405884 4.542955 -136.009995 +v -4.244116 4.542962 -142.009995 +v -5.444116 3.442961 -140.859985 +v -5.844115 9.492960 -141.759995 +v -141.194122 -13.557027 -57.659992 +v -140.394119 -17.507025 -53.159988 +v -138.844116 -21.657030 -52.309990 +v -141.444122 -14.707027 -53.709995 +v 35.755890 12.992941 24.340015 +v 29.005886 14.992941 30.190016 +v 35.505890 14.542940 30.190016 +v 29.655886 14.142942 20.340015 +v 33.155884 1.342942 20.340015 +v 34.355885 4.642941 20.340014 +v 37.755886 6.242939 20.340019 +v 18.505884 2.442950 -69.659988 +v 18.205885 -1.157048 -65.609985 +v 11.805884 -1.757048 -66.509987 +v -1.694117 -4.657047 -53.959984 +v -11.594116 2.192955 -88.059990 +v -18.344116 -4.207041 -90.009987 +v 11.805884 -2.557050 -59.209988 +v 127.005882 -14.657085 126.390022 +v -1.694115 8.542947 31.740017 +v -1.694115 10.892945 34.390007 +v -19.344116 0.692950 7.090014 +v -21.494116 0.692949 10.490015 +v -20.144117 -5.857051 5.640014 +v -1.494116 1.642948 -20.809986 +v -17.694115 14.342946 38.790024 +v -12.094114 13.192945 34.140022 +v -3.544114 12.942945 36.540024 +v 0.155884 -0.107054 11.090014 +v 0.855884 -1.357055 10.490016 +v 0.905884 -0.107056 15.640015 +v -141.794113 -21.407028 -46.409988 +v -135.394119 -21.457024 -52.809990 +v -135.344116 -20.507029 -46.409988 +v -141.744125 -19.907032 -40.009991 +v -135.344116 -19.657032 -40.009991 +v -137.444122 -19.007029 -34.659988 +v -147.444122 -15.057024 -49.959995 +v -148.894119 -16.157024 -30.659985 +v -147.394119 -16.157030 -24.859983 +v -137.344116 -16.157032 -27.459984 +v -137.944122 -12.207028 -27.609985 +v -141.594116 -16.157030 -23.259983 +v -145.144119 -19.707027 -36.759991 +v -150.794113 -20.057024 -31.159990 +v -135.444122 -18.407032 -26.959991 +v 76.005882 -4.357066 17.490017 +v 83.705887 -5.057068 16.690018 +v 81.405884 -4.057067 11.040013 +v 74.755882 -5.057067 23.640017 +v 88.155884 -5.057067 12.040014 +v 55.555885 2.592941 3.390013 +v 60.405884 3.392937 5.540013 +v 59.455883 3.392938 8.590017 +v 83.605888 3.392936 2.790015 +v 81.355888 3.392936 0.540017 +v 55.455883 3.392939 -14.159983 +v 56.755886 2.592939 -9.359987 +v -13.894114 15.942943 61.990025 +v -14.844113 17.192944 56.190018 +v -20.244114 15.092945 63.590023 +v -26.594114 14.242947 65.240005 +v -25.344118 -14.657059 90.890022 +v -20.194118 -14.657058 87.990021 +v -21.294119 -14.657057 82.740021 +v -27.544119 -14.657058 86.140022 +v 11.805882 -14.657063 87.990021 +v 16.405882 -14.657063 87.840027 +v 90.605888 -5.057056 -120.759987 +v 102.605888 1.342942 -110.109985 +v 96.855888 1.342944 -115.309990 +v 97.755882 8.042944 -116.409996 +v 99.305885 14.292943 -116.709991 +v 107.805885 -5.857060 -97.609985 +v 100.555885 16.942944 -99.859993 +v 88.255882 -5.857057 -90.859985 +v -73.144119 16.692963 -59.259979 +v -74.344116 13.792964 -39.059978 +v -119.694115 -14.357030 -59.209995 +v -121.144119 -17.457029 -46.759991 +v -115.444115 -16.657032 -46.759995 +v -93.444115 -10.357033 -52.559978 +v -93.444115 -10.357036 -55.259979 +v -93.444115 -10.357032 -62.609978 +v -93.444115 -10.357034 -65.309982 +v -91.294121 -10.357034 -65.309982 +v -91.294121 -10.357035 -52.559978 +v -91.294121 -3.957034 -53.259983 +v -91.294121 -3.957035 -64.609985 +v 20.905886 14.992943 30.140015 +v 43.605888 16.542938 36.690022 +v 42.755890 14.242939 30.240015 +v 36.955887 21.592939 50.690018 +v 4.055886 12.742945 36.240025 +v 10.255886 13.192944 35.390022 +v 10.655886 10.792943 30.690018 +v 14.905886 14.392941 32.540024 +v 83.005882 -11.407074 86.940025 +v 86.855888 -11.457073 88.690025 +v 89.655884 -11.607074 82.090027 +v 83.605888 -11.457074 81.090027 +v 80.905884 -11.457074 81.090027 +v 82.855888 -5.057072 79.240013 +v 109.155884 -14.657077 86.740021 +v -135.394119 -21.207027 -60.609989 +v -141.794113 -21.707022 -65.609970 +v -146.994125 -21.657022 -66.759972 +v -135.394119 -20.557024 -65.609970 +v -149.294113 -20.207027 -35.859989 +v -148.594116 -18.657028 -23.709990 +v -155.194122 -18.257027 -20.609991 +v -152.294113 3.942976 -53.709991 +v -147.394119 3.942973 -51.359989 +v -147.444122 10.342977 -50.059994 +v -153.444122 10.342976 -53.709995 +v -152.344116 -2.457024 -54.309986 +v -152.594116 -8.857026 -54.209984 +v -153.544113 -15.057025 -53.659992 +v -149.494125 -3.757026 -42.909981 +v -151.644119 -0.907027 -37.509987 +v -155.844116 -0.907025 -35.609985 +v -156.044113 -3.757025 -33.759983 +v -155.944122 -7.507025 -34.859982 +v -155.994125 -15.657026 -34.209995 +v -154.694122 -0.257024 -53.909985 +v -147.344116 15.092974 -53.409977 +v -125.094116 7.692963 29.040018 +v -126.894119 11.692963 27.590017 +v -125.244118 8.192963 33.990013 +v -131.344116 6.192964 29.090019 +v -142.844116 6.742966 29.090019 +v -146.594116 9.092966 34.090012 +v -150.744125 3.842968 39.990013 +v -126.894119 11.692962 52.390007 +v -130.844116 9.592966 30.340017 +v -131.344116 6.192964 50.890011 +v -142.844116 6.742966 50.890011 +v -145.794113 1.342966 51.040016 +v -149.094116 3.742968 45.890011 +v -124.244118 7.292964 38.790012 +v -59.944118 -5.057044 9.790014 +v -23.144117 -5.857051 10.440014 +v -64.944115 -5.057044 13.540014 +v -71.044121 1.342957 15.040014 +v -65.894119 11.992956 -2.559984 +v -61.394115 12.192957 -6.309984 +v -58.294113 12.842957 -11.409986 +v -41.594116 -5.057049 30.040016 +v -35.394115 10.692950 29.640017 +v 88.105888 -14.657073 89.740021 +v -143.094116 3.192966 21.790012 +v 43.805893 44.542950 -147.610016 +v 47.555889 36.592949 -147.610001 +v 45.655888 36.592949 -150.860001 +v 41.955887 36.592949 -150.860001 +v 110.105888 19.542936 -19.059982 +v 34.205883 4.542955 -142.409988 +v 34.205883 4.542956 -146.209991 +v 27.805883 4.542957 -145.009995 +v 27.805883 4.542956 -142.409988 +v -77.994118 13.992962 -30.159986 +v -128.994125 -17.957033 -27.209991 +v -128.994125 -16.657030 -20.809984 +v -129.544113 -16.657028 -18.509983 +v -109.144119 16.492968 5.090017 +v -87.694115 14.692961 -13.509984 +v -82.294121 14.292963 -21.509985 +v -58.594116 -5.057049 62.390018 +v 109.855888 18.092932 2.740017 +v 103.805885 18.092930 -3.909984 +v 113.305885 22.592934 5.840018 +v 116.805885 22.542929 -3.059983 +v 118.455887 22.992933 -10.109983 +v 116.905884 21.292934 -32.609982 +v 112.105888 18.142935 -35.009983 +v 106.205887 1.342941 -104.159988 +v -159.994125 3.542976 -49.409988 +v -159.194122 2.442977 -54.209988 +v -164.594116 3.042978 -54.459988 +v -164.194122 3.742976 -49.659988 +v -169.094116 2.442978 -54.559986 +v -92.794121 -1.257034 -56.009987 +v -92.944115 -0.657033 -54.459988 +v -92.744118 0.942965 -57.859985 +v -92.644119 -0.157035 -58.059986 +v -92.894119 -3.957034 -55.009983 +v -93.094116 -3.957034 -53.259983 +v 66.405884 13.242934 28.390015 +v 69.705887 17.042933 32.290020 +v 78.555885 18.242937 29.240021 +v 79.455887 -5.057065 21.440018 +v 83.705887 1.342932 16.690016 +v 39.855885 6.242940 18.890018 +v 44.455883 1.342940 20.340015 +v -147.194122 -20.907024 -71.309975 +v -154.194122 -8.357023 -70.809982 +v -154.294113 -5.157022 -70.009987 +v -147.844116 -5.157022 -78.509987 +v -22.494116 3.792959 -98.509987 +v -159.094116 8.192980 -99.359993 +v -168.544113 7.492983 -95.909996 +v -175.744125 12.392982 -108.209991 +v -165.394119 11.092984 -102.459991 +v -178.494125 12.892982 -101.859993 +v -173.944122 10.692983 -98.409996 +v -153.144119 -10.707024 -96.509979 +v -159.544113 -12.357019 -92.359978 +v -167.094116 0.692980 -85.859985 +v -173.994125 -8.457020 -62.309982 +v -185.444122 13.542985 -91.059998 +v 77.305885 -10.857073 86.940025 +v 77.205887 -11.457072 81.090027 +v 73.255882 -5.057071 80.590019 +v -109.794121 -8.057037 23.990011 +v -103.544121 -6.557040 16.190012 +v -110.494118 -8.107038 15.590015 +v -64.994118 -5.057048 62.390018 +v -68.294121 -7.407034 -78.659981 +v -69.194115 -1.007035 -78.609985 +v -58.544117 -5.057036 -85.009987 +v -70.394119 2.242966 -78.109985 +v -75.194115 -7.757033 -83.459976 +v -37.744118 -5.057051 35.140018 +v -92.794121 -1.257034 -61.859985 +v -92.644119 -0.157032 -59.809986 +v -92.744118 0.942968 -60.009987 +v -92.944115 -0.657034 -63.409985 +v -93.094116 -3.957035 -64.609985 +v -92.894119 -3.957034 -62.859982 +v 39.655884 5.142939 19.040010 +v 50.255890 14.142938 24.340015 +v 41.855888 12.992940 24.340015 +v 47.955883 1.342940 20.340015 +v 34.205887 24.692957 -149.360001 +v 8.605887 24.692955 -146.210007 +v 8.605887 24.692961 -149.360001 +v 19.305883 -5.057057 20.340017 +v 16.405884 -5.057058 23.940018 +v 22.205885 -5.057059 25.290016 +v 10.855885 7.192942 28.690020 +v 11.255884 1.342945 26.640015 +v 17.655886 11.242942 28.340017 +v 16.405884 1.342942 23.940016 +v -0.994117 -4.007047 -46.959984 +v 33.705883 4.492953 -129.559982 +v 37.405884 -3.957049 -110.409988 +v 33.055885 -5.057045 -131.409988 +v 27.805883 4.542954 -136.009995 +v 33.355885 4.542953 -136.009995 +v 21.405884 4.542957 -142.409988 +v 21.405884 4.542958 -145.009995 +v 105.355888 13.292933 3.990015 +v 102.155884 11.842933 0.440016 +v 103.605888 11.842934 -4.109984 +v -159.044113 -5.307029 -6.959986 +v -161.594116 12.492970 9.390016 +v -165.344116 4.742974 -4.909984 +v -159.644119 5.492971 -0.859984 +v -159.044113 1.092972 -6.959986 +v 53.905884 2.592939 6.090014 +v -153.344116 -15.057027 -60.809994 +v -154.494125 -0.257024 -60.659985 +v 111.155884 17.342937 -109.459991 +v 107.955887 17.342937 -108.559998 +v 111.155884 20.042936 -71.809998 +v 104.405884 17.042944 -113.159996 +v 100.805885 16.742943 -117.759995 +v 59.055885 6.742937 25.040018 +v 58.005886 1.342936 23.940016 +v 65.155884 7.242935 25.790018 +v 18.055885 6.692943 26.140018 +v -26.594118 -14.657062 132.790039 +v -26.594118 -14.657062 126.390022 +v -26.594118 -14.657057 107.190025 +v -115.194115 15.692966 8.440018 +v -107.144119 18.092960 8.390016 +v -115.094116 8.242965 12.090014 +v -107.994118 9.992965 13.490017 +v -56.144112 14.892958 -17.209986 +v -113.694115 14.192965 11.140015 +v 108.005882 22.042938 -57.059982 +v -144.444122 -7.857026 -34.109982 +v 73.555885 -5.007055 -112.259987 +v 75.305885 -5.007055 -117.459984 +v 43.805885 -3.407050 -110.409988 +v 47.405888 23.692957 -147.610001 +v 42.155888 30.142956 -150.460007 +v 45.455887 30.142956 -150.460007 +v 47.105888 30.142958 -147.610001 +v -162.144119 0.342972 -13.259986 +vt 0.687520 0.750040 +vt 0.749980 0.750040 +vt 0.749980 0.874960 +vt 0.687520 0.874960 +vt 0.125020 0.625040 +vt 0.187480 0.625040 +vt 0.187480 0.749960 +vt 0.125020 0.749960 +vt 0.437520 0.750040 +vt 0.437520 0.874960 +vt 0.499980 0.874960 +vt 0.499980 0.750040 +vt 0.000020 0.375040 +vt 0.062480 0.375040 +vt 0.062480 0.499960 +vt 0.000020 0.499960 +vt 0.250020 0.875040 +vt 0.312480 0.875040 +vt 0.312480 0.999960 +vt 0.250020 0.999960 +vt 0.937520 0.625040 +vt 0.999980 0.625040 +vt 0.999980 0.749960 +vt 0.937520 0.749960 +vt 0.000020 0.624960 +vt 0.062480 0.624960 +vt 0.375020 0.500040 +vt 0.375020 0.624960 +vt 0.437480 0.624960 +vt 0.437480 0.500040 +vt 0.500020 0.500040 +vt 0.500020 0.624960 +vt 0.562480 0.624960 +vt 0.562480 0.500040 +vt 0.062520 0.750040 +vt 0.062520 0.874960 +vt 0.124980 0.874960 +vt 0.312520 0.500040 +vt 0.312520 0.624960 +vt 0.187520 0.875040 +vt 0.187520 0.999960 +vt 0.562520 0.750040 +vt 0.624980 0.750040 +vt 0.624980 0.874960 +vt 0.562520 0.874960 +vt 0.000020 0.875040 +vt 0.000020 0.999960 +vt 0.062480 0.999960 +vt 0.812520 0.500040 +vt 0.812520 0.624960 +vt 0.874980 0.624960 +vt 0.874980 0.500040 +vt 0.624980 0.624960 +vt 0.624980 0.500040 +vt 0.687480 0.624960 +vt 0.687480 0.500040 +vt 0.749980 0.624960 +vt 0.749980 0.500040 +vt 0.812520 0.875040 +vt 0.874980 0.875040 +vt 0.874980 0.999960 +vt 0.812520 0.999960 +vt 0.749980 0.999960 +vt 0.687520 0.999960 +vt 0.374980 0.749960 +vt 0.312520 0.749960 +vt 0.812480 0.749960 +vt 0.874980 0.749960 +vt 0.374980 0.875040 +vt 0.374980 0.999960 +vt 0.125020 0.500040 +vt 0.187480 0.500040 +vt 0.249980 0.750040 +vt 0.437480 0.999960 +vt 0.187520 0.375040 +vt 0.249980 0.375040 +vt 0.249980 0.499960 +vt 0.125020 0.375040 +vt 0.937520 0.875040 +vt 0.937520 0.999960 +vt 0.999980 0.999960 +vt 0.999980 0.875040 +vt 0.562480 0.999960 +vt 0.500020 0.999960 +vt 0.000020 0.749960 +vt 0.937480 0.500040 +vt 0.249980 0.625040 +vt 0.125020 0.999960 +vt 0.624980 0.999960 +vt 0.999980 0.500040 +vt 0.937520 0.000040 +vt 0.937520 0.124960 +vt 0.999980 0.124960 +vt 0.999980 0.000040 +usemtl Material.001 +s off +f 1/1 2/2 3/3 4/4 +f 5/1 1/2 4/3 6/4 +f 7/1 5/2 6/3 8/4 +f 9/1 7/2 8/3 10/4 +f 11/1 9/2 10/3 12/4 +f 13/1 11/2 12/3 14/4 +f 4/1 3/2 15/3 16/4 +f 12/1 10/2 17/3 18/4 +f 19/4 20/3 21/1 +f 20/3 19/1 22/4 +f 23/5 24/6 25/7 26/8 +f 27/5 23/6 26/7 28/8 +f 27/4 29/3 30/1 +f 30/4 29/3 21/1 +f 19/1 21/4 31/3 32/2 +f 23/1 27/4 30/3 33/2 +f 24/1 23/4 33/3 34/2 +f 20/4 34/3 33/1 +f 29/1 35/4 31/3 21/2 +f 30/9 36/10 37/11 33/12 +f 36/9 38/10 39/11 37/12 +f 38/9 40/10 41/11 39/12 +f 30/9 21/12 42/11 36/10 +f 36/9 42/12 43/11 38/10 +f 38/9 43/12 44/11 40/10 +f 20/9 33/12 37/11 45/10 +f 45/9 37/12 39/11 46/10 +f 46/9 39/12 41/11 47/10 +f 20/9 45/10 42/11 21/12 +f 45/9 46/10 43/11 42/12 +f 46/9 47/10 44/11 43/12 +f 48/13 49/14 50/15 51/16 +f 52/15 53/16 54/13 55/14 +f 54/13 53/15 56/16 +f 55/13 54/15 57/16 +f 58/17 59/18 60/19 61/20 +f 62/13 63/16 57/15 64/14 +f 65/13 66/16 63/15 62/14 +f 63/13 67/16 55/15 57/14 +f 66/13 68/16 67/15 63/14 +f 69/13 70/16 68/15 66/14 +f 52/15 55/14 67/13 71/16 +f 68/13 72/16 71/15 67/14 +f 70/13 73/16 72/15 68/14 +f 73/13 74/16 75/15 72/14 +f 76/21 77/22 74/23 73/24 +f 78/25 79/26 80/16 +f 80/16 81/25 82/26 83/15 +f 84/27 83/28 82/29 85/30 +f 85/27 86/28 87/29 84/30 +f 87/16 86/25 88/26 89/15 +f 84/27 87/28 90/29 91/30 +f 90/16 87/25 89/26 92/15 +f 93/31 94/32 95/33 96/34 +f 97/35 98/36 99/37 100/8 +f 101/35 97/36 100/37 102/8 +f 103/35 101/36 102/37 104/8 +f 97/27 101/30 105/29 106/28 +f 98/16 106/25 107/26 108/15 +f 98/28 97/30 106/29 +f 105/29 101/30 103/28 +f 109/16 88/25 86/26 110/15 +f 111/27 110/28 86/29 85/30 +f 95/16 94/15 82/26 81/25 +f 111/27 85/30 82/29 94/28 +f 98/27 112/28 89/29 99/30 +f 104/38 80/39 79/28 103/27 +f 89/16 112/26 92/25 +f 113/1 114/2 115/3 116/4 +f 117/40 115/41 114/20 118/17 +f 102/36 100/37 119/35 +f 102/36 119/37 120/35 +f 121/13 122/14 123/15 124/16 +f 125/13 121/14 124/15 126/16 +f 127/13 125/14 126/15 128/16 +f 129/13 127/14 128/15 130/16 +f 131/13 129/14 130/15 132/16 +f 126/13 124/14 133/15 134/16 +f 128/13 126/14 134/15 135/16 +f 136/5 137/6 138/7 139/8 +f 140/42 141/43 142/44 143/45 +f 144/13 131/16 145/15 146/14 +f 147/46 144/47 146/48 148/36 +f 149/49 147/50 148/51 150/52 +f 151/13 129/16 131/15 144/14 +f 152/21 151/24 144/23 147/22 +f 153/49 152/50 147/51 149/52 +f 154/34 153/33 149/53 155/54 +f 143/54 154/53 155/55 156/56 +f 157/13 127/16 129/15 151/14 +f 158/21 157/24 151/23 152/22 +f 159/49 158/50 152/51 153/52 +f 160/34 159/33 153/53 154/54 +f 142/54 160/53 154/55 143/56 +f 161/13 125/16 127/15 157/14 +f 162/46 161/47 157/48 158/36 +f 163/49 162/50 158/51 159/52 +f 164/56 163/55 159/57 160/58 +f 165/58 164/57 160/50 142/49 +f 166/13 121/16 125/15 161/14 +f 167/21 166/24 161/23 162/22 +f 168/49 167/50 162/51 163/52 +f 169/34 168/33 163/53 164/54 +f 170/54 169/53 164/55 165/56 +f 171/13 122/16 121/15 166/14 +f 172/46 171/47 166/48 167/36 +f 173/49 172/50 167/51 168/52 +f 139/56 173/55 168/57 169/58 +f 136/58 139/57 169/50 170/49 +f 174/49 175/50 172/51 173/52 +f 176/42 177/45 178/44 179/43 +f 179/43 178/44 180/4 181/1 +f 181/42 180/45 182/44 183/43 +f 183/43 182/44 184/4 185/1 +f 185/42 184/45 186/44 187/43 +f 177/4 176/1 187/43 186/44 +f 188/1 179/2 181/3 189/4 +f 181/1 183/2 190/3 191/4 +f 192/1 185/3 187/4 +f 187/3 176/4 193/1 +f 194/49 195/51 196/50 +f 180/49 194/52 196/51 182/50 +f 196/49 195/51 197/50 +f 182/49 196/52 197/51 184/50 +f 197/49 195/51 198/50 +f 184/49 197/52 198/51 186/50 +f 198/49 195/51 199/50 +f 186/49 198/52 199/51 177/50 +f 199/49 195/51 200/50 +f 177/49 199/52 200/51 178/50 +f 200/49 195/51 194/50 +f 178/49 200/52 194/51 180/50 +f 201/1 202/2 203/3 204/4 +f 205/1 206/2 207/3 208/4 +f 209/1 205/2 208/3 210/4 +f 211/1 209/2 210/3 212/4 +f 213/1 211/2 212/3 214/4 +f 204/1 203/2 215/3 216/4 +f 217/1 204/2 216/3 218/4 +f 207/1 217/2 218/3 219/4 +f 208/1 207/2 219/3 185/4 +f 210/1 208/2 185/3 192/4 +f 212/1 210/2 192/3 220/4 +f 214/1 212/2 220/3 221/4 +f 218/1 216/2 222/3 223/4 +f 219/1 218/2 223/3 190/4 +f 185/1 219/2 190/3 183/4 +f 220/1 192/2 187/3 193/4 +f 221/1 220/2 193/3 224/4 +f 223/1 222/2 225/3 226/4 +f 190/1 223/2 226/3 191/4 +f 176/3 227/4 224/1 193/2 +f 228/1 224/2 227/3 229/4 +f 226/1 225/2 230/3 231/4 +f 191/1 226/2 231/3 232/4 +f 181/1 191/2 232/3 189/4 +f 176/1 179/2 188/3 233/4 +f 227/1 176/2 233/3 234/4 +f 229/1 227/2 234/3 235/4 +f 231/1 230/2 236/3 237/4 +f 232/1 231/2 237/3 238/4 +f 189/1 232/2 238/3 239/4 +f 188/1 189/2 239/3 240/4 +f 233/1 188/2 240/3 241/4 +f 234/1 233/2 241/3 242/4 +f 237/1 236/2 243/3 244/4 +f 238/1 237/2 244/3 245/4 +f 239/1 238/2 245/3 246/4 +f 240/1 239/2 246/3 247/4 +f 241/1 240/2 247/3 248/4 +f 242/1 241/2 248/3 249/4 +f 250/49 251/51 252/50 +f 253/49 254/51 255/50 +f 256/1 257/2 258/3 259/4 +f 260/1 256/2 259/3 261/4 +f 262/1 260/2 261/3 263/4 +f 264/1 262/2 263/3 265/4 +f 266/1 264/2 265/3 267/4 +f 268/1 266/2 267/3 269/4 +f 270/1 268/2 269/3 271/4 +f 272/59 273/60 274/61 275/62 +f 275/4 274/3 276/63 277/64 +f 277/39 276/28 278/65 279/66 +f 280/39 279/66 278/65 281/28 +f 273/57 272/50 282/67 283/2 +f 283/57 282/50 284/67 285/2 +f 285/59 284/60 286/61 287/62 +f 287/4 286/3 280/63 281/64 +f 273/59 288/60 289/61 274/62 +f 274/4 289/3 290/63 276/64 +f 276/39 290/28 291/65 278/66 +f 292/4 287/3 281/63 293/64 +f 281/39 278/66 291/65 293/28 +f 288/57 273/50 283/67 294/2 +f 294/57 283/50 285/67 295/2 +f 295/59 285/60 287/61 292/62 +f 289/4 296/3 297/63 290/64 +f 290/39 297/28 298/65 291/66 +f 293/39 291/66 298/65 299/28 +f 300/4 292/3 293/63 299/64 +f 301/50 302/51 303/68 304/67 +f 305/53 306/55 307/1 308/43 +f 306/33 305/53 309/43 310/42 +f 311/33 312/53 313/43 314/42 +f 315/33 306/53 310/43 316/42 +f 312/33 311/53 317/43 318/42 +f 303/33 308/42 307/43 304/53 +f 306/53 315/55 319/1 307/43 +f 315/53 320/55 321/1 319/43 +f 304/33 307/42 319/43 301/53 +f 301/33 319/42 321/43 302/53 +f 305/33 311/53 314/43 309/42 +f 322/13 323/14 324/15 325/16 +f 325/13 324/14 326/15 327/16 +f 327/13 326/14 328/15 329/16 +f 330/18 331/69 332/70 333/19 +f 334/13 335/16 327/15 329/14 +f 336/13 337/16 335/15 334/14 +f 335/13 338/16 325/15 327/14 +f 337/13 339/16 338/15 335/14 +f 340/13 341/16 339/15 337/14 +f 342/21 343/22 341/23 340/24 +f 338/13 344/16 322/15 325/14 +f 339/13 345/16 344/15 338/14 +f 341/13 346/16 345/15 339/14 +f 343/46 347/36 346/48 341/47 +f 344/13 348/16 349/15 322/14 +f 345/13 350/16 348/15 344/14 +f 346/13 351/16 350/15 345/14 +f 352/71 353/72 354/6 355/5 +f 356/6 353/72 352/71 357/5 +f 358/69 359/10 360/65 +f 361/69 358/10 360/65 +f 362/69 361/10 360/65 +f 363/35 364/8 365/37 366/36 +f 367/35 363/8 366/37 368/36 +f 369/28 370/65 371/9 372/29 +f 373/28 374/65 370/9 369/29 +f 371/35 370/36 366/37 365/8 +f 370/35 374/36 368/37 366/8 +f 375/13 376/14 377/15 378/16 +f 378/13 377/14 379/15 380/16 +f 380/13 379/14 381/15 382/16 +f 382/13 381/14 383/15 384/16 +f 385/13 386/14 387/15 388/16 +f 389/13 385/14 388/15 390/16 +f 388/13 387/14 391/15 392/16 +f 390/13 388/14 392/15 393/16 +f 384/13 383/14 394/15 395/16 +f 395/13 394/14 386/15 385/16 +f 396/40 397/17 398/7 +f 399/40 396/17 398/7 +f 400/40 399/17 398/7 +f 401/40 400/17 398/7 +f 402/40 401/17 398/7 +f 403/40 402/17 398/7 +f 404/40 403/17 398/7 +f 397/40 404/17 398/7 +f 405/7 396/40 399/17 406/73 +f 406/7 399/40 400/17 407/73 +f 408/17 409/7 410/73 +f 408/17 411/7 412/73 +f 413/29 414/32 415/12 416/9 +f 416/29 415/32 417/12 418/9 +f 419/55 413/1 416/2 420/57 +f 421/13 422/16 423/15 424/14 +f 425/13 426/14 427/15 428/16 +f 428/13 427/14 429/15 430/16 +f 430/13 429/14 431/15 432/16 +f 422/13 428/14 430/15 423/16 +f 433/13 423/14 430/15 432/16 +f 434/21 424/22 423/23 433/24 +f 435/34 436/54 424/53 434/33 +f 437/54 438/56 436/55 435/53 +f 439/29 440/32 441/12 442/9 +f 443/23 421/24 444/21 445/22 +f 442/2 441/67 445/59 444/3 +f 438/2 442/67 444/59 436/3 +f 421/48 424/47 436/46 444/36 +f 446/13 447/14 448/15 449/16 +f 449/13 448/14 450/15 451/16 +f 452/29 441/32 440/12 453/9 +f 454/29 455/9 456/12 457/32 +f 452/29 453/9 455/12 454/32 +f 454/2 457/67 458/59 459/3 +f 460/21 459/22 461/23 462/24 +f 452/2 454/67 459/59 460/3 +f 445/46 460/36 462/48 443/47 +f 441/2 452/67 460/59 445/3 +f 463/13 464/14 450/15 448/16 +f 465/13 463/14 448/15 447/16 +f 465/13 447/14 443/15 462/16 +f 466/46 467/36 468/48 469/47 +f 470/56 466/57 469/55 +f 471/58 472/50 473/57 +f 467/57 466/55 472/56 471/58 +f 474/69 473/10 472/74 475/70 +f 472/19 466/20 476/17 475/18 +f 466/19 470/20 477/17 476/18 +f 478/40 479/17 470/20 480/41 +f 481/18 476/19 477/70 478/69 +f 476/18 481/19 482/70 475/69 +f 483/1 484/2 485/3 486/4 +f 487/1 483/2 486/3 488/4 +f 489/1 487/2 488/3 490/4 +f 491/1 489/2 490/3 492/4 +f 493/1 491/2 492/3 494/4 +f 495/1 493/2 494/3 496/4 +f 486/1 485/2 497/3 498/4 +f 488/1 486/2 498/3 499/4 +f 490/1 488/2 499/3 500/4 +f 492/1 490/2 500/3 501/4 +f 494/1 492/2 501/3 502/4 +f 496/1 494/2 502/3 503/4 +f 498/1 497/2 504/3 505/4 +f 499/1 498/2 505/3 506/4 +f 500/1 499/2 506/3 507/4 +f 501/1 500/2 507/3 508/4 +f 502/1 501/2 508/3 509/4 +f 503/1 502/2 509/3 510/4 +f 505/1 504/2 511/3 512/4 +f 506/1 505/2 512/3 513/4 +f 507/1 506/2 513/3 514/4 +f 508/1 507/2 514/3 515/4 +f 509/1 508/2 515/3 516/4 +f 510/1 509/2 516/3 517/4 +f 512/1 511/2 518/3 519/4 +f 513/1 512/2 519/3 520/4 +f 514/1 513/2 520/3 521/4 +f 515/1 514/2 521/3 522/4 +f 516/1 515/2 522/3 523/4 +f 519/1 518/2 524/3 525/4 +f 520/1 519/2 525/3 526/4 +f 521/1 520/2 526/3 527/4 +f 522/1 521/2 527/3 528/4 +f 523/1 522/2 528/3 529/4 +f 528/1 527/2 530/3 531/4 +f 529/1 528/2 531/3 532/4 +f 533/29 534/12 535/9 +f 536/29 533/32 535/12 537/9 +f 538/29 539/32 540/12 541/9 +f 542/29 538/32 541/12 543/9 +f 542/29 543/12 544/9 +f 545/29 546/12 547/9 +f 548/29 545/32 547/12 549/9 +f 548/29 550/12 551/9 +f 552/29 551/12 553/9 +f 554/29 544/12 555/9 +f 554/29 555/12 556/9 +f 533/75 541/76 540/77 534/72 +f 541/72 533/71 536/78 543/75 +f 546/78 544/75 543/72 536/71 +f 545/78 555/75 544/72 546/71 +f 555/75 545/76 548/77 556/72 +f 557/29 558/12 559/9 +f 537/29 560/9 546/12 536/32 +f 539/29 538/9 561/12 562/32 +f 563/29 564/9 537/12 535/32 +f 565/9 550/12 566/29 +f 567/29 568/9 569/12 570/32 +f 566/29 550/12 548/9 +f 558/29 557/9 564/12 563/32 +f 550/29 565/9 553/12 551/32 +f 538/29 542/9 571/12 561/32 +f 564/29 572/9 560/12 537/32 +f 571/29 554/9 573/12 574/32 +f 557/29 575/9 572/12 564/32 +f 554/29 556/9 567/12 573/32 +f 560/29 576/9 547/12 546/32 +f 572/29 577/9 576/12 560/32 +f 576/29 578/9 549/12 547/32 +f 577/29 579/9 578/12 576/32 +f 549/55 580/1 566/2 548/57 +f 580/9 549/12 578/29 +f 579/55 581/1 580/2 578/57 +f 582/29 583/9 581/12 579/32 +f 542/29 544/9 554/12 571/32 +f 573/29 567/9 570/12 584/32 +f 585/29 563/9 535/12 534/32 +f 583/2 586/3 587/59 581/67 +f 587/3 586/63 588/62 589/59 +f 590/5 589/8 588/7 591/6 +f 580/2 581/67 587/59 592/3 +f 592/3 587/63 589/62 593/59 +f 594/5 593/8 589/7 590/6 +f 565/2 595/3 596/59 553/67 +f 597/29 598/32 599/12 600/9 +f 601/29 602/32 603/12 604/9 +f 605/32 606/9 607/29 +f 608/29 609/32 610/12 611/9 +f 612/29 603/32 613/12 614/9 +f 615/29 612/32 614/12 616/9 +f 614/55 613/57 617/2 618/1 +f 616/29 614/32 618/12 600/9 +f 619/57 620/50 621/67 622/2 +f 621/57 623/50 624/67 625/2 +f 623/57 626/50 627/67 624/2 +f 625/57 624/50 628/67 629/2 +f 624/57 627/50 630/67 628/2 +f 631/4 632/3 633/63 634/64 +f 635/35 631/37 634/36 +f 636/4 637/3 638/63 639/64 +f 640/59 641/60 637/61 636/62 +f 639/39 638/65 642/66 +f 643/35 636/37 639/36 +f 644/35 645/37 646/36 +f 647/35 648/37 649/36 +f 632/4 650/3 649/63 633/64 +f 649/36 650/37 647/35 +f 639/36 651/37 643/35 +f 648/8 652/35 649/37 +f 653/8 646/35 654/37 +f 655/35 653/8 654/37 656/36 +f 637/4 657/3 634/63 638/64 +f 641/59 658/60 657/61 637/62 +f 642/66 638/65 634/39 +f 634/36 657/37 635/35 +f 659/79 635/80 657/81 658/82 +f 653/8 644/35 646/37 +f 660/55 661/57 662/2 663/1 +f 664/29 665/12 666/9 +f 667/29 668/9 669/12 670/32 +f 661/29 671/9 668/12 667/32 +f 660/55 672/1 671/2 661/57 +f 672/12 660/32 673/29 674/9 +f 675/11 676/45 677/83 678/84 +f 679/11 680/84 677/83 676/45 +f 681/29 682/12 683/9 +f 681/29 683/12 684/9 +f 683/66 682/65 680/69 679/18 +f 684/66 683/65 679/69 676/18 +f 685/29 686/9 681/12 684/32 +f 687/29 669/9 686/12 685/32 +f 681/29 688/9 689/12 682/32 +f 686/29 690/9 688/12 681/32 +f 669/29 668/9 690/12 686/32 +f 688/29 691/9 692/12 689/32 +f 690/29 693/9 691/12 688/32 +f 668/29 671/9 693/12 690/32 +f 691/29 694/9 695/12 692/32 +f 693/29 696/9 694/12 691/32 +f 671/29 672/9 696/12 693/32 +f 672/29 674/9 697/12 696/32 +f 698/25 699/85 700/35 701/26 +f 665/25 702/85 703/35 666/26 +f 702/24 704/23 705/82 703/79 +f 662/25 706/85 707/35 663/26 +f 708/79 709/82 710/81 711/80 +f 712/59 713/60 714/61 715/62 +f 713/59 716/60 717/61 714/62 +f 715/4 714/3 718/63 719/64 +f 714/4 717/3 720/63 718/64 +f 717/35 721/8 722/37 720/36 +f 723/57 713/50 712/67 724/2 +f 708/57 723/50 724/67 709/2 +f 725/57 716/50 713/67 723/2 +f 726/35 727/8 728/37 729/36 +f 710/4 726/3 729/63 730/64 +f 711/35 710/8 730/37 731/36 +f 732/1 733/2 734/3 735/4 +f 736/1 732/2 735/3 737/4 +f 734/1 738/2 739/3 740/4 +f 735/1 734/2 740/3 741/4 +f 737/1 735/2 741/3 742/4 +f 743/1 737/2 742/3 744/4 +f 745/1 743/2 744/3 746/4 +f 747/71 748/6 749/5 +f 747/71 750/6 748/5 +f 751/5 752/6 747/71 +f 747/71 749/6 752/5 +f 753/5 751/6 747/71 +f 754/52 755/86 756/21 757/51 +f 755/52 758/86 759/21 756/51 +f 758/52 760/86 761/21 759/51 +f 762/26 747/5 763/8 764/35 +f 765/26 762/5 764/8 766/35 +f 767/53 768/43 769/1 770/55 +f 771/53 772/43 768/1 767/55 +f 763/53 747/43 772/1 771/55 +f 773/33 774/53 768/43 772/42 +f 775/15 776/26 777/5 778/71 +f 778/15 777/26 779/5 780/71 +f 780/15 779/26 781/5 782/71 +f 782/15 781/26 783/5 784/71 +f 750/52 784/51 785/21 748/86 +f 748/52 785/51 775/21 749/86 +f 749/52 775/51 778/21 752/86 +f 752/52 778/51 780/21 751/86 +f 751/52 780/51 782/21 753/86 +f 753/52 782/51 784/21 750/86 +f 786/29 787/32 788/12 789/9 +f 787/12 786/9 790/29 +f 791/29 792/32 793/12 794/9 +f 790/29 795/32 796/12 787/9 +f 789/29 797/12 798/9 +f 787/29 796/32 799/12 788/9 +f 798/12 786/9 789/29 +f 788/29 799/32 792/12 791/9 +f 789/29 788/32 791/12 800/9 +f 801/29 802/9 803/12 804/32 +f 805/29 806/9 802/12 801/32 +f 807/29 808/9 806/12 805/32 +f 809/6 803/7 802/73 810/87 +f 810/6 802/7 806/73 811/87 +f 811/6 806/7 808/73 812/87 +f 813/46 814/36 815/48 816/47 +f 801/2 804/67 814/59 813/3 +f 817/21 813/22 816/23 818/24 +f 805/2 801/67 813/59 817/3 +f 819/46 817/36 818/48 820/47 +f 807/2 805/67 817/59 819/3 +f 821/13 822/14 816/15 815/16 +f 822/13 823/14 824/15 825/16 +f 822/13 825/14 818/15 816/16 +f 825/13 824/14 826/15 827/16 +f 825/13 827/14 820/15 818/16 +f 826/13 828/14 829/15 830/16 +f 827/13 826/14 830/15 831/16 +f 827/13 831/14 832/15 820/16 +f 830/13 829/14 833/15 834/16 +f 831/13 830/14 834/15 835/16 +f 798/69 797/10 810/74 811/70 +f 786/69 798/10 811/74 812/70 +f 790/69 786/10 812/74 836/70 +f 837/29 838/12 839/9 +f 840/29 841/32 842/12 837/9 +f 843/29 840/32 837/12 839/9 +f 844/29 843/32 839/12 845/9 +f 846/29 847/32 844/12 848/9 +f 848/29 844/32 845/12 849/9 +f 850/29 851/12 852/9 +f 842/29 853/12 854/9 +f 838/29 837/32 842/12 854/9 +f 855/29 856/9 845/12 839/32 +f 857/55 858/1 856/2 855/57 +f 859/29 860/32 861/12 862/9 +f 863/29 864/12 860/9 +f 862/29 861/12 865/9 +f 866/78 849/75 867/72 868/71 +f 869/75 848/76 849/77 866/72 +f 851/78 846/75 848/72 869/71 +f 850/78 865/75 846/72 851/71 +f 870/78 862/75 865/72 850/71 +f 871/29 865/9 861/12 872/32 +f 847/29 846/9 865/12 871/32 +f 873/29 874/9 875/12 876/32 +f 841/29 840/9 874/12 873/32 +f 877/29 878/9 879/12 880/32 +f 875/29 881/9 878/12 877/32 +f 874/29 882/9 881/12 875/32 +f 840/29 843/9 882/12 874/32 +f 878/29 872/9 864/12 879/32 +f 881/29 871/9 872/12 878/32 +f 882/29 847/9 871/12 881/32 +f 843/29 844/9 847/12 882/32 +f 872/29 861/9 860/12 864/32 +f 883/13 884/15 885/16 +f 886/66 887/18 888/69 889/65 +f 884/15 883/14 890/13 891/16 +f 891/13 892/16 893/15 884/14 +f 894/13 895/16 892/15 891/14 +f 896/13 897/16 895/15 894/14 +f 888/21 887/22 897/23 896/24 +f 892/13 898/16 899/15 893/14 +f 895/13 900/16 898/15 892/14 +f 897/13 901/16 900/15 895/14 +f 887/46 902/36 901/48 897/47 +f 903/29 904/9 905/12 889/32 +f 904/29 906/9 907/12 905/32 +f 903/29 889/9 908/32 +f 909/66 910/18 911/69 912/65 +f 911/35 913/36 902/8 +f 911/35 910/36 914/37 913/8 +f 915/13 916/14 917/15 918/16 +f 919/13 915/14 918/15 920/16 +f 913/46 914/36 919/48 920/47 +f 918/13 917/14 898/15 900/16 +f 920/13 918/14 900/15 901/16 +f 902/21 913/22 920/23 901/24 +f 917/13 916/14 921/15 922/16 +f 898/13 917/14 922/15 899/16 +f 923/1 924/2 925/3 926/4 +f 927/1 923/2 926/3 928/4 +f 929/1 927/2 928/3 930/4 +f 931/1 929/2 930/3 932/4 +f 933/1 931/2 932/3 934/4 +f 935/1 933/2 934/3 936/4 +f 926/1 925/2 937/3 938/4 +f 928/1 926/2 938/3 939/4 +f 930/1 928/2 939/3 940/4 +f 932/1 930/2 940/3 941/4 +f 934/1 932/2 941/3 942/4 +f 936/1 934/2 942/3 943/4 +f 941/1 940/2 944/3 945/4 +f 942/1 941/2 945/3 946/4 +f 947/1 948/2 949/3 950/4 +f 951/1 952/2 927/3 929/4 +f 953/1 954/2 955/3 956/4 +f 957/1 953/2 956/3 952/4 +f 958/1 957/2 952/3 951/4 +f 959/1 951/2 929/3 931/4 +f 960/1 959/2 931/3 933/4 +f 961/1 962/2 954/3 953/4 +f 963/1 958/2 951/3 959/4 +f 964/1 961/2 953/3 957/4 +f 965/1 964/2 957/3 958/4 +f 966/1 963/2 959/3 960/4 +f 967/1 965/2 958/3 963/4 +f 949/1 960/2 933/3 935/4 +f 950/1 949/2 935/3 968/4 +f 948/1 966/2 960/3 949/4 +f 969/1 967/2 963/3 966/4 +f 970/1 969/2 966/3 948/4 +f 971/1 972/2 973/3 974/4 +f 975/1 976/2 977/3 962/4 +f 978/1 975/2 962/3 961/4 +f 973/1 978/2 961/3 964/4 +f 974/1 973/2 964/3 965/4 +f 979/1 974/2 965/3 967/4 +f 980/1 979/2 967/3 969/4 +f 981/1 980/2 969/3 970/4 +f 924/3 923/4 956/1 955/2 +f 952/1 956/2 923/3 927/4 +f 982/21 983/22 984/23 985/24 +f 983/51 982/50 986/49 987/52 +f 988/13 985/14 989/15 990/16 +f 991/46 982/36 985/48 988/47 +f 982/51 991/50 992/49 986/52 +f 993/13 988/14 990/15 994/16 +f 995/21 991/22 988/23 993/24 +f 996/49 992/52 991/51 995/50 +f 997/13 993/14 994/15 998/16 +f 999/46 995/36 993/48 997/47 +f 1000/49 996/52 995/51 999/50 +f 1001/13 997/14 998/15 1002/16 +f 1003/21 999/22 997/23 1001/24 +f 1004/49 1000/52 999/51 1003/50 +f 1005/13 1001/14 1002/15 1006/16 +f 1007/46 1003/36 1001/48 1005/47 +f 985/13 984/14 1008/15 989/16 +f 1009/1 1010/2 1011/3 1012/4 +f 1013/1 1014/2 1015/3 1016/4 +f 1017/1 1013/2 1016/3 1018/4 +f 1019/1 1017/2 1018/3 1020/4 +f 1021/1 1019/2 1020/3 1022/4 +f 1023/1 1021/2 1022/3 1024/4 +f 1025/1 1023/2 1024/3 1011/4 +f 1011/3 1010/4 1026/1 1025/2 +f 1016/1 1015/2 1027/3 1028/4 +f 1018/1 1016/2 1028/3 1029/4 +f 1020/1 1018/2 1029/3 1030/4 +f 1022/1 1020/2 1030/3 1031/4 +f 1024/1 1022/2 1031/3 1032/4 +f 1011/1 1024/2 1032/3 1012/4 +f 1028/1 1027/2 1033/3 1034/4 +f 1029/1 1028/2 1034/3 1035/4 +f 1030/1 1029/2 1035/3 1036/4 +f 1031/1 1030/2 1036/3 1037/4 +f 1032/1 1031/2 1037/3 1038/4 +f 1012/1 1032/2 1038/3 1039/4 +f 1009/1 1012/2 1039/3 1040/4 +f 1034/1 1033/2 1041/3 1042/4 +f 1035/1 1034/2 1042/3 1043/4 +f 1036/1 1035/2 1043/3 1044/4 +f 1037/1 1036/2 1044/3 1045/4 +f 1038/1 1037/2 1045/3 1046/4 +f 1039/1 1038/2 1046/3 1047/4 +f 1040/1 1039/2 1047/3 1048/4 +f 1042/1 1041/2 1049/3 1050/4 +f 1043/1 1042/2 1050/3 1051/4 +f 1044/1 1043/2 1051/3 1052/4 +f 1045/1 1044/2 1052/3 1053/4 +f 1046/1 1045/2 1053/3 1054/4 +f 1047/1 1046/2 1054/3 1055/4 +f 1048/1 1047/2 1055/3 1056/4 +f 1050/1 1049/2 1057/3 1058/4 +f 1051/1 1050/2 1058/3 1059/4 +f 1052/1 1051/2 1059/3 1060/4 +f 1053/1 1052/2 1060/3 1061/4 +f 1054/1 1053/2 1061/3 1062/4 +f 1055/1 1054/2 1062/3 1063/4 +f 1056/1 1055/2 1063/3 1064/4 +f 1065/1 1066/2 1067/3 1068/4 +f 1069/1 1065/2 1068/3 1070/4 +f 1071/1 1069/2 1070/3 1072/4 +f 1073/1 1071/2 1072/3 1074/4 +f 1075/1 1073/2 1074/3 1076/4 +f 1077/1 1075/2 1076/3 1078/4 +f 1079/1 1077/2 1078/3 1080/4 +f 1068/1 1067/2 1081/3 1082/4 +f 1070/1 1068/2 1082/3 1083/4 +f 1072/1 1070/2 1083/3 1084/4 +f 1074/1 1072/2 1084/3 1085/4 +f 1076/1 1074/2 1085/3 1086/4 +f 1078/1 1076/2 1086/3 1087/4 +f 1080/1 1078/2 1087/3 1088/4 +f 1082/1 1081/2 1089/3 1090/4 +f 1083/1 1082/2 1090/3 1091/4 +f 1084/1 1083/2 1091/3 1092/4 +f 1085/1 1084/2 1092/3 1093/4 +f 1086/1 1085/2 1093/3 1094/4 +f 1087/1 1086/2 1094/3 1095/4 +f 1088/1 1087/2 1095/3 1096/4 +f 1091/1 1090/2 1097/3 1098/4 +f 1092/1 1091/2 1098/3 1099/4 +f 1093/1 1092/2 1099/3 1100/4 +f 1094/1 1093/2 1100/3 1101/4 +f 1095/1 1094/2 1101/3 1102/4 +f 1096/1 1095/2 1102/3 1103/4 +f 1098/1 1097/2 1104/3 1105/4 +f 1099/1 1098/2 1105/3 1106/4 +f 1100/1 1099/2 1106/3 1107/4 +f 1101/1 1100/2 1107/3 1108/4 +f 1102/1 1101/2 1108/3 1109/4 +f 1103/1 1102/2 1109/3 1110/4 +f 1104/1 1111/2 1112/3 1113/4 +f 1105/1 1104/2 1113/3 1114/4 +f 1106/1 1105/2 1114/3 1115/4 +f 1107/1 1106/2 1115/3 1116/4 +f 1108/1 1107/2 1116/3 1117/4 +f 1109/1 1108/2 1117/3 1118/4 +f 1110/1 1109/2 1118/3 1119/4 +f 1120/37 1121/88 1122/41 1123/40 +f 1124/37 1125/88 1121/41 1120/40 +f 1126/37 1127/88 1125/41 1124/40 +f 1128/37 1127/88 1126/41 1129/40 +f 1130/17 1127/20 1128/19 1131/18 +f 1132/17 1122/20 1121/19 1133/18 +f 1134/10 1122/74 1132/84 1135/11 +f 1121/17 1125/18 1136/19 1133/20 +f 1137/10 1138/74 1139/84 1140/11 +f 1141/17 1142/20 1139/19 1138/18 +f 1133/18 1136/69 1143/70 1141/19 +f 1132/18 1133/69 1141/70 1138/19 +f 1135/10 1132/74 1138/84 1137/11 +f 1144/15 1145/26 1146/5 1147/71 +f 1147/15 1146/26 1148/5 1149/71 +f 1149/15 1148/26 1150/5 1151/71 +f 1152/17 1153/7 1154/73 +f 1155/73 1156/7 1157/17 +f 1158/30 1159/27 1160/29 +f 1159/27 1161/29 1160/28 +f 1162/5 1163/6 1164/71 +f 1165/5 1162/6 1164/71 +f 1166/17 1167/18 1168/19 1169/20 +f 1168/17 1170/18 1171/19 1169/20 +f 1172/65 1173/10 1174/69 +f 1173/65 1175/10 1174/69 +f 1175/65 1176/10 1174/69 +f 1176/65 1177/10 1174/69 +f 1177/65 1172/10 1174/69 +f 1178/13 1179/14 1180/15 1181/16 +f 1179/13 1182/14 1183/15 1180/16 +f 1184/13 1185/15 1186/16 +f 1187/57 1188/50 1189/67 1190/2 +f 1191/57 1192/50 1188/67 1187/2 +f 1193/57 1194/50 1192/67 1191/2 +f 1195/37 1196/88 1197/41 1198/40 +f 1199/37 1195/88 1198/41 1200/40 +f 1201/37 1199/88 1200/41 1202/40 +f 1195/37 1203/40 1204/41 1196/88 +f 1203/37 1205/40 1206/41 1204/88 +f 1199/37 1207/40 1203/41 1195/88 +f 1207/37 1208/40 1205/41 1203/88 +f 1201/37 1209/40 1207/41 1199/88 +f 1209/37 1210/40 1208/41 1207/88 +f 1208/35 1210/8 1211/37 1212/36 +f 1213/79 1214/82 1212/81 1211/80 +f 1205/35 1208/8 1212/37 1215/36 +f 1216/79 1217/82 1218/81 1215/80 +f 1206/35 1205/8 1215/37 1218/36 +f 1219/57 1220/2 1221/67 1222/50 +f 1217/57 1216/2 1220/67 1219/50 +f 1220/57 1223/2 1224/67 1221/50 +f 1216/57 1214/2 1223/67 1220/50 +f 1223/57 1225/2 1226/67 1224/50 +f 1214/57 1213/2 1225/67 1223/50 +f 1225/59 1227/62 1228/61 1226/60 +f 1213/59 1211/62 1227/61 1225/60 +f 1227/4 1209/64 1201/63 1228/3 +f 1211/4 1210/64 1209/63 1227/3 +f 1229/10 1230/11 1231/84 1232/74 +f 1233/17 1232/18 1231/19 1234/20 +f 1235/37 1236/40 1237/41 1238/88 +f 1239/10 1240/9 1241/65 1242/69 +f 1240/65 1239/69 1243/10 1244/9 +f 1244/65 1243/69 1245/10 1246/9 +f 1247/65 1248/69 1249/10 1246/9 +f 1246/65 1245/69 1250/10 1247/9 +f 1241/65 1251/69 1248/10 1247/9 +f 1247/65 1250/69 1242/10 1241/9 +f 1252/1 1253/2 1254/3 1255/4 +f 1256/1 1252/2 1255/3 1257/4 +f 1258/1 1259/2 1260/3 1261/4 +f 1262/1 1258/2 1261/3 1263/4 +f 1264/1 1262/2 1263/3 1265/4 +f 1254/1 1264/2 1265/3 1266/4 +f 1255/1 1254/2 1266/3 1267/4 +f 1257/1 1255/2 1267/3 1268/4 +f 1263/1 1261/2 1269/3 1270/4 +f 1271/1 1272/2 1273/3 1274/4 +f 1275/1 1271/2 1274/3 1276/4 +f 1277/1 1275/2 1276/3 1278/4 +f 1279/1 1277/2 1278/3 1253/4 +f 1274/1 1273/2 1259/3 1258/4 +f 1280/1 1281/2 1282/3 1283/4 +f 1283/1 1282/2 1272/3 1271/4 +f 1284/1 1280/2 1283/3 1285/4 +f 1285/1 1283/2 1271/3 1275/4 +f 1286/1 1285/2 1275/3 1277/4 +f 1287/1 1284/2 1285/3 1286/4 +f 1288/1 1287/2 1286/3 1289/4 +f 1290/1 1288/2 1289/3 1291/4 +f 1276/1 1274/2 1258/3 1262/4 +f 1253/3 1252/4 1292/1 1279/2 +f 1293/1 1294/2 1295/3 1296/4 +f 1278/1 1276/2 1262/3 1264/4 +f 1253/1 1278/2 1264/3 1254/4 +f 1289/1 1286/2 1277/3 1279/4 +f 1297/1 1298/2 1281/3 1280/4 +f 1299/1 1297/2 1280/3 1284/4 +f 1300/1 1299/2 1284/3 1287/4 +f 1295/1 1300/2 1287/3 1288/4 +f 1296/1 1295/2 1288/3 1290/4 +f 1291/1 1289/2 1279/3 1292/4 +f 1301/33 1302/53 1303/43 1304/42 +f 1305/53 1304/43 1303/1 1306/55 +f 1307/53 1308/43 1304/1 1305/55 +f 1308/71 1307/5 1309/6 1310/72 +f 1306/15 1311/26 1312/5 1305/71 +f 1313/33 1314/53 1315/43 1316/42 +f 1317/33 1318/42 1319/43 1320/53 +f 1321/57 1322/2 1317/67 1323/50 +f 1323/33 1324/42 1325/43 1321/53 +f 1317/33 1322/53 1326/43 1318/42 +f 1321/33 1325/42 1326/43 1322/53 +f 1327/13 1328/14 1329/15 1330/16 +f 1331/13 1327/14 1330/15 1332/16 +f 1333/13 1334/14 1335/15 1336/16 +f 1332/13 1333/14 1336/15 1337/16 +f 1336/13 1335/14 1338/15 1339/16 +f 1337/13 1336/14 1339/15 1340/16 +f 1339/13 1338/14 1341/15 1342/16 +f 1340/13 1339/14 1342/15 1343/16 +f 1342/13 1341/14 1344/15 1345/16 +f 1343/13 1342/14 1345/15 1346/16 +f 1345/13 1344/14 1347/15 1348/16 +f 1346/13 1345/14 1348/15 1349/16 +f 1348/13 1347/15 1350/16 +f 1349/13 1348/14 1350/15 1351/16 +f 1352/13 1353/14 1334/15 1333/16 +f 1351/13 1350/15 1354/16 +f 1355/13 1351/14 1354/15 1356/16 +f 1330/13 1352/14 1333/15 1332/16 +f 1346/13 1357/14 1358/15 1343/16 +f 1359/13 1357/14 1346/15 1349/16 +f 1351/13 1355/14 1359/15 1349/16 +f 1360/17 1361/18 1362/19 1363/20 +f 1364/13 1365/15 1366/16 +f 1367/24 1368/23 1369/82 1370/79 +f 1369/24 1371/23 1372/82 1370/79 +f 1373/25 1370/85 1372/35 1374/26 +f 1375/22 1376/21 1377/23 +f 1378/21 1375/22 1377/23 1379/24 +f 1380/66 1381/65 1375/69 1378/18 +f 1382/25 1367/85 1370/35 1373/26 +f 1371/24 1376/23 1375/82 1372/79 +f 1374/25 1372/85 1375/35 1381/26 +f 1383/58 1376/50 1384/57 +f 1383/21 1364/24 1377/23 1376/22 +f 1377/13 1364/15 1366/16 +f 1385/29 1386/32 1387/12 1388/9 +f 1389/29 1385/32 1388/12 1390/9 +f 1391/29 1380/32 1387/12 1386/9 +f 1374/29 1381/32 1380/12 1391/9 +f 1392/29 1382/9 1373/32 +f 1374/29 1391/9 1392/12 1373/32 +f 1391/29 1386/9 1393/12 1392/32 +f 1386/29 1385/9 1394/12 1393/32 +f 1387/8 1380/7 1378/40 1395/37 +f 1388/66 1387/65 1395/69 1396/18 +f 1390/66 1388/65 1396/69 1397/18 +f 1395/46 1378/36 1379/48 1398/47 +f 1399/13 1398/14 1400/15 1401/16 +f 1396/21 1395/22 1398/23 1399/24 +f 1402/13 1399/14 1401/15 1403/16 +f 1397/46 1396/36 1399/48 1402/47 +f 1363/17 1404/20 1405/19 1360/18 +f 1406/29 1389/32 1390/12 1407/9 +f 1408/21 1397/22 1402/23 1409/24 +f 1410/69 1411/70 1383/74 1384/10 +f 1412/17 1364/20 1383/19 1411/18 +f 1413/17 1365/20 1364/19 1412/18 +f 1404/18 1414/69 1413/70 1412/19 +f 1412/18 1411/69 1405/70 1404/19 +f 1415/69 1405/70 1411/74 1410/10 +f 1416/3 1417/59 1418/62 1419/63 +f 1406/2 1419/3 1420/59 1421/67 +f 1406/2 1416/59 1419/3 +f 1417/8 1390/7 1397/40 1408/37 +f 1422/13 1423/14 1424/15 1425/16 +f 1426/13 1422/14 1425/15 1427/16 +f 1428/13 1426/14 1427/15 1429/16 +f 1425/13 1424/14 1430/15 1431/16 +f 1427/13 1425/14 1431/15 1432/16 +f 1429/13 1427/14 1432/15 1433/16 +f 1422/13 1434/14 1435/15 1423/16 +f 1436/35 1437/36 1438/37 1439/8 +f 1440/35 1441/8 1437/37 1442/36 +f 1443/35 1438/36 1437/37 1444/8 +f 1445/29 1446/32 1447/12 1448/9 +f 1449/29 1450/32 1451/12 1452/9 +f 1453/43 1454/53 1455/33 1456/42 +f 1454/33 1453/42 1457/43 1458/53 +f 1459/33 1460/42 1461/43 1462/53 +f 1463/37 1464/41 1465/88 +f 1463/88 1465/48 1466/36 1467/37 +f 1468/51 1466/68 1465/24 1469/21 +f 1470/69 1471/10 1472/65 +f 1471/69 1470/10 1473/65 +f 1471/69 1474/10 1472/65 +f 1474/69 1471/10 1473/65 +f 1474/9 1470/65 1472/10 +f 1470/69 1474/10 1473/65 +f 1475/24 1467/23 1466/82 1476/79 +f 1477/13 1478/14 1479/15 1480/16 +f 1480/13 1479/14 1481/15 1482/16 +f 1482/13 1481/14 1483/15 1484/16 +f 1484/13 1483/14 1485/15 1486/16 +f 1487/21 1488/22 1489/23 1490/24 +f 1491/46 1487/36 1490/48 1492/47 +f 1486/13 1485/14 1493/15 1489/16 +f 1494/8 1495/7 1487/40 1491/37 +f 1495/66 1496/65 1488/69 1487/18 +f 1497/66 1494/65 1491/69 1498/18 +f 1498/21 1491/22 1492/23 1499/24 +f 1499/13 1500/14 1501/15 1502/16 +f 1503/46 1498/36 1499/48 1502/47 +f 1504/40 1505/17 1506/7 +f 1507/12 1508/11 1509/45 1510/42 +f 1507/12 1510/42 1511/45 1512/11 +f 1510/12 1509/11 1513/45 1514/42 +f 1510/12 1514/42 1515/45 1511/11 +f 1514/12 1513/11 1516/45 1517/42 +f 1514/12 1517/42 1518/45 1515/11 +f 1517/12 1516/11 1519/45 1520/42 +f 1517/12 1520/42 1521/45 1518/11 +f 1520/12 1519/11 1522/45 1523/42 +f 1520/12 1523/42 1524/45 1521/11 +f 1523/12 1522/11 1525/45 1526/42 +f 1523/12 1526/42 1527/45 1524/11 +f 1528/87 1509/73 1508/66 1529/39 +f 1530/87 1513/73 1509/66 1528/39 +f 1531/87 1516/73 1513/66 1530/39 +f 1532/87 1519/73 1516/66 1531/39 +f 1533/87 1522/73 1519/66 1532/39 +f 1534/87 1525/73 1522/66 1533/39 +f 1535/87 1526/73 1525/66 1534/39 +f 1536/87 1527/73 1526/66 1535/39 +f 1537/12 1528/11 1529/45 1538/42 +f 1537/12 1538/42 1539/45 1540/11 +f 1541/12 1530/11 1528/45 1537/42 +f 1535/12 1534/11 1533/45 1542/42 +f 1535/12 1542/42 1543/45 1536/11 +f 1539/87 1512/73 1511/66 1540/39 +f 1543/87 1524/73 1527/66 1536/39 +f 1544/4 1545/3 1546/1 +f 1547/43 1548/1 1549/4 1550/44 +f 1548/42 1551/43 1552/44 1549/45 +f 1551/43 1553/1 1554/4 1552/44 +f 1555/1 1556/2 1551/3 1548/4 +f 1551/1 1557/3 1553/4 +f 1558/1 1548/3 1547/4 +f 1544/43 1559/1 1560/4 1561/44 +f 1562/4 1563/43 1564/1 +f 1563/42 1562/45 1565/44 1566/43 +f 1564/42 1567/43 1568/44 1562/45 +f 1569/1 1570/3 1571/4 +f 1570/1 1567/2 1564/3 1571/4 +f 1571/1 1564/2 1563/3 1557/4 +f 1552/49 1572/52 1573/51 1549/50 +f 1574/49 1575/51 1572/50 +f 1549/49 1573/52 1576/51 1550/50 +f 1554/49 1574/52 1572/51 1552/50 +f 1550/49 1576/52 1577/51 1578/50 +f 1572/49 1575/51 1573/50 +f 1578/49 1577/52 1579/51 1580/50 +f 1579/49 1575/51 1574/50 +f 1580/49 1579/52 1574/51 1554/50 +f 1575/50 1579/51 1573/49 +f 1576/49 1573/52 1579/51 1577/50 +f 1581/49 1582/52 1583/51 1584/50 +f 1585/87 1586/39 1583/66 1582/73 +f 1587/87 1585/39 1582/66 1581/73 +f 1588/87 1587/39 1581/66 1584/73 +f 1586/87 1588/39 1584/66 1583/73 +f 1589/49 1590/50 1591/51 1592/52 +f 1593/87 1592/73 1591/66 1594/39 +f 1595/87 1589/73 1592/66 1593/39 +f 1596/87 1590/73 1589/66 1595/39 +f 1594/87 1591/73 1590/66 1596/39 +f 1571/1 1557/2 1551/3 1556/4 +f 1569/1 1571/2 1556/3 1597/4 +f 1546/1 1569/2 1597/3 1598/4 +f 1544/1 1546/2 1598/3 1599/4 +f 1559/1 1544/2 1599/3 1600/4 +f 1601/1 1559/2 1600/3 1602/4 +f 1597/1 1556/2 1555/3 1603/4 +f 1598/1 1597/2 1603/3 1604/4 +f 1599/1 1598/2 1604/3 1605/4 +f 1600/1 1599/2 1605/3 1606/4 +f 1602/1 1600/2 1606/3 1607/4 +f 1555/1 1548/2 1558/3 1608/4 +f 1603/1 1555/2 1608/3 1609/4 +f 1604/1 1603/2 1609/3 1610/4 +f 1605/1 1604/2 1610/3 1611/4 +f 1606/1 1605/2 1611/3 1612/4 +f 1607/1 1606/2 1612/3 1613/4 +f 1608/1 1558/2 1614/3 1615/4 +f 1609/1 1608/2 1615/3 1616/4 +f 1610/1 1609/2 1616/3 1617/4 +f 1611/1 1610/2 1617/3 1618/4 +f 1612/1 1611/2 1618/3 1619/4 +f 1613/1 1612/2 1619/3 1620/4 +f 1621/1 1613/2 1620/3 1622/4 +f 1615/1 1614/2 1623/3 1624/4 +f 1616/1 1615/2 1624/3 1625/4 +f 1617/1 1616/2 1625/3 1626/4 +f 1618/1 1617/2 1626/3 1627/4 +f 1619/1 1618/2 1627/3 1628/4 +f 1620/1 1619/2 1628/3 1629/4 +f 1624/1 1623/2 1630/3 1631/4 +f 1625/1 1624/2 1631/3 1632/4 +f 1626/1 1625/2 1632/3 1633/4 +f 1627/1 1626/2 1633/3 1634/4 +f 1628/1 1627/2 1634/3 1635/4 +f 1629/1 1628/3 1635/4 +f 1636/28 1637/29 1638/9 1639/65 +f 1640/28 1636/29 1639/9 1641/65 +f 1642/35 1643/8 1644/37 1645/36 +f 1643/35 1646/8 1647/37 1644/36 +f 1638/35 1645/8 1644/37 1639/36 +f 1639/35 1644/8 1647/37 1641/36 +f 1648/29 1649/32 1650/12 1651/9 +f 1649/9 1652/12 1653/29 +f 1649/29 1653/9 1654/12 1650/32 +f 1654/45 1653/44 1655/89 1656/83 +f 1657/17 1658/18 1656/19 1655/20 +f 1653/45 1652/44 1659/89 1655/83 +f 1660/17 1657/18 1655/19 1659/20 +f 1652/45 1661/44 1662/89 1659/83 +f 1663/17 1660/18 1659/19 1662/20 +f 1664/17 1663/18 1662/19 1665/20 +f 1666/17 1664/18 1665/19 1667/20 +f 1668/17 1666/18 1667/19 1669/20 +f 1661/45 1670/44 1665/89 1662/83 +f 1670/45 1671/44 1667/89 1665/83 +f 1671/45 1672/44 1669/89 1667/83 +f 1649/12 1648/9 1661/29 1652/32 +f 1648/29 1670/12 1661/9 +f 1648/29 1651/32 1671/12 1670/9 +f 1672/9 1671/12 1651/29 +f 1673/45 1674/44 1657/89 1660/83 +f 1675/45 1658/83 1657/89 1674/44 +f 1676/45 1677/44 1664/89 1666/83 +f 1678/29 1679/9 1680/12 1681/32 +f 1679/29 1682/9 1683/12 1680/32 +f 1684/21 1685/22 1686/23 1687/24 +f 1685/51 1684/49 1688/52 +f 1689/49 1690/52 1691/51 1692/50 +f 1693/22 1694/21 1695/23 +f 1694/49 1693/52 1696/51 1697/50 +f 1698/49 1699/52 1700/51 1689/50 +f 1700/49 1701/51 1697/50 +f 1689/49 1700/52 1697/51 1702/50 +f 1697/49 1701/51 1694/50 +f 1699/49 1701/51 1700/50 +f 1694/49 1701/51 1703/50 +f 1694/21 1703/22 1704/23 1695/24 +f 1703/49 1701/51 1705/50 +f 1703/46 1705/36 1706/48 1704/47 +f 1705/49 1701/51 1699/50 +f 1705/21 1699/22 1698/23 1706/24 +f 1693/49 1707/52 1708/51 1696/50 +f 1685/49 1709/52 1710/51 1711/50 +f 1711/49 1710/52 1707/51 1693/50 +f 1685/49 1712/51 1713/50 +f 1714/59 1715/60 1716/61 1717/62 +f 1718/8 1719/7 1720/40 1721/37 +f 1722/1 1723/2 1724/3 1725/4 +f 1726/1 1727/2 1728/3 1729/4 +f 1724/1 1726/2 1729/3 1730/4 +f 1725/1 1724/2 1730/3 1731/4 +f 1732/1 1725/2 1731/3 1733/4 +f 1734/1 1732/2 1733/3 1735/4 +f 1736/1 1734/2 1735/3 1737/4 +f 1738/1 1736/2 1737/3 1739/4 +f 1740/13 1741/16 1742/15 1743/14 +f 1744/13 1745/16 1741/15 1740/14 +f 1746/66 1747/65 1748/69 1749/18 +f 1750/5 1751/71 1752/15 1753/26 +f 1754/29 1755/32 1756/12 1757/9 +f 1758/45 1759/83 1760/89 1761/44 +f 1761/45 1760/83 1762/89 1763/44 +f 1764/45 1765/83 1766/89 1767/44 +f 1767/45 1766/83 1768/89 1769/44 +f 1769/45 1768/83 1770/89 1771/44 +f 1766/17 1765/18 1772/19 1773/20 +f 1768/17 1766/18 1773/19 1774/20 +f 1770/17 1768/18 1774/19 1775/20 +f 1776/17 1770/18 1775/19 1777/20 +f 1778/45 1779/44 1780/89 1781/83 +f 1779/45 1782/44 1783/89 1780/83 +f 1782/45 1784/44 1785/89 1783/83 +f 1758/3 1761/63 1786/62 1787/59 +f 1761/3 1763/63 1788/62 1786/59 +f 1778/29 1764/32 1767/12 1779/9 +f 1779/29 1767/32 1769/12 1782/9 +f 1782/29 1769/32 1771/12 1784/9 +f 1789/45 1787/44 1773/89 1772/83 +f 1787/45 1786/44 1774/89 1773/83 +f 1786/45 1788/44 1775/89 1774/83 +f 1788/45 1790/44 1777/89 1775/83 +f 1780/17 1759/20 1791/19 1781/18 +f 1783/17 1760/20 1759/19 1780/18 +f 1785/17 1762/20 1760/19 1783/18 +f 1792/29 1793/9 1794/12 1795/32 +f 1796/29 1797/9 1798/12 1799/32 +f 1800/29 1801/9 1802/12 1803/32 +f 1754/29 1757/9 1796/12 1804/32 +f 1757/29 1803/9 1797/12 1796/32 +f 1756/29 1800/9 1803/12 1757/32 +f 1801/29 1795/9 1805/12 1802/32 +f 1806/29 1807/9 1808/12 1809/32 +f 1810/13 1811/14 1812/15 1813/16 +f 1814/49 1815/51 1816/50 +f 1817/49 1814/52 1816/51 1818/50 +f 1816/49 1815/51 1819/50 +f 1816/46 1819/36 1820/48 1818/47 +f 1821/1 1822/2 1823/3 1824/4 +f 1823/1 1825/2 1826/3 1827/4 +f 1824/1 1823/2 1827/3 1828/4 +f 1829/1 1824/2 1828/3 1830/4 +f 1831/1 1829/2 1830/3 1832/4 +f 1833/1 1831/2 1832/3 1834/4 +f 1827/1 1826/2 1835/3 1836/4 +f 1828/1 1827/2 1836/3 1837/4 +f 1830/1 1828/2 1837/3 1838/4 +f 1832/1 1830/2 1838/3 1839/4 +f 1834/1 1832/2 1839/3 1840/4 +f 1836/1 1835/2 1841/3 1842/4 +f 1837/1 1836/2 1842/3 1843/4 +f 1838/1 1837/2 1843/3 1844/4 +f 1839/1 1838/2 1844/3 1845/4 +f 1840/1 1839/2 1845/3 1846/4 +f 1847/1 1840/2 1846/3 1848/4 +f 1842/1 1841/2 1849/3 1850/4 +f 1843/1 1842/2 1850/3 1851/4 +f 1844/1 1843/2 1851/3 1852/4 +f 1845/1 1844/2 1852/3 1853/4 +f 1846/1 1845/2 1853/3 1854/4 +f 1850/1 1849/2 1855/3 1856/4 +f 1851/1 1850/2 1856/3 1857/4 +f 1852/1 1851/2 1857/3 1858/4 +f 1853/1 1852/2 1858/3 1859/4 +f 1854/1 1853/2 1859/3 1860/4 +f 1856/1 1855/2 1861/3 1862/4 +f 1857/1 1856/2 1862/3 1863/4 +f 1858/1 1857/2 1863/3 1864/4 +f 1859/1 1858/2 1864/3 1865/4 +f 1860/1 1859/2 1865/3 1866/4 +f 1862/1 1861/2 1867/3 1868/4 +f 1869/13 1870/15 1871/16 +f 1872/13 1869/14 1871/15 1873/16 +f 1874/17 1875/18 1876/19 1877/20 +f 1876/17 1875/18 1878/19 1879/20 +f 1880/17 1879/18 1878/19 1881/20 +f 1882/17 1880/18 1881/19 1883/20 +f 1884/17 1882/18 1883/19 1885/20 +f 1874/17 1877/18 1886/19 1887/20 +f 1887/17 1886/18 1884/19 1885/20 +f 1888/13 1869/14 1872/15 1889/16 +f 1890/46 1891/36 1888/48 1889/47 +f 1892/57 1893/50 1875/67 1874/2 +f 1892/10 1894/74 1895/84 1896/11 +f 1897/18 1898/19 1899/70 1900/69 +f 1901/18 1898/69 1897/70 1902/19 +f 1896/10 1895/74 1903/84 1904/11 +f 1897/17 1900/18 1883/19 1881/20 +f 1883/40 1900/20 1905/41 +f 1885/17 1883/18 1905/19 1906/20 +f 1885/17 1906/20 1894/19 1887/18 +f 1874/10 1887/74 1894/84 1892/11 +f 1900/44 1907/89 1908/64 1909/4 +f 1875/10 1893/11 1902/84 1878/74 +f 1902/17 1897/18 1881/19 1878/20 +f 1910/54 1911/56 1912/55 1913/53 +f 1913/34 1912/54 1914/53 1915/33 +f 1916/34 1917/54 1915/53 1914/33 +f 1918/34 1919/33 1920/53 1921/54 +f 1922/58 1919/57 1923/50 1924/49 +f 1922/54 1925/56 1920/55 1919/53 +f 1926/85 1927/35 1925/36 1922/46 +f 1928/37 1929/35 1926/8 +f 1928/85 1926/35 1922/36 1924/46 +f 1911/36 1910/46 1926/85 1929/35 +f 1928/69 1924/10 1923/74 1930/70 +f 1931/45 1932/89 1933/83 +f 1933/89 1934/45 1931/44 +f 1934/45 1933/89 1935/83 +f 1936/29 1937/9 1938/12 1939/32 +f 1939/29 1938/9 1940/12 1941/32 +f 1942/29 1943/9 1944/12 1937/32 +f 1941/29 1940/9 1945/12 1946/32 +f 1947/29 1936/9 1939/12 1948/32 +f 1946/66 1945/65 1949/69 1950/18 +f 1950/45 1949/44 1951/89 1952/83 +f 1953/45 1950/44 1952/89 1954/83 +f 1955/45 1953/44 1954/89 1956/83 +f 1957/66 1958/65 1955/69 1959/18 +f 1959/45 1955/44 1956/89 1960/83 +f 1961/29 1934/12 1962/9 +f 1963/29 1962/32 1964/12 1965/9 +f 1964/45 1966/83 1967/89 1968/44 +f 1962/45 1969/83 1966/89 1964/44 +f 1934/45 1935/83 1969/89 1962/44 +f 1960/6 1956/87 1970/73 1971/7 +f 1956/6 1954/87 1972/73 1970/7 +f 1954/6 1952/87 1973/73 1972/7 +f 1952/6 1951/87 1974/73 1973/7 +f 1951/6 1934/87 1975/73 1974/7 +f 1967/17 1966/18 1976/19 1977/20 +f 1932/19 1976/20 1966/17 1969/18 +f 1933/19 1932/20 1969/17 1935/18 +f 1978/45 1979/44 1977/89 1976/83 +f 1980/33 1981/42 1982/43 1983/53 +f 1984/18 1985/19 1986/70 1987/69 +f 1988/18 1989/19 1985/70 1984/69 +f 1990/69 1991/10 1989/74 1988/70 +f 1992/33 1993/53 1994/43 1995/42 +f 1996/6 1997/87 1998/73 1990/7 +f 1999/57 2000/50 1997/67 1996/2 +f 1999/57 1996/67 2001/2 +f 2002/57 1997/67 2000/2 +f 1983/57 2002/50 2000/67 2003/2 +f 1980/57 1983/50 2003/67 2004/2 +f 1980/57 2004/50 2005/67 2006/2 +f 2006/57 2005/50 2007/67 2008/2 +f 2007/57 1999/50 2001/67 2008/2 +f 2009/40 2010/41 2011/20 2012/17 +f 2013/33 2014/53 1981/43 2015/42 +f 2014/33 2016/53 1982/43 1981/42 +f 1981/43 1980/53 2006/33 2015/42 +f 2017/33 1992/53 1995/43 2018/42 +f 2001/33 1995/42 1994/43 2008/53 +f 2016/33 2017/53 2018/43 1982/42 +f 2012/40 2019/17 2020/20 2009/41 +f 1988/17 1984/18 2021/19 2022/20 +f 1984/17 1987/18 2019/19 2021/20 +f 1996/69 1990/10 1988/74 2022/70 +f 1991/69 2023/74 1989/70 +f 2024/17 2025/20 2026/19 2027/18 +f 1997/69 2025/70 2024/74 1998/10 +f 2027/17 2026/20 2012/19 2028/18 +f 1999/50 2007/51 2003/68 2000/67 +f 2004/50 2003/51 2007/68 2005/67 +f 2008/33 1994/42 2015/43 2006/53 +f 2025/55 1997/43 2002/53 +f 2026/53 2025/55 2002/1 2018/43 +f 2012/53 2026/1 2018/43 +f 2021/53 2019/1 1995/43 +f 2019/53 2012/55 2018/1 1995/43 +f 2022/53 2001/1 1996/43 +f 2001/53 2022/55 2021/1 1995/43 +f 2027/18 2028/69 2029/70 2030/19 +f 2024/18 2027/69 2030/70 2031/19 +f 2009/44 2020/4 2032/64 2010/89 +f 1993/33 2013/53 2015/43 1994/42 +f 1983/33 1982/42 2018/43 2002/53 +f 2033/45 2034/44 2035/89 2036/83 +f 2037/17 2038/18 2036/19 2035/20 +f 2039/29 2040/12 2041/9 +f 2042/29 2043/12 2044/9 +f 2045/29 2042/12 2046/9 +f 2047/29 2045/12 2046/9 +f 2048/78 2049/75 2050/72 2051/71 +f 2052/78 2053/75 2049/72 2048/71 +f 2043/78 2041/75 2053/72 2052/71 +f 2042/78 2039/75 2041/72 2043/71 +f 2045/75 2054/76 2039/77 2042/72 +f 2047/78 2055/75 2054/72 2045/71 +f 2056/45 2057/83 2058/89 2059/44 +f 2059/45 2058/83 2060/89 2061/44 +f 2062/45 2061/44 2060/89 2038/83 +f 2063/45 2064/83 2065/89 2066/44 +f 2065/17 2064/18 2067/19 2068/20 +f 2069/17 2065/18 2068/19 2070/20 +f 2071/45 2072/44 2073/89 2074/83 +f 2072/45 2075/44 2076/89 2073/83 +f 2059/3 2061/63 2077/62 2078/59 +f 2071/29 2079/32 2063/12 2072/9 +f 2072/29 2063/32 2066/12 2075/9 +f 2075/55 2066/57 2080/2 2033/1 +f 2078/45 2077/44 2068/89 2067/83 +f 2073/17 2058/20 2057/19 2074/18 +f 2076/17 2060/20 2058/19 2073/18 +f 2036/17 2038/20 2060/19 2076/18 +f 2081/50 2082/51 2083/68 2084/67 +f 2039/29 2085/9 2040/32 +f 2086/29 2049/9 2053/12 2087/32 +f 2046/29 2088/9 2089/12 2047/32 +f 2044/29 2090/9 2046/12 2042/32 +f 2091/29 2092/9 2093/12 2094/32 +f 2095/29 2087/9 2092/12 2091/32 +f 2090/29 2096/9 2088/12 2046/32 +f 2087/29 2053/9 2041/12 2092/32 +f 2092/29 2041/9 2040/12 2093/32 +f 2097/1 2098/2 2099/3 2100/4 +f 2101/1 2102/2 2103/3 2104/4 +f 2105/1 2100/2 2106/3 2107/4 +f 2103/1 2105/2 2107/3 2108/4 +f 2104/1 2103/2 2108/3 2109/4 +f 2110/1 2104/2 2109/3 2111/4 +f 2112/1 2110/2 2111/3 2113/4 +f 2114/1 2115/3 2116/4 +f 2107/1 2106/2 2117/3 2118/4 +f 2108/1 2107/2 2118/3 2119/4 +f 2109/1 2108/2 2119/3 2120/4 +f 2111/1 2109/2 2120/3 2121/4 +f 2113/1 2111/2 2121/3 2122/4 +f 2118/1 2117/2 2123/3 2124/4 +f 2119/1 2118/2 2124/3 2125/4 +f 2120/1 2119/2 2125/3 2126/4 +f 2121/1 2120/2 2126/3 2127/4 +f 2122/1 2121/2 2127/3 2128/4 +f 2124/1 2123/2 2129/3 2130/4 +f 2125/1 2124/2 2130/3 2131/4 +f 2126/1 2125/2 2131/3 2132/4 +f 2127/1 2126/2 2132/3 2133/4 +f 2128/1 2127/2 2133/3 2134/4 +f 2130/1 2129/2 2135/3 2136/4 +f 2131/1 2130/2 2136/3 2137/4 +f 2132/1 2131/2 2137/3 2138/4 +f 2133/1 2132/2 2138/3 2139/4 +f 2134/1 2133/2 2139/3 2140/4 +f 2134/1 2140/3 2116/4 +f 2136/1 2135/2 2141/3 2142/4 +f 2137/1 2136/2 2142/3 2143/4 +f 2138/1 2137/2 2143/3 2144/4 +f 2139/1 2138/2 2144/3 2145/4 +f 2140/1 2139/2 2145/3 2146/4 +f 2116/1 2140/2 2146/3 2114/4 +f 2145/1 2144/2 2147/3 2148/4 +f 2146/1 2145/2 2148/3 2149/4 +f 2112/43 2113/1 2150/4 2151/44 +f 2113/42 2122/43 2152/44 2150/45 +f 2122/43 2128/1 2153/4 2152/44 +f 2128/42 2134/43 2154/44 2153/45 +f 2134/43 2116/1 2155/4 2154/44 +f 2116/42 2115/43 2156/44 2155/45 +f 2154/54 2155/56 2157/55 2158/53 +f 2153/58 2154/49 2158/50 2159/57 +f 2152/58 2153/49 2159/50 2160/57 +f 2150/58 2152/49 2160/50 2161/57 +f 2151/54 2150/56 2161/55 2162/53 +f 2163/85 2164/35 2165/36 2166/46 +f 2167/36 2168/85 2169/35 +f 2169/85 2163/35 2166/36 2167/46 +f 2170/71 2171/72 2164/6 2172/5 +f 2164/52 2163/86 2172/21 +f 2173/10 2174/65 2175/9 +f 2173/10 2176/65 2174/9 +f 2164/15 2177/71 2174/5 2176/26 +f 2178/67 2177/59 2164/60 2171/68 +f 2179/29 2180/9 2181/12 2182/32 +f 2183/29 2184/9 2180/12 2179/32 +f 2178/55 2185/57 2184/2 2183/1 +f 2180/55 2186/1 2187/2 2181/57 +f 2184/29 2188/9 2186/12 2180/32 +f 2167/21 2166/22 2189/23 2190/24 +f 2190/13 2191/14 2192/15 2193/16 +f 2194/46 2167/36 2190/48 2193/47 +f 2172/21 2163/86 2195/52 2196/51 +f 2197/53 2198/55 2199/1 2200/43 +f 2201/29 2202/12 2203/9 +f 2202/12 2201/9 2204/29 +f 2205/12 2201/9 2206/29 +f 2207/17 2208/18 2209/19 2210/20 +f 2211/17 2212/20 2209/19 2210/18 +f 2213/17 2211/18 2212/19 2214/20 +f 2208/69 2205/10 2215/74 2209/70 +f 2216/17 2212/20 2209/19 2215/18 +f 2212/17 2217/20 2218/19 2209/18 +f 2208/69 2209/70 2218/74 2219/10 +f 2214/17 2220/18 2221/19 2222/20 +f 2223/41 2224/20 2214/40 +f 2214/35 2222/37 2225/36 +f 2212/17 2216/20 2223/19 2214/18 +f 2212/17 2214/18 2225/19 2217/20 +f 2226/69 2227/70 2228/74 2229/10 +f 2230/17 2231/20 2228/19 2227/18 +f 2232/17 2233/20 2231/19 2230/18 +f 2225/40 2234/41 2233/20 2223/17 +f 2222/40 2224/17 2235/20 2236/41 +f 2222/44 2236/89 2234/64 2225/4 +f 2235/40 2233/17 2234/20 2236/41 +f 2217/18 2225/69 2232/70 2230/19 +f 2230/18 2227/69 2218/70 2217/19 +f 2219/69 2218/70 2227/74 2226/10 +f 2221/18 2237/19 2238/70 2222/69 +f 2216/18 2231/19 2233/70 2223/69 +f 2231/18 2216/19 2215/70 2228/69 +f 2205/69 2229/10 2228/74 2215/70 +f 2239/29 2240/32 2241/12 2242/9 +f 2243/24 2244/23 2245/82 2246/79 +f 2247/24 2248/23 2244/82 2243/79 +f 2249/68 2250/24 2248/79 2247/60 +f 2249/25 2247/85 2243/35 2251/26 +f 2240/25 2252/85 2253/35 2241/26 +f 2254/25 2255/85 2252/35 2240/26 +f 2252/24 2256/23 2257/82 2253/79 +f 2255/24 2258/23 2256/82 2252/79 +f 2259/25 2257/85 2256/35 2260/26 +f 2261/24 2262/23 2263/82 2264/79 +f 2265/13 2266/14 2267/15 2268/16 +f 2269/13 2265/14 2268/15 2270/16 +f 2271/13 2269/14 2270/15 2272/16 +f 2273/58 2274/57 2275/50 2276/49 +f 2277/13 2278/16 2279/15 2280/14 +f 2278/13 2281/16 2271/15 2279/14 +f 2282/21 2281/24 2278/23 2283/22 +f 2284/49 2285/50 2282/51 2283/52 +f 2274/56 2285/55 2284/57 2275/58 +f 2286/42 2287/43 2276/44 2288/45 +f 2287/43 2289/1 2273/4 2276/44 +f 2286/1 2290/2 2291/3 2287/4 +f 2289/42 2292/43 2293/44 2273/45 +f 2292/43 2294/1 2295/4 2293/44 +f 2296/21 2297/24 2281/23 2282/22 +f 2298/49 2296/50 2282/51 2285/52 +f 2299/56 2298/55 2285/57 2274/58 +f 2293/54 2299/53 2274/55 2273/56 +f 2300/13 2265/16 2269/15 2297/14 +f 2301/46 2300/47 2297/48 2296/36 +f 2302/49 2301/50 2296/51 2298/52 +f 2303/56 2302/55 2298/57 2299/58 +f 2295/58 2303/57 2299/50 2293/49 +f 2304/13 2266/16 2265/15 2300/14 +f 2305/21 2304/24 2300/23 2301/22 +f 2306/49 2305/50 2301/51 2302/52 +f 2307/34 2306/33 2302/53 2303/54 +f 2308/54 2307/53 2303/55 2295/56 +f 2297/13 2269/16 2271/15 2281/14 +f 2309/4 2310/3 2311/1 +f 2310/3 2309/1 2312/4 +f 2313/29 2314/12 2315/9 +f 2316/5 2317/8 2318/7 2319/6 +f 2320/5 2321/8 2322/7 2323/6 +f 2324/3 2315/59 2314/2 +f 2324/3 2325/63 2322/62 2321/59 +f 2310/9 2326/10 2327/11 2328/12 +f 2326/9 2329/10 2330/11 2327/12 +f 2329/9 2331/10 2332/11 2330/12 +f 2333/9 2328/12 2327/11 2334/10 +f 2334/9 2327/12 2330/11 2335/10 +f 2335/9 2330/12 2332/11 2336/10 +f 2333/9 2334/10 2337/11 2312/12 +f 2334/9 2335/10 2338/11 2337/12 +f 2335/9 2336/10 2339/11 2338/12 +f 2310/9 2312/12 2337/11 2326/10 +f 2326/9 2337/12 2338/11 2329/10 +f 2329/9 2338/12 2339/11 2331/10 +f 2328/4 2340/3 2310/1 +f 2340/1 2328/4 2341/3 2316/2 +f 2341/1 2328/4 2333/3 2323/2 +f 2342/37 2343/40 2344/41 2345/88 +f 2346/37 2342/40 2345/41 2347/88 +f 2348/36 2349/37 2345/88 2344/48 +f 2349/36 2350/37 2347/88 2345/48 +f 2351/8 2352/7 2348/40 2344/37 +f 2353/66 2351/65 2344/69 2343/18 +f 2354/8 2347/37 2350/40 2355/7 +f 2356/66 2346/18 2347/69 2354/65 +f 2352/29 2351/32 2357/12 2358/9 +f 2359/29 2360/32 2361/12 2362/9 +f 2363/29 2360/12 2359/9 +f 2362/29 2361/32 2354/12 2355/9 +f 2364/29 2365/9 2366/12 2367/32 +f 2368/29 2369/9 2365/12 2364/32 +f 2370/29 2349/9 2348/12 2371/32 +f 2366/29 2350/9 2349/12 2370/32 +f 2350/6 2366/7 2365/73 2372/87 +f 2372/6 2365/7 2369/73 2373/87 +f 2374/46 2375/36 2376/48 2377/47 +f 2378/2 2379/67 2375/59 2374/3 +f 2380/21 2381/22 2382/23 2383/24 +f 2364/2 2367/67 2381/59 2380/3 +f 2384/13 2385/14 2386/15 2387/16 +f 2384/13 2387/14 2388/15 2377/16 +f 2387/13 2386/14 2389/15 2390/16 +f 2387/13 2390/14 2382/15 2388/16 +f 2390/13 2389/14 2391/15 2392/16 +f 2390/13 2392/14 2383/15 2382/16 +f 2362/69 2355/10 2350/74 2372/70 +f 2359/69 2362/10 2372/74 2373/70 +f 2393/13 2394/14 2395/15 2396/16 +f 2397/13 2393/14 2396/15 2398/16 +f 2399/13 2397/14 2398/15 2400/16 +f 2401/13 2399/14 2400/15 2402/16 +f 2395/13 2403/14 2404/15 2405/16 +f 2396/13 2395/14 2405/15 2406/16 +f 2398/13 2396/14 2406/15 2407/16 +f 2400/13 2398/14 2407/15 2408/16 +f 2402/13 2400/14 2408/15 2409/16 +f 2410/13 2402/14 2409/15 2411/16 +f 2404/13 2412/14 2413/15 2414/16 +f 2405/13 2404/14 2414/15 2415/16 +f 2406/13 2405/14 2415/15 2416/16 +f 2407/13 2406/14 2416/15 2417/16 +f 2408/13 2407/14 2417/15 2418/16 +f 2409/13 2408/14 2418/15 2419/16 +f 2420/42 2421/43 2422/44 2423/45 +f 2424/13 2425/14 2426/15 2427/16 +f 2428/46 2429/36 2425/48 2424/47 +f 2430/54 2431/56 2432/55 2433/53 +f 2434/13 2424/14 2427/15 2435/16 +f 2436/46 2428/36 2424/48 2434/47 +f 2437/49 2438/52 2428/51 2436/50 +f 2439/56 2433/58 2438/57 2437/55 +f 2440/58 2430/49 2433/50 2439/57 +f 2441/13 2434/14 2435/15 2442/16 +f 2443/21 2436/22 2434/23 2441/24 +f 2444/49 2437/52 2436/51 2443/50 +f 2445/34 2439/54 2437/53 2444/33 +f 2446/13 2441/14 2442/15 2447/16 +f 2448/46 2443/36 2441/48 2446/47 +f 2449/49 2444/52 2443/51 2448/50 +f 2450/34 2445/54 2444/53 2449/33 +f 2451/13 2446/14 2447/15 2452/16 +f 2453/21 2448/22 2446/23 2451/24 +f 2454/49 2449/52 2448/51 2453/50 +f 2455/56 2450/58 2449/57 2454/55 +f 2422/58 2456/49 2450/50 2455/57 +f 2457/13 2451/14 2452/15 2458/16 +f 2453/21 2451/24 2457/23 2459/22 +f 2460/49 2454/52 2453/51 2459/50 +f 2461/13 2457/14 2458/15 2462/16 +f 2463/36 2464/37 2465/88 2466/48 +f 2467/36 2463/37 2466/88 2468/48 +f 2469/36 2467/37 2468/88 2470/48 +f 2466/37 2465/41 2471/88 +f 2472/66 2473/65 2471/69 2465/18 +f 2472/66 2465/69 2464/18 +f 2474/29 2475/12 2476/9 +f 2475/29 2474/32 2477/12 2478/9 +f 2479/28 2480/29 2481/9 2482/65 +f 2483/28 2479/29 2482/9 2484/65 +f 2485/53 2486/55 2480/1 2479/43 +f 2487/26 2485/5 2479/8 2483/35 +f 2488/35 2489/36 2490/37 2491/8 +f 2492/27 2493/28 2494/29 2491/30 +f 2491/27 2494/28 2495/29 2488/30 +f 2496/16 2497/25 2498/26 2499/15 +f 2499/16 2498/25 2489/26 2490/15 +f 2500/27 2501/30 2502/29 2503/28 +f 2501/27 2488/30 2504/29 2502/28 +f 2505/16 2506/15 2507/26 2508/25 +f 2506/25 2505/26 2509/16 +f 2502/16 2504/15 2510/26 2511/25 +f 2488/35 2489/8 2510/37 2504/36 +f 2512/35 2513/37 2514/36 +f 2515/49 2516/52 2517/51 2518/50 +f 2519/49 2520/51 2521/50 +f 2522/29 2523/32 2524/12 2525/9 +f 2526/29 2527/12 2528/9 +f 2529/29 2530/12 2531/9 +f 2532/29 2529/12 2531/9 +f 2532/29 2533/12 2529/9 +f 2534/29 2533/12 2532/9 +f 2533/9 2534/12 2535/29 +f 2528/29 2535/12 2534/9 +f 2536/29 2537/32 2538/12 2539/9 +f 2539/29 2538/32 2534/12 2540/9 +f 2541/29 2532/9 2531/12 2542/32 +f 2543/29 2544/9 2545/12 2546/32 +f 2534/29 2538/9 2526/12 2528/32 +f 2544/29 2542/9 2547/12 2545/32 +f 2548/29 2549/9 2550/12 2551/32 +f 2552/29 2553/9 2549/12 2548/32 +f 2554/29 2555/9 2556/12 2557/32 +f 2558/29 2557/9 2559/12 2541/32 +f 2523/29 2522/9 2553/12 2552/32 +f 2556/29 2552/9 2548/12 2560/32 +f 2561/29 2562/9 2563/12 2540/32 +f 2564/29 2524/9 2523/12 2555/32 +f 2540/29 2563/9 2565/12 2539/32 +f 2562/29 2551/9 2566/12 2563/32 +f 2541/29 2559/9 2561/12 2532/32 +f 2567/29 2568/9 2569/12 2570/32 +f 2544/29 2558/9 2541/12 2542/32 +f 2555/29 2523/9 2552/12 2556/32 +f 2571/29 2572/9 2564/12 2573/32 +f 2574/29 2554/9 2557/12 2558/32 +f 2572/29 2575/9 2524/12 2564/32 +f 2568/55 2571/1 2573/2 2569/57 +f 2563/29 2566/9 2576/12 2565/32 +f 2522/29 2577/9 2578/12 2553/32 +f 2557/29 2556/9 2560/12 2559/32 +f 2579/29 2580/9 2571/12 2568/32 +f 2573/29 2564/9 2555/12 2554/32 +f 2560/29 2548/9 2551/12 2562/32 +f 2539/29 2565/9 2581/12 2536/32 +f 2570/29 2569/9 2574/12 2543/32 +f 2543/29 2574/9 2558/12 2544/32 +f 2559/29 2560/9 2562/12 2561/32 +f 2569/29 2573/9 2554/12 2574/32 +f 2532/29 2561/9 2540/12 2534/32 +f 2582/29 2583/32 2584/12 2585/9 +f 2586/12 2582/9 2587/29 2588/32 +f 2583/12 2582/9 2586/29 2589/32 +f 2590/8 2591/7 2592/40 2593/37 +f 2594/13 2595/14 2596/15 2597/16 +f 2598/13 2599/15 2600/16 +f 2589/8 2601/37 2602/40 2583/7 +f 2603/66 2604/18 2601/69 2589/65 +f 2605/66 2606/18 2604/69 2603/65 +f 2583/66 2602/18 2607/69 2584/65 +f 2599/13 2608/16 2609/15 2600/14 +f 2607/21 2602/22 2608/23 2599/24 +f 2608/13 2610/16 2611/15 2609/14 +f 2602/21 2601/22 2610/23 2608/24 +f 2610/13 2612/16 2613/15 2611/14 +f 2601/46 2604/36 2612/48 2610/47 +f 2612/13 2614/16 2615/15 2613/14 +f 2604/21 2606/22 2614/23 2612/24 +f 2616/46 2607/36 2599/48 2598/47 +f 2617/13 2618/15 2619/16 +f 2620/29 2588/32 2587/12 2591/9 +f 2617/13 2621/16 2622/15 2618/14 +f 2623/13 2619/14 2618/15 2624/16 +f 2625/29 2626/9 2627/12 2628/32 +f 2627/29 2629/9 2630/12 2631/32 +f 2586/29 2588/9 2625/12 2589/32 +f 2628/29 2627/9 2631/12 2632/32 +f 2588/29 2620/9 2626/12 2625/32 +f 2633/29 2634/9 2635/12 2629/32 +f 2603/29 2628/9 2632/12 2605/32 +f 2626/29 2633/9 2629/12 2627/32 +f 2589/55 2625/1 2628/2 2603/57 +f 2620/29 2636/9 2633/12 2626/32 +f 2591/29 2590/9 2636/12 2620/32 +f 2636/29 2637/9 2634/12 2633/32 +f 2638/66 2590/65 2593/69 2639/18 +f 2585/66 2640/65 2641/69 2642/18 +f 2582/8 2585/7 2642/40 2643/37 +f 2587/66 2582/65 2643/69 2644/18 +f 2591/66 2587/65 2644/69 2592/18 +f 2645/46 2646/36 2647/48 2648/47 +f 2649/13 2650/14 2651/15 2652/16 +f 2648/13 2649/14 2652/15 2653/16 +f 2654/21 2645/22 2648/23 2653/24 +f 2652/13 2651/14 2655/15 2656/16 +f 2653/13 2652/14 2656/15 2657/16 +f 2641/46 2654/36 2653/48 2657/47 +f 2656/13 2655/15 2658/16 +f 2657/13 2656/14 2658/15 2659/16 +f 2642/21 2641/22 2657/23 2659/24 +f 2658/13 2655/15 2660/16 +f 2659/13 2658/14 2660/15 2661/16 +f 2643/46 2642/36 2659/48 2661/47 +f 2660/13 2655/14 2662/15 2663/16 +f 2661/13 2660/14 2663/15 2664/16 +f 2644/21 2643/22 2661/23 2664/24 +f 2663/13 2662/14 2622/15 2665/16 +f 2664/13 2663/14 2665/15 2666/16 +f 2592/46 2644/36 2664/48 2666/47 +f 2667/13 2666/15 2665/16 +f 2667/13 2665/14 2622/15 2621/16 +f 2593/21 2592/22 2666/23 2667/24 +f 2650/13 2594/15 2668/16 +f 2651/13 2650/14 2668/15 2669/16 +f 2651/13 2669/15 2655/16 +f 2622/13 2662/14 2670/15 2618/16 +f 2670/13 2669/14 2597/15 2671/16 +f 2662/13 2655/14 2669/15 2670/16 +f 2618/13 2670/14 2671/15 2624/16 +f 2639/46 2593/36 2667/48 2621/47 +f 2671/13 2597/14 2596/15 2672/16 +f 2673/13 2674/14 2675/15 2676/16 +f 2598/13 2600/14 2674/15 2673/16 +f 2677/21 2616/22 2598/23 2673/24 +f 2678/33 2679/42 2680/43 2681/53 +f 2679/43 2678/53 2682/33 2683/42 +f 2681/52 2680/51 2684/21 2685/86 +f 2686/53 2687/55 2680/1 2679/43 +f 2688/53 2686/55 2679/1 2683/43 +f 2689/72 2684/77 2690/87 2691/6 +f 2684/71 2680/72 2687/6 2690/5 +f 2692/15 2691/71 2693/5 2694/26 +f 2691/15 2690/71 2695/5 2693/26 +f 2690/15 2687/71 2696/5 2695/26 +f 2697/12 2698/42 2699/45 2700/11 +f 2701/43 2702/44 2703/4 2704/1 +f 2704/42 2703/45 2705/44 2706/43 +f 2706/43 2705/44 2707/4 2708/1 +f 2708/42 2707/45 2709/44 2710/43 +f 2710/43 2709/44 2711/4 2712/1 +f 2712/42 2711/45 2702/44 2701/43 +f 2708/43 2713/44 2714/4 2715/1 +f 2715/42 2714/45 2716/44 2717/43 +f 2717/43 2716/44 2718/4 2719/1 +f 2719/42 2718/45 2720/44 2721/43 +f 2721/43 2720/44 2722/4 2723/1 +f 2723/42 2722/45 2713/44 2708/43 +f 2712/1 2724/3 2710/4 +f 2710/1 2724/2 2723/3 2708/4 +f 2704/1 2706/3 2725/4 +f 2706/1 2708/2 2715/3 2725/4 +f 2715/1 2717/3 2725/4 +f 2721/1 2726/2 2727/3 2719/4 +f 2723/1 2726/3 2721/4 +f 2728/49 2729/51 2730/50 +f 2720/49 2728/52 2730/51 2722/50 +f 2730/49 2729/51 2731/50 +f 2722/49 2730/52 2731/51 2713/50 +f 2731/49 2729/51 2732/50 +f 2713/49 2731/52 2732/51 2714/50 +f 2732/49 2729/51 2733/50 +f 2714/49 2732/52 2733/51 2716/50 +f 2733/49 2729/51 2734/50 +f 2716/49 2733/52 2734/51 2718/50 +f 2734/49 2729/51 2728/50 +f 2718/49 2734/52 2728/51 2720/50 +f 2711/49 2735/52 2736/51 2702/50 +f 2703/49 2737/52 2738/51 2705/50 +f 2709/49 2739/52 2735/51 2711/50 +f 2705/49 2738/52 2740/51 2707/50 +f 2702/49 2736/52 2737/51 2703/50 +f 2707/49 2740/52 2739/51 2709/50 +f 2737/49 2736/52 2735/51 2738/50 +f 2735/49 2739/52 2740/51 2738/50 +f 2741/49 2742/52 2743/51 2744/50 +f 2745/87 2746/39 2743/66 2742/73 +f 2747/87 2745/39 2742/66 2741/73 +f 2748/87 2747/39 2741/66 2744/73 +f 2746/87 2748/39 2744/66 2743/73 +f 2749/49 2750/50 2751/51 2752/52 +f 2753/87 2752/73 2751/66 2754/39 +f 2755/87 2749/73 2752/66 2753/39 +f 2756/87 2750/73 2749/66 2755/39 +f 2754/87 2751/73 2750/66 2756/39 +f 2757/1 2758/2 2759/3 2760/4 +f 2761/1 2762/2 2763/3 2764/4 +f 2759/1 2765/2 2766/3 2767/4 +f 2760/1 2759/2 2767/3 2768/4 +f 2769/1 2760/2 2768/3 2770/4 +f 2763/1 2769/2 2770/3 2771/4 +f 2764/1 2763/2 2771/3 2772/4 +f 2773/1 2764/2 2772/3 2774/4 +f 2773/1 2774/3 2775/4 +f 2768/1 2767/2 2776/3 2777/4 +f 2770/1 2768/2 2777/3 2778/4 +f 2771/1 2770/2 2778/3 2779/4 +f 2772/1 2771/2 2779/3 2780/4 +f 2774/1 2772/2 2780/3 2781/4 +f 2775/1 2774/2 2781/3 2782/4 +f 2777/1 2776/2 2727/3 2726/4 +f 2778/1 2777/2 2726/3 2783/4 +f 2779/1 2778/2 2783/3 2784/4 +f 2780/1 2779/2 2784/3 2785/4 +f 2781/1 2780/2 2785/3 2786/4 +f 2782/1 2781/2 2786/3 2787/4 +f 2783/1 2726/2 2723/3 2724/4 +f 2784/1 2783/2 2724/3 2788/4 +f 2785/1 2784/2 2788/3 2789/4 +f 2786/1 2785/2 2789/3 2790/4 +f 2787/1 2786/2 2790/3 2791/4 +f 2788/1 2724/2 2712/3 2792/4 +f 2789/1 2788/2 2792/3 2793/4 +f 2790/1 2789/2 2793/3 2794/4 +f 2791/1 2790/2 2794/3 2795/4 +f 2717/1 2796/2 2797/3 2725/4 +f 2792/1 2712/2 2701/3 2798/4 +f 2793/1 2792/2 2798/3 2799/4 +f 2794/1 2793/2 2799/3 2800/4 +f 2795/1 2794/2 2800/3 2801/4 +f 2800/1 2799/2 2802/3 2803/4 +f 2801/1 2800/2 2803/3 2804/4 +f 2805/13 2806/15 2807/16 +f 2805/13 2808/16 2809/15 2806/14 +f 2808/13 2810/16 2811/15 2809/14 +f 2812/13 2813/14 2814/15 2815/16 +f 2816/73 2817/7 2818/17 +f 2819/73 2816/7 2818/17 +f 2820/73 2819/7 2818/17 +f 2821/65 2822/9 2823/10 2824/69 +f 2822/65 2821/9 2825/10 2826/69 +f 2827/65 2821/9 2824/10 2828/69 +f 2821/65 2827/9 2829/10 2825/69 +f 2825/65 2829/9 2830/10 2831/69 +f 2827/65 2832/9 2833/10 2829/69 +f 2829/65 2833/9 2834/10 2830/69 +f 2832/65 2835/9 2836/10 2833/69 +f 2833/65 2836/9 2837/10 2834/69 +f 2835/65 2822/9 2826/10 2836/69 +f 2838/69 2839/10 2840/65 +f 2838/69 2841/10 2839/65 +f 2838/69 2842/10 2841/65 +f 2843/65 2842/69 2844/10 2845/9 +f 2838/69 2844/10 2842/65 +f 2838/69 2840/10 2844/65 +f 2846/72 2847/6 2848/87 2849/77 +f 2850/71 2851/5 2852/6 2853/72 +f 2854/1 2855/2 2856/3 2857/4 +f 2858/1 2854/2 2857/3 2859/4 +f 2860/1 2858/2 2859/3 2861/4 +f 2862/1 2860/2 2861/3 2863/4 +f 2864/1 2862/2 2863/3 2865/4 +f 2861/1 2859/2 2866/3 2867/4 +f 2868/29 2869/32 2870/12 2871/9 +f 2872/29 2868/32 2871/12 2873/9 +f 2873/29 2871/32 2874/12 2875/9 +f 2875/29 2874/12 2876/9 +f 2872/29 2873/12 2877/9 +f 2872/29 2877/12 2878/9 +f 2879/29 2880/9 2881/12 2882/32 +f 2883/29 2884/9 2880/12 2879/32 +f 2885/29 2886/9 2884/12 2883/32 +f 2887/29 2888/9 2886/12 2885/32 +f 2889/6 2890/7 2881/73 2891/87 +f 2891/6 2881/7 2880/73 2892/87 +f 2892/6 2880/7 2884/73 2893/87 +f 2893/6 2884/7 2886/73 2894/87 +f 2894/6 2886/7 2888/73 2895/87 +f 2895/6 2888/7 2896/73 2897/87 +f 2898/46 2899/36 2900/48 2901/47 +f 2902/21 2898/22 2901/23 2903/24 +f 2879/2 2882/67 2898/59 2902/3 +f 2904/46 2902/36 2903/48 2905/47 +f 2883/2 2879/67 2902/59 2904/3 +f 2906/21 2904/22 2905/23 2907/24 +f 2885/2 2883/67 2904/59 2906/3 +f 2908/46 2906/36 2907/48 2909/47 +f 2887/2 2885/67 2906/59 2908/3 +f 2910/13 2911/14 2912/15 2913/16 +f 2910/13 2913/14 2903/15 2901/16 +f 2913/13 2912/14 2914/15 2915/16 +f 2913/13 2915/14 2905/15 2903/16 +f 2915/13 2914/14 2916/15 2917/16 +f 2915/13 2917/14 2907/15 2905/16 +f 2917/13 2916/14 2918/15 2919/16 +f 2917/13 2919/14 2909/15 2907/16 +f 2919/13 2918/14 2920/15 2921/16 +f 2875/69 2876/10 2891/74 2892/70 +f 2873/69 2875/10 2892/74 2893/70 +f 2877/69 2873/10 2893/74 2894/70 +f 2878/69 2877/10 2894/74 2895/70 +f 2922/29 2923/32 2924/12 2925/9 +f 2923/55 2926/57 2927/2 2924/1 +f 2926/29 2928/32 2929/12 2927/9 +f 2930/12 2931/9 2932/29 2933/32 +f 2933/29 2934/32 2935/12 2930/9 +f 2934/55 2936/57 2937/2 2935/1 +f 2936/29 2938/32 2939/12 2937/9 +f 2938/29 2940/32 2922/12 2939/9 +f 2940/29 2941/32 2923/12 2922/9 +f 2941/29 2942/32 2926/12 2923/9 +f 2942/29 2928/12 2926/9 +f 2943/29 2944/32 2934/12 2933/9 +f 2944/29 2945/32 2936/12 2934/9 +f 2945/29 2946/32 2938/12 2936/9 +f 2946/29 2947/32 2940/12 2938/9 +f 2948/29 2949/32 2945/12 2944/9 +f 2949/29 2950/32 2946/12 2945/9 +f 2951/15 2952/26 2953/5 2954/71 +f 2955/15 2956/26 2957/5 2958/71 +f 2959/69 2960/10 2961/65 +f 2962/69 2959/10 2961/65 +f 2963/69 2962/10 2961/65 +f 2964/69 2963/10 2961/65 +f 2965/69 2964/10 2961/65 +f 2960/69 2965/10 2961/65 +f 2953/65 2960/69 2959/10 2966/9 +f 2966/65 2959/69 2962/10 2956/9 +f 2956/65 2962/69 2963/10 2957/9 +f 2957/65 2963/69 2964/10 2967/9 +f 2967/65 2964/69 2965/10 2952/9 +f 2952/65 2965/69 2960/10 2953/9 +f 2968/13 2969/14 2970/15 2971/16 +f 2971/13 2970/14 2972/15 2973/16 +f 2974/13 2975/14 2976/15 2977/16 +f 2978/13 2979/14 2980/15 2981/16 +f 2976/13 2978/14 2981/15 2982/16 +f 2983/7 2984/8 2985/5 2986/6 +f 2987/29 2988/32 2989/12 2990/9 +f 2991/29 2992/32 2987/12 2990/9 +f 2993/57 2994/50 2995/67 2996/2 +f 2997/54 2998/56 2999/55 3000/53 +f 3001/58 2997/49 3000/50 3002/57 +f 3003/54 3001/56 3002/55 3004/53 +f 3005/7 3006/40 3007/17 3008/73 +f 3009/50 3007/67 3006/68 3010/51 +f 3011/53 3012/55 3013/1 3014/43 +f 3015/8 3001/37 3003/40 3016/7 +f 3017/66 2997/18 3001/69 3015/65 +f 3018/66 2998/18 2997/69 3017/65 +f 3019/13 3020/14 3021/15 3022/16 +f 3023/46 3024/36 3025/48 3026/47 +f 3027/56 3028/58 3023/57 3029/55 +f 3029/21 3023/22 3026/23 3030/24 +f 3031/18 3032/69 3033/70 3034/19 +f 3035/17 3034/20 3033/19 3036/18 +f 3037/66 3038/18 3039/69 3040/65 +f 3041/18 3038/69 3037/66 +f 3042/29 3043/32 3044/12 3045/9 +f 3046/29 3042/32 3045/12 3047/9 +f 3048/29 3046/32 3047/12 3049/9 +f 3049/29 3047/32 3050/12 3051/9 +f 3052/29 3053/12 3054/9 +f 3055/29 3054/32 3043/12 3042/9 +f 3056/29 3055/32 3042/12 3046/9 +f 3057/29 3056/32 3046/12 3048/9 +f 3054/29 3053/32 3058/12 3043/9 +f 3059/7 3060/40 3061/17 3062/73 +f 3063/53 3064/55 3065/1 3066/43 +f 3067/26 3063/5 3066/8 3068/35 +f 3045/86 3044/90 3064/22 3063/21 +f 3069/29 3070/32 3071/12 3072/9 +f 3072/29 3073/12 3074/9 +f 3073/29 3072/32 3071/12 3075/9 +f 3075/29 3071/32 3076/12 3077/9 +f 3077/29 3076/32 3078/12 3079/9 +f 3080/29 3081/12 3082/9 +f 3083/29 3084/12 3080/9 +f 3085/29 3086/32 3077/12 3079/9 +f 3087/29 3088/32 3089/12 3090/9 +f 3090/55 3089/57 3091/2 3092/1 +f 3091/29 3093/12 3094/9 +f 3092/29 3091/32 3094/12 3095/9 +f 3096/29 3097/9 3098/12 3099/32 +f 3100/29 3101/9 3097/12 3096/32 +f 3102/29 3069/9 3101/12 3100/32 +f 3069/12 3102/32 3103/29 3070/9 +f 3104/29 3105/9 3070/12 3103/32 +f 3097/29 3106/9 3107/12 3098/32 +f 3101/29 3108/9 3106/12 3097/32 +f 3069/29 3072/9 3108/12 3101/32 +f 3106/29 3109/9 3110/12 3107/32 +f 3108/29 3111/9 3109/12 3106/32 +f 3072/29 3074/9 3111/12 3108/32 +f 3109/29 3112/9 3113/12 3110/32 +f 3111/29 3114/9 3112/12 3109/32 +f 3112/29 3092/9 3095/12 3113/32 +f 3114/29 3090/9 3092/12 3112/32 +f 3094/8 3115/37 3116/40 3095/7 +f 3117/50 3118/51 3119/68 3120/67 +f 3121/50 3119/51 3118/68 3122/67 +f 3070/2 3105/67 3117/59 3120/3 +f 3071/2 3070/67 3120/59 3119/3 +f 3076/2 3071/67 3119/59 3121/3 +f 3078/2 3076/67 3121/59 3122/3 +f 3082/2 3078/67 3122/59 3118/3 +f 3105/2 3082/67 3118/59 3117/3 +f 3123/50 3124/51 3125/68 3126/67 +f 3127/50 3125/51 3124/68 3128/67 +f 3074/2 3073/67 3123/59 3126/3 +f 3129/2 3074/67 3126/59 3125/3 +f 3086/2 3129/67 3125/59 3127/3 +f 3077/2 3086/67 3127/59 3128/3 +f 3075/2 3077/67 3128/59 3124/3 +f 3073/2 3075/67 3124/59 3123/3 +f 3130/50 3131/51 3132/68 3133/67 +f 3085/2 3079/67 3133/59 3132/3 +f 3134/1 3135/2 3136/3 3137/4 +f 3138/1 3139/2 3140/3 3141/4 +f 3142/1 3138/2 3141/3 3143/4 +f 3144/1 3142/2 3143/3 3145/4 +f 3136/1 3144/2 3145/3 3146/4 +f 3137/1 3136/2 3146/3 3147/4 +f 3141/1 3140/2 3148/3 3149/4 +f 3143/1 3141/2 3149/3 3150/4 +f 3145/1 3143/2 3150/3 3151/4 +f 3146/1 3145/2 3151/3 3152/4 +f 3147/1 3146/2 3152/3 3153/4 +f 3149/1 3148/2 3154/3 3155/4 +f 3150/1 3149/2 3155/3 3156/4 +f 3151/1 3150/2 3156/3 3157/4 +f 3152/1 3151/2 3157/3 3158/4 +f 3153/1 3152/2 3158/3 3159/4 +f 3155/1 3154/2 3160/3 3161/4 +f 3156/1 3155/2 3161/3 3162/4 +f 3157/1 3156/2 3162/3 3163/4 +f 3158/1 3157/2 3163/3 3164/4 +f 3159/1 3158/2 3164/3 3165/4 +f 3161/1 3160/2 3166/3 3167/4 +f 3162/1 3161/2 3167/3 3168/4 +f 3163/1 3162/2 3168/3 3169/4 +f 3164/1 3163/2 3169/3 3170/4 +f 3165/1 3164/2 3170/3 3171/4 +f 3167/1 3166/2 3172/3 3173/4 +f 3168/1 3167/2 3173/3 3174/4 +f 3169/1 3168/2 3174/3 3175/4 +f 3170/1 3169/2 3175/3 3176/4 +f 3171/1 3170/2 3176/3 3177/4 +f 3177/1 3176/2 3178/3 3179/4 +f 3180/29 3181/12 3182/9 +f 3183/57 3184/55 3185/56 3186/58 +f 3180/29 3182/32 3187/12 3188/9 +f 3187/29 3189/12 3190/9 +f 3191/13 3192/14 3193/15 3194/16 +f 3195/58 3196/49 3197/50 3198/57 +f 3194/13 3193/14 3199/15 3200/16 +f 3201/54 3195/56 3198/55 3202/53 +f 3203/58 3201/49 3202/50 3204/57 +f 3205/7 3206/40 3207/17 3208/73 +f 3208/7 3207/40 3209/17 3210/73 +f 3210/7 3209/40 3211/17 3212/73 +f 3213/53 3214/55 3215/1 3216/43 +f 3188/86 3217/90 3218/22 3214/21 +f 3180/86 3188/90 3214/22 3213/21 +f 3187/66 3203/18 3219/69 3189/65 +f 3182/66 3181/65 3195/69 3201/18 +f 3187/8 3182/7 3201/40 3203/37 +f 3220/44 3221/4 3222/64 3223/89 +f 3224/40 3225/17 3221/20 3220/41 +f 3226/18 3227/19 3228/70 3229/69 +f 3227/18 3226/19 3230/70 3231/69 +f 3232/18 3233/69 3234/70 3235/19 +f 3236/17 3237/18 3230/19 3226/20 +f 3226/17 3229/18 3225/19 3236/20 +f 3232/17 3238/20 3224/19 3233/18 +f 3239/12 3240/9 3241/29 3242/32 +f 3243/29 3244/32 3242/12 3241/9 +f 3244/29 3245/32 3246/12 3242/9 +f 3245/55 3247/57 3248/2 3246/1 +f 3249/55 3250/57 3243/2 3251/1 +f 3250/29 3252/32 3244/12 3243/9 +f 3252/29 3253/32 3245/12 3244/9 +f 3253/29 3254/32 3247/12 3245/9 +f 3255/29 3256/32 3249/12 3257/9 +f 3256/29 3258/32 3250/12 3249/9 +f 3258/29 3259/32 3252/12 3250/9 +f 3259/29 3260/32 3253/12 3252/9 +f 3260/29 3261/32 3254/12 3253/9 +f 3262/29 3263/32 3256/12 3255/9 +f 3263/29 3264/32 3258/12 3256/9 +f 3264/29 3265/32 3259/12 3258/9 +f 3265/29 3266/32 3260/12 3259/9 +f 3266/55 3267/57 3261/2 3260/1 +f 3268/29 3269/32 3263/12 3262/9 +f 3269/29 3270/32 3264/12 3263/9 +f 3270/29 3271/32 3265/12 3264/9 +f 3271/29 3272/32 3266/12 3265/9 +f 3272/29 3273/32 3267/12 3266/9 +f 3274/29 3275/32 3269/12 3268/9 +f 3275/29 3276/32 3270/12 3269/9 +f 3276/29 3277/32 3271/12 3270/9 +f 3277/29 3278/32 3272/12 3271/9 +f 3278/29 3279/32 3273/12 3272/9 +f 3279/29 3280/32 3281/12 3273/9 +f 3282/29 3283/32 3275/12 3274/9 +f 3283/29 3284/32 3276/12 3275/9 +f 3285/58 3286/49 3287/50 3288/57 +f 3289/54 3285/56 3288/55 3290/53 +f 3291/58 3289/49 3290/50 3292/57 +f 3288/56 3287/58 3293/57 3294/55 +f 3290/34 3288/54 3294/53 3295/33 +f 3292/56 3290/58 3295/57 3296/55 +f 3297/56 3294/55 3293/57 3298/58 +f 3299/34 3295/33 3294/53 3297/54 +f 3300/56 3296/55 3295/57 3299/58 +f 3301/34 3302/54 3297/53 3298/33 +f 3302/56 3303/58 3299/57 3297/55 +f 3303/34 3304/54 3300/53 3299/33 +f 3305/56 3306/55 3300/57 3304/58 +f 3301/34 3307/33 3308/53 3302/54 +f 3303/56 3302/58 3308/57 3309/55 +f 3303/34 3309/33 3310/53 3304/54 +f 3305/56 3304/58 3310/57 3311/55 +f 3312/54 3313/56 3308/55 3307/53 +f 3314/58 3309/57 3308/50 3313/49 +f 3314/54 3315/56 3310/55 3309/53 +f 3316/35 3317/37 3318/36 +f 3319/85 3316/35 3315/36 3314/46 +f 3316/85 3319/35 3289/36 3291/46 +f 3320/85 3319/35 3314/36 3313/46 +f 3319/85 3320/35 3285/36 3289/46 +f 3318/10 3321/74 3311/84 3322/11 +f 3323/54 3324/56 3325/55 3326/53 +f 3327/58 3323/49 3326/50 3328/57 +f 3329/54 3327/56 3328/55 3330/53 +f 3328/56 3326/58 3331/57 3332/55 +f 3330/34 3328/54 3332/53 3333/33 +f 3334/56 3332/55 3331/57 3335/58 +f 3336/34 3333/33 3332/53 3334/54 +f 3337/34 3338/54 3334/53 3335/33 +f 3336/34 3334/53 3338/33 +f 3338/56 3339/58 3340/57 3336/55 +f 3339/34 3341/54 3342/53 3340/33 +f 3337/34 3343/33 3344/53 3338/54 +f 3339/56 3338/58 3344/57 3345/55 +f 3339/34 3345/33 3346/53 3341/54 +f 3347/54 3348/56 3344/55 3343/53 +f 3349/58 3345/57 3344/50 3348/49 +f 3349/54 3350/56 3346/55 3345/53 +f 3351/85 3352/35 3349/36 3348/46 +f 3351/36 3348/85 3353/35 +f 3351/85 3353/35 3327/36 3329/46 +f 3354/85 3353/35 3348/36 3347/46 +f 3323/36 3327/46 3353/85 3354/35 +f 3352/85 3355/35 3350/36 3349/46 +f 3356/13 3357/16 3358/15 3359/14 +f 3356/16 3359/15 3360/13 +f 3361/13 3362/16 3357/15 3363/14 +f 3356/15 3357/14 3362/13 3364/16 +f 3360/15 3356/14 3364/13 3365/16 +f 3365/13 3366/16 3367/15 3360/14 +f 3368/46 3366/47 3365/48 3369/36 +f 3366/13 3370/16 3371/15 3367/14 +f 3372/21 3370/24 3366/23 3368/22 +f 3373/49 3374/50 3372/51 3368/52 +f 3375/56 3374/55 3373/57 3376/58 +f 3374/49 3377/50 3378/51 3372/52 +f 3379/56 3377/55 3374/57 3375/58 +f 3380/66 3381/65 3382/69 3383/18 +f 3384/13 3359/14 3360/15 3385/16 +f 3386/13 3384/14 3385/15 3387/16 +f 3382/46 3388/36 3386/48 3387/47 +f 3385/13 3360/14 3367/15 3389/16 +f 3387/13 3385/14 3389/15 3390/16 +f 3383/21 3382/22 3387/23 3390/24 +f 3390/13 3389/14 3391/15 3392/16 +f 3393/46 3383/36 3390/48 3392/47 +f 3392/13 3391/14 3394/15 3395/16 +f 3396/21 3393/22 3392/23 3395/24 +f 3394/13 3397/14 3398/15 3399/16 +f 3395/13 3394/14 3399/15 3400/16 +f 3401/46 3396/36 3395/48 3400/47 +f 3399/13 3398/14 3402/15 3403/16 +f 3400/13 3399/14 3403/15 3404/16 +f 3405/21 3401/22 3400/23 3404/24 +f 3404/13 3403/14 3406/15 3407/16 +f 3408/46 3405/36 3404/48 3407/47 +f 3409/44 3410/89 3411/64 3412/4 +f 3413/44 3414/89 3415/64 3416/4 +f 3417/40 3413/41 3416/20 3418/17 +f 3419/18 3420/19 3421/70 3422/69 +f 3420/18 3419/19 3423/70 3424/69 +f 3419/17 3422/18 3417/19 3425/20 +f 3426/28 3427/29 3428/9 3429/65 +f 3430/53 3431/55 3426/1 3432/43 +f 3433/35 3434/8 3435/37 3436/36 +f 3437/35 3433/8 3436/37 3438/36 +f 3439/13 3440/14 3441/15 3442/16 +f 3442/13 3441/14 3443/15 3444/16 +f 3445/13 3442/14 3444/15 3446/16 +f 3447/13 3445/14 3446/15 3448/16 +f 3449/13 3447/14 3448/15 3450/16 +f 3451/35 3452/8 3453/37 3454/36 +f 3455/35 3451/8 3454/37 3456/36 +f 3457/35 3458/36 3459/37 3460/8 +f 3461/35 3462/36 3458/37 3457/8 +f 3463/35 3453/36 3462/37 3461/8 +f 3464/35 3454/36 3453/37 3463/8 +f 3465/35 3456/36 3454/37 3464/8 +f 3452/35 3466/8 3462/37 3453/36 +f 3466/35 3467/8 3458/37 3462/36 +f 3467/35 3468/8 3459/37 3458/36 +f 3469/24 3470/23 3471/21 +f 3472/29 3473/9 3474/12 3475/32 +f 3476/71 3477/72 3478/6 3479/5 +f 3480/10 3469/65 3471/9 +f 3480/10 3481/65 3482/9 +f 3480/10 3471/65 3481/9 +f 3483/15 3481/26 3471/5 3484/71 +f 3479/15 3482/26 3481/5 3483/71 +f 3476/67 3479/59 3483/60 3475/68 +f 3475/67 3483/59 3484/60 3472/68 +f 3485/73 3486/17 3478/18 3477/66 +f 3487/29 3488/12 3489/9 +f 3490/29 3487/12 3489/9 +f 3491/29 3492/12 3493/9 +f 3494/29 3488/12 3495/9 +f 3496/29 3497/32 3498/12 3499/9 +f 3496/29 3499/12 3492/9 +f 3488/78 3492/75 3491/72 3495/71 +f 3487/78 3496/75 3492/72 3488/71 +f 3496/77 3487/72 3490/75 3497/76 +f 3500/29 3501/12 3494/9 +f 3502/29 3503/12 3504/9 +f 3505/29 3506/9 3499/12 3498/32 +f 3506/29 3493/9 3492/12 3499/32 +f 3495/29 3507/9 3500/12 3494/32 +f 3501/29 3508/9 3509/12 3504/32 +f 3500/29 3510/9 3508/12 3501/32 +f 3507/29 3511/9 3510/12 3500/32 +f 3507/57 3512/1 3511/55 +f 3510/29 3513/9 3514/12 3508/32 +f 3511/29 3515/9 3513/12 3510/32 +f 3516/83 3517/89 3518/45 +f 3519/29 3520/32 3521/12 3522/9 +f 3523/29 3519/32 3522/12 3524/9 +f 3524/29 3522/32 3525/12 3526/9 +f 3527/55 3528/1 3529/2 3530/57 +f 3523/29 3524/9 3528/12 3527/32 +f 3524/29 3526/9 3531/12 3528/32 +f 3532/45 3533/44 3534/89 3535/83 +f 3536/45 3532/44 3535/89 3537/83 +f 3518/45 3536/44 3537/89 3516/83 +f 3518/29 3538/12 3536/9 +f 3539/35 3540/37 3541/36 +f 3542/35 3543/8 3540/37 3539/36 +f 3544/45 3545/44 3543/89 3542/83 +f 3546/4 3547/64 3542/63 3539/3 +f 3544/45 3542/83 3547/89 3548/44 +f 3548/45 3547/83 3549/89 3550/44 +f 3551/26 3552/5 3553/8 3554/35 +f 3540/45 3555/83 3556/89 3541/44 +f 3543/45 3557/83 3555/89 3540/44 +f 3530/66 3529/65 3544/69 3548/18 +f 3558/8 3530/7 3548/40 3550/37 +f 3534/17 3556/20 3555/19 3535/18 +f 3535/17 3555/20 3557/19 3537/18 +f 3537/17 3557/20 3517/19 3516/18 +f 3559/12 3560/9 3561/29 3562/32 +f 3563/29 3561/32 3560/12 3564/9 +f 3565/13 3566/14 3567/15 3568/16 +f 3566/13 3569/15 3567/16 +f 3566/13 3565/14 3570/15 3571/16 +f 3565/13 3572/14 3573/15 3570/16 +f 3574/46 3575/36 3571/48 3570/47 +f 3576/21 3574/22 3570/23 3573/24 +f 3577/46 3576/36 3573/48 3578/47 +f 3565/13 3568/14 3579/15 3572/16 +f 3579/13 3580/14 3581/15 3582/16 +f 3572/13 3579/14 3582/15 3583/16 +f 3572/13 3583/14 3578/15 3573/16 +f 3583/13 3582/14 3584/15 3585/16 +f 3568/29 3586/32 3580/12 3579/9 +f 3587/88 3588/41 3589/37 +f 3590/36 3588/48 3587/88 3591/37 +f 3592/51 3593/21 3588/24 3590/68 +f 3594/65 3595/10 3596/69 +f 3595/69 3597/9 3596/10 +f 3595/9 3594/69 3598/65 +f 3597/65 3595/10 3598/69 +f 3594/65 3596/10 3598/69 +f 3596/69 3597/9 3598/10 +f 3599/25 3600/85 3591/35 3601/26 +f 3602/24 3603/23 3604/82 3600/79 +f 3600/24 3604/23 3590/82 3591/79 +f 3592/25 3590/85 3604/35 3605/26 +f 3606/25 3607/85 3608/35 3609/26 +f 3610/29 3593/9 3606/12 3609/32 +f 3592/29 3605/9 3606/12 3593/32 +f 3611/71 3612/5 3613/6 3614/72 +f 3615/71 3616/5 3612/6 3611/72 +f 3617/71 3618/5 3616/6 3615/72 +f 3619/52 3620/86 3613/21 3612/51 +f 3621/26 3622/35 3623/8 3624/5 +f 3625/33 3621/42 3624/43 3626/53 +f 3624/53 3623/43 3614/1 3613/55 +f 3626/33 3624/42 3613/43 3620/53 +f 3616/13 3627/14 3628/15 3629/16 +f 3627/13 3630/14 3631/15 3628/16 +f 3631/13 3630/15 3632/16 +f 3633/29 3634/32 3635/12 3636/9 +f 3637/29 3638/12 3639/9 +f 3640/54 3641/56 3642/55 3643/53 +f 3634/66 3641/18 3640/69 3635/65 +f 3644/9 3645/10 3646/11 3647/12 +f 3648/9 3647/12 3646/11 3649/10 +f 3650/9 3648/10 3651/11 3652/12 +f 3653/9 3652/12 3651/11 3644/10 +f 3654/9 3649/65 3655/10 +f 3646/65 3656/69 3655/10 3649/9 +f 3657/10 3645/65 3658/9 +f 3646/65 3645/9 3657/10 3656/69 +f 3657/65 3659/69 3660/10 3656/9 +f 3661/65 3659/69 3657/10 3658/9 +f 3662/7 3663/73 3664/17 3665/40 +f 3666/15 3667/71 3668/5 3663/26 +f 3667/15 3669/71 3670/5 3668/26 +f 3671/7 3672/17 3665/40 +f 3671/7 3665/17 3664/40 +f 3663/7 3668/73 3673/17 3664/40 +f 3667/71 3666/72 3674/6 3675/5 +f 3675/72 3676/77 3669/87 3667/6 +f 3668/7 3670/73 3677/17 3673/40 +f 3671/7 3664/17 3673/40 +f 3671/7 3673/17 3677/40 +f 3670/7 3678/73 3679/17 3677/40 +f 3671/7 3677/17 3679/40 +f 3671/7 3679/17 3672/40 +f 3680/52 3681/86 3674/21 3682/51 +f 3682/71 3674/72 3666/6 3683/5 +f 3683/15 3666/71 3663/5 3662/26 +f 3684/66 3685/65 3686/69 3687/18 +f 3688/71 3689/5 3690/6 3691/72 +f 3689/15 3692/26 3693/5 3690/71 +f 3694/7 3695/40 3696/17 3692/73 +f 3692/7 3696/40 3697/17 3693/73 +f 3690/15 3693/26 3698/5 3699/71 +f 3699/15 3698/26 3700/5 3701/71 +f 3696/40 3695/17 3702/7 +f 3697/40 3696/17 3702/7 +f 3693/7 3697/40 3703/17 3698/73 +f 3691/71 3690/5 3699/6 3704/72 +f 3704/72 3699/6 3701/87 3705/77 +f 3706/71 3707/5 3705/6 3701/72 +f 3698/7 3703/40 3708/17 3700/73 +f 3703/40 3697/17 3702/7 +f 3708/40 3703/17 3702/7 +f 3709/52 3705/51 3707/21 3710/86 +f 3711/40 3708/17 3702/7 +f 3695/40 3711/17 3702/7 +f 3712/58 3713/57 3714/50 3715/49 +f 3713/50 3712/49 3716/58 3717/57 +f 3718/58 3719/57 3717/50 3716/49 +f 3720/49 3721/50 3722/51 3723/52 +f 3713/56 3721/55 3720/57 3714/58 +f 3721/49 3724/50 3725/51 3722/52 +f 3717/56 3724/55 3721/57 3713/58 +f 3719/56 3726/55 3724/57 3717/58 +f 3716/4 3712/44 3727/43 3728/1 +f 3728/42 3729/43 3718/44 3716/45 +f 3730/1 3731/2 3732/3 3733/4 +f 3734/1 3730/2 3733/3 3735/4 +f 3736/1 3734/2 3735/3 3737/4 +f 3738/1 3736/2 3737/3 3739/4 +f 3727/1 3738/2 3739/3 3740/4 +f 3728/1 3727/2 3740/3 3729/4 +f 3741/25 3742/85 3743/35 3744/26 +f 3744/25 3743/85 3745/35 3746/26 +f 3747/24 3745/79 3748/82 3749/23 +f 3750/29 3751/12 3746/9 +f 3746/9 3751/12 3744/29 +f 3744/29 3751/12 3741/9 +f 3746/25 3745/85 3747/35 3750/26 +f 3752/29 3753/32 3751/12 3750/9 +f 3751/8 3753/7 3754/40 3755/37 +f 3741/66 3751/65 3755/69 3742/18 +f 3756/13 3757/14 3758/15 3759/16 +f 3760/46 3761/36 3757/48 3756/47 +f 3754/34 3762/54 3761/53 3760/33 +f 3763/13 3764/14 3765/15 3758/16 +f 3760/57 3766/55 3755/56 3754/58 +f 3757/13 3767/14 3763/15 3758/16 +f 3761/21 3768/22 3767/23 3757/24 +f 3769/14 3770/16 3771/13 +f 3771/13 3770/14 3764/15 3763/16 +f 3758/13 3765/14 3772/15 3759/16 +f 3773/13 3774/14 3775/15 3776/16 +f 3775/13 3777/15 3776/16 +f 3778/16 3777/15 3775/13 +f 3779/13 3777/14 3778/15 3780/16 +f 3781/13 3779/14 3780/15 3782/16 +f 3783/13 3784/14 3785/15 3786/16 +f 3787/21 3788/22 3789/23 3790/24 +f 3788/46 3791/36 3792/48 3789/47 +f 3791/46 3793/36 3794/48 3792/47 +f 3795/13 3783/16 3786/15 3796/14 +f 3794/13 3797/16 3783/15 3795/14 +f 3793/21 3798/22 3797/23 3794/24 +f 3799/66 3800/65 3793/69 3791/18 +f 3800/8 3801/7 3798/40 3793/37 +f 3801/66 3802/65 3803/69 3798/18 +f 3804/13 3805/15 3778/16 +f 3804/13 3778/14 3775/15 3806/16 +f 3807/13 3784/14 3783/15 3797/16 +f 3806/13 3775/14 3774/15 3785/16 +f 3798/46 3803/36 3807/48 3797/47 +f 3785/13 3774/14 3808/15 3786/16 +f 3809/13 3810/14 3811/15 3812/16 +f 3810/13 3813/15 3811/16 +f 3814/13 3813/15 3810/16 +f 3815/13 3816/15 3817/16 +f 3811/13 3815/14 3817/15 3812/16 +f 3813/13 3815/15 3811/16 +f 3818/13 3819/14 3813/15 3820/16 +f 3821/9 3822/10 3823/11 3824/12 +f 3821/9 3825/12 3826/11 3822/10 +f 3827/9 3824/12 3823/11 3828/10 +f 3827/9 3828/10 3826/11 3825/12 +f 3829/9 3830/65 3831/10 +f 3832/65 3833/69 3831/10 3830/9 +f 3834/13 3835/15 3836/16 +f 3834/15 3836/16 3837/13 3838/14 +f 3839/29 3840/12 3841/9 +f 3839/29 3841/12 3842/9 +f 3843/29 3839/12 3842/9 +f 3843/29 3842/12 3844/9 +f 3845/29 3843/12 3844/9 +f 3845/29 3844/12 3846/9 +f 3847/29 3848/32 3849/12 3850/9 +f 3851/29 3852/32 3853/12 3854/9 +f 3855/29 3856/9 3857/12 3858/32 +f 3859/29 3860/9 3856/12 3855/32 +f 3861/29 3839/9 3860/12 3859/32 +f 3862/29 3840/9 3839/12 3861/32 +f 3856/29 3863/9 3864/12 3857/32 +f 3860/29 3865/9 3863/12 3856/32 +f 3839/29 3843/9 3865/12 3860/32 +f 3866/29 3867/9 3868/12 3869/32 +f 3863/29 3870/9 3871/12 3864/32 +f 3865/29 3872/9 3870/12 3863/32 +f 3843/29 3873/9 3872/12 3865/32 +f 3845/55 3874/1 3873/2 3843/57 +f 3875/29 3853/9 3874/12 3845/32 +f 3870/29 3876/9 3877/12 3871/32 +f 3872/29 3878/9 3876/12 3870/32 +f 3873/29 3879/9 3878/12 3872/32 +f 3874/29 3880/9 3879/12 3873/32 +f 3853/29 3852/9 3880/12 3874/32 +f 3848/29 3866/9 3869/12 3849/32 +f 3881/29 3882/9 3866/12 3848/32 +f 3882/29 3883/9 3867/12 3866/32 +f 3867/29 3859/9 3855/12 3868/32 +f 3883/29 3861/9 3859/12 3867/32 +f 3884/29 3862/9 3861/12 3883/32 +f 3871/29 3877/32 3885/12 3886/9 +f 3871/29 3886/12 3864/9 +f 3855/29 3858/12 3887/9 +f 3855/29 3887/12 3868/9 +f 3849/66 3888/18 3889/69 3850/65 +f 3869/8 3890/37 3888/40 3849/7 +f 3868/66 3891/18 3890/69 3869/65 +f 3887/66 3892/18 3891/69 3868/65 +f 3858/66 3893/18 3892/69 3887/65 +f 3857/8 3894/37 3893/40 3858/7 +f 3864/66 3895/18 3894/69 3857/65 +f 3886/66 3896/18 3895/69 3864/65 +f 3885/66 3897/18 3896/69 3886/65 +f 3898/13 3899/16 3900/15 3901/14 +f 3900/13 3902/16 3903/15 3904/14 +f 3899/13 3905/16 3902/15 3900/14 +f 3906/13 3907/16 3905/15 3899/14 +f 3889/46 3888/36 3907/48 3906/47 +f 3902/13 3908/16 3909/15 3903/14 +f 3905/13 3910/16 3908/15 3902/14 +f 3907/13 3911/16 3910/15 3905/14 +f 3888/21 3890/22 3911/23 3907/24 +f 3908/13 3912/16 3913/15 3909/14 +f 3910/13 3914/16 3912/15 3908/14 +f 3911/13 3915/16 3914/15 3910/14 +f 3890/46 3891/36 3915/48 3911/47 +f 3912/13 3916/16 3917/15 3913/14 +f 3914/13 3918/16 3916/15 3912/14 +f 3915/13 3919/16 3918/15 3914/14 +f 3891/21 3892/22 3919/23 3915/24 +f 3916/13 3920/16 3921/15 3917/14 +f 3918/13 3922/16 3920/15 3916/14 +f 3919/13 3923/16 3922/15 3918/14 +f 3892/46 3893/36 3923/48 3919/47 +f 3920/13 3924/16 3835/15 3921/14 +f 3922/13 3925/16 3924/15 3920/14 +f 3923/13 3926/16 3925/15 3922/14 +f 3893/21 3894/22 3926/23 3923/24 +f 3924/13 3927/16 3836/15 3835/14 +f 3925/13 3928/16 3927/15 3924/14 +f 3926/13 3929/16 3928/15 3925/14 +f 3894/46 3895/36 3929/48 3926/47 +f 3927/13 3930/16 3837/15 3836/14 +f 3928/13 3931/16 3930/15 3927/14 +f 3929/13 3932/16 3931/15 3928/14 +f 3895/21 3896/22 3932/23 3929/24 +f 3932/13 3933/16 3934/15 3931/14 +f 3896/46 3897/36 3933/48 3932/47 +f 3935/17 3936/18 3937/19 3938/20 +f 3939/17 3940/18 3941/19 3942/20 +f 3942/17 3941/18 3935/19 3938/20 +f 3939/69 3846/10 3943/74 3942/70 +f 3944/17 3938/20 3942/19 3943/18 +f 3938/17 3945/20 3946/19 3942/18 +f 3939/69 3942/70 3946/74 3841/10 +f 3847/29 3947/9 3881/12 3848/32 +f 3947/29 3948/9 3949/12 3881/32 +f 3937/17 3950/20 3945/19 3938/18 +f 3844/69 3842/10 3951/74 3952/70 +f 3953/17 3952/18 3951/19 3954/20 +f 3955/17 3953/18 3954/19 3956/20 +f 3950/40 3957/17 3958/20 3956/41 +f 3953/18 3944/19 3943/70 3952/69 +f 3846/69 3844/10 3952/74 3943/70 +f 3945/18 3950/69 3956/70 3954/19 +f 3954/18 3951/69 3946/70 3945/19 +f 3841/69 3946/70 3951/74 3842/10 +f 3959/71 3960/72 3961/6 3962/5 +f 3963/7 3964/40 3965/17 3966/73 +f 3966/7 3965/40 3967/17 3968/73 +f 3965/50 3964/51 3969/68 3967/67 +f 3970/50 3971/67 3969/68 3964/51 +f 3972/28 3973/29 3974/9 3975/65 +f 3973/28 3976/29 3977/9 3974/65 +f 3978/29 3979/32 3980/12 3981/9 +f 3982/29 3983/9 3984/12 3985/32 +f 3985/29 3984/9 3986/12 3987/32 +f 3980/66 3988/65 3989/69 3990/18 +f 3986/66 3991/18 3992/69 3987/65 +f 3991/45 3993/83 3994/89 3992/44 +f 3995/45 3996/83 3993/89 3991/44 +f 3997/45 3998/83 3996/89 3995/44 +f 3999/66 4000/18 3997/69 4001/65 +f 4000/45 4002/83 3998/89 3997/44 +f 4003/13 4004/16 4005/15 4006/14 +f 4007/13 4008/16 4004/15 4003/14 +f 4008/47 4007/48 4009/46 +f 4005/13 4010/16 4011/15 4012/14 +f 4004/13 4013/16 4010/15 4005/14 +f 4008/13 4014/16 4013/15 4004/14 +f 4015/21 4014/24 4008/23 4009/22 +f 4016/13 4007/16 4003/15 4017/14 +f 4010/13 4018/16 4019/15 4011/14 +f 4013/13 4020/16 4018/15 4010/14 +f 4014/13 4021/16 4020/15 4013/14 +f 4022/46 4021/47 4014/48 4015/36 +f 4006/13 4005/16 4012/15 4023/14 +f 4024/35 4022/8 4015/37 4025/36 +f 4025/35 4015/8 4009/37 4026/36 +f 4026/35 4009/8 4007/37 4027/36 +f 4028/71 4029/72 4030/6 4031/5 +f 4032/71 4028/72 4031/6 4033/5 +f 4031/71 4030/72 4034/6 4035/5 +f 4033/71 4031/72 4035/6 4016/5 +f 4036/71 4033/72 4016/6 4037/5 +f 4038/52 4035/51 4034/21 4039/86 +f 4040/52 4016/51 4035/21 4038/86 +f 4030/28 4029/65 4041/9 4042/29 +f 4034/53 4030/43 4042/1 4043/55 +f 4027/35 4007/37 4016/36 +f 4038/29 4044/12 4040/9 +f 4040/66 4044/65 4027/69 4016/18 +f 4045/66 4046/65 4024/69 4025/18 +f 4047/8 4045/7 4025/40 4026/37 +f 4044/66 4047/65 4026/69 4027/18 +f 4048/29 3978/9 3981/12 4046/32 +f 4002/6 4048/7 4049/73 3998/87 +f 4046/29 4045/9 4049/12 4048/32 +f 3998/6 4049/7 4050/73 3996/87 +f 4045/29 4047/9 4050/12 4049/32 +f 3996/6 4050/7 4051/73 3993/87 +f 4047/29 4044/9 4051/12 4050/32 +f 3993/6 4051/7 4052/73 3994/87 +f 4044/29 4038/9 4052/12 4051/32 +f 4053/15 4054/71 4055/5 4056/26 +f 4054/15 4057/71 4058/5 4055/26 +f 4059/44 4060/1 4061/4 +f 4062/43 4060/1 4059/4 4063/44 +f 4064/42 4062/43 4063/44 4065/45 +f 4066/43 4067/42 4068/44 +f 4066/43 4068/44 4069/4 4070/1 +f 4071/42 4070/43 4069/44 4072/45 +f 4073/1 4074/3 4066/4 +f 4070/1 4075/2 4073/3 4066/4 +f 4076/1 4077/3 4071/4 +f 4071/1 4077/2 4075/3 4070/4 +f 4078/49 4079/51 4080/50 +f 4080/49 4079/51 4081/50 +f 4082/49 4080/52 4081/51 4083/50 +f 4081/49 4079/51 4084/50 +f 4083/49 4081/52 4084/51 4065/50 +f 4084/49 4079/51 4085/50 +f 4085/49 4079/51 4086/50 +f 4086/49 4079/51 4078/50 +f 4087/49 4088/51 4089/50 +f 4089/49 4088/51 4090/50 +f 4091/49 4088/51 4087/50 +f 4090/49 4088/51 4092/50 +f 4083/49 4090/52 4092/51 4082/50 +f 4092/49 4088/51 4093/50 +f 4082/49 4092/52 4093/51 4094/50 +f 4093/49 4088/51 4091/50 +f 4061/49 4095/52 4096/51 4059/50 +f 4096/49 4097/51 4098/50 +f 4059/49 4096/52 4098/51 4063/50 +f 4098/49 4097/51 4099/50 +f 4063/49 4098/52 4099/51 4065/50 +f 4099/49 4097/51 4100/50 +f 4065/49 4099/52 4100/51 4083/50 +f 4100/49 4097/51 4101/50 +f 4095/49 4097/51 4096/50 +f 4101/49 4097/51 4095/50 +f 4089/49 4090/52 4100/51 4101/50 +f 4083/49 4100/51 4090/50 +f 4102/49 4103/51 4104/50 +f 4105/49 4102/52 4104/51 4106/50 +f 4069/49 4105/52 4106/51 4072/50 +f 4104/49 4103/51 4107/50 +f 4106/49 4104/52 4107/51 4108/50 +f 4107/49 4103/51 4109/50 +f 4108/49 4107/52 4109/51 4110/50 +f 4109/49 4103/51 4111/50 +f 4110/49 4109/52 4111/51 4112/50 +f 4111/49 4103/51 4113/50 +f 4112/49 4111/52 4113/51 4114/50 +f 4113/49 4103/51 4102/50 +f 4114/49 4113/52 4102/51 4105/50 +f 4068/49 4114/52 4105/51 4069/50 +f 4115/1 4116/2 4073/3 4075/4 +f 4117/1 4115/2 4075/3 4077/4 +f 4118/1 4117/2 4077/3 4119/4 +f 4120/1 4118/2 4119/3 4121/4 +f 4122/1 4120/2 4121/3 4123/4 +f 4124/1 4122/2 4123/3 4125/4 +f 4126/1 4127/2 4128/3 4129/4 +f 4130/1 4126/2 4129/3 4131/4 +f 4132/1 4130/2 4131/3 4133/4 +f 4134/1 4135/2 4136/3 4137/4 +f 4138/1 4134/2 4137/3 4139/4 +f 4140/1 4138/2 4139/3 4141/4 +f 4076/3 4060/4 4119/1 4077/2 +f 4060/3 4062/4 4121/1 4119/2 +f 4123/1 4121/2 4062/3 4064/4 +f 4125/1 4123/2 4064/3 4142/4 +f 4143/1 4132/2 4133/3 4144/4 +f 4145/1 4143/2 4144/3 4146/4 +f 4137/1 4136/2 4118/3 4120/4 +f 4139/1 4137/2 4120/3 4122/4 +f 4141/1 4139/2 4122/3 4124/4 +f 4147/1 4148/2 4116/3 4115/4 +f 4127/1 4149/2 4150/3 4128/4 +f 4151/1 4141/2 4124/3 4152/4 +f 4153/1 4154/2 4148/3 4147/4 +f 4155/1 4153/2 4147/3 4156/4 +f 4135/1 4155/2 4156/3 4136/4 +f 4157/1 4158/2 4126/3 4130/4 +f 4128/1 4150/2 4154/3 4153/4 +f 4159/1 4160/2 4143/3 4145/4 +f 4129/1 4128/2 4153/3 4155/4 +f 4156/1 4147/2 4115/3 4117/4 +f 4136/1 4156/2 4117/3 4118/4 +f 4131/1 4129/2 4155/3 4135/4 +f 4133/1 4131/2 4135/3 4134/4 +f 4144/1 4133/2 4134/3 4138/4 +f 4146/1 4144/2 4138/3 4140/4 +f 4161/6 4162/87 4163/73 4164/7 +f 4164/29 4163/32 4165/12 4166/9 +f 4167/13 4168/14 4169/15 4170/16 +f 4171/13 4167/14 4170/15 4172/16 +f 4173/13 4168/14 4167/15 4174/16 +f 4163/54 4162/56 4175/55 4176/53 +f 4171/13 4172/14 4177/15 4178/16 +f 4179/4 4180/3 4181/1 +f 2/1 4182/2 4183/3 3/4 +f 4184/1 13/2 14/3 4185/4 +f 3/1 4183/2 4186/3 15/4 +f 6/1 4/2 16/3 972/4 +f 8/1 6/2 972/3 971/4 +f 10/1 8/2 971/3 17/4 +f 14/1 12/2 18/3 4187/4 +f 4185/1 14/2 4187/3 4188/4 +f 1421/9 4189/12 4190/29 +f 696/29 697/9 4191/12 694/32 +f 697/55 4190/1 4189/2 4191/57 +f 4192/13 4193/14 48/15 4194/16 +f 1720/21 4195/22 4193/23 4192/24 +f 4195/46 1408/36 1409/48 4193/47 +f 4193/13 1409/14 49/15 48/16 +f 29/5 27/6 28/7 1418/8 +f 35/5 29/6 1418/7 1417/8 +f 4196/3 26/59 25/62 4197/63 +f 1420/3 28/59 26/62 4196/63 +f 1419/3 1418/59 28/62 1420/63 +f 4189/2 4196/3 4197/59 4191/67 +f 1421/2 1420/3 4196/59 4189/67 +f 19/5 4198/8 4199/7 22/6 +f 4198/7 19/6 32/5 1719/8 +f 31/5 35/6 1417/7 4200/8 +f 32/5 31/6 4200/7 1719/8 +f 34/1 20/4 22/3 4201/2 +f 40/9 3821/10 3824/11 41/12 +f 40/9 44/12 3825/11 3821/10 +f 47/9 41/12 3824/11 3827/10 +f 47/9 3827/10 3825/11 44/12 +f 4202/21 4203/22 50/23 4204/24 +f 4202/46 4204/47 3814/48 4205/36 +f 49/13 4204/15 50/16 +f 4194/13 48/14 51/15 4206/16 +f 4200/66 1417/65 1408/69 4195/18 +f 1719/66 4200/65 4195/69 1720/18 +f 52/13 883/14 885/15 53/16 +f 57/13 54/14 56/15 4207/16 +f 57/13 4207/14 4208/15 64/16 +f 4209/47 3305/48 4210/46 +f 3318/6 3317/87 4211/73 4212/7 +f 3306/40 4213/17 4214/20 4215/41 +f 60/40 4216/41 4217/20 4218/17 +f 58/18 4219/19 4220/70 59/69 +f 4219/18 58/19 4221/70 4222/69 +f 4212/69 4223/10 4222/74 4221/70 +f 61/17 3321/18 4221/19 58/20 +f 3318/69 4212/10 4221/74 3321/70 +f 4216/40 60/17 3306/20 4215/41 +f 4223/69 4224/10 4210/74 4222/70 +f 4219/17 4222/18 4210/19 3305/20 +f 4220/17 4219/18 3305/19 3306/20 +f 3095/66 3116/18 4210/69 4224/65 +f 4209/13 69/16 66/15 65/14 +f 4210/46 3116/36 69/48 4209/47 +f 3116/21 3115/22 70/23 69/24 +f 3115/46 76/36 73/48 70/47 +f 883/15 52/14 71/13 890/16 +f 72/13 75/16 890/15 71/14 +f 98/38 4225/27 4226/28 112/39 +f 4225/16 4227/15 4228/26 4226/25 +f 78/16 80/25 83/26 4229/15 +f 91/27 4229/28 83/29 84/30 +f 93/27 4230/30 111/29 94/28 +f 4231/31 1163/34 109/33 110/32 +f 4231/27 110/28 111/29 4230/30 +f 103/16 4232/15 4233/26 105/25 +f 1162/16 88/25 109/26 1163/15 +f 4234/16 96/15 95/26 81/25 +f 99/27 89/28 88/29 1162/30 +f 104/27 4234/30 81/29 80/28 +f 4235/18 108/19 107/70 4236/69 +f 4237/18 117/69 4233/70 4232/19 +f 4236/44 116/89 115/64 117/4 +f 4236/40 4238/17 113/20 116/41 +f 100/35 99/36 1162/37 1165/8 +f 104/35 102/36 120/37 4234/8 +f 103/16 79/25 4239/26 1161/15 +f 1161/16 4239/25 4240/26 1160/15 +f 100/36 1165/37 119/35 +f 122/13 4241/14 4242/15 123/16 +f 145/13 131/14 132/15 4243/16 +f 123/13 4242/14 3440/15 3439/16 +f 124/13 123/14 3439/15 133/16 +f 130/13 128/14 135/15 4244/16 +f 132/13 130/14 4244/15 4245/16 +f 4243/13 132/14 4245/15 2394/16 +f 137/5 4246/6 4247/7 138/8 +f 4248/42 4249/43 156/44 4250/45 +f 4249/43 140/1 143/4 156/44 +f 141/43 1621/1 165/4 142/44 +f 1621/42 1622/43 170/44 165/45 +f 1622/43 4251/1 136/4 170/44 +f 4252/73 138/6 4247/87 +f 139/6 138/87 4252/73 4253/7 +f 4254/29 4253/12 4252/9 +f 4255/13 4256/14 4257/15 4241/16 +f 3235/17 4258/20 174/19 4259/18 +f 4253/69 4259/74 174/70 +f 155/56 149/55 150/57 4260/58 +f 156/58 155/57 4260/50 4250/49 +f 122/15 171/14 4255/13 4241/16 +f 172/46 175/36 4255/48 171/47 +f 4253/56 174/55 173/57 139/58 +f 174/49 4258/51 175/50 +f 4261/1 201/2 204/3 217/4 +f 206/1 4261/2 217/3 207/4 +f 4262/1 213/2 214/3 2765/4 +f 2765/1 214/2 221/3 2766/4 +f 216/1 215/2 1847/3 222/4 +f 2766/1 221/2 224/3 228/4 +f 222/1 1847/2 1848/3 225/4 +f 225/1 1848/2 4263/3 230/4 +f 230/1 4263/2 4264/3 236/4 +f 235/1 234/2 242/3 2796/4 +f 236/1 4264/2 4265/3 243/4 +f 2796/1 242/2 249/3 2797/4 +f 243/1 4265/2 4266/3 4267/4 +f 244/1 243/2 4267/3 4268/4 +f 245/1 244/2 4268/3 4269/4 +f 246/1 245/2 4269/3 4270/4 +f 247/1 246/2 4270/3 4271/4 +f 248/1 247/2 4271/3 4272/4 +f 249/1 248/2 4272/3 4273/4 +f 2797/1 249/2 4273/3 2098/4 +f 4274/49 251/51 4275/50 +f 4275/49 251/51 4276/50 +f 4276/49 251/51 250/50 +f 251/51 4274/50 4277/49 +f 4278/49 250/52 252/51 4279/50 +f 252/49 251/51 4277/50 +f 4279/49 252/52 4277/51 4280/50 +f 4281/49 253/52 255/51 1713/50 +f 4282/1 4283/2 257/3 256/4 +f 4284/1 4282/2 256/3 260/4 +f 4285/1 4284/2 260/3 262/4 +f 4286/1 4285/2 262/3 264/4 +f 4287/1 4286/2 264/3 266/4 +f 4288/1 4287/2 266/3 268/4 +f 4289/1 4288/2 268/3 270/4 +f 4290/1 4289/2 270/3 1727/4 +f 1727/1 270/2 271/3 1728/4 +f 4291/79 272/82 275/81 4292/80 +f 4292/35 275/8 277/37 4258/36 +f 284/79 4293/82 4294/81 286/80 +f 286/35 4294/8 4295/37 280/36 +f 288/59 4296/60 296/61 289/62 +f 4296/57 288/50 294/67 4297/2 +f 4297/57 294/50 295/67 622/2 +f 622/59 295/60 292/61 300/62 +f 272/57 4291/67 4298/2 +f 272/57 4298/50 4299/67 282/2 +f 282/57 4299/50 4300/67 284/2 +f 284/57 4300/67 4293/2 +f 277/39 279/66 4301/65 4258/28 +f 4295/39 4302/66 279/65 280/28 +f 4301/35 279/37 4302/36 +f 1314/50 1313/67 303/68 302/51 +f 312/33 320/53 4303/43 313/42 +f 311/53 305/55 308/1 1316/43 +f 4304/57 4305/50 318/67 317/2 +f 1313/33 1316/42 308/43 303/53 +f 4306/52 4307/86 317/21 4308/51 +f 320/33 315/53 316/43 4303/42 +f 320/53 312/55 1315/1 321/43 +f 1315/43 1314/53 302/33 321/42 +f 4309/42 4310/43 1315/33 +f 312/33 318/42 4309/43 1315/53 +f 311/33 1316/53 4308/43 317/42 +f 64/13 4208/14 4311/15 349/16 +f 349/13 4311/14 323/15 322/16 +f 4213/13 3306/15 351/16 +f 4312/24 346/23 347/21 +f 4312/13 4213/14 351/15 346/16 +f 3305/13 4209/14 351/15 3306/16 +f 4313/18 4314/19 4312/70 4315/69 +f 4315/17 330/20 4316/19 4313/18 +f 330/17 4315/20 4218/19 331/18 +f 3317/69 4313/70 4316/74 4211/10 +f 4217/40 4214/41 4213/20 4218/17 +f 333/17 332/18 4213/19 4312/20 +f 4312/17 347/18 4317/19 333/20 +f 4318/69 4319/10 4317/74 347/70 +f 4320/8 343/37 342/40 4321/7 +f 4318/66 347/18 343/69 4320/65 +f 64/15 349/14 348/13 62/16 +f 350/13 65/16 62/15 348/14 +f 351/13 4209/16 65/15 350/14 +f 353/72 356/6 4322/87 3959/77 +f 352/71 355/5 4323/6 4324/72 +f 353/71 3959/72 3962/6 354/5 +f 355/71 354/72 4325/6 4326/5 +f 4324/72 4307/6 357/87 352/77 +f 356/15 4327/26 4328/5 4322/71 +f 357/15 4329/26 4327/5 356/71 +f 359/69 4330/10 360/65 +f 4331/65 359/69 358/10 4329/9 +f 4329/65 358/69 361/10 4327/9 +f 4327/65 361/69 362/10 4328/9 +f 4332/52 4333/86 2689/21 4334/51 +f 364/35 4335/8 2684/37 365/36 +f 372/28 371/65 2689/9 4333/29 +f 2689/35 371/36 365/37 2684/8 +f 4336/13 2812/14 2815/15 4337/16 +f 2815/13 2814/14 376/15 375/16 +f 4337/13 2815/14 375/15 1478/16 +f 1478/13 375/14 378/15 1479/16 +f 1479/13 378/14 380/15 1481/16 +f 1481/13 380/14 382/15 1483/16 +f 1483/13 382/14 384/15 1485/16 +f 1485/13 384/14 395/15 1493/16 +f 1493/13 395/14 385/15 389/16 +f 393/13 392/14 4338/15 1500/16 +f 1500/13 4338/14 3358/15 1501/16 +f 396/17 405/73 777/7 397/40 +f 407/7 400/40 401/17 4339/73 +f 4339/7 401/40 402/17 4340/73 +f 4340/7 402/40 403/17 4341/73 +f 4341/7 403/40 404/17 4342/73 +f 4342/7 404/40 397/17 777/73 +f 4343/73 783/7 4344/17 +f 776/73 4343/7 4344/17 +f 777/73 776/7 4344/17 +f 779/73 777/7 4344/17 +f 781/73 779/7 4344/17 +f 783/73 781/7 4344/17 +f 408/17 4345/7 409/73 +f 408/17 410/7 4339/73 +f 408/17 4339/7 411/73 +f 408/17 412/7 4345/73 +f 414/29 413/12 3681/9 +f 414/29 3681/32 4346/12 3685/9 +f 3681/29 3680/12 4346/9 +f 4347/12 414/9 3685/29 3684/32 +f 4348/29 418/12 4349/9 +f 420/29 416/9 418/12 4348/32 +f 421/13 443/16 4350/15 422/14 +f 432/13 431/14 4351/15 4352/16 +f 4350/13 425/14 428/15 422/16 +f 433/13 432/14 4352/15 4353/16 +f 4354/46 434/36 433/48 4353/47 +f 4355/56 435/58 434/57 4354/55 +f 4356/58 437/49 435/50 4355/57 +f 4357/69 4358/70 4356/74 4359/10 +f 4360/69 4361/70 4358/74 4357/10 +f 4358/6 439/7 437/73 4356/87 +f 439/29 442/9 438/12 437/32 +f 4361/6 440/7 439/73 4358/87 +f 443/15 447/13 446/14 +f 443/15 446/13 4350/14 +f 4350/13 446/14 449/15 425/16 +f 425/13 449/14 451/15 426/16 +f 4361/6 453/73 440/7 +f 4362/6 455/7 453/73 4361/87 +f 459/46 458/36 832/48 461/47 +f 835/13 834/14 463/15 465/16 +f 835/13 465/14 462/15 461/16 +f 2850/21 470/52 469/86 +f 473/25 4363/26 4364/35 471/85 +f 4363/25 4365/26 3748/35 4364/85 +f 467/57 471/56 3742/58 +f 470/52 2850/51 2853/21 1365/86 +f 4366/69 4367/10 482/74 4368/70 +f 481/17 4369/20 4368/19 482/18 +f 4370/17 4369/18 481/19 478/20 +f 4370/40 478/20 1414/41 +f 479/24 4371/23 1365/82 470/79 +f 478/44 480/89 4372/64 1414/4 +f 470/40 1365/17 4372/20 480/41 +f 4367/69 474/10 475/74 482/70 +f 1269/1 4373/2 484/3 483/4 +f 1270/1 1269/2 483/3 487/4 +f 4374/1 1270/2 487/3 489/4 +f 4375/1 4374/2 489/3 491/4 +f 4376/1 4375/2 491/3 493/4 +f 4377/1 4376/2 493/3 495/4 +f 517/1 516/2 523/3 4378/4 +f 4378/1 523/2 529/3 4379/4 +f 525/1 524/2 4380/3 1822/4 +f 526/1 525/2 1822/3 1821/4 +f 527/1 526/2 1821/3 530/4 +f 4379/1 529/2 532/3 202/4 +f 556/78 548/75 551/72 4381/71 +f 4382/29 4383/12 4384/9 +f 559/29 558/12 4384/9 +f 575/29 557/12 4385/9 +f 557/66 559/65 4386/69 4387/18 +f 4385/66 557/65 4387/69 4388/18 +f 4389/29 558/9 563/12 585/32 +f 4390/29 585/9 534/12 4391/32 +f 4392/29 4384/9 558/12 4389/32 +f 4393/29 4389/9 585/12 4390/32 +f 553/29 4394/9 4395/12 552/32 +f 570/29 569/32 4396/12 3999/9 +f 552/29 4395/9 4397/12 4398/32 +f 584/29 570/9 3999/12 4001/32 +f 556/29 4381/9 568/12 567/32 +f 4001/9 4399/12 4400/29 +f 4401/29 584/9 4001/12 4400/32 +f 574/29 573/9 584/12 4401/32 +f 575/29 4402/9 577/12 572/32 +f 4402/29 582/9 579/12 577/32 +f 586/3 4403/63 4404/62 588/59 +f 591/5 588/8 4404/7 4405/6 +f 25/3 4404/63 4403/62 4197/59 +f 4405/5 4404/8 25/7 24/6 +f 566/2 580/67 592/59 4406/3 +f 4406/3 592/63 593/62 2318/59 +f 2319/5 2318/8 593/7 594/6 +f 566/2 4406/3 595/59 565/67 +f 553/2 596/3 2325/59 4394/67 +f 596/3 595/63 2317/62 4407/59 +f 4408/17 4366/18 4409/19 4410/20 +f 4363/29 473/9 4367/12 4411/32 +f 4411/29 4367/12 1415/9 +f 4412/29 4411/32 1415/12 1384/9 +f 4366/6 4408/87 1415/73 4367/7 +f 4413/29 4414/32 4365/12 4415/9 +f 4416/29 4413/32 4415/12 4417/9 +f 4365/55 4363/57 4411/2 4415/1 +f 4415/29 4411/32 4412/12 4417/9 +f 2249/29 597/32 600/12 2250/9 +f 4418/29 611/32 4419/12 615/9 +f 4420/29 4418/32 615/12 4421/9 +f 602/29 4422/32 4423/12 603/9 +f 2259/29 2260/9 2249/12 2251/32 +f 4424/29 2249/9 2260/32 +f 4414/29 4413/32 4425/12 598/9 +f 4426/29 4365/32 4414/12 598/9 +f 4427/29 4426/32 598/12 597/9 +f 4427/29 597/32 2249/12 4424/9 +f 606/29 2259/32 2251/12 607/9 +f 4428/29 605/32 607/12 4429/9 +f 4428/29 4429/32 3606/12 3605/9 +f 609/29 4430/9 601/12 610/32 +f 4431/29 601/9 4430/32 +f 4432/29 4433/32 4422/12 602/9 +f 4432/29 602/32 601/12 4431/9 +f 4413/55 4416/1 4420/2 4425/57 +f 4417/29 4434/9 4420/12 4416/32 +f 4435/32 608/9 611/29 +f 4436/29 4435/32 611/12 4418/9 +f 4436/29 4418/32 4420/12 4434/9 +f 603/29 4423/32 4437/12 613/9 +f 4421/29 615/32 616/12 4438/9 +f 613/29 4437/32 4439/12 617/9 +f 4438/29 616/32 600/12 599/9 +f 4419/29 4440/32 612/12 615/9 +f 618/29 617/32 4441/12 4442/9 +f 600/29 618/32 4442/12 2250/9 +f 4440/29 604/32 603/12 612/9 +f 4429/29 607/32 4441/12 617/9 +f 3606/29 4429/32 617/12 4439/9 +f 620/57 4443/50 623/67 621/2 +f 4443/57 4444/50 626/67 623/2 +f 4444/57 659/50 658/67 626/2 +f 622/57 621/50 625/67 4297/2 +f 626/57 658/50 641/67 627/2 +f 4297/57 625/50 629/67 4296/2 +f 627/57 641/50 640/67 630/2 +f 4296/57 629/50 4445/67 4446/2 +f 629/57 628/50 4447/67 4445/2 +f 628/57 630/50 4448/67 4447/2 +f 630/57 640/50 4449/67 4448/2 +f 4450/39 299/28 298/65 4451/66 +f 4452/35 300/8 299/37 4450/36 +f 622/79 300/81 4452/80 +f 656/39 4451/66 298/65 297/28 +f 655/35 656/36 297/37 296/8 +f 655/80 296/81 4296/79 +f 4444/59 4443/60 632/61 631/62 +f 634/39 633/65 642/66 +f 659/79 4444/82 631/81 635/80 +f 4449/79 640/82 636/81 643/80 +f 646/39 4453/65 642/66 +f 4446/79 4445/82 645/81 644/80 +f 649/39 4454/65 642/66 +f 619/79 622/82 648/81 647/80 +f 4443/59 620/60 650/61 632/62 +f 642/66 633/65 649/39 +f 620/79 619/82 647/81 650/80 +f 642/66 4453/65 639/39 +f 4449/79 643/80 651/81 4448/82 +f 645/35 4455/37 646/36 +f 4453/65 646/39 4455/28 +f 4456/28 639/39 4453/65 +f 651/8 639/35 4456/37 +f 4454/65 649/39 652/28 +f 654/28 646/39 4454/65 +f 622/79 4452/81 648/80 +f 653/80 655/81 4296/79 +f 4452/35 4450/36 652/37 648/8 +f 652/39 4450/28 4451/65 4454/66 +f 654/39 4454/66 4451/65 656/28 +f 642/66 4454/65 646/39 +f 4446/79 644/80 653/81 4296/82 +f 667/32 670/9 701/29 +f 698/29 701/12 670/9 +f 662/29 661/9 667/12 701/32 +f 660/12 663/32 665/29 673/9 +f 664/29 4457/9 673/12 665/32 +f 4457/29 4458/9 674/12 673/32 +f 4386/11 678/84 677/83 4387/45 +f 4388/11 4387/45 677/83 680/84 +f 4382/29 684/12 4383/9 +f 575/29 4385/12 682/9 +f 559/66 4384/65 678/69 4386/18 +f 682/66 4385/65 4388/69 680/18 +f 4383/66 684/65 676/69 675/18 +f 4384/66 4383/65 675/69 678/18 +f 4459/29 4460/9 4461/12 4462/32 +f 674/29 4458/9 4190/12 697/32 +f 4458/29 4463/9 1421/12 4190/32 +f 4464/29 670/9 669/12 687/32 +f 4461/29 698/9 670/12 4464/32 +f 682/29 689/9 4402/12 575/32 +f 689/29 692/9 582/12 4402/32 +f 692/29 695/9 583/12 582/32 +f 4465/9 583/12 695/29 +f 694/29 4191/9 4465/12 695/32 +f 4191/2 4197/3 4403/59 4465/67 +f 4465/2 4403/3 586/59 583/67 +f 4461/25 4466/85 699/35 698/26 +f 4466/24 4467/23 4468/82 699/79 +f 699/24 4468/23 4469/82 700/79 +f 4430/25 4469/85 4468/35 4431/26 +f 4431/25 4468/85 4467/35 4432/26 +f 663/25 707/85 702/35 665/26 +f 702/24 707/23 4470/82 704/79 +f 4436/25 705/85 704/35 4435/26 +f 4435/25 704/85 4470/35 608/26 +f 701/25 700/85 706/35 662/26 +f 707/24 706/79 4471/82 4470/23 +f 706/24 700/79 4469/82 4471/23 +f 608/25 4470/85 4471/35 609/26 +f 609/25 4471/85 4469/35 4430/26 +f 601/25 4472/85 4473/35 610/26 +f 610/25 4473/85 4474/35 611/26 +f 4475/57 4476/50 716/67 725/2 +f 4477/57 4478/50 725/67 4479/2 +f 4475/2 725/67 4478/57 +f 4480/79 4481/82 727/81 726/80 +f 709/59 4480/60 726/61 710/62 +f 4479/59 708/60 711/61 4482/62 +f 1715/79 712/82 715/81 1716/80 +f 1716/35 715/8 719/37 4483/36 +f 4484/12 4485/42 4486/32 +f 716/79 4476/82 721/81 717/80 +f 4477/79 4479/82 4482/81 4487/80 +f 720/39 722/28 4484/65 4486/66 +f 4488/39 4486/66 4485/65 4489/28 +f 3417/40 3418/17 4485/20 4484/41 +f 3035/18 4489/19 4485/70 3418/69 +f 4489/18 3035/19 3036/70 4487/69 +f 4478/10 4477/11 4487/84 3036/74 +f 3425/18 3417/69 4484/70 722/19 +f 722/18 721/69 4490/70 3425/19 +f 4475/10 4490/74 721/84 4476/11 +f 724/57 712/50 1715/67 4491/2 +f 709/57 724/50 4491/67 4480/2 +f 4479/57 725/50 723/67 708/2 +f 4482/4 711/3 731/63 4488/64 +f 719/39 4492/66 4493/65 4483/28 +f 718/39 4494/66 4492/65 719/28 +f 720/39 4486/66 4494/65 718/28 +f 729/39 728/28 4495/65 4493/66 +f 730/39 729/28 4493/65 4492/66 +f 731/39 730/28 4492/65 4494/66 +f 4488/39 731/28 4494/65 4486/66 +f 4487/35 4482/8 4488/37 4489/36 +f 733/1 4496/2 738/3 734/4 +f 3178/1 736/2 737/3 743/4 +f 3179/1 3178/2 743/3 745/4 +f 4283/1 3179/2 745/3 257/4 +f 257/1 745/2 746/3 258/4 +f 4497/6 754/71 4498/72 +f 4499/5 4497/6 4498/71 +f 4497/71 755/6 758/5 +f 754/6 4497/71 755/5 +f 4497/6 760/71 758/72 +f 4500/15 4501/71 409/5 4345/26 +f 4501/15 757/71 410/5 409/26 +f 757/15 756/71 4339/5 410/26 +f 756/15 759/71 411/5 4339/26 +f 759/15 761/71 412/5 411/26 +f 761/15 4500/71 4345/5 412/26 +f 4499/52 4498/86 4501/21 4500/51 +f 4498/52 754/86 757/21 4501/51 +f 760/52 4499/86 4500/21 761/51 +f 764/28 763/29 777/9 405/65 +f 766/28 764/29 405/9 406/65 +f 4502/28 766/29 406/9 407/65 +f 4503/28 4502/29 407/9 4339/65 +f 770/28 4503/29 4339/9 4340/65 +f 767/28 770/29 4340/9 4341/65 +f 771/28 767/29 4341/9 4342/65 +f 763/28 771/29 4342/9 777/65 +f 4504/26 765/5 766/8 4502/35 +f 4497/26 4504/5 4502/8 4503/35 +f 4497/1 4503/55 770/53 769/43 +f 1457/33 1453/53 762/43 765/42 +f 4505/33 1457/53 765/43 4504/42 +f 774/33 1461/53 769/43 768/42 +f 784/15 783/26 4343/5 785/71 +f 785/15 4343/26 776/5 775/71 +f 800/29 791/32 794/12 4506/9 +f 2363/29 800/32 4506/12 2360/9 +f 4507/29 4508/32 3056/12 3057/9 +f 4506/29 794/32 4509/12 4510/9 +f 4357/29 4359/32 4511/12 4508/9 +f 4360/29 4357/32 4508/12 4507/9 +f 795/29 4360/32 4507/12 796/9 +f 796/29 4507/32 3057/12 799/9 +f 797/29 789/32 800/12 2363/9 +f 804/29 803/9 2369/12 2368/32 +f 457/29 456/9 808/12 807/32 +f 812/6 808/7 456/73 836/87 +f 836/6 456/7 455/73 4362/87 +f 814/21 4512/22 4513/23 815/24 +f 804/2 2368/67 4512/59 814/3 +f 458/21 819/22 820/23 832/24 +f 457/2 807/67 819/59 458/3 +f 4514/13 4515/14 4516/15 821/16 +f 4514/13 821/14 815/15 4513/16 +f 4516/13 4208/14 4207/15 823/16 +f 821/13 4516/14 823/15 822/16 +f 823/13 4207/14 56/15 824/16 +f 824/13 56/14 828/15 826/16 +f 831/13 835/14 461/15 832/16 +f 834/13 833/14 464/15 463/16 +f 797/69 2363/10 809/74 810/70 +f 795/69 790/10 836/74 4362/70 +f 4360/69 795/10 4362/74 4361/70 +f 4517/29 869/32 866/12 4518/9 +f 849/29 4519/12 867/9 +f 850/29 852/32 4520/12 4521/9 +f 870/29 850/32 4521/12 4522/9 +f 4523/29 870/12 4522/9 +f 4524/29 870/32 4523/12 4525/9 +f 3474/29 857/9 855/12 4526/32 +f 4526/29 855/9 839/12 838/32 +f 856/29 4519/9 849/12 845/32 +f 4527/29 4526/9 838/12 854/32 +f 858/29 3709/9 4519/12 856/32 +f 877/29 4528/32 876/12 875/9 +f 4524/75 859/76 862/77 870/72 +f 869/29 4517/9 852/12 851/32 +f 4528/29 877/9 880/12 4529/32 +f 2186/29 873/9 876/12 2187/32 +f 2188/29 841/9 873/12 2186/32 +f 853/29 842/9 841/12 2188/32 +f 880/55 879/1 3493/2 3506/57 +f 879/29 864/9 863/12 3493/32 +f 854/67 4530/59 3485/60 4527/68 +f 853/67 4531/59 4530/60 854/68 +f 4532/7 1504/40 4533/17 4534/73 +f 4534/7 4533/40 4535/17 4536/73 +f 4536/7 4535/40 4537/17 4538/73 +f 4538/7 4537/40 4539/17 1753/73 +f 1753/7 4539/40 1505/17 1750/73 +f 1504/17 4532/73 1750/7 1505/40 +f 889/66 888/18 77/69 908/65 +f 4540/8 902/37 887/40 886/7 +f 75/13 894/16 891/15 890/14 +f 74/13 896/16 894/15 75/14 +f 77/46 888/36 896/48 74/47 +f 889/29 905/9 4540/12 886/32 +f 907/9 4540/12 905/29 +f 906/29 4541/12 907/9 +f 4540/66 912/65 911/69 902/18 +f 4542/8 4543/37 910/40 909/7 +f 910/35 4543/36 4544/37 914/8 +f 4545/13 4546/14 916/15 915/16 +f 4547/13 4545/14 915/15 919/16 +f 914/21 4544/22 4547/23 919/24 +f 916/13 4546/14 4548/15 921/16 +f 924/1 1256/2 1257/3 925/4 +f 968/1 935/2 936/3 4074/4 +f 925/1 1257/2 1268/3 937/4 +f 4074/1 936/2 943/3 4549/4 +f 937/1 1268/2 4377/3 4550/4 +f 938/1 937/2 4550/3 4551/4 +f 939/1 938/2 4551/3 4552/4 +f 940/1 939/2 4552/3 944/4 +f 943/1 942/2 946/3 4553/4 +f 4549/1 943/2 4553/3 4554/4 +f 954/1 4555/2 4556/3 955/4 +f 962/1 977/2 4555/3 954/4 +f 1256/3 924/4 955/1 4556/2 +f 15/1 4186/2 976/3 975/4 +f 16/1 15/2 975/3 978/4 +f 972/1 16/2 978/3 973/4 +f 4557/1 970/2 948/3 947/4 +f 17/1 971/2 974/3 979/4 +f 18/1 17/2 979/3 980/4 +f 4187/1 18/2 980/3 981/4 +f 4188/1 4187/2 981/3 4558/4 +f 4558/1 981/2 970/3 4557/4 +f 2157/34 4559/54 987/53 986/33 +f 2155/54 2156/56 4559/55 2157/53 +f 4560/49 1004/52 1003/51 1007/50 +f 2425/13 1005/14 1006/15 2426/16 +f 2429/21 1007/22 1005/23 2425/24 +f 4561/49 4560/52 1007/51 2429/50 +f 4562/1 4563/2 4564/3 4565/4 +f 1010/43 1009/1 1578/4 1580/44 +f 4550/1 4377/2 495/3 1014/4 +f 4551/1 4550/2 1014/3 1013/4 +f 4552/1 4551/2 1013/3 1017/4 +f 944/1 4552/2 1017/3 1019/4 +f 945/1 944/2 1019/3 1021/4 +f 946/1 945/2 1021/3 1023/4 +f 4553/1 946/2 1023/3 1025/4 +f 4554/1 4553/2 1025/3 1026/4 +f 1014/1 495/2 496/3 1015/4 +f 1015/1 496/2 503/3 1027/4 +f 1027/1 503/2 510/3 1033/4 +f 1033/1 510/2 517/3 1041/4 +f 1041/1 517/2 4378/3 1049/4 +f 1049/1 4378/2 4379/3 1057/4 +f 1057/1 4379/2 202/3 201/4 +f 1058/1 1057/2 201/3 4261/4 +f 1059/1 1058/2 4261/3 206/4 +f 1060/1 1059/2 206/3 205/4 +f 1061/1 1060/2 205/3 209/4 +f 1062/1 1061/2 209/3 211/4 +f 1063/1 1062/2 211/3 213/4 +f 1064/1 1063/2 213/3 4262/4 +f 4267/1 4266/2 1066/3 1065/4 +f 4268/1 4267/2 1065/3 1069/4 +f 4269/1 4268/2 1069/3 1071/4 +f 4270/1 4269/2 1071/3 1073/4 +f 4271/1 4270/2 1073/3 1075/4 +f 4272/1 4271/2 1075/3 1077/4 +f 4273/1 4272/2 1077/3 1079/4 +f 2098/1 4273/2 1079/3 2099/4 +f 2099/1 1079/2 1080/3 4566/4 +f 4566/1 1080/2 1088/3 4567/4 +f 4567/1 1088/2 1096/3 4568/4 +f 1090/1 1089/2 4569/3 1097/4 +f 4568/1 1096/2 1103/3 4570/4 +f 1097/1 4569/2 1111/3 1104/4 +f 4570/1 1103/2 1110/3 4571/4 +f 4571/1 1110/2 1119/3 4572/4 +f 1113/1 1112/2 4283/3 4282/4 +f 1114/1 1113/2 4282/3 4284/4 +f 1115/1 1114/2 4284/3 4285/4 +f 1116/1 1115/2 4285/3 4286/4 +f 1117/1 1116/2 4286/3 4287/4 +f 1118/1 1117/2 4287/3 4288/4 +f 1119/1 1118/2 4288/3 4289/4 +f 4572/1 1119/2 4289/3 4290/4 +f 4573/66 4574/65 4575/69 4576/18 +f 4574/8 4577/7 4578/40 4575/37 +f 4577/66 4579/65 4580/69 4578/18 +f 4581/37 1123/88 1122/41 1134/40 +f 4582/37 1128/88 1129/41 4583/40 +f 4582/10 4584/11 1131/84 1128/74 +f 1125/37 1235/41 1136/88 +f 1125/17 1127/18 1130/19 1235/20 +f 1143/17 4585/20 1142/19 1141/18 +f 1235/44 1238/89 4586/64 1136/4 +f 1130/18 1233/19 4587/70 1235/69 +f 1131/18 1232/19 1233/70 1130/69 +f 4584/10 1229/11 1232/84 1131/74 +f 1144/53 368/43 374/1 4588/55 +f 368/6 1144/72 1147/71 4589/5 +f 1145/5 1144/71 4588/15 1155/26 +f 1149/71 4590/5 4589/6 1147/72 +f 4591/72 4590/77 1149/87 1151/6 +f 4592/71 3630/5 4591/6 1151/72 +f 4588/71 374/5 3630/6 4592/72 +f 1151/15 1150/26 1156/5 4592/71 +f 4592/15 1156/26 1155/5 4588/71 +f 1152/17 2696/7 1153/73 +f 1152/17 1154/7 2694/73 +f 1152/17 2694/7 2693/73 +f 1152/17 2693/7 2695/73 +f 1152/17 2695/7 2696/73 +f 1148/73 1146/7 1157/17 +f 1150/73 1148/7 1157/17 +f 1156/73 1150/7 1157/17 +f 1145/73 1155/7 1157/17 +f 1146/73 1145/7 1157/17 +f 1439/32 4593/33 4594/42 4595/12 +f 4227/29 4595/27 4594/30 +f 4596/32 4597/12 1159/42 4598/33 +f 4597/27 4232/28 103/29 1159/30 +f 4595/27 4227/29 4225/28 +f 4595/27 4225/29 98/28 +f 4599/32 1439/33 4595/42 4600/12 +f 4600/27 4595/30 98/29 108/28 +f 4601/10 4599/11 4600/84 4602/74 +f 4602/18 4600/19 108/70 4235/69 +f 4603/10 4604/74 4597/84 4596/11 +f 4604/18 4237/69 4232/70 4597/19 +f 4598/32 1159/12 1158/42 4605/33 +f 103/28 1161/29 1159/27 +f 4606/71 96/6 4234/5 +f 4606/71 93/6 96/5 +f 4606/71 120/6 93/5 +f 4606/71 4234/6 120/5 +f 1163/5 4231/6 1164/71 +f 4231/5 1165/6 1164/71 +f 93/5 120/6 4607/71 +f 120/5 119/6 4607/71 +f 119/5 4230/6 4607/71 +f 4230/5 93/6 4607/71 +f 4231/71 4608/6 1165/5 +f 4608/71 119/6 1165/5 +f 4608/71 4230/6 119/5 +f 4608/71 4231/6 4230/5 +f 4235/17 1171/20 4609/19 4602/18 +f 4610/10 4601/11 4602/84 4609/74 +f 4611/10 4612/74 4604/84 4603/11 +f 4604/17 4612/20 1166/19 4237/18 +f 4237/17 1166/20 1169/19 117/18 +f 1169/40 4236/20 117/41 +f 1171/17 4235/18 4236/19 1169/20 +f 4612/17 4613/18 1167/19 1166/20 +f 4611/18 4613/20 4612/17 +f 1170/17 4614/18 4609/19 1171/20 +f 4610/18 4609/20 4614/17 +f 4615/65 2831/9 1173/10 1172/69 +f 2831/65 2830/9 1175/10 1173/69 +f 2830/65 2834/9 1176/10 1175/69 +f 2834/65 2837/9 1177/10 1176/69 +f 2837/65 4615/9 1172/10 1177/69 +f 1182/13 4616/15 1183/16 +f 4617/13 1178/14 1181/15 4618/16 +f 1184/13 4617/14 4618/15 1185/16 +f 4576/21 4575/22 1187/23 1190/24 +f 4575/46 4578/36 4619/48 1187/47 +f 4578/21 4580/22 1193/23 4619/24 +f 1682/79 1226/82 1228/81 4620/80 +f 1201/35 1202/8 4620/37 1228/36 +f 1718/79 1721/80 4621/81 1222/82 +f 1196/35 4621/36 1721/37 1197/8 +f 1219/59 1222/60 4621/61 4622/62 +f 1217/59 1219/60 4622/61 1218/62 +f 4622/4 4621/3 1196/63 1204/64 +f 1218/4 4622/3 1204/63 1206/64 +f 1134/91 4581/92 4583/93 4582/94 +f 4587/17 1233/18 1234/19 1237/20 +f 1136/37 4586/88 4585/41 4623/40 +f 1237/37 4585/40 4586/41 1238/88 +f 1240/65 2509/69 1251/10 1241/9 +f 1242/65 4624/69 4625/10 1239/9 +f 2509/10 1240/9 1244/65 2506/69 +f 1239/65 4625/69 4626/10 1243/9 +f 1246/65 1249/69 2506/10 1244/9 +f 1243/65 4626/69 2843/10 1245/9 +f 1245/65 2843/69 2845/10 1250/9 +f 1250/65 2845/69 4624/10 1242/9 +f 1261/1 1260/2 4373/3 1269/4 +f 1265/1 1263/2 1270/3 4374/4 +f 1266/1 1265/2 4374/3 4375/4 +f 1267/1 1266/2 4375/3 4376/4 +f 1268/1 1267/2 4376/3 4377/4 +f 4555/1 1291/2 1292/3 4556/4 +f 977/1 1290/2 1291/3 4555/4 +f 4627/1 4628/2 1298/3 1297/4 +f 2866/1 4627/2 1297/3 1299/4 +f 1252/3 1256/4 4556/1 1292/2 +f 2867/1 2866/2 1299/3 1300/4 +f 1294/1 2867/2 1300/3 1295/4 +f 4186/1 1293/2 1296/3 976/4 +f 976/1 1296/2 1290/3 977/4 +f 1302/33 4629/53 3460/43 1303/42 +f 4630/33 1301/53 1304/43 1308/42 +f 4631/52 3459/51 3460/21 4629/86 +f 1306/53 1303/43 3460/1 4632/55 +f 1310/72 1309/6 4633/87 3459/77 +f 3459/71 4633/5 4632/6 3460/72 +f 4632/15 2820/26 1311/5 1306/71 +f 1305/15 1312/26 2817/5 1307/71 +f 1307/15 2817/26 2816/5 1309/71 +f 1309/15 2816/26 2819/5 4633/71 +f 4633/15 2819/26 2820/5 4632/71 +f 357/15 4307/71 4331/5 4329/26 +f 4634/52 4635/86 4310/21 4309/51 +f 4635/52 4306/86 4308/21 4310/51 +f 359/10 4331/65 4635/9 +f 4330/65 359/69 4635/9 +f 4306/73 4635/18 4331/17 +f 4331/66 4307/73 4306/18 +f 4310/42 4308/43 1316/33 +f 1316/53 1315/33 4310/43 +f 3659/13 3661/16 1337/15 1340/14 +f 4636/13 4637/14 1337/15 3661/16 +f 4638/13 4639/14 1331/15 1332/16 +f 1329/13 4640/14 1352/15 1330/16 +f 4638/13 1332/14 1337/15 4637/16 +f 4640/13 4641/14 1353/15 1352/16 +f 1356/13 1354/15 1435/16 +f 1358/13 3659/14 1340/15 1343/16 +f 3655/65 3656/9 3660/10 1357/69 +f 4642/17 4409/18 4366/19 4368/20 +f 4643/17 4642/18 4368/19 4369/20 +f 4644/17 4643/18 4369/19 4370/20 +f 4408/17 4410/18 1361/19 1360/20 +f 1363/17 1362/18 4644/19 4370/20 +f 2853/21 1366/52 1365/86 +f 4412/25 1371/85 1369/35 4417/26 +f 1384/25 1376/85 1371/35 4412/26 +f 4417/25 1369/85 1368/35 4434/26 +f 1392/29 1393/9 664/12 1382/32 +f 664/29 666/12 1382/9 +f 1393/29 1394/9 4457/12 664/32 +f 1394/29 4463/9 4458/12 4457/32 +f 1385/29 1389/9 4463/12 1394/32 +f 1379/13 1377/14 1366/15 4645/16 +f 1398/13 1379/14 4645/15 1400/16 +f 1403/13 1401/14 3818/15 3820/16 +f 4408/69 1360/70 1405/74 1415/10 +f 1363/17 4370/18 1414/19 1404/20 +f 4463/29 1389/9 1406/12 1421/32 +f 1409/13 1402/14 1403/15 49/16 +f 1414/40 4372/41 1365/20 4371/17 +f 666/25 703/85 1367/35 1382/26 +f 703/24 705/23 1368/82 1367/79 +f 4434/25 1368/85 705/35 4436/26 +f 49/13 1403/14 3820/15 4204/16 +f 4646/13 1434/14 1422/15 1426/16 +f 4647/13 4646/14 1426/15 1428/16 +f 3989/46 4648/36 4647/48 1428/47 +f 3990/21 3989/22 1428/23 1429/24 +f 4649/46 3990/36 1429/48 1433/47 +f 1437/37 1436/8 4598/35 1442/36 +f 4650/77 4651/38 4652/39 4653/87 +f 4651/77 4654/39 4652/87 +f 1440/5 4655/6 4656/71 +f 4655/5 4657/6 4656/71 +f 4657/5 1441/6 4656/71 +f 1441/5 1440/6 4656/71 +f 4658/71 4654/6 1443/5 +f 4658/71 4652/6 4654/5 +f 4658/71 1444/6 4652/5 +f 4658/71 1443/6 1444/5 +f 4657/35 4653/8 1437/37 1441/36 +f 4652/35 1444/36 1437/37 4653/8 +f 4659/77 4593/38 1439/39 1438/87 +f 4651/77 4659/38 1438/39 1443/87 +f 4651/77 1443/39 4654/87 +f 4650/77 4653/87 4657/39 4660/38 +f 4657/87 4655/39 4660/77 +f 1436/35 4603/8 4596/37 4598/36 +f 1436/35 4601/37 4603/36 +f 1436/35 1439/8 4599/37 4601/36 +f 4603/35 4601/8 4610/37 4611/36 +f 4661/77 1442/87 4598/39 4605/38 +f 4660/77 1440/87 1442/39 4661/38 +f 4655/87 1440/39 4660/77 +f 4611/17 4610/18 4614/19 4613/20 +f 4651/29 4662/32 4663/12 4659/9 +f 4663/29 1445/12 4659/9 +f 4659/29 1445/12 1448/9 +f 4659/29 1448/12 4593/9 +f 4664/29 4660/32 4661/12 1450/9 +f 1450/29 4661/12 1451/9 +f 4661/29 4605/12 1451/9 +f 4665/29 4664/32 1450/12 1449/9 +f 1448/29 1447/32 4666/12 4593/9 +f 1452/29 1451/32 4605/12 4667/9 +f 4668/29 4669/32 4664/12 4665/9 +f 4663/29 4670/32 1446/12 1445/9 +f 4670/29 4671/32 1747/12 1446/9 +f 1447/29 1747/32 1746/12 4666/9 +f 1446/29 1747/12 1447/9 +f 1453/33 1456/53 747/43 762/42 +f 1460/33 4505/53 4504/43 4497/42 +f 1461/33 1460/53 4497/43 769/42 +f 1456/33 773/53 772/43 747/42 +f 1458/33 1457/42 4505/43 4672/53 +f 4672/33 4505/42 1460/43 1459/53 +f 1462/33 1461/42 774/43 4673/53 +f 4673/33 774/42 773/43 4674/53 +f 4674/33 773/42 1456/43 1455/53 +f 4522/51 1469/21 1465/24 1464/68 +f 1464/24 1463/68 4523/51 4522/21 +f 1463/24 1467/68 4525/51 4523/21 +f 4460/25 1475/85 4466/35 4461/26 +f 4525/25 1467/85 1475/35 4460/26 +f 1475/24 1476/23 4467/82 4466/79 +f 4432/25 4467/85 1476/35 4433/26 +f 4433/25 1476/85 1466/35 1468/26 +f 4420/68 4421/24 4675/79 4676/60 +f 611/68 4474/60 4677/79 4419/24 +f 4473/24 4678/23 4677/82 4474/79 +f 4472/24 4679/23 4678/82 4473/79 +f 601/68 604/24 4679/79 4472/60 +f 4440/25 4678/85 4679/35 604/26 +f 4419/25 4677/85 4678/35 4440/26 +f 4422/68 4680/60 4681/79 4423/24 +f 1452/8 4667/7 4682/40 4683/37 +f 1449/66 1452/65 4683/69 4684/18 +f 4665/66 1449/65 4684/69 4685/18 +f 4668/66 4665/65 4685/69 4686/18 +f 4687/8 4668/7 4686/40 4688/37 +f 3257/66 4687/65 4688/69 4689/18 +f 4690/13 4336/14 4337/15 4691/16 +f 4683/46 4682/36 4690/48 4691/47 +f 4691/13 4337/14 1478/15 1477/16 +f 4684/21 4683/22 4691/23 1477/24 +f 4685/46 4684/36 1477/48 1480/47 +f 4686/21 4685/22 1480/23 1482/24 +f 4688/46 4686/36 1482/48 1484/47 +f 4689/21 4688/22 1484/23 1486/24 +f 1492/13 390/15 393/16 +f 1489/13 1493/14 389/15 1490/16 +f 1490/13 389/14 390/15 1492/16 +f 1488/46 4689/36 1486/48 1489/47 +f 1496/66 3257/65 4689/69 1488/18 +f 4692/66 1497/65 1498/69 1503/18 +f 1492/13 393/14 1500/15 1499/16 +f 4533/40 1504/17 1506/7 +f 4539/40 4537/17 1506/7 +f 4537/40 4535/17 1506/7 +f 1505/40 4539/17 1506/7 +f 4535/40 4533/17 1506/7 +f 1541/12 1537/42 1540/45 4693/11 +f 2698/12 1531/11 1530/45 1541/42 +f 2697/12 1532/11 1531/45 2698/42 +f 1542/12 1533/11 1532/45 2697/42 +f 1542/12 2697/42 2700/45 1543/11 +f 1540/87 1511/73 1515/66 4693/39 +f 4693/87 1515/73 1518/66 2699/39 +f 2699/87 1518/73 1521/66 2700/39 +f 2700/87 1521/73 1524/66 1543/39 +f 1545/42 1544/43 1561/44 4082/45 +f 1546/43 1545/1 4082/4 4094/44 +f 1009/42 1547/43 1550/44 1578/45 +f 1553/42 1010/43 1580/44 1554/45 +f 1553/1 1557/2 1026/3 1010/4 +f 1558/1 1547/2 1009/3 1040/4 +f 4694/42 1546/43 4094/44 4695/45 +f 4694/43 4695/4 4696/44 +f 1559/42 4697/43 4698/44 1560/45 +f 1557/1 1563/2 1566/3 1026/4 +f 1566/1 4554/3 1026/4 +f 4694/1 1570/2 1569/3 1546/4 +f 4699/1 4697/2 1559/3 1601/4 +f 4248/1 4699/2 1601/3 4249/4 +f 4249/1 1601/2 1602/3 140/4 +f 140/1 1602/2 1607/3 141/4 +f 141/1 1607/2 1613/3 1621/4 +f 1558/1 1040/2 1048/3 1614/4 +f 1614/1 1048/2 1056/3 1623/4 +f 1622/1 1620/2 1629/3 4251/4 +f 1623/1 1056/2 1064/3 1630/4 +f 1630/1 1064/2 4262/3 2758/4 +f 1631/1 1630/2 2758/3 2757/4 +f 1632/1 1631/2 2757/3 4700/4 +f 1633/1 1632/2 4700/3 2762/4 +f 1634/1 1633/2 2762/3 2761/4 +f 1635/1 1634/2 2761/3 4701/4 +f 4246/5 4702/6 4703/7 4247/8 +f 4702/5 4704/6 4705/7 4703/8 +f 4251/42 1629/43 137/44 136/45 +f 1629/43 1635/1 4246/4 137/44 +f 1635/42 4701/43 4702/44 4246/45 +f 1637/28 4706/29 1310/9 1638/65 +f 4630/52 1308/51 1310/21 4706/86 +f 3468/35 1642/8 1645/37 3459/36 +f 1310/35 3459/8 1645/37 1638/36 +f 1650/55 1654/2 2034/1 +f 1658/17 2037/18 2035/19 1656/20 +f 2034/45 1654/44 1656/89 2035/83 +f 4707/60 4708/79 1673/80 4709/61 +f 4709/45 1673/44 1660/89 1663/83 +f 4710/60 4707/79 4709/80 1677/61 +f 4711/60 4712/61 1675/80 4713/79 +f 4714/60 4715/79 1676/80 4716/61 +f 4711/60 4714/79 4716/80 4712/61 +f 4715/60 4710/79 1677/80 1676/61 +f 4708/60 4717/79 1674/80 1673/61 +f 4713/60 1675/61 1674/80 4717/79 +f 1651/29 1650/32 2034/12 1672/9 +f 4712/45 2037/83 1658/89 1675/44 +f 4709/45 1663/83 1664/89 1677/44 +f 4716/45 1676/44 1666/89 1668/83 +f 4199/29 4198/12 4718/9 +f 4719/29 4199/32 4718/12 1681/9 +f 4720/29 1683/12 4721/9 +f 4720/29 4719/32 1680/12 1683/9 +f 4719/29 1681/12 1680/9 +f 1719/29 1718/9 4718/12 4198/32 +f 1718/29 1678/9 1681/12 4718/32 +f 1682/29 4722/9 4721/12 1683/32 +f 4723/13 1686/14 1870/15 4724/16 +f 1684/17 4725/20 4726/19 1688/18 +f 4727/40 4728/41 1688/20 4729/17 +f 1712/51 4728/49 4730/52 +f 4723/13 1896/14 1687/15 1686/16 +f 4728/49 1712/50 1685/51 1688/52 +f 4280/49 1696/52 4281/51 4279/50 +f 1690/49 4274/52 4275/51 1691/50 +f 1691/49 4275/52 4276/51 4731/50 +f 1692/49 1691/52 4731/51 4732/50 +f 4731/49 4276/52 250/51 4278/50 +f 4280/49 4277/52 4274/51 1690/50 +f 1702/49 4280/52 1690/51 1689/50 +f 1696/49 1708/52 253/51 4281/50 +f 1708/49 254/51 253/50 +f 1707/49 254/51 1708/50 +f 255/49 254/51 1709/50 +f 1713/49 255/52 1709/51 1685/50 +f 1709/49 254/51 1710/50 +f 1685/46 1711/36 1870/48 1686/47 +f 1710/49 254/51 1707/50 +f 1711/21 1693/22 1695/23 1870/24 +f 1713/49 1712/52 4279/51 4281/50 +f 4733/49 4278/51 4279/50 +f 1702/49 1697/52 1696/51 4280/50 +f 4445/57 4447/2 4734/67 4735/50 +f 4447/57 4448/2 4736/67 4734/50 +f 4735/57 4734/2 4737/67 1714/50 +f 4734/57 4736/2 4481/67 4737/50 +f 4738/39 4739/28 4495/65 4740/66 +f 4741/4 1717/3 4739/63 4738/64 +f 4735/59 1714/60 1717/61 4741/62 +f 4742/39 4740/66 4495/65 728/28 +f 727/4 4743/3 4742/63 728/64 +f 4481/59 4736/60 4743/61 727/62 +f 4744/39 4745/66 4740/65 4742/28 +f 4743/4 4746/3 4744/63 4742/64 +f 4736/59 4448/60 4746/61 4743/62 +f 1717/4 1716/3 4483/63 4739/64 +f 1714/57 4737/2 4491/67 1715/50 +f 4737/57 4481/2 4480/67 4491/50 +f 4747/39 4738/28 4740/65 4745/66 +f 4748/4 4741/3 4738/63 4747/64 +f 4445/59 4735/60 4741/61 4748/62 +f 4445/79 4748/81 645/80 +f 645/35 4748/8 4747/37 4455/36 +f 4455/39 4747/28 4745/65 4453/66 +f 4456/39 4453/66 4745/65 4744/28 +f 651/80 4746/81 4448/79 +f 4746/35 651/8 4456/37 4744/36 +f 4483/39 4493/66 4495/65 4739/28 +f 1200/13 1198/14 4749/15 4750/16 +f 1197/13 4192/14 4194/15 4751/16 +f 1721/46 1720/36 4192/48 1197/47 +f 1198/13 1197/14 4751/15 4749/16 +f 1202/13 1200/14 4750/15 2979/16 +f 4752/13 1202/14 2979/15 2978/16 +f 4753/46 4620/36 1202/48 4752/47 +f 4722/8 1682/7 4620/40 4753/37 +f 2979/13 4754/15 2980/16 +f 4751/13 4194/14 4206/15 4755/16 +f 4749/13 4751/14 4755/15 4756/16 +f 4750/13 4749/14 4756/15 4757/16 +f 2979/13 4750/14 4757/15 4754/16 +f 4758/1 4290/2 1727/3 1726/4 +f 1723/1 4758/2 1726/3 1724/4 +f 2147/1 1722/2 1725/3 1732/4 +f 2148/1 2147/2 1732/3 1734/4 +f 2149/1 2148/2 1734/3 1736/4 +f 4759/1 2149/2 1736/3 1738/4 +f 4760/1 4759/2 1738/3 4563/4 +f 4563/1 1738/2 1739/3 4564/4 +f 4761/46 1749/36 4762/48 4763/47 +f 2810/13 1743/16 3586/15 2811/14 +f 4764/13 1740/16 1743/15 2810/14 +f 4762/13 1744/16 1740/15 4764/14 +f 1749/21 1748/22 1744/23 4762/24 +f 1743/13 1742/16 3580/15 3586/14 +f 1748/46 4765/36 1745/48 1744/47 +f 4766/16 3580/15 1742/13 +f 1741/13 4767/16 4766/15 1742/14 +f 4766/13 4768/16 3581/15 3580/14 +f 1749/69 4761/18 4666/66 1746/65 +f 1747/66 4671/65 4765/69 1748/18 +f 4769/29 4770/32 4771/12 4772/9 +f 4773/6 4770/73 4769/7 +f 4774/29 4775/9 4769/12 4772/32 +f 4776/29 2890/9 4775/12 4774/32 +f 4773/6 4769/7 4775/73 4777/87 +f 4777/6 4775/7 2890/73 2889/87 +f 175/21 4778/22 4256/23 4255/24 +f 4302/49 4295/52 4779/51 4778/50 +f 4302/49 4778/51 4301/50 +f 4778/51 175/50 4258/49 4301/52 +f 3224/40 4301/41 4302/20 3225/17 +f 3236/18 3225/69 4302/70 4295/19 +f 3238/18 4258/19 4301/70 3224/69 +f 4258/18 3238/19 4780/70 4292/69 +f 4298/10 4291/11 4292/84 4780/74 +f 1751/15 1750/26 4532/5 2847/71 +f 2847/15 4532/26 4534/5 2848/71 +f 2848/15 4534/26 4536/5 4781/71 +f 4781/15 4536/26 4538/5 4782/71 +f 4782/15 4538/26 1753/5 1752/71 +f 1800/29 1756/12 4783/9 +f 1800/29 4783/32 4784/12 4785/9 +f 1754/29 3085/12 1755/9 +f 3085/29 1754/9 3087/12 4786/32 +f 4787/45 1791/83 1759/89 1758/44 +f 1763/45 1762/83 2057/89 2056/44 +f 1771/45 1770/83 1776/89 2079/44 +f 1943/55 4788/57 1809/2 3520/1 +f 3520/29 1809/32 1808/12 3521/9 +f 3521/29 1808/32 4789/12 4790/9 +f 1784/45 2071/44 2074/89 1785/83 +f 4787/3 1758/63 1787/62 1789/59 +f 1763/3 2056/63 1790/62 1788/59 +f 1784/29 1771/32 2079/12 2071/9 +f 2074/17 2057/20 1762/19 1785/18 +f 4785/2 4784/67 2083/59 4791/3 +f 4783/2 1756/67 4792/59 3131/3 +f 4793/2 4783/67 3131/59 3130/3 +f 1795/29 1794/9 1942/12 1805/32 +f 4794/9 1958/12 1957/29 +f 1799/29 1798/9 4794/12 1957/32 +f 4795/29 540/9 539/12 4789/32 +f 4789/29 539/9 562/12 4790/32 +f 1807/29 4795/9 4789/12 1808/32 +f 1797/29 1947/9 1948/12 1798/32 +f 4794/29 4796/9 4797/12 1958/32 +f 1804/29 1796/9 1799/12 906/32 +f 1794/29 4788/9 1943/12 1942/32 +f 1793/29 4798/9 4788/12 1794/32 +f 4798/29 1806/9 1809/12 4788/32 +f 4799/55 1792/1 1795/2 1801/57 +f 1801/12 1800/32 4785/29 4799/9 +f 906/29 1799/32 1957/12 4541/9 +f 1803/29 1802/9 1947/12 1797/32 +f 1798/29 1948/9 4796/12 4794/32 +f 419/29 4800/32 4801/12 4802/9 +f 4803/29 868/32 4804/12 4800/9 +f 4805/29 3709/32 3710/12 4806/9 +f 4519/29 3709/12 4805/9 +f 867/29 4519/32 4805/12 4807/9 +f 4348/29 4518/32 4803/12 420/9 +f 868/14 867/78 4807/71 4804/15 +f 4800/29 419/9 420/12 4803/32 +f 4808/21 4809/22 3194/23 3200/24 +f 3200/13 3199/14 1812/15 1811/16 +f 4810/46 4808/36 3200/48 1811/47 +f 4811/21 4810/22 1811/23 1810/24 +f 1712/21 4730/22 1813/23 1812/24 +f 2516/49 2515/51 4812/50 +f 4812/49 2515/51 4732/50 +f 4812/49 4732/52 4731/51 4278/50 +f 4813/22 4814/21 4815/23 +f 2517/49 1815/51 1814/50 +f 2518/49 2517/52 1814/51 1817/50 +f 1819/49 1815/51 4813/50 +f 1819/21 4813/22 4815/23 1820/24 +f 4813/49 1815/51 2516/50 +f 4278/49 4816/52 4817/51 4812/50 +f 4818/49 2520/51 4819/50 +f 4814/49 4818/52 4819/51 4820/50 +f 4814/21 4820/22 4821/23 4815/24 +f 4819/49 2520/51 2519/50 +f 4820/49 4819/52 2519/51 4822/50 +f 4820/46 4822/36 3199/48 4821/47 +f 1712/49 4822/52 4733/51 4279/50 +f 4822/21 1712/22 1812/23 3199/24 +f 1810/10 4823/11 4824/84 1901/74 +f 1822/1 4380/2 1825/3 1823/4 +f 530/1 1821/2 1824/3 1829/4 +f 531/1 530/2 1829/3 1831/4 +f 532/1 531/2 1831/3 1833/4 +f 202/1 532/2 1833/3 203/4 +f 203/1 1833/2 1834/3 215/4 +f 215/1 1834/2 1840/3 1847/4 +f 1848/1 1846/2 1854/3 4263/4 +f 4263/1 1854/2 1860/3 4264/4 +f 4264/1 1860/2 1866/3 4265/4 +f 1863/1 1862/2 1868/3 4825/4 +f 1864/1 1863/2 4825/3 4826/4 +f 1865/1 1864/2 4826/3 3135/4 +f 1866/1 1865/2 3135/3 3134/4 +f 4265/1 1866/2 3134/3 4266/4 +f 4827/13 1872/14 1873/15 4828/16 +f 1896/57 4829/67 1892/50 +f 4830/21 4831/22 1896/23 4723/24 +f 3643/34 3642/54 4831/53 4830/33 +f 4832/46 4830/36 4723/48 4724/47 +f 1869/15 1888/16 4724/13 1870/14 +f 1891/21 4832/22 4724/23 1888/24 +f 1889/13 1872/14 4827/15 4833/16 +f 4834/21 1890/22 1889/23 4833/24 +f 4833/13 4827/14 4168/15 4173/16 +f 4835/46 4834/36 4833/48 4173/47 +f 1909/40 1908/41 1688/20 4729/17 +f 1900/40 4727/17 4728/20 1907/41 +f 1906/18 1905/69 4726/70 4725/19 +f 1895/18 1894/19 1906/70 4725/69 +f 1893/10 1810/11 1901/84 1902/74 +f 4725/17 1684/20 1903/19 1895/18 +f 1320/57 4836/50 4829/67 4837/2 +f 4728/40 1688/17 1908/20 1907/41 +f 1892/57 4829/2 4836/67 1893/50 +f 4836/57 1810/2 1893/50 +f 4829/33 1896/53 4831/43 4838/42 +f 4836/33 4839/42 4811/43 1810/53 +f 1898/17 1901/18 4824/19 4730/20 +f 4730/17 4728/18 1899/19 1898/20 +f 3324/58 1910/49 1913/50 3325/57 +f 3325/56 1913/58 1915/57 4840/55 +f 4841/56 1918/58 1917/57 4842/55 +f 1917/35 1916/37 4842/36 +f 4843/56 4840/55 1915/57 1917/58 +f 1918/34 1921/54 4843/53 1917/33 +f 1918/56 4841/58 1923/57 1919/55 +f 1910/36 3324/46 1927/85 1926/35 +f 4844/18 4841/19 4842/70 4845/69 +f 4841/18 4844/19 1930/70 1923/69 +f 4846/40 4845/17 4842/20 1916/41 +f 4847/18 4846/69 1916/70 1914/19 +f 1914/18 1912/69 4848/70 4847/19 +f 1929/69 4848/70 1912/74 1911/10 +f 1932/89 1931/45 3549/44 +f 1805/29 1942/9 1937/12 1936/32 +f 1940/29 4849/9 3558/12 1945/32 +f 1938/29 4850/9 4849/12 1940/32 +f 1937/29 1944/9 4850/12 1938/32 +f 4796/29 1941/9 1946/12 4797/32 +f 1948/29 1939/9 1941/12 4796/32 +f 1802/29 1805/9 1936/12 1947/32 +f 1958/66 4797/65 1953/69 1955/18 +f 4797/66 1946/65 1950/69 1953/18 +f 1945/66 3558/65 3550/69 1949/18 +f 1949/45 3550/44 1934/89 1951/83 +f 1959/18 4541/69 1957/66 +f 1959/45 1960/89 4541/83 +f 4851/29 1968/12 1764/9 +f 4851/29 1764/12 1778/9 +f 4851/29 1965/32 1964/12 1968/9 +f 4852/29 1961/32 1962/12 1963/9 +f 4853/29 4854/32 1975/12 4855/9 +f 4855/29 1975/32 1934/12 1961/9 +f 4855/29 1961/32 4852/12 4856/9 +f 1931/89 3550/44 3549/83 +f 4857/52 3619/86 3612/21 3616/51 +f 4858/66 4859/18 4543/69 4542/65 +f 1968/45 1967/83 1765/89 1764/44 +f 4543/35 4859/36 3629/37 4544/8 +f 4541/6 1960/87 1971/73 907/7 +f 1971/29 912/32 4540/12 907/9 +f 912/29 1971/32 1970/12 909/9 +f 909/29 1970/32 1972/12 4542/9 +f 4542/55 1972/57 1973/2 4858/1 +f 4858/29 1973/32 1974/12 3619/9 +f 3619/29 1974/32 1975/12 4854/9 +f 1765/17 1967/18 1977/19 1772/20 +f 1976/89 1932/83 3549/45 1978/44 +f 1979/45 1789/44 1772/89 1977/83 +f 4857/9 4858/12 3619/29 +f 4857/66 3616/18 4859/69 4858/65 +f 1993/73 1992/66 310/18 309/17 +f 2020/40 2019/17 4860/20 2032/41 +f 2014/73 2013/66 314/18 313/17 +f 2016/73 2014/66 313/18 4303/17 +f 1992/73 2017/66 316/18 310/17 +f 2031/70 4861/74 4862/69 +f 4861/17 2031/20 2030/19 4863/18 +f 2029/17 2011/20 4863/19 2030/18 +f 2017/73 2016/66 4303/18 316/17 +f 2011/40 2010/41 2032/20 4860/17 +f 1985/17 1989/18 2023/19 4325/20 +f 1986/17 1985/18 4325/19 4860/20 +f 2011/71 4860/72 354/6 3962/5 +f 2012/35 2019/8 4860/37 2011/36 +f 1998/69 2024/70 2031/74 4862/10 +f 2013/73 1993/66 309/18 314/17 +f 4864/21 3694/22 4865/23 4866/24 +f 3427/28 3706/29 4867/9 3428/65 +f 4868/53 3707/55 3706/1 4869/43 +f 4870/53 4869/55 3706/1 3427/43 +f 4806/33 3710/53 3707/43 4868/42 +f 3694/41 4864/88 3428/37 4867/40 +f 4712/3 4716/59 4871/62 2062/63 +f 2096/29 3503/32 3502/12 4393/9 +f 2090/29 4872/32 3503/12 2096/9 +f 2044/29 4873/32 4872/12 2090/9 +f 1672/45 2080/44 2069/89 1669/83 +f 1669/17 2069/18 2070/19 1668/20 +f 4712/45 2062/44 2038/89 2037/83 +f 2034/29 2033/32 2080/12 1672/9 +f 4716/45 1668/83 2070/89 4871/44 +f 2049/29 4874/12 2050/9 +f 1806/29 4798/32 2054/12 2055/9 +f 1806/29 2055/12 1807/9 +f 2089/75 1807/76 2055/77 2047/72 +f 4391/78 4795/75 1807/72 2089/71 +f 534/78 540/75 4795/72 4391/71 +f 2079/45 1776/83 2064/89 2063/44 +f 2066/45 2065/83 2069/89 2080/44 +f 2064/17 1776/18 1777/19 2067/20 +f 2075/45 2033/44 2036/89 2076/83 +f 2056/3 2059/63 2078/62 1790/59 +f 2061/3 2062/63 4871/62 2077/59 +f 1790/45 2078/44 2067/89 1777/83 +f 2077/45 4871/44 2070/89 2068/83 +f 4872/29 4714/32 4711/12 3503/9 +f 4791/50 2083/51 2082/68 4875/67 +f 4876/2 3081/67 2081/59 2084/3 +f 4784/2 4876/67 2084/59 2083/3 +f 3084/2 4785/67 4791/59 4875/3 +f 3080/2 3084/67 4875/59 2082/3 +f 3081/2 3080/67 2082/59 2081/3 +f 2085/29 2039/9 1793/12 1792/32 +f 2088/29 4390/9 4391/12 2089/32 +f 2039/29 2054/9 4798/12 1793/32 +f 2052/29 4873/9 2044/12 2043/32 +f 2048/29 4877/9 4873/12 2052/32 +f 2093/29 2040/9 2085/12 3083/32 +f 3083/29 2085/9 1792/12 4799/32 +f 2096/29 4393/9 4390/12 2088/32 +f 4878/1 2097/2 2100/3 2105/4 +f 2102/1 4878/2 2105/3 2103/4 +f 2802/1 2101/2 2104/3 2110/4 +f 2803/1 2802/2 2110/3 2112/4 +f 2804/1 2803/3 2112/4 +f 2100/1 2099/2 4566/3 2106/4 +f 2106/1 4566/2 4567/3 2117/4 +f 2117/1 4567/2 4568/3 2123/4 +f 2123/1 4568/2 4570/3 2129/4 +f 2129/1 4570/2 4571/3 2135/4 +f 2135/1 4571/2 4572/3 2141/4 +f 2141/1 4572/2 4290/3 4758/4 +f 2142/1 2141/2 4758/3 1723/4 +f 2143/1 2142/2 1723/3 1722/4 +f 2144/1 2143/2 1722/3 2147/4 +f 2114/1 2146/2 2149/3 4759/4 +f 2115/1 2114/2 4759/3 4760/4 +f 2804/42 2112/43 2151/44 2431/45 +f 2158/34 2157/54 986/53 992/33 +f 2159/56 2158/58 992/57 996/55 +f 2160/56 2159/58 996/57 1000/55 +f 2161/56 2160/58 1000/57 1004/55 +f 2162/34 2161/54 1004/53 4560/33 +f 2432/56 2162/58 4560/57 4561/55 +f 2431/58 2151/49 2162/50 2432/57 +f 3479/85 2168/35 2167/36 2194/46 +f 2189/13 2623/15 2624/16 +f 2166/46 2165/36 2623/48 2189/47 +f 4879/13 2193/14 2192/15 4880/16 +f 2185/29 2178/32 2171/12 853/9 +f 2173/10 2623/65 2176/9 +f 2173/10 2619/65 2623/9 +f 2173/10 2617/65 2619/9 +f 2173/10 2175/65 2617/9 +f 2194/15 2193/26 3482/5 3479/71 +f 2165/15 2164/71 2176/5 2623/26 +f 4881/15 4882/71 2617/5 2175/26 +f 2177/15 4881/71 2175/5 2174/26 +f 4883/67 4881/59 2177/60 2178/68 +f 2187/29 876/9 4528/12 4884/32 +f 2637/29 2183/9 2179/12 2634/32 +f 4883/29 2178/9 2183/12 2637/32 +f 2185/29 853/9 2188/12 2184/32 +f 2672/13 2596/14 4885/15 4886/16 +f 2191/13 2672/14 4886/15 2192/16 +f 4887/13 4886/14 4885/15 2419/16 +f 2192/13 4886/14 4887/15 4880/16 +f 2624/13 2671/14 2672/15 2191/16 +f 2189/13 2624/14 2191/15 2190/16 +f 4888/52 4889/51 2196/21 2195/86 +f 2170/73 2172/17 2196/18 4531/66 +f 4531/73 2196/17 4889/18 4530/66 +f 2163/37 2169/36 4888/35 2195/8 +f 4890/35 4888/8 2169/37 2168/36 +f 2171/67 2170/59 4531/60 853/68 +f 4862/29 2992/12 4891/9 +f 4892/29 4862/32 4891/12 4893/9 +f 4893/29 4891/32 4894/12 4895/9 +f 2464/29 4893/32 4895/12 2869/9 +f 2869/29 4895/32 4896/12 2870/9 +f 2992/67 4862/68 4863/60 4897/59 +f 4898/53 4899/55 3973/1 3972/43 +f 2198/53 4898/55 3972/1 2199/43 +f 4900/53 2197/55 2200/1 4901/43 +f 4902/53 4900/55 4901/1 3976/43 +f 4899/53 4902/55 3976/1 3973/43 +f 4903/86 4904/90 4898/22 2198/21 +f 4896/86 4903/90 2198/22 2197/21 +f 4905/86 4896/90 2197/22 4900/21 +f 3561/86 4905/90 4900/22 4902/21 +f 2201/29 2205/12 2208/9 +f 2201/29 2208/12 2219/9 +f 4906/29 4907/32 4908/12 2239/9 +f 4906/12 4347/9 3684/29 4909/32 +f 4347/29 4906/32 2239/12 2242/9 +f 2242/29 2241/32 417/12 415/9 +f 414/29 4347/32 2242/12 415/9 +f 2239/29 4908/32 2254/12 2240/9 +f 4910/29 3752/32 2254/12 4908/9 +f 4428/25 3603/85 4911/35 605/26 +f 605/25 4911/85 4912/35 606/26 +f 607/68 2246/60 2245/79 4441/24 +f 4442/25 2244/85 2248/35 2250/26 +f 4441/25 2245/85 2244/35 4442/26 +f 2251/25 2243/85 2246/35 607/26 +f 2241/25 2253/85 4913/35 417/26 +f 3752/25 4914/85 2255/35 2254/26 +f 2253/24 2257/23 4912/82 4913/79 +f 4914/24 4915/23 2258/82 2255/79 +f 606/25 4912/85 2257/35 2259/26 +f 4424/25 2258/85 4915/35 4427/26 +f 2260/25 2256/85 2258/35 4424/26 +f 598/68 2264/60 2263/79 599/24 +f 4676/24 4675/23 2262/82 2261/79 +f 4438/25 2262/85 4675/35 4421/26 +f 599/25 2263/85 2262/35 4438/26 +f 4420/25 4676/85 2261/35 4425/26 +f 4425/25 2261/85 2264/35 598/26 +f 4437/25 4916/85 4917/35 4439/26 +f 4423/25 4681/85 4916/35 4437/26 +f 2266/13 145/14 4243/15 2267/16 +f 2279/13 2271/14 2272/15 4918/16 +f 2267/13 4243/14 2394/15 2393/16 +f 2268/13 2267/14 2393/15 2397/16 +f 2270/13 2268/14 2397/15 2399/16 +f 2272/13 2270/14 2399/15 2401/16 +f 4918/13 2272/14 2401/15 4919/16 +f 4920/13 4921/14 3371/15 2280/16 +f 4918/13 4920/14 2280/15 2279/16 +f 2276/58 2275/57 3379/50 2288/49 +f 2283/46 2278/47 2277/48 3378/36 +f 3377/49 2284/50 2283/51 3378/52 +f 2275/56 2284/55 3377/57 3379/58 +f 4922/42 4923/43 4924/44 4925/45 +f 4923/43 2286/1 2288/4 4924/44 +f 2287/1 2291/2 4151/3 2289/4 +f 4923/2 2290/4 2286/1 +f 2289/1 4151/2 4152/3 2292/4 +f 2294/1 2292/2 4152/3 4926/4 +f 2294/1 4926/3 4927/4 +f 2294/42 4927/43 2308/44 2295/45 +f 4927/43 4248/1 4250/4 2308/44 +f 2266/15 2304/14 146/13 145/16 +f 148/46 146/47 2304/48 2305/36 +f 150/49 148/50 2305/51 2306/52 +f 4260/56 150/55 2306/57 2307/58 +f 4250/58 4260/57 2307/50 2308/49 +f 2314/9 4395/12 4394/29 +f 4395/29 2314/9 2313/12 4397/32 +f 2313/9 4928/12 4397/29 +f 2341/5 4407/8 2317/7 2316/6 +f 2323/5 2322/8 4407/7 2341/6 +f 2985/5 2984/8 2321/7 2320/6 +f 4394/2 2325/3 2324/59 2314/67 +f 2313/8 2984/7 4929/40 4930/37 +f 4928/66 2313/65 4930/69 4648/18 +f 4931/13 2974/14 2977/15 4932/16 +f 4929/46 2974/47 4931/48 4930/36 +f 595/3 4406/63 2318/62 2317/59 +f 2325/3 596/63 4407/62 2322/59 +f 2315/3 2324/63 2321/62 2984/59 +f 2309/5 4721/8 4722/7 4933/6 +f 4721/7 2309/6 2311/5 4720/8 +f 2331/9 3653/10 4934/11 2332/12 +f 2336/9 2332/12 4934/11 3650/10 +f 2336/9 3650/10 3652/11 2339/12 +f 2331/9 2339/12 3652/11 3653/10 +f 2319/1 4935/4 2340/3 2316/2 +f 4935/1 2311/4 2310/3 2340/2 +f 2985/1 2320/4 2323/3 2333/2 +f 2985/1 2333/4 2312/3 2986/2 +f 2312/3 2309/2 4933/1 2986/4 +f 4931/13 4932/14 4646/15 4647/16 +f 4648/21 4930/22 4931/23 4647/24 +f 4936/13 1184/15 1186/16 +f 4937/13 4617/15 1184/16 +f 4938/37 2471/40 2343/41 2342/88 +f 3039/37 4938/40 2342/41 2346/88 +f 2473/66 2353/65 2343/69 2471/18 +f 3040/66 3039/18 2346/69 2356/65 +f 2353/29 2473/32 4939/12 4940/9 +f 2351/29 2353/32 4940/12 2357/9 +f 2360/29 4506/32 4510/12 2361/9 +f 4510/29 4509/32 3040/12 2356/9 +f 2361/29 4510/32 2356/12 2354/9 +f 2370/29 2371/32 4941/12 4942/9 +f 2370/29 4942/12 4943/9 +f 2366/29 2370/32 4943/12 4944/9 +f 2366/29 4944/32 4945/12 2367/9 +f 4941/29 2371/32 2378/12 4946/9 +f 4946/2 2378/67 2374/59 4947/3 +f 4947/21 2374/22 2377/23 1914/24 +f 1916/13 1914/14 2377/15 2388/16 +f 4841/13 4842/14 2388/15 2382/16 +f 2381/46 4948/36 4841/48 2382/47 +f 2367/2 4945/67 4948/59 2381/3 +f 4311/16 4208/15 4516/13 +f 4515/13 323/16 4311/15 4516/14 +f 4515/16 324/15 323/13 +f 1929/6 1928/87 4943/73 4942/7 +f 2378/29 2371/9 2896/12 2379/32 +f 2897/6 2896/7 2371/73 2348/87 +f 2373/6 2369/7 803/73 809/87 +f 4512/46 2380/36 2383/48 4513/47 +f 2368/2 2364/67 2380/59 4512/3 +f 2920/13 4937/14 1184/15 2385/16 +f 2921/13 2920/14 2385/15 2384/16 +f 2921/13 2384/14 2377/15 2376/16 +f 4936/15 2386/16 2385/13 1184/14 +f 2386/13 4936/14 328/15 2389/16 +f 2389/13 328/14 326/15 2391/16 +f 2391/13 326/14 324/15 4515/16 +f 2392/13 2391/14 4515/15 4514/16 +f 2392/13 4514/14 4513/15 2383/16 +f 2352/69 2358/10 2897/74 2348/70 +f 2363/69 2359/10 2373/74 809/70 +f 4949/13 2415/16 2414/15 4865/14 +f 4865/13 2414/16 2413/15 4866/14 +f 4866/13 2413/16 4950/15 4951/14 +f 4951/13 4950/16 3021/15 3020/14 +f 4245/13 4244/14 4952/15 2403/16 +f 2394/13 4245/14 2403/15 2395/16 +f 4919/13 2401/14 2402/15 2410/16 +f 2403/13 4952/14 2412/15 2404/16 +f 3450/13 3448/14 3021/15 4950/16 +f 2412/13 3450/14 4950/15 2413/16 +f 2411/13 2409/14 2419/15 4885/16 +f 2595/13 3402/14 4885/15 2596/16 +f 4919/13 3397/14 4920/15 4918/16 +f 4921/13 4920/15 3397/16 +f 2410/13 3398/14 3397/15 4919/16 +f 4885/13 3402/15 2411/16 +f 2411/13 3402/14 3398/15 2410/16 +f 4887/13 2419/14 2418/15 4953/16 +f 3470/13 4880/14 4887/15 4953/16 +f 4953/13 2418/14 2417/15 4954/16 +f 3470/13 4953/16 4954/15 4955/14 +f 4954/13 2417/14 2416/15 4956/16 +f 4956/13 2416/14 2415/15 4949/16 +f 4957/73 4705/6 4958/87 +f 4959/6 4960/7 4957/73 4958/87 +f 4957/9 4960/12 4961/29 +f 4778/46 4779/36 2461/48 4256/47 +f 4256/13 2461/14 2462/15 4257/16 +f 3227/17 3231/18 4962/19 4295/20 +f 4962/70 3231/74 4960/69 +f 2438/49 4561/52 2429/51 2428/50 +f 2433/34 2432/54 4561/53 2438/33 +f 4963/54 2440/56 2439/55 2445/53 +f 2456/54 4963/56 2445/55 2450/53 +f 4959/34 2455/54 2454/53 2460/33 +f 2423/54 2422/56 2455/55 4959/53 +f 4779/21 2459/22 2457/23 2461/24 +f 4962/49 2460/52 2459/51 4779/50 +f 4960/56 4959/58 2460/57 4962/55 +f 4295/50 4962/52 4779/51 +f 4964/29 1991/12 1990/9 +f 4892/29 4964/32 1990/12 1998/9 +f 4892/29 1998/12 4862/9 +f 2470/37 2468/40 4938/41 3039/88 +f 2468/37 2466/40 2471/41 4938/88 +f 4965/29 4966/12 1991/9 +f 4964/12 2467/9 2469/29 4967/32 +f 2467/29 4964/32 4892/12 2463/9 +f 2463/29 4892/32 4893/12 2464/9 +f 4939/29 2473/32 2472/12 2464/9 +f 1991/67 4966/68 4326/60 4325/59 +f 4325/71 354/6 4860/5 +f 2475/29 4904/32 4903/12 4968/9 +f 4904/12 2475/9 2478/29 4969/32 +f 4891/29 2992/32 2991/12 4894/9 +f 2476/29 3017/32 3015/12 2474/9 +f 4894/29 2991/32 4968/12 4903/9 +f 4895/29 4894/32 4903/12 4896/9 +f 2474/29 3015/12 2477/9 +f 2478/29 2477/32 3016/12 4970/9 +f 4969/29 2478/32 4970/12 3562/9 +f 2477/29 3015/12 3016/9 +f 4971/15 4972/71 4973/5 4974/26 +f 4975/71 4976/5 3961/6 3960/72 +f 4976/71 4977/5 4897/6 3961/72 +f 3960/72 4972/6 4971/87 4975/77 +f 2992/67 4897/59 4977/60 2987/68 +f 4634/73 4971/18 4974/17 +f 2481/7 3009/40 3010/17 4978/73 +f 4978/7 3010/40 4979/17 2484/73 +f 2484/7 4979/40 4980/17 4981/73 +f 4979/50 3010/51 3006/68 4980/67 +f 4982/28 2483/29 2484/9 4981/65 +f 4983/53 2487/55 2483/1 4982/43 +f 2991/86 2990/90 2486/22 2485/21 +f 4968/86 2991/90 2485/22 2487/21 +f 2475/86 4968/90 2487/22 4983/21 +f 4971/52 4634/86 4309/21 318/51 +f 4305/33 4984/42 4975/43 4971/53 +f 4330/10 4635/65 4974/9 +f 4973/65 4985/69 4330/10 4974/9 +f 318/57 4305/67 4971/2 +f 4904/86 4969/90 4899/22 4898/21 +f 4229/30 2489/29 2513/32 78/31 +f 2489/28 4229/29 91/27 +f 78/16 2513/25 2512/26 79/15 +f 90/30 92/31 2490/32 2489/29 +f 91/27 90/29 2489/28 +f 92/16 112/15 4986/26 2490/25 +f 2491/35 2490/8 4986/37 2492/36 +f 2494/16 2493/25 4987/26 4988/15 +f 112/16 4226/15 4989/26 4986/25 +f 2492/27 4986/30 4987/29 2493/28 +f 4989/26 4226/15 4228/25 +f 2805/25 4990/26 4228/16 +f 4991/16 2508/25 2507/26 2828/15 +f 2828/16 2507/25 2497/26 2496/15 +f 2805/16 2807/25 4991/26 4990/15 +f 2823/25 4989/26 4228/16 +f 4990/25 2823/26 4228/16 +f 2807/16 4992/25 2508/26 4991/15 +f 2501/35 2500/36 2512/37 2513/8 +f 2488/35 2501/36 2513/37 2489/8 +f 2502/16 2511/15 4993/26 2503/25 +f 2490/35 4986/37 2499/36 +f 2499/16 4986/15 4994/26 2496/25 +f 4986/16 4989/15 2823/26 4994/25 +f 4990/16 4991/15 2824/26 2823/25 +f 2824/16 4991/26 2828/25 +f 79/16 2512/25 4995/26 4239/15 +f 4240/25 4239/15 4995/26 +f 4240/15 4996/25 4997/16 +f 2506/16 1249/15 2497/26 2507/25 +f 4240/16 4995/26 1251/25 +f 1251/25 4996/26 4240/16 +f 1249/16 2514/15 2498/26 2497/25 +f 2514/16 2513/15 2489/26 2498/25 +f 4998/16 2505/15 2508/26 4992/25 +f 2514/16 1249/25 1248/26 2512/15 +f 2512/16 1248/25 1251/26 4995/15 +f 4996/16 1251/25 2509/26 2505/15 +f 2495/16 2494/15 4988/26 4999/25 +f 2489/35 2488/8 2495/37 4999/36 +f 4986/16 2490/15 4988/26 4987/25 +f 2490/16 2489/15 4999/26 4988/25 +f 2513/16 2512/15 4993/26 2511/25 +f 2489/16 2513/15 2511/26 2510/25 +f 2512/27 2500/30 2503/29 4993/28 +f 4814/49 4813/52 2516/51 4812/50 +f 2516/49 1815/51 2517/50 +f 4816/49 2520/51 4817/50 +f 4817/49 2520/51 4818/50 +f 4818/51 4814/50 4812/49 4817/52 +f 2521/49 2520/51 4816/50 +f 4822/49 2519/52 2521/51 4733/50 +f 4733/49 2521/52 4816/51 4278/50 +f 2585/29 2584/32 5000/12 2640/9 +f 5001/66 2638/65 2639/69 4882/18 +f 3281/66 5002/65 2677/69 5003/18 +f 5002/8 5000/7 2616/40 2677/37 +f 2584/66 2607/18 2616/69 5000/65 +f 2600/13 2609/16 5004/15 3805/14 +f 2609/13 2611/16 5005/15 5004/14 +f 2611/13 2613/16 5006/15 5005/14 +f 4882/21 2639/22 2621/23 2617/24 +f 4883/29 2590/32 2638/12 5001/9 +f 5001/67 4882/59 4881/60 4883/68 +f 2590/29 4883/9 2637/12 2636/32 +f 2942/8 5007/7 2646/40 2645/37 +f 2928/66 2942/65 2645/69 2654/18 +f 2640/66 2928/65 2654/69 2641/18 +f 5008/13 2594/14 2650/15 2649/16 +f 2647/13 5008/14 2649/15 2648/16 +f 5003/46 2677/36 2673/48 2676/47 +f 4332/33 4334/42 2683/43 2682/53 +f 2692/53 2688/55 2683/1 4334/43 +f 4334/71 2689/72 2691/6 2692/5 +f 2687/15 2686/71 1153/5 2696/26 +f 2686/15 2688/71 1154/5 1153/26 +f 2688/15 2692/71 2694/5 1154/26 +f 2698/12 1541/42 4693/45 2699/11 +f 2758/1 4262/2 2765/3 2759/4 +f 4700/1 2757/2 2760/3 2769/4 +f 2762/1 4700/2 2769/3 2763/4 +f 4701/1 2761/2 2764/3 2773/4 +f 2767/1 2766/2 228/3 2776/4 +f 2776/1 228/2 229/3 2727/4 +f 2727/1 229/2 235/3 2719/4 +f 2719/1 235/2 2796/3 2717/4 +f 2725/1 2797/2 2098/3 2097/4 +f 2704/1 2725/2 2097/3 4878/4 +f 2701/1 2704/2 4878/3 2102/4 +f 2798/1 2701/2 2102/3 2101/4 +f 2799/1 2798/2 2101/3 2802/4 +f 2782/1 2421/2 2420/3 2775/4 +f 2787/1 2421/3 2782/4 +f 4704/5 5009/6 4958/7 4705/8 +f 5009/5 2423/6 4959/7 4958/8 +f 4701/43 2773/1 4704/4 4702/44 +f 2773/42 2775/43 5009/44 4704/45 +f 2775/43 2420/1 2423/4 5009/44 +f 2421/43 2787/1 2456/4 2422/44 +f 2787/42 2791/43 4963/44 2456/45 +f 2791/43 2795/1 2440/4 4963/44 +f 2795/42 2801/43 2430/44 2440/45 +f 2801/43 2804/1 2431/4 2430/44 +f 4997/16 4996/15 2505/26 4998/25 +f 4682/21 1158/22 1160/23 4690/24 +f 1160/13 4240/14 4336/15 4690/16 +f 4240/13 4997/14 2812/15 4336/16 +f 4997/13 4998/14 2813/15 2812/16 +f 4593/8 4666/7 4761/40 4594/37 +f 4594/21 4761/22 4763/23 4227/24 +f 4227/13 4763/16 5010/15 4228/14 +f 4228/13 5010/16 2808/15 2805/14 +f 4667/66 4605/65 1158/69 4682/18 +f 5010/13 4764/16 2810/15 2808/14 +f 4763/13 4762/16 4764/15 5010/14 +f 1311/73 2820/7 2818/17 +f 1312/73 1311/7 2818/17 +f 2817/73 1312/7 2818/17 +f 5011/17 4056/7 4055/73 +f 5011/17 4055/7 4058/73 +f 5011/17 4058/7 5012/73 +f 5011/17 5012/7 5013/73 +f 5011/17 5013/7 5014/73 +f 5011/17 5014/7 4056/73 +f 2826/65 2825/9 2831/10 4615/69 +f 2832/65 2827/9 2828/10 2496/69 +f 2835/65 2832/9 2496/10 4994/69 +f 2822/65 2835/9 4994/10 2823/69 +f 2836/65 2826/9 4615/10 2837/69 +f 4624/65 2840/69 2839/10 4625/9 +f 4625/65 2839/69 2841/10 4626/9 +f 4626/65 2841/69 2842/10 2843/9 +f 2840/10 4624/9 2845/65 2844/69 +f 2849/71 2848/5 4781/6 2851/72 +f 2851/72 4781/6 4782/87 2852/77 +f 2852/71 4782/5 1752/6 5015/72 +f 5015/72 1752/6 1751/87 2968/77 +f 2846/5 2849/6 469/71 +f 469/71 2849/5 2851/6 2850/72 +f 2853/71 2852/5 5015/6 1366/72 +f 5015/5 2968/6 1366/71 +f 4182/1 2864/2 2865/3 4183/4 +f 2857/1 2856/2 4628/3 4627/4 +f 2859/1 2857/2 4627/3 2866/4 +f 2863/1 2861/2 2867/3 1294/4 +f 2865/1 2863/2 1294/3 1293/4 +f 4183/1 2865/2 1293/3 4186/4 +f 5016/29 5017/9 5018/12 5019/32 +f 5017/12 5016/32 4038/29 4039/9 +f 4854/29 4853/32 3625/12 3626/9 +f 3619/29 4854/32 3626/12 3620/9 +f 4937/13 5020/14 1178/15 4617/16 +f 4939/29 2464/32 2869/12 2868/9 +f 4940/29 4939/32 2868/12 2872/9 +f 2357/29 4940/32 2872/12 2878/9 +f 2358/29 2357/12 2878/9 +f 2870/29 4896/32 4905/12 5021/9 +f 2871/29 2870/32 5021/12 2874/9 +f 2874/29 5021/32 5022/12 2876/9 +f 2876/29 5022/12 5023/9 +f 2882/29 2881/9 2890/12 4776/32 +f 2379/29 2896/9 2888/12 2887/32 +f 2882/2 4776/67 2899/59 2898/3 +f 2375/21 2908/22 2909/23 2376/24 +f 2379/2 2887/67 2908/59 2375/3 +f 3582/13 3581/14 5024/15 3584/16 +f 3584/13 5024/14 3773/15 2911/16 +f 3585/13 3584/14 2911/15 2910/16 +f 3585/13 2910/14 2901/15 2900/16 +f 2911/13 3773/14 3776/15 2912/16 +f 2912/13 3776/14 5025/15 2914/16 +f 2914/13 5025/14 5026/15 2916/16 +f 2916/13 5026/14 5020/15 2918/16 +f 4937/15 2920/16 2918/13 5020/14 +f 2919/13 2921/14 2376/15 2909/16 +f 2876/69 5023/10 2889/74 2891/70 +f 2358/69 2878/10 2895/74 2897/70 +f 2931/29 2930/32 5027/12 4692/9 +f 2930/29 2935/32 3282/12 5027/9 +f 2935/29 2937/32 3283/12 3282/9 +f 2937/29 2939/32 3284/12 3283/9 +f 2939/29 2922/32 2925/12 3284/9 +f 2928/29 2640/32 5000/12 2929/9 +f 3380/29 2943/32 2933/12 2932/9 +f 2947/29 5007/32 2941/12 2940/9 +f 5007/29 2942/12 2941/9 +f 468/5 2951/6 2954/71 +f 5028/15 2966/26 2956/5 2955/71 +f 2958/15 2957/26 2967/5 5029/71 +f 5029/15 2967/26 2952/5 2951/71 +f 2954/15 2953/26 2966/5 5028/71 +f 469/13 468/14 2954/15 2846/16 +f 2847/71 2846/5 2968/6 1751/72 +f 1366/13 2968/15 2971/16 +f 5028/13 5030/14 5031/15 2954/16 +f 2954/13 5031/14 5032/15 2846/16 +f 2846/13 5032/14 2969/15 2968/16 +f 4645/13 1366/14 2971/15 2973/16 +f 2973/13 2972/14 5033/15 5034/16 +f 2984/66 2983/65 5035/69 4929/18 +f 2983/66 4722/65 4753/69 5035/18 +f 2975/13 4752/14 2978/15 2976/16 +f 5035/21 4753/22 4752/23 2975/24 +f 4929/46 5035/36 2975/48 2974/47 +f 2986/5 4933/6 4722/7 2983/8 +f 3636/29 3635/12 3018/9 +f 2988/29 3636/32 3018/12 2989/9 +f 2989/29 3018/32 3017/12 2476/9 +f 2994/33 2993/53 5036/43 5037/42 +f 2995/33 5038/42 5039/43 2996/53 +f 2993/33 2996/53 5039/43 5036/42 +f 2999/56 3643/58 4830/57 4832/55 +f 2998/58 3640/49 3643/50 2999/57 +f 3000/34 2999/54 4832/53 1891/33 +f 3002/56 3000/58 1891/57 1890/55 +f 3004/34 3002/54 1890/53 4834/33 +f 4175/56 3004/58 4834/57 4835/55 +f 4162/58 3003/49 3004/50 4175/57 +f 4974/17 4635/18 4634/73 +f 3008/7 3007/40 3009/17 2481/73 +f 4981/7 4980/40 3006/17 3005/73 +f 3014/28 3013/29 3005/9 3008/65 +f 2480/28 3014/29 3008/9 2481/65 +f 3013/28 4982/29 4981/9 3005/65 +f 2486/26 3011/5 3014/8 2480/35 +f 3012/26 4983/5 4982/8 3013/35 +f 2989/86 2476/90 3012/22 3011/21 +f 2990/86 2989/90 3011/22 2486/21 +f 2476/86 2475/90 4983/22 3012/21 +f 3016/66 3003/18 4162/69 4970/65 +f 3635/8 3640/37 2998/40 3018/7 +f 2995/33 4837/53 5040/43 5038/42 +f 4837/33 4829/53 4838/43 5040/42 +f 4305/33 2994/53 5037/43 4984/42 +f 5026/13 3781/15 1182/16 +f 5020/13 1179/15 1178/16 +f 5020/13 5026/14 1182/15 1179/16 +f 5041/18 5042/19 5043/70 5044/69 +f 5042/18 5041/19 5045/70 5046/69 +f 4942/69 4941/10 5046/74 5045/70 +f 4847/17 4848/18 5045/19 5041/20 +f 1929/69 4942/10 5045/74 4848/70 +f 4941/69 4946/10 4947/74 5046/70 +f 5042/17 5046/18 4947/19 1914/20 +f 5043/17 5042/18 1914/19 1916/20 +f 5047/13 3019/14 3022/15 5048/16 +f 3025/13 5047/14 5048/15 5049/16 +f 3028/34 3687/54 3024/53 3023/33 +f 4909/66 3684/65 3687/69 3028/18 +f 5050/8 4909/7 3028/40 3027/37 +f 4907/66 5050/65 3027/69 5051/18 +f 3768/46 3029/36 3030/48 3767/47 +f 5051/34 3027/54 3029/53 3768/33 +f 4909/29 5050/32 4907/12 4906/9 +f 4804/69 3033/70 3032/74 4800/10 +f 4478/69 3036/70 3033/74 4804/10 +f 3031/17 5052/18 3431/19 3430/20 +f 3430/17 5053/18 3032/19 3031/20 +f 4801/69 4800/10 3032/74 5053/70 +f 3038/37 2470/41 3039/88 +f 2470/88 3038/48 3041/36 2469/37 +f 4509/29 3041/32 3037/12 3040/9 +f 4967/29 4965/32 1991/12 4964/9 +f 3043/29 3058/32 3180/12 3044/9 +f 3047/29 3045/32 5054/12 3050/9 +f 792/29 3048/32 3049/12 793/9 +f 4359/29 3052/12 4511/9 +f 793/29 3049/32 3051/12 3041/9 +f 794/29 793/32 3041/12 4509/9 +f 4511/29 3052/32 3054/12 3055/9 +f 4508/29 4511/32 3055/12 3056/9 +f 3050/29 5054/32 4966/12 4965/9 +f 3051/29 3050/32 4965/12 4967/9 +f 3041/29 3051/32 4967/12 2469/9 +f 799/29 3057/32 3048/12 792/9 +f 3212/7 3211/40 3060/17 3059/73 +f 3211/50 3209/51 3061/68 3060/67 +f 5055/28 3068/29 3062/9 5056/65 +f 3066/28 3065/29 3212/9 5057/65 +f 3068/28 3066/29 5057/9 3062/65 +f 3218/53 3067/55 3068/1 5055/43 +f 3217/86 5054/90 3067/22 3218/21 +f 5054/86 3045/90 3063/22 3067/21 +f 3078/29 4876/32 4793/12 3079/9 +f 3082/29 3081/32 4876/12 3078/9 +f 2094/29 3080/32 3082/12 3105/9 +f 4799/29 4785/32 3084/12 3083/9 +f 4784/29 4783/32 4793/12 4876/9 +f 4786/29 3129/32 3086/12 3085/9 +f 3074/29 3129/12 4786/9 +f 1754/29 1804/32 3088/12 3087/9 +f 3091/29 908/12 3093/9 +f 2094/29 3105/32 3104/12 2091/9 +f 3074/29 4786/9 3114/12 3111/32 +f 4786/29 3087/9 3090/12 3114/32 +f 3098/29 3107/12 4319/9 +f 3110/29 3113/32 4223/12 4212/9 +f 3110/29 4212/12 4211/9 +f 3107/29 3110/32 4211/12 4319/9 +f 3113/29 3095/12 4223/9 +f 4223/29 3095/12 4224/9 +f 3098/29 4319/32 4318/12 4320/9 +f 3099/29 3098/32 4320/12 4321/9 +f 333/18 4317/69 4316/70 330/19 +f 4211/69 4316/70 4317/74 4319/10 +f 4216/44 4215/89 4214/64 4217/4 +f 3093/66 76/18 3115/69 3094/65 +f 908/66 77/18 76/69 3093/65 +f 5058/50 3132/51 3131/68 4792/67 +f 3079/2 4793/67 3130/59 3133/3 +f 1755/2 3085/67 3132/59 5058/3 +f 1756/2 1755/67 5058/59 4792/3 +f 3089/29 3088/9 904/12 903/32 +f 3091/29 3089/9 903/12 908/32 +f 3088/29 1804/9 906/12 904/32 +f 2094/29 2093/9 3083/12 3080/32 +f 1868/1 1867/2 3139/3 3138/4 +f 4825/1 1868/2 3138/3 3142/4 +f 4826/1 4825/2 3142/3 3144/4 +f 3135/1 4826/2 3144/3 3136/4 +f 4266/1 3134/2 3137/3 1066/4 +f 1066/1 3137/2 3147/3 1067/4 +f 1067/1 3147/2 3153/3 1081/4 +f 1081/1 3153/2 3159/3 1089/4 +f 1089/1 3159/2 3165/3 4569/4 +f 4569/1 3165/2 3171/3 1111/4 +f 1111/1 3171/2 3177/3 1112/4 +f 3173/1 3172/2 4496/3 733/4 +f 3174/1 3173/2 733/3 732/4 +f 3175/1 3174/2 732/3 736/4 +f 3176/1 3175/2 736/3 3178/4 +f 1112/1 3177/2 3179/3 4283/4 +f 3183/21 4354/22 4353/23 5059/24 +f 3184/46 3183/36 5059/48 5060/47 +f 4352/13 4351/14 5061/15 5062/16 +f 5062/13 5061/14 5063/15 5064/16 +f 4353/13 4352/14 5062/15 5059/16 +f 5059/13 5062/14 5064/15 5060/16 +f 3052/66 4359/65 4356/69 5065/18 +f 3053/8 3052/7 5065/40 5066/37 +f 3180/29 3058/12 3181/9 +f 4354/53 3183/33 3186/34 4355/54 +f 5065/54 4356/56 4355/55 3186/53 +f 5066/58 5065/49 3186/50 3185/57 +f 3188/29 3187/32 3190/12 3637/9 +f 3217/29 3188/32 3637/12 3639/9 +f 5054/29 3217/32 3639/12 4966/9 +f 5060/13 5064/14 3192/15 3191/16 +f 5067/21 3184/22 5060/23 3191/24 +f 3197/34 3185/54 3184/53 5067/33 +f 3196/54 5066/56 3185/55 3197/53 +f 4809/46 5067/36 3191/48 3194/47 +f 3198/56 3197/58 5067/57 4809/55 +f 3202/34 3198/54 4809/53 4808/33 +f 3204/56 3202/58 4808/57 4810/55 +f 5068/34 3204/54 4810/53 4811/33 +f 3219/54 3203/56 3204/55 5068/53 +f 3062/7 3061/40 3206/17 3205/73 +f 3207/50 3206/67 3061/68 3209/51 +f 3215/28 5055/29 5056/9 3208/65 +f 3216/28 3215/29 3208/9 3210/65 +f 3065/28 3216/29 3210/9 3212/65 +f 3214/26 3218/5 5055/8 3215/35 +f 3064/26 3213/5 3216/8 3065/35 +f 3044/86 3180/90 3213/22 3064/21 +f 3058/66 3053/65 5066/69 3196/18 +f 3181/66 3058/65 3196/69 3195/18 +f 5064/13 5063/14 5069/15 3192/16 +f 3192/13 5069/14 4821/15 3193/16 +f 3193/13 4821/15 3199/16 +f 4703/6 4705/87 4957/73 5070/7 +f 4247/6 4703/87 5070/73 4252/7 +f 4254/29 4252/32 5070/12 5071/9 +f 4961/29 5071/9 5070/12 4957/32 +f 4295/17 4302/18 3228/19 3227/20 +f 4258/17 3235/20 3234/19 4301/18 +f 4300/6 4299/87 5071/73 4961/7 +f 4299/6 4298/87 4254/73 5071/7 +f 3221/40 3225/17 4302/20 3222/41 +f 3220/40 3223/41 4301/20 3224/17 +f 4301/40 3223/41 3222/20 4302/17 +f 4961/69 4960/10 3231/74 3230/70 +f 3235/18 4259/69 5072/70 3232/19 +f 4254/69 5072/70 4259/74 4253/10 +f 4300/69 4961/10 3230/74 3237/70 +f 3238/17 3232/20 5072/19 4780/18 +f 4298/69 4780/70 5072/74 4254/10 +f 4295/18 4294/69 3237/70 3236/19 +f 4300/10 3237/74 4294/84 4293/11 +f 3239/29 4650/12 3240/9 +f 3239/29 4662/32 4651/12 4650/9 +f 4664/29 3240/32 4650/12 4660/9 +f 3246/29 3248/32 5073/12 4662/9 +f 4662/12 3239/9 3242/29 3246/32 +f 4662/29 5073/32 4670/12 4663/9 +f 4669/29 3241/32 3240/12 4664/9 +f 4687/29 3251/32 4669/12 4668/9 +f 3251/29 3243/32 3241/12 4669/9 +f 3247/29 3799/32 5074/12 3248/9 +f 3257/29 3249/32 3251/12 4687/9 +f 3254/29 3800/32 3799/12 3247/9 +f 3255/29 3257/12 1496/9 +f 3261/29 3801/32 3800/12 3254/9 +f 1495/29 3262/32 3255/12 1496/9 +f 3267/29 3802/32 3801/12 3261/9 +f 1494/29 3268/32 3262/12 1495/9 +f 3273/29 3281/32 3802/12 3267/9 +f 3248/29 5074/32 5075/12 5073/9 +f 1497/29 5076/12 1494/9 +f 5076/29 3274/32 3268/12 1494/9 +f 5002/29 3281/12 3280/9 +f 4692/29 5027/32 5076/12 1497/9 +f 5027/29 3282/32 3274/12 5076/9 +f 3284/29 2925/32 3277/12 3276/9 +f 2925/29 2924/32 3278/12 3277/9 +f 2924/29 2927/32 3279/12 3278/9 +f 2927/29 2929/32 3280/12 3279/9 +f 2929/55 5000/57 5002/2 3280/1 +f 5073/29 5075/32 4671/12 4670/9 +f 3286/54 5077/56 5078/55 3287/53 +f 5079/54 3291/56 3292/55 4314/53 +f 3287/34 5078/54 5080/53 3293/33 +f 4314/34 3292/54 3296/53 4312/33 +f 4213/36 3300/8 3306/37 +f 3300/34 4213/54 4312/53 3296/33 +f 3322/58 3311/57 3310/50 3315/49 +f 3317/85 3316/35 3291/36 5079/46 +f 3315/85 3316/35 3318/36 3322/46 +f 5081/85 3320/35 3313/36 3312/46 +f 3286/36 3285/46 3320/85 5081/35 +f 3286/36 5081/85 3355/35 +f 4315/18 4312/19 4213/70 4218/69 +f 3317/10 5079/11 4314/84 4313/74 +f 60/40 4218/17 4213/20 3306/41 +f 61/18 60/69 3306/70 3305/19 +f 3321/18 61/69 3305/70 3311/19 +f 5077/58 3329/49 3330/50 5078/57 +f 3326/34 3325/54 4840/53 3331/33 +f 5078/56 3330/58 3333/57 5080/55 +f 3335/34 3331/33 4840/53 4843/54 +f 3340/56 5080/55 3333/57 3336/58 +f 3342/34 3293/33 5080/53 3340/54 +f 3298/58 3293/56 3342/57 +f 1921/56 3337/58 3335/57 4843/55 +f 3341/56 3301/58 3298/57 3342/55 +f 3337/56 1921/58 1920/57 3343/55 +f 3301/56 3341/58 3346/57 3307/55 +f 3347/58 3343/57 1920/50 1925/49 +f 3312/58 3307/57 3346/50 3350/49 +f 3352/85 3351/35 3329/36 5077/46 +f 1927/85 3354/35 3347/36 1925/46 +f 3324/36 3323/46 3354/85 1927/35 +f 3355/85 5081/35 3312/36 3350/46 +f 3355/85 3352/35 5077/36 3286/46 +f 3371/16 4921/15 3367/13 +f 2948/29 2944/12 2943/9 +f 2950/29 5082/32 2947/12 2946/9 +f 5082/29 5007/12 2947/9 +f 4925/58 3376/57 3719/50 3718/49 +f 4924/58 3375/57 3376/50 4925/49 +f 2288/58 3379/57 3375/50 4924/49 +f 3726/49 3373/50 3368/51 3369/52 +f 3376/56 3373/55 3726/57 3719/58 +f 3370/13 2277/16 2280/15 3371/14 +f 3378/46 2277/47 3370/48 3372/36 +f 2931/66 4692/65 1503/69 3388/18 +f 3381/8 2931/7 3388/40 3382/37 +f 2943/66 3380/65 3383/69 3393/18 +f 2948/66 2943/65 3393/69 3396/18 +f 2949/8 2948/7 3396/40 3401/37 +f 2950/66 2949/65 3401/69 3405/18 +f 5082/66 2950/65 3405/69 3408/18 +f 5007/66 5082/65 3408/69 2646/18 +f 1501/13 3358/14 3359/15 3384/16 +f 1502/13 1501/14 3384/15 3386/16 +f 3388/21 1503/22 1502/23 3386/24 +f 3389/13 3367/14 4921/15 3391/16 +f 3391/13 4921/14 3397/15 3394/16 +f 3403/13 3402/14 2595/15 3406/16 +f 3406/13 2595/14 2594/15 5008/16 +f 3407/13 3406/14 5008/15 2647/16 +f 2646/21 3408/22 3407/23 2647/24 +f 4842/13 1916/15 2388/16 +f 5083/18 5084/69 5085/70 5086/19 +f 5086/18 5087/69 5088/70 5083/19 +f 4943/69 5088/70 5087/74 4944/10 +f 1916/40 4842/17 3411/20 3410/41 +f 4846/40 3409/41 3412/20 4845/17 +f 5041/17 5044/18 4846/19 4847/20 +f 4844/17 5083/20 5088/19 1930/18 +f 5083/17 4844/20 4845/19 5084/18 +f 1928/69 1930/70 5088/74 4943/10 +f 3412/40 3411/41 4842/20 4845/17 +f 3409/40 4846/17 1916/20 3410/41 +f 4842/19 4841/20 5086/17 5085/18 +f 4841/17 4948/18 5087/19 5086/20 +f 4945/69 4944/10 5087/74 4948/70 +f 3413/37 3417/40 4870/41 3414/88 +f 4870/37 3431/40 3415/41 3414/88 +f 3416/37 3415/88 3431/41 3418/40 +f 4475/6 4478/87 4804/73 4807/7 +f 3034/18 5089/69 5052/70 3031/19 +f 4807/69 4805/10 3424/74 3423/70 +f 3034/17 3035/20 3418/19 5089/18 +f 3425/17 4490/18 3423/19 3419/20 +f 4475/69 4807/10 3423/74 4490/70 +f 4805/69 4806/10 4868/74 3424/70 +f 3420/17 3424/18 4868/19 4869/20 +f 3421/17 3420/18 4869/19 4870/20 +f 5090/21 5091/22 4951/23 3020/24 +f 5091/46 4864/36 4866/48 4951/47 +f 3432/28 3426/29 3429/9 3678/65 +f 3431/53 4870/55 3427/1 3426/43 +f 5092/53 5053/55 3430/1 3432/43 +f 4802/33 4801/53 5053/43 5092/42 +f 3429/37 3428/40 4864/41 5091/88 +f 5091/41 5090/88 3678/37 3429/40 +f 4041/35 4029/8 1647/37 5093/36 +f 3434/35 4041/8 5093/37 3435/36 +f 5094/35 3437/8 3438/37 5095/36 +f 4589/35 5094/8 5095/37 368/36 +f 133/13 3439/14 3442/15 3445/16 +f 134/13 133/14 3445/15 3447/16 +f 135/13 134/14 3447/15 3449/16 +f 4244/13 135/14 3449/15 4952/16 +f 4952/13 3449/14 3450/15 2412/16 +f 3444/13 3443/14 5049/15 5048/16 +f 3446/13 3444/14 5048/15 3022/16 +f 3448/13 3446/14 3022/15 3021/16 +f 4706/52 1310/51 3459/21 4631/86 +f 4333/52 2685/86 2684/21 2689/51 +f 4335/35 3455/8 3456/37 2684/36 +f 2680/35 2684/36 3456/37 3465/8 +f 5096/29 5097/12 5098/9 +f 3469/13 4879/14 4880/15 3470/16 +f 5097/29 5096/9 858/12 857/32 +f 3475/29 3474/9 4526/12 4527/32 +f 3473/29 5097/9 857/12 3474/32 +f 3478/21 2168/52 3479/86 +f 3475/29 4527/12 3476/9 +f 3480/10 4879/65 3469/9 +f 3480/10 2193/65 4879/9 +f 3480/10 3482/65 2193/9 +f 5099/21 3471/22 3470/23 4955/24 +f 5100/56 3484/58 3471/57 5099/55 +f 5101/13 4955/14 4954/15 4956/16 +f 3473/66 3472/65 3484/69 5100/18 +f 5097/66 3473/65 5100/69 5102/18 +f 4530/73 4889/17 3486/18 3485/66 +f 4890/52 3486/51 4889/21 4888/86 +f 2168/52 3478/51 3486/21 4890/86 +f 4527/67 3485/59 3477/60 3476/68 +f 4459/29 4524/32 4525/12 4460/9 +f 3491/29 3493/12 863/9 +f 2048/29 2051/12 4877/9 +f 4877/29 2051/32 3490/12 3489/9 +f 2051/75 2050/76 3497/77 3490/72 +f 3512/78 860/75 859/72 4524/71 +f 3507/78 863/75 860/72 3512/71 +f 3495/78 3491/75 863/72 3507/71 +f 3504/29 3503/32 4711/12 4713/9 +f 3501/29 4717/32 4708/12 3494/9 +f 4873/29 4877/12 4872/9 +f 3489/29 3488/32 4707/12 4710/9 +f 4877/29 4715/32 4714/12 4872/9 +f 3489/29 4710/32 4715/12 4877/9 +f 3504/29 4713/32 4717/12 3501/9 +f 3494/29 4708/32 4707/12 3488/9 +f 3502/29 4392/9 4389/12 4393/32 +f 5103/29 3497/9 2050/12 4874/32 +f 3504/29 3509/9 4392/12 3502/32 +f 3512/29 4462/9 3515/12 3511/32 +f 4462/29 4461/9 4464/12 3515/32 +f 4524/29 4459/9 4462/12 3512/32 +f 4384/55 4392/1 3509/2 4382/57 +f 3508/29 3514/9 4382/12 3509/32 +f 3514/29 685/9 684/12 4382/32 +f 3513/29 687/9 685/12 3514/32 +f 3515/29 4464/9 687/12 3513/32 +f 5104/44 3518/45 3517/89 +f 3543/44 5104/45 3557/89 +f 3557/89 5104/45 3517/83 +f 1944/29 1943/32 3520/12 3519/9 +f 4850/29 1944/32 3519/12 3523/9 +f 3522/29 3521/32 4790/12 3525/9 +f 4849/29 3527/9 3530/12 3558/32 +f 3526/29 3982/9 3985/12 3531/32 +f 4790/29 562/9 5105/12 3525/32 +f 3528/29 3531/9 5106/12 3529/32 +f 3525/29 5105/9 3982/12 3526/32 +f 4850/29 3523/9 3527/12 4849/32 +f 3533/45 1778/44 1781/89 3534/83 +f 3533/29 4851/12 1778/9 +f 3533/55 3532/57 1965/2 4851/1 +f 3536/29 1963/32 1965/12 3532/9 +f 3536/55 3538/57 4852/2 1963/1 +f 5107/29 3538/9 3518/12 5108/32 +f 4853/29 4855/32 4856/12 5109/9 +f 4856/29 4852/32 3538/12 5107/9 +f 5109/29 4856/32 5107/12 5019/9 +f 3541/3 4787/63 1789/62 1979/59 +f 3539/3 3541/63 1979/62 3546/59 +f 1978/8 3546/35 1979/37 +f 3547/35 3546/36 1978/37 3549/8 +f 3621/26 3551/5 3554/8 3622/35 +f 5110/33 5018/53 3552/43 3551/42 +f 3625/33 5110/53 3551/43 3621/42 +f 5109/29 5019/32 5018/12 5110/9 +f 5109/29 5110/32 3625/12 4853/9 +f 3553/28 3434/65 3433/9 3554/29 +f 3554/28 3433/65 3437/9 3622/29 +f 3541/45 3556/83 1791/89 4787/44 +f 3529/66 5106/65 3545/69 3544/18 +f 1781/17 1791/20 3556/19 3534/18 +f 3766/52 5111/21 5112/51 +f 5028/51 2955/21 5111/52 +f 5111/71 2955/5 2958/6 5112/72 +f 5112/71 2958/5 5029/6 5113/72 +f 5113/71 5029/5 2951/6 468/72 +f 467/52 5113/21 468/51 +f 467/52 3766/86 5112/21 5113/51 +f 3559/69 4970/10 4162/74 4161/70 +f 3560/69 3559/10 4161/74 4773/70 +f 4166/2 4165/67 5114/59 3575/3 +f 4969/29 3562/12 3561/9 +f 4905/29 3561/12 3563/9 +f 5021/29 4905/32 3563/12 5022/9 +f 4970/12 3559/9 3562/29 +f 5022/29 3563/32 3564/12 5023/9 +f 4969/86 3561/90 4902/22 4899/21 +f 3568/13 3567/14 2811/15 3586/16 +f 3567/13 3569/14 5115/15 2811/16 +f 4771/2 4166/67 3575/59 3574/3 +f 4772/2 4771/67 3574/59 3576/3 +f 2899/21 3577/22 3578/23 2900/24 +f 4776/2 4774/67 3577/59 2899/3 +f 4774/2 4772/67 3576/59 3577/3 +f 3583/13 3585/14 2900/15 3578/16 +f 5116/13 5117/14 3571/15 5118/16 +f 4178/13 4177/14 5115/15 3569/16 +f 3575/21 5114/22 5118/23 3571/24 +f 3571/15 5117/13 3566/14 +f 5117/13 4178/14 3569/15 3566/16 +f 3564/69 3560/10 4773/74 4777/70 +f 5023/69 3564/10 4777/74 2889/70 +f 4518/29 866/32 868/12 4803/9 +f 4517/29 3599/32 3601/12 852/9 +f 4348/29 4349/12 3599/9 +f 4518/29 4348/9 3599/12 4517/32 +f 4520/51 3589/68 3588/24 3593/21 +f 852/51 3587/68 3589/24 4520/21 +f 3601/51 3591/68 3587/24 852/21 +f 4349/25 3602/85 3600/35 3599/26 +f 418/25 5119/85 3602/35 4349/26 +f 417/25 4913/85 5119/35 418/26 +f 5119/24 4913/23 4912/82 4911/79 +f 5119/24 4911/23 3603/82 3602/79 +f 3605/25 3604/85 3603/35 4428/26 +f 3608/24 4916/23 4681/82 4680/79 +f 3607/24 4917/23 4916/82 3608/79 +f 3606/68 4439/24 4917/79 3607/60 +f 3609/25 3608/85 4680/35 4422/26 +f 1469/29 3610/32 3609/12 4422/9 +f 4433/29 1468/32 1469/12 4422/9 +f 4521/29 4520/32 3593/12 3610/9 +f 4522/29 4521/32 3610/12 1469/9 +f 4590/71 3611/5 3614/6 4589/72 +f 3611/6 4590/72 4591/71 3615/5 +f 3630/71 3617/5 3615/6 4591/72 +f 3622/28 3437/65 5094/9 3623/29 +f 3623/28 5094/65 4589/9 3614/29 +f 3616/36 3629/37 4859/35 +f 4544/46 3629/48 4547/47 +f 3628/13 3631/14 4546/15 4545/16 +f 3629/13 3628/14 4545/15 4547/16 +f 4546/13 3631/14 3632/15 4548/16 +f 3638/29 3633/32 3636/12 2988/9 +f 3639/29 3638/32 2988/12 2987/9 +f 3634/12 3633/9 3190/29 3189/32 +f 3633/12 3638/9 3637/29 3190/32 +f 5039/35 5038/36 5037/37 5036/8 +f 4324/71 4323/5 4976/6 4975/72 +f 355/71 4326/5 5120/6 4323/72 +f 3639/67 5120/59 4326/60 4966/68 +f 3639/67 2987/68 4977/60 5120/59 +f 5120/71 4977/72 4976/6 4323/5 +f 3642/56 5068/58 4811/57 4831/55 +f 3641/58 3219/49 5068/50 3642/57 +f 1320/33 1319/42 4839/43 4836/53 +f 4304/33 5121/42 1324/43 1323/53 +f 4839/4 4838/3 4831/63 4811/64 +f 1319/3 5040/59 4838/62 4839/63 +f 1318/3 5038/59 5040/62 1319/63 +f 1324/3 5037/59 5038/62 1318/63 +f 5121/3 4984/59 5037/62 1324/63 +f 4984/4 5121/3 4324/63 4975/64 +f 4304/33 4307/53 4324/43 5121/42 +f 1326/35 1325/8 1324/37 1318/36 +f 1317/57 1320/50 4837/67 2995/2 +f 1323/57 1317/50 2995/67 2994/2 +f 1323/57 2994/50 4305/67 4304/2 +f 3189/66 3219/18 3641/69 3634/65 +f 4307/57 4304/67 317/2 +f 5122/13 1359/15 1355/16 +f 2977/13 2976/14 2982/15 5123/16 +f 3645/46 2981/48 2980/47 +f 2982/47 2981/48 3649/46 +f 3653/9 3644/10 3647/11 4934/12 +f 3650/9 4934/12 3647/11 3648/10 +f 3648/9 3649/10 2981/11 3651/12 +f 3644/9 3651/12 2981/11 3645/10 +f 3654/21 5123/24 2982/23 3649/22 +f 3658/46 3645/36 2980/48 4754/47 +f 3829/46 5124/36 4639/48 4755/47 +f 3658/46 4754/47 4636/48 3661/36 +f 1359/65 3654/9 3655/10 1357/69 +f 5122/48 5123/47 3654/46 1359/36 +f 2977/13 5123/15 5125/16 +f 2977/13 5125/16 5126/15 4932/14 +f 4755/13 4639/14 4638/15 4756/16 +f 4756/13 4638/14 4637/15 4757/16 +f 4757/13 4637/14 4636/15 4754/16 +f 4932/13 5126/14 1434/15 4646/16 +f 5126/13 1356/16 1435/15 1434/14 +f 5125/13 1355/16 1356/15 5126/14 +f 5122/15 1355/14 5125/13 5123/16 +f 5090/36 3020/47 3662/46 +f 3020/13 3019/15 3662/16 +f 3678/7 5090/73 3672/17 3679/40 +f 5090/7 3662/73 3665/17 3672/40 +f 3669/15 3432/71 3678/5 3670/26 +f 3432/71 3669/72 3676/6 5092/5 +f 3681/52 413/86 3675/21 3674/51 +f 413/52 419/86 3676/21 3675/51 +f 419/52 4802/86 5092/21 3676/51 +f 5127/21 3683/22 3662/23 3019/24 +f 5128/56 3682/58 3683/57 5127/55 +f 5129/46 5127/36 3019/48 5047/47 +f 3686/34 5128/54 5127/53 5129/33 +f 3024/21 5129/22 5047/23 3025/24 +f 3687/56 3686/58 5129/57 3024/55 +f 4346/8 3680/7 3682/40 5128/37 +f 3685/66 4346/65 5128/69 3686/18 +f 5098/66 5097/65 5102/69 3688/18 +f 3694/13 3692/14 4949/15 4865/16 +f 5098/52 3688/51 3691/21 5096/86 +f 4867/7 3711/40 3695/17 3694/73 +f 3701/15 3700/26 4867/5 3706/71 +f 5096/52 3691/51 3704/21 858/86 +f 858/52 3704/51 3705/21 3709/86 +f 3700/7 3708/40 3711/17 4867/73 +f 5130/46 5099/36 4955/48 5101/47 +f 5102/34 5100/54 5099/53 5130/33 +f 3692/13 5101/14 4956/15 4949/16 +f 3689/21 5130/22 5101/23 3692/24 +f 3688/56 5102/58 5130/57 3689/55 +f 3722/21 3362/24 3361/23 3723/22 +f 3725/46 3364/47 3362/48 3722/36 +f 3369/21 3365/24 3364/23 3725/22 +f 3724/49 3726/50 3369/51 3725/52 +f 3729/43 4922/1 4925/4 3718/44 +f 3731/1 4184/2 4185/3 3732/4 +f 3732/1 4185/2 4188/3 5131/4 +f 3733/1 3732/2 5131/3 5132/4 +f 3735/1 3733/2 5132/3 4158/4 +f 3737/1 3735/2 4158/3 4157/4 +f 3739/1 3737/2 4157/3 5133/4 +f 3740/1 3739/2 5133/3 4160/4 +f 3729/1 3740/2 4160/3 4159/4 +f 3729/2 4159/4 4922/1 +f 3766/21 3760/22 3756/23 5111/24 +f 5111/13 3756/14 3759/15 5028/16 +f 3026/13 3025/14 5049/15 3769/16 +f 4364/24 3743/79 3742/82 471/23 +f 3748/24 3745/79 3743/82 4364/23 +f 4365/25 4426/26 3749/35 3748/85 +f 4910/29 3753/12 3752/9 +f 4910/66 4907/65 5051/69 3762/18 +f 3753/66 4910/65 3762/69 3754/18 +f 3759/13 3772/14 5030/15 5028/16 +f 3766/53 467/33 3742/34 3755/54 +f 3767/13 3030/14 3771/15 3763/16 +f 3762/56 5051/58 3768/57 3761/55 +f 3030/13 3026/14 3769/15 3771/16 +f 4907/29 4910/12 4908/9 +f 3750/25 3747/85 4914/35 3752/26 +f 3747/24 3749/23 4915/82 4914/79 +f 4427/25 4915/85 3749/35 4426/26 +f 3581/13 5134/15 5024/16 +f 5134/13 5135/15 5024/16 +f 5135/13 3808/15 5024/16 +f 5024/13 3808/14 3774/15 3773/16 +f 1182/13 3781/14 3782/15 4616/16 +f 5025/13 3776/14 3777/15 3779/16 +f 5026/13 5025/14 3779/15 3781/16 +f 1745/13 3790/16 4767/15 1741/14 +f 4765/21 3787/22 3790/23 1745/24 +f 3790/13 3789/16 5136/15 4767/14 +f 3789/13 3792/16 5137/15 5136/14 +f 3792/13 3794/16 3795/15 5137/14 +f 3796/13 3786/16 3808/15 5135/14 +f 4671/8 5075/7 3787/40 4765/37 +f 5075/66 5074/65 3788/69 3787/18 +f 5074/66 3799/65 3791/69 3788/18 +f 3802/66 3281/65 5003/69 3803/18 +f 3805/13 5004/16 3780/15 3778/14 +f 5004/13 5005/16 3782/15 3780/14 +f 5006/16 3782/15 5005/13 +f 5006/13 5138/16 4616/15 3782/14 +f 2600/13 3805/14 3804/15 2674/16 +f 2675/13 3806/14 3785/15 3784/16 +f 2676/13 2675/14 3784/15 3807/16 +f 3803/21 5003/22 2676/23 3807/24 +f 2674/13 3804/14 3806/15 2675/16 +f 4767/13 5136/16 4768/15 4766/14 +f 4768/13 5139/16 5134/15 3581/14 +f 5136/13 5137/16 5139/15 4768/14 +f 5139/13 3796/16 5135/15 5134/14 +f 5137/13 3795/16 3796/15 5139/14 +f 1328/13 3809/14 3812/15 1329/16 +f 3817/13 3816/14 4641/15 4640/16 +f 3812/13 3817/14 4640/15 1329/16 +f 1400/13 4645/14 2973/15 5034/16 +f 5034/13 5033/14 3819/15 3818/16 +f 1401/13 1400/14 5034/15 3818/16 +f 3820/13 3813/14 3814/15 4204/16 +f 4203/46 51/48 50/47 +f 51/47 3830/36 4206/48 +f 3822/9 4203/10 3832/11 3823/12 +f 3822/9 3826/12 51/11 4203/10 +f 3828/9 3823/12 3832/11 3830/10 +f 3828/9 3830/10 51/11 3826/12 +f 3829/21 4755/24 4206/23 3830/22 +f 5140/10 4203/65 4202/9 +f 3832/65 4203/9 5140/10 3833/69 +f 1328/10 3833/9 5140/65 3809/69 +f 4205/65 3809/69 5140/10 4202/9 +f 1328/10 1327/69 3831/65 3833/9 +f 5124/65 3829/9 3831/10 1327/69 +f 3959/71 4322/5 4972/6 3960/72 +f 3962/71 3961/72 4897/6 4863/5 +f 4322/15 4328/26 4973/5 4972/71 +f 4863/71 2011/6 3962/5 +f 4985/69 362/10 360/65 +f 4330/69 4985/10 360/65 +f 4328/65 362/69 4985/10 4973/9 +f 3974/7 3969/40 3971/17 3975/73 +f 3975/7 3971/40 3970/17 5141/73 +f 5141/7 3970/40 3964/17 3963/73 +f 3968/7 3967/40 3969/17 3974/73 +f 2199/28 3972/29 3975/9 5141/65 +f 2200/28 2199/29 5141/9 3963/65 +f 4901/28 2200/29 3963/9 3966/65 +f 3976/28 4901/29 3966/9 3977/65 +f 3988/29 3980/12 4398/9 +f 568/29 4381/12 5142/9 +f 5143/29 569/32 568/12 5142/9 +f 3979/29 3978/32 569/12 5143/9 +f 4381/78 551/75 552/72 5142/71 +f 552/14 4398/15 5143/71 5142/78 +f 5143/29 4398/32 3980/12 3979/9 +f 5105/29 5144/9 3983/12 3982/32 +f 562/29 561/9 5144/12 5105/32 +f 569/29 3978/12 4396/9 +f 3984/29 4400/9 4399/12 3986/32 +f 3983/29 4401/9 4400/12 3984/32 +f 5144/29 574/9 4401/12 3983/32 +f 561/55 571/1 574/2 5144/57 +f 4928/12 3988/32 4398/29 4397/9 +f 3531/29 3985/9 3987/12 5106/32 +f 3988/66 4928/65 4648/69 3989/18 +f 3980/8 3990/37 4649/40 3981/7 +f 4001/66 3997/18 3995/69 4399/65 +f 4399/66 3995/18 3991/69 3986/65 +f 3987/8 3992/37 3545/40 5106/7 +f 3992/45 3994/83 3518/89 3545/44 +f 3999/66 4396/69 4000/18 +f 4396/83 4002/89 4000/45 +f 4017/13 4003/16 4006/15 5145/14 +f 4018/13 1431/16 1430/15 4019/14 +f 4020/13 1432/16 1431/15 4018/14 +f 4021/13 1433/16 1432/15 4020/14 +f 4649/21 1433/24 4021/23 4022/22 +f 4006/16 4023/15 5145/13 +f 5019/29 5107/9 5108/12 5016/32 +f 4649/8 4022/36 4024/35 +f 5145/71 4032/72 4033/6 4036/5 +f 4043/26 4042/35 3553/8 3552/5 +f 5017/33 4043/42 3552/43 5018/53 +f 4039/33 4034/42 4043/43 5017/53 +f 4042/28 4041/65 3434/9 3553/29 +f 3543/83 3545/44 5104/89 +f 4046/66 3981/65 4649/69 4024/18 +f 4396/6 3978/7 4048/73 4002/87 +f 3994/6 4052/7 5108/73 3518/87 +f 4038/29 5016/9 5108/12 4052/32 +f 5146/71 5147/72 1641/6 1647/5 +f 4053/71 5146/72 1647/6 4029/5 +f 5147/15 5146/71 5014/5 5013/26 +f 5146/15 4053/71 4056/5 5014/26 +f 4054/71 4053/72 4029/6 4028/5 +f 4032/72 4057/6 4054/87 4028/77 +f 5148/71 4057/72 4032/6 5145/5 +f 5147/71 5148/72 5145/6 1641/5 +f 4057/15 5148/71 5012/5 4058/26 +f 5148/15 5147/71 5013/5 5012/26 +f 4060/42 4694/43 4696/44 4061/45 +f 4697/43 4064/1 4065/4 4698/44 +f 1566/43 1565/44 4068/4 4067/1 +f 1567/43 4071/1 4072/4 1568/44 +f 1566/1 4067/2 4549/3 4554/4 +f 4066/1 4074/2 4549/3 4067/4 +f 1570/1 4076/2 4071/3 1567/4 +f 1561/49 4078/52 4080/51 4082/50 +f 4065/49 4084/52 4085/51 4698/50 +f 4698/49 4085/52 4086/51 1560/50 +f 1560/49 4086/52 4078/51 1561/50 +f 4695/49 4091/52 4087/51 4696/50 +f 4087/8 4089/36 4696/35 +f 4094/49 4093/52 4091/51 4695/50 +f 4696/49 4101/52 4095/51 4061/50 +f 4696/49 4089/51 4101/50 +f 4072/49 4106/52 4108/51 1568/50 +f 1568/49 4108/52 4110/51 1562/50 +f 1562/49 4110/52 4112/51 1565/50 +f 1565/49 4112/52 4114/51 4068/50 +f 4116/1 968/2 4074/3 4073/4 +f 4152/1 4124/2 4125/3 4926/4 +f 4926/1 4125/2 4142/3 4927/4 +f 2291/1 4140/2 4141/3 4151/4 +f 4060/1 4076/2 1570/3 4694/4 +f 4142/1 4064/2 4697/3 4699/4 +f 4927/1 4142/2 4699/3 4248/4 +f 4923/1 4145/2 4146/3 2290/4 +f 4148/1 950/2 968/3 4116/4 +f 4154/1 947/2 950/3 4148/4 +f 4150/1 4557/2 947/3 4154/4 +f 5131/1 4188/2 4558/3 4149/4 +f 5132/1 5131/2 4149/3 4127/4 +f 4158/1 5132/2 4127/3 4126/4 +f 5133/1 4157/2 4130/3 4132/4 +f 4160/1 5133/2 4132/3 4143/4 +f 4922/1 4159/2 4145/3 4923/4 +f 2290/1 4146/2 4140/3 2291/4 +f 4149/1 4558/2 4557/3 4150/4 +f 4773/6 4161/87 4164/73 4770/7 +f 4168/13 4827/14 4828/15 4169/16 +f 5149/21 4835/22 4173/23 4174/24 +f 4176/34 4175/54 4835/53 5149/33 +f 4174/13 4167/14 4171/15 5116/16 +f 5118/13 5149/14 4174/15 5116/16 +f 5114/46 4176/36 5149/48 5118/47 +f 4165/58 4163/49 4176/50 5114/57 +f 4770/29 4164/32 4166/12 4771/9 +f 5116/13 4171/14 4178/15 5117/16 +f 590/4 4180/3 594/1 +f 4180/1 590/4 591/3 4181/2 +f 4179/5 4719/8 4720/7 2311/6 +f 22/5 4199/8 4719/7 4179/6 +f 24/1 34/4 4201/3 4405/2 +f 4405/1 4201/4 4181/3 591/2 +f 594/1 4180/4 4935/3 2319/2 +f 4179/1 2311/4 4935/3 4180/2 +f 4201/1 22/4 4179/3 4181/2 diff --git a/Projects/New/Scenes/scene.dtd b/Projects/New/Scenes/scene.dtd new file mode 100644 index 0000000..8999b5c --- /dev/null +++ b/Projects/New/Scenes/scene.dtd @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Projects/New/Scenes/scene.xml b/Projects/New/Scenes/scene.xml new file mode 100644 index 0000000..7ca9c5a --- /dev/null +++ b/Projects/New/Scenes/scene.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Projects/New/config.dtd b/Projects/New/config.dtd new file mode 100644 index 0000000..4f8b2b1 --- /dev/null +++ b/Projects/New/config.dtd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Projects/New/config.xml b/Projects/New/config.xml new file mode 100644 index 0000000..1a315ae --- /dev/null +++ b/Projects/New/config.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Projects/New/src/__injector__.c b/Projects/New/src/__injector__.c new file mode 100644 index 0000000..992db9a --- /dev/null +++ b/Projects/New/src/__injector__.c @@ -0,0 +1,213 @@ +/************************************************************************** + * Injector Plugin v1.0.0 + * + * Laplace Plugin is the plugin system of the Engine-3D. + * It is the entr + * It is made to be easy to use and to be + * used in any project. It is also made to be easy to add new functions. + * It is made by MasterLaplace. + * + * Injector Plugin is under MIT License. + * https://opensource.org/licenses/MIT + * @copyright © 2023 MasterLaplace + * @version 1.0.0 + * @date 2023-11-27 + **************************************************************************/ + +#include "injector.h" + +//////////////////////////////////////////////////////////// +// Create your variables here +//////////////////////////////////////////////////////////// +int my_variable = 0; +float delta_time = 0; +engine_t *engine = NULL; + +//////////////////////////////////////////////////////////// +// Create your functions here +//////////////////////////////////////////////////////////// +void jump(void) +{ + printf("jump\n"); + camera_t *camera = engine->game_data->camera; + camera->position.y += 1; +} + +void move_left(void) +{ + printf("move left\n"); + camera_t *camera = engine->game_data->camera; + camera->position.x -= 1; +} + +void move_right(void) +{ + printf("move right\n"); + camera_t *camera = engine->game_data->camera; + camera->position.x += 1; +} + +void move_up(void) +{ + printf("move up\n"); + camera_t *camera = engine->game_data->camera; + camera->position.y += 1; +} + +void move_down(void) +{ + printf("move down\n"); + camera_t *camera = engine->game_data->camera; + camera->position.y -= 1; +} + +void move_forward(void) +{ + printf("move forward\n"); + camera_t *camera = engine->game_data->camera; + camera->position.z += 1; +} + +void move_backward(void) +{ + printf("move backward\n"); + camera_t *camera = engine->game_data->camera; + camera->position.z -= 1; +} + +void screenshot(void) +{ + printf("screenshot\n"); + #if GRAPHICS_LIBRARY == CSFML + sfImage *image = sfRenderWindow_capture(engine->renderer->window->window); + sfImage_saveToFile(image, "screenshot.png"); + sfImage_destroy(image); + #endif +} + +void vr_mode(void) +{ + printf("vr mode\n"); + camera_set_vr(engine->game_data->camera, !engine->game_data->camera->is_vr); +} + +static const float speed_min = 0.5f; +static const float speed_max = 1.5f; +static const float friction = 0.1f; +static float speed = 1.0f; + +void run(void) +{ + speed += (speed >= speed_max)?0:friction; +} +void stop_run(void) +{ + speed -= (speed <= speed_min)?0:friction; +} +sfVector4f Forward = vector4_f_mul(engine->game_data->camera.dir, speed); +Forward.y = 0; + +if (KEY_PRESSED(sfKeyUp)) + engine->game_data->camera.Pos.y += 0.5f; +if (KEY_PRESSED(sfKeySpace)) { + engine->game_data->camera.state = JUMP; + engine->game_data->camera.velocity_y = 11.f; +} +if (KEY_PRESSED(sfKeyDown)) + engine->game_data->camera.Pos.y -= 0.5f; +if (KEY_PRESSED(sfKeyZ)) + engine->game_data->camera.Pos = vector4_f_add(engine->game_data->camera.Pos, Forward); +if (KEY_PRESSED(sfKeyS)) + engine->game_data->camera.Pos = vector4_f_sub(engine->game_data->camera.Pos, Forward); +if (KEY_PRESSED(sfKeyQ)) + engine->game_data->camera.fawY -= 0.1f; +if (KEY_PRESSED(sfKeyD)) + engine->game_data->camera.fawY += 0.1f; +if (KEY_PRESSED(sfKeyR)) + engine->game_data->camera.fawX += 0.1f; +if (KEY_PRESSED(sfKeyF)) + engine->game_data->camera.fawX -= 0.1f; + +/** + * @brief Initialize your game elements here + * + * @param engine {engine_t *} - The engine module + */ +void _injector_init(engine_t *_engine) +{ + printf("injector_init\n"); + engine = _engine; + + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_SPACE, + // .key_state = KEY_RELEASED + // }, &jump); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_DOWN, + // .key_state = KEY_PRESSED + // }, &move_down); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_UP, + // .key_state = KEY_PRESSED + // }, &move_up); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_LEFT, + // .key_state = KEY_PRESSED + // }, &move_left); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_RIGHT, + // .key_state = KEY_PRESSED + // }, &move_right); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_Z, + // .key_state = KEY_PRESSED + // }, &move_forward); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_S, + // .key_state = KEY_PRESSED + // }, &move_backward); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_Q, + // .key_state = KEY_PRESSED + // }, &move_left); + // event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + // .key_code = KEY_D, + // .key_state = KEY_PRESSED + // }, &move_right); + event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + .key_code = KEY_P, + .key_state = KEY_RELEASED + }, &screenshot); + event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + .key_code = KEY_V, + .key_state = KEY_RELEASED + }, &vr_mode); + event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + .key_code = KEY_CTRL, + .key_state = KEY_PRESSED + }, &move_right); + event_add_keyboard_callback(_engine->event, (event_keyboard_t) { + .key_code = KEY_P, + .key_state = KEY_RELEASED + }, &screenshot); +} + +/** + * @brief Update your game elements here + * + * @param engine {engine_t *} - The engine module + */ +void _injector_update(engine_t *_engine) +{ + delta_time = clock_get_f_delta_time(_engine->clock); +} + +/** + * @brief Clean your game elements here + * + * @param engine {engine_t *} - The engine module + */ +void _injector_clean(engine_t *_engine) +{ + printf("injector_clean\n"); +} diff --git a/Projects/NewProject/config.xml b/Projects/NewProject/config.xml new file mode 100644 index 0000000..315aa31 --- /dev/null +++ b/Projects/NewProject/config.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Projects/New_Game/Makefile b/Projects/New_Game/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/Projects/New_Game/config.xml b/Projects/New_Game/config.xml new file mode 100644 index 0000000..09f51e8 --- /dev/null +++ b/Projects/New_Game/config.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Scripts/build.sh b/Scripts/build.sh new file mode 100755 index 0000000..5db082a --- /dev/null +++ b/Scripts/build.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# File name: build.sh +# Author: MasterLaplace +# Created on: 2023-11-11 + +# /* +# Step 0: find and delete all .o files in the current directory and subdirectories +# Step 1: find all .c and .h files in the current directory and subdirectories +# Step 1.5: find all .c files that have been modified since the last compilation (bonus) +# Step 2: Download all .h files from the internet identified by a url +# Step 3: compile all .c files into .o files +# Step 4: link all .o files into an executable +# */ + +# get arguments +# $1 is the first argument, $2 is the second argument, etc. +# $# is the number of arguments +# $0 is the name of the script +# $@ is an array of all arguments +# $* is a string of all arguments +# $! is the process id of the last background process +# $? is the exit status of the last command +# $$ is the process id of the current process +# $- is the current options supplied to the shell +# $_ is the last argument of the previous command +# $IFS is the internal field separator + +# EXE_NAME=$1 + +# Step 0: +# find . -name "*.o" -type f -delete +# rm -f $EXE_NAME + +# Step 1: +# C_FILES=$(find . -name "*.c" -type f) +H_FILES=$(find . -name "*.h" -type f) + +# Step 2: + +regex="#include \"https?://[a-zA-Z0-9./?=_-]+.h\"" +mkdir -p "plugins" + +for h in $H_FILES; do + content=$(cat $h) + if [[ $content =~ $regex ]]; then + echo "Downloading $h" + for url in $(echo $content | grep -o -E "https?://[a-zA-Z0-9./?=_-]+.h"); do + rm -f "plugins/$(basename $url)" + wget -q -P "plugins" $url + done + fi +done + +# Step 3: +for c in $C_FILES; do + gcc -c $c +done + +# Step 4: +gcc -o $EXE_NAME *.o -include "*.h" diff --git a/Scripts/test_regex_norm_checker.py b/Scripts/test_regex_norm_checker.py index f3b03f5..634d183 100644 --- a/Scripts/test_regex_norm_checker.py +++ b/Scripts/test_regex_norm_checker.py @@ -7,43 +7,44 @@ import re -# # Define your regex pattern -# keyword_regex = r"^([a-z]+\([A-Za-z_.]+\)|^[a-z]+): " - -# # List of sample commit messages -# commit_messages = [ -# "fix(readme): fix link about the wiki", -# "fix(.github): move funding script", -# "feat(main): add new feature", -# "style: fix linting issues", -# ] - -# # Test the regex pattern on each commit message -# for message in commit_messages: -# match = re.search(keyword_regex, message) -# if match: -# print(f"Match found in '{message}': {match.group()}") -# else: -# print(f"No match found in '{message}'") - - -# Define regex for release date -realease_date_regex = r"- Release Date: \*\*([JFMASOND][a-z]+ \d+, \d+)\*\*" - -# List of sample release notes -release_notes = """ -> :clipboard: [Change Log](CHANGELOG.md). - -- [![Latest Release](https://img.shields.io/github/v/release/MasterLaplace/Engine-3D.svg?label=version)](https://github.com/MasterLaplace/Engine-3D/releases/latest/) -- Release Date: **October 13, 2023** - - -
-""" - -# Test the regex pattern on each release note -match = re.search(realease_date_regex, release_notes) -if match: - print(f"Match found in '{release_notes}': {match.group(1)}") -else: - print(f"No match found in '{release_notes}'") +# Define your regex pattern +keyword_regex = r"^([a-z]+\([A-Za-z_.-]+\)|^[a-z]+): " + +# List of sample commit messages +commit_messages = [ + "fix(readme): fix link about the wiki", + "fix(.github): move funding script", + "feat(main): add new feature", + "style: fix linting issues", + "style(docs-folder): style the docs folder", +] + +# Test the regex pattern on each commit message +for message in commit_messages: + match = re.search(keyword_regex, message) + if match: + print(f"Match found in '{message}': {match.group()}") + else: + print(f"No match found in '{message}'") + + +# # Define regex for release date +# realease_date_regex = r"- Release Date: \*\*([JFMASOND][a-z]+ \d+, \d+)\*\*" + +# # List of sample release notes +# release_notes = """ +# > :clipboard: [Change Log](CHANGELOG.md). + +# - [![Latest Release](https://img.shields.io/github/v/release/MasterLaplace/Engine-3D.svg?label=version)](https://github.com/MasterLaplace/Engine-3D/releases/latest/) +# - Release Date: **October 13, 2023** + + +#
+# """ + +# # Test the regex pattern on each release note +# match = re.search(realease_date_regex, release_notes) +# if match: +# print(f"Match found in '{release_notes}': {match.group(1)}") +# else: +# print(f"No match found in '{release_notes}'") diff --git a/bin/.gitkeep b/bin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/.poc/api/api b/docs/.poc/api/api new file mode 100755 index 0000000..e01eb39 Binary files /dev/null and b/docs/.poc/api/api differ diff --git a/docs/.poc/api/api.c b/docs/.poc/api/api.c new file mode 100644 index 0000000..1f0f3dc --- /dev/null +++ b/docs/.poc/api/api.c @@ -0,0 +1,92 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-21 +** File description: +** api +*/ + +#include +#include +#include +#include + +enum APICode { + APIC_Ok, + + APIC_Failed, + APIC_InvalidParam, + APIC_PermissionDenied, +}; + +enum APIRequest { + APIR_Open, + APIR_Ioctl, + APIR_Close, +}; + +extern inline enum APICode API_Open(va_list args) +{ + char *str = va_arg(args, char *); + + if (!str) + return APIC_InvalidParam; + + printf("Device: %s\n", str); + + return APIC_Ok; +} + +static const struct APILink_t { + const enum APIRequest request; + enum APICode (*link)(va_list args); +} APILink[] = { + { APIR_Open, &API_Open }, + { 0, NULL } +}; + +/** + * @brief Gets the error message. + * + * @param error {enum APICode} - The error code. + * @return {const char *} - The error message. + */ +extern const char *API_GetError(enum APICode error) { + switch (error) { + case APIC_Ok: return "Ok"; + case APIC_Failed: return "Failed"; + case APIC_InvalidParam: return "InvalidParam"; + case APIC_PermissionDenied: return "PermissionDenied"; + default: return "Unknown"; + } +} + +/** + * @brief Requests the API. + * + * @param request {enum APIRequest} - The request to make. + * @param ... {VA_ARGS} - The arguments to the request. + * @return {enum APICode} - The error code. + */ +extern enum APICode API_Request(enum APIRequest request, ...) { + va_list args; + enum APICode error = APIC_Ok; + + va_start(args, request); + error = APILink[request].link(args); + va_end(args); + + return error; +} + +int main(void) { + enum APICode error; + + if ((error = API_Request(APIR_Open, "Hello World!")) != APIC_Ok) + return printf("[Error]: %s\n", API_GetError(error)), EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +// Build: gcc -Wall -Wextra -Werror -o api api.c && ./api diff --git a/docs/.poc/deltaTime/deltaTime.c b/docs/.poc/deltaTime/deltaTime.c new file mode 100644 index 0000000..a68ac2b --- /dev/null +++ b/docs/.poc/deltaTime/deltaTime.c @@ -0,0 +1,91 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-12 +** File description: +** deltaTime +*/ + +#include +#include + +static inline sfVector2f f_vector_multiply(sfVector2f vector, float multiplier) { + return (sfVector2f){vector.x * multiplier, vector.y * multiplier}; +} + +static inline float time_get_delta_time(sfClock *clock) { + float delta_time = sfTime_asSeconds(sfClock_getElapsedTime(clock)); + return sfClock_restart(clock), delta_time; +} + +int main(int ac, char *av[] __attribute__((unused))) { + sfVideoMode mode = {800, 600, 32}; + sfRenderWindow *window = sfRenderWindow_create(mode, "CSFML DeltaTime Simulation", sfResize | sfClose, NULL); + + if (ac > 1) { + sfRenderWindow_setPosition(window, (sfVector2i){0, 0}); + sfRenderWindow_setFramerateLimit(window, 60); + } else if (ac > 2) { + sfRenderWindow_setPosition(window, (sfVector2i){800, 0}); + sfRenderWindow_setFramerateLimit(window, 30); + } else { + sfRenderWindow_setPosition(window, (sfVector2i){0, 600}); + sfRenderWindow_setFramerateLimit(window, 10); + } + + if (!window) { + return (1); + } + + sfClock *clock = sfClock_create(); + float delta_time = 0.0f; + + sfCircleShape *ball1 = sfCircleShape_create(); + sfCircleShape_setRadius(ball1, 20); + sfCircleShape_setFillColor(ball1, sfRed); + sfCircleShape_setPosition(ball1, (sfVector2f){100, 300}); + sfVector2f velocity1 = (sfVector2f){100.0f, 0.0f}; + + sfCircleShape *ball2 = sfCircleShape_create(); + sfCircleShape_setRadius(ball2, 20); + sfCircleShape_setFillColor(ball2, sfBlue); + sfCircleShape_setPosition(ball2, (sfVector2f){100, 400}); + sfVector2f velocity2 = (sfVector2f){100.0f, 0.0f}; + + while (sfRenderWindow_isOpen(window)) { + sfEvent event; + while (sfRenderWindow_pollEvent(window, &event)) { + if (event.type == sfEvtClosed || sfKeyboard_isKeyPressed(sfKeyEscape)) { + sfRenderWindow_close(window); + } + } + + delta_time = time_get_delta_time(clock); + + // Update the position of the balls using delta_time + sfVector2f move1 = f_vector_multiply(velocity1, delta_time); + sfVector2f move2 = f_vector_multiply(velocity2, delta_time); + + sfCircleShape_move(ball1, move1); + sfCircleShape_move(ball2, move2); + + // Clear the screen + sfRenderWindow_clear(window, sfBlack); + + // Draw the balls + sfRenderWindow_drawCircleShape(window, ball1, NULL); + sfRenderWindow_drawCircleShape(window, ball2, NULL); + + // Display the window + sfRenderWindow_display(window); + } + + sfRenderWindow_destroy(window); + sfClock_destroy(clock); + + return '0'; +} + +// Build: gcc -o ../../../bin/deltaTime deltaTime.c -lcsfml-graphics -lcsfml-window -lcsfml-system +// Run: ../../../bin//deltaTime [1|2|3] diff --git a/docs/.poc/gpu_addition/gpu_addition.cu b/docs/.poc/gpu_addition/gpu_addition.cu new file mode 100644 index 0000000..1e08b45 --- /dev/null +++ b/docs/.poc/gpu_addition/gpu_addition.cu @@ -0,0 +1,84 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** gpu_addition +*/ + +#include + +#ifdef USE_GPU +#include +#endif + +#ifdef USE_GPU +__global__ void addArrays(int *a, int *b, int *c, int n) { + int tid = blockIdx.x * blockDim.x + threadIdx.x; + if (tid < n) { + c[tid] = a[tid] + b[tid]; + } +} +#endif + +void addArraysCPU(int *a, int *b, int *c, int n) { + for (int i = 0; i < n; i++) { + c[i] = a[i] + b[i]; + } +} + +int main() { + int n = 100; + int *h_a, *h_b, *h_c; + +#ifdef USE_GPU + int *d_a, *d_b, *d_c; +#endif + + h_a = (int*)malloc(n * sizeof(int)); + h_b = (int*)malloc(n * sizeof(int)); + h_c = (int*)malloc(n * sizeof(int)); + + for (int i = 0; i < n; i++) { + h_a[i] = i; + h_b[i] = i << 1; + } + +#ifdef USE_GPU + cudaMalloc((void**)&d_a, n * sizeof(int)); + cudaMalloc((void**)&d_b, n * sizeof(int)); + cudaMalloc((void**)&d_c, n * sizeof(int)); + + cudaMemcpy(d_a, h_a, n * sizeof(int), cudaMemcpyHostToDevice); + cudaMemcpy(d_b, h_b, n * sizeof(int), cudaMemcpyHostToDevice); + + dim3 grid(1, 1, 1); + dim3 block(n, 1, 1); + + addArrays<<>>(d_a, d_b, d_c, n); + + cudaMemcpy(h_c, d_c, n * sizeof(int), cudaMemcpyDeviceToHost); +#else + addArraysCPU(h_a, h_b, h_c, n); +#endif + + for (int i = 0; i < n; i++) { + printf("%d + %d = %d\n", h_a[i], h_b[i], h_c[i]); + } + + free(h_a); + free(h_b); + free(h_c); + +#ifdef USE_GPU + cudaFree(d_a); + cudaFree(d_b); + cudaFree(d_c); +#endif + + return 0; +} + +// Build: nvcc -o ../../../bin/gpu_addition gpu_addition.cu -DUSE_GPU +// Run: ../../../bin/gpu_addition diff --git a/docs/.poc/opengl_install/opengl_install.c b/docs/.poc/opengl_install/opengl_install.c new file mode 100644 index 0000000..e3e06e3 --- /dev/null +++ b/docs/.poc/opengl_install/opengl_install.c @@ -0,0 +1,48 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-13 +** File description: +** opengl_install +*/ + +#include //! This header must be included before any other OpenGL header +#include //! This header must be included after glew.h +#include +#include + +int main() { + // Initialize GLFW + if (!glfwInit()) { + return -1; + } + + // Create a GLFW window and set its dimensions + GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", NULL, NULL); + if (!window) { + glfwTerminate(); + return -1; + } + + // Make the OpenGL context of the window current + glfwMakeContextCurrent(window); + + // Main loop + while (!glfwWindowShouldClose(window)) { + // Render your OpenGL content here + + // Swap front and back buffers + glfwSwapBuffers(window); + + // Poll for and process events + glfwPollEvents(); + } + + // Terminate GLFW and exit + glfwTerminate(); + return (0); +} + +// Build: gcc -o ../../../bin/opengl_install opengl_install.c -lGL -lGLU -lglut -lGLEW -lglfw +// Run: ../../../bin/opengl_install diff --git a/docs/.poc/webcam/new_webcam_frame.jpg b/docs/.poc/webcam/new_webcam_frame.jpg new file mode 100644 index 0000000..71d0f0c Binary files /dev/null and b/docs/.poc/webcam/new_webcam_frame.jpg differ diff --git a/docs/.poc/webcam/new_webcam_frame_gray.jpg b/docs/.poc/webcam/new_webcam_frame_gray.jpg new file mode 100644 index 0000000..7d643a9 Binary files /dev/null and b/docs/.poc/webcam/new_webcam_frame_gray.jpg differ diff --git a/docs/.poc/webcam/webcam b/docs/.poc/webcam/webcam new file mode 100755 index 0000000..6557611 Binary files /dev/null and b/docs/.poc/webcam/webcam differ diff --git a/docs/.poc/webcam/webcam.c b/docs/.poc/webcam/webcam.c new file mode 100644 index 0000000..15b40b6 --- /dev/null +++ b/docs/.poc/webcam/webcam.c @@ -0,0 +1,544 @@ +/* +** EPITECH PROJECT, 2023 +** Title: Engine-3D +** Author: MasterLaplace +** Created: 2023-10-21 +** File description: +** get frame from webcam using Video4Linux2 +** based on: +** - https://www.kernel.org/doc/html/v4.12/media/uapi/v4l/capture.c.html +** - https://www.tspi.at/2021/02/06/webcamcapture.html +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifndef __cplusplus + typedef int bool; + #define true 1 + #define false 0 +#endif + +static void printUsage(char *argv[]) { + printf("Usage: %s CAPDEV TARGETFILES [NUMFRAMES]\n", argv[0]); + printf("\n"); + printf("Captures the specified number of frames - or only a single frame if the\n"); + printf("argument is omitted\n"); + printf("\n"); + printf("Arguments:\n"); + printf("\tCAPDEV\n\t\tCapture device (for example /dev/video0)\n"); + printf("\tTARGETFILES\n\t\tTarget filename prefix excluding the extension\n"); + printf("\tNUMFRAMES\n\t\tNumber of frames to capture (if omitted capture a single frame\n\n"); +} + +enum cameraError { + cameraE_Ok, + + cameraE_Failed, + + cameraE_InvalidParam, + cameraE_UnknownDevice, + cameraE_PermissionDenied, +}; + +struct imageBuffer { + void * lpBase; + size_t sLen; +}; + +struct imgRawImage { + unsigned int numComponents; + unsigned long int width, height; + + unsigned char *lpData; +}; + +/* + Write one image into a target file + + See https://www.tspi.at/2020/03/20/libjpegexample.html +*/ +static int storeJpegImageFile(struct imgRawImage *lpImage, char *lpFilename) { + struct jpeg_compress_struct info; + struct jpeg_error_mgr err; + + unsigned char *lpRowBuffer[1]; + + FILE *fHandle; + + if ((fHandle = fopen(lpFilename, "wb")) == NULL) + return 1; + + info.err = jpeg_std_error(&err); + jpeg_create_compress(&info); + + jpeg_stdio_dest(&info, fHandle); + + info.image_width = lpImage->width; + info.image_height = lpImage->height; + info.input_components = 3; + info.in_color_space = JCS_RGB; + + jpeg_set_defaults(&info); + jpeg_set_quality(&info, 100, TRUE); + + jpeg_start_compress(&info, TRUE); + + /* Write every scanline ... */ + while(info.next_scanline < info.image_height) { + lpRowBuffer[0] = &(lpImage->lpData[info.next_scanline * (lpImage->width * 3)]); + jpeg_write_scanlines(&info, lpRowBuffer, 1); + } + + jpeg_finish_compress(&info); + fclose(fHandle); + + jpeg_destroy_compress(&info); + return 0; +} + +/* + Wrapper around ioctl that repeats the calls in case + they are interrupted by a signal (i.e. restarts) until + they succeed or fail. +*/ +static inline int xioctl(int fh, int request, void *arg) { + int r; + do { + r = ioctl(fh, request, arg); + } while((r == -1) && (errno == EINTR)); + return r; +} + +/* + Open the device file (first check it exists, is + a device file, etc.) +*/ +static inline enum cameraError deviceOpen(int *lpDeviceOut, char *deviceName) +{ + struct stat st; + int hHandle; + + if (lpDeviceOut == NULL) + return cameraE_InvalidParam; + (*lpDeviceOut) = -1; + + if (deviceName == NULL) + deviceName = (char *)"/dev/video0"; + + if (stat(deviceName, &st) == -1) + return cameraE_UnknownDevice; + + if (!S_ISCHR(st.st_mode)) + return cameraE_UnknownDevice; + + hHandle = open(deviceName, O_RDWR|O_NONBLOCK, 0); + if (hHandle < 0) { + switch(errno) { + case EACCES: return cameraE_PermissionDenied; + case EPERM: return cameraE_PermissionDenied; + default: return cameraE_Failed; + } + } + + (*lpDeviceOut) = hHandle; + return cameraE_Ok; +} + +static enum cameraError deviceClose( + int hHandle +) { + if (hHandle < 0) { return cameraE_InvalidParam; } + close(hHandle); + return cameraE_Ok; +} + +void filterGrayscale(struct imgRawImage *lpInput, struct imgRawImage **lpOutput) +{ + if (lpOutput == NULL) + (*lpOutput) = lpInput; + else { + (*lpOutput) = malloc(sizeof(struct imgRawImage)); + (*lpOutput)->width = lpInput->width; + (*lpOutput)->height = lpInput->height; + (*lpOutput)->numComponents = lpInput->numComponents; + (*lpOutput)->lpData = malloc(sizeof(unsigned char) * lpInput->width*lpInput->height*3); + } + + for (unsigned long int i = 0; i < lpInput->width * lpInput->height; i++) { + /* Do a grayscale transformation */ + unsigned char luma = (unsigned char)( + 0.299f * (float)lpInput->lpData[i * 3 + 0] + + 0.587f * (float)lpInput->lpData[i * 3 + 1] + + 0.114f * (float)lpInput->lpData[i * 3 + 2] + ); + (*lpOutput)->lpData[i * 3 + 0] = luma; + (*lpOutput)->lpData[i * 3 + 1] = luma; + (*lpOutput)->lpData[i * 3 + 2] = luma; + } +} + +void filterSepia(struct imgRawImage *lpInput, struct imgRawImage **lpOutput) +{ + if (lpOutput == NULL) + (*lpOutput) = lpInput; + else { + (*lpOutput) = malloc(sizeof(struct imgRawImage)); + (*lpOutput)->width = lpInput->width; + (*lpOutput)->height = lpInput->height; + (*lpOutput)->numComponents = lpInput->numComponents; + (*lpOutput)->lpData = malloc(sizeof(unsigned char) * lpInput->width*lpInput->height*3); + } + + for (unsigned long int i = 0; i < lpInput->width * lpInput->height; i++) { + /* Do a sepia transformation */ + unsigned char luma = (unsigned char)( + 0.299f * (float)lpInput->lpData[i * 3 + 0] + + 0.587f * (float)lpInput->lpData[i * 3 + 1] + + 0.114f * (float)lpInput->lpData[i * 3 + 2] + ); + (*lpOutput)->lpData[i * 3 + 0] = luma; + (*lpOutput)->lpData[i * 3 + 1] = luma * 0.9; + (*lpOutput)->lpData[i * 3 + 2] = luma * 0.8; + } +} + +typedef struct { + int hHandle; + int width; + int height; + int bufferCount; + struct imageBuffer *lpBuffers; + struct imgRawImage *lpRawImg; +} webcam_t; + +int main(int argc, char *argv[]) +{ + enum cameraError e; + int hHandle; + int numFrames = 1; + + struct imgRawImage *lpRawImg; + + if (argc < 3) { printUsage(argv); return 1; } + + /* Try to open the camera */ + e = deviceOpen(&hHandle, argv[1]); + if (e != cameraE_Ok) { + printf("Failed to open camera\n"); + return 2; + } + + /* Query capabilities */ + { + struct v4l2_capability cap = {0}; + + if (xioctl(hHandle, VIDIOC_QUERYCAP, &cap) == -1) { + printf("[%s:%u]: Failed to query capabilities\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { + printf("[%s:%u]: Device does not support video capture\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + } + + /* Query cropping capabilities and set cropping rectangle */ + int defaultWidth = 640; + int defaultHeight = 480; + struct v4l2_cropcap cropcap = {0}; + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(hHandle, VIDIOC_CROPCAP, &cropcap) != -1) { + printf("Setting default cropping rectangle ... "); + + struct v4l2_crop crop = {0}; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; + + if (xioctl(hHandle, VIDIOC_S_CROP, &crop) == -1) + printf("failed\n"); + else + printf("ok\n"); + } else + printf("[%s:%u]: Failed to query cropping capabilities, continuing anyways\n", __FILE__, __LINE__); + + /* v4l2_format negotiation, we just request the default ones or 640x480 */ + { + struct v4l2_format fmt = {0}; + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = defaultWidth; + fmt.fmt.pix.height = defaultHeight; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (xioctl(hHandle, VIDIOC_S_FMT, &fmt) == -1) + printf("[%s:%u]: Format negotiation (S_FMT) failed!\n", __FILE__, __LINE__); + + /* Now one should query the real size ... */ + defaultWidth = fmt.fmt.pix.width; + defaultHeight = fmt.fmt.pix.height; + } + + printf("Negotiated width and height: %d x %d\n", defaultWidth, defaultHeight); + + /* Setup buffers */ + int bufferCount = 2; + { + struct v4l2_requestbuffers rqBuffers = {0}; + + rqBuffers.count = bufferCount; + rqBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rqBuffers.memory = V4L2_MEMORY_MMAP; + + if (xioctl(hHandle, VIDIOC_REQBUFS, &rqBuffers) == -1) { + printf("[%s:%u]: Requesting buffers failed!\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + + bufferCount = rqBuffers.count; + } + + /* Map buffers */ + struct imageBuffer *lpBuffers; + { + if ((lpBuffers = calloc(bufferCount, sizeof(struct imageBuffer))) == NULL) { + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + + for (unsigned iBuf = 0; iBuf < bufferCount; iBuf++) { + struct v4l2_buffer vBuffer = {0}; + + vBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vBuffer.memory = V4L2_MEMORY_MMAP; + vBuffer.index = iBuf; + + if (xioctl(hHandle, VIDIOC_QUERYBUF, &vBuffer) == -1) { + printf("[%s:%u]: Failed to query buffer %d\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return 2; + } + + lpBuffers[iBuf].lpBase = mmap(NULL, vBuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, hHandle, vBuffer.m.offset); + lpBuffers[iBuf].sLen = vBuffer.length; + + if (lpBuffers[iBuf].lpBase == MAP_FAILED) { + printf("[%s:%u]: Failed to map buffer %d\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return 2; + } + } + } + + /* First we queue all buffers */ + { + for (unsigned iBuf = 0; iBuf < bufferCount; iBuf++) { + struct v4l2_buffer buf = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = iBuf; + + if (xioctl(hHandle, VIDIOC_QBUF, &buf) == -1) { + printf("[%s:%u]: Queueing buffer %d failed ...\n", __FILE__, __LINE__, iBuf); + deviceClose(hHandle); + return 2; + } + } + } + + /* Run streaming loop */ + { + /*Enable streaming */ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(hHandle, VIDIOC_STREAMON, &type) == -1) { + printf("[%s:%u]: Stream on failed\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + } + + /**! + * Capture frame ... + */ + do { + struct v4l2_buffer buf = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (xioctl(hHandle, VIDIOC_DQBUF, &buf) == -1) { + if (errno == EAGAIN) { continue; } + + printf("[%s:%u]: DQBUF failed\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + + printf("[%s:%u]: Dequeued buffer %d\n", __FILE__, __LINE__, buf.index); + + /**! + * ToDo: Process image ... + */ + { + if ((lpRawImg = malloc(sizeof(struct imgRawImage))) == NULL) { + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + if ((lpRawImg->lpData = malloc(sizeof(unsigned char)*defaultWidth*defaultHeight*3)) == NULL) { + free(lpRawImg); + printf("[%s:%u]: Out of memory\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + + /* + Convert the previously requested YUYV (YUV422) image into RGB (RGB888) + + YUV422: + 4 Byte -> 2 Pixel + + RGB888 + 3 Byte -> 1 Pixel + */ + + lpRawImg->numComponents = 3; + lpRawImg->width = defaultWidth; + lpRawImg->height = defaultHeight; + + for (unsigned long int row = 0; row < defaultHeight; row++) { + for (unsigned long int col = 0; col < defaultWidth; col++) { + unsigned char y0, y1, y; + unsigned char u0, v0; + + signed int c,d,e; + unsigned char r,g,b; + signed int rtmp,gtmp, btmp; + + y0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *defaultWidth) >> 1)*4 + 0]; + u0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *defaultWidth) >> 1)*4 + 1]; + y1 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *defaultWidth) >> 1)*4 + 2]; + v0 = ((unsigned char*)(lpBuffers[buf.index].lpBase))[((col + row *defaultWidth) >> 1)*4 + 3]; + + if ((col + row *defaultWidth) % 2 == 0) { y = y0; } + else { y = y1; } + + c = ((signed int)y) - 16; + d = ((signed int)u0) - 128; + e = ((signed int)v0) - 128; + + rtmp = ((298 *c + 409 *e + 128) >> 8); + gtmp = ((298 *c - 100 *d - 208 *e + 128) >> 8); + btmp = ((298 *c + 516 *d + 128) >> 8); + + if (rtmp < 0) { r = 0; } + else if (rtmp > 255) { r = 255; } + else { r = (unsigned char)rtmp; } + + if (gtmp < 0) { g = 0; } + else if (gtmp > 255) { g = 255; } + else { g = (unsigned char)gtmp; } + + if (btmp < 0) { b = 0; } + else if (btmp > 255) { b = 255; } + else { b = (unsigned char)btmp; } + + lpRawImg->lpData[(col + row * defaultWidth) * 3 + 0] = r; + lpRawImg->lpData[(col + row * defaultWidth) * 3 + 1] = g; + lpRawImg->lpData[(col + row * defaultWidth) * 3 + 2] = b; + } + } + + filterGrayscale(lpRawImg, &lpRawImg); + + /**! + * Write image to file ... + */ + printf("[%s:%u]: Writing %s\n", __FILE__, __LINE__, "webcam.jpg"); + storeJpegImageFile(lpRawImg, "new_webcam_frame_gray.jpg"); + + /**! + * Free memory of Raw Image + */ + free(lpRawImg->lpData); + free(lpRawImg); + lpRawImg = NULL; + + /* Re-enqueue */ + if (xioctl(hHandle, VIDIOC_QBUF, &buf) == -1) { + printf("[%s:%u]: Queueing buffer %d failed ...\n", __FILE__, __LINE__, buf.index); + deviceClose(hHandle); + return 2; + } + + break; + } + } while (true); + + + /* Stop streaming */ + { + /* Disable streaming */ + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(hHandle, VIDIOC_STREAMOFF, &type) == -1) { + printf("[%s:%u]: Stream off failed\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + } + + /* Release buffers ... */ + { + for (unsigned iBuf = 0; iBuf < bufferCount; iBuf++) + munmap(lpBuffers[iBuf].lpBase, lpBuffers[iBuf].sLen); + } + + { + struct v4l2_requestbuffers rqBuffers = {0}; + + rqBuffers.count = 0; + rqBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rqBuffers.memory = V4L2_MEMORY_MMAP; + + if (xioctl(hHandle, VIDIOC_REQBUFS, &rqBuffers) == -1) { + printf("[%s:%u]: Releasing buffers failed!\n", __FILE__, __LINE__); + deviceClose(hHandle); + return 2; + } + } + + /* Close camera at the end */ + deviceClose(hHandle); + return 0; +} + +// Dependencies: apt-get install libv4l-dev libjpeg-dev +// Build: gcc -o webcam webcam.c -ljpeg +// Run: ./webcam /dev/video0 webcam 1 diff --git "a/docs/01_Rast\303\251risation/Fiche Hub.pdf" "b/docs/01_Rast\303\251risation/Fiche Hub.pdf" new file mode 100644 index 0000000..d763bb9 Binary files /dev/null and "b/docs/01_Rast\303\251risation/Fiche Hub.pdf" differ diff --git a/docs/02_Collision/Fiche Hub 2.pdf b/docs/02_Collision/Fiche Hub 2.pdf new file mode 100644 index 0000000..d8bc931 Binary files /dev/null and b/docs/02_Collision/Fiche Hub 2.pdf differ diff --git a/docs/Pipeline.drawio b/docs/Pipeline.drawio new file mode 100644 index 0000000..8a608c7 --- /dev/null +++ b/docs/Pipeline.drawio @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Szczesny_Twardowski_MSc_final.pdf b/docs/Szczesny_Twardowski_MSc_final.pdf new file mode 100644 index 0000000..1e70003 Binary files /dev/null and b/docs/Szczesny_Twardowski_MSc_final.pdf differ diff --git a/docs/web/CNAME b/docs/web/CNAME new file mode 100644 index 0000000..b06029e --- /dev/null +++ b/docs/web/CNAME @@ -0,0 +1 @@ +www.me-engine-3d.com \ No newline at end of file diff --git a/docs/web/index.html b/docs/web/index.html new file mode 100644 index 0000000..25a5d92 --- /dev/null +++ b/docs/web/index.html @@ -0,0 +1,110 @@ +
+
+
+

Engine-3D

+

+ The Engine-3D is a 3D engine written in C, it is based on the CSFML library. +

+ +

Credits

+

+ The Engine-3D is developed by MasterLaplace. +

+ +

Documentation

+

+ The documentation is available here. +

+ +

Lorem ipsum

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vitae maximus metus. Cras vitae purus quis eros elementum dapibus et sit amet mi. Sed vestibulum risus eget aliquam tempor. Cras sit amet maximus velit. Donec eget lobortis neque, sed ornare augue. In hac habitasse platea dictumst. Ut vulputate elit erat, in tempor elit sodales pulvinar. Suspendisse hendrerit interdum orci vel varius. Nulla posuere justo leo. Aenean a lobortis nisl. Cras viverra eros vel consequat commodo. Aliquam ac elementum justo. +

Nullam nec risus fermentum, tincidunt massa in, interdum ligula. Phasellus congue nulla magna, vel suscipit dolor condimentum sit amet. In mattis efficitur nibh sit amet tempus. Suspendisse ornare congue tellus in viverra. Phasellus sit amet massa ultricies, tempus ligula nec, elementum turpis. Nullam porttitor tempor augue, id vehicula quam consectetur non. In vitae faucibus leo. Donec elit nulla, auctor a orci nec, porttitor facilisis augue. Sed scelerisque odio in finibus dictum. Nulla laoreet, sem eu maximus tristique, lorem purus consectetur metus, eu convallis nulla quam at purus. +

Curabitur non erat at magna eleifend suscipit a in ipsum. Aliquam lacinia, purus id auctor consequat, turpis felis lobortis tellus, non commodo quam lacus eu neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis tempor mollis eleifend. Nulla efficitur, libero ultricies vulputate congue, turpis arcu vulputate nisi, ac facilisis velit metus quis elit. Duis in est vitae nisl auctor venenatis. Nulla egestas imperdiet orci, in sodales est. Phasellus in metus purus. Etiam laoreet imperdiet diam ut commodo. Fusce sodales leo non orci cursus sodales. Vestibulum ultrices est eget tortor lobortis condimentum. In venenatis molestie metus lobortis lobortis. Nulla luctus urna quis leo convallis pretium. Nullam cursus enim suscipit, imperdiet eros nec, molestie odio. Quisque sollicitudin efficitur elit. +

Nam quis laoreet orci, eu imperdiet massa. Aenean lobortis id dui non tempor. Nullam a lacinia purus. Donec ac turpis metus. Sed in turpis quis enim luctus ultrices in vel ante. Nullam vitae magna augue. Fusce sollicitudin arcu sit amet mattis pellentesque. Nunc quis arcu at velit sollicitudin vulputate. Aenean euismod metus at sem luctus, a accumsan dui condimentum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin ut porttitor ex, vitae sollicitudin nulla. +

Vivamus eros sapien, aliquam a dolor vitae, pellentesque suscipit est. Nullam luctus egestas justo, vel bibendum odio rutrum non. Nunc non iaculis tortor. Cras justo justo, faucibus in egestas nec, commodo vel ipsum. Nulla consectetur lectus lorem, in vehicula felis elementum in. Cras ut magna mi. Nulla sagittis nisi ante, quis laoreet velit feugiat in. Phasellus sagittis sit amet nisi non finibus. Nunc cursus nisl mauris, vel condimentum tortor tempus a. In sit amet turpis cursus, malesuada nibh sed, suscipit ligula. Cras interdum tortor et metus rhoncus, congue sollicitudin elit laoreet. Etiam dignissim lorem erat, et cursus magna fringilla et. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar luctus elementum. Morbi posuere, felis id fermentum efficitur, ante libero hendrerit arcu, at accumsan lectus ligula quis risus. Praesent luctus euismod nisl lobortis ultricies. +

+ + + + + + + + + + + + diff --git a/last b/last new file mode 100755 index 0000000..6f4157c Binary files /dev/null and b/last differ diff --git a/last.c b/last.c new file mode 100644 index 0000000..30561fc --- /dev/null +++ b/last.c @@ -0,0 +1,59 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** last +*/ + +#include +#include +#include +#include + +#define typeof __typeof__ +#define auto __auto_type + +// #define init_vector(type) \ +// typedef struct type##_vector_s { \ +// size_t capacity; \ +// size_t size; \ +// unsigned sizeof_data; \ +// type *data; \ +// } type##_vector_t; \ + +// #define vector(type) type##_vector_t + +// #define vector_create(T, ...) _Generic((T), \ +// char* : "String", \ +// int : "Integer", \ +// float : "Float", \ +// long : "Long Integer", \ +// vector(int) : "Vector Integer", \ +// default : "Others") + +struct vector { + size_t capacity; + size_t size; + unsigned sizeof_data; + void *data; +}; + +// init_vector(int) +// init_vector(char) + +// int main() { +// printf("%s\n", vector_create("A")); +// printf("%s\n", vector_create(5)); +// printf("%s\n", vector_create(5.12)); + +// vector(int) v; +// v.data = calloc(2, sizeof(int)); +// v.size = 2; +// v.capacity = 2; +// v.sizeof_data = sizeof(int); +// v.data[0] = 5; +// v.data[1] = 6; + +// printf("%s\n", vector_create(v)); +// return 0; +// } diff --git a/launcher b/launcher new file mode 120000 index 0000000..a1b943f --- /dev/null +++ b/launcher @@ -0,0 +1 @@ +./Launcher/src/__main__.py \ No newline at end of file diff --git a/test b/test new file mode 100755 index 0000000..e816471 Binary files /dev/null and b/test differ diff --git a/test.c b/test.c new file mode 100644 index 0000000..107f2a6 --- /dev/null +++ b/test.c @@ -0,0 +1,219 @@ +// /* +// ** EPITECH PROJECT, 2024 +// ** Engine-3D +// ** File description: +// ** test +// */ + +// #include +// #include +// #include +// #include + +#define typeof __typeof__ + +#define lp_vector_create(type, ...) \ + _Generic((type), \ + int: lp_vector_create_with_length(sizeof(int), __VA_ARGS__), \ + char: lp_vector_create_with_length(sizeof(char), __VA_ARGS__), \ + float: lp_vector_create_with_length(sizeof(float), __VA_ARGS__), \ + double: lp_vector_create_with_length(sizeof(double), __VA_ARGS__), \ + long: lp_vector_create_with_length(sizeof(long), __VA_ARGS__), \ + long long: lp_vector_create_with_length(sizeof(long long), __VA_ARGS__), \ + unsigned: lp_vector_create_with_length(sizeof(unsigned), __VA_ARGS__), \ + unsigned long: lp_vector_create_with_length(sizeof(unsigned long), __VA_ARGS__), \ + unsigned long long: lp_vector_create_with_length(sizeof(unsigned long long), __VA_ARGS__), \ + bool: lp_vector_create_with_length(sizeof(bool), __VA_ARGS__), \ + default: lp_vector_create_with_length(sizeof(void *), __VA_ARGS__)) + +// #define lp_vector_create_with_length(type, length) \ +// lp_vector_create_with_capacity(type, length) + + +// #define lp_vector_create_with_capacity(type, capacity) \ +// ({ \ +// struct lp_vector *vector = malloc(sizeof(struct lp_vector)); \ +// vector->type = type; \ +// vector->capacity = capacity; \ +// vector->length = 0; \ +// vector->data = malloc(type * capacity); \ +// vector; \ +// }) + +// #define lp_vector_push(vector, value) \ +// ({ \ +// if (vector->length == vector->capacity) { \ +// vector->capacity *= 2; \ +// vector->data = realloc(vector->data, vector->type * vector->capacity); \ +// } \ +// memcpy(vector->data + vector->type * vector->length, &value, vector->type); \ +// vector->length++; \ +// }) + +// #define lp_vector_pop(vector) \ +// ({ \ +// vector->length--; \ +// vector->data + vector->type * vector->length; \ +// }) + +// #define lp_vector_get(vector, index) \ +// ({ \ +// vector->data + vector->type * index; \ +// }) + +// #define lp_vector_set(vector, index, value) \ +// ({ \ +// memcpy(vector->data + vector->type * index, &value, vector->type); \ +// }) + +// #define lp_vector_free(vector) \ +// ({ \ +// free(vector->data); \ +// free(vector); \ +// }) + +// #define lp_vector_foreach(vector, value) \ +// for (int i = 0; i < vector->length && (value = lp_vector_get(vector, i)); i++) + +// #define lp_vector_foreach_reverse(vector, value) \ +// for (int i = vector->length - 1; i >= 0 && (value = lp_vector_get(vector, i)); i--) + +// #define lp_vector_foreach_safe(vector, value, tmp) \ +// for (int i = 0; i < vector->length && (tmp = lp_vector_get(vector, i)) && (value = tmp); i++) + + +// struct lp_vector { +// size_t type; +// size_t capacity; +// size_t length; +// void *data; +// }; + + +// int main(void) +// { +// struct lp_vector *vector = lp_vector_create(int, 10); +// int value; + +// lp_vector_push(vector, 1); +// lp_vector_push(vector, 2); +// lp_vector_push(vector, 3); +// lp_vector_push(vector, 4); + +// lp_vector_foreach(vector, value) { +// printf("%d\n", value); +// } + +// lp_vector_free(vector); +// return 0; +// } + + +// C program to illustrate macro function. +#include +#include + +// Defining the macro with generic code for +//different argument types +#define init_vector(T) _Generic((T), \ + char* : "String", \ + int : "Integer", \ + long : "Long Integer", \ + default : "Others") + +// Driver code + + +// #define UNUSED __attribute__((unused)) +// #define PUBLIC __attribute__((visibility("default"))) +// #define PRIVATE __attribute__((visibility("hidden"))) +// #define PROTECTED __attribute__((visibility("internal"))) + +// #define CLASS_(name) \ +// typedef struct name name; \ +// struct name + +// #define PUBLIC_CLASS_(name) \ +// typedef struct name name; \ +// PUBLIC struct name + +// #define PRIVATE_CLASS_(name) \ +// typedef struct name name; \ +// PRIVATE struct name + +// #define PROTECTED_CLASS_(name) \ +// typedef struct name name; \ +// PROTECTED struct name + + +// typedef struct Vector Vector; + +// #define NEW(type) \ +// ({ \ +// type *self = malloc(sizeof(type)); \ +// self; \ +// }) + +// #define CONSTRUCTOR(type) \ +// type *type##_new(void) + +// #define DESTRUCTOR(type) \ +// void type##_destroy(type *self) + +// #define METHOD(type, name) \ +// void type##_##name(type *self) + + +// CLASS_(Vector) { +// int x; +// int y; + +// CONSTRUCTOR(Vector); +// DESTRUCTOR(Vector); +// METHOD(Vector, print); +// }; + +// Vector *Vector_new(void) +// { +// Vector *self = NEW(Vector); + +// self->x = 0; +// self->y = 0; +// return self; +// } + +// void Vector_destroy(Vector *self) +// { +// free(self); +// } + +// void Vector_print(Vector *self) +// { +// printf("Vector(%d, %d)\n", self->x, self->y); +// } + +// int main(void) +// { +// Vector *vector = Vector_new(); + +// vector->x = 10; +// vector->y = 20; +// vector->print(vector); +// Vector_destroy(vector); +// return 0; +// } + +int main(void) +{ + // Geeks is the macro name which is + // Here A is a string. + printf("%s\n", init_vector("A")); + + // floating point value + printf("%s\n", init_vector(5)); + + // float type which is not defined in the macro + printf("%s", init_vector(5.12)); + + return 0; +} diff --git a/vector b/vector new file mode 100755 index 0000000..ba28f6d Binary files /dev/null and b/vector differ diff --git a/vector.c b/vector.c new file mode 100644 index 0000000..075468c --- /dev/null +++ b/vector.c @@ -0,0 +1,87 @@ +/* +** EPITECH PROJECT, 2024 +** Engine-3D +** File description: +** vector +*/ + +#include +#include +#include +#include + +#define INIT_VECTOR(type) \ + typedef struct { \ + size_t capacity; \ + size_t size; \ + type *data; \ + } type##_vector; \ + void type##_vector_init(type##_vector *v, size_t capacity) { \ + v->capacity = capacity; \ + v->size = 0; \ + v->data = (type *)malloc(capacity * sizeof(type)); \ + } \ + void type##_vector_push_back(type##_vector *v, type element) { \ + if (v->size == v->capacity) { \ + v->capacity *= 2; \ + v->data = (type *)realloc(v->data, v->capacity * sizeof(type)); \ + } \ + v->data[v->size++] = element; \ + } \ + void type##_vector_pop_back(type##_vector *v) { \ + if (v->size > 0) { \ + v->size--; \ + } \ + } \ + void type##_vector_insert(type##_vector *v, size_t index, type element) { \ + if (index >= v->size) { \ + return; \ + } \ + if (v->size == v->capacity) { \ + v->capacity *= 2; \ + v->data = (type *)realloc(v->data, v->capacity * sizeof(type)); \ + } \ + memmove(v->data + index + 1, v->data + index, (v->size - index) * sizeof(type)); \ + v->data[index] = element; \ + v->size++; \ + } \ + void type##_vector_erase(type##_vector *v, size_t index) { \ + if (index >= v->size) { \ + return; \ + } \ + memmove(v->data + index, v->data + index + 1, (v->size - index - 1) * sizeof(type)); \ + v->size--; \ + } \ + void type##_vector_clear(type##_vector *v) { \ + v->size = 0; \ + free(v->data); \ + } \ + void type##_vector_free(type##_vector *v) { \ + free(v->data); \ + v->data = NULL; \ + v->size = 0; \ + v->capacity = 0; \ + } + +#define VECTOR_AT(v, i) \ + (i < (v)->size)\ + ?*((v)->data + (i)):0 + +INIT_VECTOR(int) + +int main() { + int_vector myIntVector; + int_vector_init(&myIntVector, 5); + + for (int i = 0; i < 10; i++) { + int_vector_push_back(&myIntVector, i); + } + + for (size_t i = 0; i < myIntVector.size; i++) { + printf("%d ", VECTOR_AT(&myIntVector, i)); + } + + int_vector_free(&myIntVector); + + return 0; +}